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