mpegpsdemux: don't scan for the last PTS if the first wasn't found
[platform/upstream/gstreamer.git] / gst / mpegdemux / gstmpegdemux.c
1  /*
2   * This library is licensed under 2 different licenses and you
3   * can choose to use it under the terms of either one of them. The
4   * two licenses are the MPL 1.1 and the LGPL.
5   *
6   * MPL:
7   *
8   * The contents of this file are subject to the Mozilla Public License
9   * Version 1.1 (the "License"); you may not use this file except in
10   * compliance with the License. You may obtain a copy of the License at
11   * http://www.mozilla.org/MPL/.
12   *
13   * Software distributed under the License is distributed on an "AS IS"
14   * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
15   * License for the specific language governing rights and limitations
16   * under the License.
17   *
18   * LGPL:
19   *
20   * This library is free software; you can redistribute it and/or
21   * modify it under the terms of the GNU Library General Public
22   * License as published by the Free Software Foundation; either
23   * version 2 of the License, or (at your option) any later version.
24   *
25   * This library is distributed in the hope that it will be useful,
26   * but WITHOUT ANY WARRANTY; without even the implied warranty of
27   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
28   * Library General Public License for more details.
29   *
30   * You should have received a copy of the GNU Library General Public
31   * License along with this library; if not, write to the
32   * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
33   * Boston, MA 02111-1307, USA.
34   *
35   * The Original Code is Fluendo MPEG Demuxer plugin.
36   *
37   * The Initial Developer of the Original Code is Fluendo, S.L.
38   * Portions created by Fluendo, S.L. are Copyright (C) 2005
39   * Fluendo, S.L. All Rights Reserved.
40   *
41   * Contributor(s): Wim Taymans <wim@fluendo.com>
42   *                 Jan Schmidt <thaytan@noraisin.net>
43   */
44
45 #ifdef HAVE_CONFIG_H
46 #include "config.h"
47 #endif
48
49 #include <string.h>
50
51 #include "gstmpegdefs.h"
52 #include "gstmpegdemux.h"
53
54 #define MAX_DVD_AUDIO_STREAMS       8
55 #define MAX_DVD_SUBPICTURE_STREAMS  32
56 #define BLOCK_SZ                    32768
57 #define SCAN_SCR_SZ                 12
58 #define SCAN_PTS_SZ                 80
59
60 #define SEGMENT_THRESHOLD (300*GST_MSECOND)
61 #define VIDEO_SEGMENT_THRESHOLD (500*GST_MSECOND)
62
63 typedef enum
64 {
65   SCAN_SCR,
66   SCAN_DTS,
67   SCAN_PTS
68 } SCAN_MODE;
69
70 /* We clamp scr delta with 0 so negative bytes won't be possible */
71 #define GSTTIME_TO_BYTES(time) \
72   ((time != -1) ? gst_util_uint64_scale (MAX(0,(gint64) (GSTTIME_TO_MPEGTIME(time))), demux->scr_rate_n, demux->scr_rate_d) : -1)
73 #define BYTES_TO_GSTTIME(bytes) ((bytes != -1) ? MPEGTIME_TO_GSTTIME(gst_util_uint64_scale (bytes, demux->scr_rate_d, demux->scr_rate_n)) : -1)
74
75 #define ADAPTER_OFFSET_FLUSH(_bytes_) demux->adapter_offset += (_bytes_)
76
77 GST_DEBUG_CATEGORY_STATIC (gstflupsdemux_debug);
78 #define GST_CAT_DEFAULT (gstflupsdemux_debug)
79
80 /* MPEG2Demux signals and args */
81 enum
82 {
83   /* FILL ME */
84   LAST_SIGNAL
85 };
86
87 enum
88 {
89   ARG_0,
90   ARG_SYNC,
91   /* FILL ME */
92 };
93
94 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
95     GST_PAD_SINK,
96     GST_PAD_ALWAYS,
97     GST_STATIC_CAPS ("video/mpeg, "
98         "mpegversion = (int) { 1, 2 }, "
99         "systemstream = (boolean) TRUE;" "video/x-cdxa")
100     );
101
102 static GstStaticPadTemplate video_template =
103     GST_STATIC_PAD_TEMPLATE ("video_%02x",
104     GST_PAD_SRC,
105     GST_PAD_SOMETIMES,
106     GST_STATIC_CAPS ("video/mpeg, "
107         "mpegversion = (int) { 1, 2, 4 }, " "systemstream = (boolean) FALSE;"
108         "video/x-h264")
109     );
110
111 static GstStaticPadTemplate audio_template =
112     GST_STATIC_PAD_TEMPLATE ("audio_%02x",
113     GST_PAD_SRC,
114     GST_PAD_SOMETIMES,
115     GST_STATIC_CAPS ("audio/mpeg, "
116         "mpegversion = (int) { 1, 4 };"
117         "audio/x-private1-lpcm; "
118         "audio/x-private1-ac3;" "audio/x-private1-dts;" "audio/ac3")
119     );
120
121 static GstStaticPadTemplate subpicture_template =
122 GST_STATIC_PAD_TEMPLATE ("subpicture_%02x",
123     GST_PAD_SRC,
124     GST_PAD_SOMETIMES,
125     GST_STATIC_CAPS ("video/x-dvd-subpicture")
126     );
127
128 static GstStaticPadTemplate private_template =
129 GST_STATIC_PAD_TEMPLATE ("private_%d",
130     GST_PAD_SRC,
131     GST_PAD_SOMETIMES,
132     GST_STATIC_CAPS_ANY);
133
134 static void gst_flups_demux_base_init (GstFluPSDemuxClass * klass);
135 static void gst_flups_demux_class_init (GstFluPSDemuxClass * klass);
136 static void gst_flups_demux_init (GstFluPSDemux * demux);
137 static void gst_flups_demux_finalize (GstFluPSDemux * demux);
138 static void gst_flups_demux_reset (GstFluPSDemux * demux);
139
140 static gboolean gst_flups_demux_sink_event (GstPad * pad, GstEvent * event);
141 static GstFlowReturn gst_flups_demux_chain (GstPad * pad, GstBuffer * buffer);
142 static gboolean gst_flups_demux_sink_activate (GstPad * sinkpad);
143 static gboolean gst_flups_demux_sink_activate_push (GstPad * sinkpad,
144     gboolean active);
145 static gboolean gst_flups_demux_sink_activate_pull (GstPad * sinkpad,
146     gboolean active);
147 static void gst_flups_demux_loop (GstPad * pad);
148
149 static gboolean gst_flups_demux_src_event (GstPad * pad, GstEvent * event);
150 static gboolean gst_flups_demux_src_query (GstPad * pad, GstQuery * query);
151 static const GstQueryType *gst_flups_demux_src_query_type (GstPad * pad);
152
153 static GstStateChangeReturn gst_flups_demux_change_state (GstElement * element,
154     GstStateChange transition);
155
156 static inline gboolean gst_flups_demux_scan_forward_ts (GstFluPSDemux * demux,
157     guint64 * pos, SCAN_MODE mode, guint64 * rts);
158 static inline gboolean gst_flups_demux_scan_backward_ts (GstFluPSDemux * demux,
159     guint64 * pos, SCAN_MODE mode, guint64 * rts);
160
161 static inline void gst_flups_demux_send_segment_updates (GstFluPSDemux * demux,
162     GstClockTime new_time);
163 static inline void gst_flups_demux_clear_times (GstFluPSDemux * demux);
164
165 static GstElementClass *parent_class = NULL;
166
167 /*static guint gst_flups_demux_signals[LAST_SIGNAL] = { 0 };*/
168
169 GType
170 gst_flups_demux_get_type (void)
171 {
172   static GType flups_demux_type = 0;
173
174   if (!flups_demux_type) {
175     static const GTypeInfo flups_demux_info = {
176       sizeof (GstFluPSDemuxClass),
177       (GBaseInitFunc) gst_flups_demux_base_init,
178       NULL,
179       (GClassInitFunc) gst_flups_demux_class_init,
180       NULL,
181       NULL,
182       sizeof (GstFluPSDemux),
183       0,
184       (GInstanceInitFunc) gst_flups_demux_init,
185     };
186
187     flups_demux_type =
188         g_type_register_static (GST_TYPE_ELEMENT, "GstMpegPSDemux",
189         &flups_demux_info, 0);
190
191     GST_DEBUG_CATEGORY_INIT (gstflupsdemux_debug, "mpegpsdemux", 0,
192         "MPEG program stream demultiplexer element");
193   }
194
195   return flups_demux_type;
196 }
197
198 static void
199 gst_flups_demux_base_init (GstFluPSDemuxClass * klass)
200 {
201   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
202
203   klass->sink_template = gst_static_pad_template_get (&sink_template);
204   klass->video_template = gst_static_pad_template_get (&video_template);
205   klass->audio_template = gst_static_pad_template_get (&audio_template);
206   klass->subpicture_template =
207       gst_static_pad_template_get (&subpicture_template);
208   klass->private_template = gst_static_pad_template_get (&private_template);
209
210   gst_element_class_add_pad_template (element_class, klass->video_template);
211   gst_element_class_add_pad_template (element_class, klass->audio_template);
212   gst_element_class_add_pad_template (element_class,
213       klass->subpicture_template);
214   gst_element_class_add_pad_template (element_class, klass->private_template);
215   gst_element_class_add_pad_template (element_class, klass->sink_template);
216
217   gst_element_class_set_details_simple (element_class,
218       "The Fluendo MPEG Program Stream Demuxer", "Codec/Demuxer",
219       "Demultiplexes MPEG Program Streams", "Wim Taymans <wim@fluendo.com>");
220 }
221
222 static void
223 gst_flups_demux_class_init (GstFluPSDemuxClass * klass)
224 {
225   GObjectClass *gobject_class;
226   GstElementClass *gstelement_class;
227
228   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
229
230   gobject_class = (GObjectClass *) klass;
231   gstelement_class = (GstElementClass *) klass;
232
233   gobject_class->finalize = (GObjectFinalizeFunc) gst_flups_demux_finalize;
234
235   gstelement_class->change_state = gst_flups_demux_change_state;
236 }
237
238 static void
239 gst_flups_demux_init (GstFluPSDemux * demux)
240 {
241   GstFluPSDemuxClass *klass = GST_FLUPS_DEMUX_GET_CLASS (demux);
242
243   demux->sinkpad = gst_pad_new_from_template (klass->sink_template, "sink");
244   gst_pad_set_event_function (demux->sinkpad,
245       GST_DEBUG_FUNCPTR (gst_flups_demux_sink_event));
246   gst_pad_set_chain_function (demux->sinkpad,
247       GST_DEBUG_FUNCPTR (gst_flups_demux_chain));
248   gst_pad_set_activate_function (demux->sinkpad,
249       GST_DEBUG_FUNCPTR (gst_flups_demux_sink_activate));
250   gst_pad_set_activatepull_function (demux->sinkpad,
251       GST_DEBUG_FUNCPTR (gst_flups_demux_sink_activate_pull));
252   gst_pad_set_activatepush_function (demux->sinkpad,
253       GST_DEBUG_FUNCPTR (gst_flups_demux_sink_activate_push));
254
255   gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
256
257   demux->streams =
258       g_malloc0 (sizeof (GstFluPSStream *) * (GST_FLUPS_DEMUX_MAX_STREAMS));
259   demux->streams_found =
260       g_malloc0 (sizeof (GstFluPSStream *) * (GST_FLUPS_DEMUX_MAX_STREAMS));
261   demux->found_count = 0;
262
263 }
264
265 static void
266 gst_flups_demux_finalize (GstFluPSDemux * demux)
267 {
268   gst_flups_demux_reset (demux);
269   g_free (demux->streams);
270   g_free (demux->streams_found);
271
272   G_OBJECT_CLASS (parent_class)->finalize (G_OBJECT (demux));
273 }
274
275 static void
276 gst_flups_demux_reset (GstFluPSDemux * demux)
277 {
278   /* Clean up the streams and pads we allocated */
279   gint i;
280   GstEvent **p_ev;
281
282   for (i = 0; i < GST_FLUPS_DEMUX_MAX_STREAMS; i++) {
283     GstFluPSStream *stream = demux->streams[i];
284
285     if (stream != NULL) {
286       if (stream->pad)
287         gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
288
289       g_free (stream);
290       demux->streams[i] = NULL;
291     }
292   }
293   memset (demux->streams_found, 0,
294       sizeof (GstFluPSStream *) * (GST_FLUPS_DEMUX_MAX_STREAMS));
295   demux->found_count = 0;
296   p_ev = &demux->lang_codes;
297
298   gst_event_replace (p_ev, NULL);
299 }
300
301 static GstFluPSStream *
302 gst_flups_demux_create_stream (GstFluPSDemux * demux, gint id, gint stream_type)
303 {
304   GstFluPSStream *stream;
305   GstPadTemplate *template;
306   gchar *name;
307   GstFluPSDemuxClass *klass = GST_FLUPS_DEMUX_GET_CLASS (demux);
308   GstCaps *caps;
309   GstClockTime threshold = SEGMENT_THRESHOLD;
310
311   name = NULL;
312   template = NULL;
313   caps = NULL;
314
315   GST_DEBUG_OBJECT (demux, "create stream id 0x%02x, type 0x%02x", id,
316       stream_type);
317
318   switch (stream_type) {
319     case ST_VIDEO_MPEG1:
320     case ST_VIDEO_MPEG2:
321     case ST_VIDEO_MPEG4:
322     case ST_GST_VIDEO_MPEG1_OR_2:
323     {
324       gint mpeg_version = 1;
325       if (stream_type == ST_VIDEO_MPEG2 ||
326           (stream_type == ST_GST_VIDEO_MPEG1_OR_2 && demux->is_mpeg2_pack)) {
327         mpeg_version = 2;
328       }
329       if (stream_type == ST_VIDEO_MPEG4) {
330         mpeg_version = 4;
331       }
332
333       template = klass->video_template;
334       name = g_strdup_printf ("video_%02x", id);
335       caps = gst_caps_new_simple ("video/mpeg",
336           "mpegversion", G_TYPE_INT, mpeg_version,
337           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
338       threshold = VIDEO_SEGMENT_THRESHOLD;
339       break;
340     }
341     case ST_AUDIO_MPEG1:
342     case ST_AUDIO_MPEG2:
343       template = klass->audio_template;
344       name = g_strdup_printf ("audio_%02x", id);
345       caps = gst_caps_new_simple ("audio/mpeg",
346           "mpegversion", G_TYPE_INT, 1, NULL);
347       break;
348     case ST_PRIVATE_SECTIONS:
349     case ST_PRIVATE_DATA:
350     case ST_MHEG:
351     case ST_DSMCC:
352       break;
353     case ST_AUDIO_AAC_ADTS:
354       template = klass->audio_template;
355       name = g_strdup_printf ("audio_%02x", id);
356       caps = gst_caps_new_simple ("audio/mpeg",
357           "mpegversion", G_TYPE_INT, 4,
358           "stream-format", G_TYPE_STRING, "adts", NULL);
359       break;
360     case ST_AUDIO_AAC_LOAS:    // LATM/LOAS AAC syntax
361       template = klass->audio_template;
362       name = g_strdup_printf ("audio_%02x", id);
363       caps = gst_caps_new_simple ("audio/mpeg",
364           "mpegversion", G_TYPE_INT, 4,
365           "stream-format", G_TYPE_STRING, "loas", NULL);
366       break;
367     case ST_VIDEO_H264:
368       template = klass->video_template;
369       name = g_strdup_printf ("video_%02x", id);
370       caps = gst_caps_new_simple ("video/x-h264", NULL);
371       threshold = VIDEO_SEGMENT_THRESHOLD;
372       break;
373     case ST_PS_AUDIO_AC3:
374       template = klass->audio_template;
375       name = g_strdup_printf ("audio_%02x", id);
376       caps = gst_caps_new_simple ("audio/x-private1-ac3", NULL);
377       break;
378     case ST_PS_AUDIO_DTS:
379       template = klass->audio_template;
380       name = g_strdup_printf ("audio_%02x", id);
381       caps = gst_caps_new_simple ("audio/x-private1-dts", NULL);
382       break;
383     case ST_PS_AUDIO_LPCM:
384       template = klass->audio_template;
385       name = g_strdup_printf ("audio_%02x", id);
386       caps = gst_caps_new_simple ("audio/x-private1-lpcm", NULL);
387       break;
388     case ST_PS_DVD_SUBPICTURE:
389       template = klass->subpicture_template;
390       name = g_strdup_printf ("subpicture_%02x", id);
391       caps = gst_caps_new_simple ("video/x-dvd-subpicture", NULL);
392       break;
393     case ST_GST_AUDIO_RAWA52:
394       template = klass->audio_template;
395       name = g_strdup_printf ("audio_%02x", id);
396       caps = gst_caps_new_simple ("audio/ac3", NULL);
397       break;
398     default:
399       break;
400   }
401
402   if (name == NULL || template == NULL || caps == NULL) {
403     if (name)
404       g_free (name);
405     if (caps)
406       gst_caps_unref (caps);
407     return FALSE;
408   }
409
410   stream = g_new0 (GstFluPSStream, 1);
411   stream->id = id;
412   stream->discont = TRUE;
413   stream->need_segment = TRUE;
414   stream->notlinked = FALSE;
415   stream->type = stream_type;
416   stream->pad = gst_pad_new_from_template (template, name);
417   stream->segment_thresh = threshold;
418   gst_pad_set_event_function (stream->pad,
419       GST_DEBUG_FUNCPTR (gst_flups_demux_src_event));
420   gst_pad_set_query_function (stream->pad,
421       GST_DEBUG_FUNCPTR (gst_flups_demux_src_query));
422   gst_pad_set_query_type_function (stream->pad,
423       GST_DEBUG_FUNCPTR (gst_flups_demux_src_query_type));
424   gst_pad_use_fixed_caps (stream->pad);
425   gst_pad_set_caps (stream->pad, caps);
426   gst_caps_unref (caps);
427   GST_DEBUG_OBJECT (demux, "create pad %s, caps %" GST_PTR_FORMAT, name, caps);
428   g_free (name);
429
430
431   return stream;
432 }
433
434 static GstFluPSStream *
435 gst_flups_demux_get_stream (GstFluPSDemux * demux, gint id, gint type)
436 {
437   GstFluPSStream *stream = demux->streams[id];
438
439   if (stream == NULL) {
440     if (!(stream = gst_flups_demux_create_stream (demux, id, type)))
441       goto unknown_stream;
442
443     GST_DEBUG_OBJECT (demux, "adding pad for stream id 0x%02x type 0x%02x", id,
444         type);
445
446     gst_pad_set_active (stream->pad, TRUE);
447     gst_element_add_pad (GST_ELEMENT (demux), stream->pad);
448
449     demux->streams[id] = stream;
450     demux->streams_found[demux->found_count++] = stream;
451   }
452   return stream;
453
454   /* ERROR */
455 unknown_stream:
456   {
457     GST_DEBUG_OBJECT (demux, "unknown stream id 0x%02x type 0x%02x", id, type);
458     return NULL;
459   }
460 }
461
462 static GstFlowReturn
463 gst_flups_demux_send_data (GstFluPSDemux * demux, GstFluPSStream * stream,
464     GstBuffer * buf)
465 {
466   GstFlowReturn result;
467   guint64 timestamp;
468   guint size;
469
470   if (stream == NULL)
471     goto no_stream;
472
473   /* timestamps */
474   if (G_UNLIKELY (demux->next_pts != G_MAXUINT64))
475     timestamp = MPEGTIME_TO_GSTTIME (demux->next_pts);
476   else
477     timestamp = GST_CLOCK_TIME_NONE;
478
479   /* discont */
480   if (G_UNLIKELY (stream->need_segment)) {
481     gint64 time, start, stop;
482     GstEvent *newsegment;
483
484     GST_DEBUG ("timestamp:%" GST_TIME_FORMAT " base_time %" GST_TIME_FORMAT
485         " src_segment.start:%" GST_TIME_FORMAT " .stop:%" GST_TIME_FORMAT,
486         GST_TIME_ARGS (timestamp), GST_TIME_ARGS (demux->base_time),
487         GST_TIME_ARGS (demux->src_segment.start),
488         GST_TIME_ARGS (demux->src_segment.stop));
489
490     if (GST_CLOCK_TIME_IS_VALID (demux->base_time) &&
491         GST_CLOCK_TIME_IS_VALID (demux->src_segment.start))
492       start = demux->base_time + demux->src_segment.start;
493     else
494       start = 0;
495
496     if (GST_CLOCK_TIME_IS_VALID (demux->src_segment.stop) &&
497         GST_CLOCK_TIME_IS_VALID (demux->base_time))
498       stop = demux->base_time + demux->src_segment.stop;
499     else
500       stop = -1;
501
502     if (timestamp != GST_CLOCK_TIME_NONE) {
503       if (demux->src_segment.rate > 0) {
504         if (GST_CLOCK_DIFF (start, timestamp) > GST_SECOND)
505           start = timestamp;
506       } else {
507         if (GST_CLOCK_DIFF (stop, timestamp) > GST_SECOND)
508           stop = timestamp;
509       }
510     }
511     if (GST_CLOCK_TIME_IS_VALID (demux->base_time) && start > demux->base_time)
512       time = start - demux->base_time;
513     else
514       time = 0;
515
516     GST_INFO_OBJECT (demux, "sending new segment: rate %g applied_rate %g "
517         "start: %" GST_TIME_FORMAT ", stop: %" GST_TIME_FORMAT
518         ", time: %" GST_TIME_FORMAT " to pad %" GST_PTR_FORMAT,
519         demux->sink_segment.rate, demux->sink_segment.applied_rate,
520         GST_TIME_ARGS (start), GST_TIME_ARGS (stop),
521         GST_TIME_ARGS (time), stream->pad);
522
523     newsegment = gst_event_new_new_segment_full (FALSE,
524         demux->sink_segment.rate, demux->sink_segment.applied_rate,
525         GST_FORMAT_TIME, start, stop, time);
526
527     gst_pad_push_event (stream->pad, newsegment);
528
529     stream->need_segment = FALSE;
530   }
531
532   /* OK, sent new segment now prepare the buffer for sending */
533   /* caps */
534   gst_buffer_set_caps (buf, GST_PAD_CAPS (stream->pad));
535   GST_BUFFER_TIMESTAMP (buf) = timestamp;
536
537   /* update position in the segment */
538   gst_segment_set_last_stop (&demux->src_segment, GST_FORMAT_TIME,
539       MPEGTIME_TO_GSTTIME (demux->current_scr - demux->first_scr));
540   GST_LOG_OBJECT (demux, "last stop position is now %" GST_TIME_FORMAT
541       " current scr is %" GST_TIME_FORMAT,
542       GST_TIME_ARGS (demux->src_segment.last_stop),
543       GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->current_scr)));
544
545   if (demux->src_segment.last_stop != GST_CLOCK_TIME_NONE) {
546     GstClockTime new_time = demux->base_time + demux->src_segment.last_stop;
547
548     if (stream->last_ts == GST_CLOCK_TIME_NONE || stream->last_ts < new_time) {
549 #if 0
550       g_print ("last_ts update on pad %s to time %" GST_TIME_FORMAT "\n",
551           GST_PAD_NAME (stream->pad), GST_TIME_ARGS (cur_scr_time));
552 #endif
553       stream->last_ts = new_time;
554     }
555
556     gst_flups_demux_send_segment_updates (demux, new_time);
557   }
558
559   /* Set the buffer discont flag, and clear discont state on the stream */
560   if (stream->discont) {
561     GST_DEBUG_OBJECT (demux, "marking discont buffer");
562     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
563
564     stream->discont = FALSE;
565   }
566   size = GST_BUFFER_SIZE (buf);
567
568   demux->next_pts = G_MAXUINT64;
569   demux->next_dts = G_MAXUINT64;
570
571   result = gst_pad_push (stream->pad, buf);
572   GST_DEBUG_OBJECT (demux, "pushed stream id 0x%02x type 0x%02x, time: %"
573       GST_TIME_FORMAT ", size %d. result: %s",
574       stream->id, stream->type, GST_TIME_ARGS (timestamp),
575       size, gst_flow_get_name (result));
576
577   return result;
578
579   /* ERROR */
580 no_stream:
581   {
582     GST_DEBUG_OBJECT (demux, "no stream given");
583     gst_buffer_unref (buf);
584     return GST_FLOW_OK;
585   }
586 }
587
588 static inline void
589 gst_flups_demux_mark_discont (GstFluPSDemux * demux, gboolean discont,
590     gboolean need_segment)
591 {
592   gint i, count = demux->found_count;
593
594   /* mark discont on all streams */
595   for (i = 0; i < count; i++) {
596     GstFluPSStream *stream = demux->streams_found[i];
597
598     if (G_LIKELY (stream)) {
599       stream->discont |= discont;
600       stream->need_segment |= need_segment;
601       GST_DEBUG_OBJECT (demux, "marked stream as discont %d, need_segment %d",
602           stream->discont, stream->need_segment);
603     }
604   }
605 }
606
607 static inline gboolean
608 gst_flups_demux_send_event (GstFluPSDemux * demux, GstEvent * event)
609 {
610   gint i, count = demux->found_count;
611   gboolean ret = FALSE;
612
613   for (i = 0; i < count; i++) {
614     GstFluPSStream *stream = demux->streams_found[i];
615
616     if (stream && !stream->notlinked) {
617       (void) gst_event_ref (event);
618
619       if (!gst_pad_push_event (stream->pad, event)) {
620         GST_DEBUG_OBJECT (stream, "event %s was not handled correctly",
621             GST_EVENT_TYPE_NAME (event));
622       } else {
623         /* If at least one push returns TRUE, then we return TRUE. */
624         GST_DEBUG_OBJECT (stream, "event %s was handled correctly",
625             GST_EVENT_TYPE_NAME (event));
626         ret = TRUE;
627       }
628     }
629   }
630
631   gst_event_unref (event);
632   return ret;
633 }
634
635 static gboolean
636 gst_flups_demux_handle_dvd_event (GstFluPSDemux * demux, GstEvent * event)
637 {
638   const GstStructure *structure = gst_event_get_structure (event);
639   const char *type = gst_structure_get_string (structure, "event");
640   gint i;
641   gchar cur_stream_name[32];
642   GstFluPSStream *temp G_GNUC_UNUSED;
643
644   if (strcmp (type, "dvd-lang-codes") == 0) {
645     GstEvent **p_ev;
646     /* Store the language codes event on the element, then iterate over the 
647      * streams it specifies and retrieve them. The stream creation code then 
648      * creates the pad appropriately and sends tag events as needed */
649     p_ev = &demux->lang_codes, event;
650     gst_event_replace (p_ev, event);
651
652     GST_DEBUG_OBJECT (demux, "Handling language codes event");
653
654     /* Create a video pad to ensure have it before emit no more pads */
655     (void) gst_flups_demux_get_stream (demux, 0xe0, ST_VIDEO_MPEG2);
656
657     /* Read out the languages for audio streams and request each one that 
658      * is present */
659     for (i = 0; i < MAX_DVD_AUDIO_STREAMS; i++) {
660       gint stream_format;
661       gint stream_id;
662
663       g_snprintf (cur_stream_name, 32, "audio-%d-format", i);
664       if (!gst_structure_get_int (structure, cur_stream_name, &stream_format))
665         break;
666
667       switch (stream_format) {
668         case 0x0:
669           /* AC3 */
670           stream_id = 0x80 + i;
671           temp = gst_flups_demux_get_stream (demux, stream_id, ST_PS_AUDIO_AC3);
672           break;
673         case 0x2:
674         case 0x3:
675           /* MPEG audio without and with extension stream are
676            * treated the same */
677           stream_id = 0xC0 + i;
678           temp = gst_flups_demux_get_stream (demux, stream_id, ST_AUDIO_MPEG1);
679           break;
680         case 0x4:
681           /* LPCM */
682           stream_id = 0xA0 + i;
683           temp =
684               gst_flups_demux_get_stream (demux, stream_id, ST_PS_AUDIO_LPCM);
685           break;
686         case 0x6:
687           /* DTS */
688           stream_id = 0x88 + i;
689           temp = gst_flups_demux_get_stream (demux, stream_id, ST_PS_AUDIO_DTS);
690           break;
691         case 0x7:
692           /* FIXME: What range is SDDS? */
693           break;
694         default:
695           GST_WARNING_OBJECT (demux,
696               "Unknown audio stream format in language code event: %d",
697               stream_format);
698           break;
699       }
700     }
701
702     /* And subtitle streams */
703     for (i = 0; i < MAX_DVD_SUBPICTURE_STREAMS; i++) {
704       g_snprintf (cur_stream_name, 32, "subpicture-%d-format", i);
705
706       if (gst_structure_get_string (structure, cur_stream_name) == NULL)
707         break;
708
709       /* Retrieve the subpicture stream to force pad creation */
710       temp = gst_flups_demux_get_stream (demux, 0x20 + i, ST_PS_DVD_SUBPICTURE);
711     }
712
713     GST_DEBUG_OBJECT (demux, "Created all pads from Language Codes event, "
714         "signalling no-more-pads");
715
716     gst_element_no_more_pads (GST_ELEMENT (demux));
717     demux->need_no_more_pads = FALSE;
718   }
719
720   gst_event_unref (event);
721   return TRUE;
722 }
723
724 static void
725 gst_flups_demux_flush (GstFluPSDemux * demux)
726 {
727   GST_DEBUG_OBJECT (demux, "flushing demuxer");
728   gst_adapter_clear (demux->adapter);
729   gst_adapter_clear (demux->rev_adapter);
730   gst_pes_filter_drain (&demux->filter);
731   gst_flups_demux_clear_times (demux);
732   demux->adapter_offset = G_MAXUINT64;
733   demux->current_scr = G_MAXUINT64;
734   demux->bytes_since_scr = 0;
735 }
736
737 static inline void
738 gst_flups_demux_clear_times (GstFluPSDemux * demux)
739 {
740   gint i, count = demux->found_count;
741
742   /* Clear the last ts for all streams */
743   for (i = 0; i < count; i++) {
744     GstFluPSStream *stream = demux->streams_found[i];
745
746     if (G_LIKELY (stream)) {
747       stream->last_seg_start = stream->last_ts = GST_CLOCK_TIME_NONE;
748     }
749   }
750 }
751
752 static inline void
753 gst_flups_demux_send_segment_updates (GstFluPSDemux * demux,
754     GstClockTime new_start)
755 {
756   GstClockTime base_time, stop, time;
757   gint i, count = demux->found_count;
758   GstEvent *event = NULL;
759
760   /* Advance all lagging streams by sending a segment update */
761   if ((base_time = demux->base_time) == GST_CLOCK_TIME_NONE)
762     base_time = 0;
763
764   stop = demux->src_segment.stop;
765   if (stop != GST_CLOCK_TIME_NONE)
766     stop += base_time;
767
768   if (new_start > stop)
769     return;
770
771   time = demux->src_segment.time;
772   time += new_start - (demux->src_segment.start + base_time);
773
774   /* FIXME: Handle reverse playback */
775   for (i = 0; i < count; i++) {
776     GstFluPSStream *stream = demux->streams_found[i];
777
778     if (stream) {
779       if (stream->last_ts == GST_CLOCK_TIME_NONE ||
780           stream->last_ts < demux->src_segment.start + base_time)
781         stream->last_ts = demux->src_segment.start + base_time;
782
783       if (stream->last_ts + stream->segment_thresh < new_start) {
784 #if 0
785         g_print ("Segment update to pad %s time %" GST_TIME_FORMAT " stop now %"
786             GST_TIME_FORMAT "\n", GST_PAD_NAME (stream->pad),
787             GST_TIME_ARGS (new_start), GST_TIME_ARGS (demux->src_segment.stop));
788 #endif
789         GST_DEBUG_OBJECT (demux,
790             "Segment update to pad %s time %" GST_TIME_FORMAT,
791             GST_PAD_NAME (stream->pad), GST_TIME_ARGS (new_start));
792         if (event == NULL) {
793           event = gst_event_new_new_segment_full (TRUE,
794               demux->src_segment.rate, demux->src_segment.applied_rate,
795               GST_FORMAT_TIME, new_start, stop, time);
796         }
797         gst_event_ref (event);
798         gst_pad_push_event (stream->pad, event);
799         stream->last_seg_start = stream->last_ts = new_start;
800         stream->need_segment = FALSE;
801       }
802     }
803   }
804
805   if (event)
806     gst_event_unref (event);
807 }
808
809 static inline void
810 gst_flups_demux_close_segment (GstFluPSDemux * demux)
811 {
812   gint i, count = demux->found_count;
813   GstEvent *event = NULL;
814   guint64 base_time;
815
816   GST_INFO_OBJECT (demux, "closing running segment %" GST_SEGMENT_FORMAT,
817       &demux->src_segment);
818
819   /* FIXME: Need to send a different segment-close to each pad where the
820    * last_seg_start != clock_time_none, as that indicates a sparse-stream
821    * event was sent there */
822
823   if ((base_time = demux->base_time) == (guint64) - 1)
824     base_time = 0;
825
826   /* Close the current segment for a linear playback */
827   if (demux->src_segment.rate >= 0) {
828     /* for forward playback, we played from start to last_stop */
829     event = gst_event_new_new_segment (TRUE,
830         demux->src_segment.rate, demux->src_segment.format,
831         demux->src_segment.start + base_time,
832         demux->src_segment.last_stop + base_time, demux->src_segment.time);
833   } else {
834     gint64 stop;
835
836     if ((stop = demux->src_segment.stop) == -1)
837       stop = demux->src_segment.duration;
838
839     /* for reverse playback, we played from stop to last_stop. */
840     event = gst_event_new_new_segment (TRUE,
841         demux->src_segment.rate, demux->src_segment.format,
842         demux->src_segment.last_stop + base_time,
843         stop + base_time, demux->src_segment.last_stop);
844   }
845
846   if (event) {
847     for (i = 0; i < count; i++) {
848       GstFluPSStream *stream = demux->streams_found[i];
849
850       if (stream && !stream->notlinked && !stream->need_segment) {
851         (void) gst_event_ref (event);
852
853         if (!gst_pad_push_event (stream->pad, event)) {
854           GST_DEBUG_OBJECT (stream, "event %s was not handled correctly",
855               GST_EVENT_TYPE_NAME (event));
856         } else {
857           /* If at least one push returns TRUE, then we return TRUE. */
858           GST_DEBUG_OBJECT (stream, "event %s was handled correctly",
859               GST_EVENT_TYPE_NAME (event));
860         }
861       }
862     }
863
864     gst_event_unref (event);
865   }
866 }
867
868 static inline gboolean
869 have_open_streams (GstFluPSDemux * demux)
870 {
871   return (demux->streams_found[0] != NULL);
872 }
873
874 static gboolean
875 gst_flups_demux_sink_event (GstPad * pad, GstEvent * event)
876 {
877   gboolean res = TRUE;
878   GstFluPSDemux *demux;
879
880   demux = GST_FLUPS_DEMUX (gst_pad_get_parent (pad));
881
882   switch (GST_EVENT_TYPE (event)) {
883     case GST_EVENT_FLUSH_START:
884       gst_flups_demux_send_event (demux, event);
885       break;
886     case GST_EVENT_FLUSH_STOP:
887       gst_flups_demux_send_event (demux, event);
888       gst_segment_init (&demux->sink_segment, GST_FORMAT_UNDEFINED);
889       gst_flups_demux_flush (demux);
890       break;
891     case GST_EVENT_NEWSEGMENT:
892     {
893       gboolean update;
894       gdouble rate;
895       GstFormat format;
896       gint64 start, stop, time;
897
898       /* Close current segment */
899       gst_flups_demux_close_segment (demux);
900
901       {
902         gdouble arate;
903
904         gst_event_parse_new_segment_full (event, &update, &rate, &arate,
905             &format, &start, &stop, &time);
906         gst_segment_set_newsegment_full (&demux->sink_segment, update, rate,
907             arate, format, start, stop, time);
908
909         if (format == GST_FORMAT_BYTES && demux->scr_rate_n != G_MAXUINT64
910             && demux->scr_rate_d != G_MAXUINT64) {
911
912           gst_segment_set_newsegment_full (&demux->src_segment, update, rate,
913               arate, GST_FORMAT_TIME, BYTES_TO_GSTTIME (start),
914               BYTES_TO_GSTTIME (stop), BYTES_TO_GSTTIME (time));
915         }
916
917       }
918
919       GST_INFO_OBJECT (demux, "received new segment: rate %g "
920           "format %d, start: %" G_GINT64_FORMAT ", stop: %" G_GINT64_FORMAT
921           ", time: %" G_GINT64_FORMAT, rate, format, start, stop, time);
922
923       /* we need to emit a new segment */
924       gst_flups_demux_mark_discont (demux, TRUE, TRUE);
925       gst_event_unref (event);
926
927       break;
928     }
929     case GST_EVENT_EOS:
930       GST_INFO_OBJECT (demux, "Received EOS");
931       if (!gst_flups_demux_send_event (demux, event)
932           && !have_open_streams (demux)) {
933         GST_WARNING_OBJECT (demux, "EOS and no streams open");
934         GST_ELEMENT_ERROR (demux, STREAM, FAILED,
935             ("Internal data stream error."), ("No valid streams detected"));
936       }
937       break;
938     case GST_EVENT_CUSTOM_DOWNSTREAM:
939     case GST_EVENT_CUSTOM_DOWNSTREAM_OOB:
940     {
941       const GstStructure *structure = gst_event_get_structure (event);
942
943       if (structure != NULL
944           && gst_structure_has_name (structure, "application/x-gst-dvd")) {
945         res = gst_flups_demux_handle_dvd_event (demux, event);
946       } else {
947         gst_flups_demux_send_event (demux, event);
948       }
949       break;
950     }
951     default:
952       gst_flups_demux_send_event (demux, event);
953       break;
954   }
955
956   gst_object_unref (demux);
957
958   return res;
959 }
960
961 static gboolean
962 gst_flups_demux_handle_seek_push (GstFluPSDemux * demux, GstEvent * event)
963 {
964   gboolean res = FALSE;
965   gdouble rate;
966   GstFormat format;
967   GstSeekFlags flags;
968   GstSeekType start_type, stop_type;
969   gint64 start, stop;
970   gint64 bstart, bstop;
971   GstEvent *bevent;
972
973   gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start,
974       &stop_type, &stop);
975
976   GST_DEBUG_OBJECT (demux, "seek event, rate: %f start: %" GST_TIME_FORMAT
977       " stop: %" GST_TIME_FORMAT, rate, GST_TIME_ARGS (start),
978       GST_TIME_ARGS (stop));
979
980   if (format == GST_FORMAT_BYTES) {
981     GST_DEBUG_OBJECT (demux, "seek not supported on format %d", format);
982     goto not_supported;
983   }
984
985   GST_DEBUG_OBJECT (demux, "seek - trying directly upstream first");
986
987   /* first try original format seek */
988   (void) gst_event_ref (event);
989   if ((res = gst_pad_push_event (demux->sinkpad, event)))
990     goto done;
991
992   if (format != GST_FORMAT_TIME) {
993     /* From here down, we only support time based seeks */
994     GST_DEBUG_OBJECT (demux, "seek not supported on format %d", format);
995     goto not_supported;
996   }
997
998   /* We need to convert to byte based seek and we need a scr_rate for that. */
999   if (demux->scr_rate_n == G_MAXUINT64 || demux->scr_rate_d == G_MAXUINT64) {
1000     GST_DEBUG_OBJECT (demux, "seek not possible, no scr_rate");
1001     goto not_supported;
1002   }
1003
1004   GST_DEBUG_OBJECT (demux, "try with scr_rate interpolation");
1005
1006   bstart = GSTTIME_TO_BYTES (start);
1007   bstop = GSTTIME_TO_BYTES (stop);
1008
1009   GST_DEBUG_OBJECT (demux, "in bytes bstart %" G_GINT64_FORMAT " bstop %"
1010       G_GINT64_FORMAT, bstart, bstop);
1011   bevent = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, start_type,
1012       bstart, stop_type, bstop);
1013
1014   res = gst_pad_push_event (demux->sinkpad, bevent);
1015
1016 done:
1017   gst_event_unref (event);
1018   return res;
1019
1020 not_supported:
1021   {
1022     gst_event_unref (event);
1023
1024     return FALSE;
1025   }
1026 }
1027
1028 static inline void
1029 gst_flups_demux_do_seek (GstFluPSDemux * demux, GstSegment * seeksegment)
1030 {
1031   gboolean found;
1032   guint64 fscr, offset;
1033   guint64 scr = GSTTIME_TO_MPEGTIME (seeksegment->last_stop + demux->base_time);
1034   guint64 scr_rate_n = demux->last_scr_offset - demux->first_scr_offset;
1035   guint64 scr_rate_d = demux->last_scr - demux->first_scr;
1036
1037   /* In some clips the PTS values are completely unaligned with SCR values.
1038    * To improve the seek in that situation we apply a factor considering the
1039    * relationship between last PTS and last SCR */
1040   if (demux->last_scr > demux->last_pts)
1041     scr = gst_util_uint64_scale (scr, demux->last_scr, demux->last_pts);
1042
1043   scr = MIN (demux->last_scr, scr);
1044   scr = MAX (demux->first_scr, scr);
1045   fscr = scr;
1046
1047   GST_INFO_OBJECT (demux, "sink segment configured %" GST_SEGMENT_FORMAT
1048       ", trying to go at SCR: %" G_GUINT64_FORMAT, &demux->sink_segment, scr);
1049
1050   offset =
1051       MIN (gst_util_uint64_scale (scr - demux->first_scr, scr_rate_n,
1052           scr_rate_d), demux->sink_segment.stop);
1053
1054   found = gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_SCR, &fscr);
1055   if (!found) {
1056     found = gst_flups_demux_scan_backward_ts (demux, &offset, SCAN_SCR, &fscr);
1057   }
1058
1059   while (found && fscr < scr) {
1060     offset++;
1061     found = gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_SCR, &fscr);
1062   }
1063
1064   while (found && fscr > scr && offset > 0) {
1065     offset--;
1066     found = gst_flups_demux_scan_backward_ts (demux, &offset, SCAN_SCR, &fscr);
1067   }
1068
1069   GST_INFO_OBJECT (demux, "doing seek at offset %" G_GUINT64_FORMAT
1070       " SCR: %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT,
1071       offset, fscr, GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (fscr)));
1072   gst_segment_set_last_stop (&demux->sink_segment, GST_FORMAT_BYTES, offset);
1073 }
1074
1075 static gboolean
1076 gst_flups_demux_handle_seek_pull (GstFluPSDemux * demux, GstEvent * event)
1077 {
1078   GstFormat format;
1079   GstSeekFlags flags;
1080   GstSeekType start_type, stop_type;
1081   gint64 start, stop;
1082   gdouble rate;
1083   gboolean update, flush;
1084   GstSegment seeksegment;
1085   GstClockTime first_pts = MPEGTIME_TO_GSTTIME (demux->first_pts);
1086
1087   gst_event_parse_seek (event, &rate, &format, &flags,
1088       &start_type, &start, &stop_type, &stop);
1089
1090   if (format != GST_FORMAT_TIME)
1091     goto wrong_format;
1092
1093   GST_DEBUG_OBJECT (demux, "Seek requested start %" GST_TIME_FORMAT " stop %"
1094       GST_TIME_FORMAT, GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
1095
1096   /* We need to convert to byte based seek and we need a scr_rate for that. */
1097   if (demux->scr_rate_n == G_MAXUINT64 || demux->scr_rate_d == G_MAXUINT64)
1098     goto no_scr_rate;
1099
1100   flush = flags & GST_SEEK_FLAG_FLUSH;
1101   /* keyframe = flags & GST_SEEK_FLAG_KEY_UNIT; *//* FIXME */
1102
1103   if (flush) {
1104     /* Flush start up and downstream to make sure data flow and loops are
1105        idle */
1106     demux->flushing = TRUE;
1107     gst_flups_demux_send_event (demux, gst_event_new_flush_start ());
1108     gst_pad_push_event (demux->sinkpad, gst_event_new_flush_start ());
1109   } else {
1110     /* Pause the pulling task */
1111     gst_pad_pause_task (demux->sinkpad);
1112   }
1113
1114   /* Take the stream lock */
1115   GST_PAD_STREAM_LOCK (demux->sinkpad);
1116
1117   if (flush) {
1118     /* Stop flushing upstream we need to pull */
1119     demux->flushing = FALSE;
1120     gst_pad_push_event (demux->sinkpad, gst_event_new_flush_stop ());
1121   }
1122
1123   /* Work on a copy until we are sure the seek succeeded. */
1124   memcpy (&seeksegment, &demux->src_segment, sizeof (GstSegment));
1125
1126   GST_DEBUG_OBJECT (demux, "segment before configure %" GST_SEGMENT_FORMAT,
1127       &demux->src_segment);
1128
1129   /* Apply the seek to our segment */
1130   gst_segment_set_seek (&seeksegment, rate, format, flags,
1131       start_type, start, stop_type, stop, &update);
1132
1133   GST_DEBUG_OBJECT (demux, "seek segment configured %" GST_SEGMENT_FORMAT,
1134       &seeksegment);
1135
1136   if (flush || seeksegment.last_stop != demux->src_segment.last_stop) {
1137     /* Do the actual seeking */
1138     gst_flups_demux_do_seek (demux, &seeksegment);
1139   }
1140
1141   /* check the limits */
1142   if (seeksegment.rate > 0.0) {
1143     if (seeksegment.start < first_pts - demux->base_time) {
1144       seeksegment.start = first_pts - demux->base_time;
1145       seeksegment.last_stop = seeksegment.start;
1146     }
1147   }
1148
1149   /* update the rate in our src segment */
1150   demux->sink_segment.rate = rate;
1151
1152   GST_DEBUG_OBJECT (demux, "seek segment adjusted %" GST_SEGMENT_FORMAT,
1153       &seeksegment);
1154
1155   if (flush) {
1156     /* Stop flushing, the sinks are at time 0 now */
1157     gst_flups_demux_send_event (demux, gst_event_new_flush_stop ());
1158   } else {
1159     gst_flups_demux_close_segment (demux);
1160   }
1161
1162   if (flush || seeksegment.last_stop != demux->src_segment.last_stop) {
1163     gst_flups_demux_flush (demux);
1164   }
1165
1166   /* Ok seek succeeded, take the newly configured segment */
1167   memcpy (&demux->src_segment, &seeksegment, sizeof (GstSegment));
1168
1169   /* Notify about the start of a new segment */
1170   if (demux->src_segment.flags & GST_SEEK_FLAG_SEGMENT) {
1171     gst_element_post_message (GST_ELEMENT (demux),
1172         gst_message_new_segment_start (GST_OBJECT (demux),
1173             demux->src_segment.format, demux->src_segment.last_stop));
1174   }
1175
1176   /* Tell all the stream a new segment is needed */
1177   gst_flups_demux_mark_discont (demux, TRUE, TRUE);
1178
1179   gst_pad_start_task (demux->sinkpad,
1180       (GstTaskFunction) gst_flups_demux_loop, demux->sinkpad);
1181
1182   GST_PAD_STREAM_UNLOCK (demux->sinkpad);
1183
1184   gst_event_unref (event);
1185   return TRUE;
1186
1187   /* ERRORS */
1188 wrong_format:
1189   {
1190     GST_WARNING_OBJECT (demux, "we only support seeking in TIME or BYTES "
1191         "formats");
1192     gst_event_unref (event);
1193     return FALSE;
1194   }
1195 no_scr_rate:
1196   {
1197     GST_WARNING_OBJECT (demux, "seek not possible, no scr_rate");
1198     gst_event_unref (event);
1199     return FALSE;
1200   }
1201 }
1202
1203 static gboolean
1204 gst_flups_demux_src_event (GstPad * pad, GstEvent * event)
1205 {
1206   gboolean res = FALSE;
1207   GstFluPSDemux *demux;
1208
1209   demux = GST_FLUPS_DEMUX (gst_pad_get_parent (pad));
1210
1211   switch (GST_EVENT_TYPE (event)) {
1212     case GST_EVENT_SEEK:
1213       if (demux->random_access) {
1214         res = gst_flups_demux_handle_seek_pull (demux, event);
1215       } else {
1216         res = gst_flups_demux_handle_seek_push (demux, event);
1217       }
1218       break;
1219     default:
1220       res = gst_pad_push_event (demux->sinkpad, event);
1221       break;
1222   }
1223
1224   gst_object_unref (demux);
1225
1226   return res;
1227 }
1228
1229 static const GstQueryType *
1230 gst_flups_demux_src_query_type (GstPad * pad)
1231 {
1232   static const GstQueryType types[] = {
1233     GST_QUERY_POSITION,
1234     GST_QUERY_DURATION,
1235     GST_QUERY_SEEKING,
1236     0
1237   };
1238
1239   return types;
1240 }
1241
1242 static gboolean
1243 gst_flups_demux_src_query (GstPad * pad, GstQuery * query)
1244 {
1245   gboolean res = FALSE;
1246   GstFluPSDemux *demux;
1247
1248   demux = GST_FLUPS_DEMUX (gst_pad_get_parent (pad));
1249
1250   GST_LOG_OBJECT (demux, "Have query of type %d on pad %" GST_PTR_FORMAT,
1251       GST_QUERY_TYPE (query), pad);
1252
1253   switch (GST_QUERY_TYPE (query)) {
1254     case GST_QUERY_POSITION:
1255     {
1256       GstClockTime pos;
1257       GstFormat format;
1258
1259       gst_query_parse_position (query, &format, NULL);
1260
1261       if (format != GST_FORMAT_TIME) {
1262         GST_DEBUG_OBJECT (demux, "position not supported for format %d",
1263             format);
1264         goto not_supported;
1265       }
1266
1267       pos = demux->src_segment.last_stop - demux->src_segment.start;
1268       GST_LOG_OBJECT (demux, "Position %" GST_TIME_FORMAT, GST_TIME_ARGS (pos));
1269       gst_query_set_position (query, format, pos);
1270       res = TRUE;
1271       break;
1272     }
1273     case GST_QUERY_DURATION:
1274     {
1275       GstFormat format;
1276       gint64 duration;
1277       GstPad *peer;
1278
1279       gst_query_parse_duration (query, &format, NULL);
1280
1281       if (G_LIKELY (format == GST_FORMAT_TIME &&
1282               GST_CLOCK_TIME_IS_VALID (demux->src_segment.duration))) {
1283         gst_query_set_duration (query, GST_FORMAT_TIME,
1284             demux->src_segment.duration);
1285         res = TRUE;
1286         break;
1287       }
1288
1289       if ((peer = gst_pad_get_peer (demux->sinkpad)) == NULL) {
1290         GST_DEBUG_OBJECT (demux, "duration not possible, no peer");
1291         goto not_supported;
1292       }
1293
1294       /* For any format other than bytes, see if upstream knows first */
1295       if (format == GST_FORMAT_BYTES) {
1296         GST_DEBUG_OBJECT (demux, "duration not supported for format %d",
1297             format);
1298         gst_object_unref (peer);
1299         goto not_supported;
1300       }
1301
1302       if (gst_pad_query (peer, query)) {
1303         gst_object_unref (peer);
1304         res = TRUE;
1305         break;
1306       }
1307
1308       /* Upstream didn't know, so we can only answer TIME queries from
1309        * here on */
1310       if (format != GST_FORMAT_TIME) {
1311         GST_DEBUG_OBJECT (demux, "duration not supported for format %d",
1312             format);
1313         gst_object_unref (peer);
1314         goto not_supported;
1315       }
1316
1317       if (demux->mux_rate == -1) {
1318         GST_DEBUG_OBJECT (demux, "duration not possible, no mux_rate");
1319         gst_object_unref (peer);
1320         goto not_supported;
1321       }
1322
1323       gst_query_set_duration (query, GST_FORMAT_BYTES, -1);
1324
1325       if (!gst_pad_query (peer, query)) {
1326         GST_LOG_OBJECT (demux, "query on peer pad failed");
1327         gst_object_unref (peer);
1328         goto not_supported;
1329       }
1330       gst_object_unref (peer);
1331
1332       gst_query_parse_duration (query, &format, &duration);
1333
1334       GST_LOG_OBJECT (demux,
1335           "query on peer pad reported bytes %" G_GUINT64_FORMAT, duration);
1336
1337       duration = BYTES_TO_GSTTIME (duration);
1338
1339       GST_LOG_OBJECT (demux, "converted to time %" GST_TIME_FORMAT,
1340           GST_TIME_ARGS (duration));
1341
1342       gst_query_set_duration (query, GST_FORMAT_TIME, duration);
1343       res = TRUE;
1344       break;
1345     }
1346     case GST_QUERY_SEEKING:{
1347       GstFormat fmt;
1348
1349       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
1350
1351       res = TRUE;
1352       if (demux->random_access) {
1353         /* In pull mode we can seek in TIME format if we have the SCR */
1354         if (fmt != GST_FORMAT_TIME || demux->scr_rate_n == G_MAXUINT64
1355             || demux->scr_rate_d == G_MAXUINT64)
1356           gst_query_set_seeking (query, fmt, FALSE, -1, -1);
1357         else
1358           gst_query_set_seeking (query, fmt, TRUE, 0, -1);
1359       } else {
1360         if (fmt == GST_FORMAT_BYTES) {
1361           /* Seeking in BYTES format not supported at all */
1362           gst_query_set_seeking (query, fmt, FALSE, -1, -1);
1363         } else {
1364           GstQuery *peerquery;
1365           gboolean seekable;
1366
1367           /* Then ask upstream */
1368           res = gst_pad_peer_query (demux->sinkpad, query);
1369           if (res) {
1370             /* If upstream can handle seeks we're done, if it
1371              * can't we still have our TIME->BYTES conversion seek
1372              */
1373             gst_query_parse_seeking (query, NULL, &seekable, NULL, NULL);
1374             if (seekable || fmt != GST_FORMAT_TIME)
1375               goto beach;
1376           }
1377
1378           /* We can seek if upstream supports BYTES seeks and we
1379            * have the SCR
1380            */
1381           peerquery = gst_query_new_seeking (GST_FORMAT_BYTES);
1382           res = gst_pad_peer_query (demux->sinkpad, peerquery);
1383           if (!res || demux->scr_rate_n == G_MAXUINT64
1384               || demux->scr_rate_d == G_MAXUINT64) {
1385             gst_query_set_seeking (query, fmt, FALSE, -1, -1);
1386           } else {
1387             gst_query_parse_seeking (peerquery, NULL, &seekable, NULL, NULL);
1388             if (seekable)
1389               gst_query_set_seeking (query, GST_FORMAT_TIME, TRUE, 0, -1);
1390             else
1391               gst_query_set_seeking (query, fmt, FALSE, -1, -1);
1392           }
1393
1394           gst_query_unref (peerquery);
1395           res = TRUE;
1396         }
1397       }
1398       break;
1399     }
1400     default:
1401       res = gst_pad_query_default (pad, query);
1402       break;
1403   }
1404
1405 beach:
1406   gst_object_unref (demux);
1407
1408   return res;
1409
1410 not_supported:
1411   {
1412     gst_object_unref (demux);
1413
1414     return FALSE;
1415   }
1416 }
1417
1418 static void
1419 gst_flups_demux_reset_psm (GstFluPSDemux * demux)
1420 {
1421   gint i;
1422
1423 #define FILL_TYPE(start, stop, type)    \
1424   for (i=start; i <= stop; i++)                 \
1425     demux->psm[i] = type;
1426
1427   FILL_TYPE (0x00, 0x1f, -1);
1428   FILL_TYPE (0x20, 0x3f, ST_PS_DVD_SUBPICTURE);
1429   FILL_TYPE (0x40, 0x7f, -1);
1430   FILL_TYPE (0x80, 0x87, ST_PS_AUDIO_AC3);
1431   FILL_TYPE (0x88, 0x9f, ST_PS_AUDIO_DTS);
1432   FILL_TYPE (0xa0, 0xaf, ST_PS_AUDIO_LPCM);
1433   FILL_TYPE (0xbd, 0xbd, -1);
1434   FILL_TYPE (0xc0, 0xdf, ST_AUDIO_MPEG1);
1435   FILL_TYPE (0xe0, 0xef, ST_GST_VIDEO_MPEG1_OR_2);
1436   FILL_TYPE (0xf0, 0xff, -1);
1437
1438 #undef FILL_TYPE
1439 }
1440
1441 /* ISO/IEC 13818-1:
1442  * pack_header() {
1443  *     pack_start_code                                   32  bslbf  -+
1444  *     '01'                                               2  bslbf   |
1445  *     system_clock_reference_base [32..30]               3  bslbf   |
1446  *     marker_bit                                         1  bslbf   |
1447  *     system_clock_reference_base [29..15]              15  bslbf   |
1448  *     marker_bit                                         1  bslbf   |
1449  *     system_clock_reference_base [14..0]               15  bslbf   |
1450  *     marker_bit                                         1  bslbf   | 112 bits
1451  *     system_clock_reference_extension                   9  ubslbf  |
1452  *     marker_bit                                         1  bslbf   |
1453  *     program_mux_rate                                  22  ubslbf  |
1454  *     marker_bit                                         1  bslbf   |
1455  *     marker_bit                                         1  bslbf   |
1456  *     reserved                                           5  bslbf   |
1457  *     pack_stuffing_length                               3  ubslbf -+
1458  *
1459  *     for (i = 0; i < pack_stuffing_length; i++) {
1460  *         stuffing_byte '1111 1111'                      8  bslbf
1461  *     }
1462  *
1463  * 112 bits = 14 bytes, as max value for pack_stuffing_length is 7, then
1464  * in total it's needed 14 + 7 = 21 bytes.
1465  */
1466 #define PACK_START_SIZE     21
1467
1468 static GstFlowReturn
1469 gst_flups_demux_parse_pack_start (GstFluPSDemux * demux)
1470 {
1471   const guint8 *data;
1472   guint length;
1473   guint32 scr1, scr2;
1474   guint64 scr, scr_adjusted, new_rate;
1475   guint64 scr_rate_n;
1476   guint64 scr_rate_d;
1477   guint avail = gst_adapter_available (demux->adapter);
1478
1479   GST_DEBUG ("parsing pack start");
1480
1481   if (G_UNLIKELY (avail < PACK_START_SIZE))
1482     goto need_more_data;
1483
1484   data = gst_adapter_peek (demux->adapter, PACK_START_SIZE);
1485
1486   /* skip start code */
1487   data += 4;
1488
1489   scr1 = GST_READ_UINT32_BE (data);
1490   scr2 = GST_READ_UINT32_BE (data + 4);
1491
1492   /* fixed length to begin with, start code and two scr values */
1493   length = 8 + 4;
1494
1495   /* start parsing the stream */
1496   if ((*data & 0xc0) == 0x40) {
1497     guint32 scr_ext;
1498     guint32 next32;
1499     guint8 stuffing_bytes;
1500
1501     GST_DEBUG ("Found MPEG2 stream");
1502     demux->is_mpeg2_pack = TRUE;
1503
1504     /* mpeg2 has more data */
1505     length += 2;
1506
1507     /* :2=01 ! scr:3 ! marker:1==1 ! scr:15 ! marker:1==1 ! scr:15 */
1508
1509     /* check markers */
1510     if (G_UNLIKELY ((scr1 & 0xc4000400) != 0x44000400))
1511       goto lost_sync;
1512
1513     scr = ((guint64) scr1 & 0x38000000) << 3;
1514     scr |= ((guint64) scr1 & 0x03fff800) << 4;
1515     scr |= ((guint64) scr1 & 0x000003ff) << 5;
1516     scr |= ((guint64) scr2 & 0xf8000000) >> 27;
1517
1518     /* marker:1==1 ! scr_ext:9 ! marker:1==1 */
1519     if (G_UNLIKELY ((scr2 & 0x04010000) != 0x04010000))
1520       goto lost_sync;
1521
1522     scr_ext = (scr2 & 0x03fe0000) >> 17;
1523     /* We keep the offset of this scr */
1524     demux->cur_scr_offset = demux->adapter_offset + 12;
1525
1526     GST_DEBUG_OBJECT (demux, "SCR: 0x%08" G_GINT64_MODIFIER "x SCRE: 0x%08x",
1527         scr, scr_ext);
1528
1529     if (scr_ext) {
1530       scr = (scr * 300 + scr_ext % 300) / 300;
1531     }
1532     /* SCR has been converted into units of 90Khz ticks to make it comparable
1533        to DTS/PTS, that also implies 1 tick rounding error */
1534     data += 6;
1535     /* PMR:22 ! :2==11 ! reserved:5 ! stuffing_len:3 */
1536     next32 = GST_READ_UINT32_BE (data);
1537     if (G_UNLIKELY ((next32 & 0x00000300) != 0x00000300))
1538       goto lost_sync;
1539
1540     new_rate = (next32 & 0xfffffc00) >> 10;
1541
1542     stuffing_bytes = (next32 & 0x07);
1543     GST_DEBUG_OBJECT (demux, "stuffing bytes: %d", stuffing_bytes);
1544
1545     data += 4;
1546     length += stuffing_bytes;
1547     while (stuffing_bytes--) {
1548       if (*data++ != 0xff)
1549         goto lost_sync;
1550     }
1551   } else {
1552     GST_DEBUG ("Found MPEG1 stream");
1553     demux->is_mpeg2_pack = FALSE;
1554
1555     /* check markers */
1556     if (G_UNLIKELY ((scr1 & 0xf1000100) != 0x21000100))
1557       goto lost_sync;
1558
1559     if (G_UNLIKELY ((scr2 & 0x01800001) != 0x01800001))
1560       goto lost_sync;
1561
1562     /* :4=0010 ! scr:3 ! marker:1==1 ! scr:15 ! marker:1==1 ! scr:15 ! marker:1==1 */
1563     scr = ((guint64) scr1 & 0x0e000000) << 5;
1564     scr |= ((guint64) scr1 & 0x00fffe00) << 6;
1565     scr |= ((guint64) scr1 & 0x000000ff) << 7;
1566     scr |= ((guint64) scr2 & 0xfe000000) >> 25;
1567
1568     /* We keep the offset of this scr */
1569     demux->cur_scr_offset = demux->adapter_offset + 8;
1570
1571     /* marker:1==1 ! mux_rate:22 ! marker:1==1 */
1572     new_rate = (scr2 & 0x007ffffe) >> 1;
1573
1574     data += 8;
1575   }
1576   new_rate *= MPEG_MUX_RATE_MULT;
1577
1578   /* scr adjusted is the new scr found + the colected adjustment */
1579   scr_adjusted = scr + demux->scr_adjust;
1580
1581   GST_LOG_OBJECT (demux,
1582       "SCR: %" G_GINT64_FORMAT " (%" G_GINT64_FORMAT "), mux_rate %"
1583       G_GINT64_FORMAT ", GStreamer Time:%" GST_TIME_FORMAT,
1584       scr, scr_adjusted, new_rate,
1585       GST_TIME_ARGS (MPEGTIME_TO_GSTTIME ((guint64) scr)));
1586
1587   /* keep the first src in order to calculate delta time */
1588   if (G_UNLIKELY (demux->first_scr == G_MAXUINT64)) {
1589     demux->first_scr = scr;
1590     demux->first_scr_offset = demux->cur_scr_offset;
1591     demux->base_time = MPEGTIME_TO_GSTTIME (demux->first_scr);
1592     /* at begin consider the new_rate as the scr rate, bytes/clock ticks */
1593     scr_rate_n = new_rate;
1594     scr_rate_d = CLOCK_FREQ;
1595   } else if (G_LIKELY (demux->first_scr_offset != demux->cur_scr_offset)) {
1596     /* estimate byte rate related to the SCR */
1597     scr_rate_n = demux->cur_scr_offset - demux->first_scr_offset;
1598     scr_rate_d = scr_adjusted - demux->first_scr;
1599   } else {
1600     scr_rate_n = demux->scr_rate_n;
1601     scr_rate_d = demux->scr_rate_d;
1602   }
1603
1604   GST_DEBUG_OBJECT (demux, "%s mode scr: %" G_GUINT64_FORMAT " at %"
1605       G_GUINT64_FORMAT ", first scr: %" G_GUINT64_FORMAT
1606       " at %" G_GUINT64_FORMAT ", scr rate: %" G_GUINT64_FORMAT
1607       "/%" G_GUINT64_FORMAT "(%f)",
1608       ((demux->sink_segment.rate >= 0.0) ? "forward" : "backward"),
1609       scr, demux->cur_scr_offset,
1610       demux->first_scr, demux->first_scr_offset,
1611       scr_rate_n, scr_rate_d, (float) scr_rate_n / scr_rate_d);
1612
1613   /* adjustment of the SCR */
1614   if (G_LIKELY (demux->current_scr != G_MAXUINT64)) {
1615     guint64 diff;
1616     guint64 old_scr, old_mux_rate, bss, adjust = 0;
1617
1618     /* keep SCR of the previous packet */
1619     old_scr = demux->current_scr;
1620     old_mux_rate = demux->mux_rate;
1621
1622     /* Bytes since SCR is the amount we placed in the adapter since then
1623      * (demux->bytes_since_scr) minus the amount remaining in the adapter,
1624      * clamped to >= 0 */
1625     bss = MAX (0, (gint) (demux->bytes_since_scr - avail));
1626
1627     /* estimate the new SCR using the previous one according the notes
1628        on point 2.5.2.2 of the ISO/IEC 13818-1 document */
1629     if (old_mux_rate != 0)
1630       adjust = (bss * CLOCK_FREQ) / old_mux_rate;
1631
1632     if (demux->sink_segment.rate >= 0.0)
1633       demux->next_scr = old_scr + adjust;
1634     else
1635       demux->next_scr = old_scr - adjust;
1636
1637     GST_DEBUG_OBJECT (demux,
1638         "bss: %" G_GUINT64_FORMAT ", next_scr: %" G_GUINT64_FORMAT
1639         ", old_scr: %" G_GUINT64_FORMAT ", scr: %" G_GUINT64_FORMAT,
1640         bss, demux->next_scr, old_scr, scr_adjusted);
1641
1642     /* calculate the absolute deference between the last scr and
1643        the new one */
1644     if (G_UNLIKELY (old_scr > scr_adjusted))
1645       diff = old_scr - scr_adjusted;
1646     else
1647       diff = scr_adjusted - old_scr;
1648
1649     /* if the difference is more than 1 second we need to reconfigure
1650        adjustment */
1651     if (G_UNLIKELY (diff > CLOCK_FREQ)) {
1652       demux->scr_adjust = demux->next_scr - scr;
1653       GST_DEBUG_OBJECT (demux, "discont found, diff: %" G_GINT64_FORMAT
1654           ", adjust %" G_GINT64_FORMAT, diff, demux->scr_adjust);
1655       scr_adjusted = demux->next_scr;
1656       /* don't update rate estimation on disconts */
1657       scr_rate_n = demux->scr_rate_n;
1658       scr_rate_d = demux->scr_rate_d;
1659     } else {
1660       demux->next_scr = scr_adjusted;
1661     }
1662   }
1663
1664   /* update the current_scr and rate members */
1665   demux->mux_rate = new_rate;
1666   demux->current_scr = scr_adjusted;
1667   demux->scr_rate_n = scr_rate_n;
1668   demux->scr_rate_d = scr_rate_d;
1669
1670   /* Reset the bytes_since_scr value to count the data remaining in the
1671    * adapter */
1672   demux->bytes_since_scr = avail;
1673
1674   gst_adapter_flush (demux->adapter, length);
1675   ADAPTER_OFFSET_FLUSH (length);
1676   return GST_FLOW_OK;
1677
1678 lost_sync:
1679   {
1680     GST_DEBUG_OBJECT (demux, "lost sync");
1681     return GST_FLOW_LOST_SYNC;
1682   }
1683 need_more_data:
1684   {
1685     GST_DEBUG_OBJECT (demux, "need more data");
1686     return GST_FLOW_NEED_MORE_DATA;
1687   }
1688 }
1689
1690 /* ISO/IEC 13818-1:
1691  * system_header () {
1692  *     system_header_start_code                          32  bslbf  -+
1693  *     header_length                                     16  uimsbf  |
1694  *     marker_bit                                         1  bslbf   |
1695  *     rate_bound                                        22  uimsbf  |
1696  *     marker_bit                                         1  bslbf   |
1697  *     audio_bound                                        6  uimsbf  |
1698  *     fixed_flag                                         1  bslbf   |
1699  *     CSPS_flag                                          1  bslbf   | 96 bits
1700  *     system_audio_lock_flag                             1  bslbf   |
1701  *     system_video_lock_flag                             1  bslbf   |
1702  *     marker_bit                                         1  bslbf   |
1703  *     video_bound                                        5  uimsbf  |
1704  *     packet_rate_restriction_flag                       1  bslbf   |
1705  *     reserved_bits                                      7  bslbf  -+
1706  *     while (nextbits () = = '1') {
1707  *         stream_id                                      8  uimsbf -+
1708  *         '11'                                           2  bslbf   | 24 bits
1709  *         P-STD_buffer_bound_scale                       1  bslbf   |
1710  *         P-STD_buffer_size_bound                       13  uimsbf -+
1711  *     }
1712  * }
1713  * 96 bits = 12 bytes, 24 bits = 3 bytes.
1714  */
1715
1716 static GstFlowReturn
1717 gst_flups_demux_parse_sys_head (GstFluPSDemux * demux)
1718 {
1719   guint16 length;
1720   const guint8 *data;
1721   gboolean csps;
1722
1723   /* start code + length */
1724   if (!(data = gst_adapter_peek (demux->adapter, 6)))
1725     goto need_more_data;
1726
1727   /* skip start code */
1728   data += 4;
1729
1730   length = GST_READ_UINT16_BE (data);
1731   GST_DEBUG_OBJECT (demux, "length %d", length);
1732
1733   length += 6;
1734
1735   if (!(data = gst_adapter_peek (demux->adapter, length)))
1736     goto need_more_data;
1737
1738   /* skip start code and length */
1739   data += 6;
1740
1741   /* marker:1==1 ! rate_bound:22 | marker:1==1 */
1742   if ((*data & 0x80) != 0x80)
1743     goto marker_expected;
1744
1745   {
1746     guint32 rate_bound;
1747
1748     if ((data[2] & 0x01) != 0x01)
1749       goto marker_expected;
1750
1751     rate_bound = ((guint32) data[0] & 0x7f) << 15;
1752     rate_bound |= ((guint32) data[1]) << 7;
1753     rate_bound |= ((guint32) data[2] & 0xfe) >> 1;
1754     rate_bound *= MPEG_MUX_RATE_MULT;
1755
1756     GST_DEBUG_OBJECT (demux, "rate bound %u", rate_bound);
1757
1758     data += 3;
1759   }
1760
1761   /* audio_bound:6==1 ! fixed:1 | constrained:1 */
1762   {
1763     guint8 audio_bound;
1764     gboolean fixed;
1765
1766     /* max number of simultaneous audio streams active */
1767     audio_bound = (data[0] & 0xfc) >> 2;
1768     /* fixed or variable bitrate */
1769     fixed = (data[0] & 0x02) == 0x02;
1770     /* meeting constraints */
1771     csps = (data[0] & 0x01) == 0x01;
1772
1773     GST_DEBUG_OBJECT (demux, "audio_bound %d, fixed %d, constrained %d",
1774         audio_bound, fixed, csps);
1775     data += 1;
1776   }
1777
1778   /* audio_lock:1 | video_lock:1 | marker:1==1 | video_bound:5 */
1779   {
1780     gboolean audio_lock;
1781     gboolean video_lock;
1782     guint8 video_bound;
1783
1784     audio_lock = (data[0] & 0x80) == 0x80;
1785     video_lock = (data[0] & 0x40) == 0x40;
1786
1787     if ((data[0] & 0x20) != 0x20)
1788       goto marker_expected;
1789
1790     /* max number of simultaneous video streams active */
1791     video_bound = (data[0] & 0x1f);
1792
1793     GST_DEBUG_OBJECT (demux, "audio_lock %d, video_lock %d, video_bound %d",
1794         audio_lock, video_lock, video_bound);
1795     data += 1;
1796   }
1797
1798   /* packet_rate_restriction:1 | reserved:7==0x7F */
1799   {
1800     gboolean packet_rate_restriction;
1801
1802     if ((data[0] & 0x7f) != 0x7f)
1803       goto marker_expected;
1804
1805     /* only valid if csps is set */
1806     if (csps) {
1807       packet_rate_restriction = (data[0] & 0x80) == 0x80;
1808
1809       GST_DEBUG_OBJECT (demux, "packet_rate_restriction %d",
1810           packet_rate_restriction);
1811     }
1812   }
1813   data += 1;
1814
1815   {
1816     gint stream_count = (length - 12) / 3;
1817     gint i;
1818
1819     GST_DEBUG_OBJECT (demux, "number of streams: %d ", stream_count);
1820
1821     for (i = 0; i < stream_count; i++) {
1822       guint8 stream_id;
1823       gboolean STD_buffer_bound_scale;
1824       guint16 STD_buffer_size_bound;
1825       guint32 buf_byte_size_bound;
1826
1827       stream_id = *data++;
1828       if (!(stream_id & 0x80))
1829         goto sys_len_error;
1830
1831       /* check marker bits */
1832       if ((*data & 0xC0) != 0xC0)
1833         goto no_placeholder_bits;
1834
1835       STD_buffer_bound_scale = *data & 0x20;
1836       STD_buffer_size_bound = ((guint16) (*data++ & 0x1F)) << 8;
1837       STD_buffer_size_bound |= *data++;
1838
1839       if (STD_buffer_bound_scale == 0) {
1840         buf_byte_size_bound = STD_buffer_size_bound * 128;
1841       } else {
1842         buf_byte_size_bound = STD_buffer_size_bound * 1024;
1843       }
1844
1845       GST_DEBUG_OBJECT (demux, "STD_buffer_bound_scale %d",
1846           STD_buffer_bound_scale);
1847       GST_DEBUG_OBJECT (demux, "STD_buffer_size_bound %d or %d bytes",
1848           STD_buffer_size_bound, buf_byte_size_bound);
1849     }
1850   }
1851
1852   gst_adapter_flush (demux->adapter, length);
1853   ADAPTER_OFFSET_FLUSH (length);
1854   return GST_FLOW_OK;
1855
1856   /* ERRORS */
1857 marker_expected:
1858   {
1859     GST_DEBUG_OBJECT (demux, "expecting marker");
1860     return GST_FLOW_LOST_SYNC;
1861   }
1862 no_placeholder_bits:
1863   {
1864     GST_DEBUG_OBJECT (demux, "expecting placeholder bit values"
1865         " '11' after stream id");
1866     return GST_FLOW_LOST_SYNC;
1867   }
1868 sys_len_error:
1869   {
1870     GST_DEBUG_OBJECT (demux, "error in system header length");
1871     return GST_FLOW_LOST_SYNC;
1872   }
1873 need_more_data:
1874   {
1875     GST_DEBUG_OBJECT (demux, "need more data");
1876     return GST_FLOW_NEED_MORE_DATA;
1877   }
1878 }
1879
1880 static GstFlowReturn
1881 gst_flups_demux_parse_psm (GstFluPSDemux * demux)
1882 {
1883   guint16 length = 0, info_length = 0, es_map_length = 0;
1884   guint8 psm_version = 0;
1885   const guint8 *data, *es_map_base;
1886   gboolean applicable;
1887
1888   /* start code + length */
1889   if (!(data = gst_adapter_peek (demux->adapter, 6)))
1890     goto need_more_data;
1891
1892   /* skip start code */
1893   data += 4;
1894
1895   length = GST_READ_UINT16_BE (data);
1896   GST_DEBUG_OBJECT (demux, "length %u", length);
1897
1898   if (G_UNLIKELY (length > 0x3FA))
1899     goto psm_len_error;
1900
1901   length += 6;
1902
1903   if (!(data = gst_adapter_peek (demux->adapter, length)))
1904     goto need_more_data;
1905
1906   /* skip start code and length */
1907   data += 6;
1908
1909   /* Read PSM applicable bit together with version */
1910   psm_version = GST_READ_UINT8 (data);
1911   applicable = (psm_version & 0x80) >> 7;
1912   psm_version &= 0x1F;
1913   GST_DEBUG_OBJECT (demux, "PSM version %u (applicable now %u)", psm_version,
1914       applicable);
1915
1916   /* Jump over version and marker bit */
1917   data += 2;
1918
1919   /* Read PS info length */
1920   info_length = GST_READ_UINT16_BE (data);
1921   /* Cap it to PSM length - needed bytes for ES map length and CRC */
1922   info_length = MIN (length - 16, info_length);
1923   GST_DEBUG_OBJECT (demux, "PS info length %u bytes", info_length);
1924
1925   /* Jump over that section */
1926   data += (2 + info_length);
1927
1928   /* Read ES map length */
1929   es_map_length = GST_READ_UINT16_BE (data);
1930   /* Cap it to PSM remaining length -  CRC */
1931   es_map_length = MIN (length - (16 + info_length), es_map_length);
1932   GST_DEBUG_OBJECT (demux, "ES map length %u bytes", es_map_length);
1933
1934   /* Jump over the size */
1935   data += 2;
1936
1937   /* Now read the ES map */
1938   es_map_base = data;
1939   while (es_map_base + 4 <= data + es_map_length) {
1940     guint8 stream_type = 0, stream_id = 0;
1941     guint16 stream_info_length = 0;
1942
1943     stream_type = GST_READ_UINT8 (es_map_base);
1944     es_map_base++;
1945     stream_id = GST_READ_UINT8 (es_map_base);
1946     es_map_base++;
1947     stream_info_length = GST_READ_UINT16_BE (es_map_base);
1948     es_map_base += 2;
1949     /* Cap stream_info_length */
1950     stream_info_length = MIN (data + es_map_length - es_map_base,
1951         stream_info_length);
1952
1953     GST_DEBUG_OBJECT (demux, "Stream type %02X with id %02X and %u bytes info",
1954         stream_type, stream_id, stream_info_length);
1955     if (G_LIKELY (stream_id != 0xbd))
1956       demux->psm[stream_id] = stream_type;
1957     else {
1958       /* Ignore stream type for private_stream_1 and discover it looking at
1959        * the stream data.
1960        * Fixes demuxing some clips with lpcm that was wrongly declared as
1961        * mpeg audio */
1962       GST_DEBUG_OBJECT (demux, "stream type for private_stream_1 ignored");
1963     }
1964     es_map_base += stream_info_length;
1965   }
1966
1967   gst_adapter_flush (demux->adapter, length);
1968   ADAPTER_OFFSET_FLUSH (length);
1969   return GST_FLOW_OK;
1970
1971 psm_len_error:
1972   {
1973     GST_DEBUG_OBJECT (demux, "error in PSM length");
1974     return GST_FLOW_LOST_SYNC;
1975   }
1976 need_more_data:
1977   {
1978     GST_DEBUG_OBJECT (demux, "need more data");
1979     return GST_FLOW_NEED_MORE_DATA;
1980   }
1981 }
1982
1983 static void
1984 gst_flups_demux_resync_cb (GstPESFilter * filter, GstFluPSDemux * demux)
1985 {
1986 }
1987
1988 static GstFlowReturn
1989 gst_flups_demux_data_cb (GstPESFilter * filter, gboolean first,
1990     GstBuffer * buffer, GstFluPSDemux * demux)
1991 {
1992   GstBuffer *out_buf;
1993   GstFlowReturn ret = GST_FLOW_OK;
1994   gint stream_type;
1995   guint32 start_code;
1996   guint8 id;
1997   guint8 *data;
1998   guint datalen;
1999   guint offset = 0;
2000
2001   data = GST_BUFFER_DATA (buffer);
2002   datalen = GST_BUFFER_SIZE (buffer);
2003
2004   start_code = filter->start_code;
2005   id = filter->id;
2006
2007   if (first) {
2008     /* find the stream type */
2009     stream_type = demux->psm[id];
2010     if (stream_type == -1) {
2011       /* no stream type, if PS1, get the new id */
2012       if (start_code == ID_PRIVATE_STREAM_1 && datalen >= 2) {
2013         guint8 nframes;
2014
2015         /* VDR writes A52 streams without any header bytes
2016          * (see ftp://ftp.mplayerhq.hu/MPlayer/samples/MPEG-VOB/vdr-AC3) */
2017         if (datalen >= 4) {
2018           guint hdr = GST_READ_UINT32_BE (data);
2019
2020           if (G_UNLIKELY ((hdr & 0xffff0000) == AC3_SYNC_WORD)) {
2021             id = 0x80;
2022             stream_type = demux->psm[id] = ST_GST_AUDIO_RAWA52;
2023             GST_DEBUG_OBJECT (demux, "Found VDR raw A52 stream");
2024           }
2025         }
2026
2027         if (G_LIKELY (stream_type == -1)) {
2028           /* new id is in the first byte */
2029           id = data[offset++];
2030           datalen--;
2031
2032           /* and remap */
2033           stream_type = demux->psm[id];
2034
2035           /* Now, if it's a subpicture stream - no more, otherwise
2036            * take the first byte too, since it's the frame count in audio
2037            * streams and our backwards compat convention is to strip it off */
2038           if (stream_type != ST_PS_DVD_SUBPICTURE) {
2039             /* Number of audio frames in this packet */
2040             nframes = data[offset++];
2041             datalen--;
2042             GST_DEBUG_OBJECT (demux, "private type 0x%02x, %d frames", id,
2043                 nframes);
2044           } else {
2045             GST_DEBUG_OBJECT (demux, "private type 0x%02x, stream type %d", id,
2046                 stream_type);
2047           }
2048         }
2049       }
2050       if (stream_type == -1)
2051         goto unknown_stream_type;
2052     }
2053     if (filter->pts != -1) {
2054       demux->next_pts = filter->pts + demux->scr_adjust;
2055       GST_DEBUG_OBJECT (demux, "PTS = %" G_GUINT64_FORMAT
2056           "(%" G_GUINT64_FORMAT ")", filter->pts, demux->next_pts);
2057     } else
2058       demux->next_pts = G_MAXUINT64;
2059
2060     if (filter->dts != -1) {
2061       demux->next_dts = filter->dts + demux->scr_adjust;
2062     } else {
2063       demux->next_dts = demux->next_pts;
2064     }
2065     GST_DEBUG_OBJECT (demux, "DTS = orig %" G_GUINT64_FORMAT
2066         " (%" G_GUINT64_FORMAT ")", filter->dts, demux->next_dts);
2067
2068     demux->current_stream = gst_flups_demux_get_stream (demux, id, stream_type);
2069   }
2070
2071   if (G_UNLIKELY (demux->current_stream == NULL)) {
2072     GST_DEBUG_OBJECT (demux, "Dropping buffer for unknown stream id 0x%02x",
2073         id);
2074     goto done;
2075   }
2076
2077   /* After 2 seconds of bitstream emit no more pads */
2078   if (demux->need_no_more_pads
2079       && (demux->current_scr - demux->first_scr) > 2 * CLOCK_FREQ) {
2080     GST_DEBUG_OBJECT (demux, "no more pads, notifying");
2081     gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
2082     demux->need_no_more_pads = FALSE;
2083   }
2084
2085   /* If the stream is not-linked, don't bother creating a sub-buffer
2086    * to send to it, unless we're processing a discont (which resets
2087    * the not-linked status and tries again */
2088   if (demux->current_stream->discont) {
2089     GST_DEBUG_OBJECT (demux, "stream is discont");
2090     demux->current_stream->notlinked = FALSE;
2091   }
2092
2093   if (demux->current_stream->notlinked == FALSE) {
2094     out_buf = gst_buffer_create_sub (buffer, offset, datalen);
2095
2096     ret = gst_flups_demux_send_data (demux, demux->current_stream, out_buf);
2097     if (ret == GST_FLOW_NOT_LINKED) {
2098       demux->current_stream->notlinked = TRUE;
2099       ret = GST_FLOW_OK;
2100     }
2101   }
2102
2103 done:
2104   gst_buffer_unref (buffer);
2105
2106   return ret;
2107
2108   /* ERRORS */
2109 unknown_stream_type:
2110   {
2111     GST_DEBUG_OBJECT (demux, "unknown stream type %02x", id);
2112     ret = GST_FLOW_OK;
2113     goto done;
2114   }
2115 }
2116
2117 static gboolean
2118 gst_flups_demux_resync (GstFluPSDemux * demux, gboolean save)
2119 {
2120   const guint8 *data;
2121   gint avail;
2122   guint32 code;
2123   gint offset;
2124   gboolean found;
2125
2126   avail = gst_adapter_available (demux->adapter);
2127   if (G_UNLIKELY (avail < 4))
2128     goto need_data;
2129
2130   /* Common case, read 4 bytes an check it */
2131   data = gst_adapter_peek (demux->adapter, 4);
2132
2133   /* read currect code */
2134   code = GST_READ_UINT32_BE (data);
2135
2136   /* The common case is that the sync code is at 0 bytes offset */
2137   if (G_LIKELY ((code & 0xffffff00) == 0x100L)) {
2138     GST_LOG_OBJECT (demux, "Found resync code %08x after 0 bytes", code);
2139     demux->last_sync_code = code;
2140     return TRUE;
2141   }
2142
2143   /* Otherwise, we are starting at byte 4 and we need to search
2144      the sync code in all available data in the adapter */
2145   offset = 4;
2146   if (offset >= avail)
2147     goto need_data;             /* Not enough data to find sync */
2148
2149   data = gst_adapter_peek (demux->adapter, avail);
2150
2151   do {
2152     code = (code << 8) | data[offset++];
2153     found = (code & 0xffffff00) == 0x100L;
2154   } while (offset < avail && !found);
2155
2156   if (!save || demux->sink_segment.rate >= 0.0) {
2157     GST_LOG_OBJECT (demux, "flushing %d bytes", offset - 4);
2158     /* forward playback, we can discard and flush the skipped bytes */
2159     gst_adapter_flush (demux->adapter, offset - 4);
2160     ADAPTER_OFFSET_FLUSH (offset - 4);
2161   } else {
2162     if (found) {
2163       GST_LOG_OBJECT (demux, "reverse saving %d bytes", offset - 4);
2164       /* reverse playback, we keep the flushed bytes and we will append them to
2165        * the next buffer in the chain function, which is the previous buffer in
2166        * the stream. */
2167       gst_adapter_push (demux->rev_adapter,
2168           gst_adapter_take_buffer (demux->adapter, offset - 4));
2169     } else {
2170       GST_LOG_OBJECT (demux, "reverse saving %d bytes", avail);
2171       /* nothing found, keep all bytes */
2172       gst_adapter_push (demux->rev_adapter,
2173           gst_adapter_take_buffer (demux->adapter, avail));
2174     }
2175   }
2176
2177   if (found) {
2178     GST_LOG_OBJECT (demux, "Found resync code %08x after %d bytes",
2179         code, offset - 4);
2180     demux->last_sync_code = code;
2181   } else {
2182     GST_LOG_OBJECT (demux, "No resync after skipping %d", offset);
2183   }
2184
2185   return found;
2186
2187 need_data:
2188   {
2189     GST_LOG_OBJECT (demux, "we need more data for resync %d", avail);
2190     return FALSE;
2191   }
2192 }
2193
2194 static inline gboolean
2195 gst_flups_demux_is_pes_sync (guint32 sync)
2196 {
2197   return ((sync & 0xfc) == 0xbc) ||
2198       ((sync & 0xe0) == 0xc0) || ((sync & 0xf0) == 0xe0);
2199 }
2200
2201 static inline gboolean
2202 gst_flups_demux_scan_ts (GstFluPSDemux * demux, const guint8 * data,
2203     SCAN_MODE mode, guint64 * rts)
2204 {
2205   gboolean ret = FALSE;
2206   guint32 scr1, scr2;
2207   guint64 scr;
2208   guint64 pts, dts;
2209   guint32 code;
2210
2211   /* read the 4 bytes for the sync code */
2212   code = GST_READ_UINT32_BE (data);
2213   if (G_LIKELY (code != ID_PS_PACK_START_CODE))
2214     goto beach;
2215
2216   /* skip start code */
2217   data += 4;
2218
2219   scr1 = GST_READ_UINT32_BE (data);
2220   scr2 = GST_READ_UINT32_BE (data + 4);
2221
2222   /* start parsing the stream */
2223   if ((*data & 0xc0) == 0x40) {
2224     guint32 scr_ext;
2225     guint32 next32;
2226     guint8 stuffing_bytes;
2227
2228     /* :2=01 ! scr:3 ! marker:1==1 ! scr:15 ! marker:1==1 ! scr:15 */
2229
2230     /* check markers */
2231     if ((scr1 & 0xc4000400) != 0x44000400)
2232       goto beach;
2233
2234     scr = ((guint64) scr1 & 0x38000000) << 3;
2235     scr |= ((guint64) scr1 & 0x03fff800) << 4;
2236     scr |= ((guint64) scr1 & 0x000003ff) << 5;
2237     scr |= ((guint64) scr2 & 0xf8000000) >> 27;
2238
2239     /* marker:1==1 ! scr_ext:9 ! marker:1==1 */
2240     if ((scr2 & 0x04010000) != 0x04010000)
2241       goto beach;
2242
2243     scr_ext = (scr2 & 0x03fe0000) >> 17;
2244
2245     if (scr_ext) {
2246       scr = (scr * 300 + scr_ext % 300) / 300;
2247     }
2248     /* SCR has been converted into units of 90Khz ticks to make it comparable
2249        to DTS/PTS, that also implies 1 tick rounding error */
2250     data += 6;
2251     /* PMR:22 ! :2==11 ! reserved:5 ! stuffing_len:3 */
2252     next32 = GST_READ_UINT32_BE (data);
2253     if ((next32 & 0x00000300) != 0x00000300)
2254       goto beach;
2255
2256     stuffing_bytes = (next32 & 0x07);
2257     data += 4;
2258     while (stuffing_bytes--) {
2259       if (*data++ != 0xff)
2260         goto beach;
2261     }
2262   } else {
2263     /* check markers */
2264     if ((scr1 & 0xf1000100) != 0x21000100)
2265       goto beach;
2266
2267     if ((scr2 & 0x01800001) != 0x01800001)
2268       goto beach;
2269
2270     /* :4=0010 ! scr:3 ! marker:1==1 ! scr:15 ! marker:1==1 ! scr:15 ! marker:1==1 */
2271     scr = ((guint64) scr1 & 0x0e000000) << 5;
2272     scr |= ((guint64) scr1 & 0x00fffe00) << 6;
2273     scr |= ((guint64) scr1 & 0x000000ff) << 7;
2274     scr |= ((guint64) scr2 & 0xfe000000) >> 25;
2275     data += 8;
2276   }
2277
2278   if (mode == SCAN_SCR) {
2279     *rts = scr;
2280     ret = TRUE;
2281   }
2282
2283   /* read the 4 bytes for the PES sync code */
2284   code = GST_READ_UINT32_BE (data);
2285   if (!gst_flups_demux_is_pes_sync (code))
2286     goto beach;
2287
2288   switch (code) {
2289     case ID_PS_PROGRAM_STREAM_MAP:
2290     case ID_PRIVATE_STREAM_2:
2291     case ID_ECM_STREAM:
2292     case ID_EMM_STREAM:
2293     case ID_PROGRAM_STREAM_DIRECTORY:
2294     case ID_DSMCC_STREAM:
2295     case ID_ITU_TREC_H222_TYPE_E_STREAM:
2296     case ID_PADDING_STREAM:
2297       goto beach;
2298     default:
2299       break;
2300   }
2301
2302   /* skip sync code and size */
2303   data += 6;
2304
2305   pts = dts = -1;
2306
2307   /* stuffing bits, first two bits are '10' for mpeg2 pes so this code is
2308    * not triggered. */
2309   while (TRUE) {
2310     if (*data != 0xff)
2311       break;
2312     data++;
2313   }
2314
2315   /* STD buffer size, never for mpeg2 */
2316   if ((*data & 0xc0) == 0x40)
2317     data += 2;
2318
2319   /* PTS but no DTS, never for mpeg2 */
2320   if ((*data & 0xf0) == 0x20) {
2321     READ_TS (data, pts, beach);
2322   }
2323   /* PTS and DTS, never for mpeg2 */
2324   else if ((*data & 0xf0) == 0x30) {
2325     READ_TS (data, pts, beach);
2326     READ_TS (data, dts, beach);
2327   } else if ((*data & 0xc0) == 0x80) {
2328     /* mpeg2 case */
2329     guchar flags;
2330
2331     /* 2: '10'
2332      * 2: PES_scrambling_control
2333      * 1: PES_priority
2334      * 1: data_alignment_indicator
2335      * 1: copyright
2336      * 1: original_or_copy
2337      */
2338     flags = *data++;
2339
2340     if ((flags & 0xc0) != 0x80)
2341       goto beach;
2342
2343     /* 2: PTS_DTS_flags
2344      * 1: ESCR_flag
2345      * 1: ES_rate_flag
2346      * 1: DSM_trick_mode_flag
2347      * 1: additional_copy_info_flag
2348      * 1: PES_CRC_flag
2349      * 1: PES_extension_flag
2350      */
2351     flags = *data++;
2352
2353     /* 8: PES_header_data_length */
2354     data++;
2355
2356     /* only DTS: this is invalid */
2357     if ((flags & 0xc0) == 0x40)
2358       goto beach;
2359
2360     /* check for PTS */
2361     if ((flags & 0x80)) {
2362       READ_TS (data, pts, beach);
2363     }
2364     /* check for DTS */
2365     if ((flags & 0x40)) {
2366       READ_TS (data, dts, beach);
2367     }
2368   }
2369
2370   if (mode == SCAN_DTS && dts != -1) {
2371     *rts = dts;
2372     ret = TRUE;
2373   }
2374
2375   if (mode == SCAN_PTS && pts != -1) {
2376     *rts = pts;
2377     ret = TRUE;
2378   }
2379 beach:
2380   return ret;
2381 }
2382
2383 static inline gboolean
2384 gst_flups_demux_scan_forward_ts (GstFluPSDemux * demux, guint64 * pos,
2385     SCAN_MODE mode, guint64 * rts)
2386 {
2387   GstFlowReturn ret = GST_FLOW_OK;
2388   GstBuffer *buffer = NULL;
2389   guint64 offset = *pos;
2390   gboolean found = FALSE;
2391   guint64 ts = 0;
2392   guint scan_sz = (mode == SCAN_SCR ? SCAN_SCR_SZ : SCAN_PTS_SZ);
2393   guint cursor, to_read = BLOCK_SZ;
2394   guint8 *data;
2395   guint end_scan, data_size;
2396
2397   do {
2398     if (offset + scan_sz > demux->sink_segment.stop)
2399       return FALSE;
2400
2401     if (offset + to_read > demux->sink_segment.stop)
2402       to_read = demux->sink_segment.stop - offset;
2403
2404     /* read some data */
2405     ret = gst_pad_pull_range (demux->sinkpad, offset, to_read, &buffer);
2406     if (G_UNLIKELY (ret != GST_FLOW_OK))
2407       return FALSE;
2408
2409     /* may get a short buffer at the end of the file */
2410     data_size = GST_BUFFER_SIZE (buffer);
2411     if (G_UNLIKELY (data_size <= scan_sz))
2412       return FALSE;
2413
2414     data = GST_BUFFER_DATA (buffer);
2415     end_scan = data_size - scan_sz;
2416
2417     /* scan the block */
2418     for (cursor = 0; !found && cursor <= end_scan; cursor++) {
2419       found = gst_flups_demux_scan_ts (demux, data++, mode, &ts);
2420     }
2421
2422     /* done with the buffer, unref it */
2423     gst_buffer_unref (buffer);
2424
2425     if (found) {
2426       *rts = ts;
2427       *pos = offset + cursor - 1;
2428     } else {
2429       offset += cursor;
2430     }
2431   } while (!found && offset < demux->sink_segment.stop);
2432
2433   return found;
2434 }
2435
2436 static inline gboolean
2437 gst_flups_demux_scan_backward_ts (GstFluPSDemux * demux, guint64 * pos,
2438     SCAN_MODE mode, guint64 * rts)
2439 {
2440   GstFlowReturn ret = GST_FLOW_OK;
2441   GstBuffer *buffer = NULL;
2442   guint64 offset = *pos;
2443   gboolean found = FALSE;
2444   guint64 ts = 0;
2445   guint scan_sz = (mode == SCAN_SCR ? SCAN_SCR_SZ : SCAN_PTS_SZ);
2446   guint cursor, to_read = BLOCK_SZ;
2447   guint start_scan, data_size;
2448   guint8 *data;
2449
2450   do {
2451     if (offset < scan_sz - 1)
2452       return FALSE;
2453
2454     if (offset > BLOCK_SZ)
2455       offset -= BLOCK_SZ;
2456     else {
2457       to_read = offset + 1;
2458       offset = 0;
2459     }
2460     /* read some data */
2461     ret = gst_pad_pull_range (demux->sinkpad, offset, to_read, &buffer);
2462     if (G_UNLIKELY (ret != GST_FLOW_OK))
2463       return FALSE;
2464
2465     /* may get a short buffer at the end of the file */
2466     data_size = GST_BUFFER_SIZE (buffer);
2467     if (G_UNLIKELY (data_size <= scan_sz))
2468       return FALSE;
2469
2470     start_scan = data_size - scan_sz;
2471     data = GST_BUFFER_DATA (buffer) + start_scan;
2472
2473     /* scan the block */
2474     for (cursor = (start_scan + 1); !found && cursor > 0; cursor--) {
2475       found = gst_flups_demux_scan_ts (demux, data--, mode, &ts);
2476     }
2477
2478     /* done with the buffer, unref it */
2479     gst_buffer_unref (buffer);
2480
2481     if (found) {
2482       *rts = ts;
2483       *pos = offset + cursor;
2484     }
2485
2486   } while (!found && offset > 0);
2487
2488   return found;
2489 }
2490
2491 static inline gboolean
2492 gst_flups_sink_get_duration (GstFluPSDemux * demux)
2493 {
2494   gboolean res = FALSE;
2495   GstPad *peer;
2496   GstFormat format = GST_FORMAT_BYTES;
2497   gint64 length = 0;
2498   guint64 offset;
2499   guint i;
2500   guint64 scr = 0;
2501
2502   /* init the sink segment */
2503   gst_segment_init (&demux->sink_segment, format);
2504
2505   /* get peer to figure out length */
2506   if ((peer = gst_pad_get_peer (demux->sinkpad)) == NULL)
2507     goto beach;
2508
2509   res = gst_pad_query_duration (peer, &format, &length);
2510   gst_object_unref (peer);
2511
2512   if (!res || length <= 0)
2513     goto beach;
2514
2515   GST_DEBUG_OBJECT (demux, "file length %" G_GINT64_FORMAT, length);
2516
2517   /* update the sink segment */
2518   demux->sink_segment.stop = length;
2519   gst_segment_set_duration (&demux->sink_segment, format, length);
2520   gst_segment_set_last_stop (&demux->sink_segment, format, 0);
2521
2522   /* Scan for notorious SCR and PTS to calculate the duration */
2523   /* scan for first SCR in the stream */
2524   offset = demux->sink_segment.start;
2525   gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_SCR, &demux->first_scr);
2526   GST_DEBUG_OBJECT (demux, "First SCR: %" G_GINT64_FORMAT " %" GST_TIME_FORMAT
2527       " in packet starting at %" G_GUINT64_FORMAT,
2528       demux->first_scr, GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->first_scr)),
2529       offset);
2530   demux->first_scr_offset = offset;
2531   /* scan for last SCR in the stream */
2532   offset = demux->sink_segment.stop;
2533   gst_flups_demux_scan_backward_ts (demux, &offset, SCAN_SCR, &demux->last_scr);
2534   GST_DEBUG_OBJECT (demux, "Last SCR: %" G_GINT64_FORMAT " %" GST_TIME_FORMAT
2535       " in packet starting at %" G_GUINT64_FORMAT,
2536       demux->last_scr, GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->last_scr)),
2537       offset);
2538   demux->last_scr_offset = offset;
2539   /* scan for first PTS in the stream */
2540   offset = demux->sink_segment.start;
2541   gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_PTS, &demux->first_pts);
2542   GST_DEBUG_OBJECT (demux, "First PTS: %" G_GINT64_FORMAT " %" GST_TIME_FORMAT
2543       " in packet starting at %" G_GUINT64_FORMAT,
2544       demux->first_pts, GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->first_pts)),
2545       offset);
2546   if (demux->first_pts != G_MAXUINT64) {
2547     /* scan for last PTS in the stream */
2548     offset = demux->sink_segment.stop;
2549     gst_flups_demux_scan_backward_ts (demux, &offset, SCAN_PTS,
2550         &demux->last_pts);
2551     GST_DEBUG_OBJECT (demux,
2552         "Last PTS: %" G_GINT64_FORMAT " %" GST_TIME_FORMAT
2553         " in packet starting at %" G_GUINT64_FORMAT, demux->last_pts,
2554         GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->last_pts)), offset);
2555   }
2556   /* Detect wrong SCR values */
2557   if (demux->first_scr > demux->last_scr) {
2558     GST_DEBUG_OBJECT (demux, "Wrong SCR values detected, searching for "
2559         "a better first SCR value");
2560     offset = demux->first_scr_offset;
2561     for (i = 0; i < 10; i++) {
2562       offset++;
2563       gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_SCR, &scr);
2564       if (scr < demux->last_scr) {
2565         demux->first_scr = scr;
2566         demux->first_scr_offset = offset;
2567         /* Start demuxing from the right place */
2568         demux->sink_segment.last_stop = offset;
2569         GST_DEBUG_OBJECT (demux, "Replaced First SCR: %" G_GINT64_FORMAT
2570             " %" GST_TIME_FORMAT " in packet starting at %" G_GUINT64_FORMAT,
2571             demux->first_scr,
2572             GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->first_scr)), offset);
2573         break;
2574       }
2575     }
2576   }
2577   /* Set the base_time and avg rate */
2578   demux->base_time = MPEGTIME_TO_GSTTIME (demux->first_scr);
2579   demux->scr_rate_n = demux->last_scr_offset - demux->first_scr_offset;
2580   demux->scr_rate_d = demux->last_scr - demux->first_scr;
2581
2582   if (G_LIKELY (demux->first_pts != G_MAXUINT64 &&
2583           demux->last_pts != G_MAXUINT64)) {
2584     /* update the src segment */
2585     demux->src_segment.start =
2586         MPEGTIME_TO_GSTTIME (demux->first_pts) - demux->base_time;
2587     demux->src_segment.stop = -1;
2588     gst_segment_set_duration (&demux->src_segment, GST_FORMAT_TIME,
2589         MPEGTIME_TO_GSTTIME (demux->last_pts - demux->first_pts));
2590     gst_segment_set_last_stop (&demux->src_segment, GST_FORMAT_TIME,
2591         demux->src_segment.start);
2592   }
2593   GST_INFO_OBJECT (demux, "sink segment configured %" GST_SEGMENT_FORMAT,
2594       &demux->sink_segment);
2595   GST_INFO_OBJECT (demux, "src segment configured %" GST_SEGMENT_FORMAT,
2596       &demux->src_segment);
2597
2598   res = TRUE;
2599
2600 beach:
2601   return res;
2602 }
2603
2604 static inline GstFlowReturn
2605 gst_flups_demux_pull_block (GstPad * pad, GstFluPSDemux * demux,
2606     guint64 offset, guint size)
2607 {
2608   GstFlowReturn ret = GST_FLOW_OK;
2609   GstBuffer *buffer;
2610   ret = gst_pad_pull_range (pad, offset, size, &buffer);
2611   if (G_UNLIKELY (ret != GST_FLOW_OK)) {
2612     GST_DEBUG_OBJECT (demux, "pull range at %" G_GUINT64_FORMAT
2613         " size %u failed", offset, size);
2614     goto beach;
2615   } else
2616     GST_LOG_OBJECT (demux, "pull range at %" G_GUINT64_FORMAT
2617         " size %u done", offset, size);
2618
2619   if (demux->sink_segment.rate < 0) {
2620     GST_LOG_OBJECT (demux, "setting discont flag on backward rate");
2621     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
2622   }
2623   ret = gst_flups_demux_chain (pad, buffer);
2624
2625 beach:
2626   return ret;
2627 }
2628
2629 static void
2630 gst_flups_demux_loop (GstPad * pad)
2631 {
2632   GstFluPSDemux *demux;
2633   GstFlowReturn ret = GST_FLOW_OK;
2634   guint64 offset = 0;
2635
2636   demux = GST_FLUPS_DEMUX (gst_pad_get_parent (pad));
2637
2638   if (G_UNLIKELY (demux->flushing)) {
2639     ret = GST_FLOW_WRONG_STATE;
2640     goto pause;
2641   }
2642
2643   if (G_UNLIKELY (demux->sink_segment.format == GST_FORMAT_UNDEFINED))
2644     gst_flups_sink_get_duration (demux);
2645
2646   offset = demux->sink_segment.last_stop;
2647   if (demux->sink_segment.rate >= 0) {
2648     guint size = BLOCK_SZ;
2649     if (G_LIKELY (demux->sink_segment.stop != -1)) {
2650       size = MIN (size, demux->sink_segment.stop - offset);
2651     }
2652     /* pull in data */
2653     ret = gst_flups_demux_pull_block (pad, demux, offset, size);
2654
2655     /* pause if something went wrong */
2656     if (G_UNLIKELY (ret != GST_FLOW_OK))
2657       goto pause;
2658
2659     /* update our position */
2660     offset += size;
2661     gst_segment_set_last_stop (&demux->sink_segment, GST_FORMAT_BYTES, offset);
2662
2663     /* check EOS condition */
2664     if ((demux->src_segment.flags & GST_SEEK_FLAG_SEGMENT) &&
2665         ((demux->sink_segment.last_stop >= demux->sink_segment.stop) ||
2666             (demux->src_segment.stop != -1 &&
2667                 demux->src_segment.last_stop >= demux->src_segment.stop))) {
2668       GST_DEBUG_OBJECT (demux, "forward mode using segment reached end of "
2669           "segment pos %" GST_TIME_FORMAT " stop %" GST_TIME_FORMAT
2670           " pos in bytes %" G_GUINT64_FORMAT " stop in bytes %"
2671           G_GUINT64_FORMAT, GST_TIME_ARGS (demux->src_segment.last_stop),
2672           GST_TIME_ARGS (demux->src_segment.stop),
2673           demux->sink_segment.last_stop, demux->sink_segment.stop);
2674       ret = GST_FLOW_UNEXPECTED;
2675       goto pause;
2676     }
2677   } else {                      /* Reverse playback */
2678     guint64 size = MIN (offset, BLOCK_SZ);
2679
2680     /* pull in data */
2681     ret = gst_flups_demux_pull_block (pad, demux, offset - size, size);
2682
2683     /* pause if something went wrong */
2684     if (G_UNLIKELY (ret != GST_FLOW_OK))
2685       goto pause;
2686
2687     /* update our position */
2688     offset -= size;
2689     gst_segment_set_last_stop (&demux->sink_segment, GST_FORMAT_BYTES, offset);
2690
2691     /* check EOS condition */
2692     if (demux->sink_segment.last_stop <= demux->sink_segment.start ||
2693         demux->src_segment.last_stop <= demux->src_segment.start) {
2694       GST_DEBUG_OBJECT (demux, "reverse mode using segment reached end of "
2695           "segment pos %" GST_TIME_FORMAT " stop %" GST_TIME_FORMAT
2696           " pos in bytes %" G_GUINT64_FORMAT " stop in bytes %"
2697           G_GUINT64_FORMAT, GST_TIME_ARGS (demux->src_segment.last_stop),
2698           GST_TIME_ARGS (demux->src_segment.start),
2699           demux->sink_segment.last_stop, demux->sink_segment.start);
2700       ret = GST_FLOW_UNEXPECTED;
2701       goto pause;
2702     }
2703   }
2704
2705   gst_object_unref (demux);
2706
2707   return;
2708
2709 pause:
2710   {
2711     const gchar *reason = gst_flow_get_name (ret);
2712
2713     GST_LOG_OBJECT (demux, "pausing task, reason %s", reason);
2714     gst_pad_pause_task (pad);
2715
2716     if (ret == GST_FLOW_UNEXPECTED) {
2717       /* perform EOS logic */
2718       gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
2719       if (demux->src_segment.flags & GST_SEEK_FLAG_SEGMENT) {
2720         gint64 stop;
2721
2722         /* for segment playback we need to post when (in stream time)
2723          * we stopped, this is either stop (when set) or the duration. */
2724         if ((stop = demux->src_segment.stop) == -1)
2725           stop = demux->src_segment.duration;
2726
2727         if (demux->sink_segment.rate >= 0) {
2728           GST_LOG_OBJECT (demux, "Sending segment done, at end of segment");
2729           gst_element_post_message (GST_ELEMENT_CAST (demux),
2730               gst_message_new_segment_done (GST_OBJECT_CAST (demux),
2731                   GST_FORMAT_TIME, stop));
2732         } else {                /* Reverse playback */
2733           GST_LOG_OBJECT (demux, "Sending segment done, at beginning of "
2734               "segment");
2735           gst_element_post_message (GST_ELEMENT_CAST (demux),
2736               gst_message_new_segment_done (GST_OBJECT_CAST (demux),
2737                   GST_FORMAT_TIME, demux->src_segment.start));
2738         }
2739       } else {
2740         /* normal playback, send EOS to all linked pads */
2741         gst_element_no_more_pads (GST_ELEMENT (demux));
2742         GST_LOG_OBJECT (demux, "Sending EOS, at end of stream");
2743         if (!gst_flups_demux_send_event (demux, gst_event_new_eos ())
2744             && !have_open_streams (demux)) {
2745           GST_WARNING_OBJECT (demux, "EOS and no streams open");
2746           GST_ELEMENT_ERROR (demux, STREAM, FAILED,
2747               ("Internal data stream error."), ("No valid streams detected"));
2748         }
2749       }
2750     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_UNEXPECTED) {
2751       GST_ELEMENT_ERROR (demux, STREAM, FAILED,
2752           ("Internal data stream error."),
2753           ("stream stopped, reason %s", reason));
2754       gst_flups_demux_send_event (demux, gst_event_new_eos ());
2755     }
2756
2757     gst_object_unref (demux);
2758     return;
2759   }
2760 }
2761
2762 /* If we can pull that's prefered */
2763 static gboolean
2764 gst_flups_demux_sink_activate (GstPad * sinkpad)
2765 {
2766   if (gst_pad_check_pull_range (sinkpad)) {
2767     return gst_pad_activate_pull (sinkpad, TRUE);
2768   } else {
2769     return gst_pad_activate_push (sinkpad, TRUE);
2770   }
2771 }
2772
2773 /* This function gets called when we activate ourselves in push mode. */
2774 static gboolean
2775 gst_flups_demux_sink_activate_push (GstPad * sinkpad, gboolean active)
2776 {
2777   GstFluPSDemux *demux;
2778
2779   demux = GST_FLUPS_DEMUX (gst_pad_get_parent (sinkpad));
2780
2781   demux->random_access = FALSE;
2782
2783   gst_object_unref (demux);
2784
2785   return TRUE;
2786 }
2787
2788 /* this function gets called when we activate ourselves in pull mode.
2789  * We can perform  random access to the resource and we start a task
2790  * to start reading */
2791 static gboolean
2792 gst_flups_demux_sink_activate_pull (GstPad * sinkpad, gboolean active)
2793 {
2794   GstFluPSDemux *demux;
2795
2796   demux = GST_FLUPS_DEMUX (gst_pad_get_parent (sinkpad));
2797
2798   if (active) {
2799     GST_DEBUG ("pull mode activated");
2800     demux->random_access = TRUE;
2801     gst_object_unref (demux);
2802     return gst_pad_start_task (sinkpad, (GstTaskFunction) gst_flups_demux_loop,
2803         sinkpad);
2804   } else {
2805     demux->random_access = FALSE;
2806     gst_object_unref (demux);
2807     return gst_pad_stop_task (sinkpad);
2808   }
2809 }
2810
2811 static GstFlowReturn
2812 gst_flups_demux_chain (GstPad * pad, GstBuffer * buffer)
2813 {
2814   GstFluPSDemux *demux = GST_FLUPS_DEMUX (gst_pad_get_parent (pad));
2815   GstFlowReturn ret = GST_FLOW_OK;
2816   guint32 avail;
2817   gboolean save, discont;
2818
2819   discont = GST_BUFFER_IS_DISCONT (buffer);
2820
2821   if (discont) {
2822     GST_LOG_OBJECT (demux, "Received buffer with discont flag and"
2823         " offset %" G_GUINT64_FORMAT, GST_BUFFER_OFFSET (buffer));
2824
2825     gst_pes_filter_drain (&demux->filter);
2826     gst_flups_demux_mark_discont (demux, TRUE, FALSE);
2827
2828     /* mark discont on all streams */
2829     if (demux->sink_segment.rate >= 0.0) {
2830       demux->current_scr = G_MAXUINT64;
2831       demux->bytes_since_scr = 0;
2832     }
2833   } else {
2834     GST_LOG_OBJECT (demux, "Received buffer with offset %" G_GUINT64_FORMAT,
2835         GST_BUFFER_OFFSET (buffer));
2836   }
2837
2838   /* We keep the offset to interpolate SCR */
2839   demux->adapter_offset = GST_BUFFER_OFFSET (buffer);
2840
2841   gst_adapter_push (demux->adapter, buffer);
2842   demux->bytes_since_scr += GST_BUFFER_SIZE (buffer);
2843
2844   avail = gst_adapter_available (demux->rev_adapter);
2845   if (avail > 0) {
2846     GST_LOG_OBJECT (demux, "appending %u saved bytes", avail);
2847     /* if we have a previous reverse chunk, append this now */
2848     /* FIXME this code assumes we receive discont buffers all thei
2849      * time */
2850     gst_adapter_push (demux->adapter,
2851         gst_adapter_take_buffer (demux->rev_adapter, avail));
2852   }
2853
2854   avail = gst_adapter_available (demux->adapter);
2855   GST_LOG_OBJECT (demux, "avail now: %d, state %d", avail, demux->filter.state);
2856
2857   switch (demux->filter.state) {
2858     case STATE_DATA_SKIP:
2859     case STATE_DATA_PUSH:
2860       ret = gst_pes_filter_process (&demux->filter);
2861       break;
2862     case STATE_HEADER_PARSE:
2863       break;
2864     default:
2865       break;
2866   }
2867
2868   switch (ret) {
2869     case GST_FLOW_NEED_MORE_DATA:
2870       /* Go and get more data */
2871       ret = GST_FLOW_OK;
2872       goto done;
2873     case GST_FLOW_LOST_SYNC:
2874       /* for FLOW_OK or lost-sync, carry onto resync */
2875       ret = GST_FLOW_OK;
2876       break;
2877     case GST_FLOW_OK:
2878       break;
2879     default:
2880       /* Any other return value should be sent upstream immediately */
2881       goto done;
2882   }
2883
2884   /* align adapter data to sync boundary, we keep the data up to the next sync
2885    * point. */
2886   save = TRUE;
2887   while (gst_flups_demux_resync (demux, save)) {
2888     gboolean ps_sync = TRUE;
2889     if (G_UNLIKELY (demux->flushing)) {
2890       ret = GST_FLOW_WRONG_STATE;
2891       goto done;
2892     }
2893
2894     /* now switch on last synced byte */
2895     switch (demux->last_sync_code) {
2896       case ID_PS_PACK_START_CODE:
2897         ret = gst_flups_demux_parse_pack_start (demux);
2898         break;
2899       case ID_PS_SYSTEM_HEADER_START_CODE:
2900         ret = gst_flups_demux_parse_sys_head (demux);
2901         break;
2902       case ID_PS_END_CODE:
2903         ret = GST_FLOW_OK;
2904         goto done;
2905       case ID_PS_PROGRAM_STREAM_MAP:
2906         ret = gst_flups_demux_parse_psm (demux);
2907         break;
2908       default:
2909         if (gst_flups_demux_is_pes_sync (demux->last_sync_code)) {
2910           ret = gst_pes_filter_process (&demux->filter);
2911         } else {
2912           GST_DEBUG_OBJECT (demux, "sync_code=%08x, non PES sync found"
2913               ", continuing", demux->last_sync_code);
2914           ps_sync = FALSE;
2915           ret = GST_FLOW_LOST_SYNC;
2916         }
2917         break;
2918     }
2919     /* if we found a ps sync, we stop saving the data, any non-ps sync gets
2920      * saved up to the next ps sync. */
2921     if (ps_sync)
2922       save = FALSE;
2923
2924     switch (ret) {
2925       case GST_FLOW_NEED_MORE_DATA:
2926         GST_DEBUG_OBJECT (demux, "need more data");
2927         ret = GST_FLOW_OK;
2928         goto done;
2929       case GST_FLOW_LOST_SYNC:
2930         if (!save || demux->sink_segment.rate >= 0.0) {
2931           GST_DEBUG_OBJECT (demux, "flushing 3 bytes");
2932           gst_adapter_flush (demux->adapter, 3);
2933           ADAPTER_OFFSET_FLUSH (3);
2934         } else {
2935           GST_DEBUG_OBJECT (demux, "saving 3 bytes");
2936           gst_adapter_push (demux->rev_adapter,
2937               gst_adapter_take_buffer (demux->adapter, 3));
2938         }
2939         ret = GST_FLOW_OK;
2940         break;
2941       default:
2942         break;
2943     }
2944   }
2945 done:
2946   gst_object_unref (demux);
2947
2948   return ret;
2949 }
2950
2951 static GstStateChangeReturn
2952 gst_flups_demux_change_state (GstElement * element, GstStateChange transition)
2953 {
2954   GstFluPSDemux *demux = GST_FLUPS_DEMUX (element);
2955   GstStateChangeReturn result;
2956
2957   switch (transition) {
2958     case GST_STATE_CHANGE_NULL_TO_READY:
2959       demux->adapter = gst_adapter_new ();
2960       demux->rev_adapter = gst_adapter_new ();
2961       demux->adapter_offset = G_MAXUINT64;
2962       gst_pes_filter_init (&demux->filter, demux->adapter,
2963           &demux->adapter_offset);
2964       gst_pes_filter_set_callbacks (&demux->filter,
2965           (GstPESFilterData) gst_flups_demux_data_cb,
2966           (GstPESFilterResync) gst_flups_demux_resync_cb, demux);
2967       demux->filter.gather_pes = TRUE;
2968       demux->first_scr = G_MAXUINT64;
2969       demux->last_scr = G_MAXUINT64;
2970       demux->current_scr = G_MAXUINT64;
2971       demux->base_time = G_MAXUINT64;
2972       demux->scr_rate_n = G_MAXUINT64;
2973       demux->scr_rate_d = G_MAXUINT64;
2974       demux->first_pts = G_MAXUINT64;
2975       demux->last_pts = G_MAXUINT64;
2976       break;
2977     case GST_STATE_CHANGE_READY_TO_PAUSED:
2978       demux->current_scr = G_MAXUINT64;
2979       demux->mux_rate = G_MAXUINT64;
2980       demux->next_pts = G_MAXUINT64;
2981       demux->next_dts = G_MAXUINT64;
2982       demux->first_scr = G_MAXUINT64;
2983       demux->last_scr = G_MAXUINT64;
2984       demux->base_time = G_MAXUINT64;
2985       demux->scr_rate_n = G_MAXUINT64;
2986       demux->scr_rate_d = G_MAXUINT64;
2987       demux->need_no_more_pads = TRUE;
2988       demux->first_pts = G_MAXUINT64;
2989       demux->last_pts = G_MAXUINT64;
2990       gst_flups_demux_reset_psm (demux);
2991       gst_segment_init (&demux->sink_segment, GST_FORMAT_UNDEFINED);
2992       gst_segment_init (&demux->src_segment, GST_FORMAT_TIME);
2993       gst_flups_demux_flush (demux);
2994       break;
2995     default:
2996       break;
2997   }
2998
2999   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
3000
3001   switch (transition) {
3002     case GST_STATE_CHANGE_PAUSED_TO_READY:
3003       gst_flups_demux_reset (demux);
3004       break;
3005     case GST_STATE_CHANGE_READY_TO_NULL:
3006       gst_pes_filter_uninit (&demux->filter);
3007       g_object_unref (demux->adapter);
3008       demux->adapter = NULL;
3009       g_object_unref (demux->rev_adapter);
3010       demux->rev_adapter = NULL;
3011       break;
3012     default:
3013       break;
3014   }
3015
3016   return result;
3017 }
3018
3019 gboolean
3020 gst_flups_demux_plugin_init (GstPlugin * plugin)
3021 {
3022   if (!gst_element_register (plugin, "mpegpsdemux",
3023           GST_RANK_PRIMARY, GST_TYPE_FLUPS_DEMUX))
3024     return FALSE;
3025
3026   return TRUE;
3027 }