Tizen 2.1 base
[profile/ivi/gst-plugins-ugly0.10.git] / gst / mpegstream / gstdvddemux.c
1 /* GStreamer
2  * Copyright (C) 2005 Martin Soto <martinsoto@users.sourceforge.net>
3  *
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.
8  *
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.
13  *
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.
18  */
19
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <string.h>
26
27 #include "gstdvddemux.h"
28
29 /* 
30  * Move PTM discont back by 0.3 seconds to allow for strange audio
31  * timestamps when audio crosses a VOBU 
32  */
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 )
37
38 GST_DEBUG_CATEGORY_STATIC (gstdvddemux_debug);
39 #define GST_CAT_DEFAULT (gstdvddemux_debug)
40
41
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))
45
46 /* DVDDemux signals and args */
47 enum
48 {
49   /* FILL ME */
50   LAST_SIGNAL
51 };
52
53 enum
54 {
55   ARG_0
56       /* FILL ME */
57 };
58
59
60 /* Define the capabilities separately, to be able to reuse them. */
61
62 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
63     GST_PAD_SINK,
64     GST_PAD_ALWAYS,
65     GST_STATIC_CAPS ("video/mpeg, "
66         "mpegversion = (int) 2, " "systemstream = (boolean) TRUE")
67     );
68
69 #define VIDEO_CAPS \
70   GST_STATIC_CAPS ("video/mpeg, " \
71     "mpegversion = (int) { 1, 2 }, " \
72     "systemstream = (boolean) FALSE" \
73   )
74
75 #define AUDIO_CAPS \
76   GST_STATIC_CAPS ( \
77     "audio/mpeg, " \
78       "mpegversion = (int) 1;" \
79     "audio/x-lpcm, " \
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 }; " \
86     "audio/x-ac3;" \
87     "audio/x-dts" \
88   )
89
90 #define SUBPICTURE_CAPS \
91   GST_STATIC_CAPS ("video/x-dvd-subpicture")
92
93 static GstStaticPadTemplate cur_video_template =
94 GST_STATIC_PAD_TEMPLATE ("current_video",
95     GST_PAD_SRC,
96     GST_PAD_ALWAYS,
97     VIDEO_CAPS);
98
99 static GstStaticPadTemplate audio_template =
100 GST_STATIC_PAD_TEMPLATE ("dvd_audio_%02d",
101     GST_PAD_SRC,
102     GST_PAD_SOMETIMES,
103     AUDIO_CAPS);
104
105 static GstStaticPadTemplate cur_audio_template =
106 GST_STATIC_PAD_TEMPLATE ("current_audio",
107     GST_PAD_SRC,
108     GST_PAD_ALWAYS,
109     AUDIO_CAPS);
110
111 static GstStaticPadTemplate subpicture_template =
112 GST_STATIC_PAD_TEMPLATE ("subpicture_%d",
113     GST_PAD_SRC,
114     GST_PAD_SOMETIMES,
115     SUBPICTURE_CAPS);
116
117 static GstStaticPadTemplate cur_subpicture_template =
118 GST_STATIC_PAD_TEMPLATE ("current_subpicture",
119     GST_PAD_SRC,
120     GST_PAD_ALWAYS,
121     SUBPICTURE_CAPS);
122
123 #define _do_init(bla) \
124     GST_DEBUG_CATEGORY_INIT (gstdvddemux_debug, "dvddemux", 0, \
125         "DVD (VOB) demultiplexer element");
126
127 GST_BOILERPLATE_FULL (GstDVDDemux, gst_dvd_demux, GstMPEGDemux,
128     GST_TYPE_MPEG_DEMUX, _do_init);
129
130 static gboolean gst_dvd_demux_process_event (GstMPEGParse * mpeg_parse,
131     GstEvent * event);
132 static gboolean gst_dvd_demux_parse_packhead (GstMPEGParse * mpeg_parse,
133     GstBuffer * buffer);
134
135 static gboolean gst_dvd_demux_handle_dvd_event
136     (GstDVDDemux * dvd_demux, GstEvent * event);
137
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);
147
148 static GstFlowReturn gst_dvd_demux_process_private
149     (GstMPEGDemux * mpeg_demux,
150     GstBuffer * buffer,
151     guint stream_nr, GstClockTime timestamp, guint headerlen, guint datalen);
152
153 static GstFlowReturn gst_dvd_demux_send_subbuffer
154     (GstMPEGDemux * mpeg_demux,
155     GstMPEGStream * outstream,
156     GstBuffer * buffer, GstClockTime timestamp, guint offset, guint size);
157
158 static GstFlowReturn gst_dvd_demux_combine_flows (GstMPEGDemux * mpegdemux,
159     GstMPEGStream * stream, GstFlowReturn flow);
160
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);
165
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);
171
172 static GstStateChangeReturn gst_dvd_demux_change_state (GstElement * element,
173     GstStateChange transition);
174
175 /*static guint gst_dvd_demux_signals[LAST_SIGNAL] = { 0 };*/
176
177
178 static void
179 gst_dvd_demux_base_init (gpointer klass)
180 {
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);
185
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;
189
190   /* sink pad */
191   gst_element_class_add_static_pad_template (element_class,
192       &sink_template);
193
194   demux_class->audio_template = gst_static_pad_template_get (&audio_template);
195
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);
204
205   gst_element_class_add_pad_template (element_class,
206       demux_class->audio_template);
207
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);
212
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);
217
218   gst_element_class_set_details_simple (element_class, "DVD Demuxer",
219       "Codec/Demuxer",
220       "Demultiplexes DVD (VOB) MPEG2 streams",
221       "Martin Soto <martinsoto@users.sourceforge.net>");
222 }
223
224
225 static void
226 gst_dvd_demux_class_init (GstDVDDemuxClass * klass)
227 {
228   GstElementClass *gstelement_class;
229   GstMPEGDemuxClass *mpeg_demux_class;
230
231   parent_class = g_type_class_peek_parent (klass);
232
233   gstelement_class = (GstElementClass *) klass;
234   mpeg_demux_class = (GstMPEGDemuxClass *) klass;
235
236   gstelement_class->change_state = gst_dvd_demux_change_state;
237
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;
245
246   klass->get_subpicture_stream = gst_dvd_demux_get_subpicture_stream;
247 }
248
249
250 static void
251 gst_dvd_demux_init (GstDVDDemux * dvd_demux, GstDVDDemuxClass * klass)
252 {
253   GstMPEGDemux *mpeg_demux = GST_MPEG_DEMUX (dvd_demux);
254   gint i;
255
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);
269
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;
274
275   for (i = 0; i < GST_DVD_DEMUX_NUM_SUBPICTURE_STREAMS; i++) {
276     dvd_demux->subpicture_stream[i] = NULL;
277   }
278
279   /* Directly after starting we operate as if we had just flushed. */
280   dvd_demux->segment_filter = TRUE;
281
282   dvd_demux->langcodes = NULL;
283 }
284
285 static gboolean
286 gst_dvd_demux_process_event (GstMPEGParse * mpeg_parse, GstEvent * event)
287 {
288   GstDVDDemux *dvd_demux = GST_DVD_DEMUX (mpeg_parse);
289   gboolean ret = TRUE;
290
291   switch (GST_EVENT_TYPE (event)) {
292     case GST_EVENT_NEWSEGMENT:
293     {
294       gboolean update;
295
296       gst_event_parse_new_segment (event, &update, NULL, NULL,
297           NULL, NULL, NULL);
298
299       if (!update) {
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;
304
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);
308       }
309
310       ret = GST_MPEG_PARSE_CLASS (parent_class)->process_event (mpeg_parse,
311           event);
312       break;
313     }
314     case GST_EVENT_FLUSH_STOP:
315       dvd_demux->segment_filter = TRUE;
316       ret = GST_MPEG_PARSE_CLASS (parent_class)->process_event (mpeg_parse,
317           event);
318
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);
322       break;
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);
328       } else {
329         ret = GST_MPEG_PARSE_CLASS (parent_class)->process_event (mpeg_parse,
330             event);
331       }
332       break;
333     default:
334       ret = GST_MPEG_PARSE_CLASS (parent_class)->process_event (mpeg_parse,
335           event);
336       break;
337   }
338
339   return ret;
340 }
341
342 static gboolean
343 gst_dvd_demux_handle_dvd_event (GstDVDDemux * dvd_demux, GstEvent * event)
344 {
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");
349
350   g_return_val_if_fail (event != NULL, FALSE);
351
352   GST_LOG_OBJECT (dvd_demux, "dvd event %" GST_PTR_FORMAT, structure);
353
354   if (strcmp (event_type, "dvd-audio-stream-change") == 0) {
355     gint stream_nr;
356
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);
361       return FALSE;
362     }
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) {
366     gint stream_nr;
367
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);
372       return FALSE;
373     }
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;
378     gchar *t;
379
380     /* reset */
381     if (dvd_demux->langcodes)
382       gst_event_unref (dvd_demux->langcodes);
383
384     /* see what kind of streams we have */
385     dvd_demux->langcodes = event;
386
387     /* now create pads for each; first video */
388     n = 2;
389     DEMUX_CLASS (dvd_demux)->get_video_stream (mpeg_demux,
390         0, GST_MPEG_DEMUX_VIDEO_MPEG, &n);
391
392     /* audio */
393     for (n = 0;; n++) {
394       gint fmt, ifo = 0;
395
396       t = g_strdup_printf ("audio-%d-format", num_audstreams);
397       if (!gst_structure_get_int (structure, t, &fmt)) {
398         g_free (t);
399         break;
400       }
401       g_free (t);
402       switch (fmt) {
403         case 0x0:              /* AC-3 */
404           fmt = GST_DVD_DEMUX_AUDIO_AC3;
405           break;
406         case 0x2:
407         case 0x3:              /* MPEG */
408           fmt = GST_MPEG_DEMUX_AUDIO_MPEG;
409           break;
410         case 0x4:
411           fmt = GST_DVD_DEMUX_AUDIO_LPCM;
412           break;
413         case 0x6:
414           fmt = GST_DVD_DEMUX_AUDIO_DTS;
415           break;
416         default:
417           fmt = GST_MPEG_DEMUX_AUDIO_UNKNOWN;
418           break;
419       }
420       DEMUX_CLASS (dvd_demux)->get_audio_stream (mpeg_demux,
421           num_audstreams++, fmt, &ifo);
422     }
423
424     /* subtitle */
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)) {
428         g_free (t);
429         continue;
430       }
431       g_free (t);
432       num_substreams = n + 1;
433     }
434
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);
440
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);
445
446     /* we know this will be all */
447     gst_element_no_more_pads (GST_ELEMENT (dvd_demux));
448
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;
452   } else {
453     GST_DEBUG_OBJECT (dvd_demux, "dvddemux Forwarding DVD event %s to all pads",
454         event_type);
455
456     PARSE_CLASS (dvd_demux)->send_event (mpeg_parse, event);
457   }
458
459   return TRUE;
460 }
461
462 static GstMPEGStream *
463 gst_dvd_demux_get_video_stream (GstMPEGDemux * mpeg_demux,
464     guint8 stream_nr, gint type, const gpointer info)
465 {
466   GstDVDDemux *dvd_demux = GST_DVD_DEMUX (mpeg_demux);
467   GstMPEGStream *str =
468       parent_class->get_video_stream (mpeg_demux, stream_nr, type, info);
469   gint mpeg_version = *((gint *) info);
470
471   if (dvd_demux->mpeg_version != mpeg_version) {
472     if (str->caps)
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);
477
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);
482       str->caps = NULL;
483       return str;
484     } else {
485       dvd_demux->mpeg_version = mpeg_version;
486     }
487   }
488
489   dvd_demux->mpeg_version = mpeg_version;
490   return str;
491 }
492
493 static GstMPEGStream *
494 gst_dvd_demux_get_audio_stream (GstMPEGDemux * mpeg_demux,
495     guint8 stream_nr, gint type, const gpointer info)
496 {
497   GstDVDDemux *dvd_demux = GST_DVD_DEMUX (mpeg_demux);
498   guint32 sample_info = 0;
499   GstMPEGStream *str;
500   GstDVDLPCMStream *lpcm_str = NULL;
501   gboolean add_pad = FALSE;
502   const gchar *codec = NULL, *lang_code = NULL;
503
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);
507
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);
511   }
512
513   if (type == GST_DVD_DEMUX_AUDIO_LPCM) {
514     sample_info = *((guint32 *) info);
515   }
516
517   str = mpeg_demux->audio_stream[stream_nr];
518
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);
522     g_free (str);
523     str = mpeg_demux->audio_stream[stream_nr] = NULL;
524   }
525
526   if (str == NULL) {
527     gchar *name;
528
529     if (type != GST_DVD_DEMUX_AUDIO_LPCM) {
530       str = g_new0 (GstMPEGStream, 1);
531     } else {
532       lpcm_str = g_new0 (GstDVDLPCMStream, 1);
533       str = (GstMPEGStream *) lpcm_str;
534     }
535
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);
539     /* update caps */
540     str->type = GST_MPEG_DEMUX_AUDIO_UNKNOWN;
541     g_free (name);
542     add_pad = TRUE;
543   } else {
544     /* Stream size may have changed, reset it. */
545     if (type != GST_DVD_DEMUX_AUDIO_LPCM) {
546       str = g_renew (GstMPEGStream, str, 1);
547     } else {
548       lpcm_str = g_renew (GstDVDLPCMStream, str, 1);
549       str = (GstMPEGStream *) lpcm_str;
550     }
551   }
552
553   mpeg_demux->audio_stream[stream_nr] = str;
554
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;
560
561     /* We need to set new caps for this pad. */
562     switch (type) {
563       case GST_DVD_DEMUX_AUDIO_LPCM:
564         /* Dynamic range in the lower byte */
565         dynamic_range = sample_info & 0xff;
566
567         /* Determine the sample width. */
568         switch (sample_info & 0xC000) {
569           case 0x8000:
570             width = 24;
571             break;
572           case 0x4000:
573             width = 20;
574             break;
575           default:
576             width = 16;
577             break;
578         }
579
580         /* Determine the rate. */
581         if (sample_info & 0x1000) {
582           rate = 96000;
583         } else {
584           rate = 48000;
585         }
586
587         mute = ((sample_info & 0x400000) != 0);
588         emphasis = ((sample_info & 0x800000) != 0);
589
590         /* Determine the number of channels. */
591         channels = ((sample_info >> 8) & 0x7) + 1;
592
593         if (str->caps)
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);
602
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";
611         break;
612
613       case GST_DVD_DEMUX_AUDIO_AC3:
614         if (str->caps)
615           gst_caps_unref (str->caps);
616         str->caps = gst_caps_new_simple ("audio/x-ac3", NULL);
617         codec = "AC-3 audio";
618         break;
619
620       case GST_DVD_DEMUX_AUDIO_DTS:
621         if (str->caps)
622           gst_caps_unref (str->caps);
623         str->caps = gst_caps_new_simple ("audio/x-dts", NULL);
624         codec = "DTS audio";
625         break;
626
627       default:
628         g_return_val_if_reached (NULL);
629         break;
630     }
631
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);
637       str->caps = NULL;
638       return str;
639     }
640
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)));
647       }
648     }
649
650     if (add_pad) {
651       if (dvd_demux->langcodes) {
652         gchar *t;
653
654         t = g_strdup_printf ("audio-%d-language", stream_nr);
655         lang_code =
656             gst_structure_get_string (gst_event_get_structure
657             (dvd_demux->langcodes), t);
658         g_free (t);
659       }
660
661       GST_DEBUG_OBJECT (mpeg_demux, "adding pad %s with language = %s",
662           GST_PAD_NAME (str->pad), (lang_code) ? lang_code : "(unknown)");
663
664       gst_pad_set_active (str->pad, TRUE);
665       gst_element_add_pad (GST_ELEMENT (mpeg_demux), str->pad);
666
667       if (codec || lang_code) {
668         GstTagList *list = gst_tag_list_new ();
669
670         if (codec) {
671           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
672               GST_TAG_AUDIO_CODEC, codec, NULL);
673         }
674         if (lang_code) {
675           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
676               GST_TAG_LANGUAGE_CODE, lang_code, NULL);
677         }
678         str->tags = gst_tag_list_copy (list);
679         gst_element_found_tags_for_pad (GST_ELEMENT (mpeg_demux),
680             str->pad, list);
681       }
682     }
683
684     str->type = type;
685   }
686
687   return str;
688 }
689
690
691 static GstMPEGStream *
692 gst_dvd_demux_get_subpicture_stream (GstMPEGDemux * mpeg_demux,
693     guint8 stream_nr, gint type, const gpointer info)
694 {
695   GstDVDDemux *dvd_demux = GST_DVD_DEMUX (mpeg_demux);
696   GstMPEGStream *str;
697   gchar *name;
698   gboolean add_pad = FALSE;
699   const gchar *lang_code = NULL;
700
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);
704
705   str = dvd_demux->subpicture_stream[stream_nr];
706
707   if (str == NULL) {
708     str = g_new0 (GstMPEGStream, 1);
709
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;
714     g_free (name);
715     add_pad = TRUE;
716   } else {
717     /* This stream may have been created by a derived class, reset the
718        size. */
719     str = g_renew (GstMPEGStream, str, 1);
720   }
721
722   dvd_demux->subpicture_stream[stream_nr] = str;
723
724   if (str->type != GST_DVD_DEMUX_SUBP_DVD) {
725     /* We need to set new caps for this pad. */
726     if (str->caps)
727       gst_caps_unref (str->caps);
728     str->caps = gst_caps_new_simple ("video/x-dvd-subpicture", NULL);
729
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);
735       str->caps = NULL;
736       return str;
737     }
738
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)));
745       }
746     }
747
748     if (add_pad) {
749       if (dvd_demux->langcodes) {
750         gchar *t;
751
752         t = g_strdup_printf ("subtitle-%d-language", stream_nr);
753         lang_code =
754             gst_structure_get_string (gst_event_get_structure
755             (dvd_demux->langcodes), t);
756         g_free (t);
757       }
758
759       GST_DEBUG_OBJECT (mpeg_demux, "adding pad %s with language = %s",
760           GST_PAD_NAME (str->pad), (lang_code) ? lang_code : "(unknown)");
761
762       gst_pad_set_active (str->pad, TRUE);
763       gst_element_add_pad (GST_ELEMENT (mpeg_demux), str->pad);
764
765       if (lang_code) {
766         GstTagList *list = gst_tag_list_new ();
767
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),
772             str->pad, list);
773       }
774     }
775     str->type = GST_DVD_DEMUX_SUBP_DVD;
776   }
777
778   return str;
779 }
780
781 static gboolean
782 gst_dvd_demux_parse_packhead (GstMPEGParse * mpeg_parse, GstBuffer * buffer)
783 {
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;
787
788   GST_MPEG_PARSE_CLASS (parent_class)->parse_packhead (mpeg_parse, buffer);
789
790   if (pending_tags) {
791     GstMPEGStream **streams;
792     guint i, num;
793
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)));
800     }
801   }
802
803   return TRUE;
804 }
805
806 static GstFlowReturn
807 gst_dvd_demux_process_private (GstMPEGDemux * mpeg_demux,
808     GstBuffer * buffer,
809     guint stream_nr, GstClockTime timestamp, guint headerlen, guint datalen)
810 {
811   GstDVDDemux *dvd_demux = GST_DVD_DEMUX (mpeg_demux);
812   GstFlowReturn ret = GST_FLOW_OK;
813   guint8 *basebuf;
814   guint8 ps_id_code;
815   GstMPEGStream *outstream = NULL;
816   guint first_access = 0;
817   gint align = 1, len, off;
818
819   basebuf = GST_BUFFER_DATA (buffer);
820
821   /* Determine the substream number. */
822   ps_id_code = basebuf[headerlen + 4];
823
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. */
827   switch (stream_nr) {
828     case 0:
829       /* Private stream 1. */
830
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);
836
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];
840
841         headerlen += 4;
842         datalen -= 4;
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);
848
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];
852
853         headerlen += 4;
854         datalen -= 4;
855       } else if (ps_id_code >= 0xA0 && ps_id_code <= 0xA7) {
856         GstDVDLPCMStream *lpcm_str;
857         guint32 lpcm_sample_info;
858
859         GST_LOG_OBJECT (dvd_demux,
860             "we have an audio (LPCM) packet, track %d", ps_id_code - 0xA0);
861
862         /* Compose the sample info from the LPCM header, masking out the frame_num */
863         lpcm_sample_info =
864             basebuf[headerlen + 10] | (basebuf[headerlen +
865                 9] << 8) | ((basebuf[headerlen + 8] & 0xc0) << 16);
866
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;
870
871         /* Determine the position of the "first access". */
872         first_access = (basebuf[headerlen + 6] << 8) | basebuf[headerlen + 7];
873
874         /* Get rid of the LPCM header. */
875         headerlen += 7;
876         datalen -= 7;
877
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);
885
886         headerlen += 1;
887         datalen -= 1;
888       } else {
889         GST_WARNING_OBJECT (dvd_demux,
890             "unknown DVD (private 1) id 0x%02x", ps_id_code);
891       }
892       break;
893
894     case 1:
895       /* Private stream 2 */
896
897       switch (ps_id_code) {
898         case 0:
899           GST_LOG_OBJECT (dvd_demux, "we have a PCI nav packet");
900
901           outstream = DEMUX_CLASS (mpeg_demux)->get_private_stream (mpeg_demux,
902               1, GST_MPEG_DEMUX_PRIVATE_UNKNOWN, NULL);
903           break;
904
905         case 1:
906           GST_LOG_OBJECT (dvd_demux, "we have a DSI nav packet");
907
908           outstream = DEMUX_CLASS (mpeg_demux)->get_private_stream (mpeg_demux,
909               1, GST_MPEG_DEMUX_PRIVATE_UNKNOWN, NULL);
910           break;
911
912         default:
913           GST_WARNING_OBJECT (dvd_demux,
914               "unknown DVD (private 2) id 0x%02x", ps_id_code);
915           break;
916       }
917       break;
918
919     default:
920       g_return_val_if_reached (GST_FLOW_UNEXPECTED);
921       break;
922   }
923
924   if (outstream == NULL) {
925     return GST_FLOW_OK;
926   }
927
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
932        one. */
933     off = headerlen + 4;
934     len = first_access - 1;
935     len -= len % align;
936     if (len > 0) {
937       ret = DEMUX_CLASS (dvd_demux)->send_subbuffer (mpeg_demux, outstream,
938           buffer, GST_CLOCK_TIME_NONE, off, len);
939     }
940     off += len;
941     len = datalen - len;
942     len -= len % align;
943     if (len > 0) {
944       ret = DEMUX_CLASS (dvd_demux)->send_subbuffer (mpeg_demux, outstream,
945           buffer, timestamp, off, len);
946     }
947   } else {
948     off = headerlen + 4;
949     len = datalen;
950     len -= len % align;
951     if (len > 0) {
952       ret = DEMUX_CLASS (dvd_demux)->send_subbuffer (mpeg_demux, outstream,
953           buffer, timestamp, off, len);
954     }
955   }
956
957   return ret;
958 }
959
960 /* random magic value */
961 #define MIN_BUFS_FOR_NO_MORE_PADS 100
962
963 static GstFlowReturn
964 gst_dvd_demux_combine_flows (GstMPEGDemux * mpegdemux, GstMPEGStream * stream,
965     GstFlowReturn flow)
966 {
967   GstDVDDemux *demux = (GstDVDDemux *) mpegdemux;
968   gint i;
969
970   /* store the value */
971   stream->last_flow = flow;
972
973   /* if it's success we can return the value right away */
974   if (flow == GST_FLOW_OK)
975     goto done;
976
977   /* any other error that is not-linked can be returned right
978    * away */
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);
982     goto done;
983   }
984
985   /* let parent class check for anything non-not-linked for its streams */
986   flow =
987       GST_MPEG_DEMUX_CLASS (parent_class)->combine_flows (mpegdemux, stream,
988       flow);
989   if (flow != GST_FLOW_NOT_LINKED)
990     goto done;
991
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)
999         goto done;
1000       if (demux->subpicture_stream[i]->buffers_sent < MIN_BUFS_FOR_NO_MORE_PADS) {
1001         flow = GST_FLOW_OK;
1002         goto done;
1003       }
1004     }
1005   }
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");
1009
1010 done:
1011   return flow;
1012 }
1013
1014 static GstFlowReturn
1015 gst_dvd_demux_send_subbuffer (GstMPEGDemux * mpeg_demux,
1016     GstMPEGStream * outstream, GstBuffer * buffer,
1017     GstClockTime timestamp, guint offset, guint size)
1018 {
1019   GstDVDDemux *dvd_demux = GST_DVD_DEMUX (mpeg_demux);
1020   GstFlowReturn ret;
1021   GstPad *outpad;
1022   gint cur_nr;
1023
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;
1031     } else {
1032       /* Discard the buffer. */
1033       return GST_FLOW_OK;
1034     }
1035   }
1036
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);
1041
1042   /* Send the buffer to the standard output pad. */
1043   ret = parent_class->send_subbuffer (mpeg_demux, outstream, buffer,
1044       timestamp, offset, size);
1045
1046   /* Determine the current output pad and stream number for the given
1047      type of stream. */
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;
1052       break;
1053     case GST_MPEG_DEMUX_STREAM_AUDIO:
1054       outpad = dvd_demux->cur_audio;
1055       cur_nr = dvd_demux->cur_audio_nr;
1056       break;
1057     case GST_MPEG_DEMUX_STREAM_PRIVATE:
1058       outpad = NULL;
1059       cur_nr = 0;
1060       break;
1061     case GST_DVD_DEMUX_STREAM_SUBPICTURE:
1062       outpad = dvd_demux->cur_subpicture;
1063       cur_nr = dvd_demux->cur_subpicture_nr;
1064       break;
1065     default:
1066       g_return_val_if_reached (GST_FLOW_UNEXPECTED);
1067       break;
1068   }
1069
1070   if (outpad != NULL && cur_nr == outstream->number && size > 0) {
1071     GstBuffer *outbuf;
1072
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);
1077
1078     GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
1079     GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET (buffer) + offset;
1080     gst_buffer_set_caps (outbuf, outstream->caps);
1081
1082     ret = gst_pad_push (outpad, outbuf);
1083
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;
1091       ret = GST_FLOW_OK;
1092     }
1093   }
1094
1095   gst_buffer_unref (buffer);
1096
1097   ret = DEMUX_CLASS (dvd_demux)->combine_flows (mpeg_demux, outstream, ret);
1098
1099   return ret;
1100 }
1101
1102 static void
1103 gst_dvd_demux_set_cur_audio (GstDVDDemux * dvd_demux, gint stream_nr)
1104 {
1105   GstMPEGDemux *mpeg_demux = GST_MPEG_DEMUX (dvd_demux);
1106   GstMPEGStream *str;
1107   GstCaps *caps;
1108
1109   g_return_if_fail (stream_nr >= -1 &&
1110       stream_nr < GST_MPEG_DEMUX_NUM_AUDIO_STREAMS);
1111
1112   GST_DEBUG_OBJECT (dvd_demux, "changing current audio to %02d", stream_nr);
1113
1114   dvd_demux->cur_audio_nr = stream_nr;
1115
1116   if (stream_nr == -1) {
1117     return;
1118   }
1119
1120   str = mpeg_demux->audio_stream[stream_nr];
1121   if (str != NULL) {
1122     /* (Re)set the caps in the "current" pad. */
1123     caps = GST_PAD_CAPS (str->pad);
1124     if (caps != NULL) {
1125       gst_pad_set_caps (dvd_demux->cur_audio, caps);
1126     }
1127   }
1128 }
1129
1130 static void
1131 gst_dvd_demux_set_cur_subpicture (GstDVDDemux * dvd_demux, gint stream_nr)
1132 {
1133   GstMPEGStream *str;
1134
1135   g_return_if_fail (stream_nr >= -1 &&
1136       stream_nr < GST_DVD_DEMUX_NUM_SUBPICTURE_STREAMS);
1137
1138   GST_DEBUG_OBJECT (dvd_demux, "changing current subpicture to %02d",
1139       stream_nr);
1140
1141   dvd_demux->cur_subpicture_nr = stream_nr;
1142
1143   if (stream_nr == -1) {
1144     return;
1145   }
1146
1147   str = dvd_demux->subpicture_stream[stream_nr];
1148   if (str != NULL) {
1149     GstCaps *caps = NULL;
1150
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);
1154   }
1155 }
1156
1157 static void
1158 gst_dvd_demux_reset (GstDVDDemux * dvd_demux)
1159 {
1160   int i;
1161
1162   GstMPEGDemux *mpeg_demux = GST_MPEG_DEMUX (dvd_demux);
1163
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 ());
1169
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;
1178     }
1179   }
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);
1183
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;
1188
1189   /* Reset max_gap handling */
1190   mpeg_demux->max_gap = MAX_GAP;
1191   mpeg_demux->max_gap_tolerance = MAX_GAP_TOLERANCE;
1192 }
1193
1194 static void
1195 gst_dvd_demux_synchronise_pads (GstMPEGDemux * mpeg_demux,
1196     GstClockTime threshold, GstClockTime new_ts)
1197 {
1198   GstDVDDemux *dvd_demux = GST_DVD_DEMUX (mpeg_demux);
1199   int i;
1200
1201   parent_class->synchronise_pads (mpeg_demux, threshold, new_ts);
1202
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;
1213       }
1214     }
1215   }
1216 }
1217
1218 static void
1219 gst_dvd_demux_sync_stream_to_time (GstMPEGDemux * mpeg_demux,
1220     GstMPEGStream * stream, GstClockTime last_ts)
1221 {
1222   GstDVDDemux *dvd_demux = GST_DVD_DEMUX (mpeg_demux);
1223   GstMPEGParse *mpeg_parse = GST_MPEG_PARSE (mpeg_demux);
1224   GstPad *outpad;
1225   gint cur_nr;
1226
1227   parent_class->sync_stream_to_time (mpeg_demux, stream, last_ts);
1228
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;
1233       break;
1234     case GST_MPEG_DEMUX_STREAM_AUDIO:
1235       outpad = dvd_demux->cur_audio;
1236       cur_nr = dvd_demux->cur_audio_nr;
1237       break;
1238     case GST_DVD_DEMUX_STREAM_SUBPICTURE:
1239       outpad = dvd_demux->cur_subpicture;
1240       cur_nr = dvd_demux->cur_subpicture_nr;
1241       break;
1242     default:
1243       return;
1244   }
1245
1246   if (outpad && (cur_nr == stream->number)) {
1247     guint64 update_time;
1248
1249     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));
1254   }
1255 }
1256
1257 static GstStateChangeReturn
1258 gst_dvd_demux_change_state (GstElement * element, GstStateChange transition)
1259 {
1260   GstDVDDemux *dvd_demux = GST_DVD_DEMUX (element);
1261   GstStateChangeReturn ret;
1262
1263   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1264
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;
1271       }
1272       break;
1273     default:
1274       break;
1275   }
1276   return ret;
1277 }
1278
1279 gboolean
1280 gst_dvd_demux_plugin_init (GstPlugin * plugin)
1281 {
1282   return gst_element_register (plugin, "dvddemux",
1283       GST_RANK_SECONDARY + 1, GST_TYPE_DVD_DEMUX);
1284 }