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