diff options
author | Mark Nauwelaerts <mnauw@users.sourceforge.net> | 2007-10-13 15:13:34 +0000 |
---|---|---|
committer | Tim-Philipp Müller <tim@centricular.net> | 2007-10-13 15:13:34 +0000 |
commit | 5c5d85f8ccc17b3915d04c77e0c59282c0dac08c (patch) | |
tree | 113bc840e445dba69d7730ee572b110c05645638 /gst/dvdsub | |
parent | 10585630e6a5c061060204b177543880b3b64762 (diff) |
gst/dvdsub/: Add dvd subtitle parser, which just packetizes the input stream. This is needed to mux dvd subtitles int...
Original commit message from CVS:
Patch by: Mark Nauwelaerts <mnauw at users.sourceforge.net>
* gst/dvdsub/Makefile.am:
* gst/dvdsub/gstdvdsubdec.c:
* gst/dvdsub/gstdvdsubparse.c:
* gst/dvdsub/gstdvdsubparse.h:
Add dvd subtitle parser, which just packetizes the input
stream. This is needed to mux dvd subtitles into matroska
files, since the muxer expects unfragmented and properly
timestamped input (#415754).
Diffstat (limited to 'gst/dvdsub')
-rw-r--r-- | gst/dvdsub/Makefile.am | 9 | ||||
-rw-r--r-- | gst/dvdsub/gstdvdsubdec.c | 23 | ||||
-rw-r--r-- | gst/dvdsub/gstdvdsubparse.c | 234 | ||||
-rw-r--r-- | gst/dvdsub/gstdvdsubparse.h | 65 |
4 files changed, 314 insertions, 17 deletions
diff --git a/gst/dvdsub/Makefile.am b/gst/dvdsub/Makefile.am index f2e734d5..9efff3cb 100644 --- a/gst/dvdsub/Makefile.am +++ b/gst/dvdsub/Makefile.am @@ -1,9 +1,8 @@ - plugin_LTLIBRARIES = libgstdvdsub.la -libgstdvdsub_la_SOURCES = gstdvdsubdec.c -libgstdvdsub_la_CFLAGS = $(GST_CFLAGS) -libgstdvdsub_la_LIBADD = $(GST_LIBS) +libgstdvdsub_la_SOURCES = gstdvdsubdec.c gstdvdsubparse.c +libgstdvdsub_la_CFLAGS = $(GST_BASE_CFLAGS) $(GST_CFLAGS) +libgstdvdsub_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) libgstdvdsub_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -noinst_HEADERS = gstdvdsubdec.h +noinst_HEADERS = gstdvdsubdec.h gstdvdsubparse.h diff --git a/gst/dvdsub/gstdvdsubdec.c b/gst/dvdsub/gstdvdsubdec.c index 02c202e9..93e47a07 100644 --- a/gst/dvdsub/gstdvdsubdec.c +++ b/gst/dvdsub/gstdvdsubdec.c @@ -25,6 +25,7 @@ #endif #include "gstdvdsubdec.h" +#include "gstdvdsubparse.h" #include <string.h> GST_BOILERPLATE (GstDvdSubDec, gst_dvd_sub_dec, GstElement, GST_TYPE_ELEMENT); @@ -43,13 +44,6 @@ static gboolean gst_dvd_sub_dec_sink_event (GstPad * pad, GstEvent * event); static GstFlowReturn gst_send_subtitle_frame (GstDvdSubDec * dec, GstClockTime end_ts); -static const GstElementDetails gst_dvd_sub_dec_details = -GST_ELEMENT_DETAILS ("DVD subtitle Decoder", - "Codec/Decoder/Video", - "Decodes DVD subtitles into AYUV video frames", - "Wim Taymans <wim.taymans@chello.be>, " - "Jan Schmidt <thaytan@mad.scientist.com>"); - static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, @@ -110,7 +104,10 @@ gst_dvd_sub_dec_base_init (gpointer klass) gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&subtitle_template)); - gst_element_class_set_details (element_class, &gst_dvd_sub_dec_details); + gst_element_class_set_details_simple (element_class, "DVD subtitle decoder", + "Codec/Decoder/Video", "Decodes DVD subtitles into AYUV video frames", + "Wim Taymans <wim.taymans@gmail.com>, " + "Jan Schmidt <thaytan@mad.scientist.com>"); } static void @@ -989,12 +986,14 @@ static gboolean plugin_init (GstPlugin * plugin) { if (!gst_element_register (plugin, "dvdsubdec", GST_RANK_NONE, - GST_TYPE_DVD_SUB_DEC)) { + GST_TYPE_DVD_SUB_DEC) || + !gst_element_register (plugin, "dvdsubparse", GST_RANK_NONE, + GST_TYPE_DVD_SUB_PARSE)) { return FALSE; } GST_DEBUG_CATEGORY_INIT (gst_dvd_sub_dec_debug, "dvdsubdec", 0, - "DVD subtitle decoder element"); + "DVD subtitle decoder"); return TRUE; } @@ -1002,5 +1001,5 @@ plugin_init (GstPlugin * plugin) GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, "dvdsub", - "Decode DVD subtitles to AYUV video frames", plugin_init, - VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN); + "DVD subtitle parser and decoder", plugin_init, + VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN); diff --git a/gst/dvdsub/gstdvdsubparse.c b/gst/dvdsub/gstdvdsubparse.c new file mode 100644 index 00000000..6f499050 --- /dev/null +++ b/gst/dvdsub/gstdvdsubparse.c @@ -0,0 +1,234 @@ +/* GStreamer DVD subtitle parser + * Copyright (C) 2007 Mark Nauwelaerts <mnauw@users.sourceforge.net> + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <string.h> +#include <gst/gst.h> +#include "gstdvdsubparse.h" + +GST_DEBUG_CATEGORY_STATIC (dvdsubparse_debug); +#define GST_CAT_DEFAULT dvdsubparse_debug + +static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-dvd-subpicture, parsed=(boolean)true") + ); + +static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-dvd-subpicture") + ); + +static void gst_dvd_sub_parse_finalize (GObject * object); + +static void gst_dvd_sub_parse_reset (GstDvdSubParse * parse); + +static gboolean gst_dvd_sub_parse_event (GstPad * pad, GstEvent * event); +static GstFlowReturn gst_dvd_sub_parse_chain (GstPad * pad, GstBuffer * buf); + +static GstStateChangeReturn gst_dvd_sub_parse_change_state (GstElement * + element, GstStateChange transition); +GST_BOILERPLATE (GstDvdSubParse, gst_dvd_sub_parse, GstElement, + GST_TYPE_ELEMENT); + +static void +gst_dvd_sub_parse_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_template)); + + gst_element_class_set_details_simple (element_class, "DVD subtitle parser", + "Codec/Parser/Subtitle", "Parses and packetizes DVD subtitle streams", + "Mark Nauwelaerts <mnauw@users.sourceforge.net>"); +} + +static void +gst_dvd_sub_parse_class_init (GstDvdSubParseClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + gobject_class->finalize = gst_dvd_sub_parse_finalize; + + GST_DEBUG_CATEGORY_INIT (dvdsubparse_debug, "dvdsubparse", 0, + "DVD subtitle parser"); + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_dvd_sub_parse_change_state); +} + +static void +gst_dvd_sub_parse_finalize (GObject * object) +{ + GstDvdSubParse *parse = GST_DVD_SUB_PARSE (object); + + gst_object_unref (parse->adapter); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_dvd_sub_parse_init (GstDvdSubParse * parse, GstDvdSubParseClass * klass) +{ + parse->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink"); + gst_pad_set_chain_function (parse->sinkpad, + GST_DEBUG_FUNCPTR (gst_dvd_sub_parse_chain)); + gst_pad_set_event_function (parse->sinkpad, + GST_DEBUG_FUNCPTR (gst_dvd_sub_parse_event)); + gst_element_add_pad (GST_ELEMENT (parse), parse->sinkpad); + + parse->srcpad = gst_pad_new_from_static_template (&src_template, "src"); + gst_pad_use_fixed_caps (parse->srcpad); + gst_pad_set_caps (parse->srcpad, + gst_pad_template_get_caps (gst_static_pad_template_get (&src_template))); + gst_element_add_pad (GST_ELEMENT (parse), parse->srcpad); + + /* remainder */ + parse->adapter = gst_adapter_new (); + gst_dvd_sub_parse_reset (parse); +} + +static void +gst_dvd_sub_parse_reset (GstDvdSubParse * parse) +{ + parse->needed = 0; + parse->stamp = GST_CLOCK_TIME_NONE; + gst_adapter_clear (parse->adapter); +} + +static gboolean +gst_dvd_sub_parse_event (GstPad * pad, GstEvent * event) +{ + GstDvdSubParse *parse; + gboolean ret; + + parse = GST_DVD_SUB_PARSE (gst_pad_get_parent (pad)); + + switch GST_EVENT_TYPE + (event) { + case GST_EVENT_FLUSH_STOP: + gst_dvd_sub_parse_reset (parse); + /* fall-through */ + default: + ret = gst_pad_event_default (pad, event); + break; + } + + gst_object_unref (parse); + return ret; +} + + +static GstFlowReturn +gst_dvd_sub_parse_chain (GstPad * pad, GstBuffer * buf) +{ + GstDvdSubParse *parse = GST_DVD_SUB_PARSE (GST_PAD_PARENT (pad)); + GstAdapter *adapter; + GstBuffer *outbuf = NULL; + GstFlowReturn ret = GST_FLOW_OK; + + adapter = parse->adapter; + + GST_LOG_OBJECT (parse, "%4u bytes, ts: %" GST_TIME_FORMAT, + GST_BUFFER_SIZE (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); + + gst_adapter_push (adapter, buf); + + if (!parse->needed) { + const guint8 *data; + + data = gst_adapter_peek (adapter, 2); + parse->needed = GST_READ_UINT16_BE (data); + } + + if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) { + if (GST_CLOCK_TIME_IS_VALID (parse->stamp)) + /* normally, we expect only the first fragment to carry a timestamp */ + GST_WARNING_OBJECT (parse, "Received more timestamps than expected."); + else + parse->stamp = GST_BUFFER_TIMESTAMP (buf); + } + + if (parse->needed) { + guint av; + + av = gst_adapter_available (adapter); + if (av >= parse->needed) { + if (av > parse->needed) { + /* normally, we expect several fragment, boundary aligned */ + GST_WARNING_OBJECT (parse, "Unexpected: needed %d, " + "but more (%d) is available.", parse->needed, av); + } + outbuf = gst_adapter_take_buffer (adapter, parse->needed); + /* decorate buffer */ + gst_buffer_set_caps (outbuf, GST_PAD_CAPS (parse->srcpad)); + GST_BUFFER_TIMESTAMP (outbuf) = parse->stamp; + /* reset state */ + parse->stamp = GST_CLOCK_TIME_NONE; + parse->needed = 0; + /* and send along */ + ret = gst_pad_push (parse->srcpad, outbuf); + } + } + + return ret; +} + +static GstStateChangeReturn +gst_dvd_sub_parse_change_state (GstElement * element, GstStateChange transition) +{ + GstDvdSubParse *parse = GST_DVD_SUB_PARSE (element); + GstStateChangeReturn ret; + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + case GST_STATE_CHANGE_READY_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + if (ret != GST_STATE_CHANGE_SUCCESS) + return ret; + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + gst_dvd_sub_parse_reset (parse); + break; + default: + break; + } + + return GST_STATE_CHANGE_SUCCESS; +} diff --git a/gst/dvdsub/gstdvdsubparse.h b/gst/dvdsub/gstdvdsubparse.h new file mode 100644 index 00000000..8bf89874 --- /dev/null +++ b/gst/dvdsub/gstdvdsubparse.h @@ -0,0 +1,65 @@ +/* GStreamer DVD subtitle parser + * Copyright (C) 2007 Mark Nauwelaerts <mnauw@users.sourceforge.net> + * + * 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. + */ + +#ifndef __GST_DVDSUBPARSE_H__ +#define __GST_DVDSUBPARSE_H__ + +#include <gst/gst.h> +#include <gst/base/gstadapter.h> + +G_BEGIN_DECLS + +#define GST_TYPE_DVD_SUB_PARSE \ + (gst_dvd_sub_parse_get_type()) +#define GST_DVD_SUB_PARSE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_DVD_SUB_PARSE, GstDvdSubParse)) +#define GST_DVD_SUB_PARSE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_DVD_SUB_PARSE, GstDvdSubParseClass)) +#define GST_DVD_SUB_PARSE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), GST_TYPE_DVD_SUB_PARSE, GstDvdSubParseClass)) +#define GST_IS_DVD_SUB_PARSE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_DVD_SUB_PARSE)) +#define GST_IS_DVD_SUB_PARSE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_DVD_SUB_PARSE)) + +typedef struct _GstDvdSubParse GstDvdSubParse; +typedef struct _GstDvdSubParseClass GstDvdSubParseClass; + +struct _GstDvdSubParse { + GstElement element; + + /*< private >*/ + GstPad *srcpad; + GstPad *sinkpad; + + GstAdapter *adapter; /* buffer incoming data */ + GstClockTime stamp; /* timestamp of current packet */ + guint needed; /* size of current packet to be assembled */ +}; + +struct _GstDvdSubParseClass { + GstElementClass parent_class; +}; + +GType gst_dvd_sub_parse_get_type (void); + +G_END_DECLS + +#endif /* __GST_DVDSUBPARSE_H__ */ + |