1 /* GStreamer DVD subtitle parser
2 * Copyright (C) 2007 Mark Nauwelaerts <mnauw@users.sourceforge.net>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
26 #include "gstdvdsubparse.h"
28 GST_DEBUG_CATEGORY_STATIC (dvdsubparse_debug);
29 #define GST_CAT_DEFAULT dvdsubparse_debug
31 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
34 GST_STATIC_CAPS ("subpicture/x-dvd, parsed=(boolean)true")
37 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
40 GST_STATIC_CAPS ("subpicture/x-dvd")
43 static void gst_dvd_sub_parse_finalize (GObject * object);
45 static void gst_dvd_sub_parse_reset (GstDvdSubParse * parse);
47 static gboolean gst_dvd_sub_parse_event (GstPad * pad, GstObject * parent,
49 static GstFlowReturn gst_dvd_sub_parse_chain (GstPad * pad, GstObject * parent,
52 static GstStateChangeReturn gst_dvd_sub_parse_change_state (GstElement *
53 element, GstStateChange transition);
55 #define gst_dvd_sub_parse_parent_class parent_class
56 G_DEFINE_TYPE (GstDvdSubParse, gst_dvd_sub_parse, GST_TYPE_ELEMENT);
57 GST_ELEMENT_REGISTER_DEFINE (dvdsubparse, "dvdsubparse", GST_RANK_NONE,
58 GST_TYPE_DVD_SUB_PARSE);
61 gst_dvd_sub_parse_class_init (GstDvdSubParseClass * klass)
63 GObjectClass *gobject_class;
64 GstElementClass *gstelement_class;
66 gobject_class = (GObjectClass *) klass;
67 gstelement_class = (GstElementClass *) klass;
69 gobject_class->finalize = gst_dvd_sub_parse_finalize;
71 GST_DEBUG_CATEGORY_INIT (dvdsubparse_debug, "dvdsubparse", 0,
72 "DVD subtitle parser");
74 gstelement_class->change_state =
75 GST_DEBUG_FUNCPTR (gst_dvd_sub_parse_change_state);
77 gst_element_class_add_static_pad_template (gstelement_class, &src_template);
78 gst_element_class_add_static_pad_template (gstelement_class, &sink_template);
80 gst_element_class_set_static_metadata (gstelement_class,
81 "DVD subtitle parser", "Codec/Parser/Subtitle",
82 "Parses and packetizes DVD subtitle streams",
83 "Mark Nauwelaerts <mnauw@users.sourceforge.net>");
87 gst_dvd_sub_parse_finalize (GObject * object)
89 GstDvdSubParse *parse = GST_DVD_SUB_PARSE (object);
91 g_object_unref (parse->adapter);
92 parse->adapter = NULL;
94 G_OBJECT_CLASS (parent_class)->finalize (object);
98 gst_dvd_sub_parse_init (GstDvdSubParse * parse)
100 parse->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink");
101 gst_pad_set_chain_function (parse->sinkpad,
102 GST_DEBUG_FUNCPTR (gst_dvd_sub_parse_chain));
103 gst_pad_set_event_function (parse->sinkpad,
104 GST_DEBUG_FUNCPTR (gst_dvd_sub_parse_event));
105 gst_element_add_pad (GST_ELEMENT (parse), parse->sinkpad);
107 parse->srcpad = gst_pad_new_from_static_template (&src_template, "src");
108 gst_pad_use_fixed_caps (parse->srcpad);
109 gst_pad_set_caps (parse->srcpad,
110 gst_static_pad_template_get_caps (&src_template));
111 gst_element_add_pad (GST_ELEMENT (parse), parse->srcpad);
114 parse->adapter = gst_adapter_new ();
115 gst_dvd_sub_parse_reset (parse);
119 gst_dvd_sub_parse_reset (GstDvdSubParse * parse)
122 parse->stamp = GST_CLOCK_TIME_NONE;
123 gst_adapter_clear (parse->adapter);
127 gst_dvd_sub_parse_event (GstPad * pad, GstObject * parent, GstEvent * event)
129 GstDvdSubParse *parse;
132 parse = GST_DVD_SUB_PARSE (parent);
134 switch (GST_EVENT_TYPE (event)) {
139 gst_event_unref (event);
140 caps = gst_static_pad_template_get_caps (&src_template);
141 gst_pad_push_event (parse->srcpad, gst_event_new_caps (caps));
142 gst_caps_unref (caps);
146 case GST_EVENT_FLUSH_STOP:
147 gst_dvd_sub_parse_reset (parse);
150 ret = gst_pad_event_default (pad, parent, event);
159 gst_dvd_sub_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
161 GstDvdSubParse *parse = GST_DVD_SUB_PARSE (parent);
163 GstBuffer *outbuf = NULL;
164 GstFlowReturn ret = GST_FLOW_OK;
166 adapter = parse->adapter;
168 GST_LOG_OBJECT (parse, "%" G_GSIZE_FORMAT " bytes, ts: %" GST_TIME_FORMAT,
169 gst_buffer_get_size (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
171 gst_adapter_push (adapter, buf);
173 if (!parse->needed) {
176 gst_adapter_copy (adapter, data, 0, 2);
177 parse->needed = GST_READ_UINT16_BE (data);
180 if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
181 if (GST_CLOCK_TIME_IS_VALID (parse->stamp))
182 /* normally, we expect only the first fragment to carry a timestamp */
183 GST_WARNING_OBJECT (parse, "Received more timestamps than expected.");
185 parse->stamp = GST_BUFFER_TIMESTAMP (buf);
191 av = gst_adapter_available (adapter);
192 if (av >= parse->needed) {
193 if (av > parse->needed) {
194 /* normally, we expect several fragment, boundary aligned */
195 GST_WARNING_OBJECT (parse, "Unexpected: needed %d, "
196 "but more (%d) is available.", parse->needed, av);
198 outbuf = gst_adapter_take_buffer (adapter, parse->needed);
199 /* decorate buffer */
200 GST_BUFFER_TIMESTAMP (outbuf) = parse->stamp;
202 parse->stamp = GST_CLOCK_TIME_NONE;
205 ret = gst_pad_push (parse->srcpad, outbuf);
212 static GstStateChangeReturn
213 gst_dvd_sub_parse_change_state (GstElement * element, GstStateChange transition)
215 GstDvdSubParse *parse = GST_DVD_SUB_PARSE (element);
216 GstStateChangeReturn ret;
218 switch (transition) {
219 case GST_STATE_CHANGE_NULL_TO_READY:
220 case GST_STATE_CHANGE_READY_TO_PAUSED:
222 case GST_STATE_CHANGE_PAUSED_TO_READY:
228 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
229 if (ret != GST_STATE_CHANGE_SUCCESS)
232 switch (transition) {
233 case GST_STATE_CHANGE_PAUSED_TO_READY:
234 gst_dvd_sub_parse_reset (parse);
240 return GST_STATE_CHANGE_SUCCESS;