From 61898506c8fe0bf85170ab290bf3aecb2c0a81b0 Mon Sep 17 00:00:00 2001 From: "David I. Lehn" Date: Thu, 19 Dec 2002 21:34:56 +0000 Subject: initial checkin of work-in-progress vbidec plugin for closed caption support Original commit message from CVS: initial checkin of work-in-progress vbidec plugin for closed caption support --- gst/vbidec/gstvbidec.c | 372 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 372 insertions(+) create mode 100644 gst/vbidec/gstvbidec.c (limited to 'gst/vbidec/gstvbidec.c') diff --git a/gst/vbidec/gstvbidec.c b/gst/vbidec/gstvbidec.c new file mode 100644 index 00000000..1da10543 --- /dev/null +++ b/gst/vbidec/gstvbidec.c @@ -0,0 +1,372 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include "gstvbidec.h" +#include "vbidata.h" +#include "vbiscreen.h" + +#define GST_TYPE_VBIDEC \ + (gst_vbidec_get_type()) +#define GST_VBIDEC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VBIDEC,GstVBIDec)) +#define GST_VBIDEC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VBIDEC,GstVBIDec)) +#define GST_IS_VBIDEC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VBIDEC)) +#define GST_IS_VBIDEC_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VBIDEC)) + +//typedef struct _GstVBIDec GstVBIDec; +typedef struct _GstVBIDecClass GstVBIDecClass; + +struct _GstVBIDec { + GstElement element; + + /* pads */ + GstPad *sinkpad, + *srcpad; + char caption[128]; + vbiscreen_t *vbiscreen; + vbidata_t *vbidata; + int caption_type; + gboolean dvd_input; +}; + +struct _GstVBIDecClass { + GstElementClass parent_class; +}; + +GType gst_vbidec_get_type(void); + +/* elementfactory information */ +static GstElementDetails gst_vbidec_details = { + "VBI decoder", + "Codec/Video/Decoder", + "GPL", + "Decodes closed captions and XDS data from VBI data", + VERSION, + "David I. Lehn ", + "(C) 2002" +}; + +/* VBIDec signals and args */ +enum { + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_CAPTION_TYPE, + ARG_DVD_INPUT +}; + +GST_PAD_TEMPLATE_FACTORY (sink_template_factory, + "sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_CAPS_NEW ( + "vbidec_sink", + "application/octet-stream", + NULL + ) +); + +GST_PAD_TEMPLATE_FACTORY (src_template_factory, + "src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_CAPS_NEW ( + "vbidec_src", + "text/plain", + NULL + ) +); + + +#define GST_TYPE_VBIDEC_CAPTION_TYPE_TYPE (gst_vbidec_caption_type_get_type()) +static GType +gst_vbidec_caption_type_get_type (void) +{ + static GType vbidec_caption_type_type = 0; + static GEnumValue vbidec_caption_type[] = { + { CAPTURE_OFF, "0", "Closed Captions off"}, + { CAPTURE_CC1, "1", "Closed Caption CC1"}, + { CAPTURE_CC2, "2", "Closed Caption CC2"}, + { CAPTURE_CC3, "4", "Closed Caption CC3"}, + { CAPTURE_CC4, "5", "Closed Caption CC4"}, + { CAPTURE_T1, "6", "Closed Caption T1"}, + { CAPTURE_T2, "7", "Closed Caption T2"}, + { CAPTURE_T3, "8", "Closed Caption T3"}, + { CAPTURE_T4, "9", "Closed Caption T4"}, + {0, NULL, NULL}, + }; + if (!vbidec_caption_type_type) { + vbidec_caption_type_type = g_enum_register_static ("GstVBIDecCaptionTypeType", vbidec_caption_type); + } + return vbidec_caption_type_type; +} + +static void gst_vbidec_class_init (GstVBIDecClass *klass); +static void gst_vbidec_init (GstVBIDec *vbidec); + +static void gst_vbidec_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec); +static void gst_vbidec_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec); + +static void gst_vbidec_chain (GstPad *pad, GstBuffer *buffer); + +static GstElementClass *parent_class = NULL; +/*static guint gst_vbidec_signals[LAST_SIGNAL] = { 0 };*/ + +GType +gst_vbidec_get_type (void) +{ + static GType vbidec_type = 0; + + if (!vbidec_type) { + static const GTypeInfo vbidec_info = { + sizeof(GstVBIDecClass), + NULL, + NULL, + (GClassInitFunc)gst_vbidec_class_init, + NULL, + NULL, + sizeof(GstVBIDec), + 0, + (GInstanceInitFunc)gst_vbidec_init, + }; + vbidec_type = g_type_register_static(GST_TYPE_ELEMENT, "GstVBIDec", &vbidec_info, 0); + } + return vbidec_type; +} + +static void +gst_vbidec_class_init(GstVBIDecClass *klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass*)klass; + gstelement_class = (GstElementClass*)klass; + + parent_class = g_type_class_ref(GST_TYPE_ELEMENT); + + gobject_class->set_property = gst_vbidec_set_property; + gobject_class->get_property = gst_vbidec_get_property; + + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_CAPTION_TYPE, + g_param_spec_enum ("caption type", "caption type", "Closed Caption Type", + GST_TYPE_VBIDEC_CAPTION_TYPE_TYPE, CAPTURE_OFF, G_PARAM_READWRITE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DVD_INPUT, + g_param_spec_boolean ("dvd input", "dvd input", "VBI is encapsulated in MPEG2 GOP user_data field (as on DVDs)", + FALSE, G_PARAM_READWRITE)); +} + +static void +gst_vbidec_init (GstVBIDec *vbidec) +{ + /* create the sink and src pads */ + vbidec->sinkpad = gst_pad_new_from_template ( + GST_PAD_TEMPLATE_GET (sink_template_factory), "sink"); + gst_element_add_pad (GST_ELEMENT (vbidec), vbidec->sinkpad); + gst_pad_set_chain_function (vbidec->sinkpad, GST_DEBUG_FUNCPTR (gst_vbidec_chain)); + + vbidec->srcpad = gst_pad_new_from_template ( + GST_PAD_TEMPLATE_GET (src_template_factory), "src"); + gst_element_add_pad (GST_ELEMENT (vbidec), vbidec->srcpad); + + vbidec->vbiscreen = vbiscreen_new(0, 0, 1.0, 0, (void *)vbidec); + vbidec->vbidata = vbidata_new_line(vbidec->vbiscreen, 0); + vbidec->caption_type = CAPTURE_OFF; + vbidata_capture_mode(vbidec->vbidata, vbidec->caption_type); + vbidec->dvd_input = FALSE; +} + +static void +line21_decode(GstVBIDec *vbidec, guint8 *data, guint32 size) +{ + vbidata_process_line(vbidec->vbidata, data, 0); +} + +static void +dvd_user_data_decode(GstVBIDec *vbidec, guint8 *data, guint32 size) +{ + //char caption[128]; + //int ci; /* caption index */ + int i; /* buf index */ + int num_disp_field; + guint8 b1, b2; + int w; + + //g_print("%%%% vbi decode\n"); + //g_print("== %p %d\n", data, size); + i = 0; + /* Check for Closed Captioning data */ + if (data[i] != 0x43 || data[i+1] != 0x43 || + data[i+2] != 0x01 || data[i+3] != 0xf8) { + g_print ("non-CC data\n"); + return; + } + //g_print ("CC data\n"); + i += 4; /* above */ + i += 4; /* ? */ + num_disp_field = data[i] & 0x3f; + //g_print ("ndf %d\n", num_disp_field); + while ((data[i] & 0xfe) == 0xfe) { + if (data[i] & 0x1) { + b1 = data[i+1] & 0x7f; + b2 = data[i+2] & 0x7f; + w = (b2 << 8) | b1; + vbidata_process_16b(vbidec->vbidata, 0, w); + } + i += 3; + } +} + +static void +gst_vbidec_chain (GstPad *pad, GstBuffer *buf) +{ + GstVBIDec *vbidec = GST_VBIDEC (gst_pad_get_parent (pad)); + guint32 size; + guint8 *data; + guint64 pts; + + size = GST_BUFFER_SIZE (buf); + data = GST_BUFFER_DATA (buf); + pts = GST_BUFFER_TIMESTAMP (buf); + + /* + g_print("** user_data: addr:%p len:%d state:%d\n", data, size, 0); + { + int i; + guint8 ud; + g_print("** \""); + for (i=0; idvd_input) { + dvd_user_data_decode(vbidec, data, size); + } else { + line21_decode(vbidec, data, size); + } + + gst_buffer_unref(buf); +} + +void +gst_vbidec_show_text (GstVBIDec *vbidec, char *text, int len) +{ + //fprintf(stderr, "%*s\n", len, text); + if (len > 0) { + if (GST_PAD_IS_USABLE (vbidec->srcpad)) { + GstBuffer *buf = gst_buffer_new_and_alloc (len); + memcpy (GST_BUFFER_DATA (buf), text, len); + GST_BUFFER_SIZE (buf) = len; + // FIXME + //GST_BUFFER_TIMESTAMP (buf) = vbidec->... + //... + //fprintf(stderr, "vbi text pushed\n"); + gst_pad_push (vbidec->srcpad, buf); + } + } +} + +static void +gst_vbidec_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + GstVBIDec *vbidec; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail (GST_IS_VBIDEC (object)); + vbidec = GST_VBIDEC (object); + + switch (prop_id) { + case ARG_DVD_INPUT: + vbidec->dvd_input = g_value_get_boolean(value); + break; + case ARG_CAPTION_TYPE: + vbidec->caption_type = g_value_get_enum(value); + vbidata_capture_mode(vbidec->vbidata, vbidec->caption_type); + break; + default: + break; + } +} + +static void +gst_vbidec_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + GstVBIDec *vbidec; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail (GST_IS_VBIDEC (object)); + vbidec = GST_VBIDEC (object); + + switch (prop_id) { + case ARG_DVD_INPUT: + g_value_set_boolean(value, vbidec->dvd_input); + break; + case ARG_CAPTION_TYPE: + g_value_set_enum(value, vbidec->caption_type); + break; + default: + break; + } +} + +static gboolean +plugin_init (GModule *module, GstPlugin *plugin) +{ + GstElementFactory *factory; + + /* create an elementfactory for the vbidec element */ + factory = gst_element_factory_new("vbidec",GST_TYPE_VBIDEC, + &gst_vbidec_details); + g_return_val_if_fail(factory != NULL, FALSE); + gst_element_factory_set_rank (factory, GST_ELEMENT_RANK_PRIMARY); + + gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (src_template_factory)); + gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (sink_template_factory)); + + gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory)); + + return TRUE; +} + +GstPluginDesc plugin_desc = { + GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "vbidec", + plugin_init +}; -- cgit v1.2.1