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>.
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.
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.
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.
23 * SECTION:gstbaseparse
24 * @short_description: Base class for stream parsers
25 * @see_also: #GstBaseTransform
27 * This base class is for parser elements that process data and splits it
28 * into separate audio/video/whatever frames.
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>
40 * Handles POSITION/DURATION/SEEKING/FORMAT/CONVERT queries
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.
47 * Description of the parsing mechanism:
50 * <itemizedlist><title>Set-up phase</title>
52 * GstBaseParse class calls @set_sink_caps to inform the subclass about
53 * incoming sinkpad caps. Subclass should set the srcpad caps accordingly.
56 * GstBaseParse calls @start to inform subclass that data processing is
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.
65 * GstBaseParse class sets up appropriate data passing mode (pull/push)
66 * and starts to process the data.
72 * <title>Parsing phase</title>
74 * GstBaseParse gathers at least min_frame_size bytes of data either
75 * by pulling it from upstream or collecting buffers into internal
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).
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.
95 * Finally the buffer can be pushed downstream and parsing loop starts
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.
106 * <itemizedlist><title>Shutdown phase</title>
108 * GstBaseParse class calls @stop to inform the subclass that data
109 * parsing will be stopped.
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).
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.
125 * GstBaseParse uses subclasses conversion methods also for seeking. If
126 * subclass doesn't provide @convert function, seeking will get disabled.
128 * Subclass @start and @stop functions will be called to inform the beginning
129 * and end of data processing.
131 * Things that subclass need to take care of:
133 * <listitem><para>Provide pad templates</para></listitem>
135 * Fixate the source pad caps when appropriate
138 * Inform base class how big data chunks should be retrieved. This is
139 * done with @gst_base_parse_set_min_frame_size function.
142 * Examine data chunks passed to subclass with @check_valid_frame
143 * and tell if they contain a valid frame
146 * Set the caps and timestamp to frame that is passed to subclass with
147 * @parse_frame function.
149 * <listitem><para>Provide conversion functions</para></listitem>
151 * Update the duration information with @gst_base_parse_set_duration
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).
171 * - Better segment handling:
172 * - NEWSEGMENT for gaps
173 * - Not NEWSEGMENT starting at 0 but at first frame timestamp
175 * - Seek table generation and subclass seek entry injection
177 * - In push mode provide a queue of adapter-"queued" buffers for upstream
179 * - Queue buffers/events until caps are set
180 * - Let subclass decide if frames outside the segment should be dropped
181 * - Send queries upstream
191 #include "gstbaseparse.h"
193 GST_DEBUG_CATEGORY_STATIC (gst_base_parse_debug);
194 #define GST_CAT_DEFAULT gst_base_parse_debug
196 /* Supported formats */
197 static GstFormat fmtlist[] = {
204 #define GST_BASE_PARSE_GET_PRIVATE(obj) \
205 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BASE_PARSE, GstBaseParsePrivate))
207 struct _GstBaseParsePrivate
209 GstActivateMode pad_mode;
212 GstFormat duration_fmt;
213 gint64 estimated_duration;
215 guint min_frame_size;
216 gboolean passthrough;
217 guint fps_num, fps_den;
218 guint update_interval;
225 GstClockTime next_ts;
226 GstClockTime prev_ts;
227 GstClockTime frame_duration;
231 guint64 acc_duration;
233 GList *pending_events;
238 struct _GstBaseParseClassPrivate
243 static GstElementClass *parent_class = NULL;
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);
252 gst_base_parse_get_type (void)
254 static GType base_parse_type = 0;
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,
264 sizeof (GstBaseParse),
266 (GInstanceInitFunc) gst_base_parse_init,
269 base_parse_type = g_type_register_static (GST_TYPE_ELEMENT,
270 "GstBaseParse", &base_parse_info, G_TYPE_FLAG_ABSTRACT);
272 return base_parse_type;
275 static void gst_base_parse_finalize (GObject * object);
277 static gboolean gst_base_parse_sink_activate (GstPad * sinkpad);
278 static gboolean gst_base_parse_sink_activate_push (GstPad * pad,
280 static gboolean gst_base_parse_sink_activate_pull (GstPad * pad,
282 static gboolean gst_base_parse_handle_seek (GstBaseParse * parse,
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);
291 static GstFlowReturn gst_base_parse_chain (GstPad * pad, GstBuffer * buffer);
292 static void gst_base_parse_loop (GstPad * pad);
294 static gboolean gst_base_parse_check_frame (GstBaseParse * parse,
295 GstBuffer * buffer, guint * framesize, gint * skipsize);
297 static GstFlowReturn gst_base_parse_parse_frame (GstBaseParse * parse,
300 static gboolean gst_base_parse_sink_eventfunc (GstBaseParse * parse,
303 static gboolean gst_base_parse_src_eventfunc (GstBaseParse * parse,
306 static gboolean gst_base_parse_is_seekable (GstBaseParse * parse);
308 gboolean gst_base_parse_convert (GstBaseParse * parse, GstFormat src_format,
309 gint64 src_value, GstFormat dest_format, gint64 * dest_value);
311 static void gst_base_parse_drain (GstBaseParse * parse);
314 gst_base_parse_base_init (gpointer g_class)
316 GstBaseParseClass *klass = GST_BASE_PARSE_CLASS (g_class);
317 GstBaseParseClassPrivate *priv;
319 GST_DEBUG_CATEGORY_INIT (gst_base_parse_debug, "baseparse", 0,
320 "baseparse element");
322 /* TODO: Remove this once GObject supports class private data */
323 priv = g_slice_new0 (GstBaseParseClassPrivate);
325 memcpy (priv, klass->priv, sizeof (GstBaseParseClassPrivate));
330 gst_base_parse_base_finalize (gpointer g_class)
332 GstBaseParseClass *klass = GST_BASE_PARSE_CLASS (g_class);
334 g_slice_free (GstBaseParseClassPrivate, klass->priv);
339 gst_base_parse_finalize (GObject * object)
341 GstBaseParse *parse = GST_BASE_PARSE (object);
344 g_mutex_free (parse->parse_lock);
345 g_object_unref (parse->adapter);
347 if (parse->pending_segment) {
348 p_ev = &parse->pending_segment;
349 gst_event_replace (p_ev, NULL);
351 if (parse->close_segment) {
352 p_ev = &parse->close_segment;
353 gst_event_replace (p_ev, NULL);
356 if (parse->priv->cache) {
357 gst_buffer_unref (parse->priv->cache);
358 parse->priv->cache = NULL;
361 g_list_foreach (parse->priv->pending_events, (GFunc) gst_mini_object_unref,
363 g_list_free (parse->priv->pending_events);
364 parse->priv->pending_events = NULL;
366 G_OBJECT_CLASS (parent_class)->finalize (object);
370 gst_base_parse_class_init (GstBaseParseClass * klass)
372 GObjectClass *gobject_class;
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);
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;
389 gst_base_parse_init (GstBaseParse * parse, GstBaseParseClass * bclass)
391 GstPadTemplate *pad_template;
393 GST_DEBUG_OBJECT (parse, "gst_base_parse_init");
395 parse->priv = GST_BASE_PARSE_GET_PRIVATE (parse);
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);
415 GST_DEBUG_OBJECT (parse, "sinkpad created");
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");
431 parse->parse_lock = g_mutex_new ();
432 parse->adapter = gst_adapter_new ();
433 parse->pending_segment = NULL;
434 parse->close_segment = NULL;
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");
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.
456 * Default callback for check_valid_frame.
458 * Returns: Always TRUE.
461 gst_base_parse_check_frame (GstBaseParse * parse,
462 GstBuffer * buffer, guint * framesize, gint * skipsize)
464 *framesize = GST_BUFFER_SIZE (buffer);
471 * gst_base_parse_parse_frame:
472 * @parse: #GstBaseParse.
473 * @buffer: #GstBuffer.
475 * Default callback for parse_frame.
478 gst_base_parse_parse_frame (GstBaseParse * parse, GstBuffer * buffer)
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;
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;
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.
498 * Convert given byte position into #GstClockTime format.
500 * Returns: TRUE if conversion succeeded.
503 gst_base_parse_bytepos_to_time (GstBaseParse * parse, gint64 bytepos,
504 GstClockTime * pos_in_time)
506 GstBaseParseClass *klass;
507 gboolean res = FALSE;
509 klass = GST_BASE_PARSE_GET_CLASS (parse);
511 if (klass->convert) {
512 res = klass->convert (parse, GST_FORMAT_BYTES, bytepos,
513 GST_FORMAT_TIME, (gint64 *) pos_in_time);
520 * gst_base_parse_sink_event:
521 * @pad: #GstPad that received the event.
522 * @event: #GstEvent to be handled.
524 * Handler for sink pad events.
526 * Returns: TRUE if the event was handled.
529 gst_base_parse_sink_event (GstPad * pad, GstEvent * event)
532 GstBaseParseClass *bclass;
533 gboolean handled = FALSE;
537 parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
538 bclass = GST_BASE_PARSE_GET_CLASS (parse);
540 GST_DEBUG_OBJECT (parse, "handling event %d", GST_EVENT_TYPE (event));
542 /* Cache all events except EOS, NEWSEGMENT and FLUSH_STOP if we have a
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);
554 handled = bclass->event (parse, event);
557 ret = gst_pad_event_default (pad, event);
560 gst_object_unref (parse);
561 GST_DEBUG_OBJECT (parse, "event handled");
567 * gst_base_parse_sink_eventfunc:
568 * @parse: #GstBaseParse.
569 * @event: #GstEvent to be handled.
571 * Element-level event handler function.
573 * Returns: TRUE if the event was handled and not need forwarding.
576 gst_base_parse_sink_eventfunc (GstBaseParse * parse, GstEvent * event)
578 gboolean handled = FALSE;
581 switch (GST_EVENT_TYPE (event)) {
582 case GST_EVENT_NEWSEGMENT:
584 gdouble rate, applied_rate;
586 gint64 start, stop, pos, offset = 0;
589 gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
590 &format, &start, &stop, &pos);
593 if (format == GST_FORMAT_BYTES) {
594 GstClockTime seg_start, seg_stop, seg_pos;
596 /* stop time is allowed to be open-ended, but not start & pos */
597 seg_stop = GST_CLOCK_TIME_NONE;
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));
613 if (format != GST_FORMAT_TIME) {
614 /* Unknown incoming segment format. Output a default open-ended
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);
621 gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
622 &format, &start, &stop, &pos);
624 gst_segment_set_newsegment_full (&parse->segment, update, rate,
625 applied_rate, format, start, stop, pos);
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));
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
635 eventp = &parse->pending_segment;
636 gst_event_replace (eventp, event);
637 gst_event_unref (event);
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;
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);
658 case GST_EVENT_FLUSH_STOP:
659 gst_adapter_clear (parse->adapter);
660 parse->priv->flushing = FALSE;
661 parse->priv->discont = TRUE;
665 gst_base_parse_drain (parse);
677 * gst_base_parse_src_event:
678 * @pad: #GstPad that received the event.
679 * @event: #GstEvent that was received.
681 * Handler for source pad events.
683 * Returns: TRUE if the event was handled.
686 gst_base_parse_src_event (GstPad * pad, GstEvent * event)
689 GstBaseParseClass *bclass;
690 gboolean handled = FALSE;
693 parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
694 bclass = GST_BASE_PARSE_GET_CLASS (parse);
696 GST_DEBUG_OBJECT (parse, "event %d, %s", GST_EVENT_TYPE (event),
697 GST_EVENT_TYPE_NAME (event));
699 if (bclass->src_event)
700 handled = bclass->src_event (parse, event);
703 ret = gst_pad_event_default (pad, event);
705 gst_object_unref (parse);
711 * gst_base_parse_src_eventfunc:
712 * @parse: #GstBaseParse.
713 * @event: #GstEvent that was received.
715 * Default srcpad event handler.
717 * Returns: TRUE if the event was handled and can be dropped.
720 gst_base_parse_src_eventfunc (GstBaseParse * parse, GstEvent * event)
722 gboolean handled = FALSE;
723 GstBaseParseClass *bclass;
725 bclass = GST_BASE_PARSE_GET_CLASS (parse);
727 switch (GST_EVENT_TYPE (event)) {
730 if (bclass->is_seekable (parse)) {
731 handled = gst_base_parse_handle_seek (parse, event);
732 gst_event_unref (event);
744 * gst_base_parse_is_seekable:
745 * @parse: #GstBaseParse.
747 * Default handler for is_seekable.
749 * Returns: Always TRUE.
752 gst_base_parse_is_seekable (GstBaseParse * parse)
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.
765 * Implementation of "convert" vmethod in #GstBaseParse class.
767 * Returns: TRUE if conversion was successful.
770 gst_base_parse_convert (GstBaseParse * parse,
771 GstFormat src_format,
772 gint64 src_value, GstFormat dest_format, gint64 * dest_value)
774 gboolean ret = FALSE;
775 guint64 bytes, duration;
777 if (G_UNLIKELY (src_format == dest_format)) {
778 *dest_value = src_value;
782 if (G_UNLIKELY (src_value == -1)) {
787 /* need at least some frames */
788 if (!parse->priv->framecount)
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;
796 duration = parse->priv->acc_duration / GST_MSECOND;
797 bytes = parse->priv->bytecount;
800 if (G_UNLIKELY (!duration || !bytes))
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");
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);
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,
819 GST_DEBUG_OBJECT (parse,
820 "time %" G_GINT64_FORMAT " ms in bytes = %" G_GINT64_FORMAT,
821 src_value / GST_MSECOND, *dest_value);
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);
832 } else if (dest_format == GST_FORMAT_BYTES) {
840 * gst_base_parse_update_duration:
841 * @parse: #GstBaseParse.
845 gst_base_parse_update_duration (GstBaseParse * aacparse)
849 GstBaseParseClass *klass;
851 parse = GST_BASE_PARSE (aacparse);
852 klass = GST_BASE_PARSE_GET_CLASS (parse);
854 /* must be able to convert */
858 peer = gst_pad_get_peer (parse->sinkpad);
860 GstFormat pformat = GST_FORMAT_BYTES;
861 gboolean qres = FALSE;
862 gint64 ptot, dest_value;
864 qres = gst_pad_query_duration (peer, &pformat, &ptot);
865 gst_object_unref (GST_OBJECT (peer));
867 if (klass->convert (parse, pformat, ptot, GST_FORMAT_TIME, &dest_value))
868 parse->priv->estimated_duration = dest_value;
874 * gst_base_parse_handle_and_push_buffer:
875 * @parse: #GstBaseParse.
876 * @klass: #GstBaseParseClass.
877 * @buffer: #GstBuffer.
879 * Parses the frame from given buffer and pushes it forward. Also performs
880 * timestamp handling and checks the segment limits.
882 * This is called with srcpad STREAM_LOCK held.
884 * Returns: #GstFlowReturn
887 gst_base_parse_handle_and_push_buffer (GstBaseParse * parse,
888 GstBaseParseClass * klass, GstBuffer * buffer)
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;
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));
904 ret = klass->parse_frame (parse, buffer);
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);
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;
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);
925 } else if (ret != GST_FLOW_OK) {
929 return gst_base_parse_push_buffer (parse, buffer);
933 * gst_base_parse_push_buffer:
934 * @parse: #GstBaseParse.
935 * @buffer: #GstBuffer.
937 * Pushes the buffer downstream, sends any pending events and
938 * does some timestamp and segment handling.
940 * This must be called with srcpad STREAM_LOCK held.
942 * Returns: #GstFlowReturn
945 gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer)
947 GstFlowReturn ret = GST_FLOW_OK;
948 GstClockTime last_stop = GST_CLOCK_TIME_NONE;
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)));
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);
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);
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);
974 /* should have caps by now */
975 g_return_val_if_fail (GST_PAD_CAPS (parse->srcpad), GST_FLOW_ERROR);
977 gst_buffer_set_caps (buffer, GST_PAD_CAPS (parse->srcpad));
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);
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;
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;
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;
1013 if (G_UNLIKELY (parse->priv->pending_events)) {
1016 for (l = parse->priv->pending_events; l != NULL; l = l->next) {
1017 gst_pad_push_event (parse->srcpad, GST_EVENT (l->data));
1019 g_list_free (parse->priv->pending_events);
1020 parse->priv->pending_events = NULL;
1023 /* TODO: Add to seek table */
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);
1040 ret = gst_pad_push (parse->srcpad, buffer);
1041 GST_LOG_OBJECT (parse, "frame (%d bytes) pushed: %d",
1042 GST_BUFFER_SIZE (buffer), ret);
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);
1054 * gst_base_parse_drain:
1055 * @parse: #GstBaseParse.
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.
1062 gst_base_parse_drain (GstBaseParse * parse)
1066 GST_DEBUG_OBJECT (parse, "draining");
1067 parse->priv->drain = TRUE;
1070 avail = gst_adapter_available (parse->adapter);
1074 if (gst_base_parse_chain (parse->sinkpad, NULL) != GST_FLOW_OK) {
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);
1085 parse->priv->drain = FALSE;
1090 * gst_base_parse_chain:
1092 * @buffer: #GstBuffer.
1094 * Returns: #GstFlowReturn.
1096 static GstFlowReturn
1097 gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
1099 GstBaseParseClass *bclass;
1100 GstBaseParse *parse;
1101 GstFlowReturn ret = GST_FLOW_OK;
1102 GstBuffer *outbuf = NULL;
1103 GstBuffer *tmpbuf = NULL;
1108 GstClockTime timestamp;
1110 parse = GST_BASE_PARSE (GST_OBJECT_PARENT (pad));
1111 bclass = GST_BASE_PARSE_GET_CLASS (parse);
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);
1120 gst_adapter_push (parse->adapter, buffer);
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 ();
1128 /* Synchronization loop */
1130 GST_BASE_PARSE_LOCK (parse);
1131 min_size = parse->priv->min_frame_size;
1132 GST_BASE_PARSE_UNLOCK (parse);
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);
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);
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);
1157 if (parse->priv->discont) {
1158 GST_DEBUG_OBJECT (parse, "marking DISCONT");
1159 GST_BUFFER_FLAG_SET (tmpbuf, GST_BUFFER_FLAG_DISCONT);
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);
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;
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. */
1189 gst_buffer_unref (tmpbuf);
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;
1199 /* Grab lock to prevent a race with FLUSH_START handler */
1200 GST_PAD_STREAM_LOCK (parse->srcpad);
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);
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);
1213 /* Subclass may want to know the data offset */
1214 GST_BUFFER_OFFSET (outbuf) = parse->priv->offset;
1215 parse->priv->offset += fsize;
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;
1225 ret = gst_base_parse_handle_and_push_buffer (parse, bclass, outbuf);
1226 GST_PAD_STREAM_UNLOCK (parse->srcpad);
1228 if (ret != GST_FLOW_OK) {
1229 GST_LOG_OBJECT (parse, "push returned %d", ret);
1235 GST_LOG_OBJECT (parse, "chain leaving");
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)
1245 GstFlowReturn ret = GST_FLOW_OK;
1247 g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
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);
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;
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;
1267 /* refill the cache */
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;
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;
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;
1287 ret = gst_pad_pull_range (parse->sinkpad, parse->priv->offset, size,
1288 &parse->priv->cache);
1290 if (ret != GST_FLOW_OK) {
1291 GST_DEBUG_OBJECT (parse, "pull_range returned %d", ret);
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));
1301 *buffer = parse->priv->cache;
1302 parse->priv->cache = NULL;
1307 *buffer = gst_buffer_create_sub (parse->priv->cache, 0, size);
1308 GST_BUFFER_OFFSET (*buffer) = parse->priv->offset;
1314 * gst_base_parse_loop:
1317 * Loop that is used in pull mode to retrieve data from upstream.
1320 gst_base_parse_loop (GstPad * pad)
1322 GstBaseParse *parse;
1323 GstBaseParseClass *klass;
1324 GstBuffer *buffer, *outbuf;
1325 gboolean ret = FALSE;
1326 guint fsize = 0, min_size;
1329 parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
1330 klass = GST_BASE_PARSE_GET_CLASS (parse);
1332 /* TODO: Check if we reach segment stop limit */
1336 GST_BASE_PARSE_LOCK (parse);
1337 min_size = parse->priv->min_frame_size;
1338 GST_BASE_PARSE_UNLOCK (parse);
1340 ret = gst_base_parse_pull_range (parse, min_size, &buffer);
1342 if (ret == GST_FLOW_UNEXPECTED)
1344 else if (ret != GST_FLOW_OK)
1347 if (parse->priv->discont) {
1348 GST_DEBUG_OBJECT (parse, "marking DISCONT");
1349 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
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;
1358 if (klass->check_valid_frame (parse, buffer, &fsize, &skip)) {
1359 parse->priv->drain = FALSE;
1362 parse->priv->drain = FALSE;
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;
1372 GST_DEBUG_OBJECT (parse, "finding sync...");
1373 gst_buffer_unref (buffer);
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);
1381 gst_buffer_unref (buffer);
1382 ret = gst_base_parse_pull_range (parse, fsize, &outbuf);
1384 if (ret == GST_FLOW_UNEXPECTED)
1386 else if (ret != GST_FLOW_OK)
1388 if (GST_BUFFER_SIZE (outbuf) < fsize)
1392 parse->priv->offset += fsize;
1394 /* Does the subclass want to skip too? */
1396 parse->priv->offset += skip;
1398 /* This always unrefs the outbuf, even if error occurs */
1399 ret = gst_base_parse_handle_and_push_buffer (parse, klass, outbuf);
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 ());
1411 gst_object_unref (parse);
1416 GST_LOG_OBJECT (parse, "pausing task %d", ret);
1417 gst_pad_pause_task (pad);
1418 gst_object_unref (parse);
1423 GST_LOG_OBJECT (parse, "sending eos");
1424 gst_pad_push_event (parse->srcpad, gst_event_new_eos ());
1431 * gst_base_parse_sink_activate:
1432 * @sinkpad: #GstPad to be activated.
1434 * Returns: TRUE if activation succeeded.
1437 gst_base_parse_sink_activate (GstPad * sinkpad)
1439 GstBaseParse *parse;
1440 gboolean result = TRUE;
1442 parse = GST_BASE_PARSE (gst_pad_get_parent (sinkpad));
1444 GST_DEBUG_OBJECT (parse, "sink activate");
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);
1450 GST_DEBUG_OBJECT (parse, "trying to activate in push mode");
1451 result = gst_pad_activate_push (sinkpad, TRUE);
1454 GST_DEBUG_OBJECT (parse, "sink activate return %d", result);
1455 gst_object_unref (parse);
1461 * gst_base_parse_activate:
1462 * @parse: #GstBaseParse.
1463 * @active: TRUE if element will be activated, FALSE if disactivated.
1465 * Returns: TRUE if the operation succeeded.
1468 gst_base_parse_activate (GstBaseParse * parse, gboolean active)
1470 GstBaseParseClass *klass;
1471 gboolean result = FALSE;
1473 GST_DEBUG_OBJECT (parse, "activate");
1475 klass = GST_BASE_PARSE_GET_CLASS (parse);
1478 if (parse->priv->pad_mode == GST_ACTIVATE_NONE && klass->start)
1479 result = klass->start (parse);
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;
1497 if (parse->pending_segment)
1498 gst_event_unref (parse->pending_segment);
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);
1505 GST_OBJECT_UNLOCK (parse);
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);
1512 if (parse->priv->pad_mode != GST_ACTIVATE_NONE && klass->stop)
1513 result = klass->stop (parse);
1515 g_list_foreach (parse->priv->pending_events, (GFunc) gst_mini_object_unref,
1517 g_list_free (parse->priv->pending_events);
1518 parse->priv->pending_events = NULL;
1520 if (parse->priv->cache) {
1521 gst_buffer_unref (parse->priv->cache);
1522 parse->priv->cache = NULL;
1525 parse->priv->pad_mode = GST_ACTIVATE_NONE;
1527 GST_DEBUG_OBJECT (parse, "activate: %d", result);
1533 * gst_base_parse_sink_activate_push:
1534 * @pad: #GstPad to be (de)activated.
1535 * @active: TRUE when activating, FALSE when deactivating.
1537 * Returns: TRUE if (de)activation succeeded.
1540 gst_base_parse_sink_activate_push (GstPad * pad, gboolean active)
1542 gboolean result = TRUE;
1543 GstBaseParse *parse;
1545 parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
1547 GST_DEBUG_OBJECT (parse, "sink activate push");
1549 result = gst_base_parse_activate (parse, active);
1552 parse->priv->pad_mode = active ? GST_ACTIVATE_PUSH : GST_ACTIVATE_NONE;
1554 GST_DEBUG_OBJECT (parse, "sink activate push: %d", result);
1556 gst_object_unref (parse);
1562 * gst_base_parse_sink_activate_pull:
1563 * @sinkpad: #GstPad to be (de)activated.
1564 * @active: TRUE when activating, FALSE when deactivating.
1566 * Returns: TRUE if (de)activation succeeded.
1569 gst_base_parse_sink_activate_pull (GstPad * sinkpad, gboolean active)
1571 gboolean result = FALSE;
1572 GstBaseParse *parse;
1574 parse = GST_BASE_PARSE (gst_pad_get_parent (sinkpad));
1576 GST_DEBUG_OBJECT (parse, "activate pull");
1578 result = gst_base_parse_activate (parse, active);
1582 result &= gst_pad_start_task (sinkpad,
1583 (GstTaskFunction) gst_base_parse_loop, sinkpad);
1585 result &= gst_pad_stop_task (sinkpad);
1590 parse->priv->pad_mode = active ? GST_ACTIVATE_PULL : GST_ACTIVATE_NONE;
1592 GST_DEBUG_OBJECT (parse, "sink activate pull: %d", result);
1594 gst_object_unref (parse);
1600 * gst_base_parse_set_duration:
1601 * @parse: #GstBaseParse.
1603 * @duration: duration value.
1605 * Sets the duration of the currently playing media. Subclass can use this
1606 * when it notices a change in the media duration.
1609 gst_base_parse_set_duration (GstBaseParse * parse,
1610 GstFormat fmt, gint64 duration)
1612 g_return_if_fail (parse != NULL);
1614 GST_BASE_PARSE_LOCK (parse);
1615 if (duration != parse->priv->duration) {
1618 m = gst_message_new_duration (GST_OBJECT (parse), fmt, duration);
1619 gst_element_post_message (GST_ELEMENT (parse), m);
1621 /* TODO: what about duration tag? */
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);
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
1636 * Subclass can use this function to tell the base class that it needs to
1637 * give at least #min_size buffers.
1640 gst_base_parse_set_min_frame_size (GstBaseParse * parse, guint min_size)
1642 g_return_if_fail (parse != NULL);
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);
1651 * gst_base_transform_set_passthrough:
1652 * @trans: the #GstBaseParse to set
1653 * @passthrough: boolean indicating passthrough mode.
1655 * Set passthrough mode for this parser. If operating in passthrough,
1656 * incoming buffers are pushed through unmodified.
1659 gst_base_parse_set_passthrough (GstBaseParse * parse, gboolean passthrough)
1661 g_return_if_fail (parse != NULL);
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);
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.
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.
1684 gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num,
1685 guint fps_den, gint interval)
1687 g_return_if_fail (parse != NULL);
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",
1696 fps_num = fps_den = 0;
1698 parse->priv->frame_duration = GST_CLOCK_TIME_NONE;
1700 parse->priv->frame_duration =
1701 gst_util_uint64_scale (GST_SECOND, parse->priv->fps_den,
1702 parse->priv->fps_num);
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);
1711 * gst_base_transform_get_sync:
1712 * @parse: the #GstBaseParse to query
1714 * Returns: TRUE if parser is considered 'in sync'. That is, frames have been
1715 * continuously successfully parsed and pushed.
1718 gst_base_parse_get_sync (GstBaseParse * parse)
1722 g_return_val_if_fail (parse != NULL, FALSE);
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);
1729 GST_DEBUG_OBJECT (parse, "sync: %d", ret);
1734 * gst_base_transform_get_drain:
1735 * @parse: the #GstBaseParse to query
1737 * Returns: TRUE if parser is currently 'draining'. That is, leftover data
1738 * (e.g. in FLUSH or EOS situation) is being parsed.
1741 gst_base_parse_get_drain (GstBaseParse * parse)
1745 g_return_val_if_fail (parse != NULL, FALSE);
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);
1752 GST_DEBUG_OBJECT (parse, "drain: %d", ret);
1757 * gst_base_parse_get_querytypes:
1760 * Returns: A table of #GstQueryType items describing supported query types.
1762 static const GstQueryType *
1763 gst_base_parse_get_querytypes (GstPad * pad)
1765 static const GstQueryType list[] = {
1779 * gst_base_parse_query:
1781 * @query: #GstQuery.
1783 * Returns: TRUE on success.
1786 gst_base_parse_query (GstPad * pad, GstQuery * query)
1788 GstBaseParse *parse;
1789 GstBaseParseClass *klass;
1790 gboolean res = FALSE;
1792 parse = GST_BASE_PARSE (GST_PAD_PARENT (pad));
1793 klass = GST_BASE_PARSE_GET_CLASS (parse);
1795 /* If subclass doesn't provide conversion function we can't reply
1796 to the query either */
1797 if (!klass->convert) {
1801 switch (GST_QUERY_TYPE (query)) {
1802 case GST_QUERY_POSITION:
1807 GST_DEBUG_OBJECT (parse, "position query");
1809 gst_query_parse_position (query, &format, NULL);
1811 g_mutex_lock (parse->parse_lock);
1813 if (format == GST_FORMAT_BYTES) {
1814 dest_value = parse->priv->offset;
1816 } else if (format == parse->segment.format &&
1817 GST_CLOCK_TIME_IS_VALID (parse->segment.last_stop)) {
1818 dest_value = parse->segment.last_stop;
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);
1825 g_mutex_unlock (parse->parse_lock);
1828 gst_query_set_position (query, format, dest_value);
1830 res = gst_pad_query_default (pad, query);
1834 case GST_QUERY_DURATION:
1839 GST_DEBUG_OBJECT (parse, "duration query");
1841 gst_query_parse_duration (query, &format, NULL);
1843 g_mutex_lock (parse->parse_lock);
1845 if (format == GST_FORMAT_BYTES) {
1846 res = gst_pad_query_peer_duration (parse->sinkpad, &format,
1848 } else if (parse->priv->duration != -1 &&
1849 format == parse->priv->duration_fmt) {
1850 dest_value = parse->priv->duration;
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;
1860 g_mutex_unlock (parse->parse_lock);
1863 gst_query_set_duration (query, format, dest_value);
1865 res = gst_pad_query_default (pad, query);
1868 case GST_QUERY_SEEKING:
1871 gboolean seekable = FALSE;
1873 GST_DEBUG_OBJECT (parse, "seeking query");
1875 gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
1877 if (fmt != GST_FORMAT_TIME) {
1878 return gst_pad_query_default (pad, query);
1881 seekable = klass->is_seekable (parse);
1883 /* TODO: could this duration be calculated/converted if subclass
1885 gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0,
1886 (parse->priv->duration == -1) ?
1887 GST_CLOCK_TIME_NONE : parse->priv->duration);
1889 GST_DEBUG_OBJECT (parse, "seekable: %d", seekable);
1893 case GST_QUERY_FORMATS:
1894 gst_query_set_formatsv (query, 3, fmtlist);
1898 case GST_QUERY_CONVERT:
1900 GstFormat src_format, dest_format;
1901 gint64 src_value, dest_value;
1903 gst_query_parse_convert (query, &src_format, &src_value,
1904 &dest_format, &dest_value);
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);
1912 gst_query_set_convert (query, src_format, src_value,
1913 dest_format, dest_value);
1919 res = gst_pad_query_default (pad, query);
1927 * gst_base_parse_handle_seek:
1928 * @parse: #GstBaseParse.
1929 * @event: #GstEvent.
1931 * Returns: TRUE if seek succeeded.
1934 gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event)
1936 GstBaseParseClass *klass;
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;
1946 klass = GST_BASE_PARSE_GET_CLASS (parse);
1948 gst_event_parse_seek (event, &rate, &format, &flags,
1949 &cur_type, &cur, &stop_type, &stop);
1951 /* no negative rates yet */
1955 if (cur_type != GST_SEEK_TYPE_SET)
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);
1964 gst_event_ref (event);
1965 if (gst_pad_push_event (parse->sinkpad, event)) {
1966 gst_event_unref (event);
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))
1977 /* get flush flag */
1978 flush = flags & GST_SEEK_FLAG_FLUSH;
1980 dstformat = GST_FORMAT_BYTES;
1981 if (!gst_pad_query_convert (parse->srcpad, format, cur, &dstformat, &seekpos)) {
1982 GST_DEBUG_OBJECT (parse, "conversion failed");
1986 GST_DEBUG_OBJECT (parse,
1987 "seek position %" G_GINT64_FORMAT " in bytes: %" G_GINT64_FORMAT, cur,
1990 if (parse->priv->pad_mode == GST_ACTIVATE_PULL) {
1993 GST_DEBUG_OBJECT (parse, "seek in PULL mode");
1996 if (parse->srcpad) {
1997 GST_DEBUG_OBJECT (parse, "sending flush start");
1998 gst_pad_push_event (parse->srcpad, gst_event_new_flush_start ());
2001 gst_pad_pause_task (parse->sinkpad);
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);
2008 /* save current position */
2009 last_stop = parse->segment.last_stop;
2010 GST_DEBUG_OBJECT (parse, "stopped streaming at %" G_GINT64_FORMAT,
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));
2017 GST_DEBUG_OBJECT (parse, "configuring seek");
2018 gst_segment_set_seek (&seeksegment, rate, format, flags,
2019 cur_type, cur, stop_type, stop, &update);
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;
2026 parse->priv->offset = seekpos;
2028 /* prepare for streaming again */
2030 GST_DEBUG_OBJECT (parse, "sending flush stop");
2031 gst_pad_push_event (parse->srcpad, gst_event_new_flush_stop ());
2033 if (parse->close_segment)
2034 gst_event_unref (parse->close_segment);
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);
2040 /* keep track of our last_stop */
2041 seeksegment.accum = parse->segment.last_stop;
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));
2051 memcpy (&parse->segment, &seeksegment, sizeof (GstSegment));
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);
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);
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));
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;
2077 /* Start streaming thread if paused */
2078 gst_pad_start_task (parse->sinkpad,
2079 (GstTaskFunction) gst_base_parse_loop, parse->sinkpad);
2081 GST_PAD_STREAM_UNLOCK (parse->sinkpad);
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);
2091 res = gst_pad_push_event (parse->sinkpad, new_event);
2100 GST_DEBUG_OBJECT (parse, "negative playback rates are not supported yet.");
2106 GST_DEBUG_OBJECT (parse, "unsupported seek type.");
2114 * gst_base_parse_sink_setcaps:
2118 * Returns: TRUE if caps were accepted.
2121 gst_base_parse_sink_setcaps (GstPad * pad, GstCaps * caps)
2123 GstBaseParse *parse;
2124 GstBaseParseClass *klass;
2125 gboolean res = TRUE;
2127 parse = GST_BASE_PARSE (GST_PAD_PARENT (pad));
2128 klass = GST_BASE_PARSE_GET_CLASS (parse);
2130 GST_DEBUG_OBJECT (parse, "caps: %" GST_PTR_FORMAT, caps);
2132 if (klass->set_sink_caps)
2133 res = klass->set_sink_caps (parse, caps);
2135 parse->negotiated = res;
2136 return res && gst_pad_set_caps (pad, caps);