baseparse: introduce a baseparse frame to serve as context
[gstreamer-omap:gstreamer.git] / gst / audioparsers / gstbaseparse.c
1 /* GStreamer
2  * Copyright (C) 2008 Nokia Corporation. All rights reserved.
3  *   Contact: Stefan Kost <stefan.kost@nokia.com>
4  * Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 /**
23  * SECTION:gstbaseparse
24  * @short_description: Base class for stream parsers
25  * @see_also: #GstBaseTransform
26  *
27  * This base class is for parser elements that process data and splits it 
28  * into separate audio/video/whatever frames.
29  *
30  * It provides for:
31  * <itemizedlist>
32  *   <listitem><para>One sinkpad and one srcpad</para></listitem>
33  *   <listitem><para>Handles state changes</para></listitem>
34  *   <listitem><para>Does flushing</para></listitem>
35  *   <listitem><para>Push mode</para></listitem>
36  *   <listitem><para>Pull mode</para></listitem>
37  *   <listitem><para>Handles events (NEWSEGMENT/EOS/FLUSH)</para></listitem>
38  *   <listitem><para>Handles seeking in both modes</para></listitem>
39  *   <listitem><para>
40  *        Handles POSITION/DURATION/SEEKING/FORMAT/CONVERT queries
41  *   </para></listitem>
42  * </itemizedlist>
43  *
44  * The purpose of this base class is to provide a basic functionality of
45  * a parser and share a lot of rather complex code.
46  *
47  * Description of the parsing mechanism:
48  * <orderedlist>
49  * <listitem>
50  *   <itemizedlist><title>Set-up phase</title>
51  *   <listitem><para>
52  *     GstBaseParse class calls @set_sink_caps to inform the subclass about
53  *     incoming sinkpad caps. Subclass should set the srcpad caps accordingly.
54  *   </para></listitem>
55  *   <listitem><para>
56  *     GstBaseParse calls @start to inform subclass that data processing is
57  *     about to start now.
58  *   </para></listitem>
59  *   <listitem><para>
60  *      At least in this point subclass needs to tell the GstBaseParse class
61  *      how big data chunks it wants to receive (min_frame_size). It can do 
62  *      this with @gst_base_parse_set_min_frame_size.
63  *   </para></listitem>
64  *   <listitem><para>
65  *      GstBaseParse class sets up appropriate data passing mode (pull/push)
66  *      and starts to process the data.
67  *   </para></listitem>
68  *   </itemizedlist>
69  * </listitem>
70  * <listitem>
71  *   <itemizedlist>
72  *   <title>Parsing phase</title>
73  *     <listitem><para>
74  *       GstBaseParse gathers at least min_frame_size bytes of data either 
75  *       by pulling it from upstream or collecting buffers into internal
76  *       #GstAdapter.
77  *     </para></listitem>
78  *     <listitem><para>
79  *       A buffer of (at least) min_frame_size bytes is passed to subclass with
80  *       @check_valid_frame. Subclass checks the contents and returns TRUE
81  *       if the buffer contains a valid frame. It also needs to set the
82  *       @framesize according to the detected frame size. If buffer didn't
83  *       contain a valid frame, this call must return FALSE and optionally
84  *       set the @skipsize value to inform base class that how many bytes
85  *       it needs to skip in order to find a valid frame. @framesize can always
86  *       indicate a new minimum for current frame parsing.  The passed buffer
87  *       is read-only.  Note that @check_valid_frame might receive any small
88  *       amount of input data when leftover data is being drained (e.g. at EOS).
89  *     </para></listitem>
90  *     <listitem><para>
91  *       After valid frame is found, it will be passed again to subclass with
92  *       @parse_frame call. Now subclass is responsible for parsing the
93  *       frame contents and setting the caps, and buffer metadata (e.g.
94  *       buffer timestamp and duration, or keyframe if applicable).
95  *       (although the latter can also be done by GstBaseParse if it is
96  *       appropriately configured, see below).
97  *     </para></listitem>
98  *     <listitem><para>
99  *       Finally the buffer can be pushed downstream and parsing loop starts
100  *       over again.  Just prior to actually pushing the buffer in question,
101  *       it is passed to @pre_push_buffer which gives subclass yet one
102  *       last chance to examine buffer metadata, or to send some custom (tag)
103  *       events, or to perform custom (segment) filtering.
104  *     </para></listitem>
105  *     <listitem><para>
106  *       During the parsing process GstBaseParseClass will handle both srcpad and
107  *       sinkpad events. They will be passed to subclass if @event or
108  *       @src_event callbacks have been provided.
109  *     </para></listitem>
110  *   </itemizedlist>
111  * </listitem>
112  * <listitem>
113  *   <itemizedlist><title>Shutdown phase</title>
114  *   <listitem><para>
115  *     GstBaseParse class calls @stop to inform the subclass that data
116  *     parsing will be stopped.
117  *   </para></listitem>
118  *   </itemizedlist>
119  * </listitem>
120  * </orderedlist>
121  *
122  * Subclass is responsible for providing pad template caps for
123  * source and sink pads. The pads need to be named "sink" and "src". It also 
124  * needs to set the fixed caps on srcpad, when the format is ensured (e.g. 
125  * when base class calls subclass' @set_sink_caps function).
126  *
127  * This base class uses GST_FORMAT_DEFAULT as a meaning of frames. So,
128  * subclass conversion routine needs to know that conversion from
129  * GST_FORMAT_TIME to GST_FORMAT_DEFAULT must return the
130  * frame number that can be found from the given byte position.
131  *
132  * GstBaseParse uses subclasses conversion methods also for seeking (or otherwise
133  * uses its own default one, see also below).
134  *
135  * Subclass @start and @stop functions will be called to inform the beginning
136  * and end of data processing.
137  *
138  * Things that subclass need to take care of:
139  * <itemizedlist>
140  *   <listitem><para>Provide pad templates</para></listitem>
141  *   <listitem><para>
142  *      Fixate the source pad caps when appropriate
143  *   </para></listitem>
144  *   <listitem><para>
145  *      Inform base class how big data chunks should be retrieved. This is
146  *      done with @gst_base_parse_set_min_frame_size function.
147  *   </para></listitem>
148  *   <listitem><para>
149  *      Examine data chunks passed to subclass with @check_valid_frame
150  *      and tell if they contain a valid frame
151  *   </para></listitem>
152  *   <listitem><para>
153  *      Set the caps and timestamp to frame that is passed to subclass with
154  *      @parse_frame function.
155  *   </para></listitem>
156  *   <listitem><para>Provide conversion functions</para></listitem>
157  *   <listitem><para>
158  *      Update the duration information with @gst_base_parse_set_duration
159  *   </para></listitem>
160  *   <listitem><para>
161  *      Optionally passthrough using @gst_base_parse_set_passthrough
162  *   </para></listitem>
163  *   <listitem><para>
164  *      Configure various baseparse parameters using @gst_base_parse_set_seek and
165  *      @gst_base_parse_set_frame_props.
166  *   </para></listitem>
167  *   <listitem><para>
168  *      In particular, if subclass is unable to determine a duration, but
169  *      parsing (or specs) yields a frames per seconds rate, then this can be
170  *      provided to GstBaseParse to enable it to cater for
171  *      buffer time metadata (which will be taken from upstream as much as possible).
172  *      Internally keeping track of frame durations and respective
173  *      sizes that have been pushed provides GstBaseParse with an estimated bitrate.
174  *      A default @convert (used if not overriden) will then use these
175  *      rates to perform obvious conversions.  These rates are also used to update
176  *      (estimated) duration at regular frame intervals.
177  *   </para></listitem>
178  * </itemizedlist>
179  *
180  */
181
182 /* TODO:
183  *  - In push mode provide a queue of adapter-"queued" buffers for upstream
184  *    buffer metadata
185  *  - Queue buffers/events until caps are set
186  */
187
188 #ifdef HAVE_CONFIG_H
189 #  include "config.h"
190 #endif
191
192 #include <stdlib.h>
193 #include <string.h>
194
195 #include "gstbaseparse.h"
196
197 #define MIN_FRAMES_TO_POST_BITRATE 10
198 #define TARGET_DIFFERENCE          (20 * GST_SECOND)
199
200 GST_DEBUG_CATEGORY_STATIC (gst_base_parse_debug);
201 #define GST_CAT_DEFAULT gst_base_parse_debug
202
203 /* Supported formats */
204 static GstFormat fmtlist[] = {
205   GST_FORMAT_DEFAULT,
206   GST_FORMAT_BYTES,
207   GST_FORMAT_TIME,
208   0
209 };
210
211 #define GST_BASE_PARSE_GET_PRIVATE(obj)  \
212     (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BASE_PARSE, GstBaseParsePrivate))
213
214 struct _GstBaseParsePrivate
215 {
216   GstActivateMode pad_mode;
217
218   gint64 duration;
219   GstFormat duration_fmt;
220   gint64 estimated_duration;
221
222   guint min_frame_size;
223   gboolean passthrough;
224   guint fps_num, fps_den;
225   guint update_interval;
226   guint bitrate;
227   guint lead_in, lead_out;
228   GstClockTime lead_in_ts, lead_out_ts;
229   GstBaseParseSeekable seekable;
230
231   gboolean discont;
232   gboolean flushing;
233   gboolean drain;
234
235   gint64 offset;
236   gint64 sync_offset;
237   GstClockTime next_ts;
238   GstClockTime prev_ts;
239   GstClockTime frame_duration;
240   gboolean seen_keyframe;
241   gboolean is_video;
242
243   guint64 framecount;
244   guint64 bytecount;
245   guint64 data_bytecount;
246   guint64 acc_duration;
247   GstClockTime first_frame_ts;
248   gint64 first_frame_offset;
249
250   gboolean post_min_bitrate;
251   gboolean post_avg_bitrate;
252   gboolean post_max_bitrate;
253   guint min_bitrate;
254   guint avg_bitrate;
255   guint max_bitrate;
256   guint posted_avg_bitrate;
257
258   GList *pending_events;
259
260   GstBuffer *cache;
261
262   /* index entry storage, either ours or provided */
263   GstIndex *index;
264   gint index_id;
265   gboolean own_index;
266   /* seek table entries only maintained if upstream is BYTE seekable */
267   gboolean upstream_seekable;
268   gboolean upstream_has_duration;
269   gint64 upstream_size;
270   /* minimum distance between two index entries */
271   GstClockTimeDiff idx_interval;
272   /* ts and offset of last entry added */
273   GstClockTime index_last_ts;
274   guint64 index_last_offset;
275   gboolean index_last_valid;
276
277   /* timestamps currently produced are accurate, e.g. started from 0 onwards */
278   gboolean exact_position;
279   /* seek events are temporarily kept to match them with newsegments */
280   GSList *pending_seeks;
281
282   /* reverse playback */
283   GSList *buffers_pending;
284   GSList *buffers_queued;
285   GstClockTime last_ts;
286   gint64 last_offset;
287 };
288
289 typedef struct _GstBaseParseSeek
290 {
291   GstSegment segment;
292   gboolean accurate;
293   gint64 offset;
294   GstClockTime start_ts;
295 } GstBaseParseSeek;
296
297 static GstElementClass *parent_class = NULL;
298
299 static void gst_base_parse_class_init (GstBaseParseClass * klass);
300 static void gst_base_parse_init (GstBaseParse * parse,
301     GstBaseParseClass * klass);
302
303 GType
304 gst_base_parse_get_type (void)
305 {
306   static GType base_parse_type = 0;
307
308   if (!base_parse_type) {
309     static const GTypeInfo base_parse_info = {
310       sizeof (GstBaseParseClass),
311       (GBaseInitFunc) NULL,
312       (GBaseFinalizeFunc) NULL,
313       (GClassInitFunc) gst_base_parse_class_init,
314       NULL,
315       NULL,
316       sizeof (GstBaseParse),
317       0,
318       (GInstanceInitFunc) gst_base_parse_init,
319     };
320
321     base_parse_type = g_type_register_static (GST_TYPE_ELEMENT,
322         "GstAudioBaseParseBad", &base_parse_info, G_TYPE_FLAG_ABSTRACT);
323   }
324   return base_parse_type;
325 }
326
327 static void gst_base_parse_finalize (GObject * object);
328
329 static GstStateChangeReturn gst_base_parse_change_state (GstElement * element,
330     GstStateChange transition);
331 static void gst_base_parse_reset (GstBaseParse * parse);
332
333 static void gst_base_parse_set_index (GstElement * element, GstIndex * index);
334 static GstIndex *gst_base_parse_get_index (GstElement * element);
335
336 static gboolean gst_base_parse_sink_activate (GstPad * sinkpad);
337 static gboolean gst_base_parse_sink_activate_push (GstPad * pad,
338     gboolean active);
339 static gboolean gst_base_parse_sink_activate_pull (GstPad * pad,
340     gboolean active);
341 static gboolean gst_base_parse_handle_seek (GstBaseParse * parse,
342     GstEvent * event);
343 static void gst_base_parse_handle_tag (GstBaseParse * parse, GstEvent * event);
344
345 static gboolean gst_base_parse_src_event (GstPad * pad, GstEvent * event);
346 static gboolean gst_base_parse_sink_event (GstPad * pad, GstEvent * event);
347 static gboolean gst_base_parse_query (GstPad * pad, GstQuery * query);
348 static gboolean gst_base_parse_sink_setcaps (GstPad * pad, GstCaps * caps);
349 static const GstQueryType *gst_base_parse_get_querytypes (GstPad * pad);
350
351 static GstFlowReturn gst_base_parse_chain (GstPad * pad, GstBuffer * buffer);
352 static void gst_base_parse_loop (GstPad * pad);
353
354 static gboolean gst_base_parse_check_frame (GstBaseParse * parse,
355     GstBaseParseFrame * frame, guint * framesize, gint * skipsize);
356 static GstFlowReturn gst_base_parse_parse_frame (GstBaseParse * parse,
357     GstBaseParseFrame * frame);
358
359 static gboolean gst_base_parse_sink_eventfunc (GstBaseParse * parse,
360     GstEvent * event);
361
362 static gboolean gst_base_parse_src_eventfunc (GstBaseParse * parse,
363     GstEvent * event);
364
365 static void gst_base_parse_drain (GstBaseParse * parse);
366
367 static void gst_base_parse_post_bitrates (GstBaseParse * parse,
368     gboolean post_min, gboolean post_avg, gboolean post_max);
369
370 static gint64 gst_base_parse_find_offset (GstBaseParse * parse,
371     GstClockTime time, gboolean before, GstClockTime * _ts);
372 static GstFlowReturn gst_base_parse_locate_time (GstBaseParse * parse,
373     GstClockTime * _time, gint64 * _offset);
374
375 static GstFlowReturn gst_base_parse_process_fragment (GstBaseParse * parse,
376     gboolean push_only);
377
378 static void
379 gst_base_parse_clear_queues (GstBaseParse * parse)
380 {
381   g_slist_foreach (parse->priv->buffers_queued, (GFunc) gst_buffer_unref, NULL);
382   g_slist_free (parse->priv->buffers_queued);
383   parse->priv->buffers_queued = NULL;
384   g_slist_foreach (parse->priv->buffers_pending, (GFunc) gst_buffer_unref,
385       NULL);
386   g_slist_free (parse->priv->buffers_pending);
387   parse->priv->buffers_pending = NULL;
388 }
389
390 static void
391 gst_base_parse_finalize (GObject * object)
392 {
393   GstBaseParse *parse = GST_BASE_PARSE (object);
394   GstEvent **p_ev;
395
396   g_object_unref (parse->adapter);
397
398   if (parse->pending_segment) {
399     p_ev = &parse->pending_segment;
400     gst_event_replace (p_ev, NULL);
401   }
402   if (parse->close_segment) {
403     p_ev = &parse->close_segment;
404     gst_event_replace (p_ev, NULL);
405   }
406
407   if (parse->priv->cache) {
408     gst_buffer_unref (parse->priv->cache);
409     parse->priv->cache = NULL;
410   }
411
412   g_list_foreach (parse->priv->pending_events, (GFunc) gst_mini_object_unref,
413       NULL);
414   g_list_free (parse->priv->pending_events);
415   parse->priv->pending_events = NULL;
416
417   if (parse->priv->index) {
418     gst_object_unref (parse->priv->index);
419     parse->priv->index = NULL;
420   }
421
422   gst_base_parse_clear_queues (parse);
423
424   G_OBJECT_CLASS (parent_class)->finalize (object);
425 }
426
427 static void
428 gst_base_parse_class_init (GstBaseParseClass * klass)
429 {
430   GObjectClass *gobject_class;
431   GstElementClass *gstelement_class;
432
433   gobject_class = G_OBJECT_CLASS (klass);
434   g_type_class_add_private (klass, sizeof (GstBaseParsePrivate));
435   parent_class = g_type_class_peek_parent (klass);
436   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_base_parse_finalize);
437
438   gstelement_class = (GstElementClass *) klass;
439   gstelement_class->change_state =
440       GST_DEBUG_FUNCPTR (gst_base_parse_change_state);
441   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_base_parse_set_index);
442   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_base_parse_get_index);
443
444   /* Default handlers */
445   klass->check_valid_frame = gst_base_parse_check_frame;
446   klass->parse_frame = gst_base_parse_parse_frame;
447   klass->src_event = gst_base_parse_src_eventfunc;
448   klass->convert = gst_base_parse_convert_default;
449
450   GST_DEBUG_CATEGORY_INIT (gst_base_parse_debug, "baseparse", 0,
451       "baseparse element");
452 }
453
454 static void
455 gst_base_parse_init (GstBaseParse * parse, GstBaseParseClass * bclass)
456 {
457   GstPadTemplate *pad_template;
458
459   GST_DEBUG_OBJECT (parse, "gst_base_parse_init");
460
461   parse->priv = GST_BASE_PARSE_GET_PRIVATE (parse);
462
463   pad_template =
464       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "sink");
465   g_return_if_fail (pad_template != NULL);
466   parse->sinkpad = gst_pad_new_from_template (pad_template, "sink");
467   gst_pad_set_event_function (parse->sinkpad,
468       GST_DEBUG_FUNCPTR (gst_base_parse_sink_event));
469   gst_pad_set_setcaps_function (parse->sinkpad,
470       GST_DEBUG_FUNCPTR (gst_base_parse_sink_setcaps));
471   gst_pad_set_chain_function (parse->sinkpad,
472       GST_DEBUG_FUNCPTR (gst_base_parse_chain));
473   gst_pad_set_activate_function (parse->sinkpad,
474       GST_DEBUG_FUNCPTR (gst_base_parse_sink_activate));
475   gst_pad_set_activatepush_function (parse->sinkpad,
476       GST_DEBUG_FUNCPTR (gst_base_parse_sink_activate_push));
477   gst_pad_set_activatepull_function (parse->sinkpad,
478       GST_DEBUG_FUNCPTR (gst_base_parse_sink_activate_pull));
479   gst_element_add_pad (GST_ELEMENT (parse), parse->sinkpad);
480
481   GST_DEBUG_OBJECT (parse, "sinkpad created");
482
483   pad_template =
484       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "src");
485   g_return_if_fail (pad_template != NULL);
486   parse->srcpad = gst_pad_new_from_template (pad_template, "src");
487   gst_pad_set_event_function (parse->srcpad,
488       GST_DEBUG_FUNCPTR (gst_base_parse_src_event));
489   gst_pad_set_query_type_function (parse->srcpad,
490       GST_DEBUG_FUNCPTR (gst_base_parse_get_querytypes));
491   gst_pad_set_query_function (parse->srcpad,
492       GST_DEBUG_FUNCPTR (gst_base_parse_query));
493   gst_pad_use_fixed_caps (parse->srcpad);
494   gst_element_add_pad (GST_ELEMENT (parse), parse->srcpad);
495   GST_DEBUG_OBJECT (parse, "src created");
496
497   parse->adapter = gst_adapter_new ();
498
499   parse->priv->pad_mode = GST_ACTIVATE_NONE;
500
501   /* init state */
502   gst_base_parse_reset (parse);
503   GST_DEBUG_OBJECT (parse, "init ok");
504 }
505
506 /**
507  * gst_base_parse_frame_init:
508  * @parse: #GstBaseParse.
509  * @fmt: #GstBaseParseFrame.
510  *
511  * Sets a #GstBaseParseFrame to initial state.  Currently this means
512  * all fields are zero-ed.
513  */
514 void
515 gst_base_parse_frame_init (GstBaseParse * parse, GstBaseParseFrame * frame)
516 {
517   memset (frame, 0, sizeof (*frame));
518 }
519
520 /* clear == frame no longer to be used following this */
521 static void
522 gst_base_parse_frame_clear (GstBaseParse * parse, GstBaseParseFrame * frame)
523 {
524   /* limited for now */
525   if (frame->buffer) {
526     gst_buffer_unref (frame->buffer);
527     frame->buffer = NULL;
528   }
529 }
530
531 static inline void
532 gst_base_parse_frame_update (GstBaseParse * parse, GstBaseParseFrame * frame,
533     GstBuffer * buf)
534 {
535   gst_buffer_replace (&frame->buffer, buf);
536   if (parse->priv->drain) {
537     frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DRAIN;
538   } else {
539     frame->flags &= ~(GST_BASE_PARSE_FRAME_FLAG_DRAIN);
540   }
541   /* losing sync is pretty much a discont (and vice versa), no ? */
542   if (!parse->priv->discont) {
543     frame->flags |= GST_BASE_PARSE_FRAME_FLAG_SYNC;
544   } else {
545     frame->flags &= ~(GST_BASE_PARSE_FRAME_FLAG_SYNC);
546   }
547 }
548
549 static void
550 gst_base_parse_reset (GstBaseParse * parse)
551 {
552   GST_OBJECT_LOCK (parse);
553   gst_segment_init (&parse->segment, GST_FORMAT_TIME);
554   parse->priv->duration = -1;
555   parse->priv->min_frame_size = 1;
556   parse->priv->discont = TRUE;
557   parse->priv->flushing = FALSE;
558   parse->priv->offset = 0;
559   parse->priv->sync_offset = 0;
560   parse->priv->update_interval = 50;
561   parse->priv->fps_num = parse->priv->fps_den = 0;
562   parse->priv->frame_duration = GST_CLOCK_TIME_NONE;
563   parse->priv->lead_in = parse->priv->lead_out = 0;
564   parse->priv->lead_in_ts = parse->priv->lead_out_ts = 0;
565   parse->priv->seekable = GST_BASE_PARSE_SEEK_DEFAULT;
566   parse->priv->bitrate = 0;
567   parse->priv->framecount = 0;
568   parse->priv->bytecount = 0;
569   parse->priv->acc_duration = 0;
570   parse->priv->first_frame_ts = GST_CLOCK_TIME_NONE;
571   parse->priv->first_frame_offset = -1;
572   parse->priv->estimated_duration = -1;
573   parse->priv->next_ts = 0;
574   parse->priv->passthrough = FALSE;
575   parse->priv->post_min_bitrate = TRUE;
576   parse->priv->post_avg_bitrate = TRUE;
577   parse->priv->post_max_bitrate = TRUE;
578   parse->priv->min_bitrate = G_MAXUINT;
579   parse->priv->max_bitrate = 0;
580   parse->priv->avg_bitrate = 0;
581   parse->priv->posted_avg_bitrate = 0;
582
583   parse->priv->index_last_ts = 0;
584   parse->priv->index_last_offset = 0;
585   parse->priv->index_last_valid = TRUE;
586   parse->priv->upstream_seekable = FALSE;
587   parse->priv->upstream_size = 0;
588   parse->priv->upstream_has_duration = FALSE;
589   parse->priv->idx_interval = 0;
590   parse->priv->exact_position = TRUE;
591   parse->priv->seen_keyframe = FALSE;
592
593   parse->priv->last_ts = GST_CLOCK_TIME_NONE;
594   parse->priv->last_offset = 0;
595
596   if (parse->pending_segment) {
597     gst_event_unref (parse->pending_segment);
598     parse->pending_segment = NULL;
599   }
600
601   g_list_foreach (parse->priv->pending_events, (GFunc) gst_mini_object_unref,
602       NULL);
603   g_list_free (parse->priv->pending_events);
604   parse->priv->pending_events = NULL;
605
606   if (parse->priv->cache) {
607     gst_buffer_unref (parse->priv->cache);
608     parse->priv->cache = NULL;
609   }
610
611   g_slist_foreach (parse->priv->pending_seeks, (GFunc) g_free, NULL);
612   g_slist_free (parse->priv->pending_seeks);
613   parse->priv->pending_seeks = NULL;
614
615   GST_OBJECT_UNLOCK (parse);
616 }
617
618 /**
619  * gst_base_parse_check_frame:
620  * @parse: #GstBaseParse.
621  * @buffer: GstBuffer.
622  * @framesize: This will be set to tell the found frame size in bytes.
623  * @skipsize: Output parameter that tells how much data needs to be skipped
624  *            in order to find the following frame header.
625  *
626  * Default callback for check_valid_frame.
627  * 
628  * Returns: Always TRUE.
629  */
630 static gboolean
631 gst_base_parse_check_frame (GstBaseParse * parse,
632     GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
633 {
634   *framesize = GST_BUFFER_SIZE (frame->buffer);
635   *skipsize = 0;
636   return TRUE;
637 }
638
639
640 /**
641  * gst_base_parse_parse_frame:
642  * @parse: #GstBaseParse.
643  * @buffer: #GstBuffer.
644  *
645  * Default callback for parse_frame.
646  */
647 static GstFlowReturn
648 gst_base_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
649 {
650   GstBuffer *buffer = frame->buffer;
651
652   if (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
653       GST_CLOCK_TIME_IS_VALID (parse->priv->next_ts)) {
654     GST_BUFFER_TIMESTAMP (buffer) = parse->priv->next_ts;
655   }
656   if (!GST_BUFFER_DURATION_IS_VALID (buffer) &&
657       GST_CLOCK_TIME_IS_VALID (parse->priv->frame_duration)) {
658     GST_BUFFER_DURATION (buffer) = parse->priv->frame_duration;
659   }
660   return GST_FLOW_OK;
661 }
662
663 /**
664  * gst_base_parse_convert:
665  * @parse: #GstBaseParse.
666  * @src_format: #GstFormat describing the source format.
667  * @src_value: Source value to be converted.
668  * @dest_format: #GstFormat defining the converted format.
669  * @dest_value: Pointer where the conversion result will be put.
670  *
671  * Converts using configured "convert" vmethod in #GstBaseParse class.
672  *
673  * Returns: TRUE if conversion was successful.
674  */
675 static gboolean
676 gst_base_parse_convert (GstBaseParse * parse,
677     GstFormat src_format,
678     gint64 src_value, GstFormat dest_format, gint64 * dest_value)
679 {
680   GstBaseParseClass *klass = GST_BASE_PARSE_GET_CLASS (parse);
681   gboolean ret;
682
683   g_return_val_if_fail (dest_value != NULL, FALSE);
684
685   if (!klass->convert)
686     return FALSE;
687
688   ret = klass->convert (parse, src_format, src_value, dest_format, dest_value);
689
690 #ifndef GST_DISABLE_GST_DEBUG
691   {
692     if (ret) {
693       if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_BYTES) {
694         GST_LOG_OBJECT (parse,
695             "TIME -> BYTES: %" GST_TIME_FORMAT " -> %" G_GINT64_FORMAT,
696             GST_TIME_ARGS (src_value), *dest_value);
697       } else if (dest_format == GST_FORMAT_TIME &&
698           src_format == GST_FORMAT_BYTES) {
699         GST_LOG_OBJECT (parse,
700             "BYTES -> TIME: %" G_GINT64_FORMAT " -> %" GST_TIME_FORMAT,
701             src_value, GST_TIME_ARGS (*dest_value));
702       } else {
703         GST_LOG_OBJECT (parse,
704             "%s -> %s: %" G_GINT64_FORMAT " -> %" G_GINT64_FORMAT,
705             GST_STR_NULL (gst_format_get_name (src_format)),
706             GST_STR_NULL (gst_format_get_name (dest_format)),
707             src_value, *dest_value);
708       }
709     } else {
710       GST_DEBUG_OBJECT (parse, "conversion failed");
711     }
712   }
713 #endif
714
715   return ret;
716 }
717
718 /**
719  * gst_base_parse_sink_event:
720  * @pad: #GstPad that received the event.
721  * @event: #GstEvent to be handled.
722  *
723  * Handler for sink pad events.
724  *
725  * Returns: TRUE if the event was handled.
726  */
727 static gboolean
728 gst_base_parse_sink_event (GstPad * pad, GstEvent * event)
729 {
730   GstBaseParse *parse;
731   GstBaseParseClass *bclass;
732   gboolean handled = FALSE;
733   gboolean ret = TRUE;
734
735   parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
736   bclass = GST_BASE_PARSE_GET_CLASS (parse);
737
738   GST_DEBUG_OBJECT (parse, "handling event %d, %s", GST_EVENT_TYPE (event),
739       GST_EVENT_TYPE_NAME (event));
740
741   /* Cache all events except EOS, NEWSEGMENT and FLUSH_STOP if we have a
742    * pending segment */
743   if (parse->pending_segment && GST_EVENT_TYPE (event) != GST_EVENT_EOS
744       && GST_EVENT_TYPE (event) != GST_EVENT_NEWSEGMENT
745       && GST_EVENT_TYPE (event) != GST_EVENT_FLUSH_START
746       && GST_EVENT_TYPE (event) != GST_EVENT_FLUSH_STOP) {
747
748     if (GST_EVENT_TYPE (event) == GST_EVENT_TAG)
749       /* See if any bitrate tags were posted */
750       gst_base_parse_handle_tag (parse, event);
751
752     parse->priv->pending_events =
753         g_list_append (parse->priv->pending_events, event);
754     ret = TRUE;
755   } else {
756
757     if (GST_EVENT_TYPE (event) == GST_EVENT_EOS &&
758         parse->priv->framecount < MIN_FRAMES_TO_POST_BITRATE)
759       /* We've not posted bitrate tags yet - do so now */
760       gst_base_parse_post_bitrates (parse, TRUE, TRUE, TRUE);
761
762     if (bclass->event)
763       handled = bclass->event (parse, event);
764
765     if (!handled)
766       handled = gst_base_parse_sink_eventfunc (parse, event);
767
768     if (!handled)
769       ret = gst_pad_event_default (pad, event);
770   }
771
772   gst_object_unref (parse);
773   GST_DEBUG_OBJECT (parse, "event handled");
774   return ret;
775 }
776
777
778 /**
779  * gst_base_parse_sink_eventfunc:
780  * @parse: #GstBaseParse.
781  * @event: #GstEvent to be handled.
782  *
783  * Element-level event handler function.
784  *
785  * The event will be unreffed only if it has been handled and this
786  * function returns %TRUE
787  *
788  * Returns: %TRUE if the event was handled and not need forwarding.
789  */
790 static gboolean
791 gst_base_parse_sink_eventfunc (GstBaseParse * parse, GstEvent * event)
792 {
793   gboolean handled = FALSE;
794   GstEvent **eventp;
795
796   switch (GST_EVENT_TYPE (event)) {
797     case GST_EVENT_NEWSEGMENT:
798     {
799       gdouble rate, applied_rate;
800       GstFormat format;
801       gint64 start, stop, pos, next_ts, offset = 0;
802       gboolean update;
803
804       gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
805           &format, &start, &stop, &pos);
806
807       GST_DEBUG_OBJECT (parse, "newseg rate %g, applied rate %g, "
808           "format %d, start = %" GST_TIME_FORMAT ", stop = %" GST_TIME_FORMAT
809           ", pos = %" GST_TIME_FORMAT, rate, applied_rate, format,
810           GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (pos));
811
812       if (format == GST_FORMAT_BYTES) {
813         GstClockTime seg_start, seg_stop;
814         GstBaseParseSeek *seek = NULL;
815         GSList *node;
816
817         /* stop time is allowed to be open-ended, but not start & pos */
818         seg_stop = GST_CLOCK_TIME_NONE;
819         seg_start = 0;
820         offset = pos;
821
822         GST_OBJECT_LOCK (parse);
823         for (node = parse->priv->pending_seeks; node; node = node->next) {
824           GstBaseParseSeek *tmp = node->data;
825
826           if (tmp->offset == pos) {
827             seek = tmp;
828             break;
829           }
830         }
831         parse->priv->pending_seeks =
832             g_slist_remove (parse->priv->pending_seeks, seek);
833         GST_OBJECT_UNLOCK (parse);
834
835         if (seek) {
836           GST_DEBUG_OBJECT (parse,
837               "Matched newsegment to%s seek: %" GST_SEGMENT_FORMAT,
838               seek->accurate ? " accurate" : "", &seek->segment);
839           seg_start = seek->segment.start;
840           seg_stop = seek->segment.stop;
841           next_ts = seek->start_ts;
842           parse->priv->exact_position = seek->accurate;
843           g_free (seek);
844         } else {
845           /* best attempt convert */
846           /* as these are only estimates, stop is kept open-ended to avoid
847            * premature cutting */
848           gst_base_parse_convert (parse, GST_FORMAT_BYTES, start,
849               GST_FORMAT_TIME, (gint64 *) & seg_start);
850           parse->priv->exact_position = (start == 0);
851           next_ts = seg_start;
852         }
853
854         gst_event_unref (event);
855         event = gst_event_new_new_segment_full (update, rate, applied_rate,
856             GST_FORMAT_TIME, seg_start, seg_stop, seg_start);
857         format = GST_FORMAT_TIME;
858         start = seg_start;
859         stop = seg_stop;
860         GST_DEBUG_OBJECT (parse, "Converted incoming segment to TIME. "
861             "start = %" GST_TIME_FORMAT ", stop = %" GST_TIME_FORMAT,
862             GST_TIME_ARGS (seg_start), GST_TIME_ARGS (seg_stop));
863       } else if (format != GST_FORMAT_TIME) {
864         /* Unknown incoming segment format. Output a default open-ended 
865          * TIME segment */
866         gst_event_unref (event);
867         event = gst_event_new_new_segment_full (update, rate, applied_rate,
868             GST_FORMAT_TIME, 0, GST_CLOCK_TIME_NONE, 0);
869         format = GST_FORMAT_TIME;
870         next_ts = start = 0;
871         stop = GST_CLOCK_TIME_NONE;
872       } else {
873         /* not considered BYTE seekable if it is talking to us in TIME,
874          * whatever else it might claim */
875         parse->priv->upstream_seekable = FALSE;
876         next_ts = start;
877       }
878
879       gst_segment_set_newsegment_full (&parse->segment, update, rate,
880           applied_rate, format, start, stop, start);
881
882       /* save the segment for later, right before we push a new buffer so that
883        * the caps are fixed and the next linked element can receive
884        * the segment. */
885       eventp = &parse->pending_segment;
886       gst_event_replace (eventp, event);
887       gst_event_unref (event);
888       handled = TRUE;
889
890       /* but finish the current segment */
891       GST_DEBUG_OBJECT (parse, "draining current segment");
892       if (parse->segment.rate > 0.0)
893         gst_base_parse_drain (parse);
894       else
895         gst_base_parse_process_fragment (parse, FALSE);
896       gst_adapter_clear (parse->adapter);
897       parse->priv->offset = offset;
898       parse->priv->sync_offset = offset;
899       parse->priv->next_ts = next_ts;
900       parse->priv->last_ts = GST_CLOCK_TIME_NONE;
901       parse->priv->discont = TRUE;
902       parse->priv->seen_keyframe = FALSE;
903       break;
904     }
905
906     case GST_EVENT_FLUSH_START:
907       parse->priv->flushing = TRUE;
908       handled = gst_pad_push_event (parse->srcpad, gst_event_ref (event));
909       if (handled)
910         gst_event_unref (event);
911       /* Wait for _chain() to exit by taking the srcpad STREAM_LOCK */
912       GST_PAD_STREAM_LOCK (parse->srcpad);
913       GST_PAD_STREAM_UNLOCK (parse->srcpad);
914
915       break;
916
917     case GST_EVENT_FLUSH_STOP:
918       gst_adapter_clear (parse->adapter);
919       gst_base_parse_clear_queues (parse);
920       parse->priv->flushing = FALSE;
921       parse->priv->discont = TRUE;
922       parse->priv->last_ts = GST_CLOCK_TIME_NONE;
923       break;
924
925     case GST_EVENT_EOS:
926       if (parse->segment.rate > 0.0)
927         gst_base_parse_drain (parse);
928       else
929         gst_base_parse_process_fragment (parse, FALSE);
930
931       /* If we STILL have zero frames processed, fire an error */
932       if (parse->priv->framecount == 0) {
933         GST_ELEMENT_ERROR (parse, STREAM, WRONG_TYPE,
934             ("No valid frames found before end of stream"), (NULL));
935       }
936       /* newsegment before eos */
937       if (parse->pending_segment) {
938         gst_pad_push_event (parse->srcpad, parse->pending_segment);
939         parse->pending_segment = NULL;
940       }
941       break;
942
943     default:
944       break;
945   }
946
947   return handled;
948 }
949
950
951 /**
952  * gst_base_parse_src_event:
953  * @pad: #GstPad that received the event.
954  * @event: #GstEvent that was received.
955  *
956  * Handler for source pad events.
957  *
958  * Returns: TRUE if the event was handled.
959  */
960 static gboolean
961 gst_base_parse_src_event (GstPad * pad, GstEvent * event)
962 {
963   GstBaseParse *parse;
964   GstBaseParseClass *bclass;
965   gboolean handled = FALSE;
966   gboolean ret = TRUE;
967
968   parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
969   bclass = GST_BASE_PARSE_GET_CLASS (parse);
970
971   GST_DEBUG_OBJECT (parse, "event %d, %s", GST_EVENT_TYPE (event),
972       GST_EVENT_TYPE_NAME (event));
973
974   if (bclass->src_event)
975     handled = bclass->src_event (parse, event);
976
977   if (!handled)
978     ret = gst_pad_event_default (pad, event);
979   else
980     gst_event_unref (event);
981
982   gst_object_unref (parse);
983   return ret;
984 }
985
986
987 /**
988  * gst_base_parse_src_eventfunc:
989  * @parse: #GstBaseParse.
990  * @event: #GstEvent that was received.
991  *
992  * Default srcpad event handler.
993  *
994  * Returns: TRUE if the event was handled and can be dropped.
995  */
996 static gboolean
997 gst_base_parse_src_eventfunc (GstBaseParse * parse, GstEvent * event)
998 {
999   gboolean handled = FALSE;
1000
1001   switch (GST_EVENT_TYPE (event)) {
1002     case GST_EVENT_SEEK:
1003     {
1004       if (parse->priv->seekable > GST_BASE_PARSE_SEEK_NONE) {
1005         handled = gst_base_parse_handle_seek (parse, event);
1006       }
1007       break;
1008     }
1009     default:
1010       break;
1011   }
1012   return handled;
1013 }
1014
1015
1016 /**
1017  * gst_base_parse_convert_default:
1018  * @parse: #GstBaseParse.
1019  * @src_format: #GstFormat describing the source format.
1020  * @src_value: Source value to be converted.
1021  * @dest_format: #GstFormat defining the converted format.
1022  * @dest_value: Pointer where the conversion result will be put.
1023  *
1024  * Default implementation of "convert" vmethod in #GstBaseParse class.
1025  *
1026  * Returns: TRUE if conversion was successful.
1027  */
1028 gboolean
1029 gst_base_parse_convert_default (GstBaseParse * parse,
1030     GstFormat src_format,
1031     gint64 src_value, GstFormat dest_format, gint64 * dest_value)
1032 {
1033   gboolean ret = FALSE;
1034   guint64 bytes, duration;
1035
1036   if (G_UNLIKELY (src_format == dest_format)) {
1037     *dest_value = src_value;
1038     return TRUE;
1039   }
1040
1041   if (G_UNLIKELY (src_value == -1)) {
1042     *dest_value = -1;
1043     return TRUE;
1044   }
1045
1046   if (G_UNLIKELY (src_value == 0)) {
1047     *dest_value = 0;
1048     return TRUE;
1049   }
1050
1051   /* need at least some frames */
1052   if (!parse->priv->framecount)
1053     return FALSE;
1054
1055   duration = parse->priv->acc_duration / GST_MSECOND;
1056   bytes = parse->priv->bytecount;
1057
1058   if (G_UNLIKELY (!duration || !bytes))
1059     return FALSE;
1060
1061   if (src_format == GST_FORMAT_BYTES) {
1062     if (dest_format == GST_FORMAT_TIME) {
1063       /* BYTES -> TIME conversion */
1064       GST_DEBUG_OBJECT (parse, "converting bytes -> time");
1065       *dest_value = gst_util_uint64_scale (src_value, duration, bytes);
1066       *dest_value *= GST_MSECOND;
1067       GST_DEBUG_OBJECT (parse, "conversion result: %" G_GINT64_FORMAT " ms",
1068           *dest_value / GST_MSECOND);
1069       ret = TRUE;
1070     }
1071   } else if (src_format == GST_FORMAT_TIME) {
1072     if (dest_format == GST_FORMAT_BYTES) {
1073       GST_DEBUG_OBJECT (parse, "converting time -> bytes");
1074       *dest_value = gst_util_uint64_scale (src_value / GST_MSECOND, bytes,
1075           duration);
1076       GST_DEBUG_OBJECT (parse,
1077           "time %" G_GINT64_FORMAT " ms in bytes = %" G_GINT64_FORMAT,
1078           src_value / GST_MSECOND, *dest_value);
1079       ret = TRUE;
1080     }
1081   } else if (src_format == GST_FORMAT_DEFAULT) {
1082     /* DEFAULT == frame-based */
1083     if (dest_format == GST_FORMAT_TIME) {
1084       if (parse->priv->fps_den) {
1085         *dest_value = gst_util_uint64_scale (src_value,
1086             GST_SECOND * parse->priv->fps_den, parse->priv->fps_num);
1087         ret = TRUE;
1088       }
1089     } else if (dest_format == GST_FORMAT_BYTES) {
1090     }
1091   }
1092
1093   return ret;
1094 }
1095
1096 /**
1097  * gst_base_parse_update_duration:
1098  * @parse: #GstBaseParse.
1099  *
1100  */
1101 static void
1102 gst_base_parse_update_duration (GstBaseParse * aacparse)
1103 {
1104   GstPad *peer;
1105   GstBaseParse *parse;
1106
1107   parse = GST_BASE_PARSE (aacparse);
1108
1109   peer = gst_pad_get_peer (parse->sinkpad);
1110   if (peer) {
1111     GstFormat pformat = GST_FORMAT_BYTES;
1112     gboolean qres = FALSE;
1113     gint64 ptot, dest_value;
1114
1115     qres = gst_pad_query_duration (peer, &pformat, &ptot);
1116     gst_object_unref (GST_OBJECT (peer));
1117     if (qres) {
1118       if (gst_base_parse_convert (parse, pformat, ptot,
1119               GST_FORMAT_TIME, &dest_value))
1120         parse->priv->estimated_duration = dest_value;
1121     }
1122   }
1123 }
1124
1125 static void
1126 gst_base_parse_post_bitrates (GstBaseParse * parse, gboolean post_min,
1127     gboolean post_avg, gboolean post_max)
1128 {
1129   GstTagList *taglist = gst_tag_list_new ();
1130
1131   if (post_min && parse->priv->post_min_bitrate)
1132     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
1133         GST_TAG_MINIMUM_BITRATE, parse->priv->min_bitrate, NULL);
1134
1135   if (post_avg && parse->priv->post_avg_bitrate) {
1136     parse->priv->posted_avg_bitrate = parse->priv->avg_bitrate;
1137     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
1138         parse->priv->avg_bitrate, NULL);
1139   }
1140
1141   if (post_max && parse->priv->post_max_bitrate)
1142     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
1143         GST_TAG_MAXIMUM_BITRATE, parse->priv->max_bitrate, NULL);
1144
1145   GST_DEBUG_OBJECT (parse, "Updated bitrates. Min: %u, Avg: %u, Max: %u",
1146       parse->priv->min_bitrate, parse->priv->avg_bitrate,
1147       parse->priv->max_bitrate);
1148
1149   gst_element_found_tags_for_pad (GST_ELEMENT (parse), parse->srcpad, taglist);
1150 }
1151
1152 /**
1153  * gst_base_parse_update_bitrates:
1154  * @parse: #GstBaseParse.
1155  * @buffer: Current frame as a #GstBuffer
1156  *
1157  * Keeps track of the minimum and maximum bitrates, and also maintains a
1158  * running average bitrate of the stream so far.
1159  */
1160 static void
1161 gst_base_parse_update_bitrates (GstBaseParse * parse, GstBaseParseFrame * frame)
1162 {
1163   /* Only update the tag on a 10 kbps delta */
1164   static const gint update_threshold = 10000;
1165
1166   GstBaseParseClass *klass;
1167   guint64 data_len, frame_dur;
1168   gint overhead, frame_bitrate, old_avg_bitrate;
1169   gboolean update_min = FALSE, update_avg = FALSE, update_max = FALSE;
1170   GstBuffer *buffer = frame->buffer;
1171
1172   klass = GST_BASE_PARSE_GET_CLASS (parse);
1173
1174   overhead = frame->overhead;
1175   if (overhead == -1)
1176     return;
1177
1178   data_len = GST_BUFFER_SIZE (buffer) - overhead;
1179   parse->priv->data_bytecount += data_len;
1180
1181   /* duration should be valid by now,
1182    * either set by subclass or maybe based on fps settings */
1183   if (GST_BUFFER_DURATION_IS_VALID (buffer) && parse->priv->acc_duration != 0) {
1184     /* Calculate duration of a frame from buffer properties */
1185     frame_dur = GST_BUFFER_DURATION (buffer);
1186     parse->priv->avg_bitrate = (8 * parse->priv->data_bytecount * GST_SECOND) /
1187         parse->priv->acc_duration;
1188
1189   } else {
1190     /* No way to figure out frame duration (is this even possible?) */
1191     return;
1192   }
1193
1194   /* override if subclass provided bitrate, e.g. metadata based */
1195   if (parse->priv->bitrate) {
1196     parse->priv->avg_bitrate = parse->priv->bitrate;
1197     /* spread this (confirmed) info ASAP */
1198     if (parse->priv->posted_avg_bitrate != parse->priv->avg_bitrate)
1199       gst_base_parse_post_bitrates (parse, FALSE, TRUE, FALSE);
1200   }
1201
1202   frame_bitrate = (8 * data_len * GST_SECOND) / frame_dur;
1203
1204   GST_LOG_OBJECT (parse, "frame bitrate %u, avg bitrate %u", frame_bitrate,
1205       parse->priv->avg_bitrate);
1206
1207   if (parse->priv->framecount < MIN_FRAMES_TO_POST_BITRATE) {
1208     goto exit;
1209   } else if (parse->priv->framecount == MIN_FRAMES_TO_POST_BITRATE) {
1210     /* always post all at threshold time */
1211     update_min = update_max = update_avg = TRUE;
1212   } else {
1213     if (frame_bitrate < parse->priv->min_bitrate) {
1214       parse->priv->min_bitrate = frame_bitrate;
1215       update_min = TRUE;
1216     }
1217
1218     if (frame_bitrate > parse->priv->max_bitrate) {
1219       parse->priv->max_bitrate = frame_bitrate;
1220       update_max = TRUE;
1221     }
1222
1223     old_avg_bitrate = parse->priv->posted_avg_bitrate;
1224     if ((gint) (old_avg_bitrate - parse->priv->avg_bitrate) > update_threshold
1225         || (gint) (parse->priv->avg_bitrate - old_avg_bitrate) >
1226         update_threshold)
1227       update_avg = TRUE;
1228   }
1229
1230   if ((update_min || update_avg || update_max))
1231     gst_base_parse_post_bitrates (parse, update_min, update_avg, update_max);
1232
1233   /* If average bitrate changes that much and no valid (time) duration provided,
1234    * then post a new duration message so applications can update their cached
1235    * values */
1236   if (update_avg && !(parse->priv->duration_fmt == GST_FORMAT_TIME &&
1237           GST_CLOCK_TIME_IS_VALID (parse->priv->duration)))
1238     gst_element_post_message (GST_ELEMENT (parse),
1239         gst_message_new_duration (GST_OBJECT (parse), GST_FORMAT_TIME, -1));
1240
1241 exit:
1242   return;
1243 }
1244
1245 /**
1246  * gst_base_parse_add_index_entry:
1247  * @parse: #GstBaseParse.
1248  * @offset: offset of entry
1249  * @ts: timestamp associated with offset
1250  * @key: whether entry refers to keyframe
1251  * @force: add entry disregarding sanity checks
1252  *
1253  * Adds an entry to the index associating @offset to @ts.  It is recommended
1254  * to only add keyframe entries.  @force allows to bypass checks, such as
1255  * whether the stream is (upstream) seekable, another entry is already "close"
1256  * to the new entry, etc.
1257  *
1258  * Returns: #gboolean indicating whether entry was added
1259  */
1260 gboolean
1261 gst_base_parse_add_index_entry (GstBaseParse * parse, guint64 offset,
1262     GstClockTime ts, gboolean key, gboolean force)
1263 {
1264   gboolean ret = FALSE;
1265   GstIndexAssociation associations[2];
1266
1267   GST_LOG_OBJECT (parse, "Adding key=%d index entry %" GST_TIME_FORMAT
1268       " @ offset 0x%08" G_GINT64_MODIFIER "x", key, GST_TIME_ARGS (ts), offset);
1269
1270   if (G_LIKELY (!force)) {
1271
1272     if (!parse->priv->upstream_seekable) {
1273       GST_DEBUG_OBJECT (parse, "upstream not seekable; discarding");
1274       goto exit;
1275     }
1276
1277     /* FIXME need better helper data structure that handles these issues
1278      * related to ongoing collecting of index entries */
1279     if (parse->priv->index_last_offset >= offset) {
1280       GST_DEBUG_OBJECT (parse, "already have entries up to offset "
1281           "0x%08" G_GINT64_MODIFIER "x", parse->priv->index_last_offset);
1282       goto exit;
1283     }
1284
1285     if (GST_CLOCK_DIFF (parse->priv->index_last_ts, ts) <
1286         parse->priv->idx_interval) {
1287       GST_DEBUG_OBJECT (parse, "entry too close to last time %" GST_TIME_FORMAT,
1288           GST_TIME_ARGS (parse->priv->index_last_ts));
1289       goto exit;
1290     }
1291
1292     /* if last is not really the last one */
1293     if (!parse->priv->index_last_valid) {
1294       GstClockTime prev_ts;
1295
1296       gst_base_parse_find_offset (parse, ts, TRUE, &prev_ts);
1297       if (GST_CLOCK_DIFF (prev_ts, ts) < parse->priv->idx_interval) {
1298         GST_DEBUG_OBJECT (parse,
1299             "entry too close to existing entry %" GST_TIME_FORMAT,
1300             GST_TIME_ARGS (prev_ts));
1301         parse->priv->index_last_offset = offset;
1302         parse->priv->index_last_ts = ts;
1303         goto exit;
1304       }
1305     }
1306   }
1307
1308   associations[0].format = GST_FORMAT_TIME;
1309   associations[0].value = ts;
1310   associations[1].format = GST_FORMAT_BYTES;
1311   associations[1].value = offset;
1312
1313   /* index might change on-the-fly, although that would be nutty app ... */
1314   GST_OBJECT_LOCK (parse);
1315   gst_index_add_associationv (parse->priv->index, parse->priv->index_id,
1316       (key) ? GST_ASSOCIATION_FLAG_KEY_UNIT : GST_ASSOCIATION_FLAG_NONE,
1317       2, (const GstIndexAssociation *) &associations);
1318   GST_OBJECT_UNLOCK (parse);
1319
1320   if (key) {
1321     parse->priv->index_last_offset = offset;
1322     parse->priv->index_last_ts = ts;
1323   }
1324
1325   ret = TRUE;
1326
1327 exit:
1328   return ret;
1329 }
1330
1331 /* check for seekable upstream, above and beyond a mere query */
1332 static void
1333 gst_base_parse_check_seekability (GstBaseParse * parse)
1334 {
1335   GstQuery *query;
1336   gboolean seekable = FALSE;
1337   gint64 start = -1, stop = -1;
1338   guint idx_interval = 0;
1339
1340   query = gst_query_new_seeking (GST_FORMAT_BYTES);
1341   if (!gst_pad_peer_query (parse->sinkpad, query)) {
1342     GST_DEBUG_OBJECT (parse, "seeking query failed");
1343     goto done;
1344   }
1345
1346   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
1347
1348   /* try harder to query upstream size if we didn't get it the first time */
1349   if (seekable && stop == -1) {
1350     GstFormat fmt = GST_FORMAT_BYTES;
1351
1352     GST_DEBUG_OBJECT (parse, "doing duration query to fix up unset stop");
1353     gst_pad_query_peer_duration (parse->sinkpad, &fmt, &stop);
1354   }
1355
1356   /* if upstream doesn't know the size, it's likely that it's not seekable in
1357    * practice even if it technically may be seekable */
1358   if (seekable && (start != 0 || stop <= start)) {
1359     GST_DEBUG_OBJECT (parse, "seekable but unknown start/stop -> disable");
1360     seekable = FALSE;
1361   }
1362
1363   /* let's not put every single frame into our index */
1364   if (seekable) {
1365     if (stop < 10 * 1024 * 1024)
1366       idx_interval = 100;
1367     else if (stop < 100 * 1024 * 1024)
1368       idx_interval = 500;
1369     else
1370       idx_interval = 1000;
1371   }
1372
1373 done:
1374   gst_query_unref (query);
1375
1376   GST_DEBUG_OBJECT (parse, "seekable: %d (%" G_GUINT64_FORMAT " - %"
1377       G_GUINT64_FORMAT ")", seekable, start, stop);
1378   parse->priv->upstream_seekable = seekable;
1379   parse->priv->upstream_size = seekable ? stop : 0;
1380
1381   GST_DEBUG_OBJECT (parse, "idx_interval: %ums", idx_interval);
1382   parse->priv->idx_interval = idx_interval * GST_MSECOND;
1383 }
1384
1385 /* some misc checks on upstream */
1386 static void
1387 gst_base_parse_check_upstream (GstBaseParse * parse)
1388 {
1389   GstFormat fmt = GST_FORMAT_TIME;
1390   gint64 stop;
1391
1392   if (gst_pad_query_peer_duration (parse->sinkpad, &fmt, &stop))
1393     if (GST_CLOCK_TIME_IS_VALID (stop) && stop) {
1394       /* upstream has one, accept it also, and no further updates */
1395       gst_base_parse_set_duration (parse, GST_FORMAT_TIME, stop, 0);
1396       parse->priv->upstream_has_duration = TRUE;
1397     }
1398
1399   GST_DEBUG_OBJECT (parse, "upstream_has_duration: %d",
1400       parse->priv->upstream_has_duration);
1401 }
1402
1403 /* checks src caps to determine if dealing with audio or video */
1404 /* TODO maybe forego automagic stuff and let subclass configure it ? */
1405 static void
1406 gst_base_parse_check_media (GstBaseParse * parse)
1407 {
1408   GstCaps *caps;
1409   GstStructure *s;
1410
1411   caps = GST_PAD_CAPS (parse->srcpad);
1412   if (G_LIKELY (caps) && (s = gst_caps_get_structure (caps, 0))) {
1413     parse->priv->is_video =
1414         g_str_has_prefix (gst_structure_get_name (s), "video");
1415   } else {
1416     /* historical default */
1417     parse->priv->is_video = FALSE;
1418   }
1419
1420   GST_DEBUG_OBJECT (parse, "media is video == %d", parse->priv->is_video);
1421 }
1422
1423 /**
1424  * gst_base_parse_handle_and_push_buffer:
1425  * @parse: #GstBaseParse.
1426  * @klass: #GstBaseParseClass.
1427  * @buffer: #GstBuffer.
1428  *
1429  * Parses the frame from given buffer and pushes it forward. Also performs
1430  * timestamp handling and checks the segment limits.
1431  *
1432  * This is called with srcpad STREAM_LOCK held.
1433  *
1434  * Returns: #GstFlowReturn
1435  */
1436 static GstFlowReturn
1437 gst_base_parse_handle_and_push_frame (GstBaseParse * parse,
1438     GstBaseParseClass * klass, GstBaseParseFrame * frame)
1439 {
1440   GstFlowReturn ret;
1441   gint64 offset;
1442   GstBuffer *buffer;
1443
1444   g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR);
1445
1446   buffer = frame->buffer;
1447
1448   if (parse->priv->discont) {
1449     GST_DEBUG_OBJECT (parse, "marking DISCONT");
1450     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
1451     parse->priv->discont = FALSE;
1452   }
1453
1454   /* some one-time start-up */
1455   if (G_UNLIKELY (!parse->priv->framecount)) {
1456     gst_base_parse_check_seekability (parse);
1457     gst_base_parse_check_upstream (parse);
1458   }
1459
1460   GST_LOG_OBJECT (parse,
1461       "parsing frame at offset %" G_GUINT64_FORMAT
1462       " (%#" G_GINT64_MODIFIER "x) of size %d",
1463       GST_BUFFER_OFFSET (buffer), GST_BUFFER_OFFSET (buffer),
1464       GST_BUFFER_SIZE (buffer));
1465
1466   /* store offset as it might get overwritten */
1467   offset = GST_BUFFER_OFFSET (buffer);
1468   ret = klass->parse_frame (parse, frame);
1469   /* sync */
1470   buffer = frame->buffer;
1471   /* subclass must play nice */
1472   g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
1473
1474   /* check initial frame to determine if subclass/format can provide ts.
1475    * If so, that allows and enables extra seek and duration determining options */
1476   if (G_UNLIKELY (parse->priv->first_frame_offset < 0 && ret == GST_FLOW_OK)) {
1477     if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
1478         parse->priv->pad_mode == GST_ACTIVATE_PULL) {
1479       parse->priv->first_frame_offset = offset;
1480       parse->priv->first_frame_ts = GST_BUFFER_TIMESTAMP (buffer);
1481       GST_DEBUG_OBJECT (parse, "subclass provided ts %" GST_TIME_FORMAT
1482           " for first frame at offset %" G_GINT64_FORMAT,
1483           GST_TIME_ARGS (parse->priv->first_frame_ts),
1484           parse->priv->first_frame_offset);
1485       if (!GST_CLOCK_TIME_IS_VALID (parse->priv->duration)) {
1486         gint64 off;
1487         GstClockTime last_ts = G_MAXINT64;
1488
1489         GST_DEBUG_OBJECT (parse, "no duration; trying scan to determine");
1490         gst_base_parse_locate_time (parse, &last_ts, &off);
1491         if (GST_CLOCK_TIME_IS_VALID (last_ts))
1492           gst_base_parse_set_duration (parse, GST_FORMAT_TIME, last_ts, 0);
1493       }
1494     } else {
1495       /* disable further checks */
1496       parse->priv->first_frame_offset = 0;
1497     }
1498   }
1499
1500   /* re-use default handler to add missing metadata as-much-as-possible */
1501   gst_base_parse_parse_frame (parse, frame);
1502   if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
1503       GST_BUFFER_DURATION_IS_VALID (buffer)) {
1504     parse->priv->next_ts =
1505         GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer);
1506   } else {
1507     /* we lost track, do not produce bogus time next time around
1508      * (probably means parser subclass has given up on parsing as well) */
1509     GST_DEBUG_OBJECT (parse, "no next fallback timestamp");
1510     parse->priv->next_ts = GST_CLOCK_TIME_NONE;
1511   }
1512
1513   if (parse->priv->upstream_seekable && parse->priv->exact_position &&
1514       GST_BUFFER_TIMESTAMP_IS_VALID (buffer))
1515     gst_base_parse_add_index_entry (parse, offset,
1516         GST_BUFFER_TIMESTAMP (buffer),
1517         !GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT), FALSE);
1518
1519   /* First buffers are dropped, this means that the subclass needs more
1520    * frames to decide on the format and queues them internally */
1521   /* convert internal flow to OK and mark discont for the next buffer. */
1522   if (ret == GST_BASE_PARSE_FLOW_DROPPED) {
1523     gst_base_parse_frame_clear (parse, frame);
1524     return GST_FLOW_OK;
1525   } else if (ret != GST_FLOW_OK) {
1526     return ret;
1527   }
1528
1529   return gst_base_parse_push_frame (parse, frame);
1530 }
1531
1532 /**
1533  * gst_base_parse_push_frame:
1534  * @parse: #GstBaseParse.
1535  * @frame: #GstBaseParseFrame.
1536  *
1537  * Pushes the frame downstream, sends any pending events and
1538  * does some timestamp and segment handling.
1539  *
1540  * This must be called with sinkpad STREAM_LOCK held.
1541  *
1542  * Returns: #GstFlowReturn
1543  */
1544 GstFlowReturn
1545 gst_base_parse_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1546 {
1547   GstFlowReturn ret = GST_FLOW_OK;
1548   GstClockTime last_start = GST_CLOCK_TIME_NONE;
1549   GstClockTime last_stop = GST_CLOCK_TIME_NONE;
1550   GstBaseParseClass *klass = GST_BASE_PARSE_GET_CLASS (parse);
1551   GstBuffer *buffer;
1552
1553   g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR);
1554   g_return_val_if_fail (frame->buffer != NULL, GST_FLOW_ERROR);
1555
1556   buffer = frame->buffer;
1557
1558   GST_LOG_OBJECT (parse,
1559       "processing buffer of size %d with ts %" GST_TIME_FORMAT
1560       ", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buffer),
1561       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
1562       GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
1563
1564   /* update stats */
1565   parse->priv->bytecount += GST_BUFFER_SIZE (buffer);
1566   if (G_LIKELY (!(frame->flags & GST_BASE_PARSE_FRAME_FLAG_NO_FRAME))) {
1567     parse->priv->framecount++;
1568     if (GST_BUFFER_DURATION_IS_VALID (buffer)) {
1569       parse->priv->acc_duration += GST_BUFFER_DURATION (buffer);
1570     }
1571   }
1572   if (parse->priv->update_interval &&
1573       (parse->priv->framecount % parse->priv->update_interval) == 0)
1574     gst_base_parse_update_duration (parse);
1575
1576   if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer))
1577     last_start = last_stop = GST_BUFFER_TIMESTAMP (buffer);
1578   if (last_start != GST_CLOCK_TIME_NONE
1579       && GST_BUFFER_DURATION_IS_VALID (buffer))
1580     last_stop = last_start + GST_BUFFER_DURATION (buffer);
1581
1582   /* should have caps by now */
1583   g_return_val_if_fail (GST_PAD_CAPS (parse->srcpad), GST_FLOW_ERROR);
1584
1585   /* segment adjustment magic; only if we are running the whole show */
1586   if (!parse->priv->passthrough && parse->segment.rate > 0.0 &&
1587       (parse->priv->pad_mode == GST_ACTIVATE_PULL ||
1588           parse->priv->upstream_seekable)) {
1589     /* segment times are typically estimates,
1590      * actual frame data might lead subclass to different timestamps,
1591      * so override segment start from what is supplied there */
1592     if (G_UNLIKELY (parse->pending_segment && !parse->priv->exact_position &&
1593             GST_CLOCK_TIME_IS_VALID (last_start))) {
1594       gst_event_unref (parse->pending_segment);
1595       parse->segment.start =
1596           MIN ((guint64) last_start, (guint64) parse->segment.stop);
1597       GST_DEBUG_OBJECT (parse,
1598           "adjusting pending segment start to %" GST_TIME_FORMAT,
1599           GST_TIME_ARGS (parse->segment.start));
1600       parse->pending_segment =
1601           gst_event_new_new_segment (FALSE, parse->segment.rate,
1602           parse->segment.format, parse->segment.start, parse->segment.stop,
1603           parse->segment.start);
1604     }
1605     /* handle gaps, e.g. non-zero start-time, in as much not handled by above */
1606     if (GST_CLOCK_TIME_IS_VALID (parse->segment.last_stop) &&
1607         GST_CLOCK_TIME_IS_VALID (last_start)) {
1608       GstClockTimeDiff diff;
1609
1610       /* only send newsegments with increasing start times,
1611        * otherwise if these go back and forth downstream (sinks) increase
1612        * accumulated time and running_time */
1613       diff = GST_CLOCK_DIFF (parse->segment.last_stop, last_start);
1614       if (G_UNLIKELY (diff > 2 * GST_SECOND && last_start > parse->segment.start
1615               && (!GST_CLOCK_TIME_IS_VALID (parse->segment.stop) ||
1616                   last_start < parse->segment.stop))) {
1617         GST_DEBUG_OBJECT (parse,
1618             "Gap of %" G_GINT64_FORMAT " ns detected in stream "
1619             "(%" GST_TIME_FORMAT " -> %" GST_TIME_FORMAT "). "
1620             "Sending updated NEWSEGMENT events", diff,
1621             GST_TIME_ARGS (parse->segment.last_stop),
1622             GST_TIME_ARGS (last_start));
1623         if (G_UNLIKELY (parse->pending_segment)) {
1624           gst_event_unref (parse->pending_segment);
1625           parse->segment.start = last_start;
1626           parse->pending_segment =
1627               gst_event_new_new_segment (FALSE, parse->segment.rate,
1628               parse->segment.format, parse->segment.start, parse->segment.stop,
1629               parse->segment.start);
1630         } else {
1631           /* send newsegment events such that the gap is not accounted in
1632            * accum time, hence running_time */
1633           /* close ahead of gap */
1634           gst_pad_push_event (parse->srcpad,
1635               gst_event_new_new_segment (TRUE, parse->segment.rate,
1636                   parse->segment.format, parse->segment.last_stop,
1637                   parse->segment.last_stop, parse->segment.last_stop));
1638           /* skip gap */
1639           gst_pad_push_event (parse->srcpad,
1640               gst_event_new_new_segment (FALSE, parse->segment.rate,
1641                   parse->segment.format, last_start, parse->segment.stop,
1642                   last_start));
1643         }
1644         /* align segment view with downstream,
1645          * prevents double-counting accum when closing segment */
1646         gst_segment_set_newsegment (&parse->segment, FALSE,
1647             parse->segment.rate, parse->segment.format, last_start,
1648             parse->segment.stop, last_start);
1649         parse->segment.last_stop = last_start;
1650       }
1651     }
1652   }
1653
1654   /* and should then also be linked downstream, so safe to send some events */
1655   if (G_UNLIKELY (parse->close_segment)) {
1656     /* only set up by loop */
1657     GST_DEBUG_OBJECT (parse, "loop sending close segment");
1658     gst_pad_push_event (parse->srcpad, parse->close_segment);
1659     parse->close_segment = NULL;
1660   }
1661   if (G_UNLIKELY (parse->pending_segment)) {
1662     GST_DEBUG_OBJECT (parse, "%s push pending segment",
1663         parse->priv->pad_mode == GST_ACTIVATE_PULL ? "loop" : "chain");
1664     gst_pad_push_event (parse->srcpad, parse->pending_segment);
1665     parse->pending_segment = NULL;
1666
1667     /* have caps; check identity */
1668     gst_base_parse_check_media (parse);
1669   }
1670
1671   /* update bitrates and optionally post corresponding tags
1672    * (following newsegment) */
1673   gst_base_parse_update_bitrates (parse, frame);
1674
1675   if (G_UNLIKELY (parse->priv->pending_events)) {
1676     GList *l;
1677
1678     for (l = parse->priv->pending_events; l != NULL; l = l->next) {
1679       gst_pad_push_event (parse->srcpad, GST_EVENT (l->data));
1680     }
1681     g_list_free (parse->priv->pending_events);
1682     parse->priv->pending_events = NULL;
1683   }
1684
1685   if (klass->pre_push_frame) {
1686     ret = klass->pre_push_frame (parse, frame);
1687   } else {
1688     frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
1689   }
1690
1691   /* take final ownership of frame buffer */
1692   buffer = frame->buffer;
1693   frame->buffer = NULL;
1694
1695   /* subclass must play nice */
1696   g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
1697
1698   /* decorate */
1699   gst_buffer_set_caps (buffer, GST_PAD_CAPS (parse->srcpad));
1700
1701   parse->priv->seen_keyframe |= parse->priv->is_video &&
1702       !GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
1703
1704   if (frame->flags & GST_BASE_PARSE_FRAME_FLAG_CLIP) {
1705     if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
1706         GST_CLOCK_TIME_IS_VALID (parse->segment.stop) &&
1707         GST_BUFFER_TIMESTAMP (buffer) >
1708         parse->segment.stop + parse->priv->lead_out_ts) {
1709       GST_LOG_OBJECT (parse, "Dropped frame, after segment");
1710       ret = GST_FLOW_UNEXPECTED;
1711     } else if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
1712         GST_BUFFER_DURATION_IS_VALID (buffer) &&
1713         GST_CLOCK_TIME_IS_VALID (parse->segment.start) &&
1714         GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer) +
1715         parse->priv->lead_in_ts < parse->segment.start) {
1716       if (parse->priv->seen_keyframe) {
1717         GST_LOG_OBJECT (parse, "Frame before segment, after keyframe");
1718         ret = GST_FLOW_OK;
1719       } else {
1720         GST_LOG_OBJECT (parse, "Dropped frame, before segment");
1721         ret = GST_BASE_PARSE_FLOW_DROPPED;
1722       }
1723     } else {
1724       ret = GST_FLOW_OK;
1725     }
1726   }
1727
1728   if (ret == GST_BASE_PARSE_FLOW_DROPPED) {
1729     GST_LOG_OBJECT (parse, "frame (%d bytes) dropped",
1730         GST_BUFFER_SIZE (buffer));
1731     gst_buffer_unref (buffer);
1732     ret = GST_FLOW_OK;
1733   } else if (ret == GST_FLOW_OK) {
1734     if (parse->segment.rate > 0.0) {
1735       ret = gst_pad_push (parse->srcpad, buffer);
1736       GST_LOG_OBJECT (parse, "frame (%d bytes) pushed: %s",
1737           GST_BUFFER_SIZE (buffer), gst_flow_get_name (ret));
1738     } else {
1739       GST_LOG_OBJECT (parse, "frame (%d bytes) queued for now",
1740           GST_BUFFER_SIZE (buffer));
1741       parse->priv->buffers_queued =
1742           g_slist_prepend (parse->priv->buffers_queued, buffer);
1743       ret = GST_FLOW_OK;
1744     }
1745   } else {
1746     gst_buffer_unref (buffer);
1747     GST_LOG_OBJECT (parse, "frame (%d bytes) not pushed: %s",
1748         GST_BUFFER_SIZE (buffer), gst_flow_get_name (ret));
1749     /* if we are not sufficiently in control, let upstream decide on EOS */
1750     if (ret == GST_FLOW_UNEXPECTED &&
1751         (parse->priv->passthrough ||
1752             (parse->priv->pad_mode == GST_ACTIVATE_PUSH &&
1753                 !parse->priv->upstream_seekable)))
1754       ret = GST_FLOW_OK;
1755   }
1756
1757   /* Update current running segment position */
1758   if (ret == GST_FLOW_OK && last_stop != GST_CLOCK_TIME_NONE &&
1759       parse->segment.last_stop < last_stop)
1760     gst_segment_set_last_stop (&parse->segment, GST_FORMAT_TIME, last_stop);
1761
1762   gst_base_parse_frame_clear (parse, frame);
1763
1764   return ret;
1765 }
1766
1767
1768 /**
1769  * gst_base_parse_drain:
1770  * @parse: #GstBaseParse.
1771  *
1772  * Drains the adapter until it is empty. It decreases the min_frame_size to
1773  * match the current adapter size and calls chain method until the adapter
1774  * is emptied or chain returns with error.
1775  */
1776 static void
1777 gst_base_parse_drain (GstBaseParse * parse)
1778 {
1779   guint avail;
1780
1781   GST_DEBUG_OBJECT (parse, "draining");
1782   parse->priv->drain = TRUE;
1783
1784   for (;;) {
1785     avail = gst_adapter_available (parse->adapter);
1786     if (!avail)
1787       break;
1788
1789     if (gst_base_parse_chain (parse->sinkpad, NULL) != GST_FLOW_OK) {
1790       break;
1791     }
1792
1793     /* nothing changed, maybe due to truncated frame; break infinite loop */
1794     if (avail == gst_adapter_available (parse->adapter)) {
1795       GST_DEBUG_OBJECT (parse, "no change during draining; flushing");
1796       gst_adapter_clear (parse->adapter);
1797     }
1798   }
1799
1800   parse->priv->drain = FALSE;
1801 }
1802
1803 /**
1804  * gst_base_parse_process_fragment:
1805  * @parse: #GstBaseParse.
1806  *
1807  * Processes a reverse playback (forward) fragment:
1808  * - append head of last fragment that was skipped to current fragment data
1809  * - drain the resulting current fragment data (i.e. repeated chain)
1810  * - add time/duration (if needed) to frames queued by chain
1811  * - push queued data
1812  */
1813 static GstFlowReturn
1814 gst_base_parse_process_fragment (GstBaseParse * parse, gboolean push_only)
1815 {
1816   GstBuffer *buf;
1817   GstFlowReturn ret = GST_FLOW_OK;
1818   GSList *send = NULL;
1819
1820   if (push_only)
1821     goto push;
1822
1823   /* restore order */
1824   parse->priv->buffers_pending = g_slist_reverse (parse->priv->buffers_pending);
1825   while (parse->priv->buffers_pending) {
1826     buf = GST_BUFFER_CAST (parse->priv->buffers_pending->data);
1827     GST_LOG_OBJECT (parse, "adding pending buffer (size %d)",
1828         GST_BUFFER_SIZE (buf));
1829     gst_adapter_push (parse->adapter, buf);
1830     parse->priv->buffers_pending =
1831         g_slist_delete_link (parse->priv->buffers_pending,
1832         parse->priv->buffers_pending);
1833   }
1834
1835   /* invalidate so no fall-back timestamping is performed;
1836    * ok if taken from subclass or upstream */
1837   parse->priv->next_ts = GST_CLOCK_TIME_NONE;
1838   /* prevent it hanging around stop all the time */
1839   parse->segment.last_stop = GST_CLOCK_TIME_NONE;
1840   /* mark next run */
1841   parse->priv->discont = TRUE;
1842
1843   /* chain looks for frames and queues resulting ones (in stead of pushing) */
1844   /* initial skipped data is added to buffers_pending */
1845   gst_base_parse_drain (parse);
1846
1847 push:
1848   /* add metadata (if needed to queued buffers */
1849   GST_LOG_OBJECT (parse, "last timestamp: %" GST_TIME_FORMAT,
1850       GST_TIME_ARGS (parse->priv->last_ts));
1851   while (parse->priv->buffers_queued) {
1852     buf = GST_BUFFER_CAST (parse->priv->buffers_queued->data);
1853
1854     /* no touching if upstream or parsing provided time */
1855     if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
1856       GST_LOG_OBJECT (parse, "buffer has time %" GST_TIME_FORMAT,
1857           GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
1858     } else if (GST_CLOCK_TIME_IS_VALID (parse->priv->last_ts) &&
1859         GST_BUFFER_DURATION_IS_VALID (buf)) {
1860       if (G_LIKELY (GST_BUFFER_DURATION (buf) <= parse->priv->last_ts))
1861         parse->priv->last_ts -= GST_BUFFER_DURATION (buf);
1862       else
1863         parse->priv->last_ts = 0;
1864       GST_BUFFER_TIMESTAMP (buf) = parse->priv->last_ts;
1865       GST_LOG_OBJECT (parse, "applied time %" GST_TIME_FORMAT,
1866           GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
1867     } else {
1868       /* no idea, very bad */
1869       GST_WARNING_OBJECT (parse, "could not determine time for buffer");
1870     }
1871
1872     /* reverse order for ascending sending */
1873     send = g_slist_prepend (send, buf);
1874     parse->priv->buffers_queued =
1875         g_slist_delete_link (parse->priv->buffers_queued,
1876         parse->priv->buffers_queued);
1877   }
1878
1879   /* send buffers */
1880   while (send) {
1881     buf = GST_BUFFER_CAST (send->data);
1882     GST_LOG_OBJECT (parse, "pushing buffer %p, timestamp %"
1883         GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT
1884         ", offset %" G_GINT64_FORMAT, buf,
1885         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
1886         GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_OFFSET (buf));
1887
1888     if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (parse->priv->last_ts)))
1889       parse->priv->last_ts = GST_BUFFER_TIMESTAMP (buf);
1890
1891     /* iterate output queue an push downstream */
1892     ret = gst_pad_push (parse->srcpad, buf);
1893     send = g_slist_delete_link (send, send);
1894
1895     /* clear any leftover if error */
1896     if (G_UNLIKELY (ret != GST_FLOW_OK)) {
1897       while (send) {
1898         buf = GST_BUFFER_CAST (send->data);
1899         gst_buffer_unref (buf);
1900         send = g_slist_delete_link (send, send);
1901       }
1902     }
1903   }
1904
1905   /* any trailing unused no longer usable (ideally none) */
1906   if (G_UNLIKELY (gst_adapter_available (parse->adapter))) {
1907     GST_DEBUG_OBJECT (parse, "discarding %d trailing bytes",
1908         gst_adapter_available (parse->adapter));
1909     gst_adapter_clear (parse->adapter);
1910   }
1911
1912   return ret;
1913 }
1914
1915 /* small helper that checks whether we have been trying to resync too long */
1916 static inline GstFlowReturn
1917 gst_base_parse_check_sync (GstBaseParse * parse)
1918 {
1919   if (G_UNLIKELY (parse->priv->discont &&
1920           parse->priv->offset - parse->priv->sync_offset > 2 * 1024 * 1024)) {
1921     GST_ELEMENT_ERROR (parse, STREAM, DECODE,
1922         ("Failed to parse stream"), (NULL));
1923     return GST_FLOW_ERROR;
1924   }
1925
1926   return GST_FLOW_OK;
1927 }
1928
1929
1930 /**
1931  * gst_base_parse_chain:
1932  * @pad: #GstPad.
1933  * @buffer: #GstBuffer.
1934  *
1935  * Returns: #GstFlowReturn.
1936  */
1937 static GstFlowReturn
1938 gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
1939 {
1940   GstBaseParseClass *bclass;
1941   GstBaseParse *parse;
1942   GstFlowReturn ret = GST_FLOW_OK;
1943   GstBuffer *outbuf = NULL;
1944   GstBuffer *tmpbuf = NULL;
1945   guint fsize = 0;
1946   gint skip = -1;
1947   const guint8 *data;
1948   guint old_min_size = 0, min_size, av;
1949   GstClockTime timestamp;
1950   GstBaseParseFrame _frame = { 0, };
1951   GstBaseParseFrame *frame;
1952
1953   parse = GST_BASE_PARSE (GST_OBJECT_PARENT (pad));
1954   bclass = GST_BASE_PARSE_GET_CLASS (parse);
1955   frame = &_frame;
1956
1957   if (G_LIKELY (buffer)) {
1958     GST_LOG_OBJECT (parse, "buffer size: %d, offset = %" G_GINT64_FORMAT,
1959         GST_BUFFER_SIZE (buffer), GST_BUFFER_OFFSET (buffer));
1960     if (G_UNLIKELY (parse->priv->passthrough)) {
1961       frame->buffer = gst_buffer_make_metadata_writable (buffer);
1962       return gst_base_parse_push_frame (parse, frame);
1963     }
1964     /* upstream feeding us in reverse playback;
1965      * gather each fragment, then process it in single run */
1966     if (parse->segment.rate < 0.0) {
1967       if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))) {
1968         GST_DEBUG_OBJECT (parse, "buffer starts new reverse playback fragment");
1969         ret = gst_base_parse_process_fragment (parse, FALSE);
1970       }
1971       gst_adapter_push (parse->adapter, buffer);
1972       return ret;
1973     }
1974     gst_adapter_push (parse->adapter, buffer);
1975   }
1976
1977   /* Parse and push as many frames as possible */
1978   /* Stop either when adapter is empty or we are flushing */
1979   while (!parse->priv->flushing) {
1980     gboolean res;
1981
1982     tmpbuf = gst_buffer_new ();
1983
1984     old_min_size = 0;
1985     /* Synchronization loop */
1986     for (;;) {
1987       min_size = MAX (parse->priv->min_frame_size, fsize);
1988       av = gst_adapter_available (parse->adapter);
1989
1990       /* loop safety check */
1991       if (G_UNLIKELY (old_min_size >= min_size))
1992         goto invalid_min;
1993       old_min_size = min_size;
1994
1995       if (G_UNLIKELY (parse->priv->drain)) {
1996         min_size = av;
1997         GST_DEBUG_OBJECT (parse, "draining, data left: %d", min_size);
1998         if (G_UNLIKELY (!min_size)) {
1999           gst_buffer_unref (tmpbuf);
2000           goto done;
2001         }
2002       }
2003
2004       /* Collect at least min_frame_size bytes */
2005       if (av < min_size) {
2006         GST_DEBUG_OBJECT (parse, "not enough data available (only %d bytes)",
2007             av);
2008         gst_buffer_unref (tmpbuf);
2009         goto done;
2010       }
2011
2012       /* always pass all available data */
2013       data = gst_adapter_peek (parse->adapter, av);
2014       GST_BUFFER_DATA (tmpbuf) = (guint8 *) data;
2015       GST_BUFFER_SIZE (tmpbuf) = min_size;
2016       GST_BUFFER_OFFSET (tmpbuf) = parse->priv->offset;
2017       GST_BUFFER_FLAG_SET (tmpbuf, GST_MINI_OBJECT_FLAG_READONLY);
2018
2019       if (parse->priv->discont) {
2020         GST_DEBUG_OBJECT (parse, "marking DISCONT");
2021         GST_BUFFER_FLAG_SET (tmpbuf, GST_BUFFER_FLAG_DISCONT);
2022       }
2023
2024       skip = -1;
2025       gst_base_parse_frame_update (parse, frame, tmpbuf);
2026       res = bclass->check_valid_frame (parse, frame, &fsize, &skip);
2027       gst_buffer_replace (&frame->buffer, NULL);
2028       if (res) {
2029         if (gst_adapter_available (parse->adapter) < fsize) {
2030           GST_DEBUG_OBJECT (parse,
2031               "found valid frame but not enough data available (only %d bytes)",
2032               gst_adapter_available (parse->adapter));
2033           gst_buffer_unref (tmpbuf);
2034           goto done;
2035         }
2036         GST_LOG_OBJECT (parse, "valid frame of size %d at pos %d", fsize, skip);
2037         break;
2038       }
2039       if (skip == -1) {
2040         /* subclass didn't touch this value. By default we skip 1 byte */
2041         skip = 1;
2042       }
2043       if (skip > 0) {
2044         GST_LOG_OBJECT (parse, "finding sync, skipping %d bytes", skip);
2045         if (parse->segment.rate < 0.0 && !parse->priv->buffers_queued) {
2046           /* reverse playback, and no frames found yet, so we are skipping
2047            * the leading part of a fragment, which may form the tail of
2048            * fragment coming later, hopefully subclass skips efficiently ... */
2049           timestamp = gst_adapter_prev_timestamp (parse->adapter, NULL);
2050           outbuf = gst_adapter_take_buffer (parse->adapter, skip);
2051           outbuf = gst_buffer_make_metadata_writable (outbuf);
2052           GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
2053           parse->priv->buffers_pending =
2054               g_slist_prepend (parse->priv->buffers_pending, outbuf);
2055           outbuf = NULL;
2056         } else {
2057           gst_adapter_flush (parse->adapter, skip);
2058         }
2059         parse->priv->offset += skip;
2060         if (!parse->priv->discont)
2061           parse->priv->sync_offset = parse->priv->offset;
2062         parse->priv->discont = TRUE;
2063         /* something changed least; nullify loop check */
2064         old_min_size = 0;
2065       }
2066       /* skip == 0 should imply subclass set min_size to need more data;
2067        * we check this shortly */
2068       if ((ret = gst_base_parse_check_sync (parse)) != GST_FLOW_OK) {
2069         gst_buffer_unref (tmpbuf);
2070         goto done;
2071       }
2072     }
2073     gst_buffer_unref (tmpbuf);
2074     tmpbuf = NULL;
2075
2076     if (skip > 0) {
2077       /* Subclass found the sync, but still wants to skip some data */
2078       GST_LOG_OBJECT (parse, "skipping %d bytes", skip);
2079       gst_adapter_flush (parse->adapter, skip);
2080       parse->priv->offset += skip;
2081     }
2082
2083     /* Grab lock to prevent a race with FLUSH_START handler */
2084     GST_PAD_STREAM_LOCK (parse->srcpad);
2085
2086     /* FLUSH_START event causes the "flushing" flag to be set. In this
2087      * case we can leave the frame pushing loop */
2088     if (parse->priv->flushing) {
2089       GST_PAD_STREAM_UNLOCK (parse->srcpad);
2090       break;
2091     }
2092
2093     /* FIXME: Would it be more efficient to make a subbuffer instead? */
2094     outbuf = gst_adapter_take_buffer (parse->adapter, fsize);
2095     outbuf = gst_buffer_make_metadata_writable (outbuf);
2096
2097     /* Subclass may want to know the data offset */
2098     GST_BUFFER_OFFSET (outbuf) = parse->priv->offset;
2099     parse->priv->offset += fsize;
2100     GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE;
2101
2102     /* move along with upstream timestamp (if any),
2103      * but interpolate in between */
2104     timestamp = gst_adapter_prev_timestamp (parse->adapter, NULL);
2105     if (GST_CLOCK_TIME_IS_VALID (timestamp) &&
2106         (parse->priv->prev_ts != timestamp)) {
2107       parse->priv->prev_ts = parse->priv->next_ts = timestamp;
2108     }
2109
2110     frame->buffer = outbuf;
2111     ret = gst_base_parse_handle_and_push_frame (parse, bclass, frame);
2112     GST_PAD_STREAM_UNLOCK (parse->srcpad);
2113
2114     if (ret != GST_FLOW_OK) {
2115       GST_LOG_OBJECT (parse, "push returned %d", ret);
2116       break;
2117     }
2118   }
2119
2120 done:
2121   GST_LOG_OBJECT (parse, "chain leaving");
2122   return ret;
2123
2124   /* ERRORS */
2125 invalid_min:
2126   {
2127     GST_ELEMENT_ERROR (parse, STREAM, FAILED, (NULL),
2128         ("min_size evolution %d -> %d; breaking to avoid looping",
2129             old_min_size, min_size));
2130     return GST_FLOW_ERROR;
2131   }
2132 }
2133
2134 /* pull @size bytes at current offset,
2135  * i.e. at least try to and possibly return a shorter buffer if near the end */
2136 static GstFlowReturn
2137 gst_base_parse_pull_range (GstBaseParse * parse, guint size,
2138     GstBuffer ** buffer)
2139 {
2140   GstFlowReturn ret = GST_FLOW_OK;
2141
2142   g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
2143
2144   /* Caching here actually makes much less difference than one would expect.
2145    * We do it mainly to avoid pulling buffers of 1 byte all the time */
2146   if (parse->priv->cache) {
2147     gint64 cache_offset = GST_BUFFER_OFFSET (parse->priv->cache);
2148     gint cache_size = GST_BUFFER_SIZE (parse->priv->cache);
2149
2150     if (cache_offset <= parse->priv->offset &&
2151         (parse->priv->offset + size) <= (cache_offset + cache_size)) {
2152       *buffer = gst_buffer_create_sub (parse->priv->cache,
2153           parse->priv->offset - cache_offset, size);
2154       GST_BUFFER_OFFSET (*buffer) = parse->priv->offset;
2155       return GST_FLOW_OK;
2156     }
2157     /* not enough data in the cache, free cache and get a new one */
2158     gst_buffer_unref (parse->priv->cache);
2159     parse->priv->cache = NULL;
2160   }
2161
2162   /* refill the cache */
2163   ret =
2164       gst_pad_pull_range (parse->sinkpad, parse->priv->offset, MAX (size,
2165           64 * 1024), &parse->priv->cache);
2166   if (ret != GST_FLOW_OK) {
2167     parse->priv->cache = NULL;
2168     return ret;
2169   }
2170
2171   if (GST_BUFFER_SIZE (parse->priv->cache) >= size) {
2172     *buffer = gst_buffer_create_sub (parse->priv->cache, 0, size);
2173     GST_BUFFER_OFFSET (*buffer) = parse->priv->offset;
2174     return GST_FLOW_OK;
2175   }
2176
2177   /* Not possible to get enough data, try a last time with
2178    * requesting exactly the size we need */
2179   gst_buffer_unref (parse->priv->cache);
2180   parse->priv->cache = NULL;
2181
2182   ret = gst_pad_pull_range (parse->sinkpad, parse->priv->offset, size,
2183       &parse->priv->cache);
2184
2185   if (ret != GST_FLOW_OK) {
2186     GST_DEBUG_OBJECT (parse, "pull_range returned %d", ret);
2187     *buffer = NULL;
2188     return ret;
2189   }
2190
2191   if (GST_BUFFER_SIZE (parse->priv->cache) < size) {
2192     GST_DEBUG_OBJECT (parse, "Returning short buffer at offset %"
2193         G_GUINT64_FORMAT ": wanted %u bytes, got %u bytes", parse->priv->offset,
2194         size, GST_BUFFER_SIZE (parse->priv->cache));
2195
2196     *buffer = parse->priv->cache;
2197     parse->priv->cache = NULL;
2198
2199     return GST_FLOW_OK;
2200   }
2201
2202   *buffer = gst_buffer_create_sub (parse->priv->cache, 0, size);
2203   GST_BUFFER_OFFSET (*buffer) = parse->priv->offset;
2204
2205   return GST_FLOW_OK;
2206 }
2207
2208 static GstFlowReturn
2209 gst_base_parse_handle_previous_fragment (GstBaseParse * parse)
2210 {
2211   gint64 offset = 0;
2212   GstClockTime ts = 0;
2213   GstBuffer *buffer;
2214   GstFlowReturn ret;
2215
2216   GST_DEBUG_OBJECT (parse, "fragment ended; last_ts = %" GST_TIME_FORMAT
2217       ", last_offset = %" G_GINT64_FORMAT, GST_TIME_ARGS (parse->priv->last_ts),
2218       parse->priv->last_offset);
2219
2220   if (!parse->priv->last_offset || parse->priv->last_ts <= parse->segment.start) {
2221     GST_DEBUG_OBJECT (parse, "past start of segment %" GST_TIME_FORMAT,
2222         GST_TIME_ARGS (parse->segment.start));
2223     ret = GST_FLOW_UNEXPECTED;
2224     goto exit;
2225   }
2226
2227   /* last fragment started at last_offset / last_ts;
2228    * seek back 10s capped at 1MB */
2229   if (parse->priv->last_ts >= 10 * GST_SECOND)
2230     ts = parse->priv->last_ts - 10 * GST_SECOND;
2231   /* if we are exact now, we will be more so going backwards */
2232   if (parse->priv->exact_position) {
2233     offset = gst_base_parse_find_offset (parse, ts, TRUE, NULL);
2234   } else {
2235     GstFormat dstformat = GST_FORMAT_BYTES;
2236
2237     if (!gst_pad_query_convert (parse->srcpad, GST_FORMAT_TIME, ts,
2238             &dstformat, &offset)) {
2239       GST_DEBUG_OBJECT (parse, "conversion failed, only BYTE based");
2240     }
2241   }
2242   offset = CLAMP (offset, parse->priv->last_offset - 1024 * 1024,
2243       parse->priv->last_offset - 1024);
2244   offset = MAX (0, offset);
2245
2246   GST_DEBUG_OBJECT (parse, "next fragment from offset %" G_GINT64_FORMAT,
2247       offset);
2248   parse->priv->offset = offset;
2249
2250   ret = gst_base_parse_pull_range (parse, parse->priv->last_offset - offset,
2251       &buffer);
2252   if (ret != GST_FLOW_OK)
2253     goto exit;
2254
2255   /* offset will increase again as fragment is processed/parsed */
2256   parse->priv->last_offset = offset;
2257
2258   gst_adapter_push (parse->adapter, buffer);
2259   ret = gst_base_parse_process_fragment (parse, FALSE);
2260   if (ret != GST_FLOW_OK)
2261     goto exit;
2262
2263   /* force previous fragment */
2264   parse->priv->offset = -1;
2265
2266 exit:
2267   return ret;
2268 }
2269
2270 /* PULL mode:
2271  * pull and scan for next frame starting from current offset
2272  * ajusts sync, drain and offset going along */
2273 static GstFlowReturn
2274 gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass,
2275     GstBaseParseFrame * frame, gboolean full)
2276 {
2277   GstBuffer *buffer, *outbuf;
2278   GstFlowReturn ret = GST_FLOW_OK;
2279   guint fsize = 0, min_size, old_min_size = 0;
2280   gint skip = 0;
2281
2282   g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR);
2283
2284   GST_LOG_OBJECT (parse, "scanning for frame at offset %" G_GUINT64_FORMAT
2285       " (%#" G_GINT64_MODIFIER "x)", parse->priv->offset, parse->priv->offset);
2286
2287   while (TRUE) {
2288     gboolean res;
2289
2290     min_size = MAX (parse->priv->min_frame_size, fsize);
2291     /* loop safety check */
2292     if (G_UNLIKELY (old_min_size >= min_size))
2293       goto invalid_min;
2294     old_min_size = min_size;
2295
2296     ret = gst_base_parse_pull_range (parse, min_size, &buffer);
2297     if (ret != GST_FLOW_OK)
2298       goto done;
2299
2300     if (parse->priv->discont) {
2301       GST_DEBUG_OBJECT (parse, "marking DISCONT");
2302       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
2303     }
2304
2305     /* if we got a short read, inform subclass we are draining leftover
2306      * and no more is to be expected */
2307     if (GST_BUFFER_SIZE (buffer) < min_size)
2308       parse->priv->drain = TRUE;
2309
2310     skip = -1;
2311     gst_base_parse_frame_update (parse, frame, buffer);
2312     res = klass->check_valid_frame (parse, frame, &fsize, &skip);
2313     gst_buffer_replace (&frame->buffer, NULL);
2314     if (res) {
2315       parse->priv->drain = FALSE;
2316       GST_LOG_OBJECT (parse, "valid frame of size %d at pos %d", fsize, skip);
2317       break;
2318     }
2319     parse->priv->drain = FALSE;
2320     if (skip == -1)
2321       skip = 1;
2322     if (skip > 0) {
2323       GST_LOG_OBJECT (parse, "finding sync, skipping %d bytes", skip);
2324       if (full && parse->segment.rate < 0.0 && !parse->priv->buffers_queued) {
2325         /* reverse playback, and no frames found yet, so we are skipping
2326          * the leading part of a fragment, which may form the tail of
2327          * fragment coming later, hopefully subclass skips efficiently ... */
2328         outbuf = gst_buffer_create_sub (buffer, 0, skip);
2329         parse->priv->buffers_pending =
2330             g_slist_prepend (parse->priv->buffers_pending, outbuf);
2331         outbuf = NULL;
2332       }
2333       parse->priv->offset += skip;
2334       if (!parse->priv->discont)
2335         parse->priv->sync_offset = parse->priv->offset;
2336       parse->priv->discont = TRUE;
2337       /* something changed least; nullify loop check */
2338       old_min_size = 0;
2339     }
2340     /* skip == 0 should imply subclass set min_size to need more data;
2341      * we check this shortly */
2342     GST_DEBUG_OBJECT (parse, "finding sync...");
2343     gst_buffer_unref (buffer);
2344     if ((ret = gst_base_parse_check_sync (parse)) != GST_FLOW_OK) {
2345       goto done;
2346     }
2347   }
2348
2349   /* Does the subclass want to skip too? */
2350   if (skip > 0)
2351     parse->priv->offset += skip;
2352   else if (skip < 0)
2353     skip = 0;
2354
2355   if (fsize + skip <= GST_BUFFER_SIZE (buffer)) {
2356     outbuf = gst_buffer_create_sub (buffer, skip, fsize);
2357     GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET (buffer) + skip;
2358     GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE;
2359     gst_buffer_unref (buffer);
2360   } else {
2361     gst_buffer_unref (buffer);
2362     ret = gst_base_parse_pull_range (parse, fsize, &outbuf);
2363     if (ret != GST_FLOW_OK)
2364       goto done;
2365     if (GST_BUFFER_SIZE (outbuf) < fsize) {
2366       gst_buffer_unref (outbuf);
2367       ret = GST_FLOW_UNEXPECTED;
2368     }
2369   }
2370
2371   parse->priv->offset += fsize;
2372
2373   frame->buffer = outbuf;
2374
2375 done:
2376   return ret;
2377
2378   /* ERRORS */
2379 invalid_min:
2380   {
2381     GST_ELEMENT_ERROR (parse, STREAM, FAILED, (NULL),
2382         ("min_size evolution %d -> %d; breaking to avoid looping",
2383             old_min_size, min_size));
2384     return GST_FLOW_ERROR;
2385   }
2386 }
2387
2388 /**
2389  * gst_base_parse_loop:
2390  * @pad: GstPad
2391  *
2392  * Loop that is used in pull mode to retrieve data from upstream.
2393  */
2394 static void
2395 gst_base_parse_loop (GstPad * pad)
2396 {
2397   GstBaseParse *parse;
2398   GstBaseParseClass *klass;
2399   GstFlowReturn ret = GST_FLOW_OK;
2400   GstBaseParseFrame frame = { 0, };
2401
2402   parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
2403   klass = GST_BASE_PARSE_GET_CLASS (parse);
2404
2405   /* reverse playback:
2406    * first fragment (closest to stop time) is handled normally below,
2407    * then we pull in fragments going backwards */
2408   if (parse->segment.rate < 0.0) {
2409     /* check if we jumped back to a previous fragment,
2410      * which is a post-first fragment */
2411     if (parse->priv->offset < 0) {
2412       ret = gst_base_parse_handle_previous_fragment (parse);
2413       goto done;
2414     }
2415   }
2416
2417   ret = gst_base_parse_scan_frame (parse, klass, &frame, TRUE);
2418   if (ret != GST_FLOW_OK)
2419     goto done;
2420
2421   /* This always cleans up frame, even if error occurs */
2422   ret = gst_base_parse_handle_and_push_frame (parse, klass, &frame);
2423
2424   /* eat expected eos signalling past segment in reverse playback */
2425   if (parse->segment.rate < 0.0 && ret == GST_FLOW_UNEXPECTED &&
2426       parse->segment.last_stop >= parse->segment.stop) {
2427     GST_DEBUG_OBJECT (parse, "downstream has reached end of segment");
2428     /* push what was accumulated during loop run */
2429     gst_base_parse_process_fragment (parse, TRUE);
2430     /* force previous fragment */
2431     parse->priv->offset = -1;
2432     ret = GST_FLOW_OK;
2433   }
2434
2435 done:
2436   if (ret == GST_FLOW_UNEXPECTED)
2437     goto eos;
2438   else if (ret != GST_FLOW_OK)
2439     goto pause;
2440
2441   gst_object_unref (parse);
2442   return;
2443
2444   /* ERRORS */
2445 eos:
2446   {
2447     ret = GST_FLOW_UNEXPECTED;
2448     GST_DEBUG_OBJECT (parse, "eos");
2449     /* fall-through */
2450   }
2451 pause:
2452   {
2453     gboolean push_eos = FALSE;
2454
2455     GST_DEBUG_OBJECT (parse, "pausing task, reason %s",
2456         gst_flow_get_name (ret));
2457     gst_pad_pause_task (parse->sinkpad);
2458
2459     if (ret == GST_FLOW_UNEXPECTED) {
2460       /* handle end-of-stream/segment */
2461       if (parse->segment.flags & GST_SEEK_FLAG_SEGMENT) {
2462         gint64 stop;
2463
2464         if ((stop = parse->segment.stop) == -1)
2465           stop = parse->segment.duration;
2466
2467         GST_DEBUG_OBJECT (parse, "sending segment_done");
2468
2469         gst_element_post_message
2470             (GST_ELEMENT_CAST (parse),
2471             gst_message_new_segment_done (GST_OBJECT_CAST (parse),
2472                 GST_FORMAT_TIME, stop));
2473       } else {
2474         /* If we STILL have zero frames processed, fire an error */
2475         if (parse->priv->framecount == 0) {
2476           GST_ELEMENT_ERROR (parse, STREAM, WRONG_TYPE,
2477               ("No valid frames found before end of stream"), (NULL));
2478         }
2479         push_eos = TRUE;
2480       }
2481     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_UNEXPECTED) {
2482       /* for fatal errors we post an error message, wrong-state is
2483        * not fatal because it happens due to flushes and only means
2484        * that we should stop now. */
2485       GST_ELEMENT_ERROR (parse, STREAM, FAILED, (NULL),
2486           ("streaming stopped, reason %s", gst_flow_get_name (ret)));
2487       push_eos = TRUE;
2488     }
2489     if (push_eos) {
2490       /* newsegment before eos */
2491       if (parse->pending_segment) {
2492         gst_pad_push_event (parse->srcpad, parse->pending_segment);
2493         parse->pending_segment = NULL;
2494       }
2495       gst_pad_push_event (parse->srcpad, gst_event_new_eos ());
2496     }
2497     gst_object_unref (parse);
2498   }
2499 }
2500
2501
2502 /**
2503  * gst_base_parse_sink_activate:
2504  * @sinkpad: #GstPad to be activated.
2505  *
2506  * Returns: TRUE if activation succeeded.
2507  */
2508 static gboolean
2509 gst_base_parse_sink_activate (GstPad * sinkpad)
2510 {
2511   GstBaseParse *parse;
2512   gboolean result = TRUE;
2513
2514   parse = GST_BASE_PARSE (gst_pad_get_parent (sinkpad));
2515
2516   GST_DEBUG_OBJECT (parse, "sink activate");
2517
2518   if (gst_pad_check_pull_range (sinkpad)) {
2519     GST_DEBUG_OBJECT (parse, "trying to activate in pull mode");
2520     result = gst_pad_activate_pull (sinkpad, TRUE);
2521   } else {
2522     GST_DEBUG_OBJECT (parse, "trying to activate in push mode");
2523     result = gst_pad_activate_push (sinkpad, TRUE);
2524   }
2525
2526   GST_DEBUG_OBJECT (parse, "sink activate return %d", result);
2527   gst_object_unref (parse);
2528   return result;
2529 }
2530
2531
2532 /**
2533  * gst_base_parse_activate:
2534  * @parse: #GstBaseParse.
2535  * @active: TRUE if element will be activated, FALSE if deactivated.
2536  *
2537  * Returns: TRUE if the operation succeeded.
2538  */
2539 static gboolean
2540 gst_base_parse_activate (GstBaseParse * parse, gboolean active)
2541 {
2542   GstBaseParseClass *klass;
2543   gboolean result = FALSE;
2544
2545   GST_DEBUG_OBJECT (parse, "activate");
2546
2547   klass = GST_BASE_PARSE_GET_CLASS (parse);
2548
2549   if (active) {
2550     if (parse->priv->pad_mode == GST_ACTIVATE_NONE && klass->start)
2551       result = klass->start (parse);
2552   } else {
2553     /* We must make sure streaming has finished before resetting things
2554      * and calling the ::stop vfunc */
2555     GST_PAD_STREAM_LOCK (parse->sinkpad);
2556     GST_PAD_STREAM_UNLOCK (parse->sinkpad);
2557
2558     if (parse->priv->pad_mode != GST_ACTIVATE_NONE && klass->stop)
2559       result = klass->stop (parse);
2560
2561     parse->priv->pad_mode = GST_ACTIVATE_NONE;
2562   }
2563   GST_DEBUG_OBJECT (parse, "activate: %d", result);
2564   return result;
2565 }
2566
2567
2568 /**
2569  * gst_base_parse_sink_activate_push:
2570  * @pad: #GstPad to be (de)activated.
2571  * @active: TRUE when activating, FALSE when deactivating.
2572  *
2573  * Returns: TRUE if (de)activation succeeded.
2574  */
2575 static gboolean
2576 gst_base_parse_sink_activate_push (GstPad * pad, gboolean active)
2577 {
2578   gboolean result = TRUE;
2579   GstBaseParse *parse;
2580
2581   parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
2582
2583   GST_DEBUG_OBJECT (parse, "sink activate push");
2584
2585   result = gst_base_parse_activate (parse, active);
2586
2587   if (result)
2588     parse->priv->pad_mode = active ? GST_ACTIVATE_PUSH : GST_ACTIVATE_NONE;
2589
2590   GST_DEBUG_OBJECT (parse, "sink activate push: %d", result);
2591
2592   gst_object_unref (parse);
2593   return result;
2594 }
2595
2596
2597 /**
2598  * gst_base_parse_sink_activate_pull:
2599  * @sinkpad: #GstPad to be (de)activated.
2600  * @active: TRUE when activating, FALSE when deactivating.
2601  *
2602  * Returns: TRUE if (de)activation succeeded.
2603  */
2604 static gboolean
2605 gst_base_parse_sink_activate_pull (GstPad * sinkpad, gboolean active)
2606 {
2607   gboolean result = FALSE;
2608   GstBaseParse *parse;
2609
2610   parse = GST_BASE_PARSE (gst_pad_get_parent (sinkpad));
2611
2612   GST_DEBUG_OBJECT (parse, "activate pull");
2613
2614   result = gst_base_parse_activate (parse, active);
2615
2616   if (result) {
2617     if (active) {
2618       parse->pending_segment = gst_event_new_new_segment (FALSE,
2619           parse->segment.rate, parse->segment.format,
2620           parse->segment.start, parse->segment.stop, parse->segment.last_stop);
2621       result &= gst_pad_start_task (sinkpad,
2622           (GstTaskFunction) gst_base_parse_loop, sinkpad);
2623     } else {
2624       result &= gst_pad_stop_task (sinkpad);
2625     }
2626   }
2627
2628   if (result)
2629     parse->priv->pad_mode = active ? GST_ACTIVATE_PULL : GST_ACTIVATE_NONE;
2630
2631   GST_DEBUG_OBJECT (parse, "sink activate pull: %d", result);
2632
2633   gst_object_unref (parse);
2634   return result;
2635 }
2636
2637
2638 /**
2639  * gst_base_parse_set_duration:
2640  * @parse: #GstBaseParse.
2641  * @fmt: #GstFormat.
2642  * @duration: duration value.
2643  *
2644  * Sets the duration of the currently playing media. Subclass can use this
2645  * when it is able to determine duration and/or notices a change in the media
2646  * duration.  Alternatively, if @interval is non-zero (default), then stream
2647  * duration is determined based on estimated bitrate, and updated every @interval
2648  * frames. */
2649 void
2650 gst_base_parse_set_duration (GstBaseParse * parse,
2651     GstFormat fmt, gint64 duration, gint interval)
2652 {
2653   g_return_if_fail (parse != NULL);
2654
2655   if (parse->priv->upstream_has_duration) {
2656     GST_DEBUG_OBJECT (parse, "using upstream duration; discarding update");
2657     goto exit;
2658   }
2659
2660   if (duration != parse->priv->duration) {
2661     GstMessage *m;
2662
2663     m = gst_message_new_duration (GST_OBJECT (parse), fmt, duration);
2664     gst_element_post_message (GST_ELEMENT (parse), m);
2665
2666     /* TODO: what about duration tag? */
2667   }
2668   parse->priv->duration = duration;
2669   parse->priv->duration_fmt = fmt;
2670   GST_DEBUG_OBJECT (parse, "set duration: %" G_GINT64_FORMAT, duration);
2671   if (fmt == GST_FORMAT_TIME && GST_CLOCK_TIME_IS_VALID (duration)) {
2672     if (interval != 0) {
2673       GST_DEBUG_OBJECT (parse, "valid duration provided, disabling estimate");
2674       interval = 0;
2675     }
2676   }
2677   GST_DEBUG_OBJECT (parse, "set update interval: %d", interval);
2678   parse->priv->update_interval = interval;
2679 exit:
2680   return;
2681 }
2682
2683 /**
2684  * gst_base_parse_set_seek:
2685  * @parse: #GstBaseParse.
2686  * @seek: #GstBaseParseSeekable.
2687  * @abitrate: average bitrate.
2688  *
2689  * Sets whether and how the media is seekable (in time).
2690  * Also optionally provides average bitrate detected in media (if non-zero),
2691  * e.g. based on metadata, as it will be posted to the application.
2692  *
2693  * By default, announced average bitrate is estimated, and seekability is assumed
2694  * possible based on estimated bitrate.
2695  */
2696 void
2697 gst_base_parse_set_seek (GstBaseParse * parse,
2698     GstBaseParseSeekable seek, guint bitrate)
2699 {
2700   parse->priv->seekable = seek;
2701   parse->priv->bitrate = bitrate;
2702   GST_DEBUG_OBJECT (parse, "seek %d, bitrate %d", seek, bitrate);
2703 }
2704
2705
2706 /**
2707  * gst_base_parse_set_min_frame_size:
2708  * @parse: #GstBaseParse.
2709  * @min_size: Minimum size of the data that this base class should give to
2710  *            subclass.
2711  *
2712  * Subclass can use this function to tell the base class that it needs to
2713  * give at least #min_size buffers.
2714  */
2715 void
2716 gst_base_parse_set_min_frame_size (GstBaseParse * parse, guint min_size)
2717 {
2718   g_return_if_fail (parse != NULL);
2719
2720   parse->priv->min_frame_size = min_size;
2721   GST_LOG_OBJECT (parse, "set frame_min_size: %d", min_size);
2722 }
2723
2724 /**
2725  * gst_base_parse_set_passthrough:
2726  * @parse: the #GstBaseParse to set
2727  * @passthrough: boolean indicating passthrough mode.
2728  *
2729  * Set passthrough mode for this parser (which only applies operating in pull
2730  * mode).  If operating in passthrough, incoming buffers are pushed through
2731  * unmodified.  That is, no @check_valid_frame or @parse_frame callbacks
2732  * will be invoked.  On the ohter hand, @pre_push_buffer is still invoked,
2733  * where subclass can perform as much or as little is appropriate for
2734  * "passthrough" semantics.
2735  */
2736 void
2737 gst_base_parse_set_passthrough (GstBaseParse * parse, gboolean passthrough)
2738 {
2739   g_return_if_fail (parse != NULL);
2740
2741   parse->priv->passthrough = passthrough;
2742   GST_LOG_OBJECT (parse, "set passthrough: %d", passthrough);
2743 }
2744
2745 /**
2746  * gst_base_parse_set_frame_props:
2747  * @parse: the #GstBaseParse to set
2748  * @fps_num: frames per second (numerator).
2749  * @fps_den: frames per second (denominator).
2750  * @lead_in: frames needed before a segment for subsequent decode
2751  * @lead_out: frames needed after a segment
2752  *
2753  * If frames per second is configured, parser can take care of buffer duration
2754  * and timestamping.  When performing segment clipping, or seeking to a specific
2755  * location, a corresponding decoder might need an initial @lead_in and a
2756  * following @lead_out number of frames to ensure the desired segment is
2757  * entirely filled upon decoding.
2758  */
2759 void
2760 gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num,
2761     guint fps_den, guint lead_in, guint lead_out)
2762 {
2763   g_return_if_fail (parse != NULL);
2764
2765   parse->priv->fps_num = fps_num;
2766   parse->priv->fps_den = fps_den;
2767   if (!fps_num || !fps_den) {
2768     GST_DEBUG_OBJECT (parse, "invalid fps (%d/%d), ignoring parameters",
2769         fps_num, fps_den);
2770     fps_num = fps_den = 0;
2771     parse->priv->frame_duration = GST_CLOCK_TIME_NONE;
2772     parse->priv->lead_in = parse->priv->lead_out = 0;
2773     parse->priv->lead_in_ts = parse->priv->lead_out_ts = 0;
2774   } else {
2775     parse->priv->frame_duration =
2776         gst_util_uint64_scale (GST_SECOND, fps_den, fps_num);
2777     parse->priv->lead_in = lead_in;
2778     parse->priv->lead_out = lead_out;
2779     parse->priv->lead_in_ts =
2780         gst_util_uint64_scale (GST_SECOND, fps_den * lead_in, fps_num);
2781     parse->priv->lead_out_ts =
2782         gst_util_uint64_scale (GST_SECOND, fps_den * lead_out, fps_num);
2783   }
2784   GST_LOG_OBJECT (parse, "set fps: %d/%d => duration: %" G_GINT64_FORMAT " ms",
2785       fps_num, fps_den, parse->priv->frame_duration / GST_MSECOND);
2786   GST_LOG_OBJECT (parse, "set lead in: %d frames = %" G_GUINT64_FORMAT " ms, "
2787       "lead out: %d frames = %" G_GUINT64_FORMAT " ms",
2788       lead_in, parse->priv->lead_in_ts / GST_MSECOND,
2789       lead_out, parse->priv->lead_out_ts / GST_MSECOND);
2790 }
2791
2792 static gboolean
2793 gst_base_parse_get_duration (GstBaseParse * parse, GstFormat format,
2794     GstClockTime * duration)
2795 {
2796   gboolean res = FALSE;
2797
2798   g_return_val_if_fail (duration != NULL, FALSE);
2799
2800   *duration = GST_CLOCK_TIME_NONE;
2801   if (parse->priv->duration != -1 && format == parse->priv->duration_fmt) {
2802     GST_LOG_OBJECT (parse, "using provided duration");
2803     *duration = parse->priv->duration;
2804     res = TRUE;
2805   } else if (parse->priv->duration != -1) {
2806     GST_LOG_OBJECT (parse, "converting provided duration");
2807     res = gst_base_parse_convert (parse, parse->priv->duration_fmt,
2808         parse->priv->duration, format, (gint64 *) duration);
2809   } else if (format == GST_FORMAT_TIME && parse->priv->estimated_duration != -1) {
2810     GST_LOG_OBJECT (parse, "using estimated duration");