docs: Fix typos in function/object descriptions
[platform/upstream/gstreamer.git] / libs / gst / base / 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  * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
6  *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23
24 /**
25  * SECTION:gstbaseparse
26  * @short_description: Base class for stream parsers
27  * @see_also: #GstBaseTransform
28  *
29  * This base class is for parser elements that process data and splits it
30  * into separate audio/video/whatever frames.
31  *
32  * It provides for:
33  * <itemizedlist>
34  *   <listitem><para>provides one sink pad and one source pad</para></listitem>
35  *   <listitem><para>handles state changes</para></listitem>
36  *   <listitem><para>can operate in pull mode or push mode</para></listitem>
37  *   <listitem><para>handles seeking in both modes</para></listitem>
38  *   <listitem><para>handles events (SEGMENT/EOS/FLUSH)</para></listitem>
39  *   <listitem><para>
40  *        handles queries (POSITION/DURATION/SEEKING/FORMAT/CONVERT)
41  *   </para></listitem>
42  *   <listitem><para>handles flushing</para></listitem>
43  * </itemizedlist>
44  *
45  * The purpose of this base class is to provide the basic functionality of
46  * a parser and share a lot of rather complex code.
47  *
48  * Description of the parsing mechanism:
49  * <orderedlist>
50  * <listitem>
51  *   <itemizedlist><title>Set-up phase</title>
52  *   <listitem><para>
53  *     GstBaseParse calls @start to inform subclass that data processing is
54  *     about to start now.
55  *   </para></listitem>
56  *   <listitem><para>
57  *     GstBaseParse class calls @set_sink_caps to inform the subclass about
58  *     incoming sinkpad caps. Subclass could already set the srcpad caps
59  *     accordingly, but this might be delayed until calling
60  *     gst_base_parse_finish_frame() with a non-queued frame.
61  *   </para></listitem>
62  *   <listitem><para>
63  *      At least at this point subclass needs to tell the GstBaseParse class
64  *      how big data chunks it wants to receive (min_frame_size). It can do
65  *      this with gst_base_parse_set_min_frame_size().
66  *   </para></listitem>
67  *   <listitem><para>
68  *      GstBaseParse class sets up appropriate data passing mode (pull/push)
69  *      and starts to process the data.
70  *   </para></listitem>
71  *   </itemizedlist>
72  * </listitem>
73  * <listitem>
74  *   <itemizedlist>
75  *   <title>Parsing phase</title>
76  *     <listitem><para>
77  *       GstBaseParse gathers at least min_frame_size bytes of data either
78  *       by pulling it from upstream or collecting buffers in an internal
79  *       #GstAdapter.
80  *     </para></listitem>
81  *     <listitem><para>
82  *       A buffer of (at least) min_frame_size bytes is passed to subclass with
83  *       @handle_frame. Subclass checks the contents and can optionally
84  *       return GST_FLOW_OK along with an amount of data to be skipped to find
85  *       a valid frame (which will result in a subsequent DISCONT).
86  *       If, otherwise, the buffer does not hold a complete frame,
87  *       @handle_frame can merely return and will be called again when additional
88  *       data is available.  In push mode this amounts to an
89  *       additional input buffer (thus minimal additional latency), in pull mode
90  *       this amounts to some arbitrary reasonable buffer size increase.
91  *       Of course, gst_base_parse_set_min_frame_size() could also be used if a
92  *       very specific known amount of additional data is required.
93  *       If, however, the buffer holds a complete valid frame, it can pass
94  *       the size of this frame to gst_base_parse_finish_frame().
95  *       If acting as a converter, it can also merely indicate consumed input data
96  *       while simultaneously providing custom output data.
97  *       Note that baseclass performs some processing (such as tracking
98  *       overall consumed data rate versus duration) for each finished frame,
99  *       but other state is only updated upon each call to @handle_frame
100  *       (such as tracking upstream input timestamp).
101  *       </para><para>
102  *       Subclass is also responsible for setting the buffer metadata
103  *       (e.g. buffer timestamp and duration, or keyframe if applicable).
104  *       (although the latter can also be done by GstBaseParse if it is
105  *       appropriately configured, see below).  Frame is provided with
106  *       timestamp derived from upstream (as much as generally possible),
107  *       duration obtained from configuration (see below), and offset
108  *       if meaningful (in pull mode).
109  *       </para><para>
110  *       Note that @check_valid_frame might receive any small
111  *       amount of input data when leftover data is being drained (e.g. at EOS).
112  *     </para></listitem>
113  *     <listitem><para>
114  *       As part of finish frame processing,
115  *       just prior to actually pushing the buffer in question,
116  *       it is passed to @pre_push_frame which gives subclass yet one
117  *       last chance to examine buffer metadata, or to send some custom (tag)
118  *       events, or to perform custom (segment) filtering.
119  *     </para></listitem>
120  *     <listitem><para>
121  *       During the parsing process GstBaseParseClass will handle both srcpad
122  *       and sinkpad events. They will be passed to subclass if @event or
123  *       @src_event callbacks have been provided.
124  *     </para></listitem>
125  *   </itemizedlist>
126  * </listitem>
127  * <listitem>
128  *   <itemizedlist><title>Shutdown phase</title>
129  *   <listitem><para>
130  *     GstBaseParse class calls @stop to inform the subclass that data
131  *     parsing will be stopped.
132  *   </para></listitem>
133  *   </itemizedlist>
134  * </listitem>
135  * </orderedlist>
136  *
137  * Subclass is responsible for providing pad template caps for
138  * source and sink pads. The pads need to be named "sink" and "src". It also
139  * needs to set the fixed caps on srcpad, when the format is ensured (e.g.
140  * when base class calls subclass' @set_sink_caps function).
141  *
142  * This base class uses #GST_FORMAT_DEFAULT as a meaning of frames. So,
143  * subclass conversion routine needs to know that conversion from
144  * #GST_FORMAT_TIME to #GST_FORMAT_DEFAULT must return the
145  * frame number that can be found from the given byte position.
146  *
147  * GstBaseParse uses subclasses conversion methods also for seeking (or
148  * otherwise uses its own default one, see also below).
149  *
150  * Subclass @start and @stop functions will be called to inform the beginning
151  * and end of data processing.
152  *
153  * Things that subclass need to take care of:
154  * <itemizedlist>
155  *   <listitem><para>Provide pad templates</para></listitem>
156  *   <listitem><para>
157  *      Fixate the source pad caps when appropriate
158  *   </para></listitem>
159  *   <listitem><para>
160  *      Inform base class how big data chunks should be retrieved. This is
161  *      done with gst_base_parse_set_min_frame_size() function.
162  *   </para></listitem>
163  *   <listitem><para>
164  *      Examine data chunks passed to subclass with @handle_frame and pass
165  *      proper frame(s) to gst_base_parse_finish_frame(), and setting src pad
166  *      caps and timestamps on frame.
167  *   </para></listitem>
168  *   <listitem><para>Provide conversion functions</para></listitem>
169  *   <listitem><para>
170  *      Update the duration information with gst_base_parse_set_duration()
171  *   </para></listitem>
172  *   <listitem><para>
173  *      Optionally passthrough using gst_base_parse_set_passthrough()
174  *   </para></listitem>
175  *   <listitem><para>
176  *      Configure various baseparse parameters using
177  *      gst_base_parse_set_average_bitrate(), gst_base_parse_set_syncable()
178  *      and gst_base_parse_set_frame_rate().
179  *   </para></listitem>
180  *   <listitem><para>
181  *      In particular, if subclass is unable to determine a duration, but
182  *      parsing (or specs) yields a frames per seconds rate, then this can be
183  *      provided to GstBaseParse to enable it to cater for
184  *      buffer time metadata (which will be taken from upstream as much as
185  *      possible). Internally keeping track of frame durations and respective
186  *      sizes that have been pushed provides GstBaseParse with an estimated
187  *      bitrate. A default @convert (used if not overridden) will then use these
188  *      rates to perform obvious conversions.  These rates are also used to
189  *      update (estimated) duration at regular frame intervals.
190  *   </para></listitem>
191  * </itemizedlist>
192  *
193  */
194
195 /* TODO:
196  *  - In push mode provide a queue of adapter-"queued" buffers for upstream
197  *    buffer metadata
198  *  - Queue buffers/events until caps are set
199  */
200
201 #ifdef HAVE_CONFIG_H
202 #  include "config.h"
203 #endif
204
205 #include <stdlib.h>
206 #include <string.h>
207
208 #include <gst/base/gstadapter.h>
209
210 #include "gstbaseparse.h"
211
212 /* FIXME: get rid of old GstIndex code */
213 #include "gstindex.h"
214 #include "gstindex.c"
215 #include "gstmemindex.c"
216
217 #define GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC  (1 << 0)
218
219 #define MIN_FRAMES_TO_POST_BITRATE 10
220 #define TARGET_DIFFERENCE          (20 * GST_SECOND)
221 #define MAX_INDEX_ENTRIES          4096
222
223 GST_DEBUG_CATEGORY_STATIC (gst_base_parse_debug);
224 #define GST_CAT_DEFAULT gst_base_parse_debug
225
226 /* Supported formats */
227 static const GstFormat fmtlist[] = {
228   GST_FORMAT_DEFAULT,
229   GST_FORMAT_BYTES,
230   GST_FORMAT_TIME,
231   GST_FORMAT_UNDEFINED
232 };
233
234 #define GST_BASE_PARSE_GET_PRIVATE(obj)  \
235     (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BASE_PARSE, GstBaseParsePrivate))
236
237 struct _GstBaseParsePrivate
238 {
239   GstPadMode pad_mode;
240
241   GstAdapter *adapter;
242
243   gint64 duration;
244   GstFormat duration_fmt;
245   gint64 estimated_duration;
246   gint64 estimated_drift;
247
248   guint min_frame_size;
249   gboolean disable_passthrough;
250   gboolean passthrough;
251   gboolean pts_interpolate;
252   gboolean infer_ts;
253   gboolean syncable;
254   gboolean has_timing_info;
255   guint fps_num, fps_den;
256   gint update_interval;
257   guint bitrate;
258   guint lead_in, lead_out;
259   GstClockTime lead_in_ts, lead_out_ts;
260   GstClockTime min_latency, max_latency;
261
262   gboolean discont;
263   gboolean flushing;
264   gboolean drain;
265
266   gint64 offset;
267   gint64 sync_offset;
268   GstClockTime next_pts;
269   GstClockTime next_dts;
270   GstClockTime prev_pts;
271   GstClockTime prev_dts;
272   GstClockTime frame_duration;
273   gboolean seen_keyframe;
274   gboolean is_video;
275   gint flushed;
276
277   guint64 framecount;
278   guint64 bytecount;
279   guint64 data_bytecount;
280   guint64 acc_duration;
281   GstClockTime first_frame_pts;
282   GstClockTime first_frame_dts;
283   gint64 first_frame_offset;
284
285   gboolean post_min_bitrate;
286   gboolean post_avg_bitrate;
287   gboolean post_max_bitrate;
288   guint min_bitrate;
289   guint avg_bitrate;
290   guint max_bitrate;
291   guint posted_avg_bitrate;
292
293   /* frames/buffers that are queued and ready to go on OK */
294   GQueue queued_frames;
295
296   GstBuffer *cache;
297
298   /* index entry storage, either ours or provided */
299   GstIndex *index;
300   gint index_id;
301   gboolean own_index;
302   GMutex index_lock;
303
304   /* seek table entries only maintained if upstream is BYTE seekable */
305   gboolean upstream_seekable;
306   gboolean upstream_has_duration;
307   gint64 upstream_size;
308   GstFormat upstream_format;
309   /* minimum distance between two index entries */
310   GstClockTimeDiff idx_interval;
311   guint64 idx_byte_interval;
312   /* ts and offset of last entry added */
313   GstClockTime index_last_ts;
314   gint64 index_last_offset;
315   gboolean index_last_valid;
316
317   /* timestamps currently produced are accurate, e.g. started from 0 onwards */
318   gboolean exact_position;
319   /* seek events are temporarily kept to match them with newsegments */
320   GSList *pending_seeks;
321
322   /* reverse playback */
323   GSList *buffers_pending;
324   GSList *buffers_head;
325   GSList *buffers_queued;
326   GSList *buffers_send;
327   GstClockTime last_pts;
328   GstClockTime last_dts;
329   gint64 last_offset;
330
331   /* Pending serialized events */
332   GList *pending_events;
333   /* Newsegment event to be sent after SEEK */
334   gboolean pending_segment;
335
336   /* offset of last parsed frame/data */
337   gint64 prev_offset;
338   /* force a new frame, regardless of offset */
339   gboolean new_frame;
340   /* whether we are merely scanning for a frame */
341   gboolean scanning;
342   /* ... and resulting frame, if any */
343   GstBaseParseFrame *scanned_frame;
344
345   /* TRUE if we're still detecting the format, i.e.
346    * if ::detect() is still called for future buffers */
347   gboolean detecting;
348   GList *detect_buffers;
349   guint detect_buffers_size;
350
351   /* if TRUE, a STREAM_START event needs to be pushed */
352   gboolean push_stream_start;
353 };
354
355 typedef struct _GstBaseParseSeek
356 {
357   GstSegment segment;
358   gboolean accurate;
359   gint64 offset;
360   GstClockTime start_ts;
361 } GstBaseParseSeek;
362
363 #define DEFAULT_DISABLE_PASSTHROUGH        FALSE
364
365 enum
366 {
367   PROP_0,
368   PROP_DISABLE_PASSTHROUGH,
369   PROP_LAST
370 };
371
372 #define GST_BASE_PARSE_INDEX_LOCK(parse) \
373   g_mutex_lock (&parse->priv->index_lock);
374 #define GST_BASE_PARSE_INDEX_UNLOCK(parse) \
375   g_mutex_unlock (&parse->priv->index_lock);
376
377 static GstElementClass *parent_class = NULL;
378
379 static void gst_base_parse_class_init (GstBaseParseClass * klass);
380 static void gst_base_parse_init (GstBaseParse * parse,
381     GstBaseParseClass * klass);
382
383 GType
384 gst_base_parse_get_type (void)
385 {
386   static volatile gsize base_parse_type = 0;
387
388   if (g_once_init_enter (&base_parse_type)) {
389     static const GTypeInfo base_parse_info = {
390       sizeof (GstBaseParseClass),
391       (GBaseInitFunc) NULL,
392       (GBaseFinalizeFunc) NULL,
393       (GClassInitFunc) gst_base_parse_class_init,
394       NULL,
395       NULL,
396       sizeof (GstBaseParse),
397       0,
398       (GInstanceInitFunc) gst_base_parse_init,
399     };
400     GType _type;
401
402     _type = g_type_register_static (GST_TYPE_ELEMENT,
403         "GstBaseParse", &base_parse_info, G_TYPE_FLAG_ABSTRACT);
404     g_once_init_leave (&base_parse_type, _type);
405   }
406   return (GType) base_parse_type;
407 }
408
409 static void gst_base_parse_finalize (GObject * object);
410
411 static GstStateChangeReturn gst_base_parse_change_state (GstElement * element,
412     GstStateChange transition);
413 static void gst_base_parse_reset (GstBaseParse * parse);
414
415 #if 0
416 static void gst_base_parse_set_index (GstElement * element, GstIndex * index);
417 static GstIndex *gst_base_parse_get_index (GstElement * element);
418 #endif
419
420 static gboolean gst_base_parse_sink_activate (GstPad * sinkpad,
421     GstObject * parent);
422 static gboolean gst_base_parse_sink_activate_mode (GstPad * pad,
423     GstObject * parent, GstPadMode mode, gboolean active);
424 static gboolean gst_base_parse_handle_seek (GstBaseParse * parse,
425     GstEvent * event);
426 static void gst_base_parse_handle_tag (GstBaseParse * parse, GstEvent * event);
427
428 static void gst_base_parse_set_property (GObject * object, guint prop_id,
429     const GValue * value, GParamSpec * pspec);
430 static void gst_base_parse_get_property (GObject * object, guint prop_id,
431     GValue * value, GParamSpec * pspec);
432
433 static gboolean gst_base_parse_src_event (GstPad * pad, GstObject * parent,
434     GstEvent * event);
435 static gboolean gst_base_parse_src_query (GstPad * pad, GstObject * parent,
436     GstQuery * query);
437
438 static gboolean gst_base_parse_sink_event (GstPad * pad, GstObject * parent,
439     GstEvent * event);
440 static gboolean gst_base_parse_sink_query (GstPad * pad, GstObject * parent,
441     GstQuery * query);
442
443 static GstFlowReturn gst_base_parse_chain (GstPad * pad, GstObject * parent,
444     GstBuffer * buffer);
445 static void gst_base_parse_loop (GstPad * pad);
446
447 static GstFlowReturn gst_base_parse_parse_frame (GstBaseParse * parse,
448     GstBaseParseFrame * frame);
449
450 static gboolean gst_base_parse_sink_event_default (GstBaseParse * parse,
451     GstEvent * event);
452
453 static gboolean gst_base_parse_src_event_default (GstBaseParse * parse,
454     GstEvent * event);
455
456 static gboolean gst_base_parse_sink_query_default (GstBaseParse * parse,
457     GstQuery * query);
458 static gboolean gst_base_parse_src_query_default (GstBaseParse * parse,
459     GstQuery * query);
460
461 static void gst_base_parse_drain (GstBaseParse * parse);
462
463 static void gst_base_parse_post_bitrates (GstBaseParse * parse,
464     gboolean post_min, gboolean post_avg, gboolean post_max);
465
466 static gint64 gst_base_parse_find_offset (GstBaseParse * parse,
467     GstClockTime time, gboolean before, GstClockTime * _ts);
468 static GstFlowReturn gst_base_parse_locate_time (GstBaseParse * parse,
469     GstClockTime * _time, gint64 * _offset);
470
471 static GstFlowReturn gst_base_parse_start_fragment (GstBaseParse * parse);
472 static GstFlowReturn gst_base_parse_finish_fragment (GstBaseParse * parse,
473     gboolean prev_head);
474
475 static inline GstFlowReturn gst_base_parse_check_sync (GstBaseParse * parse);
476
477 static gboolean gst_base_parse_is_seekable (GstBaseParse * parse);
478
479 static void
480 gst_base_parse_clear_queues (GstBaseParse * parse)
481 {
482   g_slist_foreach (parse->priv->buffers_queued, (GFunc) gst_buffer_unref, NULL);
483   g_slist_free (parse->priv->buffers_queued);
484   parse->priv->buffers_queued = NULL;
485   g_slist_foreach (parse->priv->buffers_pending, (GFunc) gst_buffer_unref,
486       NULL);
487   g_slist_free (parse->priv->buffers_pending);
488   parse->priv->buffers_pending = NULL;
489   g_slist_foreach (parse->priv->buffers_head, (GFunc) gst_buffer_unref, NULL);
490   g_slist_free (parse->priv->buffers_head);
491   parse->priv->buffers_head = NULL;
492   g_slist_foreach (parse->priv->buffers_send, (GFunc) gst_buffer_unref, NULL);
493   g_slist_free (parse->priv->buffers_send);
494   parse->priv->buffers_send = NULL;
495
496   g_list_foreach (parse->priv->detect_buffers, (GFunc) gst_buffer_unref, NULL);
497   g_list_free (parse->priv->detect_buffers);
498   parse->priv->detect_buffers = NULL;
499   parse->priv->detect_buffers_size = 0;
500
501   g_queue_foreach (&parse->priv->queued_frames,
502       (GFunc) gst_base_parse_frame_free, NULL);
503   g_queue_clear (&parse->priv->queued_frames);
504
505   gst_buffer_replace (&parse->priv->cache, NULL);
506
507   g_list_foreach (parse->priv->pending_events, (GFunc) gst_event_unref, NULL);
508   g_list_free (parse->priv->pending_events);
509   parse->priv->pending_events = NULL;
510   parse->priv->pending_segment = FALSE;
511 }
512
513 static void
514 gst_base_parse_finalize (GObject * object)
515 {
516   GstBaseParse *parse = GST_BASE_PARSE (object);
517
518   g_object_unref (parse->priv->adapter);
519
520   if (parse->priv->cache) {
521     gst_buffer_unref (parse->priv->cache);
522     parse->priv->cache = NULL;
523   }
524
525   g_list_foreach (parse->priv->pending_events, (GFunc) gst_mini_object_unref,
526       NULL);
527   g_list_free (parse->priv->pending_events);
528   parse->priv->pending_events = NULL;
529   parse->priv->pending_segment = FALSE;
530
531   if (parse->priv->index) {
532     gst_object_unref (parse->priv->index);
533     parse->priv->index = NULL;
534   }
535   g_mutex_clear (&parse->priv->index_lock);
536
537   gst_base_parse_clear_queues (parse);
538
539   G_OBJECT_CLASS (parent_class)->finalize (object);
540 }
541
542 static void
543 gst_base_parse_class_init (GstBaseParseClass * klass)
544 {
545   GObjectClass *gobject_class;
546   GstElementClass *gstelement_class;
547
548   gobject_class = G_OBJECT_CLASS (klass);
549   g_type_class_add_private (klass, sizeof (GstBaseParsePrivate));
550   parent_class = g_type_class_peek_parent (klass);
551
552   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_base_parse_finalize);
553   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_base_parse_set_property);
554   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_base_parse_get_property);
555
556   /**
557    * GstBaseParse:disable-passthrough:
558    *
559    * If set to #TRUE, baseparse will unconditionally force parsing of the
560    * incoming data. This can be required in the rare cases where the incoming
561    * side-data (caps, pts, dts, ...) is not trusted by the user and wants to
562    * force validation and parsing of the incoming data.
563    * If set to #FALSE, decision of whether to parse the data or not is up to
564    * the implementation (standard behaviour).
565    */
566   g_object_class_install_property (gobject_class, PROP_DISABLE_PASSTHROUGH,
567       g_param_spec_boolean ("disable-passthrough", "Disable passthrough",
568           "Force processing (disables passthrough)",
569           DEFAULT_DISABLE_PASSTHROUGH,
570           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
571
572   gstelement_class = (GstElementClass *) klass;
573   gstelement_class->change_state =
574       GST_DEBUG_FUNCPTR (gst_base_parse_change_state);
575
576 #if 0
577   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_base_parse_set_index);
578   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_base_parse_get_index);
579 #endif
580
581   /* Default handlers */
582   klass->sink_event = gst_base_parse_sink_event_default;
583   klass->src_event = gst_base_parse_src_event_default;
584   klass->sink_query = gst_base_parse_sink_query_default;
585   klass->src_query = gst_base_parse_src_query_default;
586   klass->convert = gst_base_parse_convert_default;
587
588   GST_DEBUG_CATEGORY_INIT (gst_base_parse_debug, "baseparse", 0,
589       "baseparse element");
590 }
591
592 static void
593 gst_base_parse_init (GstBaseParse * parse, GstBaseParseClass * bclass)
594 {
595   GstPadTemplate *pad_template;
596
597   GST_DEBUG_OBJECT (parse, "gst_base_parse_init");
598
599   parse->priv = GST_BASE_PARSE_GET_PRIVATE (parse);
600
601   pad_template =
602       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "sink");
603   g_return_if_fail (pad_template != NULL);
604   parse->sinkpad = gst_pad_new_from_template (pad_template, "sink");
605   gst_pad_set_event_function (parse->sinkpad,
606       GST_DEBUG_FUNCPTR (gst_base_parse_sink_event));
607   gst_pad_set_query_function (parse->sinkpad,
608       GST_DEBUG_FUNCPTR (gst_base_parse_sink_query));
609   gst_pad_set_chain_function (parse->sinkpad,
610       GST_DEBUG_FUNCPTR (gst_base_parse_chain));
611   gst_pad_set_activate_function (parse->sinkpad,
612       GST_DEBUG_FUNCPTR (gst_base_parse_sink_activate));
613   gst_pad_set_activatemode_function (parse->sinkpad,
614       GST_DEBUG_FUNCPTR (gst_base_parse_sink_activate_mode));
615   GST_PAD_SET_PROXY_ALLOCATION (parse->sinkpad);
616   gst_element_add_pad (GST_ELEMENT (parse), parse->sinkpad);
617
618   GST_DEBUG_OBJECT (parse, "sinkpad created");
619
620   pad_template =
621       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "src");
622   g_return_if_fail (pad_template != NULL);
623   parse->srcpad = gst_pad_new_from_template (pad_template, "src");
624   gst_pad_set_event_function (parse->srcpad,
625       GST_DEBUG_FUNCPTR (gst_base_parse_src_event));
626   gst_pad_set_query_function (parse->srcpad,
627       GST_DEBUG_FUNCPTR (gst_base_parse_src_query));
628   gst_pad_use_fixed_caps (parse->srcpad);
629   gst_element_add_pad (GST_ELEMENT (parse), parse->srcpad);
630   GST_DEBUG_OBJECT (parse, "src created");
631
632   g_queue_init (&parse->priv->queued_frames);
633
634   parse->priv->adapter = gst_adapter_new ();
635
636   parse->priv->pad_mode = GST_PAD_MODE_NONE;
637
638   g_mutex_init (&parse->priv->index_lock);
639
640   /* init state */
641   gst_base_parse_reset (parse);
642   GST_DEBUG_OBJECT (parse, "init ok");
643
644   GST_OBJECT_FLAG_SET (parse, GST_ELEMENT_FLAG_INDEXABLE);
645 }
646
647 static void
648 gst_base_parse_set_property (GObject * object, guint prop_id,
649     const GValue * value, GParamSpec * pspec)
650 {
651   GstBaseParse *parse = GST_BASE_PARSE (object);
652
653   switch (prop_id) {
654     case PROP_DISABLE_PASSTHROUGH:
655       parse->priv->disable_passthrough = g_value_get_boolean (value);
656       break;
657     default:
658       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
659       break;
660   }
661 }
662
663 static void
664 gst_base_parse_get_property (GObject * object, guint prop_id, GValue * value,
665     GParamSpec * pspec)
666 {
667   GstBaseParse *parse = GST_BASE_PARSE (object);
668
669   switch (prop_id) {
670     case PROP_DISABLE_PASSTHROUGH:
671       g_value_set_boolean (value, parse->priv->disable_passthrough);
672       break;
673     default:
674       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
675       break;
676   }
677 }
678
679 static GstBaseParseFrame *
680 gst_base_parse_frame_copy (GstBaseParseFrame * frame)
681 {
682   GstBaseParseFrame *copy;
683
684   copy = g_slice_dup (GstBaseParseFrame, frame);
685   copy->buffer = gst_buffer_ref (frame->buffer);
686   copy->_private_flags &= ~GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC;
687
688   GST_TRACE ("copied frame %p -> %p", frame, copy);
689
690   return copy;
691 }
692
693 void
694 gst_base_parse_frame_free (GstBaseParseFrame * frame)
695 {
696   GST_TRACE ("freeing frame %p", frame);
697
698   if (frame->buffer) {
699     gst_buffer_unref (frame->buffer);
700     frame->buffer = NULL;
701   }
702
703   if (!(frame->_private_flags & GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC)) {
704     g_slice_free (GstBaseParseFrame, frame);
705   } else {
706     memset (frame, 0, sizeof (*frame));
707   }
708 }
709
710 G_DEFINE_BOXED_TYPE (GstBaseParseFrame, gst_base_parse_frame,
711     (GBoxedCopyFunc) gst_base_parse_frame_copy,
712     (GBoxedFreeFunc) gst_base_parse_frame_free);
713
714 /**
715  * gst_base_parse_frame_init:
716  * @frame: #GstBaseParseFrame.
717  *
718  * Sets a #GstBaseParseFrame to initial state.  Currently this means
719  * all public fields are zero-ed and a private flag is set to make
720  * sure gst_base_parse_frame_free() only frees the contents but not
721  * the actual frame. Use this function to initialise a #GstBaseParseFrame
722  * allocated on the stack.
723  */
724 void
725 gst_base_parse_frame_init (GstBaseParseFrame * frame)
726 {
727   memset (frame, 0, sizeof (GstBaseParseFrame));
728   frame->_private_flags = GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC;
729   GST_TRACE ("inited frame %p", frame);
730 }
731
732 /**
733  * gst_base_parse_frame_new:
734  * @buffer: (transfer none): a #GstBuffer
735  * @flags: the flags
736  * @overhead: number of bytes in this frame which should be counted as
737  *     metadata overhead, ie. not used to calculate the average bitrate.
738  *     Set to -1 to mark the entire frame as metadata. If in doubt, set to 0.
739  *
740  * Allocates a new #GstBaseParseFrame. This function is mainly for bindings,
741  * elements written in C should usually allocate the frame on the stack and
742  * then use gst_base_parse_frame_init() to initialise it.
743  *
744  * Returns: a newly-allocated #GstBaseParseFrame. Free with
745  *     gst_base_parse_frame_free() when no longer needed.
746  */
747 GstBaseParseFrame *
748 gst_base_parse_frame_new (GstBuffer * buffer, GstBaseParseFrameFlags flags,
749     gint overhead)
750 {
751   GstBaseParseFrame *frame;
752
753   frame = g_slice_new0 (GstBaseParseFrame);
754   frame->buffer = gst_buffer_ref (buffer);
755
756   GST_TRACE ("created frame %p", frame);
757   return frame;
758 }
759
760 static inline void
761 gst_base_parse_frame_update (GstBaseParse * parse, GstBaseParseFrame * frame,
762     GstBuffer * buf)
763 {
764   gst_buffer_replace (&frame->buffer, buf);
765
766   parse->flags = 0;
767
768   /* set flags one by one for clarity */
769   if (G_UNLIKELY (parse->priv->drain))
770     parse->flags |= GST_BASE_PARSE_FLAG_DRAINING;
771
772   /* losing sync is pretty much a discont (and vice versa), no ? */
773   if (G_UNLIKELY (parse->priv->discont))
774     parse->flags |= GST_BASE_PARSE_FLAG_LOST_SYNC;
775 }
776
777 static void
778 gst_base_parse_reset (GstBaseParse * parse)
779 {
780   GST_OBJECT_LOCK (parse);
781   gst_segment_init (&parse->segment, GST_FORMAT_TIME);
782   parse->priv->duration = -1;
783   parse->priv->min_frame_size = 1;
784   parse->priv->discont = TRUE;
785   parse->priv->flushing = FALSE;
786   parse->priv->offset = 0;
787   parse->priv->sync_offset = 0;
788   parse->priv->update_interval = -1;
789   parse->priv->fps_num = parse->priv->fps_den = 0;
790   parse->priv->frame_duration = GST_CLOCK_TIME_NONE;
791   parse->priv->lead_in = parse->priv->lead_out = 0;
792   parse->priv->lead_in_ts = parse->priv->lead_out_ts = 0;
793   parse->priv->bitrate = 0;
794   parse->priv->framecount = 0;
795   parse->priv->bytecount = 0;
796   parse->priv->acc_duration = 0;
797   parse->priv->first_frame_pts = GST_CLOCK_TIME_NONE;
798   parse->priv->first_frame_dts = GST_CLOCK_TIME_NONE;
799   parse->priv->first_frame_offset = -1;
800   parse->priv->estimated_duration = -1;
801   parse->priv->estimated_drift = 0;
802   parse->priv->next_pts = GST_CLOCK_TIME_NONE;
803   parse->priv->next_dts = 0;
804   parse->priv->syncable = TRUE;
805   parse->priv->disable_passthrough = DEFAULT_DISABLE_PASSTHROUGH;
806   parse->priv->passthrough = FALSE;
807   parse->priv->pts_interpolate = TRUE;
808   parse->priv->infer_ts = TRUE;
809   parse->priv->has_timing_info = FALSE;
810   parse->priv->post_min_bitrate = TRUE;
811   parse->priv->post_avg_bitrate = TRUE;
812   parse->priv->post_max_bitrate = TRUE;
813   parse->priv->min_bitrate = G_MAXUINT;
814   parse->priv->max_bitrate = 0;
815   parse->priv->avg_bitrate = 0;
816   parse->priv->posted_avg_bitrate = 0;
817
818   parse->priv->index_last_ts = GST_CLOCK_TIME_NONE;
819   parse->priv->index_last_offset = -1;
820   parse->priv->index_last_valid = TRUE;
821   parse->priv->upstream_seekable = FALSE;
822   parse->priv->upstream_size = 0;
823   parse->priv->upstream_has_duration = FALSE;
824   parse->priv->upstream_format = GST_FORMAT_UNDEFINED;
825   parse->priv->idx_interval = 0;
826   parse->priv->idx_byte_interval = 0;
827   parse->priv->exact_position = TRUE;
828   parse->priv->seen_keyframe = FALSE;
829
830   parse->priv->last_dts = GST_CLOCK_TIME_NONE;
831   parse->priv->last_pts = GST_CLOCK_TIME_NONE;
832   parse->priv->last_offset = 0;
833
834   g_list_foreach (parse->priv->pending_events, (GFunc) gst_mini_object_unref,
835       NULL);
836   g_list_free (parse->priv->pending_events);
837   parse->priv->pending_events = NULL;
838   parse->priv->pending_segment = FALSE;
839
840   if (parse->priv->cache) {
841     gst_buffer_unref (parse->priv->cache);
842     parse->priv->cache = NULL;
843   }
844
845   g_slist_foreach (parse->priv->pending_seeks, (GFunc) g_free, NULL);
846   g_slist_free (parse->priv->pending_seeks);
847   parse->priv->pending_seeks = NULL;
848
849   if (parse->priv->adapter)
850     gst_adapter_clear (parse->priv->adapter);
851
852   parse->priv->new_frame = TRUE;
853
854   g_list_foreach (parse->priv->detect_buffers, (GFunc) gst_buffer_unref, NULL);
855   g_list_free (parse->priv->detect_buffers);
856   parse->priv->detect_buffers = NULL;
857   parse->priv->detect_buffers_size = 0;
858   GST_OBJECT_UNLOCK (parse);
859 }
860
861 /* gst_base_parse_parse_frame:
862  * @parse: #GstBaseParse.
863  * @buffer: #GstBuffer.
864  *
865  * Default callback for parse_frame.
866  */
867 static GstFlowReturn
868 gst_base_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
869 {
870   GstBuffer *buffer = frame->buffer;
871
872   if (!GST_BUFFER_PTS_IS_VALID (buffer) &&
873       GST_CLOCK_TIME_IS_VALID (parse->priv->next_pts)) {
874     GST_BUFFER_PTS (buffer) = parse->priv->next_pts;
875   }
876   if (!GST_BUFFER_DTS_IS_VALID (buffer) &&
877       GST_CLOCK_TIME_IS_VALID (parse->priv->next_dts)) {
878     GST_BUFFER_DTS (buffer) = parse->priv->next_dts;
879   }
880   if (!GST_BUFFER_DURATION_IS_VALID (buffer) &&
881       GST_CLOCK_TIME_IS_VALID (parse->priv->frame_duration)) {
882     GST_BUFFER_DURATION (buffer) = parse->priv->frame_duration;
883   }
884   return GST_FLOW_OK;
885 }
886
887 /* gst_base_parse_convert:
888  * @parse: #GstBaseParse.
889  * @src_format: #GstFormat describing the source format.
890  * @src_value: Source value to be converted.
891  * @dest_format: #GstFormat defining the converted format.
892  * @dest_value: Pointer where the conversion result will be put.
893  *
894  * Converts using configured "convert" vmethod in #GstBaseParse class.
895  *
896  * Returns: TRUE if conversion was successful.
897  */
898 static gboolean
899 gst_base_parse_convert (GstBaseParse * parse,
900     GstFormat src_format,
901     gint64 src_value, GstFormat dest_format, gint64 * dest_value)
902 {
903   GstBaseParseClass *klass = GST_BASE_PARSE_GET_CLASS (parse);
904   gboolean ret;
905
906   g_return_val_if_fail (dest_value != NULL, FALSE);
907
908   if (!klass->convert)
909     return FALSE;
910
911   ret = klass->convert (parse, src_format, src_value, dest_format, dest_value);
912
913 #ifndef GST_DISABLE_GST_DEBUG
914   {
915     if (ret) {
916       if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_BYTES) {
917         GST_LOG_OBJECT (parse,
918             "TIME -> BYTES: %" GST_TIME_FORMAT " -> %" G_GINT64_FORMAT,
919             GST_TIME_ARGS (src_value), *dest_value);
920       } else if (dest_format == GST_FORMAT_TIME &&
921           src_format == GST_FORMAT_BYTES) {
922         GST_LOG_OBJECT (parse,
923             "BYTES -> TIME: %" G_GINT64_FORMAT " -> %" GST_TIME_FORMAT,
924             src_value, GST_TIME_ARGS (*dest_value));
925       } else {
926         GST_LOG_OBJECT (parse,
927             "%s -> %s: %" G_GINT64_FORMAT " -> %" G_GINT64_FORMAT,
928             GST_STR_NULL (gst_format_get_name (src_format)),
929             GST_STR_NULL (gst_format_get_name (dest_format)),
930             src_value, *dest_value);
931       }
932     } else {
933       GST_DEBUG_OBJECT (parse, "conversion failed");
934     }
935   }
936 #endif
937
938   return ret;
939 }
940
941 /* gst_base_parse_sink_event:
942  * @pad: #GstPad that received the event.
943  * @event: #GstEvent to be handled.
944  *
945  * Handler for sink pad events.
946  *
947  * Returns: TRUE if the event was handled.
948  */
949 static gboolean
950 gst_base_parse_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
951 {
952   GstBaseParse *parse = GST_BASE_PARSE (parent);
953   GstBaseParseClass *bclass = GST_BASE_PARSE_GET_CLASS (parse);
954   gboolean ret;
955
956   ret = bclass->sink_event (parse, event);
957
958   return ret;
959 }
960
961
962 /* gst_base_parse_sink_event_default:
963  * @parse: #GstBaseParse.
964  * @event: #GstEvent to be handled.
965  *
966  * Element-level event handler function.
967  *
968  * The event will be unreffed only if it has been handled and this
969  * function returns %TRUE
970  *
971  * Returns: %TRUE if the event was handled and not need forwarding.
972  */
973 static gboolean
974 gst_base_parse_sink_event_default (GstBaseParse * parse, GstEvent * event)
975 {
976   GstBaseParseClass *klass = GST_BASE_PARSE_GET_CLASS (parse);
977   gboolean ret = FALSE;
978   gboolean forward_immediate = FALSE;
979
980   GST_DEBUG_OBJECT (parse, "handling event %d, %s", GST_EVENT_TYPE (event),
981       GST_EVENT_TYPE_NAME (event));
982
983   switch (GST_EVENT_TYPE (event)) {
984     case GST_EVENT_CAPS:
985     {
986       GstCaps *caps;
987
988       gst_event_parse_caps (event, &caps);
989       GST_DEBUG_OBJECT (parse, "caps: %" GST_PTR_FORMAT, caps);
990
991       if (klass->set_sink_caps)
992         ret = klass->set_sink_caps (parse, caps);
993       else
994         ret = TRUE;
995
996       /* will send our own caps downstream */
997       gst_event_unref (event);
998       event = NULL;
999       break;
1000     }
1001     case GST_EVENT_SEGMENT:
1002     {
1003       const GstSegment *in_segment;
1004       GstSegment out_segment;
1005       gint64 offset = 0, next_dts;
1006       guint32 seqnum = gst_event_get_seqnum (event);
1007
1008       gst_event_parse_segment (event, &in_segment);
1009       gst_segment_init (&out_segment, GST_FORMAT_TIME);
1010
1011       GST_DEBUG_OBJECT (parse, "segment %" GST_SEGMENT_FORMAT, in_segment);
1012
1013       parse->priv->upstream_format = in_segment->format;
1014       if (in_segment->format == GST_FORMAT_BYTES) {
1015         GstBaseParseSeek *seek = NULL;
1016         GSList *node;
1017
1018         /* stop time is allowed to be open-ended, but not start & pos */
1019         offset = in_segment->time;
1020
1021         GST_OBJECT_LOCK (parse);
1022         for (node = parse->priv->pending_seeks; node; node = node->next) {
1023           GstBaseParseSeek *tmp = node->data;
1024
1025           if (tmp->offset == offset) {
1026             seek = tmp;
1027             break;
1028           }
1029         }
1030         parse->priv->pending_seeks =
1031             g_slist_remove (parse->priv->pending_seeks, seek);
1032         GST_OBJECT_UNLOCK (parse);
1033
1034         if (seek) {
1035           GST_DEBUG_OBJECT (parse,
1036               "Matched newsegment to%s seek: %" GST_SEGMENT_FORMAT,
1037               seek->accurate ? " accurate" : "", &seek->segment);
1038
1039           out_segment.start = seek->segment.start;
1040           out_segment.stop = seek->segment.stop;
1041           out_segment.time = seek->segment.start;
1042
1043           next_dts = seek->start_ts;
1044           parse->priv->exact_position = seek->accurate;
1045           g_free (seek);
1046         } else {
1047           /* best attempt convert */
1048           /* as these are only estimates, stop is kept open-ended to avoid
1049            * premature cutting */
1050           gst_base_parse_convert (parse, GST_FORMAT_BYTES, in_segment->start,
1051               GST_FORMAT_TIME, (gint64 *) & next_dts);
1052
1053           out_segment.start = next_dts;
1054           out_segment.stop = GST_CLOCK_TIME_NONE;
1055           out_segment.time = next_dts;
1056
1057           parse->priv->exact_position = (in_segment->start == 0);
1058         }
1059
1060         gst_event_unref (event);
1061
1062         event = gst_event_new_segment (&out_segment);
1063         gst_event_set_seqnum (event, seqnum);
1064
1065         GST_DEBUG_OBJECT (parse, "Converted incoming segment to TIME. %"
1066             GST_SEGMENT_FORMAT, in_segment);
1067
1068       } else if (in_segment->format != GST_FORMAT_TIME) {
1069         /* Unknown incoming segment format. Output a default open-ended
1070          * TIME segment */
1071         gst_event_unref (event);
1072
1073         out_segment.start = 0;
1074         out_segment.stop = GST_CLOCK_TIME_NONE;
1075         out_segment.time = 0;
1076
1077         event = gst_event_new_segment (&out_segment);
1078         gst_event_set_seqnum (event, seqnum);
1079
1080         next_dts = 0;
1081       } else {
1082         /* not considered BYTE seekable if it is talking to us in TIME,
1083          * whatever else it might claim */
1084         parse->priv->upstream_seekable = FALSE;
1085         next_dts = in_segment->start;
1086       }
1087
1088       memcpy (&parse->segment, &out_segment, sizeof (GstSegment));
1089
1090       /*
1091          gst_segment_set_newsegment (&parse->segment, update, rate,
1092          applied_rate, format, start, stop, start);
1093        */
1094
1095       /* save the segment for later, right before we push a new buffer so that
1096        * the caps are fixed and the next linked element can receive
1097        * the segment. */
1098       parse->priv->pending_segment = TRUE;
1099       ret = TRUE;
1100
1101       /* but finish the current segment */
1102       GST_DEBUG_OBJECT (parse, "draining current segment");
1103       if (in_segment->rate > 0.0)
1104         gst_base_parse_drain (parse);
1105       else
1106         gst_base_parse_finish_fragment (parse, FALSE);
1107       gst_adapter_clear (parse->priv->adapter);
1108
1109       parse->priv->offset = offset;
1110       parse->priv->sync_offset = offset;
1111       parse->priv->next_dts = next_dts;
1112       parse->priv->next_pts = GST_CLOCK_TIME_NONE;
1113       parse->priv->last_pts = GST_CLOCK_TIME_NONE;
1114       parse->priv->last_dts = GST_CLOCK_TIME_NONE;
1115       parse->priv->prev_pts = GST_CLOCK_TIME_NONE;
1116       parse->priv->prev_dts = GST_CLOCK_TIME_NONE;
1117       parse->priv->discont = TRUE;
1118       parse->priv->seen_keyframe = FALSE;
1119       break;
1120     }
1121
1122     case GST_EVENT_FLUSH_START:
1123       GST_OBJECT_LOCK (parse);
1124       parse->priv->flushing = TRUE;
1125       GST_OBJECT_UNLOCK (parse);
1126       break;
1127
1128     case GST_EVENT_FLUSH_STOP:
1129       gst_adapter_clear (parse->priv->adapter);
1130       gst_base_parse_clear_queues (parse);
1131       parse->priv->flushing = FALSE;
1132       parse->priv->discont = TRUE;
1133       parse->priv->last_pts = GST_CLOCK_TIME_NONE;
1134       parse->priv->last_dts = GST_CLOCK_TIME_NONE;
1135       parse->priv->new_frame = TRUE;
1136
1137       forward_immediate = TRUE;
1138       break;
1139
1140     case GST_EVENT_EOS:
1141       if (parse->segment.rate > 0.0)
1142         gst_base_parse_drain (parse);
1143       else
1144         gst_base_parse_finish_fragment (parse, TRUE);
1145
1146       /* If we STILL have zero frames processed, fire an error */
1147       if (parse->priv->framecount == 0) {
1148         GST_ELEMENT_ERROR (parse, STREAM, WRONG_TYPE,
1149             ("No valid frames found before end of stream"), (NULL));
1150       }
1151       /* newsegment and other serialized events before eos */
1152       if (G_UNLIKELY (parse->priv->pending_events)) {
1153         GList *l;
1154
1155         for (l = parse->priv->pending_events; l != NULL; l = l->next) {
1156           gst_pad_push_event (parse->srcpad, GST_EVENT (l->data));
1157         }
1158         g_list_free (parse->priv->pending_events);
1159         parse->priv->pending_events = NULL;
1160         parse->priv->pending_segment = FALSE;
1161       }
1162       if (parse->priv->framecount < MIN_FRAMES_TO_POST_BITRATE) {
1163         /* We've not posted bitrate tags yet - do so now */
1164         gst_base_parse_post_bitrates (parse, TRUE, TRUE, TRUE);
1165       }
1166       forward_immediate = TRUE;
1167       break;
1168     case GST_EVENT_CUSTOM_DOWNSTREAM:{
1169       /* FIXME: Code duplicated from libgstvideo because core can't depend on -base */
1170 #ifndef GST_VIDEO_EVENT_STILL_STATE_NAME
1171 #define GST_VIDEO_EVENT_STILL_STATE_NAME "GstEventStillFrame"
1172 #endif
1173
1174       const GstStructure *s;
1175       gboolean ev_still_state;
1176
1177       s = gst_event_get_structure (event);
1178       if (s != NULL &&
1179           gst_structure_has_name (s, GST_VIDEO_EVENT_STILL_STATE_NAME) &&
1180           gst_structure_get_boolean (s, "still-state", &ev_still_state)) {
1181         if (ev_still_state) {
1182           GST_DEBUG_OBJECT (parse, "draining current data for still-frame");
1183           if (parse->segment.rate > 0.0)
1184             gst_base_parse_drain (parse);
1185           else
1186             gst_base_parse_finish_fragment (parse, TRUE);
1187         }
1188         forward_immediate = TRUE;
1189       }
1190       break;
1191     }
1192     case GST_EVENT_GAP:
1193     {
1194       GST_DEBUG_OBJECT (parse, "draining current data due to gap event");
1195       if (parse->segment.rate > 0.0)
1196         gst_base_parse_drain (parse);
1197       else
1198         gst_base_parse_finish_fragment (parse, TRUE);
1199       forward_immediate = TRUE;
1200       break;
1201     }
1202     case GST_EVENT_TAG:
1203       /* See if any bitrate tags were posted */
1204       gst_base_parse_handle_tag (parse, event);
1205       break;
1206
1207     case GST_EVENT_STREAM_START:
1208       if (parse->priv->pad_mode != GST_PAD_MODE_PULL)
1209         forward_immediate = TRUE;
1210       break;
1211
1212     default:
1213       break;
1214   }
1215
1216   /* Forward non-serialized events and EOS/FLUSH_STOP immediately.
1217    * For EOS this is required because no buffer or serialized event
1218    * will come after EOS and nothing could trigger another
1219    * _finish_frame() call.   *
1220    * If the subclass handles sending of EOS manually it can return
1221    * _DROPPED from ::finish() and all other subclasses should have
1222    * decoded/flushed all remaining data before this
1223    *
1224    * For FLUSH_STOP this is required because it is expected
1225    * to be forwarded immediately and no buffers are queued anyway.
1226    */
1227   if (event) {
1228     if (!GST_EVENT_IS_SERIALIZED (event) || forward_immediate) {
1229       ret = gst_pad_push_event (parse->srcpad, event);
1230     } else {
1231       // GST_VIDEO_DECODER_STREAM_LOCK (decoder);
1232       parse->priv->pending_events =
1233           g_list_prepend (parse->priv->pending_events, event);
1234       // GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
1235       ret = TRUE;
1236     }
1237   }
1238
1239   GST_DEBUG_OBJECT (parse, "event handled");
1240
1241   return ret;
1242 }
1243
1244 static gboolean
1245 gst_base_parse_sink_query_default (GstBaseParse * parse, GstQuery * query)
1246 {
1247   GstPad *pad;
1248   gboolean res;
1249
1250   pad = GST_BASE_PARSE_SINK_PAD (parse);
1251
1252   switch (GST_QUERY_TYPE (query)) {
1253     case GST_QUERY_CAPS:
1254     {
1255       GstBaseParseClass *bclass;
1256
1257       bclass = GST_BASE_PARSE_GET_CLASS (parse);
1258
1259       if (bclass->get_sink_caps) {
1260         GstCaps *caps, *filter;
1261
1262         gst_query_parse_caps (query, &filter);
1263         caps = bclass->get_sink_caps (parse, filter);
1264         GST_LOG_OBJECT (parse, "sink getcaps returning caps %" GST_PTR_FORMAT,
1265             caps);
1266         gst_query_set_caps_result (query, caps);
1267         gst_caps_unref (caps);
1268
1269         res = TRUE;
1270       } else {
1271         GstCaps *caps, *template_caps, *filter;
1272
1273         gst_query_parse_caps (query, &filter);
1274         template_caps = gst_pad_get_pad_template_caps (pad);
1275         if (filter != NULL) {
1276           caps =
1277               gst_caps_intersect_full (filter, template_caps,
1278               GST_CAPS_INTERSECT_FIRST);
1279           gst_caps_unref (template_caps);
1280         } else {
1281           caps = template_caps;
1282         }
1283         gst_query_set_caps_result (query, caps);
1284         gst_caps_unref (caps);
1285
1286         res = TRUE;
1287       }
1288       break;
1289     }
1290     default:
1291     {
1292       res = gst_pad_query_default (pad, GST_OBJECT_CAST (parse), query);
1293       break;
1294     }
1295   }
1296
1297   return res;
1298 }
1299
1300 static gboolean
1301 gst_base_parse_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
1302 {
1303   GstBaseParseClass *bclass;
1304   GstBaseParse *parse;
1305   gboolean ret;
1306
1307   parse = GST_BASE_PARSE (parent);
1308   bclass = GST_BASE_PARSE_GET_CLASS (parse);
1309
1310   GST_DEBUG_OBJECT (parse, "%s query", GST_QUERY_TYPE_NAME (query));
1311
1312   if (bclass->sink_query)
1313     ret = bclass->sink_query (parse, query);
1314   else
1315     ret = FALSE;
1316
1317   GST_LOG_OBJECT (parse, "%s query result: %d %" GST_PTR_FORMAT,
1318       GST_QUERY_TYPE_NAME (query), ret, query);
1319
1320   return ret;
1321 }
1322
1323 static gboolean
1324 gst_base_parse_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
1325 {
1326   GstBaseParseClass *bclass;
1327   GstBaseParse *parse;
1328   gboolean ret;
1329
1330   parse = GST_BASE_PARSE (parent);
1331   bclass = GST_BASE_PARSE_GET_CLASS (parse);
1332
1333   GST_DEBUG_OBJECT (parse, "%s query: %" GST_PTR_FORMAT,
1334       GST_QUERY_TYPE_NAME (query), query);
1335
1336   if (bclass->src_query)
1337     ret = bclass->src_query (parse, query);
1338   else
1339     ret = FALSE;
1340
1341   GST_LOG_OBJECT (parse, "%s query result: %d %" GST_PTR_FORMAT,
1342       GST_QUERY_TYPE_NAME (query), ret, query);
1343
1344   return ret;
1345 }
1346
1347 /* gst_base_parse_src_event:
1348  * @pad: #GstPad that received the event.
1349  * @event: #GstEvent that was received.
1350  *
1351  * Handler for source pad events.
1352  *
1353  * Returns: TRUE if the event was handled.
1354  */
1355 static gboolean
1356 gst_base_parse_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
1357 {
1358   GstBaseParse *parse;
1359   GstBaseParseClass *bclass;
1360   gboolean ret = TRUE;
1361
1362   parse = GST_BASE_PARSE (parent);
1363   bclass = GST_BASE_PARSE_GET_CLASS (parse);
1364
1365   GST_DEBUG_OBJECT (parse, "event %d, %s", GST_EVENT_TYPE (event),
1366       GST_EVENT_TYPE_NAME (event));
1367
1368   if (bclass->src_event)
1369     ret = bclass->src_event (parse, event);
1370   else
1371     gst_event_unref (event);
1372
1373   return ret;
1374 }
1375
1376 static gboolean
1377 gst_base_parse_is_seekable (GstBaseParse * parse)
1378 {
1379   /* FIXME: could do more here, e.g. check index or just send data from 0
1380    * in pull mode and let decoder/sink clip */
1381   return parse->priv->syncable;
1382 }
1383
1384 /* gst_base_parse_src_event_default:
1385  * @parse: #GstBaseParse.
1386  * @event: #GstEvent that was received.
1387  *
1388  * Default srcpad event handler.
1389  *
1390  * Returns: TRUE if the event was handled and can be dropped.
1391  */
1392 static gboolean
1393 gst_base_parse_src_event_default (GstBaseParse * parse, GstEvent * event)
1394 {
1395   gboolean res = FALSE;
1396
1397   switch (GST_EVENT_TYPE (event)) {
1398     case GST_EVENT_SEEK:
1399       if (gst_base_parse_is_seekable (parse))
1400         res = gst_base_parse_handle_seek (parse, event);
1401       break;
1402     default:
1403       res = gst_pad_event_default (parse->srcpad, GST_OBJECT_CAST (parse),
1404           event);
1405       break;
1406   }
1407   return res;
1408 }
1409
1410
1411 /**
1412  * gst_base_parse_convert_default:
1413  * @parse: #GstBaseParse.
1414  * @src_format: #GstFormat describing the source format.
1415  * @src_value: Source value to be converted.
1416  * @dest_format: #GstFormat defining the converted format.
1417  * @dest_value: Pointer where the conversion result will be put.
1418  *
1419  * Default implementation of "convert" vmethod in #GstBaseParse class.
1420  *
1421  * Returns: TRUE if conversion was successful.
1422  */
1423 gboolean
1424 gst_base_parse_convert_default (GstBaseParse * parse,
1425     GstFormat src_format,
1426     gint64 src_value, GstFormat dest_format, gint64 * dest_value)
1427 {
1428   gboolean ret = FALSE;
1429   guint64 bytes, duration;
1430
1431   if (G_UNLIKELY (src_format == dest_format)) {
1432     *dest_value = src_value;
1433     return TRUE;
1434   }
1435
1436   if (G_UNLIKELY (src_value == -1)) {
1437     *dest_value = -1;
1438     return TRUE;
1439   }
1440
1441   if (G_UNLIKELY (src_value == 0)) {
1442     *dest_value = 0;
1443     return TRUE;
1444   }
1445
1446   /* need at least some frames */
1447   if (!parse->priv->framecount)
1448     goto no_framecount;
1449
1450   duration = parse->priv->acc_duration / GST_MSECOND;
1451   bytes = parse->priv->bytecount;
1452
1453   if (G_UNLIKELY (!duration || !bytes))
1454     goto no_duration_bytes;
1455
1456   if (src_format == GST_FORMAT_BYTES) {
1457     if (dest_format == GST_FORMAT_TIME) {
1458       /* BYTES -> TIME conversion */
1459       GST_DEBUG_OBJECT (parse, "converting bytes -> time");
1460       *dest_value = gst_util_uint64_scale (src_value, duration, bytes);
1461       *dest_value *= GST_MSECOND;
1462       GST_DEBUG_OBJECT (parse, "conversion result: %" G_GINT64_FORMAT " ms",
1463           *dest_value / GST_MSECOND);
1464       ret = TRUE;
1465     } else {
1466       GST_DEBUG_OBJECT (parse, "converting bytes -> other not implemented");
1467     }
1468   } else if (src_format == GST_FORMAT_TIME) {
1469     if (dest_format == GST_FORMAT_BYTES) {
1470       GST_DEBUG_OBJECT (parse, "converting time -> bytes");
1471       *dest_value = gst_util_uint64_scale (src_value / GST_MSECOND, bytes,
1472           duration);
1473       GST_DEBUG_OBJECT (parse,
1474           "time %" G_GINT64_FORMAT " ms in bytes = %" G_GINT64_FORMAT,
1475           src_value / GST_MSECOND, *dest_value);
1476       ret = TRUE;
1477     } else {
1478       GST_DEBUG_OBJECT (parse, "converting time -> other not implemented");
1479     }
1480   } else if (src_format == GST_FORMAT_DEFAULT) {
1481     /* DEFAULT == frame-based */
1482     if (dest_format == GST_FORMAT_TIME) {
1483       GST_DEBUG_OBJECT (parse, "converting default -> time");
1484       if (parse->priv->fps_den) {
1485         *dest_value = gst_util_uint64_scale (src_value,
1486             GST_SECOND * parse->priv->fps_den, parse->priv->fps_num);
1487         ret = TRUE;
1488       }
1489     } else {
1490       GST_DEBUG_OBJECT (parse, "converting default -> other not implemented");
1491     }
1492   } else {
1493     GST_DEBUG_OBJECT (parse, "conversion not implemented");
1494   }
1495   return ret;
1496
1497   /* ERRORS */
1498 no_framecount:
1499   {
1500     GST_DEBUG_OBJECT (parse, "no framecount");
1501     return FALSE;
1502   }
1503 no_duration_bytes:
1504   {
1505     GST_DEBUG_OBJECT (parse, "no duration %" G_GUINT64_FORMAT ", bytes %"
1506         G_GUINT64_FORMAT, duration, bytes);
1507     return FALSE;
1508   }
1509
1510 }
1511
1512 static void
1513 gst_base_parse_update_duration (GstBaseParse * baseparse)
1514 {
1515   GstPad *peer;
1516   GstBaseParse *parse;
1517
1518   parse = GST_BASE_PARSE (baseparse);
1519
1520   peer = gst_pad_get_peer (parse->sinkpad);
1521   if (peer) {
1522     gboolean qres = FALSE;
1523     gint64 ptot, dest_value;
1524
1525     qres = gst_pad_query_duration (peer, GST_FORMAT_BYTES, &ptot);
1526     gst_object_unref (GST_OBJECT (peer));
1527     if (qres) {
1528       if (gst_base_parse_convert (parse, GST_FORMAT_BYTES, ptot,
1529               GST_FORMAT_TIME, &dest_value)) {
1530
1531         /* inform if duration changed, but try to avoid spamming */
1532         parse->priv->estimated_drift +=
1533             dest_value - parse->priv->estimated_duration;
1534         if (parse->priv->estimated_drift > GST_SECOND ||
1535             parse->priv->estimated_drift < -GST_SECOND) {
1536           gst_element_post_message (GST_ELEMENT (parse),
1537               gst_message_new_duration_changed (GST_OBJECT (parse)));
1538           parse->priv->estimated_drift = 0;
1539         }
1540         parse->priv->estimated_duration = dest_value;
1541         GST_LOG_OBJECT (parse,
1542             "updated estimated duration to %" GST_TIME_FORMAT,
1543             GST_TIME_ARGS (dest_value));
1544       }
1545     }
1546   }
1547 }
1548
1549 static void
1550 gst_base_parse_post_bitrates (GstBaseParse * parse, gboolean post_min,
1551     gboolean post_avg, gboolean post_max)
1552 {
1553   GstTagList *taglist = NULL;
1554
1555   if (post_min && parse->priv->post_min_bitrate) {
1556     taglist = gst_tag_list_new_empty ();
1557
1558     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
1559         GST_TAG_MINIMUM_BITRATE, parse->priv->min_bitrate, NULL);
1560   }
1561
1562   if (post_avg && parse->priv->post_avg_bitrate) {
1563     if (taglist == NULL)
1564       taglist = gst_tag_list_new_empty ();
1565
1566     parse->priv->posted_avg_bitrate = parse->priv->avg_bitrate;
1567     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
1568         parse->priv->avg_bitrate, NULL);
1569   }
1570
1571   if (post_max && parse->priv->post_max_bitrate) {
1572     if (taglist == NULL)
1573       taglist = gst_tag_list_new_empty ();
1574
1575     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
1576         GST_TAG_MAXIMUM_BITRATE, parse->priv->max_bitrate, NULL);
1577   }
1578
1579   GST_DEBUG_OBJECT (parse, "Updated bitrates. Min: %u, Avg: %u, Max: %u",
1580       parse->priv->min_bitrate, parse->priv->avg_bitrate,
1581       parse->priv->max_bitrate);
1582
1583   if (taglist != NULL) {
1584     gst_pad_push_event (parse->srcpad, gst_event_new_tag (taglist));
1585   }
1586 }
1587
1588 /* gst_base_parse_update_bitrates:
1589  * @parse: #GstBaseParse.
1590  * @buffer: Current frame as a #GstBuffer
1591  *
1592  * Keeps track of the minimum and maximum bitrates, and also maintains a
1593  * running average bitrate of the stream so far.
1594  */
1595 static void
1596 gst_base_parse_update_bitrates (GstBaseParse * parse, GstBaseParseFrame * frame)
1597 {
1598   /* Only update the tag on a 10 kbps delta */
1599   static const gint update_threshold = 10000;
1600
1601   guint64 data_len, frame_dur;
1602   gint overhead, frame_bitrate, old_avg_bitrate;
1603   gboolean update_min = FALSE, update_avg = FALSE, update_max = FALSE;
1604   GstBuffer *buffer = frame->buffer;
1605
1606   overhead = frame->overhead;
1607   if (overhead == -1)
1608     return;
1609
1610   data_len = gst_buffer_get_size (buffer) - overhead;
1611   parse->priv->data_bytecount += data_len;
1612
1613   /* duration should be valid by now,
1614    * either set by subclass or maybe based on fps settings */
1615   if (GST_BUFFER_DURATION_IS_VALID (buffer) && parse->priv->acc_duration != 0) {
1616     /* Calculate duration of a frame from buffer properties */
1617     frame_dur = GST_BUFFER_DURATION (buffer);
1618     parse->priv->avg_bitrate = (8 * parse->priv->data_bytecount * GST_SECOND) /
1619         parse->priv->acc_duration;
1620
1621   } else {
1622     /* No way to figure out frame duration (is this even possible?) */
1623     return;
1624   }
1625
1626   /* override if subclass provided bitrate, e.g. metadata based */
1627   if (parse->priv->bitrate) {
1628     parse->priv->avg_bitrate = parse->priv->bitrate;
1629     /* spread this (confirmed) info ASAP */
1630     if (parse->priv->posted_avg_bitrate != parse->priv->avg_bitrate)
1631       gst_base_parse_post_bitrates (parse, FALSE, TRUE, FALSE);
1632   }
1633
1634   if (frame_dur)
1635     frame_bitrate = (8 * data_len * GST_SECOND) / frame_dur;
1636   else
1637     return;
1638
1639   GST_LOG_OBJECT (parse, "frame bitrate %u, avg bitrate %u", frame_bitrate,
1640       parse->priv->avg_bitrate);
1641
1642   if (parse->priv->framecount < MIN_FRAMES_TO_POST_BITRATE) {
1643     goto exit;
1644   } else if (parse->priv->framecount == MIN_FRAMES_TO_POST_BITRATE) {
1645     /* always post all at threshold time */
1646     update_min = update_max = update_avg = TRUE;
1647   }
1648
1649   if (G_LIKELY (parse->priv->framecount >= MIN_FRAMES_TO_POST_BITRATE)) {
1650     if (frame_bitrate < parse->priv->min_bitrate) {
1651       parse->priv->min_bitrate = frame_bitrate;
1652       update_min = TRUE;
1653     }
1654
1655     if (frame_bitrate > parse->priv->max_bitrate) {
1656       parse->priv->max_bitrate = frame_bitrate;
1657       update_max = TRUE;
1658     }
1659
1660     old_avg_bitrate = parse->priv->posted_avg_bitrate;
1661     if ((gint) (old_avg_bitrate - parse->priv->avg_bitrate) > update_threshold
1662         || (gint) (parse->priv->avg_bitrate - old_avg_bitrate) >
1663         update_threshold)
1664       update_avg = TRUE;
1665   }
1666
1667   if ((update_min || update_avg || update_max))
1668     gst_base_parse_post_bitrates (parse, update_min, update_avg, update_max);
1669
1670 exit:
1671   return;
1672 }
1673
1674 /**
1675  * gst_base_parse_add_index_entry:
1676  * @parse: #GstBaseParse.
1677  * @offset: offset of entry
1678  * @ts: timestamp associated with offset
1679  * @key: whether entry refers to keyframe
1680  * @force: add entry disregarding sanity checks
1681  *
1682  * Adds an entry to the index associating @offset to @ts.  It is recommended
1683  * to only add keyframe entries.  @force allows to bypass checks, such as
1684  * whether the stream is (upstream) seekable, another entry is already "close"
1685  * to the new entry, etc.
1686  *
1687  * Returns: #gboolean indicating whether entry was added
1688  */
1689 gboolean
1690 gst_base_parse_add_index_entry (GstBaseParse * parse, guint64 offset,
1691     GstClockTime ts, gboolean key, gboolean force)
1692 {
1693   gboolean ret = FALSE;
1694   GstIndexAssociation associations[2];
1695
1696   GST_LOG_OBJECT (parse, "Adding key=%d index entry %" GST_TIME_FORMAT
1697       " @ offset 0x%08" G_GINT64_MODIFIER "x", key, GST_TIME_ARGS (ts), offset);
1698
1699   if (G_LIKELY (!force)) {
1700
1701     if (!parse->priv->upstream_seekable) {
1702       GST_DEBUG_OBJECT (parse, "upstream not seekable; discarding");
1703       goto exit;
1704     }
1705
1706     /* FIXME need better helper data structure that handles these issues
1707      * related to ongoing collecting of index entries */
1708     if (parse->priv->index_last_offset + parse->priv->idx_byte_interval >=
1709         (gint64) offset) {
1710       GST_LOG_OBJECT (parse,
1711           "already have entries up to offset 0x%08" G_GINT64_MODIFIER "x",
1712           parse->priv->index_last_offset + parse->priv->idx_byte_interval);
1713       goto exit;
1714     }
1715
1716     if (GST_CLOCK_TIME_IS_VALID (parse->priv->index_last_ts) &&
1717         GST_CLOCK_DIFF (parse->priv->index_last_ts, ts) <
1718         parse->priv->idx_interval) {
1719       GST_LOG_OBJECT (parse, "entry too close to last time %" GST_TIME_FORMAT,
1720           GST_TIME_ARGS (parse->priv->index_last_ts));
1721       goto exit;
1722     }
1723
1724     /* if last is not really the last one */
1725     if (!parse->priv->index_last_valid) {
1726       GstClockTime prev_ts;
1727
1728       gst_base_parse_find_offset (parse, ts, TRUE, &prev_ts);
1729       if (GST_CLOCK_DIFF (prev_ts, ts) < parse->priv->idx_interval) {
1730         GST_LOG_OBJECT (parse,
1731             "entry too close to existing entry %" GST_TIME_FORMAT,
1732             GST_TIME_ARGS (prev_ts));
1733         parse->priv->index_last_offset = offset;
1734         parse->priv->index_last_ts = ts;
1735         goto exit;
1736       }
1737     }
1738   }
1739
1740   associations[0].format = GST_FORMAT_TIME;
1741   associations[0].value = ts;
1742   associations[1].format = GST_FORMAT_BYTES;
1743   associations[1].value = offset;
1744
1745   /* index might change on-the-fly, although that would be nutty app ... */
1746   GST_BASE_PARSE_INDEX_LOCK (parse);
1747   gst_index_add_associationv (parse->priv->index, parse->priv->index_id,
1748       (key) ? GST_INDEX_ASSOCIATION_FLAG_KEY_UNIT :
1749       GST_INDEX_ASSOCIATION_FLAG_DELTA_UNIT, 2,
1750       (const GstIndexAssociation *) &associations);
1751   GST_BASE_PARSE_INDEX_UNLOCK (parse);
1752
1753   if (key) {
1754     parse->priv->index_last_offset = offset;
1755     parse->priv->index_last_ts = ts;
1756   }
1757
1758   ret = TRUE;
1759
1760 exit:
1761   return ret;
1762 }
1763
1764 /* check for seekable upstream, above and beyond a mere query */
1765 static void
1766 gst_base_parse_check_seekability (GstBaseParse * parse)
1767 {
1768   GstQuery *query;
1769   gboolean seekable = FALSE;
1770   gint64 start = -1, stop = -1;
1771   guint idx_interval = 0;
1772   guint64 idx_byte_interval = 0;
1773
1774   query = gst_query_new_seeking (GST_FORMAT_BYTES);
1775   if (!gst_pad_peer_query (parse->sinkpad, query)) {
1776     GST_DEBUG_OBJECT (parse, "seeking query failed");
1777     goto done;
1778   }
1779
1780   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
1781
1782   /* try harder to query upstream size if we didn't get it the first time */
1783   if (seekable && stop == -1) {
1784     GST_DEBUG_OBJECT (parse, "doing duration query to fix up unset stop");
1785     gst_pad_peer_query_duration (parse->sinkpad, GST_FORMAT_BYTES, &stop);
1786   }
1787
1788   /* if upstream doesn't know the size, it's likely that it's not seekable in
1789    * practice even if it technically may be seekable */
1790   if (seekable && (start != 0 || stop <= start)) {
1791     GST_DEBUG_OBJECT (parse, "seekable but unknown start/stop -> disable");
1792     seekable = FALSE;
1793   }
1794
1795   /* let's not put every single frame into our index */
1796   if (seekable) {
1797     if (stop < 10 * 1024 * 1024)
1798       idx_interval = 100;
1799     else if (stop < 100 * 1024 * 1024)
1800       idx_interval = 500;
1801     else
1802       idx_interval = 1000;
1803
1804     /* ensure that even for large files (e.g. very long audio files), the index
1805      * stays reasonably-size, with some arbitrary limit to the total number of
1806      * index entries */
1807     idx_byte_interval = (stop - start) / MAX_INDEX_ENTRIES;
1808     GST_DEBUG_OBJECT (parse,
1809         "Limiting index entries to %d, indexing byte interval %"
1810         G_GUINT64_FORMAT " bytes", MAX_INDEX_ENTRIES, idx_byte_interval);
1811   }
1812
1813 done:
1814   gst_query_unref (query);
1815
1816   GST_DEBUG_OBJECT (parse, "seekable: %d (%" G_GUINT64_FORMAT " - %"
1817       G_GUINT64_FORMAT ")", seekable, start, stop);
1818   parse->priv->upstream_seekable = seekable;
1819   parse->priv->upstream_size = seekable ? stop : 0;
1820
1821   GST_DEBUG_OBJECT (parse, "idx_interval: %ums", idx_interval);
1822   parse->priv->idx_interval = idx_interval * GST_MSECOND;
1823   parse->priv->idx_byte_interval = idx_byte_interval;
1824 }
1825
1826 /* some misc checks on upstream */
1827 static void
1828 gst_base_parse_check_upstream (GstBaseParse * parse)
1829 {
1830   gint64 stop;
1831
1832   if (gst_pad_peer_query_duration (parse->sinkpad, GST_FORMAT_TIME, &stop))
1833     if (GST_CLOCK_TIME_IS_VALID (stop) && stop) {
1834       /* upstream has one, accept it also, and no further updates */
1835       gst_base_parse_set_duration (parse, GST_FORMAT_TIME, stop, 0);
1836       parse->priv->upstream_has_duration = TRUE;
1837     }
1838
1839   GST_DEBUG_OBJECT (parse, "upstream_has_duration: %d",
1840       parse->priv->upstream_has_duration);
1841 }
1842
1843 /* checks src caps to determine if dealing with audio or video */
1844 /* TODO maybe forego automagic stuff and let subclass configure it ? */
1845 static void
1846 gst_base_parse_check_media (GstBaseParse * parse)
1847 {
1848   GstCaps *caps;
1849   GstStructure *s;
1850
1851   caps = gst_pad_get_current_caps (parse->srcpad);
1852   if (G_LIKELY (caps) && (s = gst_caps_get_structure (caps, 0))) {
1853     parse->priv->is_video =
1854         g_str_has_prefix (gst_structure_get_name (s), "video");
1855   } else {
1856     /* historical default */
1857     parse->priv->is_video = FALSE;
1858   }
1859   if (caps)
1860     gst_caps_unref (caps);
1861
1862   GST_DEBUG_OBJECT (parse, "media is video: %d", parse->priv->is_video);
1863 }
1864
1865 /* takes ownership of frame */
1866 static void
1867 gst_base_parse_queue_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1868 {
1869   if (!(frame->_private_flags & GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC)) {
1870     /* frame allocated on the heap, we can just take ownership */
1871     g_queue_push_tail (&parse->priv->queued_frames, frame);
1872     GST_TRACE ("queued frame %p", frame);
1873   } else {
1874     GstBaseParseFrame *copy;
1875
1876     /* probably allocated on the stack, must make a proper copy */
1877     copy = gst_base_parse_frame_copy (frame);
1878     g_queue_push_tail (&parse->priv->queued_frames, copy);
1879     GST_TRACE ("queued frame %p (copy of %p)", copy, frame);
1880     gst_base_parse_frame_free (frame);
1881   }
1882 }
1883
1884 /* makes sure that @buf is properly prepared and decorated for passing
1885  * to baseclass, and an equally setup frame is returned setup with @buf.
1886  * Takes ownership of @buf. */
1887 static GstBaseParseFrame *
1888 gst_base_parse_prepare_frame (GstBaseParse * parse, GstBuffer * buffer)
1889 {
1890   GstBaseParseFrame *frame = NULL;
1891
1892   buffer = gst_buffer_make_writable (buffer);
1893
1894   GST_LOG_OBJECT (parse,
1895       "preparing frame at offset %" G_GUINT64_FORMAT
1896       " (%#" G_GINT64_MODIFIER "x) of size %" G_GSIZE_FORMAT,
1897       GST_BUFFER_OFFSET (buffer), GST_BUFFER_OFFSET (buffer),
1898       gst_buffer_get_size (buffer));
1899
1900   if (parse->priv->discont) {
1901     GST_DEBUG_OBJECT (parse, "marking DISCONT");
1902     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
1903     parse->priv->discont = FALSE;
1904   }
1905
1906   GST_BUFFER_OFFSET (buffer) = parse->priv->offset;
1907
1908   frame = gst_base_parse_frame_new (buffer, 0, 0);
1909
1910   /* also ensure to update state flags */
1911   gst_base_parse_frame_update (parse, frame, buffer);
1912   gst_buffer_unref (buffer);
1913
1914   if (parse->priv->prev_offset != parse->priv->offset || parse->priv->new_frame) {
1915     GST_LOG_OBJECT (parse, "marking as new frame");
1916     parse->priv->new_frame = FALSE;
1917     frame->flags |= GST_BASE_PARSE_FRAME_FLAG_NEW_FRAME;
1918   }
1919
1920   frame->offset = parse->priv->prev_offset = parse->priv->offset;
1921
1922   /* use default handler to provide initial (upstream) metadata */
1923   gst_base_parse_parse_frame (parse, frame);
1924
1925   return frame;
1926 }
1927
1928 /* Wraps buffer in a frame and dispatches to subclass.
1929  * Also manages data skipping and offset handling (including adapter flushing).
1930  * Takes ownership of @buffer */
1931 static GstFlowReturn
1932 gst_base_parse_handle_buffer (GstBaseParse * parse, GstBuffer * buffer,
1933     gint * skip, gint * flushed)
1934 {
1935   GstBaseParseClass *klass = GST_BASE_PARSE_GET_CLASS (parse);
1936   GstBaseParseFrame *frame;
1937   GstFlowReturn ret;
1938
1939   g_return_val_if_fail (skip != NULL || flushed != NULL, GST_FLOW_ERROR);
1940
1941   GST_LOG_OBJECT (parse,
1942       "handling buffer of size %" G_GSIZE_FORMAT " with dts %" GST_TIME_FORMAT
1943       ", pts %" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT,
1944       gst_buffer_get_size (buffer), GST_TIME_ARGS (GST_BUFFER_DTS (buffer)),
1945       GST_TIME_ARGS (GST_BUFFER_PTS (buffer)),
1946       GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
1947
1948   /* track what is being flushed during this single round of frame processing */
1949   parse->priv->flushed = 0;
1950   *skip = 0;
1951
1952   /* make it easy for _finish_frame to pick up input data */
1953   if (parse->priv->pad_mode == GST_PAD_MODE_PULL) {
1954     gst_buffer_ref (buffer);
1955     gst_adapter_push (parse->priv->adapter, buffer);
1956   }
1957
1958   frame = gst_base_parse_prepare_frame (parse, buffer);
1959   ret = klass->handle_frame (parse, frame, skip);
1960
1961   *flushed = parse->priv->flushed;
1962
1963   GST_LOG_OBJECT (parse, "handle_frame skipped %d, flushed %d",
1964       *skip, *flushed);
1965
1966   /* subclass can only do one of these, or semantics are too unclear */
1967   g_assert (*skip == 0 || *flushed == 0);
1968
1969   /* track skipping */
1970   if (*skip > 0) {
1971     GstClockTime pts, dts;
1972     GstBuffer *outbuf;
1973
1974     GST_LOG_OBJECT (parse, "finding sync, skipping %d bytes", *skip);
1975     if (parse->segment.rate < 0.0 && !parse->priv->buffers_queued) {
1976       /* reverse playback, and no frames found yet, so we are skipping
1977        * the leading part of a fragment, which may form the tail of
1978        * fragment coming later, hopefully subclass skips efficiently ... */
1979       pts = gst_adapter_prev_pts (parse->priv->adapter, NULL);
1980       dts = gst_adapter_prev_dts (parse->priv->adapter, NULL);
1981       outbuf = gst_adapter_take_buffer (parse->priv->adapter, *skip);
1982       outbuf = gst_buffer_make_writable (outbuf);
1983       GST_BUFFER_PTS (outbuf) = pts;
1984       GST_BUFFER_DTS (outbuf) = dts;
1985       parse->priv->buffers_head =
1986           g_slist_prepend (parse->priv->buffers_head, outbuf);
1987       outbuf = NULL;
1988     } else {
1989       gst_adapter_flush (parse->priv->adapter, *skip);
1990     }
1991     if (!parse->priv->discont)
1992       parse->priv->sync_offset = parse->priv->offset;
1993     parse->priv->offset += *skip;
1994     parse->priv->discont = TRUE;
1995     /* check for indefinite skipping */
1996     if (ret == GST_FLOW_OK)
1997       ret = gst_base_parse_check_sync (parse);
1998   }
1999
2000   parse->priv->offset += *flushed;
2001
2002   if (parse->priv->pad_mode == GST_PAD_MODE_PULL) {
2003     gst_adapter_clear (parse->priv->adapter);
2004   }
2005
2006   gst_base_parse_frame_free (frame);
2007
2008   return ret;
2009 }
2010
2011 /* gst_base_parse_handle_and_push_frame:
2012  * @parse: #GstBaseParse.
2013  * @klass: #GstBaseParseClass.
2014  * @frame: (transfer full): a #GstBaseParseFrame
2015  *
2016  * Parses the frame from given buffer and pushes it forward. Also performs
2017  * timestamp handling and checks the segment limits.
2018  *
2019  * This is called with srcpad STREAM_LOCK held.
2020  *
2021  * Returns: #GstFlowReturn
2022  */
2023 static GstFlowReturn
2024 gst_base_parse_handle_and_push_frame (GstBaseParse * parse,
2025     GstBaseParseFrame * frame)
2026 {
2027   gint64 offset;
2028   GstBuffer *buffer;
2029
2030   g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR);
2031
2032   buffer = frame->buffer;
2033   offset = frame->offset;
2034
2035   /* check if subclass/format can provide ts.
2036    * If so, that allows and enables extra seek and duration determining options */
2037   if (G_UNLIKELY (parse->priv->first_frame_offset < 0)) {
2038     if (GST_BUFFER_PTS_IS_VALID (buffer) && parse->priv->has_timing_info
2039         && parse->priv->pad_mode == GST_PAD_MODE_PULL) {
2040       parse->priv->first_frame_offset = offset;
2041       parse->priv->first_frame_pts = GST_BUFFER_PTS (buffer);
2042       parse->priv->first_frame_dts = GST_BUFFER_DTS (buffer);
2043       GST_DEBUG_OBJECT (parse, "subclass provided dts %" GST_TIME_FORMAT
2044           ", pts %" GST_TIME_FORMAT " for first frame at offset %"
2045           G_GINT64_FORMAT, GST_TIME_ARGS (parse->priv->first_frame_dts),
2046           GST_TIME_ARGS (parse->priv->first_frame_pts),
2047           parse->priv->first_frame_offset);
2048       if (!GST_CLOCK_TIME_IS_VALID (parse->priv->duration)) {
2049         gint64 off;
2050         GstClockTime last_ts = G_MAXINT64;
2051
2052         GST_DEBUG_OBJECT (parse, "no duration; trying scan to determine");
2053         gst_base_parse_locate_time (parse, &last_ts, &off);
2054         if (GST_CLOCK_TIME_IS_VALID (last_ts))
2055           gst_base_parse_set_duration (parse, GST_FORMAT_TIME, last_ts, 0);
2056       }
2057     } else {
2058       /* disable further checks */
2059       parse->priv->first_frame_offset = 0;
2060     }
2061   }
2062
2063   /* track upstream time if provided, not subclass' internal notion of it */
2064   if (parse->priv->upstream_format == GST_FORMAT_TIME) {
2065     GST_BUFFER_PTS (frame->buffer) = GST_CLOCK_TIME_NONE;
2066     GST_BUFFER_DTS (frame->buffer) = GST_CLOCK_TIME_NONE;
2067   }
2068
2069   /* interpolating and no valid pts yet,
2070    * start with dts and carry on from there */
2071   if (parse->priv->infer_ts && parse->priv->pts_interpolate
2072       && !GST_CLOCK_TIME_IS_VALID (parse->priv->next_pts))
2073     parse->priv->next_pts = parse->priv->next_dts;
2074
2075   /* again use default handler to add missing metadata;
2076    * we may have new information on frame properties */
2077   gst_base_parse_parse_frame (parse, frame);
2078
2079   parse->priv->next_pts = GST_CLOCK_TIME_NONE;
2080   if (GST_BUFFER_DTS_IS_VALID (buffer) && GST_BUFFER_DURATION_IS_VALID (buffer)) {
2081     parse->priv->next_dts =
2082         GST_BUFFER_DTS (buffer) + GST_BUFFER_DURATION (buffer);
2083     if (parse->priv->pts_interpolate && GST_BUFFER_PTS_IS_VALID (buffer)) {
2084       GstClockTime next_pts =
2085           GST_BUFFER_PTS (buffer) + GST_BUFFER_DURATION (buffer);
2086       if (next_pts >= parse->priv->next_dts)
2087         parse->priv->next_pts = next_pts;
2088     }
2089   } else {
2090     /* we lost track, do not produce bogus time next time around
2091      * (probably means parser subclass has given up on parsing as well) */
2092     GST_DEBUG_OBJECT (parse, "no next fallback timestamp");
2093     parse->priv->next_dts = GST_CLOCK_TIME_NONE;
2094   }
2095
2096   if (parse->priv->upstream_seekable && parse->priv->exact_position &&
2097       GST_BUFFER_PTS_IS_VALID (buffer))
2098     gst_base_parse_add_index_entry (parse, offset,
2099         GST_BUFFER_PTS (buffer),
2100         !GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT), FALSE);
2101
2102   /* All OK, push queued frames if there are any */
2103   if (G_UNLIKELY (!g_queue_is_empty (&parse->priv->queued_frames))) {
2104     GstBaseParseFrame *queued_frame;
2105
2106     while ((queued_frame = g_queue_pop_head (&parse->priv->queued_frames))) {
2107       gst_base_parse_push_frame (parse, queued_frame);
2108     }
2109   }
2110
2111   return gst_base_parse_push_frame (parse, frame);
2112 }
2113
2114 /**
2115  * gst_base_parse_push_frame:
2116  * @parse: #GstBaseParse.
2117  * @frame: (transfer none): a #GstBaseParseFrame
2118  *
2119  * Pushes the frame's buffer downstream, sends any pending events and
2120  * does some timestamp and segment handling. Takes ownership of
2121  * frame's buffer, though caller retains ownership of @frame.
2122  *
2123  * This must be called with sinkpad STREAM_LOCK held.
2124  *
2125  * Returns: #GstFlowReturn
2126  */
2127 GstFlowReturn
2128 gst_base_parse_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
2129 {
2130   GstFlowReturn ret = GST_FLOW_OK;
2131   GstClockTime last_start = GST_CLOCK_TIME_NONE;
2132   GstClockTime last_stop = GST_CLOCK_TIME_NONE;
2133   GstBaseParseClass *klass = GST_BASE_PARSE_GET_CLASS (parse);
2134   GstBuffer *buffer;
2135   gsize size;
2136
2137   g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR);
2138   g_return_val_if_fail (frame->buffer != NULL, GST_FLOW_ERROR);
2139
2140   GST_TRACE_OBJECT (parse, "pushing frame %p", frame);
2141
2142   buffer = frame->buffer;
2143
2144   GST_LOG_OBJECT (parse,
2145       "processing buffer of size %" G_GSIZE_FORMAT " with dts %" GST_TIME_FORMAT
2146       ", pts %" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT,
2147       gst_buffer_get_size (buffer),
2148       GST_TIME_ARGS (GST_BUFFER_DTS (buffer)),
2149       GST_TIME_ARGS (GST_BUFFER_PTS (buffer)),
2150       GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
2151
2152   /* update stats */
2153   parse->priv->bytecount += frame->size;
2154   if (G_LIKELY (!(frame->flags & GST_BASE_PARSE_FRAME_FLAG_NO_FRAME))) {
2155     parse->priv->framecount++;
2156     if (GST_BUFFER_DURATION_IS_VALID (buffer)) {
2157       parse->priv->acc_duration += GST_BUFFER_DURATION (buffer);
2158     }
2159   }
2160   /* 0 means disabled */
2161   if (parse->priv->update_interval < 0)
2162     parse->priv->update_interval = 50;
2163   else if (parse->priv->update_interval > 0 &&
2164       (parse->priv->framecount % parse->priv->update_interval) == 0)
2165     gst_base_parse_update_duration (parse);
2166
2167   if (GST_BUFFER_PTS_IS_VALID (buffer))
2168     last_start = last_stop = GST_BUFFER_PTS (buffer);
2169   if (last_start != GST_CLOCK_TIME_NONE
2170       && GST_BUFFER_DURATION_IS_VALID (buffer))
2171     last_stop = last_start + GST_BUFFER_DURATION (buffer);
2172
2173   /* should have caps by now */
2174   if (!gst_pad_has_current_caps (parse->srcpad))
2175     goto no_caps;
2176
2177   if (G_UNLIKELY (parse->priv->pending_segment)) {
2178     /* have caps; check identity */
2179     gst_base_parse_check_media (parse);
2180   }
2181
2182   /* Push pending events, including SEGMENT events */
2183   if (G_UNLIKELY (parse->priv->pending_events)) {
2184     GList *r = g_list_reverse (parse->priv->pending_events);
2185     GList *l;
2186
2187     parse->priv->pending_events = NULL;
2188     for (l = r; l != NULL; l = l->next) {
2189       gst_pad_push_event (parse->srcpad, GST_EVENT (l->data));
2190     }
2191     g_list_free (r);
2192     parse->priv->pending_segment = FALSE;
2193   }
2194
2195   /* segment adjustment magic; only if we are running the whole show */
2196   if (!parse->priv->passthrough && parse->segment.rate > 0.0 &&
2197       (parse->priv->pad_mode == GST_PAD_MODE_PULL ||
2198           parse->priv->upstream_seekable)) {
2199     /* handle gaps */
2200     if (GST_CLOCK_TIME_IS_VALID (parse->segment.position) &&
2201         GST_CLOCK_TIME_IS_VALID (last_start)) {
2202       GstClockTimeDiff diff;
2203
2204       /* only send newsegments with increasing start times,
2205        * otherwise if these go back and forth downstream (sinks) increase
2206        * accumulated time and running_time */
2207       diff = GST_CLOCK_DIFF (parse->segment.position, last_start);
2208       if (G_UNLIKELY (diff > 2 * GST_SECOND
2209               && last_start > parse->segment.start
2210               && (!GST_CLOCK_TIME_IS_VALID (parse->segment.stop)
2211                   || last_start < parse->segment.stop))) {
2212
2213         GST_DEBUG_OBJECT (parse,
2214             "Gap of %" G_GINT64_FORMAT " ns detected in stream " "(%"
2215             GST_TIME_FORMAT " -> %" GST_TIME_FORMAT "). "
2216             "Sending updated SEGMENT events", diff,
2217             GST_TIME_ARGS (parse->segment.position),
2218             GST_TIME_ARGS (last_start));
2219
2220         /* skip gap FIXME */
2221         gst_pad_push_event (parse->srcpad,
2222             gst_event_new_segment (&parse->segment));
2223
2224         parse->segment.position = last_start;
2225       }
2226     }
2227   }
2228
2229   /* update bitrates and optionally post corresponding tags
2230    * (following newsegment) */
2231   gst_base_parse_update_bitrates (parse, frame);
2232
2233   if (klass->pre_push_frame) {
2234     ret = klass->pre_push_frame (parse, frame);
2235   } else {
2236     frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
2237   }
2238
2239   /* take final ownership of frame buffer */
2240   if (frame->out_buffer) {
2241     buffer = frame->out_buffer;
2242     frame->out_buffer = NULL;
2243     gst_buffer_replace (&frame->buffer, NULL);
2244   } else {
2245     buffer = frame->buffer;
2246     frame->buffer = NULL;
2247   }
2248
2249   /* subclass must play nice */
2250   g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
2251
2252   size = gst_buffer_get_size (buffer);
2253
2254   parse->priv->seen_keyframe |= parse->priv->is_video &&
2255       !GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
2256
2257   if (frame->flags & GST_BASE_PARSE_FRAME_FLAG_CLIP) {
2258     if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
2259         GST_CLOCK_TIME_IS_VALID (parse->segment.stop) &&
2260         GST_BUFFER_TIMESTAMP (buffer) >
2261         parse->segment.stop + parse->priv->lead_out_ts) {
2262       GST_LOG_OBJECT (parse, "Dropped frame, after segment");
2263       ret = GST_FLOW_EOS;
2264     } else if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
2265         GST_BUFFER_DURATION_IS_VALID (buffer) &&
2266         GST_CLOCK_TIME_IS_VALID (parse->segment.start) &&
2267         GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer) +
2268         parse->priv->lead_in_ts < parse->segment.start) {
2269       if (parse->priv->seen_keyframe) {
2270         GST_LOG_OBJECT (parse, "Frame before segment, after keyframe");
2271         ret = GST_FLOW_OK;
2272       } else {
2273         GST_LOG_OBJECT (parse, "Dropped frame, before segment");
2274         ret = GST_BASE_PARSE_FLOW_DROPPED;
2275       }
2276     } else {
2277       ret = GST_FLOW_OK;
2278     }
2279   }
2280
2281   if (ret == GST_BASE_PARSE_FLOW_DROPPED) {
2282     GST_LOG_OBJECT (parse, "frame (%" G_GSIZE_FORMAT " bytes) dropped", size);
2283     gst_buffer_unref (buffer);
2284     ret = GST_FLOW_OK;
2285   } else if (ret == GST_FLOW_OK) {
2286     if (parse->segment.rate > 0.0) {
2287       GST_LOG_OBJECT (parse, "pushing frame (%" G_GSIZE_FORMAT " bytes) now..",
2288           size);
2289       ret = gst_pad_push (parse->srcpad, buffer);
2290       GST_LOG_OBJECT (parse, "frame pushed, flow %s", gst_flow_get_name (ret));
2291     } else {
2292       GST_LOG_OBJECT (parse, "frame (%" G_GSIZE_FORMAT " bytes) queued for now",
2293           size);
2294       parse->priv->buffers_queued =
2295           g_slist_prepend (parse->priv->buffers_queued, buffer);
2296       ret = GST_FLOW_OK;
2297     }
2298   } else {
2299     GST_LOG_OBJECT (parse, "frame (%" G_GSIZE_FORMAT " bytes) not pushed: %s",
2300         size, gst_flow_get_name (ret));
2301     gst_buffer_unref (buffer);
2302     /* if we are not sufficiently in control, let upstream decide on EOS */
2303     if (ret == GST_FLOW_EOS && !parse->priv->disable_passthrough &&
2304         (parse->priv->passthrough ||
2305             (parse->priv->pad_mode == GST_PAD_MODE_PUSH &&
2306                 !parse->priv->upstream_seekable)))
2307       ret = GST_FLOW_OK;
2308   }
2309
2310   /* Update current running segment position */
2311   if (ret == GST_FLOW_OK && last_stop != GST_CLOCK_TIME_NONE &&
2312       parse->segment.position < last_stop)
2313     parse->segment.position = last_stop;
2314
2315   return ret;
2316
2317   /* ERRORS */
2318 no_caps:
2319   {
2320     GST_ELEMENT_ERROR (parse, STREAM, DECODE, ("No caps set"), (NULL));
2321     return GST_FLOW_ERROR;
2322   }
2323 }
2324
2325 /**
2326  * gst_base_parse_finish_frame:
2327  * @parse: a #GstBaseParse
2328  * @frame: a #GstBaseParseFrame
2329  * @size: consumed input data represented by frame
2330  *
2331  * Collects parsed data and pushes this downstream.
2332  * Source pad caps must be set when this is called.
2333  *
2334  * If @frame's out_buffer is set, that will be used as subsequent frame data.
2335  * Otherwise, @size samples will be taken from the input and used for output,
2336  * and the output's metadata (timestamps etc) will be taken as (optionally)
2337  * set by the subclass on @frame's (input) buffer (which is otherwise
2338  * ignored for any but the above purpose/information).
2339  *
2340  * Note that the latter buffer is invalidated by this call, whereas the
2341  * caller retains ownership of @frame.
2342  *
2343  * Returns: a #GstFlowReturn that should be escalated to caller (of caller)
2344  */
2345 GstFlowReturn
2346 gst_base_parse_finish_frame (GstBaseParse * parse, GstBaseParseFrame * frame,
2347     gint size)
2348 {
2349   GstFlowReturn ret = GST_FLOW_OK;
2350
2351   g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR);
2352   g_return_val_if_fail (frame->buffer != NULL, GST_FLOW_ERROR);
2353   g_return_val_if_fail (size > 0 || frame->out_buffer, GST_FLOW_ERROR);
2354   g_return_val_if_fail (gst_adapter_available (parse->priv->adapter) >= size,
2355       GST_FLOW_ERROR);
2356
2357   GST_LOG_OBJECT (parse, "finished frame at offset %" G_GUINT64_FORMAT ", "
2358       "flushing size %d", frame->offset, size);
2359
2360   /* some one-time start-up */
2361   if (G_UNLIKELY (parse->priv->framecount == 0)) {
2362     gst_base_parse_check_seekability (parse);
2363     gst_base_parse_check_upstream (parse);
2364   }
2365
2366   parse->priv->flushed += size;
2367
2368   if (parse->priv->scanning && frame->buffer) {
2369     if (!parse->priv->scanned_frame) {
2370       parse->priv->scanned_frame = gst_base_parse_frame_copy (frame);
2371     }
2372     goto exit;
2373   }
2374
2375   /* either PUSH or PULL mode arranges for adapter data */
2376   /* ensure output buffer */
2377   if (!frame->out_buffer) {
2378     GstBuffer *src, *dest;
2379
2380     frame->out_buffer = gst_adapter_take_buffer (parse->priv->adapter, size);
2381     dest = frame->out_buffer;
2382     src = frame->buffer;
2383     GST_BUFFER_PTS (dest) = GST_BUFFER_PTS (src);
2384     GST_BUFFER_DTS (dest) = GST_BUFFER_DTS (src);
2385     GST_BUFFER_OFFSET (dest) = GST_BUFFER_OFFSET (src);
2386     GST_BUFFER_DURATION (dest) = GST_BUFFER_DURATION (src);
2387     GST_BUFFER_OFFSET_END (dest) = GST_BUFFER_OFFSET_END (src);
2388     GST_MINI_OBJECT_FLAGS (dest) = GST_MINI_OBJECT_FLAGS (src);
2389   } else {
2390     gst_adapter_flush (parse->priv->adapter, size);
2391   }
2392
2393   /* use as input for subsequent processing */
2394   gst_buffer_replace (&frame->buffer, frame->out_buffer);
2395   gst_buffer_unref (frame->out_buffer);
2396   frame->out_buffer = NULL;
2397
2398   /* mark input size consumed */
2399   frame->size = size;
2400
2401   /* subclass might queue frames/data internally if it needs more
2402    * frames to decide on the format, or might request us to queue here. */
2403   if (frame->flags & GST_BASE_PARSE_FRAME_FLAG_DROP) {
2404     gst_buffer_replace (&frame->buffer, NULL);
2405     goto exit;
2406   } else if (frame->flags & GST_BASE_PARSE_FRAME_FLAG_QUEUE) {
2407     GstBaseParseFrame *copy;
2408
2409     copy = gst_base_parse_frame_copy (frame);
2410     copy->flags &= ~GST_BASE_PARSE_FRAME_FLAG_QUEUE;
2411     gst_base_parse_queue_frame (parse, copy);
2412     goto exit;
2413   }
2414
2415   ret = gst_base_parse_handle_and_push_frame (parse, frame);
2416
2417 exit:
2418   return ret;
2419 }
2420
2421 /* gst_base_parse_drain:
2422  *
2423  * Drains the adapter until it is empty. It decreases the min_frame_size to
2424  * match the current adapter size and calls chain method until the adapter
2425  * is emptied or chain returns with error.
2426  */
2427 static void
2428 gst_base_parse_drain (GstBaseParse * parse)
2429 {
2430   guint avail;
2431
2432   GST_DEBUG_OBJECT (parse, "draining");
2433   parse->priv->drain = TRUE;
2434
2435   for (;;) {
2436     avail = gst_adapter_available (parse->priv->adapter);
2437     if (!avail)
2438       break;
2439
2440     if (gst_base_parse_chain (parse->sinkpad, GST_OBJECT_CAST (parse),
2441             NULL) != GST_FLOW_OK) {
2442       break;
2443     }
2444
2445     /* nothing changed, maybe due to truncated frame; break infinite loop */
2446     if (avail == gst_adapter_available (parse->priv->adapter)) {
2447       GST_DEBUG_OBJECT (parse, "no change during draining; flushing");
2448       gst_adapter_clear (parse->priv->adapter);
2449     }
2450   }
2451
2452   parse->priv->drain = FALSE;
2453 }
2454
2455 /* gst_base_parse_send_buffers
2456  *
2457  * Sends buffers collected in send_buffers downstream, and ensures that list
2458  * is empty at the end (errors or not).
2459  */
2460 static GstFlowReturn
2461 gst_base_parse_send_buffers (GstBaseParse * parse)
2462 {
2463   GSList *send = NULL;
2464   GstBuffer *buf;
2465   GstFlowReturn ret = GST_FLOW_OK;
2466
2467   send = parse->priv->buffers_send;
2468
2469   /* send buffers */
2470   while (send) {
2471     buf = GST_BUFFER_CAST (send->data);
2472     GST_LOG_OBJECT (parse, "pushing buffer %p, dts %"
2473         GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT
2474         ", offset %" G_GINT64_FORMAT, buf,
2475         GST_TIME_ARGS (GST_BUFFER_DTS (buf)),
2476         GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
2477         GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_OFFSET (buf));
2478
2479     /* iterate output queue an push downstream */
2480     ret = gst_pad_push (parse->srcpad, buf);
2481     send = g_slist_delete_link (send, send);
2482
2483     /* clear any leftover if error */
2484     if (G_UNLIKELY (ret != GST_FLOW_OK)) {
2485       while (send) {
2486         buf = GST_BUFFER_CAST (send->data);
2487         gst_buffer_unref (buf);
2488         send = g_slist_delete_link (send, send);
2489       }
2490     }
2491   }
2492
2493   parse->priv->buffers_send = send;
2494
2495   return ret;
2496 }
2497
2498 /* gst_base_parse_start_fragment:
2499  *
2500  * Prepares for processing a reverse playback (forward) fragment
2501  * by (re)setting proper state variables.
2502  */
2503 static GstFlowReturn
2504 gst_base_parse_start_fragment (GstBaseParse * parse)
2505 {
2506   GST_LOG_OBJECT (parse, "starting fragment");
2507
2508   /* invalidate so no fall-back timestamping is performed;
2509    * ok if taken from subclass or upstream */
2510   parse->priv->next_pts = GST_CLOCK_TIME_NONE;
2511   parse->priv->prev_pts = GST_CLOCK_TIME_NONE;
2512   parse->priv->next_dts = GST_CLOCK_TIME_NONE;
2513   parse->priv->prev_dts = GST_CLOCK_TIME_NONE;
2514   /* prevent it hanging around stop all the time */
2515   parse->segment.position = GST_CLOCK_TIME_NONE;
2516   /* mark next run */
2517   parse->priv->discont = TRUE;
2518
2519   /* head of previous fragment is now pending tail of current fragment */
2520   parse->priv->buffers_pending = parse->priv->buffers_head;
2521   parse->priv->buffers_head = NULL;
2522
2523   return GST_FLOW_OK;
2524 }
2525
2526
2527 /* gst_base_parse_finish_fragment:
2528  *
2529  * Processes a reverse playback (forward) fragment:
2530  * - append head of last fragment that was skipped to current fragment data
2531  * - drain the resulting current fragment data (i.e. repeated chain)
2532  * - add time/duration (if needed) to frames queued by chain
2533  * - push queued data
2534  */
2535 static GstFlowReturn
2536 gst_base_parse_finish_fragment (GstBaseParse * parse, gboolean prev_head)
2537 {
2538   GstBuffer *buf;
2539   GstFlowReturn ret = GST_FLOW_OK;
2540   gboolean seen_key = FALSE, seen_delta = FALSE;
2541
2542   GST_LOG_OBJECT (parse, "finishing fragment");
2543
2544   /* restore order */
2545   parse->priv->buffers_pending = g_slist_reverse (parse->priv->buffers_pending);
2546   while (parse->priv->buffers_pending) {
2547     buf = GST_BUFFER_CAST (parse->priv->buffers_pending->data);
2548     if (prev_head) {
2549       GST_LOG_OBJECT (parse, "adding pending buffer (size %" G_GSIZE_FORMAT ")",
2550           gst_buffer_get_size (buf));
2551       gst_adapter_push (parse->priv->adapter, buf);
2552     } else {
2553       GST_LOG_OBJECT (parse, "discarding head buffer");
2554       gst_buffer_unref (buf);
2555     }
2556     parse->priv->buffers_pending =
2557         g_slist_delete_link (parse->priv->buffers_pending,
2558         parse->priv->buffers_pending);
2559   }
2560
2561   /* chain looks for frames and queues resulting ones (in stead of pushing) */
2562   /* initial skipped data is added to buffers_pending */
2563   gst_base_parse_drain (parse);
2564
2565   if (parse->priv->buffers_send) {
2566     buf = GST_BUFFER_CAST (parse->priv->buffers_send->data);
2567     seen_key |= !GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
2568   }
2569
2570   /* add metadata (if needed to queued buffers */
2571   GST_LOG_OBJECT (parse, "last timestamp: %" GST_TIME_FORMAT,
2572       GST_TIME_ARGS (parse->priv->last_pts));
2573   while (parse->priv->buffers_queued) {
2574     buf = GST_BUFFER_CAST (parse->priv->buffers_queued->data);
2575
2576     /* no touching if upstream or parsing provided time */
2577     if (GST_BUFFER_PTS_IS_VALID (buf)) {
2578       GST_LOG_OBJECT (parse, "buffer has time %" GST_TIME_FORMAT,
2579           GST_TIME_ARGS (GST_BUFFER_PTS (buf)));
2580     } else if (GST_BUFFER_DURATION_IS_VALID (buf)) {
2581       if (GST_CLOCK_TIME_IS_VALID (parse->priv->last_pts)) {
2582         if (G_LIKELY (GST_BUFFER_DURATION (buf) <= parse->priv->last_pts))
2583           parse->priv->last_pts -= GST_BUFFER_DURATION (buf);
2584         else
2585           parse->priv->last_pts = 0;
2586         GST_BUFFER_PTS (buf) = parse->priv->last_pts;
2587         GST_LOG_OBJECT (parse, "applied time %" GST_TIME_FORMAT,
2588             GST_TIME_ARGS (GST_BUFFER_PTS (buf)));
2589       }
2590       if (GST_CLOCK_TIME_IS_VALID (parse->priv->last_dts)) {
2591         if (G_LIKELY (GST_BUFFER_DURATION (buf) <= parse->priv->last_dts))
2592           parse->priv->last_dts -= GST_BUFFER_DURATION (buf);
2593         else
2594           parse->priv->last_dts = 0;
2595         GST_BUFFER_DTS (buf) = parse->priv->last_dts;
2596         GST_LOG_OBJECT (parse, "applied dts %" GST_TIME_FORMAT,
2597             GST_TIME_ARGS (GST_BUFFER_DTS (buf)));
2598       }
2599     } else {
2600       /* no idea, very bad */
2601       GST_WARNING_OBJECT (parse, "could not determine time for buffer");
2602     }
2603
2604     parse->priv->last_pts = GST_BUFFER_PTS (buf);
2605     parse->priv->last_dts = GST_BUFFER_DTS (buf);
2606
2607     /* reverse order for ascending sending */
2608     /* send downstream at keyframe not preceded by a keyframe
2609      * (e.g. that should identify start of collection of IDR nals) */
2610     if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT)) {
2611       if (seen_key) {
2612         ret = gst_base_parse_send_buffers (parse);
2613         /* if a problem, throw all to sending */
2614         if (ret != GST_FLOW_OK) {
2615           parse->priv->buffers_send =
2616               g_slist_reverse (parse->priv->buffers_queued);
2617           parse->priv->buffers_queued = NULL;
2618           break;
2619         }
2620         seen_key = FALSE;
2621       }
2622       seen_delta = TRUE;
2623     } else {
2624       seen_key = TRUE;
2625     }
2626
2627     parse->priv->buffers_send =
2628         g_slist_prepend (parse->priv->buffers_send, buf);
2629     parse->priv->buffers_queued =
2630         g_slist_delete_link (parse->priv->buffers_queued,
2631         parse->priv->buffers_queued);
2632   }
2633
2634   /* audio may have all marked as keyframe, so arrange to send here */
2635   if (!seen_delta)
2636     ret = gst_base_parse_send_buffers (parse);
2637
2638   /* any trailing unused no longer usable (ideally none) */
2639   if (G_UNLIKELY (gst_adapter_available (parse->priv->adapter))) {
2640     GST_DEBUG_OBJECT (parse, "discarding %" G_GSIZE_FORMAT " trailing bytes",
2641         gst_adapter_available (parse->priv->adapter));
2642     gst_adapter_clear (parse->priv->adapter);
2643   }
2644
2645   return ret;
2646 }
2647
2648 /* small helper that checks whether we have been trying to resync too long */
2649 static inline GstFlowReturn
2650 gst_base_parse_check_sync (GstBaseParse * parse)
2651 {
2652   if (G_UNLIKELY (parse->priv->discont &&
2653           parse->priv->offset - parse->priv->sync_offset > 2 * 1024 * 1024)) {
2654     GST_ELEMENT_ERROR (parse, STREAM, DECODE,
2655         ("Failed to parse stream"), (NULL));
2656     return GST_FLOW_ERROR;
2657   }
2658
2659   return GST_FLOW_OK;
2660 }
2661
2662 static GstFlowReturn
2663 gst_base_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
2664 {
2665   GstBaseParseClass *bclass;
2666   GstBaseParse *parse;
2667   GstFlowReturn ret = GST_FLOW_OK;
2668   GstBuffer *tmpbuf = NULL;
2669   guint fsize = 1;
2670   gint skip = -1;
2671   const guint8 *data;
2672   guint min_size, av;
2673   GstClockTime pts, dts;
2674
2675   parse = GST_BASE_PARSE (parent);
2676   bclass = GST_BASE_PARSE_GET_CLASS (parse);
2677
2678   if (parse->priv->detecting) {
2679     GstBuffer *detect_buf;
2680
2681     if (parse->priv->detect_buffers_size == 0) {
2682       detect_buf = gst_buffer_ref (buffer);
2683     } else {
2684       GList *l;
2685       guint offset = 0;
2686
2687       detect_buf = gst_buffer_new ();
2688
2689       for (l = parse->priv->detect_buffers; l; l = l->next) {
2690         gsize tmpsize = gst_buffer_get_size (l->data);
2691
2692         gst_buffer_copy_into (detect_buf, GST_BUFFER_CAST (l->data),
2693             GST_BUFFER_COPY_MEMORY, offset, tmpsize);
2694         offset += tmpsize;
2695       }
2696       if (buffer)
2697         gst_buffer_copy_into (detect_buf, buffer, GST_BUFFER_COPY_MEMORY,
2698             offset, gst_buffer_get_size (buffer));
2699     }
2700
2701     ret = bclass->detect (parse, detect_buf);
2702     gst_buffer_unref (detect_buf);
2703
2704     if (ret == GST_FLOW_OK) {
2705       GList *l;
2706
2707       /* Detected something */
2708       parse->priv->detecting = FALSE;
2709
2710       for (l = parse->priv->detect_buffers; l; l = l->next) {
2711         if (ret == GST_FLOW_OK && !parse->priv->flushing)
2712           ret =
2713               gst_base_parse_chain (GST_BASE_PARSE_SINK_PAD (parse),
2714               parent, GST_BUFFER_CAST (l->data));
2715         else
2716           gst_buffer_unref (GST_BUFFER_CAST (l->data));
2717       }
2718       g_list_free (parse->priv->detect_buffers);
2719       parse->priv->detect_buffers = NULL;
2720       parse->priv->detect_buffers_size = 0;
2721
2722       if (ret != GST_FLOW_OK) {
2723         return ret;
2724       }
2725
2726       /* Handle the current buffer */
2727     } else if (ret == GST_FLOW_NOT_NEGOTIATED) {
2728       /* Still detecting, append buffer or error out if draining */
2729
2730       if (parse->priv->drain) {
2731         GST_DEBUG_OBJECT (parse, "Draining but did not detect format yet");
2732         return GST_FLOW_ERROR;
2733       } else if (parse->priv->flushing) {
2734         g_list_foreach (parse->priv->detect_buffers, (GFunc) gst_buffer_unref,
2735             NULL);
2736         g_list_free (parse->priv->detect_buffers);
2737         parse->priv->detect_buffers = NULL;
2738         parse->priv->detect_buffers_size = 0;
2739       } else {
2740         parse->priv->detect_buffers =
2741             g_list_append (parse->priv->detect_buffers, buffer);
2742         parse->priv->detect_buffers_size += gst_buffer_get_size (buffer);
2743         return GST_FLOW_OK;
2744       }
2745     } else {
2746       /* Something went wrong, subclass responsible for error reporting */
2747       return ret;
2748     }
2749
2750     /* And now handle the current buffer if detection worked */
2751   }
2752
2753   if (G_LIKELY (buffer)) {
2754     GST_LOG_OBJECT (parse,
2755         "buffer size: %" G_GSIZE_FORMAT ", offset = %" G_GINT64_FORMAT
2756         ", dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT,
2757         gst_buffer_get_size (buffer), GST_BUFFER_OFFSET (buffer),
2758         GST_TIME_ARGS (GST_BUFFER_DTS (buffer)),
2759         GST_TIME_ARGS (GST_BUFFER_PTS (buffer)));
2760
2761     if (G_UNLIKELY (!parse->priv->disable_passthrough
2762             && parse->priv->passthrough)) {
2763       GstBaseParseFrame frame;
2764
2765       gst_base_parse_frame_init (&frame);
2766       frame.buffer = gst_buffer_make_writable (buffer);
2767       ret = gst_base_parse_push_frame (parse, &frame);
2768       gst_base_parse_frame_free (&frame);
2769       return ret;
2770     }
2771     /* upstream feeding us in reverse playback;
2772      * finish previous fragment and start new upon DISCONT */
2773     if (parse->segment.rate < 0.0) {
2774       if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))) {
2775         GST_DEBUG_OBJECT (parse, "buffer starts new reverse playback fragment");
2776         ret = gst_base_parse_finish_fragment (parse, TRUE);
2777         gst_base_parse_start_fragment (parse);
2778       }
2779     }
2780     gst_adapter_push (parse->priv->adapter, buffer);
2781   }
2782
2783   /* Parse and push as many frames as possible */
2784   /* Stop either when adapter is empty or we are flushing */
2785   while (!parse->priv->flushing) {
2786     gint flush = 0;
2787
2788     /* note: if subclass indicates MAX fsize,
2789      * this will not likely be available anyway ... */
2790     min_size = MAX (parse->priv->min_frame_size, fsize);
2791     av = gst_adapter_available (parse->priv->adapter);
2792
2793     if (G_UNLIKELY (parse->priv->drain)) {
2794       min_size = av;
2795       GST_DEBUG_OBJECT (parse, "draining, data left: %d", min_size);
2796       if (G_UNLIKELY (!min_size)) {
2797         goto done;
2798       }
2799     }
2800
2801     /* Collect at least min_frame_size bytes */
2802     if (av < min_size) {
2803       GST_DEBUG_OBJECT (parse, "not enough data available (only %d bytes)", av);
2804       goto done;
2805     }
2806
2807     /* move along with upstream timestamp (if any),
2808      * but interpolate in between */
2809     pts = gst_adapter_prev_pts (parse->priv->adapter, NULL);
2810     dts = gst_adapter_prev_dts (parse->priv->adapter, NULL);
2811     if (GST_CLOCK_TIME_IS_VALID (pts) && (parse->priv->prev_pts != pts))
2812       parse->priv->prev_pts = parse->priv->next_pts = pts;
2813
2814     if (GST_CLOCK_TIME_IS_VALID (dts) && (parse->priv->prev_dts != dts))
2815       parse->priv->prev_dts = parse->priv->next_dts = dts;
2816
2817     /* we can mess with, erm interpolate, timestamps,
2818      * and incoming stuff has PTS but no DTS seen so far,
2819      * then pick up DTS from PTS and hope for the best ... */
2820     if (parse->priv->infer_ts &&
2821         parse->priv->pts_interpolate &&
2822         !GST_CLOCK_TIME_IS_VALID (dts) &&
2823         !GST_CLOCK_TIME_IS_VALID (parse->priv->prev_dts) &&
2824         GST_CLOCK_TIME_IS_VALID (pts))
2825       parse->priv->next_dts = pts;
2826
2827     /* always pass all available data */
2828     data = gst_adapter_map (parse->priv->adapter, av);
2829     /* arrange for actual data to be copied if subclass tries to,
2830      * since what is passed is tied to the adapter */
2831     tmpbuf = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY |
2832         GST_MEMORY_FLAG_NO_SHARE, (gpointer) data, av, 0, av, NULL, NULL);
2833
2834     /* already inform subclass what timestamps we have planned,
2835      * at least if provided by time-based upstream */
2836     if (parse->priv->upstream_format == GST_FORMAT_TIME) {
2837       GST_BUFFER_PTS (tmpbuf) = parse->priv->next_pts;
2838       GST_BUFFER_DTS (tmpbuf) = parse->priv->next_dts;
2839     }
2840
2841     /* keep the adapter mapped, so keep track of what has to be flushed */
2842     ret = gst_base_parse_handle_buffer (parse, tmpbuf, &skip, &flush);
2843     tmpbuf = NULL;
2844
2845     /* probably already implicitly unmapped due to adapter operation,
2846      * but for good measure ... */
2847     gst_adapter_unmap (parse->priv->adapter);
2848     if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
2849       goto done;
2850     }
2851     if (skip == 0 && flush == 0) {
2852       GST_LOG_OBJECT (parse, "nothing skipped and no frames finished, "
2853           "breaking to get more data");
2854       goto done;
2855     }
2856   }
2857
2858 done:
2859   GST_LOG_OBJECT (parse, "chain leaving");
2860   return ret;
2861 }
2862
2863 /* pull @size bytes at current offset,
2864  * i.e. at least try to and possibly return a shorter buffer if near the end */
2865 static GstFlowReturn
2866 gst_base_parse_pull_range (GstBaseParse * parse, guint size,
2867     GstBuffer ** buffer)
2868 {
2869   GstFlowReturn ret = GST_FLOW_OK;
2870
2871   g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
2872
2873   /* Caching here actually makes much less difference than one would expect.
2874    * We do it mainly to avoid pulling buffers of 1 byte all the time */
2875   if (parse->priv->cache) {
2876     gint64 cache_offset = GST_BUFFER_OFFSET (parse->priv->cache);
2877     gint cache_size = gst_buffer_get_size (parse->priv->cache);
2878
2879     if (cache_offset <= parse->priv->offset &&
2880         (parse->priv->offset + size) <= (cache_offset + cache_size)) {
2881       *buffer = gst_buffer_copy_region (parse->priv->cache, GST_BUFFER_COPY_ALL,
2882           parse->priv->offset - cache_offset, size);
2883       GST_BUFFER_OFFSET (*buffer) = parse->priv->offset;
2884       return GST_FLOW_OK;
2885     }
2886     /* not enough data in the cache, free cache and get a new one */
2887     gst_buffer_unref (parse->priv->cache);
2888     parse->priv->cache = NULL;
2889   }
2890
2891   /* refill the cache */
2892   ret =
2893       gst_pad_pull_range (parse->sinkpad, parse->priv->offset, MAX (size,
2894           64 * 1024), &parse->priv->cache);
2895   if (ret != GST_FLOW_OK) {
2896     parse->priv->cache = NULL;
2897     return ret;
2898   }
2899
2900   if (gst_buffer_get_size (parse->priv->cache) >= size) {
2901     *buffer =
2902         gst_buffer_copy_region (parse->priv->cache, GST_BUFFER_COPY_ALL, 0,
2903         size);
2904     GST_BUFFER_OFFSET (*buffer) = parse->priv->offset;
2905     return GST_FLOW_OK;
2906   }
2907
2908   /* Not possible to get enough data, try a last time with
2909    * requesting exactly the size we need */
2910   gst_buffer_unref (parse->priv->cache);
2911   parse->priv->cache = NULL;
2912
2913   ret = gst_pad_pull_range (parse->sinkpad, parse->priv->offset, size,
2914       &parse->priv->cache);
2915
2916   if (ret != GST_FLOW_OK) {
2917     GST_DEBUG_OBJECT (parse, "pull_range returned %d", ret);
2918     *buffer = NULL;
2919     return ret;
2920   }
2921
2922   if (gst_buffer_get_size (parse->priv->cache) < size) {
2923     GST_DEBUG_OBJECT (parse, "Returning short buffer at offset %"
2924         G_GUINT64_FORMAT ": wanted %u bytes, got %" G_GSIZE_FORMAT " bytes",
2925         parse->priv->offset, size, gst_buffer_get_size (parse->priv->cache));
2926
2927     *buffer = parse->priv->cache;
2928     parse->priv->cache = NULL;
2929
2930     return GST_FLOW_OK;
2931   }
2932
2933   *buffer =
2934       gst_buffer_copy_region (parse->priv->cache, GST_BUFFER_COPY_ALL, 0, size);
2935   GST_BUFFER_OFFSET (*buffer) = parse->priv->offset;
2936
2937   return GST_FLOW_OK;
2938 }
2939
2940 static GstFlowReturn
2941 gst_base_parse_handle_previous_fragment (GstBaseParse * parse)
2942 {
2943   gint64 offset = 0;
2944   GstClockTime ts = 0;
2945   GstBuffer *buffer;
2946   GstFlowReturn ret;
2947
2948   GST_DEBUG_OBJECT (parse, "fragment ended; last_ts = %" GST_TIME_FORMAT
2949       ", last_offset = %" G_GINT64_FORMAT,
2950       GST_TIME_ARGS (parse->priv->last_pts), parse->priv->last_offset);
2951
2952   if (!parse->priv->last_offset
2953       || parse->priv->last_pts <= parse->segment.start) {
2954     GST_DEBUG_OBJECT (parse, "past start of segment %" GST_TIME_FORMAT,
2955         GST_TIME_ARGS (parse->segment.start));
2956     ret = GST_FLOW_EOS;
2957     goto exit;
2958   }
2959
2960   /* last fragment started at last_offset / last_ts;
2961    * seek back 10s capped at 1MB */
2962   if (parse->priv->last_pts >= 10 * GST_SECOND)
2963     ts = parse->priv->last_pts - 10 * GST_SECOND;
2964   /* if we are exact now, we will be more so going backwards */
2965   if (parse->priv->exact_position) {
2966     offset = gst_base_parse_find_offset (parse, ts, TRUE, NULL);
2967   } else {
2968     if (!gst_base_parse_convert (parse, GST_FORMAT_TIME, ts,
2969             GST_FORMAT_BYTES, &offset)) {
2970       GST_DEBUG_OBJECT (parse, "conversion failed, only BYTE based");
2971     }
2972   }
2973   offset = CLAMP (offset, parse->priv->last_offset - 1024 * 1024,
2974       parse->priv->last_offset - 1024);
2975   offset = MAX (0, offset);
2976
2977   GST_DEBUG_OBJECT (parse, "next fragment from offset %" G_GINT64_FORMAT,
2978       offset);
2979   parse->priv->offset = offset;
2980
2981   ret = gst_base_parse_pull_range (parse, parse->priv->last_offset - offset,
2982       &buffer);
2983   if (ret != GST_FLOW_OK)
2984     goto exit;
2985
2986   /* offset will increase again as fragment is processed/parsed */
2987   parse->priv->last_offset = offset;
2988
2989   gst_base_parse_start_fragment (parse);
2990   gst_adapter_push (parse->priv->adapter, buffer);
2991   ret = gst_base_parse_finish_fragment (parse, TRUE);
2992   if (ret != GST_FLOW_OK)
2993     goto exit;
2994
2995   /* force previous fragment */
2996   parse->priv->offset = -1;
2997
2998 exit:
2999   return ret;
3000 }
3001
3002 /* PULL mode:
3003  * pull and scan for next frame starting from current offset
3004  * ajusts sync, drain and offset going along */
3005 static GstFlowReturn
3006 gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass)
3007 {
3008   GstBuffer *buffer;
3009   GstFlowReturn ret = GST_FLOW_OK;
3010   guint fsize, min_size;
3011   gint flushed = 0;
3012   gint skip = 0;
3013
3014   GST_LOG_OBJECT (parse, "scanning for frame at offset %" G_GUINT64_FORMAT
3015       " (%#" G_GINT64_MODIFIER "x)", parse->priv->offset, parse->priv->offset);
3016
3017   /* let's make this efficient for all subclass once and for all;
3018    * maybe it does not need this much, but in the latter case, we know we are
3019    * in pull mode here and might as well try to read and supply more anyway
3020    * (so does the buffer caching mechanism) */
3021   fsize = 64 * 1024;
3022
3023   while (TRUE) {
3024     min_size = MAX (parse->priv->min_frame_size, fsize);
3025
3026     GST_LOG_OBJECT (parse, "reading buffer size %u", min_size);
3027
3028     ret = gst_base_parse_pull_range (parse, min_size, &buffer);
3029     if (ret != GST_FLOW_OK)
3030       goto done;
3031
3032     /* if we got a short read, inform subclass we are draining leftover
3033      * and no more is to be expected */
3034     if (gst_buffer_get_size (buffer) < min_size) {
3035       GST_LOG_OBJECT (parse, "... but did not get that; marked draining");
3036       parse->priv->drain = TRUE;
3037     }
3038
3039     if (parse->priv->detecting) {
3040       ret = klass->detect (parse, buffer);
3041       if (ret == GST_FLOW_NOT_NEGOTIATED) {
3042         /* If draining we error out, otherwise request a buffer
3043          * with 64kb more */
3044         if (parse->priv->drain) {
3045           gst_buffer_unref (buffer);
3046           GST_ERROR_OBJECT (parse, "Failed to detect format but draining");
3047           return GST_FLOW_ERROR;
3048         } else {
3049           fsize += 64 * 1024;
3050           gst_buffer_unref (buffer);
3051           continue;
3052         }
3053       } else if (ret != GST_FLOW_OK) {
3054         gst_buffer_unref (buffer);
3055         GST_ERROR_OBJECT (parse, "detect() returned %s",
3056             gst_flow_get_name (ret));
3057         return ret;
3058       }
3059
3060       /* Else handle this buffer normally */
3061     }
3062
3063     ret = gst_base_parse_handle_buffer (parse, buffer, &skip, &flushed);
3064     if (ret != GST_FLOW_OK)
3065       break;
3066
3067     /* something flushed means something happened,
3068      * and we should bail out of this loop so as not to occupy
3069      * the task thread indefinitely */
3070     if (flushed) {
3071       GST_LOG_OBJECT (parse, "frame finished, breaking loop");
3072       break;
3073     }
3074     /* nothing flushed, no skip and draining, so nothing left to do */
3075     if (!skip && parse->priv->drain) {
3076       GST_LOG_OBJECT (parse, "no activity or result when draining; "
3077           "breaking loop and marking EOS");
3078       ret = GST_FLOW_EOS;
3079       break;
3080     }
3081     /* otherwise, get some more data
3082      * note that is checked this does not happen indefinitely */
3083     if (!skip) {
3084       GST_LOG_OBJECT (parse, "getting some more data");
3085       fsize += 64 * 1024;
3086     }
3087     parse->priv->drain = FALSE;
3088   }
3089
3090 done:
3091   return ret;
3092 }
3093
3094 /* Loop that is used in pull mode to retrieve data from upstream */
3095 static void
3096 gst_base_parse_loop (GstPad * pad)
3097 {
3098   GstBaseParse *parse;
3099   GstBaseParseClass *klass;
3100   GstFlowReturn ret = GST_FLOW_OK;
3101
3102   parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
3103   klass = GST_BASE_PARSE_GET_CLASS (parse);
3104
3105   GST_LOG_OBJECT (parse, "Entering parse loop");
3106
3107   if (G_UNLIKELY (parse->priv->push_stream_start)) {
3108     gchar *stream_id;
3109     GstEvent *event;
3110
3111     stream_id =
3112         gst_pad_create_stream_id (parse->srcpad, GST_ELEMENT_CAST (parse),
3113         NULL);
3114
3115     event = gst_event_new_stream_start (stream_id);
3116     gst_event_set_group_id (event, gst_util_group_id_next ());
3117
3118     GST_DEBUG_OBJECT (parse, "Pushing STREAM_START");
3119     gst_pad_push_event (parse->srcpad, event);
3120     parse->priv->push_stream_start = FALSE;
3121     g_free (stream_id);
3122   }
3123
3124   /* reverse playback:
3125    * first fragment (closest to stop time) is handled normally below,
3126    * then we pull in fragments going backwards */
3127   if (parse->segment.rate < 0.0) {
3128     /* check if we jumped back to a previous fragment,
3129      * which is a post-first fragment */
3130     if (parse->priv->offset < 0) {
3131       ret = gst_base_parse_handle_previous_fragment (parse);
3132       goto done;
3133     }
3134   }
3135
3136   ret = gst_base_parse_scan_frame (parse, klass);
3137   if (ret != GST_FLOW_OK)
3138     goto done;
3139
3140   /* eat expected eos signalling past segment in reverse playback */
3141   if (parse->segment.rate < 0.0 && ret == GST_FLOW_EOS &&
3142       parse->segment.position >= parse->segment.stop) {
3143     GST_DEBUG_OBJECT (parse, "downstream has reached end of segment");
3144     /* push what was accumulated during loop run */
3145     gst_base_parse_finish_fragment (parse, FALSE);
3146     /* force previous fragment */
3147     parse->priv->offset = -1;
3148     ret = GST_FLOW_OK;
3149   }
3150
3151 done:
3152   if (ret == GST_FLOW_EOS)
3153     goto eos;
3154   else if (ret != GST_FLOW_OK)
3155     goto pause;
3156
3157   gst_object_unref (parse);
3158   return;
3159
3160   /* ERRORS */
3161 eos:
3162   {
3163     ret = GST_FLOW_EOS;
3164     GST_DEBUG_OBJECT (parse, "eos");
3165     /* fall-through */
3166   }
3167 pause:
3168   {
3169     gboolean push_eos = FALSE;
3170
3171     GST_DEBUG_OBJECT (parse, "pausing task, reason %s",
3172         gst_flow_get_name (ret));
3173     gst_pad_pause_task (parse->sinkpad);
3174
3175     if (ret == GST_FLOW_EOS) {
3176       /* handle end-of-stream/segment */
3177       if (parse->segment.flags & GST_SEGMENT_FLAG_SEGMENT) {
3178         gint64 stop;
3179
3180         if ((stop = parse->segment.stop) == -1)
3181           stop = parse->segment.duration;
3182
3183         GST_DEBUG_OBJECT (parse, "sending segment_done");
3184
3185         gst_element_post_message
3186             (GST_ELEMENT_CAST (parse),
3187             gst_message_new_segment_done (GST_OBJECT_CAST (parse),
3188                 GST_FORMAT_TIME, stop));
3189         gst_pad_push_event (parse->srcpad,
3190             gst_event_new_segment_done (GST_FORMAT_TIME, stop));
3191       } else {
3192         /* If we STILL have zero frames processed, fire an error */
3193         if (parse->priv->framecount == 0) {
3194           GST_ELEMENT_ERROR (parse, STREAM, WRONG_TYPE,
3195               ("No valid frames found before end of stream"), (NULL));
3196         }
3197         push_eos = TRUE;
3198       }
3199     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
3200       /* for fatal errors we post an error message, wrong-state is
3201        * not fatal because it happens due to flushes and only means
3202        * that we should stop now. */
3203       GST_ELEMENT_ERROR (parse, STREAM, FAILED, (NULL),
3204           ("streaming stopped, reason %s", gst_flow_get_name (ret)));
3205       push_eos = TRUE;
3206     }
3207     if (push_eos) {
3208       /* Push pending events, including SEGMENT events */
3209       if (G_UNLIKELY (parse->priv->pending_events)) {
3210         GList *r = g_list_reverse (parse->priv->pending_events);
3211         GList *l;
3212
3213         parse->priv->pending_events = NULL;
3214         for (l = r; l != NULL; l = l->next) {
3215           gst_pad_push_event (parse->srcpad, GST_EVENT (l->data));
3216         }
3217         g_list_free (r);
3218         parse->priv->pending_segment = FALSE;
3219       }
3220
3221       gst_pad_push_event (parse->srcpad, gst_event_new_eos ());
3222     }
3223     gst_object_unref (parse);
3224   }
3225 }
3226
3227 static gboolean
3228 gst_base_parse_sink_activate (GstPad * sinkpad, GstObject * parent)
3229 {
3230   GstSchedulingFlags sched_flags;
3231   GstBaseParse *parse;
3232   GstQuery *query;
3233   gboolean pull_mode;
3234
3235   parse = GST_BASE_PARSE (parent);
3236
3237   GST_DEBUG_OBJECT (parse, "sink activate");
3238
3239   query = gst_query_new_scheduling ();
3240   if (!gst_pad_peer_query (sinkpad, query)) {
3241     gst_query_unref (query);
3242     goto baseparse_push;
3243   }
3244
3245   gst_query_parse_scheduling (query, &sched_flags, NULL, NULL, NULL);
3246
3247   pull_mode = gst_query_has_scheduling_mode (query, GST_PAD_MODE_PULL)
3248       && ((sched_flags & GST_SCHEDULING_FLAG_SEEKABLE) != 0);
3249
3250   gst_query_unref (query);
3251
3252   if (!pull_mode)
3253     goto baseparse_push;
3254
3255   GST_DEBUG_OBJECT (parse, "trying to activate in pull mode");
3256   if (!gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE))
3257     goto baseparse_push;
3258
3259   parse->priv->push_stream_start = TRUE;
3260
3261   return gst_pad_start_task (sinkpad, (GstTaskFunction) gst_base_parse_loop,
3262       sinkpad, NULL);
3263   /* fallback */
3264 baseparse_push:
3265   {
3266     GST_DEBUG_OBJECT (parse, "trying to activate in push mode");
3267     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
3268   }
3269 }
3270
3271 static gboolean
3272 gst_base_parse_activate (GstBaseParse * parse, gboolean active)
3273 {
3274   GstBaseParseClass *klass;
3275   gboolean result = TRUE;
3276
3277   GST_DEBUG_OBJECT (parse, "activate %d", active);
3278
3279   klass = GST_BASE_PARSE_GET_CLASS (parse);
3280
3281   if (active) {
3282     if (parse->priv->pad_mode == GST_PAD_MODE_NONE && klass->start)
3283       result = klass->start (parse);
3284
3285     /* If the subclass implements ::detect we want to
3286      * call it for the first buffers now */
3287     parse->priv->detecting = (klass->detect != NULL);
3288   } else {
3289     /* We must make sure streaming has finished before resetting things
3290      * and calling the ::stop vfunc */
3291     GST_PAD_STREAM_LOCK (parse->sinkpad);
3292     GST_PAD_STREAM_UNLOCK (parse->sinkpad);
3293
3294     if (parse->priv->pad_mode != GST_PAD_MODE_NONE && klass->stop)
3295       result = klass->stop (parse);
3296
3297     parse->priv->pad_mode = GST_PAD_MODE_NONE;
3298   }
3299   GST_DEBUG_OBJECT (parse, "activate return: %d", result);
3300   return result;
3301 }
3302
3303 static gboolean
3304 gst_base_parse_sink_activate_mode (GstPad * pad, GstObject * parent,
3305     GstPadMode mode, gboolean active)
3306 {
3307   gboolean result;
3308   GstBaseParse *parse;
3309
3310   parse = GST_BASE_PARSE (parent);
3311
3312   GST_DEBUG_OBJECT (parse, "sink %sactivate in %s mode",
3313       (active) ? "" : "de", gst_pad_mode_get_name (mode));
3314
3315   if (!gst_base_parse_activate (parse, active))
3316     goto activate_failed;
3317
3318   switch (mode) {
3319     case GST_PAD_MODE_PULL:
3320       if (active) {
3321         parse->priv->pending_events =
3322             g_list_prepend (parse->priv->pending_events,
3323             gst_event_new_segment (&parse->segment));
3324         parse->priv->pending_segment = TRUE;
3325         result = TRUE;
3326       } else {
3327         result = gst_pad_stop_task (pad);
3328       }
3329       break;
3330     default:
3331       result = TRUE;
3332       break;
3333   }
3334   if (result)
3335     parse->priv->pad_mode = active ? mode : GST_PAD_MODE_NONE;
3336
3337   GST_DEBUG_OBJECT (parse, "sink activate return: %d", result);
3338
3339   return result;
3340
3341   /* ERRORS */
3342 activate_failed:
3343   {
3344     GST_DEBUG_OBJECT (parse, "activate failed");
3345     return FALSE;
3346   }
3347 }
3348
3349 /**
3350  * gst_base_parse_set_duration:
3351  * @parse: #GstBaseParse.
3352  * @fmt: #GstFormat.
3353  * @duration: duration value.
3354  * @interval: how often to update the duration estimate based on bitrate, or 0.
3355  *
3356  * Sets the duration of the currently playing media. Subclass can use this
3357  * when it is able to determine duration and/or notices a change in the media
3358  * duration.  Alternatively, if @interval is non-zero (default), then stream
3359  * duration is determined based on estimated bitrate, and updated every @interval
3360  * frames.
3361  */
3362 void
3363 gst_base_parse_set_duration (GstBaseParse * parse,
3364     GstFormat fmt, gint64 duration, gint interval)
3365 {
3366   g_return_if_fail (parse != NULL);
3367
3368   if (parse->priv->upstream_has_duration) {
3369     GST_DEBUG_OBJECT (parse, "using upstream duration; discarding update");
3370     goto exit;
3371   }
3372
3373   if (duration != parse->priv->duration) {
3374     GstMessage *m;
3375
3376     m = gst_message_new_duration_changed (GST_OBJECT (parse));
3377     gst_element_post_message (GST_ELEMENT (parse), m);
3378
3379     /* TODO: what about duration tag? */
3380   }
3381   parse->priv->duration = duration;
3382   parse->priv->duration_fmt = fmt;
3383   GST_DEBUG_OBJECT (parse, "set duration: %" G_GINT64_FORMAT, duration);
3384   if (fmt == GST_FORMAT_TIME && GST_CLOCK_TIME_IS_VALID (duration)) {
3385     if (interval != 0) {
3386       GST_DEBUG_OBJECT (parse, "valid duration provided, disabling estimate");
3387       interval = 0;
3388     }
3389   }
3390   GST_DEBUG_OBJECT (parse, "set update interval: %d", interval);
3391   parse->priv->update_interval = interval;
3392 exit:
3393   return;
3394 }
3395
3396 /**
3397  * gst_base_parse_set_average_bitrate:
3398  * @parse: #GstBaseParse.
3399  * @bitrate: average bitrate in bits/second
3400  *
3401  * Optionally sets the average bitrate detected in media (if non-zero),
3402  * e.g. based on metadata, as it will be posted to the application.
3403  *
3404  * By default, announced average bitrate is estimated. The average bitrate
3405  * is used to estimate the total duration of the stream and to estimate
3406  * a seek position, if there's no index and the format is syncable
3407  * (see gst_base_parse_set_syncable()).
3408  */
3409 void
3410 gst_base_parse_set_average_bitrate (GstBaseParse * parse, guint bitrate)
3411 {
3412   parse->priv->bitrate = bitrate;
3413   GST_DEBUG_OBJECT (parse, "bitrate %u", bitrate);
3414 }
3415
3416 /**
3417  * gst_base_parse_set_min_frame_size:
3418  * @parse: #GstBaseParse.
3419  * @min_size: Minimum size of the data that this base class should give to
3420  *            subclass.
3421  *
3422  * Subclass can use this function to tell the base class that it needs to
3423  * give at least #min_size buffers.
3424  */
3425 void
3426 gst_base_parse_set_min_frame_size (GstBaseParse * parse, guint min_size)
3427 {
3428   g_return_if_fail (parse != NULL);
3429
3430   parse->priv->min_frame_size = min_size;
3431   GST_LOG_OBJECT (parse, "set frame_min_size: %d", min_size);
3432 }
3433
3434 /**
3435  * gst_base_parse_set_frame_rate:
3436  * @parse: the #GstBaseParse to set
3437  * @fps_num: frames per second (numerator).
3438  * @fps_den: frames per second (denominator).
3439  * @lead_in: frames needed before a segment for subsequent decode
3440  * @lead_out: frames needed after a segment
3441  *
3442  * If frames per second is configured, parser can take care of buffer duration
3443  * and timestamping.  When performing segment clipping, or seeking to a specific
3444  * location, a corresponding decoder might need an initial @lead_in and a
3445  * following @lead_out number of frames to ensure the desired segment is
3446  * entirely filled upon decoding.
3447  */
3448 void
3449 gst_base_parse_set_frame_rate (GstBaseParse * parse, guint fps_num,
3450     guint fps_den, guint lead_in, guint lead_out)
3451 {
3452   g_return_if_fail (parse != NULL);
3453
3454   parse->priv->fps_num = fps_num;
3455   parse->priv->fps_den = fps_den;
3456   if (!fps_num || !fps_den) {
3457     GST_DEBUG_OBJECT (parse, "invalid fps (%d/%d), ignoring parameters",
3458         fps_num, fps_den);
3459     fps_num = fps_den = 0;
3460     parse->priv->frame_duration = GST_CLOCK_TIME_NONE;
3461     parse->priv->lead_in = parse->priv->lead_out = 0;
3462     parse->priv->lead_in_ts = parse->priv->lead_out_ts = 0;
3463   } else {
3464     parse->priv->frame_duration =
3465         gst_util_uint64_scale (GST_SECOND, fps_den, fps_num);
3466     parse->priv->lead_in = lead_in;
3467     parse->priv->lead_out = lead_out;
3468     parse->priv->lead_in_ts =
3469         gst_util_uint64_scale (GST_SECOND, fps_den * lead_in, fps_num);
3470     parse->priv->lead_out_ts =
3471         gst_util_uint64_scale (GST_SECOND, fps_den * lead_out, fps_num);
3472     /* aim for about 1.5s to estimate duration */
3473     if (parse->priv->update_interval < 0) {
3474       parse->priv->update_interval = fps_num * 3 / (fps_den * 2);
3475       GST_LOG_OBJECT (parse, "estimated update interval to %d frames",
3476           parse->priv->update_interval);
3477     }
3478   }
3479   GST_LOG_OBJECT (parse, "set fps: %d/%d => duration: %" G_GINT64_FORMAT " ms",
3480       fps_num, fps_den, parse->priv->frame_duration / GST_MSECOND);
3481   GST_LOG_OBJECT (parse, "set lead in: %d frames = %" G_GUINT64_FORMAT " ms, "
3482       "lead out: %d frames = %" G_GUINT64_FORMAT " ms",
3483       lead_in, parse->priv->lead_in_ts / GST_MSECOND,
3484       lead_out, parse->priv->lead_out_ts / GST_MSECOND);
3485 }
3486
3487 /**
3488  * gst_base_parse_set_has_timing_info:
3489  * @parse: a #GstBaseParse
3490  * @has_timing: whether frames carry timing information
3491  *
3492  * Set if frames carry timing information which the subclass can (generally)
3493  * parse and provide.  In particular, intrinsic (rather than estimated) time
3494  * can be obtained following a seek.
3495  */
3496 void
3497 gst_base_parse_set_has_timing_info (GstBaseParse * parse, gboolean has_timing)
3498 {
3499   parse->priv->has_timing_info = has_timing;
3500   GST_INFO_OBJECT (parse, "has_timing: %s", (has_timing) ? "yes" : "no");
3501 }
3502
3503 /**
3504  * gst_base_parse_set_syncable:
3505  * @parse: a #GstBaseParse
3506  * @syncable: set if frame starts can be identified
3507  *
3508  * Set if frame starts can be identified. This is set by default and
3509  * determines whether seeking based on bitrate averages
3510  * is possible for a format/stream.
3511  */
3512 void
3513 gst_base_parse_set_syncable (GstBaseParse * parse, gboolean syncable)
3514 {
3515   parse->priv->syncable = syncable;
3516   GST_INFO_OBJECT (parse, "syncable: %s", (syncable) ? "yes" : "no");
3517 }
3518
3519 /**
3520  * gst_base_parse_set_passthrough:
3521  * @parse: a #GstBaseParse
3522  * @passthrough: %TRUE if parser should run in passthrough mode
3523  *
3524  * Set if the nature of the format or configuration does not allow (much)
3525  * parsing, and the parser should operate in passthrough mode (which only
3526  * applies when operating in push mode). That is, incoming buffers are
3527  * pushed through unmodified, i.e. no @check_valid_frame or @parse_frame
3528  * callbacks will be invoked, but @pre_push_frame will still be invoked,
3529  * so subclass can perform as much or as little is appropriate for
3530  * passthrough semantics in @pre_push_frame.
3531  */
3532 void
3533 gst_base_parse_set_passthrough (GstBaseParse * parse, gboolean passthrough)
3534 {
3535   parse->priv->passthrough = passthrough;
3536   GST_INFO_OBJECT (parse, "passthrough: %s", (passthrough) ? "yes" : "no");
3537 }
3538
3539 /**
3540  * gst_base_parse_set_pts_interpolation:
3541  * @parse: a #GstBaseParse
3542  * @pts_interpolate: %TRUE if parser should interpolate PTS timestamps
3543  *
3544  * By default, the base class will guess PTS timestamps using a simple
3545  * interpolation (previous timestamp + duration), which is incorrect for
3546  * data streams with reordering, where PTS can go backward. Sub-classes
3547  * implementing such formats should disable PTS interpolation.
3548  */
3549 void
3550 gst_base_parse_set_pts_interpolation (GstBaseParse * parse,
3551     gboolean pts_interpolate)
3552 {
3553   parse->priv->pts_interpolate = pts_interpolate;
3554   GST_INFO_OBJECT (parse, "PTS interpolation: %s",
3555       (pts_interpolate) ? "yes" : "no");
3556 }
3557
3558 /**
3559  * gst_base_parse_set_infer_ts:
3560  * @parse: a #GstBaseParse
3561  * @infer_ts: %TRUE if parser should infer DTS/PTS from each other
3562  *
3563  * By default, the base class might try to infer PTS from DTS and vice
3564  * versa.  While this is generally correct for audio data, it may not
3565  * be otherwise. Sub-classes implementing such formats should disable
3566  * timestamp inferring.
3567  */
3568 void
3569 gst_base_parse_set_infer_ts (GstBaseParse * parse, gboolean infer_ts)
3570 {
3571   parse->priv->infer_ts = infer_ts;
3572   GST_INFO_OBJECT (parse, "TS inferring: %s", (infer_ts) ? "yes" : "no");
3573 }
3574
3575 /**
3576  * gst_base_parse_set_latency:
3577  * @parse: a #GstBaseParse
3578  * @min_latency: minimum parse latency
3579  * @max_latency: maximum parse latency
3580  *
3581  * Sets the minimum and maximum (which may likely be equal) latency introduced
3582  * by the parsing process.  If there is such a latency, which depends on the
3583  * particular parsing of the format, it typically corresponds to 1 frame duration.
3584  */
3585 void
3586 gst_base_parse_set_latency (GstBaseParse * parse, GstClockTime min_latency,
3587     GstClockTime max_latency)
3588 {
3589   GST_OBJECT_LOCK (parse);
3590   parse->priv->min_latency = min_latency;
3591   parse->priv->max_latency = max_latency;
3592   GST_OBJECT_UNLOCK (parse);
3593   GST_INFO_OBJECT (parse, "min/max latency %" GST_TIME_FORMAT ", %"
3594       GST_TIME_FORMAT, GST_TIME_ARGS (min_latency),
3595       GST_TIME_ARGS (max_latency));
3596 }
3597
3598 static gboolean
3599 gst_base_parse_get_duration (GstBaseParse * parse, GstFormat format,
3600     GstClockTime * duration)
3601 {
3602   gboolean res = FALSE;
3603
3604   g_return_val_if_fail (duration != NULL, FALSE);
3605
3606   *duration = GST_CLOCK_TIME_NONE;
3607   if (parse->priv->duration != -1 && format == parse->priv->duration_fmt) {
3608     GST_LOG_OBJECT (parse, "using provided duration");
3609     *duration = parse->priv->duration;
3610     res = TRUE;
3611   } else if (parse->priv->duration != -1) {
3612     GST_LOG_OBJECT (parse, "converting provided duration");
3613     res = gst_base_parse_convert (parse, parse->priv->duration_fmt,
3614         parse->priv->duration, format, (gint64 *) duration);
3615   } else if (format == GST_FORMAT_TIME && parse->priv->estimated_duration != -1) {
3616     GST_LOG_OBJECT (parse, "using estimated duration");
3617     *duration = parse->priv->estimated_duration;
3618     res = TRUE;
3619   } else {
3620     GST_LOG_OBJECT (parse, "cannot estimate duration");
3621   }
3622
3623   GST_LOG_OBJECT (parse, "res: %d, duration %" GST_TIME_FORMAT, res,
3624       GST_TIME_ARGS (*duration));
3625   return res;
3626 }
3627
3628 static gboolean
3629 gst_base_parse_src_query_default (GstBaseParse * parse, GstQuery * query)
3630 {
3631   gboolean res = FALSE;
3632   GstPad *pad;
3633
3634   pad = GST_BASE_PARSE_SRC_PAD (parse);
3635
3636   switch (GST_QUERY_TYPE (query)) {
3637     case GST_QUERY_POSITION:
3638     {
3639       gint64 dest_value;
3640       GstFormat format;
3641
3642       GST_DEBUG_OBJECT (parse, "position query");
3643       gst_query_parse_position (query, &format, NULL);
3644
3645       /* try upstream first */
3646       res = gst_pad_query_default (pad, GST_OBJECT_CAST (parse), query);
3647       if (!res) {
3648         /* Fall back on interpreting segment */
3649         GST_OBJECT_LOCK (parse);
3650         if (format == GST_FORMAT_BYTES) {
3651           dest_value = parse->priv->offset;
3652           res = TRUE;
3653         } else if (format == parse->segment.format &&
3654             GST_CLOCK_TIME_IS_VALID (parse->segment.position)) {
3655           dest_value = gst_segment_to_stream_time (&parse->segment,
3656               parse->segment.format, parse->segment.position);
3657           res = TRUE;
3658         }
3659         GST_OBJECT_UNLOCK (parse);
3660         if (!res) {
3661           /* no precise result, upstream no idea either, then best estimate */
3662           /* priv->offset is updated in both PUSH/PULL modes */
3663           res = gst_base_parse_convert (parse,
3664               GST_FORMAT_BYTES, parse->priv->offset, format, &dest_value);
3665         }
3666         if (res)
3667           gst_query_set_position (query, format, dest_value);
3668       }
3669       break;
3670     }
3671     case GST_QUERY_DURATION:
3672     {
3673       GstFormat format;
3674       GstClockTime duration;
3675
3676       GST_DEBUG_OBJECT (parse, "duration query");
3677       gst_query_parse_duration (query, &format, NULL);
3678
3679       /* consult upstream */
3680       res = gst_pad_query_default (pad, GST_OBJECT_CAST (parse), query);
3681
3682       /* otherwise best estimate from us */
3683       if (!res) {
3684         res = gst_base_parse_get_duration (parse, format, &duration);
3685         if (res)
3686           gst_query_set_duration (query, format, duration);
3687       }
3688       break;
3689     }
3690     case GST_QUERY_SEEKING:
3691     {
3692       GstFormat fmt;
3693       GstClockTime duration = GST_CLOCK_TIME_NONE;
3694       gboolean seekable = FALSE;
3695
3696       GST_DEBUG_OBJECT (parse, "seeking query");
3697       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
3698
3699       /* consult upstream */
3700       res = gst_pad_query_default (pad, GST_OBJECT_CAST (parse), query);
3701
3702       /* we may be able to help if in TIME */
3703       if (fmt == GST_FORMAT_TIME && gst_base_parse_is_seekable (parse)) {
3704         gst_query_parse_seeking (query, &fmt, &seekable, NULL, NULL);
3705         /* already OK if upstream takes care */
3706         GST_LOG_OBJECT (parse, "upstream handled %d, seekable %d",
3707             res, seekable);
3708         if (!(res && seekable)) {
3709           if (!gst_base_parse_get_duration (parse, GST_FORMAT_TIME, &duration)
3710               || duration == -1) {
3711             /* seekable if we still have a chance to get duration later on */
3712             seekable =
3713                 parse->priv->upstream_seekable && parse->priv->update_interval;
3714           } else {
3715             seekable = parse->priv->upstream_seekable;
3716             GST_LOG_OBJECT (parse, "already determine upstream seekabled: %d",
3717                 seekable);
3718           }
3719           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
3720           res = TRUE;
3721         }
3722       }
3723       break;
3724     }
3725     case GST_QUERY_FORMATS:
3726       gst_query_set_formatsv (query, 3, fmtlist);
3727       res = TRUE;
3728       break;
3729     case GST_QUERY_CONVERT:
3730     {
3731       GstFormat src_format, dest_format;
3732       gint64 src_value, dest_value;
3733
3734       gst_query_parse_convert (query, &src_format, &src_value,
3735           &dest_format, &dest_value);
3736
3737       res = gst_base_parse_convert (parse, src_format, src_value,
3738           dest_format, &dest_value);
3739       if (res) {
3740         gst_query_set_convert (query, src_format, src_value,
3741             dest_format, dest_value);
3742       }
3743       break;
3744     }
3745     case GST_QUERY_LATENCY:
3746     {
3747       if ((res = gst_pad_peer_query (parse->sinkpad, query))) {
3748         gboolean live;
3749         GstClockTime min_latency, max_latency;
3750
3751         gst_query_parse_latency (query, &live, &min_latency, &max_latency);
3752         GST_DEBUG_OBJECT (parse, "Peer latency: live %d, min %"
3753             GST_TIME_FORMAT " max %" GST_TIME_FORMAT, live,
3754             GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency));
3755
3756         GST_OBJECT_LOCK (parse);
3757         /* add our latency */
3758         if (min_latency != -1)
3759           min_latency += parse->priv->min_latency;
3760         if (max_latency != -1)
3761           max_latency += parse->priv->max_latency;
3762         GST_OBJECT_UNLOCK (parse);
3763
3764         gst_query_set_latency (query, live, min_latency, max_latency);
3765       }
3766       break;
3767     }
3768     case GST_QUERY_SEGMENT:
3769     {
3770       GstFormat format;
3771       gint64 start, stop;
3772
3773       format = parse->segment.format;
3774
3775       start =
3776           gst_segment_to_stream_time (&parse->segment, format,
3777           parse->segment.start);
3778       if ((stop = parse->segment.stop) == -1)
3779         stop = parse->segment.duration;
3780       else
3781         stop = gst_segment_to_stream_time (&parse->segment, format, stop);
3782
3783       gst_query_set_segment (query, parse->segment.rate, format, start, stop);
3784       res = TRUE;
3785       break;
3786     }
3787     default:
3788       res = gst_pad_query_default (pad, GST_OBJECT_CAST (parse), query);
3789       break;
3790   }
3791   return res;
3792 }
3793
3794 /* scans for a cluster start from @pos,
3795  * return GST_FLOW_OK and frame position/time in @pos/@time if found */
3796 static GstFlowReturn
3797 gst_base_parse_find_frame (GstBaseParse * parse, gint64 * pos,
3798     GstClockTime * time, GstClockTime * duration)
3799 {
3800   GstBaseParseClass *klass;
3801   gint64 orig_offset;
3802   gboolean orig_drain, orig_discont;
3803   GstFlowReturn ret = GST_FLOW_OK;
3804   GstBuffer *buf = NULL;
3805   GstBaseParseFrame *sframe = NULL;
3806
3807   g_return_val_if_fail (pos != NULL, GST_FLOW_ERROR);
3808   g_return_val_if_fail (time != NULL, GST_FLOW_ERROR);
3809   g_return_val_if_fail (duration != NULL, GST_FLOW_ERROR);
3810
3811   klass = GST_BASE_PARSE_GET_CLASS (parse);
3812
3813   *time = GST_CLOCK_TIME_NONE;
3814   *duration = GST_CLOCK_TIME_NONE;
3815
3816   /* save state */
3817   orig_offset = parse->priv->offset;
3818   orig_discont = parse->priv->discont;
3819   orig_drain = parse->priv->drain;
3820
3821   GST_DEBUG_OBJECT (parse, "scanning for frame starting at %" G_GINT64_FORMAT
3822       " (%#" G_GINT64_MODIFIER "x)", *pos, *pos);
3823
3824   /* jump elsewhere and locate next frame */
3825   parse->priv->offset = *pos;
3826   /* mark as scanning so frames don't get processed all the way */
3827   parse->priv->scanning = TRUE;
3828   ret = gst_base_parse_scan_frame (parse, klass);
3829   parse->priv->scanning = FALSE;
3830   /* retrieve frame found during scan */
3831   sframe = parse->priv->scanned_frame;
3832   parse->priv->scanned_frame = NULL;
3833
3834   if (ret != GST_FLOW_OK || !sframe)
3835     goto done;
3836
3837   /* get offset first, subclass parsing might dump other stuff in there */
3838   *pos = sframe->offset;
3839   buf = sframe->buffer;
3840   g_assert (buf);
3841
3842   /* but it should provide proper time */
3843   *time = GST_BUFFER_TIMESTAMP (buf);
3844   *duration = GST_BUFFER_DURATION (buf);
3845
3846   GST_LOG_OBJECT (parse,
3847       "frame with time %" GST_TIME_FORMAT " at offset %" G_GINT64_FORMAT,
3848       GST_TIME_ARGS (*time), *pos);
3849
3850 done:
3851   if (sframe)
3852     gst_base_parse_frame_free (sframe);
3853
3854   /* restore state */
3855   parse->priv->offset = orig_offset;
3856   parse->priv->discont = orig_discont;
3857   parse->priv->drain = orig_drain;
3858
3859   return ret;
3860 }
3861
3862 /* bisect and scan through file for frame starting before @time,
3863  * returns OK and @time/@offset if found, NONE and/or error otherwise
3864  * If @time == G_MAXINT64, scan for duration ( == last frame) */
3865 static GstFlowReturn
3866 gst_base_parse_locate_time (GstBaseParse * parse, GstClockTime * _time,
3867     gint64 * _offset)
3868 {
3869   GstFlowReturn ret = GST_FLOW_OK;
3870   gint64 lpos, hpos, newpos;
3871   GstClockTime time, ltime, htime, newtime, dur;
3872   gboolean cont = TRUE;
3873   const GstClockTime tolerance = TARGET_DIFFERENCE;
3874   const guint chunk = 4 * 1024;
3875
3876   g_return_val_if_fail (_time != NULL, GST_FLOW_ERROR);
3877   g_return_val_if_fail (_offset != NULL, GST_FLOW_ERROR);
3878
3879   GST_DEBUG_OBJECT (parse, "Bisecting for time %" GST_TIME_FORMAT,
3880       GST_TIME_ARGS (*_time));
3881
3882   /* TODO also make keyframe aware if useful some day */
3883
3884   time = *_time;
3885
3886   /* basic cases */
3887   if (time == 0) {
3888     *_offset = 0;
3889     return GST_FLOW_OK;
3890   }
3891
3892   if (time == -1) {
3893     *_offset = -1;
3894     return GST_FLOW_OK;
3895   }
3896
3897   /* do not know at first */
3898   *_offset = -1;
3899   *_time = GST_CLOCK_TIME_NONE;
3900
3901   /* need initial positions; start and end */
3902   lpos = parse->priv->first_frame_offset;
3903   ltime = parse->priv->first_frame_pts;
3904   /* try other one if no luck */
3905   if (!GST_CLOCK_TIME_IS_VALID (ltime))
3906     ltime = parse->priv->first_frame_dts;
3907   if (!gst_base_parse_get_duration (parse, GST_FORMAT_TIME, &htime)) {
3908     GST_DEBUG_OBJECT (parse, "Unknown time duration, cannot bisect");
3909     return GST_FLOW_ERROR;
3910   }
3911   hpos = parse->priv->upstream_size;
3912
3913   GST_DEBUG_OBJECT (parse,
3914       "Bisection initial bounds: bytes %" G_GINT64_FORMAT " %" G_GINT64_FORMAT
3915       ", times %" GST_TIME_FORMAT " %" GST_TIME_FORMAT, lpos, hpos,
3916       GST_TIME_ARGS (ltime), GST_TIME_ARGS (htime));
3917
3918   /* check preconditions are satisfied;
3919    * start and end are needed, except for special case where we scan for
3920    * last frame to determine duration */
3921   if (parse->priv->pad_mode != GST_PAD_MODE_PULL || !hpos ||
3922       !GST_CLOCK_TIME_IS_VALID (ltime) ||
3923       (!GST_CLOCK_TIME_IS_VALID (htime) && time != G_MAXINT64)) {
3924     return GST_FLOW_OK;
3925   }
3926
3927   /* shortcut cases */
3928   if (time < ltime) {
3929     goto exit;
3930   } else if (time < ltime + tolerance) {
3931     *_offset = lpos;
3932     *_time = ltime;
3933     goto exit;
3934   } else if (time >= htime) {
3935     *_offset = hpos;
3936     *_time = htime;
3937     goto exit;
3938   }
3939
3940   while (htime > ltime && cont) {
3941     GST_LOG_OBJECT (parse,
3942         "lpos: %" G_GUINT64_FORMAT ", ltime: %" GST_TIME_FORMAT, lpos,
3943         GST_TIME_ARGS (ltime));
3944     GST_LOG_OBJECT (parse,
3945         "hpos: %" G_GUINT64_FORMAT ", htime: %" GST_TIME_FORMAT, hpos,
3946         GST_TIME_ARGS (htime));
3947     if (G_UNLIKELY (time == G_MAXINT64)) {
3948       newpos = hpos;
3949     } else if (G_LIKELY (hpos > lpos)) {
3950       newpos =
3951           gst_util_uint64_scale (hpos - lpos, time - ltime, htime - ltime) +
3952           lpos - chunk;
3953     } else {
3954       /* should mean lpos == hpos, since lpos <= hpos is invariant */
3955       newpos = lpos;
3956       /* we check this case once, but not forever, so break loop */
3957       cont = FALSE;
3958     }
3959
3960     /* ensure */
3961     newpos = CLAMP (newpos, lpos, hpos);
3962     GST_LOG_OBJECT (parse,
3963         "estimated _offset for %" GST_TIME_FORMAT ": %" G_GINT64_FORMAT,
3964         GST_TIME_ARGS (time), newpos);
3965
3966     ret = gst_base_parse_find_frame (parse, &newpos, &newtime, &dur);
3967     if (ret == GST_FLOW_EOS) {
3968       /* heuristic HACK */
3969       hpos = MAX (lpos, hpos - chunk);
3970       continue;
3971     } else if (ret != GST_FLOW_OK) {
3972       goto exit;
3973     }
3974
3975     if (newtime == -1 || newpos == -1) {
3976       GST_DEBUG_OBJECT (parse, "subclass did not provide metadata; aborting");
3977       break;
3978     }
3979
3980     if (G_UNLIKELY (time == G_MAXINT64)) {
3981       *_offset = newpos;
3982       *_time = newtime;
3983       if (GST_CLOCK_TIME_IS_VALID (dur))
3984         *_time += dur;
3985       break;
3986     } else if (newtime > time) {
3987       /* overshoot */
3988       hpos = (newpos >= hpos) ? MAX (lpos, hpos - chunk) : MAX (lpos, newpos);
3989       htime = newtime;
3990     } else if (newtime + tolerance > time) {
3991       /* close enough undershoot */
3992       *_offset = newpos;
3993       *_time = newtime;
3994       break;
3995     } else if (newtime < ltime) {
3996       /* so a position beyond lpos resulted in earlier time than ltime ... */
3997       GST_DEBUG_OBJECT (parse, "non-ascending time; aborting");
3998       break;
3999     } else {
4000       /* undershoot too far */
4001       newpos += newpos == lpos ? chunk : 0;
4002       lpos = CLAMP (newpos, lpos, hpos);
4003       ltime = newtime;
4004     }
4005   }
4006
4007 exit:
4008   GST_LOG_OBJECT (parse, "return offset %" G_GINT64_FORMAT ", time %"
4009       GST_TIME_FORMAT, *_offset, GST_TIME_ARGS (*_time));
4010   return ret;
4011 }
4012
4013 static gint64
4014 gst_base_parse_find_offset (GstBaseParse * parse, GstClockTime time,
4015     gboolean before, GstClockTime * _ts)
4016 {
4017   gint64 bytes = 0, ts = 0;
4018   GstIndexEntry *entry = NULL;
4019
4020   if (time == GST_CLOCK_TIME_NONE) {
4021     ts = time;
4022     bytes = -1;
4023     goto exit;
4024   }
4025
4026   GST_BASE_PARSE_INDEX_LOCK (parse);
4027   if (parse->priv->index) {
4028     /* Let's check if we have an index entry for that time */
4029     entry = gst_index_get_assoc_entry (parse->priv->index,
4030         parse->priv->index_id,
4031         before ? GST_INDEX_LOOKUP_BEFORE : GST_INDEX_LOOKUP_AFTER,
4032         GST_INDEX_ASSOCIATION_FLAG_KEY_UNIT, GST_FORMAT_TIME, time);
4033   }
4034
4035   if (entry) {
4036     gst_index_entry_assoc_map (entry, GST_FORMAT_BYTES, &bytes);
4037     gst_index_entry_assoc_map (entry, GST_FORMAT_TIME, &ts);
4038
4039     GST_DEBUG_OBJECT (parse, "found index entry for %" GST_TIME_FORMAT
4040         " at %" GST_TIME_FORMAT ", offset %" G_GINT64_FORMAT,
4041         GST_TIME_ARGS (time), GST_TIME_ARGS (ts), bytes);
4042   } else {
4043     GST_DEBUG_OBJECT (parse, "no index entry found for %" GST_TIME_FORMAT,
4044         GST_TIME_ARGS (time));
4045     if (!before) {
4046       bytes = -1;
4047       ts = GST_CLOCK_TIME_NONE;
4048     }
4049   }
4050   GST_BASE_PARSE_INDEX_UNLOCK (parse);
4051
4052 exit:
4053   if (_ts)
4054     *_ts = ts;
4055
4056   return bytes;
4057 }
4058
4059 /* returns TRUE if seek succeeded */
4060 static gboolean
4061 gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event)
4062 {
4063   gdouble rate;
4064   GstFormat format;
4065   GstSeekFlags flags;
4066   GstSeekType start_type = GST_SEEK_TYPE_NONE, stop_type;
4067   gboolean flush, update, res = TRUE, accurate;
4068   gint64 start, stop, seekpos, seekstop;
4069   GstSegment seeksegment = { 0, };
4070   GstClockTime start_ts;
4071   guint32 seqnum;
4072   GstEvent *segment_event;
4073
4074   /* try upstream first, unless we're driving the streaming thread ourselves */
4075   if (parse->priv->pad_mode != GST_PAD_MODE_PULL) {
4076     res = gst_pad_push_event (parse->sinkpad, gst_event_ref (event));
4077     if (res)
4078       goto done;
4079   }
4080
4081   gst_event_parse_seek (event, &rate, &format, &flags,
4082       &start_type, &start, &stop_type, &stop);
4083   seqnum = gst_event_get_seqnum (event);
4084
4085   GST_DEBUG_OBJECT (parse, "seek to format %s, rate %f, "
4086       "start type %d at %" GST_TIME_FORMAT ", end type %d at %"
4087       GST_TIME_FORMAT, gst_format_get_name (format), rate,
4088       start_type, GST_TIME_ARGS (start), stop_type, GST_TIME_ARGS (stop));
4089
4090   /* we can only handle TIME, so check if subclass can convert
4091    * to TIME format if it's some other format (such as DEFAULT) */
4092   if (format != GST_FORMAT_TIME) {
4093     if (!gst_base_parse_convert (parse, format, start, GST_FORMAT_TIME, &start)
4094         || !gst_base_parse_convert (parse, format, stop, GST_FORMAT_TIME,
4095             &stop))
4096       goto no_convert_to_time;
4097
4098     GST_INFO_OBJECT (parse, "converted %s format to start time "
4099         "%" GST_TIME_FORMAT " and stop time %" GST_TIME_FORMAT,
4100         gst_format_get_name (format), GST_TIME_ARGS (start),
4101         GST_TIME_ARGS (stop));
4102
4103     format = GST_FORMAT_TIME;
4104   }
4105
4106   /* no negative rates in push mode (unless upstream takes care of that, but
4107    * we've already tried upstream and it didn't handle the seek request) */
4108   if (rate < 0.0 && parse->priv->pad_mode == GST_PAD_MODE_PUSH)
4109     goto negative_rate;
4110
4111   if (rate < 0.0 && parse->priv->pad_mode == GST_PAD_MODE_PULL)
4112     goto negative_rate_pull_mode;
4113
4114   if (start_type != GST_SEEK_TYPE_SET ||
4115       (stop_type != GST_SEEK_TYPE_SET && stop_type != GST_SEEK_TYPE_NONE))
4116     goto wrong_type;
4117
4118   /* get flush flag */
4119   flush = flags & GST_SEEK_FLAG_FLUSH;
4120
4121   /* copy segment, we need this because we still need the old
4122    * segment when we close the current segment. */
4123   gst_segment_copy_into (&parse->segment, &seeksegment);
4124
4125   GST_DEBUG_OBJECT (parse, "configuring seek");
4126   gst_segment_do_seek (&seeksegment, rate, format, flags,
4127       start_type, start, stop_type, stop, &update);
4128
4129   /* accurate seeking implies seek tables are used to obtain position,
4130    * and the requested segment is maintained exactly, not adjusted any way */
4131   accurate = flags & GST_SEEK_FLAG_ACCURATE;
4132
4133   /* maybe we can be accurate for (almost) free */
4134   gst_base_parse_find_offset (parse, seeksegment.position, TRUE, &start_ts);
4135   if (seeksegment.position <= start_ts + TARGET_DIFFERENCE) {
4136     GST_DEBUG_OBJECT (parse, "accurate seek possible");
4137     accurate = TRUE;
4138   }
4139   if (accurate) {
4140     GstClockTime startpos = seeksegment.position;
4141
4142     /* accurate requested, so ... seek a bit before target */
4143     if (startpos < parse->priv->lead_in_ts)
4144       startpos = 0;
4145     else
4146       startpos -= parse->priv->lead_in_ts;
4147     seekpos = gst_base_parse_find_offset (parse, startpos, TRUE, &start_ts);
4148     seekstop = gst_base_parse_find_offset (parse, seeksegment.stop, FALSE,
4149         NULL);
4150   } else {
4151     start_ts = seeksegment.position;
4152     if (!gst_base_parse_convert (parse, format, seeksegment.position,
4153             GST_FORMAT_BYTES, &seekpos))
4154       goto convert_failed;
4155     if (!gst_base_parse_convert (parse, format, seeksegment.stop,
4156             GST_FORMAT_BYTES, &seekstop))
4157       goto convert_failed;
4158   }
4159
4160   GST_DEBUG_OBJECT (parse,
4161       "seek position %" G_GINT64_FORMAT " in bytes: %" G_GINT64_FORMAT,
4162       start_ts, seekpos);
4163   GST_DEBUG_OBJECT (parse,
4164       "seek stop %" G_GINT64_FORMAT " in bytes: %" G_GINT64_FORMAT,
4165       seeksegment.stop, seekstop);
4166
4167   if (parse->priv->pad_mode == GST_PAD_MODE_PULL) {
4168     gint64 last_stop;
4169
4170     GST_DEBUG_OBJECT (parse, "seek in PULL mode");
4171
4172     if (flush) {
4173       if (parse->srcpad) {
4174         GstEvent *fevent = gst_event_new_flush_start ();
4175         GST_DEBUG_OBJECT (parse, "sending flush start");
4176
4177         gst_event_set_seqnum (fevent, seqnum);
4178
4179         gst_pad_push_event (parse->srcpad, gst_event_ref (fevent));
4180         /* unlock upstream pull_range */
4181         gst_pad_push_event (parse->sinkpad, fevent);
4182       }
4183     } else {
4184       gst_pad_pause_task (parse->sinkpad);
4185     }
4186
4187     /* we should now be able to grab the streaming thread because we stopped it
4188      * with the above flush/pause code */
4189     GST_PAD_STREAM_LOCK (parse->sinkpad);
4190
4191     /* save current position */
4192     last_stop = parse->segment.position;
4193     GST_DEBUG_OBJECT (parse, "stopped streaming at %" G_GINT64_FORMAT,
4194         last_stop);
4195
4196     /* now commit to new position */
4197
4198     /* prepare for streaming again */
4199     if (flush) {
4200       GstEvent *fevent = gst_event_new_flush_stop (TRUE);
4201       GST_DEBUG_OBJECT (parse, "sending flush stop");
4202       gst_event_set_seqnum (fevent, seqnum);
4203       gst_pad_push_event (parse->srcpad, gst_event_ref (fevent));
4204       gst_pad_push_event (parse->sinkpad, fevent);
4205       gst_base_parse_clear_queues (parse);
4206     } else {
4207       /* keep track of our position */
4208       seeksegment.base = gst_segment_to_running_time (&seeksegment,
4209           seeksegment.format, parse->segment.position);
4210     }
4211
4212     memcpy (&parse->segment, &seeksegment, sizeof (GstSegment));
4213
4214     /* store the newsegment event so it can be sent from the streaming thread. */
4215     /* This will be sent later in _loop() */
4216     parse->priv->pending_segment = TRUE;
4217     segment_event = gst_event_new_segment (&parse->segment);
4218     gst_event_set_seqnum (segment_event, seqnum);
4219     parse->priv->pending_events =
4220         g_list_prepend (parse->priv->pending_events, segment_event);
4221
4222     GST_DEBUG_OBJECT (parse, "Created newseg format %d, "
4223         "start = %" GST_TIME_FORMAT ", stop = %" GST_TIME_FORMAT
4224         ", time = %" GST_TIME_FORMAT, format,
4225         GST_TIME_ARGS (parse->segment.start),
4226         GST_TIME_ARGS (parse->segment.stop),
4227         GST_TIME_ARGS (parse->segment.time));
4228
4229     /* one last chance in pull mode to stay accurate;
4230      * maybe scan and subclass can find where to go */
4231     if (!accurate) {
4232       gint64 scanpos;
4233       GstClockTime ts = seeksegment.position;
4234
4235       gst_base_parse_locate_time (parse, &ts, &scanpos);
4236       if (scanpos >= 0) {
4237         accurate = TRUE;
4238         seekpos = scanpos;
4239         /* running collected index now consists of several intervals,
4240          * so optimized check no longer possible */
4241         parse->priv->index_last_valid = FALSE;
4242         parse->priv->index_last_offset = 0;
4243         parse->priv->index_last_ts = 0;
4244       }
4245     }
4246
4247     /* mark discont if we are going to stream from another position. */
4248     if (seekpos != parse->priv->offset) {
4249       GST_DEBUG_OBJECT (parse,
4250           "mark DISCONT, we did a seek to another position");
4251       parse->priv->offset = seekpos;
4252       parse->priv->last_offset = seekpos;
4253       parse->priv->seen_keyframe = FALSE;
4254       parse->priv->discont = TRUE;
4255       parse->priv->next_dts = start_ts;
4256       parse->priv->next_pts = GST_CLOCK_TIME_NONE;
4257       parse->priv->last_dts = GST_CLOCK_TIME_NONE;
4258       parse->priv->last_pts = GST_CLOCK_TIME_NONE;
4259       parse->priv->sync_offset = seekpos;
4260       parse->priv->exact_position = accurate;
4261     }
4262
4263     /* Start streaming thread if paused */
4264     gst_pad_start_task (parse->sinkpad,
4265         (GstTaskFunction) gst_base_parse_loop, parse->sinkpad, NULL);
4266
4267     GST_PAD_STREAM_UNLOCK (parse->sinkpad);
4268
4269     /* handled seek */
4270     res = TRUE;
4271   } else {
4272     GstEvent *new_event;
4273     GstBaseParseSeek *seek;
4274     GstSeekFlags flags = (flush ? GST_SEEK_FLAG_FLUSH : GST_SEEK_FLAG_NONE);
4275
4276     /* The only thing we need to do in PUSH-mode is to send the
4277        seek event (in bytes) to upstream. Segment / flush handling happens
4278        in corresponding src event handlers */
4279     GST_DEBUG_OBJECT (parse, "seek in PUSH mode");
4280     if (seekstop >= 0 && seekstop <= seekpos)
4281       seekstop = seekpos;
4282     new_event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags,
4283         GST_SEEK_TYPE_SET, seekpos, stop_type, seekstop);
4284     gst_event_set_seqnum (new_event, seqnum);
4285
4286     /* store segment info so its precise details can be reconstructed when
4287      * receiving newsegment;
4288      * this matters for all details when accurate seeking,
4289      * is most useful to preserve NONE stop time otherwise */
4290     seek = g_new0 (GstBaseParseSeek, 1);
4291     seek->segment = seeksegment;
4292     seek->accurate = accurate;
4293     seek->offset = seekpos;
4294     seek->start_ts = start_ts;
4295     GST_OBJECT_LOCK (parse);
4296     /* less optimal, but preserves order */
4297     parse->priv->pending_seeks =
4298         g_slist_append (parse->priv->pending_seeks, seek);
4299     GST_OBJECT_UNLOCK (parse);
4300
4301     res = gst_pad_push_event (parse->sinkpad, new_event);
4302
4303     if (!res) {
4304       GST_OBJECT_LOCK (parse);
4305       parse->priv->pending_seeks =
4306           g_slist_remove (parse->priv->pending_seeks, seek);
4307       GST_OBJECT_UNLOCK (parse);
4308       g_free (seek);
4309     }
4310   }
4311
4312 done:
4313   gst_event_unref (event);
4314   return res;
4315
4316   /* ERRORS */
4317 negative_rate_pull_mode:
4318   {
4319     GST_FIXME_OBJECT (parse, "negative playback in pull mode needs fixing");
4320     res = FALSE;
4321     goto done;
4322   }
4323 negative_rate:
4324   {
4325     GST_DEBUG_OBJECT (parse, "negative playback rates delegated upstream.");
4326     res = FALSE;
4327     goto done;
4328   }
4329 wrong_type:
4330   {
4331     GST_DEBUG_OBJECT (parse, "unsupported seek type.");
4332     res = FALSE;
4333     goto done;
4334   }
4335 no_convert_to_time:
4336   {
4337     GST_DEBUG_OBJECT (parse, "seek in %s format was requested, but subclass "
4338         "couldn't convert that into TIME format", gst_format_get_name (format));
4339     res = FALSE;
4340     goto done;
4341   }
4342 convert_failed:
4343   {
4344     GST_DEBUG_OBJECT (parse, "conversion TIME to BYTES failed.");
4345     res = FALSE;
4346     goto done;
4347   }
4348 }
4349
4350 /* Checks if bitrates are available from upstream tags so that we don't
4351  * override them later
4352  */
4353 static void
4354 gst_base_parse_handle_tag (GstBaseParse * parse, GstEvent * event)
4355 {
4356   GstTagList *taglist = NULL;
4357   guint tmp;
4358
4359   gst_event_parse_tag (event, &taglist);
4360
4361   /* We only care about stream tags here */
4362   if (gst_tag_list_get_scope (taglist) != GST_TAG_SCOPE_STREAM)
4363     return;
4364
4365   if (gst_tag_list_get_uint (taglist, GST_TAG_MINIMUM_BITRATE, &tmp)) {
4366     GST_DEBUG_OBJECT (parse, "upstream min bitrate %d", tmp);
4367     parse->priv->post_min_bitrate = FALSE;
4368   }
4369   if (gst_tag_list_get_uint (taglist, GST_TAG_BITRATE, &tmp)) {
4370     GST_DEBUG_OBJECT (parse, "upstream avg bitrate %d", tmp);
4371     parse->priv->post_avg_bitrate = FALSE;
4372   }
4373   if (gst_tag_list_get_uint (taglist, GST_TAG_MAXIMUM_BITRATE, &tmp)) {
4374     GST_DEBUG_OBJECT (parse, "upstream max bitrate %d", tmp);
4375     parse->priv->post_max_bitrate = FALSE;
4376   }
4377 }
4378
4379 #if 0
4380 static void
4381 gst_base_parse_set_index (GstElement * element, GstIndex * index)
4382 {
4383   GstBaseParse *parse = GST_BASE_PARSE (element);
4384
4385   GST_BASE_PARSE_INDEX_LOCK (parse);
4386   if (parse->priv->index)
4387     gst_object_unref (parse->priv->index);
4388   if (index) {
4389     parse->priv->index = gst_object_ref (index);
4390     gst_index_get_writer_id (index, GST_OBJECT_CAST (element),
4391         &parse->priv->index_id);
4392     parse->priv->own_index = FALSE;
4393   } else {
4394     parse->priv->index = NULL;
4395   }
4396   GST_BASE_PARSE_INDEX_UNLOCK (parse);
4397 }
4398
4399 static GstIndex *
4400 gst_base_parse_get_index (GstElement * element)
4401 {
4402   GstBaseParse *parse = GST_BASE_PARSE (element);
4403   GstIndex *result = NULL;
4404
4405   GST_BASE_PARSE_INDEX_LOCK (parse);
4406   if (parse->priv->index)
4407     result = gst_object_ref (parse->priv->index);
4408   GST_BASE_PARSE_INDEX_UNLOCK (parse);
4409
4410   return result;
4411 }
4412 #endif
4413
4414 static GstStateChangeReturn
4415 gst_base_parse_change_state (GstElement * element, GstStateChange transition)
4416 {
4417   GstBaseParse *parse;
4418   GstStateChangeReturn result;
4419
4420   parse = GST_BASE_PARSE (element);
4421
4422   switch (transition) {
4423     case GST_STATE_CHANGE_READY_TO_PAUSED:
4424       /* If this is our own index destroy it as the
4425        * old entries might be wrong for the new stream */
4426       GST_BASE_PARSE_INDEX_LOCK (parse);
4427       if (parse->priv->own_index) {
4428         gst_object_unref (parse->priv->index);
4429         parse->priv->index = NULL;
4430         parse->priv->own_index = FALSE;
4431       }
4432
4433       /* If no index was created, generate one */
4434       if (G_UNLIKELY (!parse->priv->index)) {
4435         GST_DEBUG_OBJECT (parse, "no index provided creating our own");
4436
4437         parse->priv->index = g_object_new (gst_mem_index_get_type (), NULL);
4438         gst_index_get_writer_id (parse->priv->index, GST_OBJECT (parse),
4439             &parse->priv->index_id);
4440         parse->priv->own_index = TRUE;
4441       }
4442       GST_BASE_PARSE_INDEX_UNLOCK (parse);
4443       break;
4444     default:
4445       break;
4446   }
4447
4448   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
4449
4450   switch (transition) {
4451     case GST_STATE_CHANGE_PAUSED_TO_READY:
4452       gst_base_parse_reset (parse);
4453       break;
4454     default:
4455       break;
4456   }
4457
4458   return result;
4459 }
4460
4461 /**
4462  * gst_base_parse_set_ts_at_offset:
4463  * @parse: a #GstBaseParse
4464  * @offset: offset into current buffer
4465  *
4466  * This function should only be called from a @handle_frame implementation.
4467  *
4468  * GstBaseParse creates initial timestamps for frames by using the last
4469  * timestamp seen in the stream before the frame starts.  In certain
4470  * cases, the correct timestamps will occur in the stream after the
4471  * start of the frame, but before the start of the actual picture data.
4472  * This function can be used to set the timestamps based on the offset
4473  * into the frame data that the picture starts.
4474  *
4475  * Since: 1.2
4476  */
4477 void
4478 gst_base_parse_set_ts_at_offset (GstBaseParse * parse, gsize offset)
4479 {
4480   GstClockTime pts, dts;
4481
4482   g_return_if_fail (GST_IS_BASE_PARSE (parse));
4483   g_return_if_fail (offset >= 0);
4484
4485   pts = gst_adapter_prev_pts_at_offset (parse->priv->adapter, offset, NULL);
4486   dts = gst_adapter_prev_dts_at_offset (parse->priv->adapter, offset, NULL);
4487
4488   if (!GST_CLOCK_TIME_IS_VALID (pts) || !GST_CLOCK_TIME_IS_VALID (dts)) {
4489     GST_DEBUG_OBJECT (parse,
4490         "offset adapter timestamps dts=%" GST_TIME_FORMAT " pts=%"
4491         GST_TIME_FORMAT, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts));
4492   }
4493   if (GST_CLOCK_TIME_IS_VALID (pts) && (parse->priv->prev_pts != pts))
4494     parse->priv->prev_pts = parse->priv->next_pts = pts;
4495
4496   if (GST_CLOCK_TIME_IS_VALID (dts) && (parse->priv->prev_dts != dts))
4497     parse->priv->prev_dts = parse->priv->next_dts = dts;
4498 }