baseparse: Set the last stop to the buffer starttime if the duration is invalid
[platform/upstream/gst-plugins-good.git] / gst / audioparsers / gstbaseparse.c
1 /* GStreamer
2  * Copyright (C) 2008 Nokia Corporation. All rights reserved.
3  *   Contact: Stefan Kost <stefan.kost@nokia.com>
4  * Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 /**
23  * SECTION:gstbaseparse
24  * @short_description: Base class for stream parsers
25  * @see_also: #GstBaseTransform
26  *
27  * This base class is for parser elements that process data and splits it 
28  * into separate audio/video/whatever frames.
29  *
30  * It provides for:
31  * <itemizedlist>
32  *   <listitem><para>One sinkpad and one srcpad</para></listitem>
33  *   <listitem><para>Handles state changes</para></listitem>
34  *   <listitem><para>Does flushing</para></listitem>
35  *   <listitem><para>Push mode</para></listitem>
36  *   <listitem><para>Pull mode</para></listitem>
37  *   <listitem><para>Handles events (NEWSEGMENT/EOS/FLUSH)</para></listitem>
38  *   <listitem><para>Handles seeking in both modes</para></listitem>
39  *   <listitem><para>
40  *        Handles POSITION/DURATION/SEEKING/FORMAT/CONVERT queries
41  *   </para></listitem>
42  * </itemizedlist>
43  *
44  * The purpose of this base class is to provide a basic functionality of
45  * a parser and share a lot of rather complex code.
46  *
47  * Description of the parsing mechanism:
48  * <orderedlist>
49  * <listitem>
50  *   <itemizedlist><title>Set-up phase</title>
51  *   <listitem><para>
52  *     GstBaseParse class calls @set_sink_caps to inform the subclass about
53  *     incoming sinkpad caps. Subclass should set the srcpad caps accordingly.
54  *   </para></listitem>
55  *   <listitem><para>
56  *     GstBaseParse calls @start to inform subclass that data processing is
57  *     about to start now.
58  *   </para></listitem>
59  *   <listitem><para>
60  *      At least in this point subclass needs to tell the GstBaseParse class
61  *      how big data chunks it wants to receive (min_frame_size). It can do 
62  *      this with @gst_base_parse_set_min_frame_size.
63  *   </para></listitem>
64  *   <listitem><para>
65  *      GstBaseParse class sets up appropriate data passing mode (pull/push)
66  *      and starts to process the data.
67  *   </para></listitem>
68  *   </itemizedlist>
69  * </listitem>
70  * <listitem>
71  *   <itemizedlist>
72  *   <title>Parsing phase</title>
73  *     <listitem><para>
74  *       GstBaseParse gathers at least min_frame_size bytes of data either 
75  *       by pulling it from upstream or collecting buffers into internal
76  *       #GstAdapter.
77  *     </para></listitem>
78  *     <listitem><para>
79  *       A buffer of min_frame_size bytes is passed to subclass with
80  *       @check_valid_frame. Subclass checks the contents and returns TRUE
81  *       if the buffer contains a valid frame. It also needs to set the
82  *       @framesize according to the detected frame size. If buffer didn't
83  *       contain a valid frame, this call must return FALSE and optionally
84  *       set the @skipsize value to inform base class that how many bytes
85  *       it needs to skip in order to find a valid frame. The passed buffer
86  *       is read-only.  Note that @check_valid_frame might receive any small
87  *       amount of input data when leftover data is being drained (e.g. at EOS).
88  *     </para></listitem>
89  *     <listitem><para>
90  *       After valid frame is found, it will be passed again to subclass with
91  *       @parse_frame call. Now subclass is responsible for parsing the
92  *       frame contents and setting the buffer timestamp, duration and caps.
93  *     </para></listitem>
94  *     <listitem><para>
95  *       Finally the buffer can be pushed downstream and parsing loop starts
96  *       over again.
97  *     </para></listitem>
98  *     <listitem><para>
99  *       During the parsing process GstBaseParseClass will handle both srcpad and
100  *       sinkpad events. They will be passed to subclass if @event or
101  *       @src_event callbacks have been provided.
102  *     </para></listitem>
103  *   </itemizedlist>
104  * </listitem>
105  * <listitem>
106  *   <itemizedlist><title>Shutdown phase</title>
107  *   <listitem><para>
108  *     GstBaseParse class calls @stop to inform the subclass that data
109  *     parsing will be stopped.
110  *   </para></listitem>
111  *   </itemizedlist>
112  * </listitem>
113  * </orderedlist>
114  *
115  * Subclass is responsible for providing pad template caps for
116  * source and sink pads. The pads need to be named "sink" and "src". It also 
117  * needs to set the fixed caps on srcpad, when the format is ensured (e.g. 
118  * when base class calls subclass' @set_sink_caps function).
119  *
120  * This base class uses GST_FORMAT_DEFAULT as a meaning of frames. So,
121  * subclass conversion routine needs to know that conversion from
122  * GST_FORMAT_TIME to GST_FORMAT_DEFAULT must return the
123  * frame number that can be found from the given byte position.
124  *
125  * GstBaseParse uses subclasses conversion methods also for seeking. If
126  * subclass doesn't provide @convert function, seeking will get disabled.
127  *
128  * Subclass @start and @stop functions will be called to inform the beginning
129  * and end of data processing.
130  *
131  * Things that subclass need to take care of:
132  * <itemizedlist>
133  *   <listitem><para>Provide pad templates</para></listitem>
134  *   <listitem><para>
135  *      Fixate the source pad caps when appropriate
136  *   </para></listitem>
137  *   <listitem><para>
138  *      Inform base class how big data chunks should be retrieved. This is
139  *      done with @gst_base_parse_set_min_frame_size function.
140  *   </para></listitem>
141  *   <listitem><para>
142  *      Examine data chunks passed to subclass with @check_valid_frame
143  *      and tell if they contain a valid frame
144  *   </para></listitem>
145  *   <listitem><para>
146  *      Set the caps and timestamp to frame that is passed to subclass with
147  *      @parse_frame function.
148  *   </para></listitem>
149  *   <listitem><para>Provide conversion functions</para></listitem>
150  *   <listitem><para>
151  *      Update the duration information with @gst_base_parse_set_duration
152  *   </para></listitem>
153  *   <listitem><para>
154  *      Alternatively, parsing (or specs) might yield a frames per seconds rate
155  *      which can be provided to GstBaseParse to enable it to cater for
156  *      buffer time metadata (which will be taken from upstream as much as possible).
157  *      Internally keeping track of frames and respective
158  *      sizes that have been pushed provides GstBaseParse with a bytes per frame
159  *      rate.  A default @convert (used if not overriden) will then use these
160  *      rates to perform obvious conversions.  These rates are also used to update
161  *      (estimated) duration at regular frame intervals.
162  *      If no (fixed) frames per second rate applies, default conversion will be
163  *      based on (estimated) bytes per second (but no default buffer metadata
164  *      can be provided in this case).
165  *   </para></listitem>
166  * </itemizedlist>
167  *
168  */
169
170 /* TODO:
171  *  - Better segment handling:
172  *    - NEWSEGMENT for gaps
173  *    - Not NEWSEGMENT starting at 0 but at first frame timestamp
174  *  - GstIndex support
175  *  - Seek table generation and subclass seek entry injection
176  *  - Accurate seeking
177  *  - In push mode provide a queue of adapter-"queued" buffers for upstream
178  *    buffer metadata
179  *  - Queue buffers/events until caps are set
180  *  - Let subclass decide if frames outside the segment should be dropped
181  *  - Send queries upstream
182  */
183
184 #ifdef HAVE_CONFIG_H
185 #  include "config.h"
186 #endif
187
188 #include <stdlib.h>
189 #include <string.h>
190
191 #include "gstbaseparse.h"
192
193 GST_DEBUG_CATEGORY_STATIC (gst_base_parse_debug);
194 #define GST_CAT_DEFAULT gst_base_parse_debug
195
196 /* Supported formats */
197 static GstFormat fmtlist[] = {
198   GST_FORMAT_DEFAULT,
199   GST_FORMAT_BYTES,
200   GST_FORMAT_TIME,
201   0
202 };
203
204 #define GST_BASE_PARSE_GET_PRIVATE(obj)  \
205     (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BASE_PARSE, GstBaseParsePrivate))
206
207 struct _GstBaseParsePrivate
208 {
209   GstActivateMode pad_mode;
210
211   gint64 duration;
212   GstFormat duration_fmt;
213   gint64 estimated_duration;
214
215   guint min_frame_size;
216   gboolean passthrough;
217   guint fps_num, fps_den;
218   guint update_interval;
219
220   gboolean discont;
221   gboolean flushing;
222   gboolean drain;
223
224   gint64 offset;
225   GstClockTime next_ts;
226   GstClockTime prev_ts;
227   GstClockTime frame_duration;
228
229   guint64 framecount;
230   guint64 bytecount;
231   guint64 data_bytecount;
232   guint64 acc_duration;
233
234   gboolean post_min_bitrate;
235   gboolean post_avg_bitrate;
236   gboolean post_max_bitrate;
237   guint min_bitrate;
238   guint avg_bitrate;
239   guint max_bitrate;
240
241   GList *pending_events;
242
243   GstBuffer *cache;
244 };
245
246 static GstElementClass *parent_class = NULL;
247
248 static void gst_base_parse_class_init (GstBaseParseClass * klass);
249 static void gst_base_parse_init (GstBaseParse * parse,
250     GstBaseParseClass * klass);
251
252 GType
253 gst_base_parse_get_type (void)
254 {
255   static GType base_parse_type = 0;
256
257   if (!base_parse_type) {
258     static const GTypeInfo base_parse_info = {
259       sizeof (GstBaseParseClass),
260       (GBaseInitFunc) NULL,
261       (GBaseFinalizeFunc) NULL,
262       (GClassInitFunc) gst_base_parse_class_init,
263       NULL,
264       NULL,
265       sizeof (GstBaseParse),
266       0,
267       (GInstanceInitFunc) gst_base_parse_init,
268     };
269
270     base_parse_type = g_type_register_static (GST_TYPE_ELEMENT,
271         "GstAudioBaseParseBad", &base_parse_info, G_TYPE_FLAG_ABSTRACT);
272   }
273   return base_parse_type;
274 }
275
276 static void gst_base_parse_finalize (GObject * object);
277
278 static gboolean gst_base_parse_sink_activate (GstPad * sinkpad);
279 static gboolean gst_base_parse_sink_activate_push (GstPad * pad,
280     gboolean active);
281 static gboolean gst_base_parse_sink_activate_pull (GstPad * pad,
282     gboolean active);
283 static gboolean gst_base_parse_handle_seek (GstBaseParse * parse,
284     GstEvent * event);
285 static void gst_base_parse_handle_tag (GstBaseParse * parse, GstEvent * event);
286
287 static gboolean gst_base_parse_src_event (GstPad * pad, GstEvent * event);
288 static gboolean gst_base_parse_sink_event (GstPad * pad, GstEvent * event);
289 static gboolean gst_base_parse_query (GstPad * pad, GstQuery * query);
290 static gboolean gst_base_parse_sink_setcaps (GstPad * pad, GstCaps * caps);
291 static const GstQueryType *gst_base_parse_get_querytypes (GstPad * pad);
292
293 static GstFlowReturn gst_base_parse_chain (GstPad * pad, GstBuffer * buffer);
294 static void gst_base_parse_loop (GstPad * pad);
295
296 static gboolean gst_base_parse_check_frame (GstBaseParse * parse,
297     GstBuffer * buffer, guint * framesize, gint * skipsize);
298
299 static GstFlowReturn gst_base_parse_parse_frame (GstBaseParse * parse,
300     GstBuffer * buffer);
301
302 static gboolean gst_base_parse_sink_eventfunc (GstBaseParse * parse,
303     GstEvent * event);
304
305 static gboolean gst_base_parse_src_eventfunc (GstBaseParse * parse,
306     GstEvent * event);
307
308 static gboolean gst_base_parse_is_seekable (GstBaseParse * parse);
309
310 gboolean gst_base_parse_convert (GstBaseParse * parse, GstFormat src_format,
311     gint64 src_value, GstFormat dest_format, gint64 * dest_value);
312
313 static void gst_base_parse_drain (GstBaseParse * parse);
314
315 static void
316 gst_base_parse_finalize (GObject * object)
317 {
318   GstBaseParse *parse = GST_BASE_PARSE (object);
319   GstEvent **p_ev;
320
321   g_mutex_free (parse->parse_lock);
322   g_object_unref (parse->adapter);
323
324   if (parse->pending_segment) {
325     p_ev = &parse->pending_segment;
326     gst_event_replace (p_ev, NULL);
327   }
328   if (parse->close_segment) {
329     p_ev = &parse->close_segment;
330     gst_event_replace (p_ev, NULL);
331   }
332
333   if (parse->priv->cache) {
334     gst_buffer_unref (parse->priv->cache);
335     parse->priv->cache = NULL;
336   }
337
338   g_list_foreach (parse->priv->pending_events, (GFunc) gst_mini_object_unref,
339       NULL);
340   g_list_free (parse->priv->pending_events);
341   parse->priv->pending_events = NULL;
342
343   G_OBJECT_CLASS (parent_class)->finalize (object);
344 }
345
346 static void
347 gst_base_parse_class_init (GstBaseParseClass * klass)
348 {
349   GObjectClass *gobject_class;
350
351   gobject_class = G_OBJECT_CLASS (klass);
352   g_type_class_add_private (klass, sizeof (GstBaseParsePrivate));
353   parent_class = g_type_class_peek_parent (klass);
354   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_base_parse_finalize);
355
356   /* Default handlers */
357   klass->check_valid_frame = gst_base_parse_check_frame;
358   klass->parse_frame = gst_base_parse_parse_frame;
359   klass->event = gst_base_parse_sink_eventfunc;
360   klass->src_event = gst_base_parse_src_eventfunc;
361   klass->is_seekable = gst_base_parse_is_seekable;
362   klass->convert = gst_base_parse_convert;
363
364   GST_DEBUG_CATEGORY_INIT (gst_base_parse_debug, "baseparse", 0,
365       "baseparse element");
366 }
367
368 static void
369 gst_base_parse_init (GstBaseParse * parse, GstBaseParseClass * bclass)
370 {
371   GstPadTemplate *pad_template;
372
373   GST_DEBUG_OBJECT (parse, "gst_base_parse_init");
374
375   parse->priv = GST_BASE_PARSE_GET_PRIVATE (parse);
376
377   pad_template =
378       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "sink");
379   g_return_if_fail (pad_template != NULL);
380   parse->sinkpad = gst_pad_new_from_template (pad_template, "sink");
381   gst_pad_set_event_function (parse->sinkpad,
382       GST_DEBUG_FUNCPTR (gst_base_parse_sink_event));
383   gst_pad_set_setcaps_function (parse->sinkpad,
384       GST_DEBUG_FUNCPTR (gst_base_parse_sink_setcaps));
385   gst_pad_set_chain_function (parse->sinkpad,
386       GST_DEBUG_FUNCPTR (gst_base_parse_chain));
387   gst_pad_set_activate_function (parse->sinkpad,
388       GST_DEBUG_FUNCPTR (gst_base_parse_sink_activate));
389   gst_pad_set_activatepush_function (parse->sinkpad,
390       GST_DEBUG_FUNCPTR (gst_base_parse_sink_activate_push));
391   gst_pad_set_activatepull_function (parse->sinkpad,
392       GST_DEBUG_FUNCPTR (gst_base_parse_sink_activate_pull));
393   gst_element_add_pad (GST_ELEMENT (parse), parse->sinkpad);
394
395   GST_DEBUG_OBJECT (parse, "sinkpad created");
396
397   pad_template =
398       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "src");
399   g_return_if_fail (pad_template != NULL);
400   parse->srcpad = gst_pad_new_from_template (pad_template, "src");
401   gst_pad_set_event_function (parse->srcpad,
402       GST_DEBUG_FUNCPTR (gst_base_parse_src_event));
403   gst_pad_set_query_type_function (parse->srcpad,
404       GST_DEBUG_FUNCPTR (gst_base_parse_get_querytypes));
405   gst_pad_set_query_function (parse->srcpad,
406       GST_DEBUG_FUNCPTR (gst_base_parse_query));
407   gst_pad_use_fixed_caps (parse->srcpad);
408   gst_element_add_pad (GST_ELEMENT (parse), parse->srcpad);
409   GST_DEBUG_OBJECT (parse, "src created");
410
411   parse->parse_lock = g_mutex_new ();
412   parse->adapter = gst_adapter_new ();
413   parse->pending_segment = NULL;
414   parse->close_segment = NULL;
415
416   parse->priv->pad_mode = GST_ACTIVATE_NONE;
417   parse->priv->duration = -1;
418   parse->priv->min_frame_size = 1;
419   parse->priv->passthrough = FALSE;
420   parse->priv->discont = FALSE;
421   parse->priv->flushing = FALSE;
422   parse->priv->offset = 0;
423   GST_DEBUG_OBJECT (parse, "init ok");
424 }
425
426
427
428 /**
429  * gst_base_parse_check_frame:
430  * @parse: #GstBaseParse.
431  * @buffer: GstBuffer.
432  * @framesize: This will be set to tell the found frame size in bytes.
433  * @skipsize: Output parameter that tells how much data needs to be skipped
434  *            in order to find the following frame header.
435  *
436  * Default callback for check_valid_frame.
437  * 
438  * Returns: Always TRUE.
439  */
440 static gboolean
441 gst_base_parse_check_frame (GstBaseParse * parse,
442     GstBuffer * buffer, guint * framesize, gint * skipsize)
443 {
444   *framesize = GST_BUFFER_SIZE (buffer);
445   *skipsize = 0;
446   return TRUE;
447 }
448
449
450 /**
451  * gst_base_parse_parse_frame:
452  * @parse: #GstBaseParse.
453  * @buffer: #GstBuffer.
454  *
455  * Default callback for parse_frame.
456  */
457 static GstFlowReturn
458 gst_base_parse_parse_frame (GstBaseParse * parse, GstBuffer * buffer)
459 {
460   if (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
461       GST_CLOCK_TIME_IS_VALID (parse->priv->next_ts)) {
462     GST_BUFFER_TIMESTAMP (buffer) = parse->priv->next_ts;
463   }
464   if (!GST_BUFFER_DURATION_IS_VALID (buffer) &&
465       GST_CLOCK_TIME_IS_VALID (parse->priv->frame_duration)) {
466     GST_BUFFER_DURATION (buffer) = parse->priv->frame_duration;
467   }
468   return GST_FLOW_OK;
469 }
470
471
472 /**
473  * gst_base_parse_bytepos_to_time:
474  * @parse: #GstBaseParse.
475  * @bytepos: Position (in bytes) to be converted.
476  * @pos_in_time: #GstClockTime pointer where the result is set.
477  *
478  * Convert given byte position into #GstClockTime format.
479  * 
480  * Returns: TRUE if conversion succeeded.
481  */
482 static gboolean
483 gst_base_parse_bytepos_to_time (GstBaseParse * parse, gint64 bytepos,
484     GstClockTime * pos_in_time)
485 {
486   GstBaseParseClass *klass;
487   gboolean res = FALSE;
488
489   klass = GST_BASE_PARSE_GET_CLASS (parse);
490
491   if (klass->convert) {
492     res = klass->convert (parse, GST_FORMAT_BYTES, bytepos,
493         GST_FORMAT_TIME, (gint64 *) pos_in_time);
494   }
495   return res;
496 }
497
498
499 /**
500  * gst_base_parse_sink_event:
501  * @pad: #GstPad that received the event.
502  * @event: #GstEvent to be handled.
503  *
504  * Handler for sink pad events.
505  *
506  * Returns: TRUE if the event was handled.
507  */
508 static gboolean
509 gst_base_parse_sink_event (GstPad * pad, GstEvent * event)
510 {
511   GstBaseParse *parse;
512   GstBaseParseClass *bclass;
513   gboolean handled = FALSE;
514   gboolean ret = TRUE;
515
516
517   parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
518   bclass = GST_BASE_PARSE_GET_CLASS (parse);
519
520   GST_DEBUG_OBJECT (parse, "handling event %d", GST_EVENT_TYPE (event));
521
522   /* Cache all events except EOS, NEWSEGMENT and FLUSH_STOP if we have a
523    * pending segment */
524   if (parse->pending_segment && GST_EVENT_TYPE (event) != GST_EVENT_EOS
525       && GST_EVENT_TYPE (event) != GST_EVENT_NEWSEGMENT
526       && GST_EVENT_TYPE (event) != GST_EVENT_FLUSH_START
527       && GST_EVENT_TYPE (event) != GST_EVENT_FLUSH_STOP) {
528
529     if (GST_EVENT_TYPE (event) == GST_EVENT_TAG)
530       /* See if any bitrate tags were posted */
531       gst_base_parse_handle_tag (parse, event);
532
533     parse->priv->pending_events =
534         g_list_append (parse->priv->pending_events, event);
535     ret = TRUE;
536   } else {
537
538     if (bclass->event)
539       handled = bclass->event (parse, event);
540
541     if (!handled)
542       ret = gst_pad_event_default (pad, event);
543   }
544
545   gst_object_unref (parse);
546   GST_DEBUG_OBJECT (parse, "event handled");
547   return ret;
548 }
549
550
551 /**
552  * gst_base_parse_sink_eventfunc:
553  * @parse: #GstBaseParse.
554  * @event: #GstEvent to be handled.
555  *
556  * Element-level event handler function.
557  *
558  * Returns: TRUE if the event was handled and not need forwarding.
559  */
560 static gboolean
561 gst_base_parse_sink_eventfunc (GstBaseParse * parse, GstEvent * event)
562 {
563   gboolean handled = FALSE;
564   GstEvent **eventp;
565
566   switch (GST_EVENT_TYPE (event)) {
567     case GST_EVENT_NEWSEGMENT:
568     {
569       gdouble rate, applied_rate;
570       GstFormat format;
571       gint64 start, stop, pos, offset = 0;
572       gboolean update;
573
574       gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
575           &format, &start, &stop, &pos);
576
577
578       if (format == GST_FORMAT_BYTES) {
579         GstClockTime seg_start, seg_stop, seg_pos;
580
581         /* stop time is allowed to be open-ended, but not start & pos */
582         seg_stop = GST_CLOCK_TIME_NONE;
583         offset = pos;
584
585         if (gst_base_parse_bytepos_to_time (parse, start, &seg_start) &&
586             gst_base_parse_bytepos_to_time (parse, pos, &seg_pos)) {
587           gst_event_unref (event);
588           event = gst_event_new_new_segment_full (update, rate, applied_rate,
589               GST_FORMAT_TIME, seg_start, seg_stop, seg_pos);
590           format = GST_FORMAT_TIME;
591           GST_DEBUG_OBJECT (parse, "Converted incoming segment to TIME. "
592               "start = %" GST_TIME_FORMAT ", stop = %" GST_TIME_FORMAT
593               ", pos = %" GST_TIME_FORMAT, GST_TIME_ARGS (seg_start),
594               GST_TIME_ARGS (seg_stop), GST_TIME_ARGS (seg_pos));
595         }
596       }
597
598       if (format != GST_FORMAT_TIME) {
599         /* Unknown incoming segment format. Output a default open-ended 
600          * TIME segment */
601         gst_event_unref (event);
602         event = gst_event_new_new_segment_full (update, rate, applied_rate,
603             GST_FORMAT_TIME, 0, GST_CLOCK_TIME_NONE, 0);
604       }
605
606       gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
607           &format, &start, &stop, &pos);
608
609       gst_segment_set_newsegment_full (&parse->segment, update, rate,
610           applied_rate, format, start, stop, pos);
611
612       GST_DEBUG_OBJECT (parse, "Created newseg rate %g, applied rate %g, "
613           "format %d, start = %" GST_TIME_FORMAT ", stop = %" GST_TIME_FORMAT
614           ", pos = %" GST_TIME_FORMAT, rate, applied_rate, format,
615           GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (pos));
616
617       /* save the segment for later, right before we push a new buffer so that
618        * the caps are fixed and the next linked element can receive
619        * the segment. */
620       eventp = &parse->pending_segment;
621       gst_event_replace (eventp, event);
622       gst_event_unref (event);
623       handled = TRUE;
624
625       /* but finish the current segment */
626       GST_DEBUG_OBJECT (parse, "draining current segment");
627       gst_base_parse_drain (parse);
628       gst_adapter_clear (parse->adapter);
629       parse->priv->offset = offset;
630       parse->priv->next_ts = start;
631       break;
632     }
633
634     case GST_EVENT_FLUSH_START:
635       parse->priv->flushing = TRUE;
636       handled = gst_pad_push_event (parse->srcpad, event);
637       /* Wait for _chain() to exit by taking the srcpad STREAM_LOCK */
638       GST_PAD_STREAM_LOCK (parse->srcpad);
639       GST_PAD_STREAM_UNLOCK (parse->srcpad);
640
641       break;
642
643     case GST_EVENT_FLUSH_STOP:
644       gst_adapter_clear (parse->adapter);
645       parse->priv->flushing = FALSE;
646       parse->priv->discont = TRUE;
647       break;
648
649     case GST_EVENT_EOS:
650       gst_base_parse_drain (parse);
651       break;
652
653     default:
654       break;
655   }
656
657   return handled;
658 }
659
660
661 /**
662  * gst_base_parse_src_event:
663  * @pad: #GstPad that received the event.
664  * @event: #GstEvent that was received.
665  *
666  * Handler for source pad events.
667  *
668  * Returns: TRUE if the event was handled.
669  */
670 static gboolean
671 gst_base_parse_src_event (GstPad * pad, GstEvent * event)
672 {
673   GstBaseParse *parse;
674   GstBaseParseClass *bclass;
675   gboolean handled = FALSE;
676   gboolean ret = TRUE;
677
678   parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
679   bclass = GST_BASE_PARSE_GET_CLASS (parse);
680
681   GST_DEBUG_OBJECT (parse, "event %d, %s", GST_EVENT_TYPE (event),
682       GST_EVENT_TYPE_NAME (event));
683
684   if (bclass->src_event)
685     handled = bclass->src_event (parse, event);
686
687   if (!handled)
688     ret = gst_pad_event_default (pad, event);
689
690   gst_object_unref (parse);
691   return ret;
692 }
693
694
695 /**
696  * gst_base_parse_src_eventfunc:
697  * @parse: #GstBaseParse.
698  * @event: #GstEvent that was received.
699  *
700  * Default srcpad event handler.
701  *
702  * Returns: TRUE if the event was handled and can be dropped.
703  */
704 static gboolean
705 gst_base_parse_src_eventfunc (GstBaseParse * parse, GstEvent * event)
706 {
707   gboolean handled = FALSE;
708   GstBaseParseClass *bclass;
709
710   bclass = GST_BASE_PARSE_GET_CLASS (parse);
711
712   switch (GST_EVENT_TYPE (event)) {
713     case GST_EVENT_SEEK:
714     {
715       if (bclass->is_seekable (parse)) {
716         handled = gst_base_parse_handle_seek (parse, event);
717         gst_event_unref (event);
718       }
719       break;
720     }
721     default:
722       break;
723   }
724   return handled;
725 }
726
727
728 /**
729  * gst_base_parse_is_seekable:
730  * @parse: #GstBaseParse.
731  *
732  * Default handler for is_seekable.
733  *
734  * Returns: Always TRUE.
735  */
736 static gboolean
737 gst_base_parse_is_seekable (GstBaseParse * parse)
738 {
739   return TRUE;
740 }
741
742 /**
743  * gst_base_parse_convert:
744  * @parse: #GstBaseParse.
745  * @src_format: #GstFormat describing the source format.
746  * @src_value: Source value to be converted.
747  * @dest_format: #GstFormat defining the converted format.
748  * @dest_value: Pointer where the conversion result will be put.
749  *
750  * Implementation of "convert" vmethod in #GstBaseParse class.
751  *
752  * Returns: TRUE if conversion was successful.
753  */
754 gboolean
755 gst_base_parse_convert (GstBaseParse * parse,
756     GstFormat src_format,
757     gint64 src_value, GstFormat dest_format, gint64 * dest_value)
758 {
759   gboolean ret = FALSE;
760   guint64 bytes, duration;
761
762   if (G_UNLIKELY (src_format == dest_format)) {
763     *dest_value = src_value;
764     return TRUE;
765   }
766
767   if (G_UNLIKELY (src_value == -1)) {
768     *dest_value = -1;
769     return TRUE;
770   }
771
772   /* need at least some frames */
773   if (!parse->priv->framecount)
774     return FALSE;
775
776   /* either frame info (having num means den also ok) or use average bitrate */
777   if (parse->priv->fps_num) {
778     duration = parse->priv->framecount * parse->priv->fps_den * 1000;
779     bytes = parse->priv->bytecount * parse->priv->fps_num;
780   } else {
781     duration = parse->priv->acc_duration / GST_MSECOND;
782     bytes = parse->priv->bytecount;
783   }
784
785   if (G_UNLIKELY (!duration || !bytes))
786     return FALSE;
787
788   if (src_format == GST_FORMAT_BYTES) {
789     if (dest_format == GST_FORMAT_TIME) {
790       /* BYTES -> TIME conversion */
791       GST_DEBUG_OBJECT (parse, "converting bytes -> time");
792
793       *dest_value = gst_util_uint64_scale (src_value, duration, bytes);
794       *dest_value *= GST_MSECOND;
795       GST_DEBUG_OBJECT (parse, "conversion result: %" G_GINT64_FORMAT " ms",
796           *dest_value / GST_MSECOND);
797       ret = TRUE;
798     }
799   } else if (src_format == GST_FORMAT_TIME) {
800     GST_DEBUG_OBJECT (parse, "converting time -> bytes");
801     if (dest_format == GST_FORMAT_BYTES) {
802       *dest_value = gst_util_uint64_scale (src_value / GST_MSECOND, bytes,
803           duration);
804       GST_DEBUG_OBJECT (parse,
805           "time %" G_GINT64_FORMAT " ms in bytes = %" G_GINT64_FORMAT,
806           src_value / GST_MSECOND, *dest_value);
807       ret = TRUE;
808     }
809   } else if (src_format == GST_FORMAT_DEFAULT) {
810     /* DEFAULT == frame-based */
811     if (dest_format == GST_FORMAT_TIME) {
812       if (parse->priv->fps_den) {
813         *dest_value = gst_util_uint64_scale (src_value,
814             GST_SECOND * parse->priv->fps_den, parse->priv->fps_num);
815         ret = TRUE;
816       }
817     } else if (dest_format == GST_FORMAT_BYTES) {
818     }
819   }
820
821   return ret;
822 }
823
824 /**
825  * gst_base_parse_update_duration:
826  * @parse: #GstBaseParse.
827  *
828  */
829 static void
830 gst_base_parse_update_duration (GstBaseParse * aacparse)
831 {
832   GstPad *peer;
833   GstBaseParse *parse;
834   GstBaseParseClass *klass;
835
836   parse = GST_BASE_PARSE (aacparse);
837   klass = GST_BASE_PARSE_GET_CLASS (parse);
838
839   /* must be able to convert */
840   if (!klass->convert)
841     return;
842
843   peer = gst_pad_get_peer (parse->sinkpad);
844   if (peer) {
845     GstFormat pformat = GST_FORMAT_BYTES;
846     gboolean qres = FALSE;
847     gint64 ptot, dest_value;
848
849     qres = gst_pad_query_duration (peer, &pformat, &ptot);
850     gst_object_unref (GST_OBJECT (peer));
851     if (qres) {
852       if (klass->convert (parse, pformat, ptot, GST_FORMAT_TIME, &dest_value))
853         parse->priv->estimated_duration = dest_value;
854     }
855   }
856 }
857
858 /**
859  * gst_base_parse_update_bitrates:
860  * @parse: #GstBaseParse.
861  * @buffer: Current frame as a #GstBuffer
862  *
863  * Keeps track of the minimum and maximum bitrates, and also maintains a
864  * running average bitrate of the stream so far.
865  */
866 static void
867 gst_base_parse_update_bitrates (GstBaseParse * parse, GstBuffer * buffer)
868 {
869   /* Only update the tag on a 10 kbps delta */
870   static const gint update_threshold = 10000;
871
872   GstBaseParseClass *klass;
873   guint64 data_len, frame_dur;
874   gint overhead = 0, frame_bitrate, old_avg_bitrate = parse->priv->avg_bitrate;
875   gboolean update_min = FALSE, update_avg = FALSE, update_max = FALSE;
876
877   klass = GST_BASE_PARSE_GET_CLASS (parse);
878
879   if (klass->get_frame_overhead) {
880     overhead = klass->get_frame_overhead (parse, buffer);
881     if (overhead == -1)
882       return;
883   }
884
885   data_len = GST_BUFFER_SIZE (buffer) - overhead;
886   parse->priv->data_bytecount += data_len;
887
888   if (parse->priv->fps_num) {
889     /* Calculate duration of a frame from frame properties */
890     frame_dur = (GST_SECOND * parse->priv->fps_den) / parse->priv->fps_num;
891     parse->priv->avg_bitrate = (8 * parse->priv->data_bytecount * GST_SECOND) /
892         (parse->priv->framecount * frame_dur);
893
894   } else if (GST_BUFFER_DURATION_IS_VALID (buffer)) {
895     /* Calculate duration of a frame from buffer properties */
896     frame_dur = GST_BUFFER_DURATION (buffer);
897     parse->priv->avg_bitrate = (8 * parse->priv->data_bytecount * GST_SECOND) /
898         parse->priv->acc_duration;
899
900   } else {
901     /* No way to figure out frame duration (is this even possible?) */
902     return;
903   }
904
905   frame_bitrate = (8 * data_len * GST_SECOND) / frame_dur;
906
907   if (frame_bitrate < parse->priv->min_bitrate) {
908     parse->priv->min_bitrate = frame_bitrate;
909     update_min = parse->priv->post_min_bitrate;
910   }
911
912   if (frame_bitrate > parse->priv->max_bitrate) {
913     parse->priv->max_bitrate = frame_bitrate;
914     update_max = parse->priv->post_max_bitrate;
915   }
916
917   if (old_avg_bitrate / update_threshold !=
918       parse->priv->avg_bitrate / update_threshold)
919     update_avg = parse->priv->post_avg_bitrate;
920
921   if (update_min || update_avg || update_max) {
922     GstTagList *taglist = gst_tag_list_new ();
923
924     if (update_min)
925       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_MINIMUM_BITRATE,
926           parse->priv->min_bitrate, NULL);
927     if (update_avg)
928       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
929           parse->priv->avg_bitrate, NULL);
930     if (update_max)
931       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
932           parse->priv->max_bitrate, NULL);
933
934     GST_DEBUG_OBJECT (parse, "Updated bitrates. Min: %u, Avg: %u, Max: %u",
935         parse->priv->min_bitrate, parse->priv->avg_bitrate,
936         parse->priv->max_bitrate);
937
938     gst_element_found_tags_for_pad (GST_ELEMENT (parse), parse->srcpad,
939         taglist);
940   }
941 }
942
943 /**
944  * gst_base_parse_handle_and_push_buffer:
945  * @parse: #GstBaseParse.
946  * @klass: #GstBaseParseClass.
947  * @buffer: #GstBuffer.
948  *
949  * Parses the frame from given buffer and pushes it forward. Also performs
950  * timestamp handling and checks the segment limits.
951  *
952  * This is called with srcpad STREAM_LOCK held.
953  *
954  * Returns: #GstFlowReturn
955  */
956 static GstFlowReturn
957 gst_base_parse_handle_and_push_buffer (GstBaseParse * parse,
958     GstBaseParseClass * klass, GstBuffer * buffer)
959 {
960   GstFlowReturn ret;
961
962   if (parse->priv->discont) {
963     GST_DEBUG_OBJECT (parse, "marking DISCONT");
964     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
965     parse->priv->discont = FALSE;
966   }
967
968   GST_LOG_OBJECT (parse,
969       "parsing frame at offset %" G_GUINT64_FORMAT
970       " (%#" G_GINT64_MODIFIER "x) of size %d",
971       GST_BUFFER_OFFSET (buffer), GST_BUFFER_OFFSET (buffer),
972       GST_BUFFER_SIZE (buffer));
973
974   ret = klass->parse_frame (parse, buffer);
975
976   /* re-use default handler to add missing metadata as-much-as-possible */
977   gst_base_parse_parse_frame (parse, buffer);
978   if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
979       GST_BUFFER_DURATION_IS_VALID (buffer)) {
980     parse->priv->next_ts =
981         GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer);
982   } else {
983     /* we lost track, do not produce bogus time next time around
984      * (probably means parser subclass has given up on parsing as well) */
985     GST_DEBUG_OBJECT (parse, "no next fallback timestamp");
986     parse->priv->next_ts = GST_CLOCK_TIME_NONE;
987   }
988
989   /* First buffers are dropped, this means that the subclass needs more
990    * frames to decide on the format and queues them internally */
991   /* convert internal flow to OK and mark discont for the next buffer. */
992   if (ret == GST_BASE_PARSE_FLOW_DROPPED) {
993     gst_buffer_unref (buffer);
994     return GST_FLOW_OK;
995   } else if (ret != GST_FLOW_OK) {
996     return ret;
997   }
998
999   return gst_base_parse_push_buffer (parse, buffer);
1000 }
1001
1002 /**
1003  * gst_base_parse_push_buffer:
1004  * @parse: #GstBaseParse.
1005  * @buffer: #GstBuffer.
1006  *
1007  * Pushes the buffer downstream, sends any pending events and
1008  * does some timestamp and segment handling.
1009  *
1010  * This must be called with srcpad STREAM_LOCK held.
1011  *
1012  * Returns: #GstFlowReturn
1013  */
1014 GstFlowReturn
1015 gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer)
1016 {
1017   GstFlowReturn ret = GST_FLOW_OK;
1018   GstClockTime last_start = GST_CLOCK_TIME_NONE;
1019   GstClockTime last_stop = GST_CLOCK_TIME_NONE;
1020
1021   GST_LOG_OBJECT (parse,
1022       "processing buffer of size %d with ts %" GST_TIME_FORMAT
1023       ", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buffer),
1024       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
1025       GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
1026
1027   /* update stats */
1028   parse->priv->bytecount += GST_BUFFER_SIZE (buffer);
1029   if (!GST_BUFFER_FLAG_IS_SET (buffer, GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME)) {
1030     parse->priv->framecount++;
1031     if (GST_BUFFER_DURATION_IS_VALID (buffer)) {
1032       parse->priv->acc_duration += GST_BUFFER_DURATION (buffer);
1033     }
1034   }
1035   GST_BUFFER_FLAG_UNSET (buffer, GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME);
1036   if (parse->priv->update_interval &&
1037       (parse->priv->framecount % parse->priv->update_interval) == 0)
1038     gst_base_parse_update_duration (parse);
1039
1040   gst_base_parse_update_bitrates (parse, buffer);
1041
1042   if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer))
1043     last_start = last_stop = GST_BUFFER_TIMESTAMP (buffer);
1044   if (last_start != GST_CLOCK_TIME_NONE
1045       && GST_BUFFER_DURATION_IS_VALID (buffer))
1046     last_stop = last_start + GST_BUFFER_DURATION (buffer);
1047
1048   /* should have caps by now */
1049   g_return_val_if_fail (GST_PAD_CAPS (parse->srcpad), GST_FLOW_ERROR);
1050
1051   gst_buffer_set_caps (buffer, GST_PAD_CAPS (parse->srcpad));
1052
1053   /* segment times are typically estimates,
1054    * actual frame data might lead subclass to different timestamps,
1055    * so override segment start from what is supplied there */
1056   if (G_UNLIKELY (parse->pending_segment && !parse->priv->passthrough &&
1057           GST_CLOCK_TIME_IS_VALID (last_start))) {
1058     gst_event_unref (parse->pending_segment);
1059     /* stop time possibly lost this way,
1060      * but unlikely and not really supported */
1061     parse->pending_segment =
1062         gst_event_new_new_segment (FALSE, parse->segment.rate,
1063         parse->segment.format, last_start, -1, last_start);
1064   }
1065
1066   /* and should then also be linked downstream, so safe to send some events */
1067   if (parse->priv->pad_mode == GST_ACTIVATE_PULL) {
1068     if (G_UNLIKELY (parse->close_segment)) {
1069       GST_DEBUG_OBJECT (parse, "loop sending close segment");
1070       gst_pad_push_event (parse->srcpad, parse->close_segment);
1071       parse->close_segment = NULL;
1072     }
1073
1074     if (G_UNLIKELY (parse->pending_segment)) {
1075       GST_DEBUG_OBJECT (parse, "loop push pending segment");
1076       gst_pad_push_event (parse->srcpad, parse->pending_segment);
1077       parse->pending_segment = NULL;
1078     }
1079   } else {
1080     if (G_UNLIKELY (parse->pending_segment)) {
1081       GST_DEBUG_OBJECT (parse, "chain pushing a pending segment");
1082       gst_pad_push_event (parse->srcpad, parse->pending_segment);
1083       parse->pending_segment = NULL;
1084     }
1085   }
1086
1087   if (G_UNLIKELY (parse->priv->pending_events)) {
1088     GList *l;
1089
1090     for (l = parse->priv->pending_events; l != NULL; l = l->next) {
1091       gst_pad_push_event (parse->srcpad, GST_EVENT (l->data));
1092     }
1093     g_list_free (parse->priv->pending_events);
1094     parse->priv->pending_events = NULL;
1095   }
1096
1097   /* TODO: Add to seek table */
1098
1099   if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
1100       GST_CLOCK_TIME_IS_VALID (parse->segment.stop) &&
1101       GST_BUFFER_TIMESTAMP (buffer) > parse->segment.stop) {
1102     GST_LOG_OBJECT (parse, "Dropped frame, after segment");
1103     gst_buffer_unref (buffer);
1104   } else if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
1105       GST_BUFFER_DURATION_IS_VALID (buffer) &&
1106       GST_CLOCK_TIME_IS_VALID (parse->segment.start) &&
1107       GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer)
1108       < parse->segment.start) {
1109     /* FIXME: subclass needs way to override the start as downstream might
1110      * need frames before for proper decoding */
1111     GST_LOG_OBJECT (parse, "Dropped frame, before segment");
1112     gst_buffer_unref (buffer);
1113   } else {
1114     ret = gst_pad_push (parse->srcpad, buffer);
1115     GST_LOG_OBJECT (parse, "frame (%d bytes) pushed: %d",
1116         GST_BUFFER_SIZE (buffer), ret);
1117   }
1118
1119   /* Update current running segment position */
1120   if (ret == GST_FLOW_OK && last_stop != GST_CLOCK_TIME_NONE)
1121     gst_segment_set_last_stop (&parse->segment, GST_FORMAT_TIME, last_stop);
1122
1123   return ret;
1124 }
1125
1126
1127 /**
1128  * gst_base_parse_drain:
1129  * @parse: #GstBaseParse.
1130  *
1131  * Drains the adapter until it is empty. It decreases the min_frame_size to
1132  * match the current adapter size and calls chain method until the adapter
1133  * is emptied or chain returns with error.
1134  */
1135 static void
1136 gst_base_parse_drain (GstBaseParse * parse)
1137 {
1138   guint avail;
1139
1140   GST_DEBUG_OBJECT (parse, "draining");
1141   parse->priv->drain = TRUE;
1142
1143   for (;;) {
1144     avail = gst_adapter_available (parse->adapter);
1145     if (!avail)
1146       break;
1147
1148     if (gst_base_parse_chain (parse->sinkpad, NULL) != GST_FLOW_OK) {
1149       break;
1150     }
1151
1152     /* nothing changed, maybe due to truncated frame; break infinite loop */
1153     if (avail == gst_adapter_available (parse->adapter)) {
1154       GST_DEBUG_OBJECT (parse, "no change during draining; flushing");
1155       gst_adapter_clear (parse->adapter);
1156     }
1157   }
1158
1159   parse->priv->drain = FALSE;
1160 }
1161
1162
1163 /**
1164  * gst_base_parse_chain:
1165  * @pad: #GstPad.
1166  * @buffer: #GstBuffer.
1167  *
1168  * Returns: #GstFlowReturn.
1169  */
1170 static GstFlowReturn
1171 gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
1172 {
1173   GstBaseParseClass *bclass;
1174   GstBaseParse *parse;
1175   GstFlowReturn ret = GST_FLOW_OK;
1176   GstBuffer *outbuf = NULL;
1177   GstBuffer *tmpbuf = NULL;
1178   guint fsize = 0;
1179   gint skip = -1;
1180   const guint8 *data;
1181   guint min_size;
1182   GstClockTime timestamp;
1183
1184   parse = GST_BASE_PARSE (GST_OBJECT_PARENT (pad));
1185   bclass = GST_BASE_PARSE_GET_CLASS (parse);
1186
1187   if (G_LIKELY (buffer)) {
1188     GST_LOG_OBJECT (parse, "buffer size: %d, offset = %" G_GINT64_FORMAT,
1189         GST_BUFFER_SIZE (buffer), GST_BUFFER_OFFSET (buffer));
1190     if (G_UNLIKELY (parse->priv->passthrough)) {
1191       buffer = gst_buffer_make_metadata_writable (buffer);
1192       return gst_base_parse_push_buffer (parse, buffer);
1193     } else
1194       gst_adapter_push (parse->adapter, buffer);
1195   }
1196
1197   /* Parse and push as many frames as possible */
1198   /* Stop either when adapter is empty or we are flushing */
1199   while (!parse->priv->flushing) {
1200     tmpbuf = gst_buffer_new ();
1201
1202     /* Synchronization loop */
1203     for (;;) {
1204       GST_BASE_PARSE_LOCK (parse);
1205       min_size = parse->priv->min_frame_size;
1206       GST_BASE_PARSE_UNLOCK (parse);
1207
1208       if (G_UNLIKELY (parse->priv->drain)) {
1209         min_size = gst_adapter_available (parse->adapter);
1210         GST_DEBUG_OBJECT (parse, "draining, data left: %d", min_size);
1211         if (G_UNLIKELY (!min_size)) {
1212           gst_buffer_unref (tmpbuf);
1213           goto done;
1214         }
1215       }
1216
1217       /* Collect at least min_frame_size bytes */
1218       if (gst_adapter_available (parse->adapter) < min_size) {
1219         GST_DEBUG_OBJECT (parse, "not enough data available (only %d bytes)",
1220             gst_adapter_available (parse->adapter));
1221         gst_buffer_unref (tmpbuf);
1222         goto done;
1223       }
1224
1225       data = gst_adapter_peek (parse->adapter, min_size);
1226       GST_BUFFER_DATA (tmpbuf) = (guint8 *) data;
1227       GST_BUFFER_SIZE (tmpbuf) = min_size;
1228       GST_BUFFER_OFFSET (tmpbuf) = parse->priv->offset;
1229       GST_BUFFER_FLAG_SET (tmpbuf, GST_MINI_OBJECT_FLAG_READONLY);
1230
1231       if (parse->priv->discont) {
1232         GST_DEBUG_OBJECT (parse, "marking DISCONT");
1233         GST_BUFFER_FLAG_SET (tmpbuf, GST_BUFFER_FLAG_DISCONT);
1234       }
1235
1236       skip = -1;
1237       if (bclass->check_valid_frame (parse, tmpbuf, &fsize, &skip)) {
1238         if (gst_adapter_available (parse->adapter) < fsize) {
1239           GST_DEBUG_OBJECT (parse,
1240               "found valid frame but not enough data available (only %d bytes)",
1241               gst_adapter_available (parse->adapter));
1242           gst_buffer_unref (tmpbuf);
1243           goto done;
1244         }
1245         break;
1246       }
1247       if (skip > 0) {
1248         GST_LOG_OBJECT (parse, "finding sync, skipping %d bytes", skip);
1249         gst_adapter_flush (parse->adapter, skip);
1250         parse->priv->offset += skip;
1251         parse->priv->discont = TRUE;
1252       } else if (skip == -1) {
1253         /* subclass didn't touch this value. By default we skip 1 byte */
1254         GST_LOG_OBJECT (parse, "finding sync, skipping 1 byte");
1255         gst_adapter_flush (parse->adapter, 1);
1256         parse->priv->offset++;
1257         parse->priv->discont = TRUE;
1258       }
1259       /* There is a possibility that subclass set the skip value to zero.
1260          This means that it has probably found a frame but wants to ask
1261          more data (by increasing the min_size) to be sure of this. */
1262     }
1263     gst_buffer_unref (tmpbuf);
1264     tmpbuf = NULL;
1265
1266     if (skip > 0) {
1267       /* Subclass found the sync, but still wants to skip some data */
1268       GST_LOG_OBJECT (parse, "skipping %d bytes", skip);
1269       gst_adapter_flush (parse->adapter, skip);
1270       parse->priv->offset += skip;
1271     }
1272
1273     /* Grab lock to prevent a race with FLUSH_START handler */
1274     GST_PAD_STREAM_LOCK (parse->srcpad);
1275
1276     /* FLUSH_START event causes the "flushing" flag to be set. In this
1277      * case we can leave the frame pushing loop */
1278     if (parse->priv->flushing) {
1279       GST_PAD_STREAM_UNLOCK (parse->srcpad);
1280       break;
1281     }
1282
1283     /* FIXME: Would it be more efficient to make a subbuffer instead? */
1284     outbuf = gst_adapter_take_buffer (parse->adapter, fsize);
1285     outbuf = gst_buffer_make_metadata_writable (outbuf);
1286
1287     /* Subclass may want to know the data offset */
1288     GST_BUFFER_OFFSET (outbuf) = parse->priv->offset;
1289     parse->priv->offset += fsize;
1290
1291     /* move along with upstream timestamp (if any),
1292      * but interpolate in between */
1293     timestamp = gst_adapter_prev_timestamp (parse->adapter, NULL);
1294     if (GST_CLOCK_TIME_IS_VALID (timestamp) &&
1295         (parse->priv->prev_ts != timestamp)) {
1296       parse->priv->prev_ts = parse->priv->next_ts = timestamp;
1297     }
1298
1299     ret = gst_base_parse_handle_and_push_buffer (parse, bclass, outbuf);
1300     GST_PAD_STREAM_UNLOCK (parse->srcpad);
1301
1302     if (ret != GST_FLOW_OK) {
1303       GST_LOG_OBJECT (parse, "push returned %d", ret);
1304       break;
1305     }
1306   }
1307
1308 done:
1309   GST_LOG_OBJECT (parse, "chain leaving");
1310   return ret;
1311 }
1312
1313 /* pull @size bytes at current offset,
1314  * i.e. at least try to and possibly return a shorter buffer if near the end */
1315 static GstFlowReturn
1316 gst_base_parse_pull_range (GstBaseParse * parse, guint size,
1317     GstBuffer ** buffer)
1318 {
1319   GstFlowReturn ret = GST_FLOW_OK;
1320
1321   g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
1322
1323   /* Caching here actually makes much less difference than one would expect.
1324    * We do it mainly to avoid pulling buffers of 1 byte all the time */
1325   if (parse->priv->cache) {
1326     guint64 cache_offset = GST_BUFFER_OFFSET (parse->priv->cache);
1327     guint cache_size = GST_BUFFER_SIZE (parse->priv->cache);
1328
1329     if (cache_offset <= parse->priv->offset &&
1330         (parse->priv->offset + size) <= (cache_offset + cache_size)) {
1331       *buffer = gst_buffer_create_sub (parse->priv->cache,
1332           parse->priv->offset - cache_offset, size);
1333       GST_BUFFER_OFFSET (*buffer) = parse->priv->offset;
1334       return GST_FLOW_OK;
1335     }
1336     /* not enough data in the cache, free cache and get a new one */
1337     gst_buffer_unref (parse->priv->cache);
1338     parse->priv->cache = NULL;
1339   }
1340
1341   /* refill the cache */
1342   ret =
1343       gst_pad_pull_range (parse->sinkpad, parse->priv->offset, MAX (size,
1344           64 * 1024), &parse->priv->cache);
1345   if (ret != GST_FLOW_OK) {
1346     parse->priv->cache = NULL;
1347     return ret;
1348   }
1349
1350   if (GST_BUFFER_SIZE (parse->priv->cache) >= size) {
1351     *buffer = gst_buffer_create_sub (parse->priv->cache, 0, size);
1352     GST_BUFFER_OFFSET (*buffer) = parse->priv->offset;
1353     return GST_FLOW_OK;
1354   }
1355
1356   /* Not possible to get enough data, try a last time with
1357    * requesting exactly the size we need */
1358   gst_buffer_unref (parse->priv->cache);
1359   parse->priv->cache = NULL;
1360
1361   ret = gst_pad_pull_range (parse->sinkpad, parse->priv->offset, size,
1362       &parse->priv->cache);
1363
1364   if (ret != GST_FLOW_OK) {
1365     GST_DEBUG_OBJECT (parse, "pull_range returned %d", ret);
1366     *buffer = NULL;
1367     return ret;
1368   }
1369
1370   if (GST_BUFFER_SIZE (parse->priv->cache) < size) {
1371     GST_DEBUG_OBJECT (parse, "Returning short buffer at offset %"
1372         G_GUINT64_FORMAT ": wanted %u bytes, got %u bytes", parse->priv->offset,
1373         size, GST_BUFFER_SIZE (parse->priv->cache));
1374
1375     *buffer = parse->priv->cache;
1376     parse->priv->cache = NULL;
1377
1378     return GST_FLOW_OK;
1379   }
1380
1381   *buffer = gst_buffer_create_sub (parse->priv->cache, 0, size);
1382   GST_BUFFER_OFFSET (*buffer) = parse->priv->offset;
1383
1384   return GST_FLOW_OK;
1385 }
1386
1387 /**
1388  * gst_base_parse_loop:
1389  * @pad: GstPad
1390  *
1391  * Loop that is used in pull mode to retrieve data from upstream.
1392  */
1393 static void
1394 gst_base_parse_loop (GstPad * pad)
1395 {
1396   GstBaseParse *parse;
1397   GstBaseParseClass *klass;
1398   GstBuffer *buffer, *outbuf;
1399   gboolean ret = FALSE;
1400   guint fsize = 0, min_size;
1401   gint skip = 0;
1402
1403   parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
1404   klass = GST_BASE_PARSE_GET_CLASS (parse);
1405
1406   /* TODO: Check if we reach segment stop limit */
1407
1408   while (TRUE) {
1409
1410     GST_BASE_PARSE_LOCK (parse);
1411     min_size = parse->priv->min_frame_size;
1412     GST_BASE_PARSE_UNLOCK (parse);
1413
1414     ret = gst_base_parse_pull_range (parse, min_size, &buffer);
1415
1416     if (ret == GST_FLOW_UNEXPECTED)
1417       goto eos;
1418     else if (ret != GST_FLOW_OK)
1419       goto need_pause;
1420
1421     if (parse->priv->discont) {
1422       GST_DEBUG_OBJECT (parse, "marking DISCONT");
1423       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
1424     }
1425
1426     /* if we got a short read, inform subclass we are draining leftover
1427      * and no more is to be expected */
1428     if (GST_BUFFER_SIZE (buffer) < min_size)
1429       parse->priv->drain = TRUE;
1430
1431     skip = -1;
1432     if (klass->check_valid_frame (parse, buffer, &fsize, &skip)) {
1433       parse->priv->drain = FALSE;
1434       break;
1435     }
1436     parse->priv->drain = FALSE;
1437     if (skip > 0) {
1438       GST_LOG_OBJECT (parse, "finding sync, skipping %d bytes", skip);
1439       parse->priv->offset += skip;
1440       parse->priv->discont = TRUE;
1441     } else if (skip == -1) {
1442       GST_LOG_OBJECT (parse, "finding sync, skipping 1 byte");
1443       parse->priv->offset++;
1444       parse->priv->discont = TRUE;
1445     }
1446     GST_DEBUG_OBJECT (parse, "finding sync...");
1447     gst_buffer_unref (buffer);
1448   }
1449
1450   if (fsize <= GST_BUFFER_SIZE (buffer)) {
1451     outbuf = gst_buffer_create_sub (buffer, 0, fsize);
1452     GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET (buffer);
1453     gst_buffer_unref (buffer);
1454   } else {
1455     gst_buffer_unref (buffer);
1456     ret = gst_base_parse_pull_range (parse, fsize, &outbuf);
1457
1458     if (ret == GST_FLOW_UNEXPECTED)
1459       goto eos;
1460     else if (ret != GST_FLOW_OK)
1461       goto need_pause;
1462     if (GST_BUFFER_SIZE (outbuf) < fsize)
1463       goto eos;
1464   }
1465
1466   parse->priv->offset += fsize;
1467
1468   /* Does the subclass want to skip too? */
1469   if (skip > 0)
1470     parse->priv->offset += skip;
1471
1472   /* This always unrefs the outbuf, even if error occurs */
1473   ret = gst_base_parse_handle_and_push_buffer (parse, klass, outbuf);
1474
1475   if (ret != GST_FLOW_OK) {
1476     GST_DEBUG_OBJECT (parse, "flow: %s", gst_flow_get_name (ret));
1477     if (GST_FLOW_IS_FATAL (ret)) {
1478       GST_ELEMENT_ERROR (parse, STREAM, FAILED, (NULL),
1479           ("streaming task paused, reason: %s", gst_flow_get_name (ret)));
1480       gst_pad_push_event (parse->srcpad, gst_event_new_eos ());
1481     }
1482     goto need_pause;
1483   }
1484
1485   gst_object_unref (parse);
1486   return;
1487
1488 need_pause:
1489   {
1490     GST_LOG_OBJECT (parse, "pausing task %d", ret);
1491     gst_pad_pause_task (pad);
1492     gst_object_unref (parse);
1493     return;
1494   }
1495 eos:
1496   {
1497     GST_LOG_OBJECT (parse, "sending eos");
1498     gst_pad_push_event (parse->srcpad, gst_event_new_eos ());
1499     goto need_pause;
1500   }
1501 }
1502
1503
1504 /**
1505  * gst_base_parse_sink_activate:
1506  * @sinkpad: #GstPad to be activated.
1507  *
1508  * Returns: TRUE if activation succeeded.
1509  */
1510 static gboolean
1511 gst_base_parse_sink_activate (GstPad * sinkpad)
1512 {
1513   GstBaseParse *parse;
1514   gboolean result = TRUE;
1515
1516   parse = GST_BASE_PARSE (gst_pad_get_parent (sinkpad));
1517
1518   GST_DEBUG_OBJECT (parse, "sink activate");
1519
1520   if (gst_pad_check_pull_range (sinkpad)) {
1521     GST_DEBUG_OBJECT (parse, "trying to activate in pull mode");
1522     result = gst_pad_activate_pull (sinkpad, TRUE);
1523   } else {
1524     GST_DEBUG_OBJECT (parse, "trying to activate in push mode");
1525     result = gst_pad_activate_push (sinkpad, TRUE);
1526   }
1527
1528   GST_DEBUG_OBJECT (parse, "sink activate return %d", result);
1529   gst_object_unref (parse);
1530   return result;
1531 }
1532
1533
1534 /**
1535  * gst_base_parse_activate:
1536  * @parse: #GstBaseParse.
1537  * @active: TRUE if element will be activated, FALSE if disactivated.
1538  *
1539  * Returns: TRUE if the operation succeeded.
1540  */
1541 static gboolean
1542 gst_base_parse_activate (GstBaseParse * parse, gboolean active)
1543 {
1544   GstBaseParseClass *klass;
1545   gboolean result = FALSE;
1546
1547   GST_DEBUG_OBJECT (parse, "activate");
1548
1549   klass = GST_BASE_PARSE_GET_CLASS (parse);
1550
1551   if (active) {
1552     if (parse->priv->pad_mode == GST_ACTIVATE_NONE && klass->start)
1553       result = klass->start (parse);
1554
1555     GST_OBJECT_LOCK (parse);
1556     gst_segment_init (&parse->segment, GST_FORMAT_TIME);
1557     parse->priv->duration = -1;
1558     parse->priv->discont = TRUE;
1559     parse->priv->flushing = FALSE;
1560     parse->priv->offset = 0;
1561     parse->priv->update_interval = 0;
1562     parse->priv->fps_num = parse->priv->fps_den = 0;
1563     parse->priv->frame_duration = GST_CLOCK_TIME_NONE;
1564     parse->priv->framecount = 0;
1565     parse->priv->bytecount = 0;
1566     parse->priv->acc_duration = 0;
1567     parse->priv->estimated_duration = -1;
1568     parse->priv->next_ts = 0;
1569     parse->priv->passthrough = FALSE;
1570     parse->priv->post_min_bitrate = TRUE;
1571     parse->priv->post_avg_bitrate = TRUE;
1572     parse->priv->post_max_bitrate = TRUE;
1573     parse->priv->min_bitrate = G_MAXUINT;
1574     parse->priv->max_bitrate = 0;
1575     parse->priv->max_bitrate = 0;
1576
1577     if (parse->pending_segment)
1578       gst_event_unref (parse->pending_segment);
1579
1580     parse->pending_segment =
1581         gst_event_new_new_segment (FALSE, parse->segment.rate,
1582         parse->segment.format,
1583         parse->segment.start, parse->segment.stop, parse->segment.last_stop);
1584
1585     GST_OBJECT_UNLOCK (parse);
1586   } else {
1587     /* We must make sure streaming has finished before resetting things
1588      * and calling the ::stop vfunc */
1589     GST_PAD_STREAM_LOCK (parse->sinkpad);
1590     GST_PAD_STREAM_UNLOCK (parse->sinkpad);
1591
1592     if (parse->priv->pad_mode != GST_ACTIVATE_NONE && klass->stop)
1593       result = klass->stop (parse);
1594
1595     g_list_foreach (parse->priv->pending_events, (GFunc) gst_mini_object_unref,
1596         NULL);
1597     g_list_free (parse->priv->pending_events);
1598     parse->priv->pending_events = NULL;
1599
1600     if (parse->priv->cache) {
1601       gst_buffer_unref (parse->priv->cache);
1602       parse->priv->cache = NULL;
1603     }
1604
1605     parse->priv->pad_mode = GST_ACTIVATE_NONE;
1606   }
1607   GST_DEBUG_OBJECT (parse, "activate: %d", result);
1608   return result;
1609 }
1610
1611
1612 /**
1613  * gst_base_parse_sink_activate_push:
1614  * @pad: #GstPad to be (de)activated.
1615  * @active: TRUE when activating, FALSE when deactivating.
1616  *
1617  * Returns: TRUE if (de)activation succeeded.
1618  */
1619 static gboolean
1620 gst_base_parse_sink_activate_push (GstPad * pad, gboolean active)
1621 {
1622   gboolean result = TRUE;
1623   GstBaseParse *parse;
1624
1625   parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
1626
1627   GST_DEBUG_OBJECT (parse, "sink activate push");
1628
1629   result = gst_base_parse_activate (parse, active);
1630
1631   if (result)
1632     parse->priv->pad_mode = active ? GST_ACTIVATE_PUSH : GST_ACTIVATE_NONE;
1633
1634   GST_DEBUG_OBJECT (parse, "sink activate push: %d", result);
1635
1636   gst_object_unref (parse);
1637   return result;
1638 }
1639
1640
1641 /**
1642  * gst_base_parse_sink_activate_pull:
1643  * @sinkpad: #GstPad to be (de)activated.
1644  * @active: TRUE when activating, FALSE when deactivating.
1645  *
1646  * Returns: TRUE if (de)activation succeeded.
1647  */
1648 static gboolean
1649 gst_base_parse_sink_activate_pull (GstPad * sinkpad, gboolean active)
1650 {
1651   gboolean result = FALSE;
1652   GstBaseParse *parse;
1653
1654   parse = GST_BASE_PARSE (gst_pad_get_parent (sinkpad));
1655
1656   GST_DEBUG_OBJECT (parse, "activate pull");
1657
1658   result = gst_base_parse_activate (parse, active);
1659
1660   if (result) {
1661     if (active) {
1662       result &= gst_pad_start_task (sinkpad,
1663           (GstTaskFunction) gst_base_parse_loop, sinkpad);
1664     } else {
1665       result &= gst_pad_stop_task (sinkpad);
1666     }
1667   }
1668
1669   if (result)
1670     parse->priv->pad_mode = active ? GST_ACTIVATE_PULL : GST_ACTIVATE_NONE;
1671
1672   GST_DEBUG_OBJECT (parse, "sink activate pull: %d", result);
1673
1674   gst_object_unref (parse);
1675   return result;
1676 }
1677
1678
1679 /**
1680  * gst_base_parse_set_duration:
1681  * @parse: #GstBaseParse.
1682  * @fmt: #GstFormat.
1683  * @duration: duration value.
1684  *
1685  * Sets the duration of the currently playing media. Subclass can use this
1686  * when it notices a change in the media duration.
1687  */
1688 void
1689 gst_base_parse_set_duration (GstBaseParse * parse,
1690     GstFormat fmt, gint64 duration)
1691 {
1692   g_return_if_fail (parse != NULL);
1693
1694   GST_BASE_PARSE_LOCK (parse);
1695   if (duration != parse->priv->duration) {
1696     GstMessage *m;
1697
1698     m = gst_message_new_duration (GST_OBJECT (parse), fmt, duration);
1699     gst_element_post_message (GST_ELEMENT (parse), m);
1700
1701     /* TODO: what about duration tag? */
1702   }
1703   parse->priv->duration = duration;
1704   parse->priv->duration_fmt = fmt;
1705   GST_DEBUG_OBJECT (parse, "set duration: %" G_GINT64_FORMAT, duration);
1706   GST_BASE_PARSE_UNLOCK (parse);
1707 }
1708
1709
1710 /**
1711  * gst_base_parse_set_min_frame_size:
1712  * @parse: #GstBaseParse.
1713  * @min_size: Minimum size of the data that this base class should give to
1714  *            subclass.
1715  *
1716  * Subclass can use this function to tell the base class that it needs to
1717  * give at least #min_size buffers.
1718  */
1719 void
1720 gst_base_parse_set_min_frame_size (GstBaseParse * parse, guint min_size)
1721 {
1722   g_return_if_fail (parse != NULL);
1723
1724   GST_BASE_PARSE_LOCK (parse);
1725   parse->priv->min_frame_size = min_size;
1726   GST_LOG_OBJECT (parse, "set frame_min_size: %d", min_size);
1727   GST_BASE_PARSE_UNLOCK (parse);
1728 }
1729
1730 /**
1731  * gst_base_transform_set_passthrough:
1732  * @trans: the #GstBaseParse to set
1733  * @passthrough: boolean indicating passthrough mode.
1734  *
1735  * Set passthrough mode for this parser.  If operating in passthrough,
1736  * incoming buffers are pushed through unmodified.
1737  */
1738 void
1739 gst_base_parse_set_passthrough (GstBaseParse * parse, gboolean passthrough)
1740 {
1741   g_return_if_fail (parse != NULL);
1742
1743   GST_BASE_PARSE_LOCK (parse);
1744   parse->priv->passthrough = passthrough;
1745   GST_LOG_OBJECT (parse, "set passthrough: %d", passthrough);
1746   GST_BASE_PARSE_UNLOCK (parse);
1747 }
1748
1749 /**
1750  * gst_base_transform_set_frame_props:
1751  * @parse: the #GstBaseParse to set
1752  * @fps_num: frames per second (numerator).
1753  * @fps_den: frames per second (denominator).
1754  * @interval: duration update interval in frames.
1755  *
1756  * If frames per second is configured, parser can provide for default @convert
1757  * between GST_FORMAT_TIME and GST_FORMAT_BYTES, as well as buffer duration
1758  * and timestamping.  However, even if this frame information is provided,
1759  * subclass can still choose to provide for a @convert and set buffer metadata.
1760  * If #interval is non-zero (default), then stream duration is determined
1761  * based on frame and byte counts, and updated every #interval frames.
1762  */
1763 void
1764 gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num,
1765     guint fps_den, gint interval)
1766 {
1767   g_return_if_fail (parse != NULL);
1768
1769   GST_BASE_PARSE_LOCK (parse);
1770   parse->priv->fps_num = fps_num;
1771   parse->priv->fps_den = fps_den;
1772   parse->priv->update_interval = interval;
1773   if (!fps_num || !fps_den) {
1774     GST_DEBUG_OBJECT (parse, "invalid fps (%d/%d), ignoring parameters",
1775         fps_num, fps_den);
1776     fps_num = fps_den = 0;
1777     interval = 0;
1778     parse->priv->frame_duration = GST_CLOCK_TIME_NONE;
1779   } else {
1780     parse->priv->frame_duration =
1781         gst_util_uint64_scale (GST_SECOND, parse->priv->fps_den,
1782         parse->priv->fps_num);
1783   }
1784   GST_LOG_OBJECT (parse, "set fps: %d/%d => duration: %" G_GINT64_FORMAT " ms",
1785       fps_num, fps_den, parse->priv->frame_duration / GST_MSECOND);
1786   GST_LOG_OBJECT (parse, "set update interval: %d", interval);
1787   GST_BASE_PARSE_UNLOCK (parse);
1788 }
1789
1790 /**
1791  * gst_base_transform_get_sync:
1792  * @parse: the #GstBaseParse to query
1793  *
1794  * Returns: TRUE if parser is considered 'in sync'.  That is, frames have been
1795  * continuously successfully parsed and pushed.
1796  */
1797 gboolean
1798 gst_base_parse_get_sync (GstBaseParse * parse)
1799 {
1800   gboolean ret;
1801
1802   g_return_val_if_fail (parse != NULL, FALSE);
1803
1804   GST_BASE_PARSE_LOCK (parse);
1805   /* losing sync is pretty much a discont (and vice versa), no ? */
1806   ret = !parse->priv->discont;
1807   GST_BASE_PARSE_UNLOCK (parse);
1808
1809   GST_DEBUG_OBJECT (parse, "sync: %d", ret);
1810   return ret;
1811 }
1812
1813 /**
1814  * gst_base_transform_get_drain:
1815  * @parse: the #GstBaseParse to query
1816  *
1817  * Returns: TRUE if parser is currently 'draining'.  That is, leftover data
1818  * (e.g. in FLUSH or EOS situation) is being parsed.
1819  */
1820 gboolean
1821 gst_base_parse_get_drain (GstBaseParse * parse)
1822 {
1823   gboolean ret;
1824
1825   g_return_val_if_fail (parse != NULL, FALSE);
1826
1827   GST_BASE_PARSE_LOCK (parse);
1828   /* losing sync is pretty much a discont (and vice versa), no ? */
1829   ret = parse->priv->drain;
1830   GST_BASE_PARSE_UNLOCK (parse);
1831
1832   GST_DEBUG_OBJECT (parse, "drain: %d", ret);
1833   return ret;
1834 }
1835
1836 /**
1837  * gst_base_parse_get_querytypes:
1838  * @pad: GstPad
1839  *
1840  * Returns: A table of #GstQueryType items describing supported query types.
1841  */
1842 static const GstQueryType *
1843 gst_base_parse_get_querytypes (GstPad * pad)
1844 {
1845   static const GstQueryType list[] = {
1846     GST_QUERY_POSITION,
1847     GST_QUERY_DURATION,
1848     GST_QUERY_FORMATS,
1849     GST_QUERY_SEEKING,
1850     GST_QUERY_CONVERT,
1851     0
1852   };
1853
1854   return list;
1855 }
1856
1857
1858 /**
1859  * gst_base_parse_query:
1860  * @pad: #GstPad.
1861  * @query: #GstQuery.
1862  *
1863  * Returns: TRUE on success.
1864  */
1865 static gboolean
1866 gst_base_parse_query (GstPad * pad, GstQuery * query)
1867 {
1868   GstBaseParse *parse;
1869   GstBaseParseClass *klass;
1870   gboolean res = FALSE;
1871
1872   parse = GST_BASE_PARSE (GST_PAD_PARENT (pad));
1873   klass = GST_BASE_PARSE_GET_CLASS (parse);
1874
1875   /* If subclass doesn't provide conversion function we can't reply
1876      to the query either */
1877   if (!klass->convert) {
1878     return FALSE;
1879   }
1880
1881   switch (GST_QUERY_TYPE (query)) {
1882     case GST_QUERY_POSITION:
1883     {
1884       gint64 dest_value;
1885       GstFormat format;
1886
1887       GST_DEBUG_OBJECT (parse, "position query");
1888
1889       gst_query_parse_position (query, &format, NULL);
1890
1891       g_mutex_lock (parse->parse_lock);
1892
1893       if (format == GST_FORMAT_BYTES) {
1894         dest_value = parse->priv->offset;
1895         res = TRUE;
1896       } else if (format == parse->segment.format &&
1897           GST_CLOCK_TIME_IS_VALID (parse->segment.last_stop)) {
1898         dest_value = parse->segment.last_stop;
1899         res = TRUE;
1900       } else {
1901         /* priv->offset is updated in both PUSH/PULL modes */
1902         res = klass->convert (parse, GST_FORMAT_BYTES, parse->priv->offset,
1903             format, &dest_value);
1904       }
1905       g_mutex_unlock (parse->parse_lock);
1906
1907       if (res)
1908         gst_query_set_position (query, format, dest_value);
1909       else
1910         res = gst_pad_query_default (pad, query);
1911
1912       break;
1913     }
1914     case GST_QUERY_DURATION:
1915     {
1916       GstFormat format;
1917       gint64 dest_value;
1918
1919       GST_DEBUG_OBJECT (parse, "duration query");
1920
1921       gst_query_parse_duration (query, &format, NULL);
1922
1923       g_mutex_lock (parse->parse_lock);
1924
1925       if (format == GST_FORMAT_BYTES) {
1926         res = gst_pad_query_peer_duration (parse->sinkpad, &format,
1927             &dest_value);
1928       } else if (parse->priv->duration != -1 &&
1929           format == parse->priv->duration_fmt) {
1930         dest_value = parse->priv->duration;
1931         res = TRUE;
1932       } else if (parse->priv->duration != -1) {
1933         res = klass->convert (parse, parse->priv->duration_fmt,
1934             parse->priv->duration, format, &dest_value);
1935       } else if (parse->priv->estimated_duration != -1) {
1936         dest_value = parse->priv->estimated_duration;
1937         res = TRUE;
1938       }
1939
1940       g_mutex_unlock (parse->parse_lock);
1941
1942       if (res)
1943         gst_query_set_duration (query, format, dest_value);
1944       else
1945         res = gst_pad_query_default (pad, query);
1946       break;
1947     }
1948     case GST_QUERY_SEEKING:
1949     {
1950       GstFormat fmt;
1951       gboolean seekable = FALSE;
1952
1953       GST_DEBUG_OBJECT (parse, "seeking query");
1954
1955       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
1956
1957       if (fmt != GST_FORMAT_TIME) {
1958         return gst_pad_query_default (pad, query);
1959       }
1960
1961       seekable = klass->is_seekable (parse);
1962
1963       /* TODO: could this duration be calculated/converted if subclass
1964          hasn't given it? */
1965       gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0,
1966           (parse->priv->duration == -1) ?
1967           GST_CLOCK_TIME_NONE : parse->priv->duration);
1968
1969       GST_DEBUG_OBJECT (parse, "seekable: %d", seekable);
1970       res = TRUE;
1971       break;
1972     }
1973     case GST_QUERY_FORMATS:
1974       gst_query_set_formatsv (query, 3, fmtlist);
1975       res = TRUE;
1976       break;
1977
1978     case GST_QUERY_CONVERT:
1979     {
1980       GstFormat src_format, dest_format;
1981       gint64 src_value, dest_value;
1982
1983       gst_query_parse_convert (query, &src_format, &src_value,
1984           &dest_format, &dest_value);
1985
1986       /* FIXME: hm? doesn't make sense 
1987        * We require all those values to be given
1988        if (src_format && src_value && dest_format && dest_value ) { */
1989       res = klass->convert (parse, src_format, src_value,
1990           dest_format, &dest_value);
1991       if (res) {
1992         gst_query_set_convert (query, src_format, src_value,
1993             dest_format, dest_value);
1994       }
1995       /*} */
1996       break;
1997     }
1998     default:
1999       res = gst_pad_query_default (pad, query);
2000       break;
2001   }
2002   return res;
2003 }
2004
2005
2006 /**
2007  * gst_base_parse_handle_seek:
2008  * @parse: #GstBaseParse.
2009  * @event: #GstEvent.
2010  *
2011  * Returns: TRUE if seek succeeded.
2012  */
2013 static gboolean
2014 gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event)
2015 {
2016   GstBaseParseClass *klass;
2017   gdouble rate;
2018   GstFormat format;
2019   GstSeekFlags flags;
2020   GstSeekType cur_type = GST_SEEK_TYPE_NONE, stop_type;
2021   gboolean flush, update, res = TRUE;
2022   gint64 cur, stop, seekpos;
2023   GstSegment seeksegment = { 0, };
2024   GstFormat dstformat;
2025
2026   klass = GST_BASE_PARSE_GET_CLASS (parse);
2027
2028   gst_event_parse_seek (event, &rate, &format, &flags,
2029       &cur_type, &cur, &stop_type, &stop);
2030
2031   /* no negative rates yet */
2032   if (rate < 0.0)
2033     goto negative_rate;
2034
2035   if (cur_type != GST_SEEK_TYPE_SET)
2036     goto wrong_type;
2037
2038   /* For any format other than TIME, see if upstream handles
2039    * it directly or fail. For TIME, try upstream, but do it ourselves if
2040    * it fails upstream */
2041   if (format != GST_FORMAT_TIME) {
2042     return gst_pad_push_event (parse->sinkpad, event);
2043   } else {
2044     gst_event_ref (event);
2045     if (gst_pad_push_event (parse->sinkpad, event)) {
2046       gst_event_unref (event);
2047       return TRUE;
2048     }
2049   }
2050
2051   /* to much estimating going on to support this sensibly,
2052    * and no eos/end-of-segment loop handling either ... */
2053   if (stop_type != GST_SEEK_TYPE_NONE || (flags & GST_SEEK_FLAG_SEGMENT))
2054     goto wrong_type;
2055   stop = -1;
2056
2057   /* get flush flag */
2058   flush = flags & GST_SEEK_FLAG_FLUSH;
2059
2060   dstformat = GST_FORMAT_BYTES;
2061   if (!gst_pad_query_convert (parse->srcpad, format, cur, &dstformat, &seekpos)) {
2062     GST_DEBUG_OBJECT (parse, "conversion failed");
2063     return FALSE;
2064   }
2065
2066   GST_DEBUG_OBJECT (parse,
2067       "seek position %" G_GINT64_FORMAT " in bytes: %" G_GINT64_FORMAT, cur,
2068       seekpos);
2069
2070   if (parse->priv->pad_mode == GST_ACTIVATE_PULL) {
2071     gint64 last_stop;
2072
2073     GST_DEBUG_OBJECT (parse, "seek in PULL mode");
2074
2075     if (flush) {
2076       if (parse->srcpad) {
2077         GST_DEBUG_OBJECT (parse, "sending flush start");
2078         gst_pad_push_event (parse->srcpad, gst_event_new_flush_start ());
2079       }
2080     } else {
2081       gst_pad_pause_task (parse->sinkpad);
2082     }
2083
2084     /* we should now be able to grab the streaming thread because we stopped it
2085      * with the above flush/pause code */
2086     GST_PAD_STREAM_LOCK (parse->sinkpad);
2087
2088     /* save current position */
2089     last_stop = parse->segment.last_stop;
2090     GST_DEBUG_OBJECT (parse, "stopped streaming at %" G_GINT64_FORMAT,
2091         last_stop);
2092
2093     /* copy segment, we need this because we still need the old
2094      * segment when we close the current segment. */
2095     memcpy (&seeksegment, &parse->segment, sizeof (GstSegment));
2096
2097     GST_DEBUG_OBJECT (parse, "configuring seek");
2098     gst_segment_set_seek (&seeksegment, rate, format, flags,
2099         cur_type, cur, stop_type, stop, &update);
2100
2101     /* figure out the last position we need to play. If it's configured (stop !=
2102      * -1), use that, else we play until the total duration of the file */
2103     if ((stop = seeksegment.stop) == -1)
2104       stop = seeksegment.duration;
2105
2106     parse->priv->offset = seekpos;
2107
2108     /* prepare for streaming again */
2109     if (flush) {
2110       GST_DEBUG_OBJECT (parse, "sending flush stop");
2111       gst_pad_push_event (parse->srcpad, gst_event_new_flush_stop ());
2112     } else {
2113       if (parse->close_segment)
2114         gst_event_unref (parse->close_segment);
2115
2116       parse->close_segment = gst_event_new_new_segment (TRUE,
2117           parse->segment.rate, parse->segment.format,
2118           parse->segment.accum, parse->segment.last_stop, parse->segment.accum);
2119
2120       /* keep track of our last_stop */
2121       seeksegment.accum = parse->segment.last_stop;
2122
2123       GST_DEBUG_OBJECT (parse, "Created close seg format %d, "
2124           "start = %" GST_TIME_FORMAT ", stop = %" GST_TIME_FORMAT
2125           ", pos = %" GST_TIME_FORMAT, format,
2126           GST_TIME_ARGS (parse->segment.accum),
2127           GST_TIME_ARGS (parse->segment.last_stop),
2128           GST_TIME_ARGS (parse->segment.accum));
2129     }
2130
2131     memcpy (&parse->segment, &seeksegment, sizeof (GstSegment));
2132
2133     /* store the newsegment event so it can be sent from the streaming thread. */
2134     if (parse->pending_segment)
2135       gst_event_unref (parse->pending_segment);
2136
2137     /* This will be sent later in _loop() */
2138     parse->pending_segment =
2139         gst_event_new_new_segment (FALSE, parse->segment.rate,
2140         parse->segment.format,
2141         parse->segment.last_stop, stop, parse->segment.last_stop);
2142
2143     GST_DEBUG_OBJECT (parse, "Created newseg format %d, "
2144         "start = %" GST_TIME_FORMAT ", stop = %" GST_TIME_FORMAT
2145         ", pos = %" GST_TIME_FORMAT, format,
2146         GST_TIME_ARGS (parse->segment.last_stop),
2147         GST_TIME_ARGS (stop), GST_TIME_ARGS (parse->segment.last_stop));
2148
2149     /* mark discont if we are going to stream from another position. */
2150     if (last_stop != parse->segment.last_stop) {
2151       GST_DEBUG_OBJECT (parse,
2152           "mark DISCONT, we did a seek to another position");
2153       parse->priv->discont = TRUE;
2154       parse->priv->next_ts = parse->segment.last_stop;
2155     }
2156
2157     /* Start streaming thread if paused */
2158     gst_pad_start_task (parse->sinkpad,
2159         (GstTaskFunction) gst_base_parse_loop, parse->sinkpad);
2160
2161     GST_PAD_STREAM_UNLOCK (parse->sinkpad);
2162   } else {
2163     GstEvent *new_event;
2164     /* The only thing we need to do in PUSH-mode is to send the
2165        seek event (in bytes) to upstream. Segment / flush handling happens
2166        in corresponding src event handlers */
2167     GST_DEBUG_OBJECT (parse, "seek in PUSH mode");
2168     new_event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flush,
2169         GST_SEEK_TYPE_SET, seekpos, stop_type, stop);
2170
2171     res = gst_pad_push_event (parse->sinkpad, new_event);
2172   }
2173
2174 done:
2175   return res;
2176
2177   /* ERRORS */
2178 negative_rate:
2179   {
2180     GST_DEBUG_OBJECT (parse, "negative playback rates are not supported yet.");
2181     res = FALSE;
2182     goto done;
2183   }
2184 wrong_type:
2185   {
2186     GST_DEBUG_OBJECT (parse, "unsupported seek type.");
2187     res = FALSE;
2188     goto done;
2189   }
2190 }
2191
2192 /**
2193  * gst_base_parse_handle_tag:
2194  * @parse: #GstBaseParse.
2195  * @event: #GstEvent.
2196  *
2197  * Checks if bitrates are available from upstream tags so that we don't
2198  * override them later
2199  */
2200 static void
2201 gst_base_parse_handle_tag (GstBaseParse * parse, GstEvent * event)
2202 {
2203   GstTagList *taglist = NULL;
2204   guint tmp;
2205
2206   gst_event_parse_tag (event, &taglist);
2207
2208   if (gst_tag_list_get_uint (taglist, GST_TAG_MINIMUM_BITRATE, &tmp))
2209     parse->priv->post_min_bitrate = FALSE;
2210   if (gst_tag_list_get_uint (taglist, GST_TAG_BITRATE, &tmp))
2211     parse->priv->post_avg_bitrate = FALSE;
2212   if (gst_tag_list_get_uint (taglist, GST_TAG_MAXIMUM_BITRATE, &tmp))
2213     parse->priv->post_max_bitrate = FALSE;
2214 }
2215
2216 /**
2217  * gst_base_parse_sink_setcaps:
2218  * @pad: #GstPad.
2219  * @caps: #GstCaps.
2220  *
2221  * Returns: TRUE if caps were accepted.
2222  */
2223 static gboolean
2224 gst_base_parse_sink_setcaps (GstPad * pad, GstCaps * caps)
2225 {
2226   GstBaseParse *parse;
2227   GstBaseParseClass *klass;
2228   gboolean res = TRUE;
2229
2230   parse = GST_BASE_PARSE (GST_PAD_PARENT (pad));
2231   klass = GST_BASE_PARSE_GET_CLASS (parse);
2232
2233   GST_DEBUG_OBJECT (parse, "caps: %" GST_PTR_FORMAT, caps);
2234
2235   if (klass->set_sink_caps)
2236     res = klass->set_sink_caps (parse, caps);
2237
2238   parse->negotiated = res;
2239   return res && gst_pad_set_caps (pad, caps);
2240 }