2 * Copyright (C) 2005 Martin Soto <martinsoto@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., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
27 #include "gstdvddemux.h"
30 * Move PTM discont back by 0.3 seconds to allow for strange audio
31 * timestamps when audio crosses a VOBU
33 #define PTM_DISCONT_ADJUST (0.3 * GST_SECOND)
34 #define INITIAL_END_PTM (-1)
35 #define MAX_GAP ( 3 * GST_SECOND / 2 )
36 #define MAX_GAP_TOLERANCE ( GST_SECOND / 20 )
38 GST_DEBUG_CATEGORY_STATIC (gstdvddemux_debug);
39 #define GST_CAT_DEFAULT (gstdvddemux_debug)
42 #define PARSE_CLASS(o) GST_MPEG_PARSE_CLASS (G_OBJECT_GET_CLASS (o))
43 #define DEMUX_CLASS(o) GST_MPEG_DEMUX_CLASS (G_OBJECT_GET_CLASS (o))
44 #define CLASS(o) GST_DVD_DEMUX_CLASS (G_OBJECT_GET_CLASS (o))
46 /* DVDDemux signals and args */
60 /* Define the capabilities separately, to be able to reuse them. */
62 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
65 GST_STATIC_CAPS ("video/mpeg, "
66 "mpegversion = (int) 2, " "systemstream = (boolean) TRUE")
70 GST_STATIC_CAPS ("video/mpeg, " \
71 "mpegversion = (int) { 1, 2 }, " \
72 "systemstream = (boolean) FALSE" \
78 "mpegversion = (int) 1;" \
80 "width = (int) { 16, 20, 24 }, " \
81 "rate = (int) { 48000, 96000 }, " \
82 "channels = (int) [ 1, 8 ], " \
83 "dynamic_range = (int) [ 0, 255 ], " \
84 "emphasis = (boolean) { FALSE, TRUE }, " \
85 "mute = (boolean) { FALSE, TRUE }; " \
90 #define SUBPICTURE_CAPS \
91 GST_STATIC_CAPS ("video/x-dvd-subpicture")
93 static GstStaticPadTemplate cur_video_template =
94 GST_STATIC_PAD_TEMPLATE ("current_video",
99 static GstStaticPadTemplate audio_template =
100 GST_STATIC_PAD_TEMPLATE ("dvd_audio_%02d",
105 static GstStaticPadTemplate cur_audio_template =
106 GST_STATIC_PAD_TEMPLATE ("current_audio",
111 static GstStaticPadTemplate subpicture_template =
112 GST_STATIC_PAD_TEMPLATE ("subpicture_%d",
117 static GstStaticPadTemplate cur_subpicture_template =
118 GST_STATIC_PAD_TEMPLATE ("current_subpicture",
123 #define _do_init(bla) \
124 GST_DEBUG_CATEGORY_INIT (gstdvddemux_debug, "dvddemux", 0, \
125 "DVD (VOB) demultiplexer element");
127 GST_BOILERPLATE_FULL (GstDVDDemux, gst_dvd_demux, GstMPEGDemux,
128 GST_TYPE_MPEG_DEMUX, _do_init);
130 static gboolean gst_dvd_demux_process_event (GstMPEGParse * mpeg_parse,
132 static gboolean gst_dvd_demux_parse_packhead (GstMPEGParse * mpeg_parse,
135 static gboolean gst_dvd_demux_handle_dvd_event
136 (GstDVDDemux * dvd_demux, GstEvent * event);
138 static GstMPEGStream *gst_dvd_demux_get_video_stream
139 (GstMPEGDemux * mpeg_demux,
140 guint8 stream_nr, gint type, const gpointer info);
141 static GstMPEGStream *gst_dvd_demux_get_audio_stream
142 (GstMPEGDemux * dvd_demux,
143 guint8 stream_nr, gint type, const gpointer info);
144 static GstMPEGStream *gst_dvd_demux_get_subpicture_stream
145 (GstMPEGDemux * dvd_demux,
146 guint8 stream_nr, gint type, const gpointer info);
148 static GstFlowReturn gst_dvd_demux_process_private
149 (GstMPEGDemux * mpeg_demux,
151 guint stream_nr, GstClockTime timestamp, guint headerlen, guint datalen);
153 static GstFlowReturn gst_dvd_demux_send_subbuffer
154 (GstMPEGDemux * mpeg_demux,
155 GstMPEGStream * outstream,
156 GstBuffer * buffer, GstClockTime timestamp, guint offset, guint size);
158 static GstFlowReturn gst_dvd_demux_combine_flows (GstMPEGDemux * mpegdemux,
159 GstMPEGStream * stream, GstFlowReturn flow);
161 static void gst_dvd_demux_set_cur_audio
162 (GstDVDDemux * dvd_demux, gint stream_nr);
163 static void gst_dvd_demux_set_cur_subpicture
164 (GstDVDDemux * dvd_demux, gint stream_nr);
166 static void gst_dvd_demux_reset (GstDVDDemux * dvd_demux);
167 static void gst_dvd_demux_synchronise_pads (GstMPEGDemux * mpeg_demux,
168 GstClockTime threshold, GstClockTime new_ts);
169 static void gst_dvd_demux_sync_stream_to_time (GstMPEGDemux * mpeg_demux,
170 GstMPEGStream * stream, GstClockTime last_ts);
172 static GstStateChangeReturn gst_dvd_demux_change_state (GstElement * element,
173 GstStateChange transition);
175 /*static guint gst_dvd_demux_signals[LAST_SIGNAL] = { 0 };*/
179 gst_dvd_demux_base_init (gpointer klass)
181 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
182 GstMPEGParseClass *mpeg_parse_class = GST_MPEG_PARSE_CLASS (klass);
183 GstMPEGDemuxClass *demux_class = GST_MPEG_DEMUX_CLASS (klass);
184 GstDVDDemuxClass *dvd_demux_class = GST_DVD_DEMUX_CLASS (klass);
186 mpeg_parse_class->send_buffer = NULL;
187 mpeg_parse_class->process_event = gst_dvd_demux_process_event;
188 mpeg_parse_class->parse_packhead = gst_dvd_demux_parse_packhead;
191 gst_element_class_add_static_pad_template (element_class,
194 demux_class->audio_template = gst_static_pad_template_get (&audio_template);
196 dvd_demux_class->cur_video_template =
197 gst_static_pad_template_get (&cur_video_template);
198 dvd_demux_class->cur_audio_template =
199 gst_static_pad_template_get (&cur_audio_template);
200 dvd_demux_class->subpicture_template =
201 gst_static_pad_template_get (&subpicture_template);
202 dvd_demux_class->cur_subpicture_template =
203 gst_static_pad_template_get (&cur_subpicture_template);
205 gst_element_class_add_pad_template (element_class,
206 demux_class->audio_template);
208 gst_element_class_add_pad_template (element_class,
209 dvd_demux_class->cur_video_template);
210 gst_element_class_add_pad_template (element_class,
211 dvd_demux_class->cur_audio_template);
213 gst_element_class_add_pad_template (element_class,
214 dvd_demux_class->subpicture_template);
215 gst_element_class_add_pad_template (element_class,
216 dvd_demux_class->cur_subpicture_template);
218 gst_element_class_set_details_simple (element_class, "DVD Demuxer",
220 "Demultiplexes DVD (VOB) MPEG2 streams",
221 "Martin Soto <martinsoto@users.sourceforge.net>");
226 gst_dvd_demux_class_init (GstDVDDemuxClass * klass)
228 GstElementClass *gstelement_class;
229 GstMPEGDemuxClass *mpeg_demux_class;
231 parent_class = g_type_class_peek_parent (klass);
233 gstelement_class = (GstElementClass *) klass;
234 mpeg_demux_class = (GstMPEGDemuxClass *) klass;
236 gstelement_class->change_state = gst_dvd_demux_change_state;
238 mpeg_demux_class->get_audio_stream = gst_dvd_demux_get_audio_stream;
239 mpeg_demux_class->get_video_stream = gst_dvd_demux_get_video_stream;
240 mpeg_demux_class->send_subbuffer = gst_dvd_demux_send_subbuffer;
241 mpeg_demux_class->combine_flows = gst_dvd_demux_combine_flows;
242 mpeg_demux_class->process_private = gst_dvd_demux_process_private;
243 mpeg_demux_class->synchronise_pads = gst_dvd_demux_synchronise_pads;
244 mpeg_demux_class->sync_stream_to_time = gst_dvd_demux_sync_stream_to_time;
246 klass->get_subpicture_stream = gst_dvd_demux_get_subpicture_stream;
251 gst_dvd_demux_init (GstDVDDemux * dvd_demux, GstDVDDemuxClass * klass)
253 GstMPEGDemux *mpeg_demux = GST_MPEG_DEMUX (dvd_demux);
256 /* Create the pads for the current streams. */
257 dvd_demux->cur_video =
258 DEMUX_CLASS (dvd_demux)->new_output_pad (mpeg_demux, "current_video",
259 CLASS (dvd_demux)->cur_video_template);
260 gst_element_add_pad (GST_ELEMENT (mpeg_demux), dvd_demux->cur_video);
261 dvd_demux->cur_audio =
262 DEMUX_CLASS (dvd_demux)->new_output_pad (mpeg_demux, "current_audio",
263 CLASS (dvd_demux)->cur_audio_template);
264 gst_element_add_pad (GST_ELEMENT (mpeg_demux), dvd_demux->cur_audio);
265 dvd_demux->cur_subpicture =
266 DEMUX_CLASS (dvd_demux)->new_output_pad (mpeg_demux, "current_subpicture",
267 CLASS (dvd_demux)->cur_subpicture_template);
268 gst_element_add_pad (GST_ELEMENT (mpeg_demux), dvd_demux->cur_subpicture);
270 dvd_demux->mpeg_version = 0;
271 dvd_demux->cur_video_nr = 0;
272 dvd_demux->cur_audio_nr = 0;
273 dvd_demux->cur_subpicture_nr = 0;
275 for (i = 0; i < GST_DVD_DEMUX_NUM_SUBPICTURE_STREAMS; i++) {
276 dvd_demux->subpicture_stream[i] = NULL;
279 /* Directly after starting we operate as if we had just flushed. */
280 dvd_demux->segment_filter = TRUE;
282 dvd_demux->langcodes = NULL;
286 gst_dvd_demux_process_event (GstMPEGParse * mpeg_parse, GstEvent * event)
288 GstDVDDemux *dvd_demux = GST_DVD_DEMUX (mpeg_parse);
291 switch (GST_EVENT_TYPE (event)) {
292 case GST_EVENT_NEWSEGMENT:
296 gst_event_parse_new_segment (event, &update, NULL, NULL,
300 /* This is a discontinuity in the timestamp sequence. which
301 may mean that we find some audio blocks lying outside the
302 segment. Filter them. */
303 dvd_demux->segment_filter = TRUE;
305 /* reset stream synchronization; parent handles other streams */
306 gst_mpeg_streams_reset_cur_ts (dvd_demux->subpicture_stream,
307 GST_DVD_DEMUX_NUM_SUBPICTURE_STREAMS, 0);
310 ret = GST_MPEG_PARSE_CLASS (parent_class)->process_event (mpeg_parse,
314 case GST_EVENT_FLUSH_STOP:
315 dvd_demux->segment_filter = TRUE;
316 ret = GST_MPEG_PARSE_CLASS (parent_class)->process_event (mpeg_parse,
319 /* parent class will have reset the other streams */
320 gst_mpeg_streams_reset_last_flow (dvd_demux->subpicture_stream,
321 GST_DVD_DEMUX_NUM_SUBPICTURE_STREAMS);
323 case GST_EVENT_CUSTOM_DOWNSTREAM:
324 case GST_EVENT_CUSTOM_DOWNSTREAM_OOB:
325 if (event->structure != NULL &&
326 gst_structure_has_name (event->structure, "application/x-gst-dvd")) {
327 ret = gst_dvd_demux_handle_dvd_event (dvd_demux, event);
329 ret = GST_MPEG_PARSE_CLASS (parent_class)->process_event (mpeg_parse,
334 ret = GST_MPEG_PARSE_CLASS (parent_class)->process_event (mpeg_parse,
343 gst_dvd_demux_handle_dvd_event (GstDVDDemux * dvd_demux, GstEvent * event)
345 GstMPEGParse *mpeg_parse = GST_MPEG_PARSE (dvd_demux);
346 GstMPEGDemux *mpeg_demux = GST_MPEG_DEMUX (dvd_demux);
347 const GstStructure *structure = gst_event_get_structure (event);
348 const char *event_type = gst_structure_get_string (structure, "event");
350 g_return_val_if_fail (event != NULL, FALSE);
352 GST_LOG_OBJECT (dvd_demux, "dvd event %" GST_PTR_FORMAT, structure);
354 if (strcmp (event_type, "dvd-audio-stream-change") == 0) {
357 gst_structure_get_int (structure, "physical", &stream_nr);
358 if (stream_nr < -1 || stream_nr >= GST_MPEG_DEMUX_NUM_AUDIO_STREAMS) {
359 GST_ERROR_OBJECT (dvd_demux,
360 "GstDVDDemux: Invalid audio stream %02d", stream_nr);
363 gst_dvd_demux_set_cur_audio (dvd_demux, stream_nr);
364 gst_event_unref (event);
365 } else if (strcmp (event_type, "dvd-spu-stream-change") == 0) {
368 gst_structure_get_int (structure, "physical", &stream_nr);
369 if (stream_nr < -1 || stream_nr >= GST_DVD_DEMUX_NUM_SUBPICTURE_STREAMS) {
370 GST_ERROR_OBJECT (dvd_demux,
371 "GstDVDDemux: Invalid subpicture stream %02d", stream_nr);
374 gst_dvd_demux_set_cur_subpicture (dvd_demux, stream_nr);
375 gst_event_unref (event);
376 } else if (!strcmp (event_type, "dvd-lang-codes")) {
377 gint num_substreams = 0, num_audstreams = 0, n;
381 if (dvd_demux->langcodes)
382 gst_event_unref (dvd_demux->langcodes);
384 /* see what kind of streams we have */
385 dvd_demux->langcodes = event;
387 /* now create pads for each; first video */
389 DEMUX_CLASS (dvd_demux)->get_video_stream (mpeg_demux,
390 0, GST_MPEG_DEMUX_VIDEO_MPEG, &n);
396 t = g_strdup_printf ("audio-%d-format", num_audstreams);
397 if (!gst_structure_get_int (structure, t, &fmt)) {
404 fmt = GST_DVD_DEMUX_AUDIO_AC3;
408 fmt = GST_MPEG_DEMUX_AUDIO_MPEG;
411 fmt = GST_DVD_DEMUX_AUDIO_LPCM;
414 fmt = GST_DVD_DEMUX_AUDIO_DTS;
417 fmt = GST_MPEG_DEMUX_AUDIO_UNKNOWN;
420 DEMUX_CLASS (dvd_demux)->get_audio_stream (mpeg_demux,
421 num_audstreams++, fmt, &ifo);
425 for (n = 0; n < GST_DVD_DEMUX_NUM_SUBPICTURE_STREAMS; n++) {
426 t = g_strdup_printf ("subtitle-%d-language", n);
427 if (!gst_structure_get_value (structure, t)) {
432 num_substreams = n + 1;
435 /* now we have a maximum,
436 * and can also fill empty slots in case of cranky DVD */
437 for (n = 0; n < num_substreams; n++)
438 CLASS (dvd_demux)->get_subpicture_stream (mpeg_demux,
439 n, GST_DVD_DEMUX_SUBP_DVD, NULL);
441 GST_DEBUG_OBJECT (dvd_demux,
442 "Created 1 video stream, %d audio streams and %d subpicture streams "
443 "based on DVD lang codes event; now signalling no-more-pads",
444 num_audstreams, num_substreams);
446 /* we know this will be all */
447 gst_element_no_more_pads (GST_ELEMENT (dvd_demux));
449 /* Keep video/audio/subtitle pads within 1/2 sec of the SCR */
450 mpeg_demux->max_gap = MAX_GAP;
451 mpeg_demux->max_gap_tolerance = MAX_GAP_TOLERANCE;
453 GST_DEBUG_OBJECT (dvd_demux, "dvddemux Forwarding DVD event %s to all pads",
456 PARSE_CLASS (dvd_demux)->send_event (mpeg_parse, event);
462 static GstMPEGStream *
463 gst_dvd_demux_get_video_stream (GstMPEGDemux * mpeg_demux,
464 guint8 stream_nr, gint type, const gpointer info)
466 GstDVDDemux *dvd_demux = GST_DVD_DEMUX (mpeg_demux);
468 parent_class->get_video_stream (mpeg_demux, stream_nr, type, info);
469 gint mpeg_version = *((gint *) info);
471 if (dvd_demux->mpeg_version != mpeg_version) {
473 gst_caps_unref (str->caps);
474 str->caps = gst_caps_new_simple ("video/mpeg",
475 "mpegversion", G_TYPE_INT, mpeg_version,
476 "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
478 if (!gst_pad_set_caps (dvd_demux->cur_video, str->caps)) {
479 GST_ELEMENT_ERROR (GST_ELEMENT (mpeg_demux),
480 CORE, NEGOTIATION, (NULL), ("failed to set caps"));
481 gst_caps_unref (str->caps);
485 dvd_demux->mpeg_version = mpeg_version;
489 dvd_demux->mpeg_version = mpeg_version;
493 static GstMPEGStream *
494 gst_dvd_demux_get_audio_stream (GstMPEGDemux * mpeg_demux,
495 guint8 stream_nr, gint type, const gpointer info)
497 GstDVDDemux *dvd_demux = GST_DVD_DEMUX (mpeg_demux);
498 guint32 sample_info = 0;
500 GstDVDLPCMStream *lpcm_str = NULL;
501 gboolean add_pad = FALSE;
502 const gchar *codec = NULL, *lang_code = NULL;
504 g_return_val_if_fail (stream_nr < GST_MPEG_DEMUX_NUM_AUDIO_STREAMS, NULL);
505 g_return_val_if_fail (type > GST_MPEG_DEMUX_AUDIO_UNKNOWN &&
506 type < GST_DVD_DEMUX_AUDIO_LAST, NULL);
508 if (type < GST_MPEG_DEMUX_AUDIO_LAST) {
509 /* FIXME: language codes on MPEG audio streams */
510 return parent_class->get_audio_stream (mpeg_demux, stream_nr, type, info);
513 if (type == GST_DVD_DEMUX_AUDIO_LPCM) {
514 sample_info = *((guint32 *) info);
517 str = mpeg_demux->audio_stream[stream_nr];
519 /* If the stream type is changing, recreate the pad */
520 if (str && str->type != type) {
521 gst_element_remove_pad (GST_ELEMENT (mpeg_demux), str->pad);
523 str = mpeg_demux->audio_stream[stream_nr] = NULL;
529 if (type != GST_DVD_DEMUX_AUDIO_LPCM) {
530 str = g_new0 (GstMPEGStream, 1);
532 lpcm_str = g_new0 (GstDVDLPCMStream, 1);
533 str = (GstMPEGStream *) lpcm_str;
536 name = g_strdup_printf ("audio_%02d", stream_nr);
537 DEMUX_CLASS (dvd_demux)->init_stream (mpeg_demux, type, str, stream_nr,
538 name, DEMUX_CLASS (dvd_demux)->audio_template);
540 str->type = GST_MPEG_DEMUX_AUDIO_UNKNOWN;
544 /* Stream size may have changed, reset it. */
545 if (type != GST_DVD_DEMUX_AUDIO_LPCM) {
546 str = g_renew (GstMPEGStream, str, 1);
548 lpcm_str = g_renew (GstDVDLPCMStream, str, 1);
549 str = (GstMPEGStream *) lpcm_str;
553 mpeg_demux->audio_stream[stream_nr] = str;
555 if (type != str->type ||
556 (type == GST_DVD_DEMUX_AUDIO_LPCM &&
557 sample_info != lpcm_str->sample_info)) {
558 gint width, rate, channels, dynamic_range;
559 gboolean emphasis, mute;
561 /* We need to set new caps for this pad. */
563 case GST_DVD_DEMUX_AUDIO_LPCM:
564 /* Dynamic range in the lower byte */
565 dynamic_range = sample_info & 0xff;
567 /* Determine the sample width. */
568 switch (sample_info & 0xC000) {
580 /* Determine the rate. */
581 if (sample_info & 0x1000) {
587 mute = ((sample_info & 0x400000) != 0);
588 emphasis = ((sample_info & 0x800000) != 0);
590 /* Determine the number of channels. */
591 channels = ((sample_info >> 8) & 0x7) + 1;
594 gst_caps_unref (str->caps);
595 str->caps = gst_caps_new_simple ("audio/x-lpcm",
596 "width", G_TYPE_INT, width,
597 "rate", G_TYPE_INT, rate,
598 "channels", G_TYPE_INT, channels,
599 "dynamic_range", G_TYPE_INT, dynamic_range,
600 "emphasis", G_TYPE_BOOLEAN, emphasis,
601 "mute", G_TYPE_BOOLEAN, mute, NULL);
603 lpcm_str->sample_info = sample_info;
604 lpcm_str->width = width;
605 lpcm_str->rate = rate;
606 lpcm_str->channels = channels;
607 lpcm_str->dynamic_range = dynamic_range;
608 lpcm_str->mute = mute;
609 lpcm_str->emphasis = emphasis;
610 codec = "LPCM audio";
613 case GST_DVD_DEMUX_AUDIO_AC3:
615 gst_caps_unref (str->caps);
616 str->caps = gst_caps_new_simple ("audio/x-ac3", NULL);
617 codec = "AC-3 audio";
620 case GST_DVD_DEMUX_AUDIO_DTS:
622 gst_caps_unref (str->caps);
623 str->caps = gst_caps_new_simple ("audio/x-dts", NULL);
628 g_return_val_if_reached (NULL);
632 if (!gst_pad_set_caps (str->pad, str->caps)) {
633 GST_ELEMENT_ERROR (GST_ELEMENT (mpeg_demux),
634 CORE, NEGOTIATION, (NULL),
635 ("failed to set caps on pad %s:%s", GST_DEBUG_PAD_NAME (str->pad)));
636 gst_caps_unref (str->caps);
641 if (str->number == dvd_demux->cur_audio_nr) {
642 /* This is the current audio stream. Use the same caps. */
643 if (!gst_pad_set_caps (dvd_demux->cur_audio, str->caps)) {
644 GST_ELEMENT_ERROR (GST_ELEMENT (mpeg_demux),
645 CORE, NEGOTIATION, (NULL), ("failed to set caps on pad %s:%s",
646 GST_DEBUG_PAD_NAME (dvd_demux->cur_audio)));
651 if (dvd_demux->langcodes) {
654 t = g_strdup_printf ("audio-%d-language", stream_nr);
656 gst_structure_get_string (gst_event_get_structure
657 (dvd_demux->langcodes), t);
661 GST_DEBUG_OBJECT (mpeg_demux, "adding pad %s with language = %s",
662 GST_PAD_NAME (str->pad), (lang_code) ? lang_code : "(unknown)");
664 gst_pad_set_active (str->pad, TRUE);
665 gst_element_add_pad (GST_ELEMENT (mpeg_demux), str->pad);
667 if (codec || lang_code) {
668 GstTagList *list = gst_tag_list_new ();
671 gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
672 GST_TAG_AUDIO_CODEC, codec, NULL);
675 gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
676 GST_TAG_LANGUAGE_CODE, lang_code, NULL);
678 str->tags = gst_tag_list_copy (list);
679 gst_element_found_tags_for_pad (GST_ELEMENT (mpeg_demux),
691 static GstMPEGStream *
692 gst_dvd_demux_get_subpicture_stream (GstMPEGDemux * mpeg_demux,
693 guint8 stream_nr, gint type, const gpointer info)
695 GstDVDDemux *dvd_demux = GST_DVD_DEMUX (mpeg_demux);
698 gboolean add_pad = FALSE;
699 const gchar *lang_code = NULL;
701 g_return_val_if_fail (stream_nr < GST_DVD_DEMUX_NUM_SUBPICTURE_STREAMS, NULL);
702 g_return_val_if_fail (type > GST_DVD_DEMUX_SUBP_UNKNOWN &&
703 type < GST_DVD_DEMUX_SUBP_LAST, NULL);
705 str = dvd_demux->subpicture_stream[stream_nr];
708 str = g_new0 (GstMPEGStream, 1);
710 name = g_strdup_printf ("subpicture_%02d", stream_nr);
711 DEMUX_CLASS (dvd_demux)->init_stream (mpeg_demux, type, str, stream_nr,
712 name, CLASS (dvd_demux)->subpicture_template);
713 str->type = GST_DVD_DEMUX_SUBP_UNKNOWN;
717 /* This stream may have been created by a derived class, reset the
719 str = g_renew (GstMPEGStream, str, 1);
722 dvd_demux->subpicture_stream[stream_nr] = str;
724 if (str->type != GST_DVD_DEMUX_SUBP_DVD) {
725 /* We need to set new caps for this pad. */
727 gst_caps_unref (str->caps);
728 str->caps = gst_caps_new_simple ("video/x-dvd-subpicture", NULL);
730 if (!gst_pad_set_caps (str->pad, str->caps)) {
731 GST_ELEMENT_ERROR (GST_ELEMENT (mpeg_demux),
732 CORE, NEGOTIATION, (NULL),
733 ("failed to set caps on pad %s:%s", GST_DEBUG_PAD_NAME (str->pad)));
734 gst_caps_unref (str->caps);
739 if (str->number == dvd_demux->cur_subpicture_nr) {
740 /* This is the current subpicture stream. Use the same caps. */
741 if (!gst_pad_set_caps (dvd_demux->cur_subpicture, str->caps)) {
742 GST_ELEMENT_ERROR (GST_ELEMENT (mpeg_demux),
743 CORE, NEGOTIATION, (NULL),
744 ("failed to set caps on pad %s:%s", GST_DEBUG_PAD_NAME (str->pad)));
749 if (dvd_demux->langcodes) {
752 t = g_strdup_printf ("subtitle-%d-language", stream_nr);
754 gst_structure_get_string (gst_event_get_structure
755 (dvd_demux->langcodes), t);
759 GST_DEBUG_OBJECT (mpeg_demux, "adding pad %s with language = %s",
760 GST_PAD_NAME (str->pad), (lang_code) ? lang_code : "(unknown)");
762 gst_pad_set_active (str->pad, TRUE);
763 gst_element_add_pad (GST_ELEMENT (mpeg_demux), str->pad);
766 GstTagList *list = gst_tag_list_new ();
768 gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
769 GST_TAG_LANGUAGE_CODE, lang_code, NULL);
770 str->tags = gst_tag_list_copy (list);
771 gst_element_found_tags_for_pad (GST_ELEMENT (mpeg_demux),
775 str->type = GST_DVD_DEMUX_SUBP_DVD;
782 gst_dvd_demux_parse_packhead (GstMPEGParse * mpeg_parse, GstBuffer * buffer)
784 GstMPEGDemux *mpeg_demux = GST_MPEG_DEMUX (mpeg_parse);
785 GstDVDDemux *dvd_demux = GST_DVD_DEMUX (mpeg_parse);
786 gboolean pending_tags = mpeg_demux->pending_tags;
788 GST_MPEG_PARSE_CLASS (parent_class)->parse_packhead (mpeg_parse, buffer);
791 GstMPEGStream **streams;
794 streams = dvd_demux->subpicture_stream;
795 num = GST_DVD_DEMUX_NUM_SUBPICTURE_STREAMS;
796 for (i = 0; i < num; ++i) {
797 if (streams[i] != NULL && streams[i]->tags != NULL)
798 gst_pad_push_event (streams[i]->pad,
799 gst_event_new_tag (gst_tag_list_copy (streams[i]->tags)));
807 gst_dvd_demux_process_private (GstMPEGDemux * mpeg_demux,
809 guint stream_nr, GstClockTime timestamp, guint headerlen, guint datalen)
811 GstDVDDemux *dvd_demux = GST_DVD_DEMUX (mpeg_demux);
812 GstFlowReturn ret = GST_FLOW_OK;
815 GstMPEGStream *outstream = NULL;
816 guint first_access = 0;
817 gint align = 1, len, off;
819 basebuf = GST_BUFFER_DATA (buffer);
821 /* Determine the substream number. */
822 ps_id_code = basebuf[headerlen + 4];
824 /* In the following, the "first access" refers to the location in a
825 buffer the time stamp is associated to. DVDs include this
826 information explicitely. */
829 /* Private stream 1. */
831 if (ps_id_code >= 0x80 && ps_id_code <= 0x87) {
832 GST_LOG_OBJECT (dvd_demux,
833 "we have an audio (AC3) packet, track %d", ps_id_code - 0x80);
834 outstream = DEMUX_CLASS (dvd_demux)->get_audio_stream (mpeg_demux,
835 ps_id_code - 0x80, GST_DVD_DEMUX_AUDIO_AC3, NULL);
837 /* Determine the position of the "first access". This
838 should always be the beginning of an AC3 frame. */
839 first_access = (basebuf[headerlen + 6] << 8) | basebuf[headerlen + 7];
843 } else if (ps_id_code >= 0x88 && ps_id_code <= 0x8f) {
844 GST_LOG_OBJECT (dvd_demux,
845 "we have an audio (DTS) packet, track %d", ps_id_code - 0x88);
846 outstream = DEMUX_CLASS (dvd_demux)->get_audio_stream (mpeg_demux,
847 ps_id_code - 0x88, GST_DVD_DEMUX_AUDIO_DTS, NULL);
849 /* Determine the position of the "first access". This
850 should always be the beginning of a DTS frame. */
851 first_access = (basebuf[headerlen + 6] << 8) | basebuf[headerlen + 7];
855 } else if (ps_id_code >= 0xA0 && ps_id_code <= 0xA7) {
856 GstDVDLPCMStream *lpcm_str;
857 guint32 lpcm_sample_info;
859 GST_LOG_OBJECT (dvd_demux,
860 "we have an audio (LPCM) packet, track %d", ps_id_code - 0xA0);
862 /* Compose the sample info from the LPCM header, masking out the frame_num */
864 basebuf[headerlen + 10] | (basebuf[headerlen +
865 9] << 8) | ((basebuf[headerlen + 8] & 0xc0) << 16);
867 outstream = DEMUX_CLASS (dvd_demux)->get_audio_stream (mpeg_demux,
868 ps_id_code - 0xA0, GST_DVD_DEMUX_AUDIO_LPCM, &lpcm_sample_info);
869 lpcm_str = (GstDVDLPCMStream *) outstream;
871 /* Determine the position of the "first access". */
872 first_access = (basebuf[headerlen + 6] << 8) | basebuf[headerlen + 7];
874 /* Get rid of the LPCM header. */
878 /* align by frame round up to nearest byte */
879 align = (lpcm_str->width * lpcm_str->channels + 7) / 8;
880 } else if (ps_id_code >= 0x20 && ps_id_code <= 0x3F) {
881 GST_LOG_OBJECT (dvd_demux,
882 "we have a subpicture packet, track %d", ps_id_code - 0x20);
883 outstream = CLASS (dvd_demux)->get_subpicture_stream (mpeg_demux,
884 ps_id_code - 0x20, GST_DVD_DEMUX_SUBP_DVD, NULL);
889 GST_WARNING_OBJECT (dvd_demux,
890 "unknown DVD (private 1) id 0x%02x", ps_id_code);
895 /* Private stream 2 */
897 switch (ps_id_code) {
899 GST_LOG_OBJECT (dvd_demux, "we have a PCI nav packet");
901 outstream = DEMUX_CLASS (mpeg_demux)->get_private_stream (mpeg_demux,
902 1, GST_MPEG_DEMUX_PRIVATE_UNKNOWN, NULL);
906 GST_LOG_OBJECT (dvd_demux, "we have a DSI nav packet");
908 outstream = DEMUX_CLASS (mpeg_demux)->get_private_stream (mpeg_demux,
909 1, GST_MPEG_DEMUX_PRIVATE_UNKNOWN, NULL);
913 GST_WARNING_OBJECT (dvd_demux,
914 "unknown DVD (private 2) id 0x%02x", ps_id_code);
920 g_return_val_if_reached (GST_FLOW_UNEXPECTED);
924 if (outstream == NULL) {
928 if (timestamp != GST_CLOCK_TIME_NONE && first_access > 1) {
929 /* We have a first access location. Since GStreamer doesn't have
930 a means to associate a timestamp to the middle of a buffer, we
931 send two separate buffers and put the timestamp in the second
934 len = first_access - 1;
937 ret = DEMUX_CLASS (dvd_demux)->send_subbuffer (mpeg_demux, outstream,
938 buffer, GST_CLOCK_TIME_NONE, off, len);
944 ret = DEMUX_CLASS (dvd_demux)->send_subbuffer (mpeg_demux, outstream,
945 buffer, timestamp, off, len);
952 ret = DEMUX_CLASS (dvd_demux)->send_subbuffer (mpeg_demux, outstream,
953 buffer, timestamp, off, len);
960 /* random magic value */
961 #define MIN_BUFS_FOR_NO_MORE_PADS 100
964 gst_dvd_demux_combine_flows (GstMPEGDemux * mpegdemux, GstMPEGStream * stream,
967 GstDVDDemux *demux = (GstDVDDemux *) mpegdemux;
970 /* store the value */
971 stream->last_flow = flow;
973 /* if it's success we can return the value right away */
974 if (flow == GST_FLOW_OK)
977 /* any other error that is not-linked can be returned right
979 if (flow != GST_FLOW_NOT_LINKED) {
980 GST_DEBUG_OBJECT (demux, "flow %s on pad %" GST_PTR_FORMAT,
981 gst_flow_get_name (flow), stream->pad);
985 /* let parent class check for anything non-not-linked for its streams */
987 GST_MPEG_DEMUX_CLASS (parent_class)->combine_flows (mpegdemux, stream,
989 if (flow != GST_FLOW_NOT_LINKED)
992 /* only return NOT_LINKED if all other pads returned NOT_LINKED */
993 for (i = 0; i < GST_DVD_DEMUX_NUM_SUBPICTURE_STREAMS; i++) {
994 if (demux->subpicture_stream[i] != NULL) {
995 flow = demux->subpicture_stream[i]->last_flow;
996 /* some other return value (must be SUCCESS but we can return
997 * other values as well) */
998 if (flow != GST_FLOW_NOT_LINKED)
1000 if (demux->subpicture_stream[i]->buffers_sent < MIN_BUFS_FOR_NO_MORE_PADS) {
1006 /* if we get here, all other pads were unlinked and we return
1007 * NOT_LINKED then */
1008 GST_DEBUG_OBJECT (demux, "all pads combined have not-linked flow");
1014 static GstFlowReturn
1015 gst_dvd_demux_send_subbuffer (GstMPEGDemux * mpeg_demux,
1016 GstMPEGStream * outstream, GstBuffer * buffer,
1017 GstClockTime timestamp, guint offset, guint size)
1019 GstDVDDemux *dvd_demux = GST_DVD_DEMUX (mpeg_demux);
1024 if (dvd_demux->segment_filter &&
1025 GST_MPEG_DEMUX_STREAM_KIND (outstream->type) ==
1026 GST_MPEG_DEMUX_STREAM_AUDIO) {
1027 /* We are in segment_filter mode and have an audio buffer. */
1028 if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
1029 /* This is the first valid audio buffer after the flush. */
1030 dvd_demux->segment_filter = FALSE;
1032 /* Discard the buffer. */
1037 /* You never know what happens to a buffer when you send it. Just
1038 in case, we keep a reference to the buffer during the execution
1039 of this function. */
1040 gst_buffer_ref (buffer);
1042 /* Send the buffer to the standard output pad. */
1043 ret = parent_class->send_subbuffer (mpeg_demux, outstream, buffer,
1044 timestamp, offset, size);
1046 /* Determine the current output pad and stream number for the given
1048 switch (GST_MPEG_DEMUX_STREAM_KIND (outstream->type)) {
1049 case GST_MPEG_DEMUX_STREAM_VIDEO:
1050 outpad = dvd_demux->cur_video;
1051 cur_nr = dvd_demux->cur_video_nr;
1053 case GST_MPEG_DEMUX_STREAM_AUDIO:
1054 outpad = dvd_demux->cur_audio;
1055 cur_nr = dvd_demux->cur_audio_nr;
1057 case GST_MPEG_DEMUX_STREAM_PRIVATE:
1061 case GST_DVD_DEMUX_STREAM_SUBPICTURE:
1062 outpad = dvd_demux->cur_subpicture;
1063 cur_nr = dvd_demux->cur_subpicture_nr;
1066 g_return_val_if_reached (GST_FLOW_UNEXPECTED);
1070 if (outpad != NULL && cur_nr == outstream->number && size > 0) {
1073 /* We have a packet of the current stream. Send it to the
1074 corresponding pad as well. */
1075 outbuf = gst_buffer_create_sub (buffer, offset, size);
1076 g_return_val_if_fail (outbuf != NULL, GST_FLOW_UNEXPECTED);
1078 GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
1079 GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET (buffer) + offset;
1080 gst_buffer_set_caps (outbuf, outstream->caps);
1082 ret = gst_pad_push (outpad, outbuf);
1084 /* this was one of the current_foo pads, which is shadowing one of the
1085 * foo_%02d pads, so since we keep track of the last flow value in the
1086 * stream structure we need to combine the OK/NOT_LINKED flows here
1087 * (because both pads share the same stream structure) */
1088 if ((ret == GST_FLOW_NOT_LINKED && outstream->last_flow == GST_FLOW_OK) ||
1089 (ret == GST_FLOW_OK && outstream->last_flow == GST_FLOW_NOT_LINKED)) {
1090 outstream->last_flow = GST_FLOW_OK;
1095 gst_buffer_unref (buffer);
1097 ret = DEMUX_CLASS (dvd_demux)->combine_flows (mpeg_demux, outstream, ret);
1103 gst_dvd_demux_set_cur_audio (GstDVDDemux * dvd_demux, gint stream_nr)
1105 GstMPEGDemux *mpeg_demux = GST_MPEG_DEMUX (dvd_demux);
1109 g_return_if_fail (stream_nr >= -1 &&
1110 stream_nr < GST_MPEG_DEMUX_NUM_AUDIO_STREAMS);
1112 GST_DEBUG_OBJECT (dvd_demux, "changing current audio to %02d", stream_nr);
1114 dvd_demux->cur_audio_nr = stream_nr;
1116 if (stream_nr == -1) {
1120 str = mpeg_demux->audio_stream[stream_nr];
1122 /* (Re)set the caps in the "current" pad. */
1123 caps = GST_PAD_CAPS (str->pad);
1125 gst_pad_set_caps (dvd_demux->cur_audio, caps);
1131 gst_dvd_demux_set_cur_subpicture (GstDVDDemux * dvd_demux, gint stream_nr)
1135 g_return_if_fail (stream_nr >= -1 &&
1136 stream_nr < GST_DVD_DEMUX_NUM_SUBPICTURE_STREAMS);
1138 GST_DEBUG_OBJECT (dvd_demux, "changing current subpicture to %02d",
1141 dvd_demux->cur_subpicture_nr = stream_nr;
1143 if (stream_nr == -1) {
1147 str = dvd_demux->subpicture_stream[stream_nr];
1149 GstCaps *caps = NULL;
1151 /* (Re)set the caps in the "current" pad. */
1152 caps = GST_PAD_CAPS (str->pad);
1153 gst_pad_set_caps (dvd_demux->cur_subpicture, caps);
1158 gst_dvd_demux_reset (GstDVDDemux * dvd_demux)
1162 GstMPEGDemux *mpeg_demux = GST_MPEG_DEMUX (dvd_demux);
1164 GST_INFO ("Resetting the dvd demuxer");
1165 for (i = 0; i < GST_DVD_DEMUX_NUM_SUBPICTURE_STREAMS; i++) {
1166 if (dvd_demux->subpicture_stream[i]) {
1167 gst_pad_push_event (dvd_demux->subpicture_stream[i]->pad,
1168 gst_event_new_eos ());
1170 gst_element_remove_pad (GST_ELEMENT (dvd_demux),
1171 dvd_demux->subpicture_stream[i]->pad);
1172 if (dvd_demux->subpicture_stream[i]->caps)
1173 gst_caps_unref (dvd_demux->subpicture_stream[i]->caps);
1174 if (dvd_demux->subpicture_stream[i]->tags)
1175 gst_tag_list_free (dvd_demux->subpicture_stream[i]->tags);
1176 g_free (dvd_demux->subpicture_stream[i]);
1177 dvd_demux->subpicture_stream[i] = NULL;
1180 gst_pad_set_caps (dvd_demux->cur_video, NULL);
1181 gst_pad_set_caps (dvd_demux->cur_audio, NULL);
1182 gst_pad_set_caps (dvd_demux->cur_subpicture, NULL);
1184 dvd_demux->cur_video_nr = 0;
1185 dvd_demux->cur_audio_nr = 0;
1186 dvd_demux->cur_subpicture_nr = 0;
1187 dvd_demux->mpeg_version = 0;
1189 /* Reset max_gap handling */
1190 mpeg_demux->max_gap = MAX_GAP;
1191 mpeg_demux->max_gap_tolerance = MAX_GAP_TOLERANCE;
1195 gst_dvd_demux_synchronise_pads (GstMPEGDemux * mpeg_demux,
1196 GstClockTime threshold, GstClockTime new_ts)
1198 GstDVDDemux *dvd_demux = GST_DVD_DEMUX (mpeg_demux);
1201 parent_class->synchronise_pads (mpeg_demux, threshold, new_ts);
1203 for (i = 0; i < GST_DVD_DEMUX_NUM_SUBPICTURE_STREAMS; i++) {
1204 if (dvd_demux->subpicture_stream[i]) {
1205 GST_LOG_OBJECT (mpeg_demux, "stream: %d, current: %" GST_TIME_FORMAT
1206 ", threshold %" GST_TIME_FORMAT, i,
1207 GST_TIME_ARGS (dvd_demux->subpicture_stream[i]->cur_ts),
1208 GST_TIME_ARGS (threshold));
1209 if (dvd_demux->subpicture_stream[i]->cur_ts < threshold) {
1210 DEMUX_CLASS (mpeg_demux)->sync_stream_to_time (mpeg_demux,
1211 dvd_demux->subpicture_stream[i], new_ts);
1212 dvd_demux->subpicture_stream[i]->cur_ts = new_ts;
1219 gst_dvd_demux_sync_stream_to_time (GstMPEGDemux * mpeg_demux,
1220 GstMPEGStream * stream, GstClockTime last_ts)
1222 GstDVDDemux *dvd_demux = GST_DVD_DEMUX (mpeg_demux);
1223 GstMPEGParse *mpeg_parse = GST_MPEG_PARSE (mpeg_demux);
1227 parent_class->sync_stream_to_time (mpeg_demux, stream, last_ts);
1229 switch (GST_MPEG_DEMUX_STREAM_KIND (stream->type)) {
1230 case GST_MPEG_DEMUX_STREAM_VIDEO:
1231 outpad = dvd_demux->cur_video;
1232 cur_nr = dvd_demux->cur_video_nr;
1234 case GST_MPEG_DEMUX_STREAM_AUDIO:
1235 outpad = dvd_demux->cur_audio;
1236 cur_nr = dvd_demux->cur_audio_nr;
1238 case GST_DVD_DEMUX_STREAM_SUBPICTURE:
1239 outpad = dvd_demux->cur_subpicture;
1240 cur_nr = dvd_demux->cur_subpicture_nr;
1246 if (outpad && (cur_nr == stream->number)) {
1247 guint64 update_time;
1250 MIN ((guint64) last_ts, (guint64) mpeg_parse->current_segment.stop);
1251 gst_pad_push_event (outpad, gst_event_new_new_segment (TRUE,
1252 mpeg_parse->current_segment.rate, GST_FORMAT_TIME,
1253 update_time, mpeg_parse->current_segment.stop, update_time));
1257 static GstStateChangeReturn
1258 gst_dvd_demux_change_state (GstElement * element, GstStateChange transition)
1260 GstDVDDemux *dvd_demux = GST_DVD_DEMUX (element);
1261 GstStateChangeReturn ret;
1263 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1265 switch (transition) {
1266 case GST_STATE_CHANGE_PAUSED_TO_READY:
1267 gst_dvd_demux_reset (dvd_demux);
1268 if (dvd_demux->langcodes) {
1269 gst_event_unref (dvd_demux->langcodes);
1270 dvd_demux->langcodes = NULL;
1280 gst_dvd_demux_plugin_init (GstPlugin * plugin)
1282 return gst_element_register (plugin, "dvddemux",
1283 GST_RANK_SECONDARY + 1, GST_TYPE_DVD_DEMUX);