2 * Copyright (C) 2009 Igalia S.L.
3 * Author: Iago Toral Quiroga <itoral@igalia.com>
4 * Copyright (C) 2011 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>.
5 * Copyright (C) 2011 Nokia Corporation. All rights reserved.
6 * Contact: Stefan Kost <stefan.kost@nokia.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
25 * SECTION:gstaudiodecoder
26 * @short_description: Base class for audio decoders
27 * @see_also: #GstBaseTransform
30 * This base class is for audio decoders turning encoded data into
33 * GstAudioDecoder and subclass should cooperate as follows.
36 * <itemizedlist><title>Configuration</title>
38 * Initially, GstAudioDecoder calls @start when the decoder element
39 * is activated, which allows subclass to perform any global setup.
40 * Base class (context) parameters can already be set according to subclass
41 * capabilities (or possibly upon receive more information in subsequent
45 * GstAudioDecoder calls @set_format to inform subclass of the format
46 * of input audio data that it is about to receive.
47 * While unlikely, it might be called more than once, if changing input
48 * parameters require reconfiguration.
51 * GstAudioDecoder calls @stop at end of all processing.
55 * As of configuration stage, and throughout processing, GstAudioDecoder
56 * provides various (context) parameters, e.g. describing the format of
57 * output audio data (valid when output caps have been set) or current parsing state.
58 * Conversely, subclass can and should configure context to inform
59 * base class of its expectation w.r.t. buffer handling.
62 * <title>Data processing</title>
64 * Base class gathers input data, and optionally allows subclass
65 * to parse this into subsequently manageable (as defined by subclass)
66 * chunks. Such chunks are subsequently referred to as 'frames',
67 * though they may or may not correspond to 1 (or more) audio format frame.
70 * Input frame is provided to subclass' @handle_frame.
73 * If codec processing results in decoded data, subclass should call
74 * @gst_audio_decoder_finish_frame to have decoded data pushed
78 * Just prior to actually pushing a buffer downstream,
79 * it is passed to @pre_push. Subclass should either use this callback
80 * to arrange for additional downstream pushing or otherwise ensure such
81 * custom pushing occurs after at least a method call has finished since
82 * setting src pad caps.
85 * During the parsing process GstAudioDecoderClass will handle both
86 * srcpad and sinkpad events. Sink events will be passed to subclass
87 * if @event callback has been provided.
92 * <itemizedlist><title>Shutdown phase</title>
94 * GstAudioDecoder class calls @stop to inform the subclass that data
95 * parsing will be stopped.
101 * Subclass is responsible for providing pad template caps for
102 * source and sink pads. The pads need to be named "sink" and "src". It also
103 * needs to set the fixed caps on srcpad, when the format is ensured. This
104 * is typically when base class calls subclass' @set_format function, though
105 * it might be delayed until calling @gst_audio_decoder_finish_frame.
107 * In summary, above process should have subclass concentrating on
108 * codec data processing while leaving other matters to base class,
109 * such as most notably timestamp handling. While it may exert more control
110 * in this area (see e.g. @pre_push), it is very much not recommended.
112 * In particular, base class will try to arrange for perfect output timestamps
113 * as much as possible while tracking upstream timestamps.
114 * To this end, if deviation between the next ideal expected perfect timestamp
115 * and upstream exceeds #GstAudioDecoder:tolerance, then resync to upstream
116 * occurs (which would happen always if the tolerance mechanism is disabled).
118 * In non-live pipelines, baseclass can also (configurably) arrange for
119 * output buffer aggregation which may help to redue large(r) numbers of
120 * small(er) buffers being pushed and processed downstream.
122 * On the other hand, it should be noted that baseclass only provides limited
123 * seeking support (upon explicit subclass request), as full-fledged support
124 * should rather be left to upstream demuxer, parser or alike. This simple
125 * approach caters for seeking and duration reporting using estimated input
128 * Things that subclass need to take care of:
130 * <listitem><para>Provide pad templates</para></listitem>
132 * Set source pad caps when appropriate
135 * Set user-configurable properties to sane defaults for format and
136 * implementing codec at hand, and convey some subclass capabilities and
137 * expectations in context.
140 * Accept data in @handle_frame and provide encoded results to
141 * @gst_audio_decoder_finish_frame. If it is prepared to perform
142 * PLC, it should also accept NULL data in @handle_frame and provide for
143 * data for indicated duration.
152 /* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
153 * with newer GLib versions (>= 2.31.0) */
154 #define GLIB_DISABLE_DEPRECATION_WARNINGS
156 #include "gstaudiodecoder.h"
157 #include <gst/pbutils/descriptions.h>
161 GST_DEBUG_CATEGORY (audiodecoder_debug);
162 #define GST_CAT_DEFAULT audiodecoder_debug
164 #define GST_AUDIO_DECODER_GET_PRIVATE(obj) \
165 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_AUDIO_DECODER, \
166 GstAudioDecoderPrivate))
181 #define DEFAULT_LATENCY 0
182 #define DEFAULT_TOLERANCE 0
183 #define DEFAULT_PLC FALSE
185 typedef struct _GstAudioDecoderContext
188 /* (output) audio format */
200 gboolean do_byte_time;
202 /* MT-protected (with LOCK) */
203 GstClockTime min_latency;
204 GstClockTime max_latency;
205 } GstAudioDecoderContext;
207 struct _GstAudioDecoderPrivate
209 /* activation status */
212 /* input base/first ts as basis for output ts */
213 GstClockTime base_ts;
214 /* input samples processed and sent downstream so far (w.r.t. base_ts) */
217 /* collected input data */
219 /* tracking input ts for changes */
220 GstClockTime prev_ts;
221 /* frames obtained from input */
223 /* collected output data */
224 GstAdapter *adapter_out;
225 /* ts and duration for output data collected above */
226 GstClockTime out_ts, out_dur;
227 /* mark outgoing discont */
230 /* subclass gave all it could already */
232 /* subclass currently being forcibly drained */
235 /* input bps estimatation */
236 /* global in bytes seen */
238 /* global samples sent out */
240 /* bytes flushed during parsing */
247 /* whether circumstances allow output aggregation */
250 /* reverse playback queues */
255 /* reversed output */
258 /* context storage */
259 GstAudioDecoderContext ctx;
262 GstClockTime latency;
263 GstClockTime tolerance;
266 /* pending serialized sink events, will be sent from finish_frame() */
267 GList *pending_events;
271 static void gst_audio_decoder_finalize (GObject * object);
272 static void gst_audio_decoder_set_property (GObject * object,
273 guint prop_id, const GValue * value, GParamSpec * pspec);
274 static void gst_audio_decoder_get_property (GObject * object,
275 guint prop_id, GValue * value, GParamSpec * pspec);
277 static void gst_audio_decoder_clear_queues (GstAudioDecoder * dec);
278 static GstFlowReturn gst_audio_decoder_chain_reverse (GstAudioDecoder *
279 dec, GstBuffer * buf);
281 static GstStateChangeReturn gst_audio_decoder_change_state (GstElement *
282 element, GstStateChange transition);
283 static gboolean gst_audio_decoder_sink_event (GstPad * pad, GstEvent * event);
284 static gboolean gst_audio_decoder_src_event (GstPad * pad, GstEvent * event);
285 static gboolean gst_audio_decoder_sink_setcaps (GstPad * pad, GstCaps * caps);
286 static gboolean gst_audio_decoder_src_setcaps (GstPad * pad, GstCaps * caps);
287 static GstFlowReturn gst_audio_decoder_chain (GstPad * pad, GstBuffer * buf);
288 static gboolean gst_audio_decoder_src_query (GstPad * pad, GstQuery * query);
289 static gboolean gst_audio_decoder_sink_query (GstPad * pad, GstQuery * query);
290 static const GstQueryType *gst_audio_decoder_get_query_types (GstPad * pad);
291 static void gst_audio_decoder_reset (GstAudioDecoder * dec, gboolean full);
294 GST_BOILERPLATE (GstAudioDecoder, gst_audio_decoder, GstElement,
298 gst_audio_decoder_base_init (gpointer g_class)
303 gst_audio_decoder_class_init (GstAudioDecoderClass * klass)
305 GObjectClass *gobject_class;
306 GstElementClass *element_class;
308 gobject_class = G_OBJECT_CLASS (klass);
309 element_class = GST_ELEMENT_CLASS (klass);
311 parent_class = g_type_class_peek_parent (klass);
313 g_type_class_add_private (klass, sizeof (GstAudioDecoderPrivate));
315 GST_DEBUG_CATEGORY_INIT (audiodecoder_debug, "audiodecoder", 0,
316 "audio decoder base class");
318 gobject_class->set_property = gst_audio_decoder_set_property;
319 gobject_class->get_property = gst_audio_decoder_get_property;
320 gobject_class->finalize = gst_audio_decoder_finalize;
322 element_class->change_state = gst_audio_decoder_change_state;
325 g_object_class_install_property (gobject_class, PROP_LATENCY,
326 g_param_spec_int64 ("min-latency", "Minimum Latency",
327 "Aggregate output data to a minimum of latency time (ns)",
328 0, G_MAXINT64, DEFAULT_LATENCY,
329 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
331 g_object_class_install_property (gobject_class, PROP_TOLERANCE,
332 g_param_spec_int64 ("tolerance", "Tolerance",
333 "Perfect ts while timestamp jitter/imperfection within tolerance (ns)",
334 0, G_MAXINT64, DEFAULT_TOLERANCE,
335 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
337 g_object_class_install_property (gobject_class, PROP_PLC,
338 g_param_spec_boolean ("plc", "Packet Loss Concealment",
339 "Perform packet loss concealment (if supported)",
340 DEFAULT_PLC, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
344 gst_audio_decoder_init (GstAudioDecoder * dec, GstAudioDecoderClass * klass)
346 GstPadTemplate *pad_template;
348 GST_DEBUG_OBJECT (dec, "gst_audio_decoder_init");
350 dec->priv = GST_AUDIO_DECODER_GET_PRIVATE (dec);
354 gst_element_class_get_pad_template (GST_ELEMENT_CLASS (klass), "sink");
355 g_return_if_fail (pad_template != NULL);
357 dec->sinkpad = gst_pad_new_from_template (pad_template, "sink");
358 gst_pad_set_event_function (dec->sinkpad,
359 GST_DEBUG_FUNCPTR (gst_audio_decoder_sink_event));
360 gst_pad_set_setcaps_function (dec->sinkpad,
361 GST_DEBUG_FUNCPTR (gst_audio_decoder_sink_setcaps));
362 gst_pad_set_chain_function (dec->sinkpad,
363 GST_DEBUG_FUNCPTR (gst_audio_decoder_chain));
364 gst_pad_set_query_function (dec->sinkpad,
365 GST_DEBUG_FUNCPTR (gst_audio_decoder_sink_query));
366 gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad);
367 GST_DEBUG_OBJECT (dec, "sinkpad created");
369 /* Setup source pad */
371 gst_element_class_get_pad_template (GST_ELEMENT_CLASS (klass), "src");
372 g_return_if_fail (pad_template != NULL);
374 dec->srcpad = gst_pad_new_from_template (pad_template, "src");
375 gst_pad_set_setcaps_function (dec->srcpad,
376 GST_DEBUG_FUNCPTR (gst_audio_decoder_src_setcaps));
377 gst_pad_set_event_function (dec->srcpad,
378 GST_DEBUG_FUNCPTR (gst_audio_decoder_src_event));
379 gst_pad_set_query_function (dec->srcpad,
380 GST_DEBUG_FUNCPTR (gst_audio_decoder_src_query));
381 gst_pad_set_query_type_function (dec->srcpad,
382 GST_DEBUG_FUNCPTR (gst_audio_decoder_get_query_types));
383 gst_pad_use_fixed_caps (dec->srcpad);
384 gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
385 GST_DEBUG_OBJECT (dec, "srcpad created");
387 dec->priv->adapter = gst_adapter_new ();
388 dec->priv->adapter_out = gst_adapter_new ();
389 g_queue_init (&dec->priv->frames);
391 g_static_rec_mutex_init (&dec->stream_lock);
393 /* property default */
394 dec->priv->latency = DEFAULT_LATENCY;
395 dec->priv->tolerance = DEFAULT_TOLERANCE;
396 dec->priv->plc = DEFAULT_PLC;
399 gst_audio_decoder_reset (dec, TRUE);
400 GST_DEBUG_OBJECT (dec, "init ok");
404 gst_audio_decoder_reset (GstAudioDecoder * dec, gboolean full)
406 GST_DEBUG_OBJECT (dec, "gst_audio_decoder_reset");
408 GST_AUDIO_DECODER_STREAM_LOCK (dec);
411 dec->priv->active = FALSE;
412 dec->priv->bytes_in = 0;
413 dec->priv->samples_out = 0;
415 dec->priv->error_count = 0;
416 gst_audio_decoder_clear_queues (dec);
418 gst_audio_info_clear (&dec->priv->ctx.info);
419 memset (&dec->priv->ctx, 0, sizeof (dec->priv->ctx));
421 if (dec->priv->taglist) {
422 gst_tag_list_free (dec->priv->taglist);
423 dec->priv->taglist = NULL;
426 gst_segment_init (&dec->segment, GST_FORMAT_TIME);
428 g_list_foreach (dec->priv->pending_events, (GFunc) gst_event_unref, NULL);
429 g_list_free (dec->priv->pending_events);
430 dec->priv->pending_events = NULL;
433 g_queue_foreach (&dec->priv->frames, (GFunc) gst_buffer_unref, NULL);
434 g_queue_clear (&dec->priv->frames);
435 gst_adapter_clear (dec->priv->adapter);
436 gst_adapter_clear (dec->priv->adapter_out);
437 dec->priv->out_ts = GST_CLOCK_TIME_NONE;
438 dec->priv->out_dur = 0;
439 dec->priv->prev_ts = GST_CLOCK_TIME_NONE;
440 dec->priv->drained = TRUE;
441 dec->priv->base_ts = GST_CLOCK_TIME_NONE;
442 dec->priv->samples = 0;
443 dec->priv->discont = TRUE;
444 dec->priv->sync_flush = FALSE;
446 GST_AUDIO_DECODER_STREAM_UNLOCK (dec);
450 gst_audio_decoder_finalize (GObject * object)
452 GstAudioDecoder *dec;
454 g_return_if_fail (GST_IS_AUDIO_DECODER (object));
455 dec = GST_AUDIO_DECODER (object);
457 if (dec->priv->adapter) {
458 g_object_unref (dec->priv->adapter);
460 if (dec->priv->adapter_out) {
461 g_object_unref (dec->priv->adapter_out);
464 g_static_rec_mutex_free (&dec->stream_lock);
466 G_OBJECT_CLASS (parent_class)->finalize (object);
469 /* automagically perform sanity checking of src caps;
470 * also extracts output data format */
472 gst_audio_decoder_src_setcaps (GstPad * pad, GstCaps * caps)
474 GstAudioDecoder *dec;
478 dec = GST_AUDIO_DECODER (gst_pad_get_parent (pad));
480 GST_DEBUG_OBJECT (dec, "setting src caps %" GST_PTR_FORMAT, caps);
482 GST_AUDIO_DECODER_STREAM_LOCK (dec);
484 /* parse caps here to check subclass;
485 * also makes us aware of output format */
486 if (!gst_caps_is_fixed (caps))
489 /* adjust ts tracking to new sample rate */
490 old_rate = GST_AUDIO_INFO_RATE (&dec->priv->ctx.info);
491 if (GST_CLOCK_TIME_IS_VALID (dec->priv->base_ts) && old_rate) {
492 dec->priv->base_ts +=
493 GST_FRAMES_TO_CLOCK_TIME (dec->priv->samples, old_rate);
494 dec->priv->samples = 0;
497 if (!gst_audio_info_from_caps (&dec->priv->ctx.info, caps))
501 GST_AUDIO_DECODER_STREAM_UNLOCK (dec);
503 gst_object_unref (dec);
509 GST_WARNING_OBJECT (dec, "rejected caps %" GST_PTR_FORMAT, caps);
516 gst_audio_decoder_sink_setcaps (GstPad * pad, GstCaps * caps)
518 GstAudioDecoder *dec;
519 GstAudioDecoderClass *klass;
522 dec = GST_AUDIO_DECODER (gst_pad_get_parent (pad));
523 klass = GST_AUDIO_DECODER_GET_CLASS (dec);
525 GST_DEBUG_OBJECT (dec, "caps: %" GST_PTR_FORMAT, caps);
527 GST_AUDIO_DECODER_STREAM_LOCK (dec);
528 /* NOTE pbutils only needed here */
529 /* TODO maybe (only) upstream demuxer/parser etc should handle this ? */
530 if (dec->priv->taglist)
531 gst_tag_list_free (dec->priv->taglist);
532 dec->priv->taglist = gst_tag_list_new ();
533 gst_pb_utils_add_codec_description_to_tag_list (dec->priv->taglist,
534 GST_TAG_AUDIO_CODEC, caps);
536 if (klass->set_format)
537 res = klass->set_format (dec, caps);
539 GST_AUDIO_DECODER_STREAM_UNLOCK (dec);
541 g_object_unref (dec);
546 gst_audio_decoder_setup (GstAudioDecoder * dec)
551 /* check if in live pipeline, then latency messing is no-no */
552 query = gst_query_new_latency ();
553 res = gst_pad_peer_query (dec->sinkpad, query);
555 gst_query_parse_latency (query, &res, NULL, NULL);
558 gst_query_unref (query);
560 /* normalize to bool */
561 dec->priv->agg = ! !res;
565 gst_audio_decoder_push_forward (GstAudioDecoder * dec, GstBuffer * buf)
567 GstAudioDecoderClass *klass;
568 GstAudioDecoderPrivate *priv;
569 GstAudioDecoderContext *ctx;
570 GstFlowReturn ret = GST_FLOW_OK;
572 klass = GST_AUDIO_DECODER_GET_CLASS (dec);
574 ctx = &dec->priv->ctx;
576 g_return_val_if_fail (ctx->info.bpf != 0, GST_FLOW_ERROR);
578 if (G_UNLIKELY (!buf)) {
579 g_assert_not_reached ();
583 GST_LOG_OBJECT (dec, "clipping buffer of size %d with ts %" GST_TIME_FORMAT
584 ", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buf),
585 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
586 GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
589 buf = gst_audio_buffer_clip (buf, &dec->segment, ctx->info.rate,
591 if (G_UNLIKELY (!buf)) {
592 GST_DEBUG_OBJECT (dec, "no data after clipping to segment");
597 gst_buffer_set_caps (buf, GST_PAD_CAPS (dec->srcpad));
599 if (G_UNLIKELY (priv->discont)) {
600 GST_LOG_OBJECT (dec, "marking discont");
601 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
602 priv->discont = FALSE;
605 /* track where we are */
606 if (G_LIKELY (GST_BUFFER_TIMESTAMP_IS_VALID (buf))) {
607 /* duration should always be valid for raw audio */
608 g_assert (GST_BUFFER_DURATION_IS_VALID (buf));
609 dec->segment.last_stop =
610 GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf);
613 if (klass->pre_push) {
614 /* last chance for subclass to do some dirty stuff */
615 ret = klass->pre_push (dec, &buf);
616 if (ret != GST_FLOW_OK || !buf) {
617 GST_DEBUG_OBJECT (dec, "subclass returned %s, buf %p",
618 gst_flow_get_name (ret), buf);
620 gst_buffer_unref (buf);
625 GST_LOG_OBJECT (dec, "pushing buffer of size %d with ts %" GST_TIME_FORMAT
626 ", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buf),
627 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
628 GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
630 ret = gst_pad_push (dec->srcpad, buf);
636 /* mini aggregator combining output buffers into fewer larger ones,
637 * if so allowed/configured */
639 gst_audio_decoder_output (GstAudioDecoder * dec, GstBuffer * buf)
641 GstAudioDecoderPrivate *priv;
642 GstFlowReturn ret = GST_FLOW_OK;
643 GstBuffer *inbuf = NULL;
647 if (G_UNLIKELY (priv->agg < 0))
648 gst_audio_decoder_setup (dec);
650 if (G_LIKELY (buf)) {
651 GST_LOG_OBJECT (dec, "output buffer of size %d with ts %" GST_TIME_FORMAT
652 ", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buf),
653 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
654 GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
659 if (priv->agg && dec->priv->latency > 0) {
661 gboolean assemble = FALSE;
662 const GstClockTimeDiff tol = 10 * GST_MSECOND;
663 GstClockTimeDiff diff = -100 * GST_MSECOND;
665 av = gst_adapter_available (priv->adapter_out);
666 if (G_UNLIKELY (!buf)) {
667 /* forcibly send current */
669 GST_LOG_OBJECT (dec, "forcing fragment flush");
670 } else if (av && (!GST_BUFFER_TIMESTAMP_IS_VALID (buf) ||
671 !GST_CLOCK_TIME_IS_VALID (priv->out_ts) ||
672 ((diff = GST_CLOCK_DIFF (GST_BUFFER_TIMESTAMP (buf),
673 priv->out_ts + priv->out_dur)) > tol) || diff < -tol)) {
675 GST_LOG_OBJECT (dec, "buffer %d ms apart from current fragment",
676 (gint) (diff / GST_MSECOND));
678 /* add or start collecting */
680 GST_LOG_OBJECT (dec, "starting new fragment");
681 priv->out_ts = GST_BUFFER_TIMESTAMP (buf);
683 GST_LOG_OBJECT (dec, "adding to fragment");
685 gst_adapter_push (priv->adapter_out, buf);
686 priv->out_dur += GST_BUFFER_DURATION (buf);
687 av += GST_BUFFER_SIZE (buf);
690 if (priv->out_dur > dec->priv->latency)
692 if (av && assemble) {
693 GST_LOG_OBJECT (dec, "assembling fragment");
695 buf = gst_adapter_take_buffer (priv->adapter_out, av);
696 GST_BUFFER_TIMESTAMP (buf) = priv->out_ts;
697 GST_BUFFER_DURATION (buf) = priv->out_dur;
698 priv->out_ts = GST_CLOCK_TIME_NONE;
703 if (G_LIKELY (buf)) {
704 if (dec->segment.rate > 0.0) {
705 ret = gst_audio_decoder_push_forward (dec, buf);
706 GST_LOG_OBJECT (dec, "buffer pushed: %s", gst_flow_get_name (ret));
709 priv->queued = g_list_prepend (priv->queued, buf);
710 GST_LOG_OBJECT (dec, "buffer queued");
723 * gst_audio_decoder_finish_frame:
724 * @dec: a #GstAudioDecoder
726 * @frames: number of decoded frames represented by decoded data
728 * Collects decoded data and pushes it downstream.
730 * @buf may be NULL in which case the indicated number of frames
731 * are discarded and considered to have produced no output
732 * (e.g. lead-in or setup frames).
733 * Otherwise, source pad caps must be set when it is called with valid
736 * Note that a frame received in gst_audio_decoder_handle_frame() may be
737 * invalidated by a call to this function.
739 * Returns: a #GstFlowReturn that should be escalated to caller (of caller)
744 gst_audio_decoder_finish_frame (GstAudioDecoder * dec, GstBuffer * buf,
747 GstAudioDecoderPrivate *priv;
748 GstAudioDecoderContext *ctx;
750 GstClockTime ts, next_ts;
751 GstFlowReturn ret = GST_FLOW_OK;
753 /* subclass should know what it is producing by now */
754 g_return_val_if_fail (buf == NULL || GST_PAD_CAPS (dec->srcpad) != NULL,
756 /* subclass should not hand us no data */
757 g_return_val_if_fail (buf == NULL || GST_BUFFER_SIZE (buf) > 0,
759 /* no dummy calls please */
760 g_return_val_if_fail (frames != 0, GST_FLOW_ERROR);
763 ctx = &dec->priv->ctx;
765 /* must know the output format by now */
766 g_return_val_if_fail (buf == NULL || GST_AUDIO_INFO_IS_VALID (&ctx->info),
769 GST_LOG_OBJECT (dec, "accepting %d bytes == %d samples for %d frames",
770 buf ? GST_BUFFER_SIZE (buf) : -1,
771 buf ? GST_BUFFER_SIZE (buf) / ctx->info.bpf : -1, frames);
773 GST_AUDIO_DECODER_STREAM_LOCK (dec);
775 if (priv->pending_events) {
776 GList *pending_events, *l;
778 pending_events = priv->pending_events;
779 priv->pending_events = NULL;
781 GST_DEBUG_OBJECT (dec, "Pushing pending events");
782 for (l = pending_events; l; l = l->next)
783 gst_pad_push_event (dec->srcpad, l->data);
784 g_list_free (pending_events);
787 /* output shoud be whole number of sample frames */
788 if (G_LIKELY (buf && ctx->info.bpf)) {
789 if (GST_BUFFER_SIZE (buf) % ctx->info.bpf)
791 /* per channel least */
792 samples = GST_BUFFER_SIZE (buf) / ctx->info.bpf;
795 /* frame and ts book-keeping */
796 if (G_UNLIKELY (frames < 0)) {
797 if (G_UNLIKELY (-frames - 1 > priv->frames.length))
799 frames = priv->frames.length + frames + 1;
800 } else if (G_UNLIKELY (frames > priv->frames.length)) {
801 if (G_LIKELY (!priv->force)) {
802 /* no way we can let this pass */
803 g_assert_not_reached ();
809 if (G_LIKELY (priv->frames.length))
810 ts = GST_BUFFER_TIMESTAMP (priv->frames.head->data);
812 ts = GST_CLOCK_TIME_NONE;
814 GST_DEBUG_OBJECT (dec, "leading frame ts %" GST_TIME_FORMAT,
817 while (priv->frames.length && frames) {
818 gst_buffer_unref (g_queue_pop_head (&priv->frames));
819 dec->priv->ctx.delay = dec->priv->frames.length;
823 if (G_UNLIKELY (!buf))
827 if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (priv->base_ts))) {
829 GST_DEBUG_OBJECT (dec, "base_ts now %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
832 /* slightly convoluted approach caters for perfect ts if subclass desires */
833 if (GST_CLOCK_TIME_IS_VALID (ts)) {
834 if (dec->priv->tolerance > 0) {
835 GstClockTimeDiff diff;
837 g_assert (GST_CLOCK_TIME_IS_VALID (priv->base_ts));
838 next_ts = priv->base_ts +
839 gst_util_uint64_scale (priv->samples, GST_SECOND, ctx->info.rate);
841 "buffer is %" G_GUINT64_FORMAT " samples past base_ts %"
842 GST_TIME_FORMAT ", expected ts %" GST_TIME_FORMAT, priv->samples,
843 GST_TIME_ARGS (priv->base_ts), GST_TIME_ARGS (next_ts));
844 diff = GST_CLOCK_DIFF (next_ts, ts);
845 GST_LOG_OBJECT (dec, "ts diff %d ms", (gint) (diff / GST_MSECOND));
846 /* if within tolerance,
847 * discard buffer ts and carry on producing perfect stream,
848 * otherwise resync to ts */
849 if (G_UNLIKELY (diff < (gint64) - dec->priv->tolerance ||
850 diff > (gint64) dec->priv->tolerance)) {
851 GST_DEBUG_OBJECT (dec, "base_ts resync");
856 GST_DEBUG_OBJECT (dec, "base_ts resync");
862 /* delayed one-shot stuff until confirmed data */
864 GST_DEBUG_OBJECT (dec, "codec tag %" GST_PTR_FORMAT, priv->taglist);
865 if (gst_tag_list_is_empty (priv->taglist)) {
866 gst_tag_list_free (priv->taglist);
868 gst_element_found_tags (GST_ELEMENT (dec), priv->taglist);
870 priv->taglist = NULL;
873 buf = gst_buffer_make_metadata_writable (buf);
874 if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (priv->base_ts))) {
875 GST_BUFFER_TIMESTAMP (buf) =
877 GST_FRAMES_TO_CLOCK_TIME (priv->samples, ctx->info.rate);
878 GST_BUFFER_DURATION (buf) = priv->base_ts +
879 GST_FRAMES_TO_CLOCK_TIME (priv->samples + samples, ctx->info.rate) -
880 GST_BUFFER_TIMESTAMP (buf);
882 GST_BUFFER_TIMESTAMP (buf) = GST_CLOCK_TIME_NONE;
883 GST_BUFFER_DURATION (buf) =
884 GST_FRAMES_TO_CLOCK_TIME (samples, ctx->info.rate);
886 priv->samples += samples;
887 priv->samples_out += samples;
889 /* we got data, so note things are looking up */
890 if (G_UNLIKELY (dec->priv->error_count))
891 dec->priv->error_count--;
894 ret = gst_audio_decoder_output (dec, buf);
896 GST_AUDIO_DECODER_STREAM_UNLOCK (dec);
903 GST_ELEMENT_ERROR (dec, STREAM, ENCODE, (NULL),
904 ("buffer size %d not a multiple of %d", GST_BUFFER_SIZE (buf),
906 gst_buffer_unref (buf);
907 ret = GST_FLOW_ERROR;
912 GST_ELEMENT_ERROR (dec, STREAM, ENCODE,
913 ("received more decoded frames %d than provided %d", frames,
914 priv->frames.length), (NULL));
916 gst_buffer_unref (buf);
917 ret = GST_FLOW_ERROR;
923 gst_audio_decoder_handle_frame (GstAudioDecoder * dec,
924 GstAudioDecoderClass * klass, GstBuffer * buffer)
926 if (G_LIKELY (buffer)) {
927 /* keep around for admin */
928 GST_LOG_OBJECT (dec, "tracking frame size %d, ts %" GST_TIME_FORMAT,
929 GST_BUFFER_SIZE (buffer),
930 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
931 g_queue_push_tail (&dec->priv->frames, buffer);
932 dec->priv->ctx.delay = dec->priv->frames.length;
933 dec->priv->bytes_in += GST_BUFFER_SIZE (buffer);
935 GST_LOG_OBJECT (dec, "providing subclass with NULL frame");
938 return klass->handle_frame (dec, buffer);
941 /* maybe subclass configurable instead, but this allows for a whole lot of
942 * raw samples, so at least quite some encoded ... */
943 #define GST_AUDIO_DECODER_MAX_SYNC 10 * 8 * 2 * 1024
946 gst_audio_decoder_push_buffers (GstAudioDecoder * dec, gboolean force)
948 GstAudioDecoderClass *klass;
949 GstAudioDecoderPrivate *priv;
950 GstAudioDecoderContext *ctx;
951 GstFlowReturn ret = GST_FLOW_OK;
955 klass = GST_AUDIO_DECODER_GET_CLASS (dec);
957 ctx = &dec->priv->ctx;
959 g_return_val_if_fail (klass->handle_frame != NULL, GST_FLOW_ERROR);
961 av = gst_adapter_available (priv->adapter);
962 GST_DEBUG_OBJECT (dec, "available: %d", av);
964 while (ret == GST_FLOW_OK) {
973 /* parse if needed */
977 /* limited (legacy) parsing; avoid whole of baseparse */
978 GST_DEBUG_OBJECT (dec, "parsing available: %d", av);
979 /* piggyback sync state on discont */
980 ctx->sync = !priv->discont;
981 ret = klass->parse (dec, priv->adapter, &offset, &len);
983 g_assert (offset <= av);
986 GST_DEBUG_OBJECT (dec, "setting DISCONT");
987 gst_adapter_flush (priv->adapter, offset);
989 /* avoid parsing indefinitely */
990 priv->sync_flush += offset;
991 if (priv->sync_flush > GST_AUDIO_DECODER_MAX_SYNC)
995 if (ret == GST_FLOW_UNEXPECTED) {
996 GST_LOG_OBJECT (dec, "no frame yet");
999 } else if (ret == GST_FLOW_OK) {
1000 GST_LOG_OBJECT (dec, "frame at offset %d of length %d", offset, len);
1001 g_assert (offset + len <= av);
1002 priv->sync_flush = 0;
1009 /* track upstream ts, but do not get stuck if nothing new upstream */
1010 ts = gst_adapter_prev_timestamp (priv->adapter, NULL);
1011 if (ts == priv->prev_ts) {
1012 GST_LOG_OBJECT (dec, "ts == prev_ts; discarding");
1013 ts = GST_CLOCK_TIME_NONE;
1017 buffer = gst_adapter_take_buffer (priv->adapter, len);
1018 buffer = gst_buffer_make_metadata_writable (buffer);
1019 GST_BUFFER_TIMESTAMP (buffer) = ts;
1027 ret = gst_audio_decoder_handle_frame (dec, klass, buffer);
1029 /* do not keep pushing it ... */
1030 if (G_UNLIKELY (!av)) {
1031 priv->drained = TRUE;
1039 GST_LOG_OBJECT (dec, "done pushing to subclass");
1045 GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("failed to parse stream"));
1046 return GST_FLOW_ERROR;
1050 static GstFlowReturn
1051 gst_audio_decoder_drain (GstAudioDecoder * dec)
1055 if (dec->priv->drained && !dec->priv->gather)
1058 /* dispatch reverse pending buffers */
1059 /* chain eventually calls upon drain as well, but by that time
1060 * gather list should be clear, so ok ... */
1061 if (dec->segment.rate < 0.0 && dec->priv->gather)
1062 gst_audio_decoder_chain_reverse (dec, NULL);
1063 /* have subclass give all it can */
1064 ret = gst_audio_decoder_push_buffers (dec, TRUE);
1065 /* ensure all output sent */
1066 ret = gst_audio_decoder_output (dec, NULL);
1067 /* everything should be away now */
1068 if (dec->priv->frames.length) {
1069 /* not fatal/impossible though if subclass/codec eats stuff */
1070 GST_WARNING_OBJECT (dec, "still %d frames left after draining",
1071 dec->priv->frames.length);
1072 g_queue_foreach (&dec->priv->frames, (GFunc) gst_buffer_unref, NULL);
1073 g_queue_clear (&dec->priv->frames);
1075 /* discard (unparsed) leftover */
1076 gst_adapter_clear (dec->priv->adapter);
1082 /* hard == FLUSH, otherwise discont */
1083 static GstFlowReturn
1084 gst_audio_decoder_flush (GstAudioDecoder * dec, gboolean hard)
1086 GstAudioDecoderClass *klass;
1087 GstFlowReturn ret = GST_FLOW_OK;
1089 klass = GST_AUDIO_DECODER_GET_CLASS (dec);
1091 GST_LOG_OBJECT (dec, "flush hard %d", hard);
1094 ret = gst_audio_decoder_drain (dec);
1096 gst_audio_decoder_clear_queues (dec);
1097 gst_segment_init (&dec->segment, GST_FORMAT_TIME);
1098 dec->priv->error_count = 0;
1100 /* only bother subclass with flushing if known it is already alive
1101 * and kicking out stuff */
1102 if (klass->flush && dec->priv->samples_out > 0)
1103 klass->flush (dec, hard);
1104 /* and get (re)set for the sequel */
1105 gst_audio_decoder_reset (dec, FALSE);
1110 static GstFlowReturn
1111 gst_audio_decoder_chain_forward (GstAudioDecoder * dec, GstBuffer * buffer)
1113 GstFlowReturn ret = GST_FLOW_OK;
1115 /* discard silly case, though maybe ts may be of value ?? */
1116 if (G_UNLIKELY (GST_BUFFER_SIZE (buffer) == 0)) {
1117 GST_DEBUG_OBJECT (dec, "discarding empty buffer");
1118 gst_buffer_unref (buffer);
1123 gst_adapter_push (dec->priv->adapter, buffer);
1125 /* new stuff, so we can push subclass again */
1126 dec->priv->drained = FALSE;
1128 /* hand to subclass */
1129 ret = gst_audio_decoder_push_buffers (dec, FALSE);
1132 GST_LOG_OBJECT (dec, "chain-done");
1137 gst_audio_decoder_clear_queues (GstAudioDecoder * dec)
1139 GstAudioDecoderPrivate *priv = dec->priv;
1141 g_list_foreach (priv->queued, (GFunc) gst_mini_object_unref, NULL);
1142 g_list_free (priv->queued);
1143 priv->queued = NULL;
1144 g_list_foreach (priv->gather, (GFunc) gst_mini_object_unref, NULL);
1145 g_list_free (priv->gather);
1146 priv->gather = NULL;
1147 g_list_foreach (priv->decode, (GFunc) gst_mini_object_unref, NULL);
1148 g_list_free (priv->decode);
1149 priv->decode = NULL;
1154 * Buffer decoding order: 7 8 9 4 5 6 3 1 2 EOS
1155 * Discont flag: D D D D
1157 * - Each Discont marks a discont in the decoding order.
1159 * for vorbis, each buffer is a keyframe when we have the previous
1160 * buffer. This means that to decode buffer 7, we need buffer 6, which
1161 * arrives out of order.
1163 * we first gather buffers in the gather queue until we get a DISCONT. We
1164 * prepend each incomming buffer so that they are in reversed order.
1166 * gather queue: 9 8 7
1170 * When a DISCONT is received (buffer 4), we move the gather queue to the
1171 * decode queue. This is simply done be taking the head of the gather queue
1172 * and prepending it to the decode queue. This yields:
1175 * decode queue: 7 8 9
1178 * Then we decode each buffer in the decode queue in order and put the output
1179 * buffer in the output queue. The first buffer (7) will not produce any output
1180 * because it needs the previous buffer (6) which did not arrive yet. This
1184 * decode queue: 7 8 9
1187 * Then we remove the consumed buffers from the decode queue. Buffer 7 is not
1188 * completely consumed, we need to keep it around for when we receive buffer
1195 * Then we accumulate more buffers:
1197 * gather queue: 6 5 4
1201 * prepending to the decode queue on DISCONT yields:
1204 * decode queue: 4 5 6 7
1207 * after decoding and keeping buffer 4:
1211 * output queue: 7 6 5
1215 static GstFlowReturn
1216 gst_audio_decoder_flush_decode (GstAudioDecoder * dec)
1218 GstAudioDecoderPrivate *priv = dec->priv;
1219 GstFlowReturn res = GST_FLOW_OK;
1220 GstClockTime timestamp;
1223 walk = priv->decode;
1225 GST_DEBUG_OBJECT (dec, "flushing buffers to decoder");
1227 /* clear buffer and decoder state */
1228 gst_audio_decoder_flush (dec, FALSE);
1232 GstBuffer *buf = GST_BUFFER_CAST (walk->data);
1234 GST_DEBUG_OBJECT (dec, "decoding buffer %p, ts %" GST_TIME_FORMAT,
1235 buf, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
1237 next = g_list_next (walk);
1238 /* decode buffer, resulting data prepended to output queue */
1239 gst_buffer_ref (buf);
1240 res = gst_audio_decoder_chain_forward (dec, buf);
1242 /* if we generated output, we can discard the buffer, else we
1243 * keep it in the queue */
1245 GST_DEBUG_OBJECT (dec, "decoded buffer to %p", priv->queued->data);
1246 priv->decode = g_list_delete_link (priv->decode, walk);
1247 gst_buffer_unref (buf);
1249 GST_DEBUG_OBJECT (dec, "buffer did not decode, keeping");
1254 /* drain any aggregation (or otherwise) leftover */
1255 gst_audio_decoder_drain (dec);
1257 /* now send queued data downstream */
1258 timestamp = GST_CLOCK_TIME_NONE;
1259 while (priv->queued) {
1260 GstBuffer *buf = GST_BUFFER_CAST (priv->queued->data);
1262 /* duration should always be valid for raw audio */
1263 g_assert (GST_BUFFER_DURATION_IS_VALID (buf));
1265 /* interpolate (backward) if needed */
1266 if (G_LIKELY (timestamp != -1))
1267 timestamp -= GST_BUFFER_DURATION (buf);
1269 if (!GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
1270 GST_LOG_OBJECT (dec, "applying reverse interpolated ts %"
1271 GST_TIME_FORMAT, GST_TIME_ARGS (timestamp));
1272 GST_BUFFER_TIMESTAMP (buf) = timestamp;
1274 /* track otherwise */
1275 timestamp = GST_BUFFER_TIMESTAMP (buf);
1276 GST_LOG_OBJECT (dec, "tracking ts %" GST_TIME_FORMAT,
1277 GST_TIME_ARGS (timestamp));
1280 if (G_LIKELY (res == GST_FLOW_OK)) {
1281 GST_DEBUG_OBJECT (dec, "pushing buffer %p of size %u, "
1282 "time %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT, buf,
1283 GST_BUFFER_SIZE (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
1284 GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
1285 /* should be already, but let's be sure */
1286 buf = gst_buffer_make_metadata_writable (buf);
1287 /* avoid stray DISCONT from forward processing,
1288 * which have no meaning in reverse pushing */
1289 GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
1290 res = gst_audio_decoder_push_forward (dec, buf);
1292 gst_buffer_unref (buf);
1295 priv->queued = g_list_delete_link (priv->queued, priv->queued);
1301 static GstFlowReturn
1302 gst_audio_decoder_chain_reverse (GstAudioDecoder * dec, GstBuffer * buf)
1304 GstAudioDecoderPrivate *priv = dec->priv;
1305 GstFlowReturn result = GST_FLOW_OK;
1307 /* if we have a discont, move buffers to the decode list */
1308 if (!buf || GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT)) {
1309 GST_DEBUG_OBJECT (dec, "received discont");
1310 while (priv->gather) {
1313 gbuf = GST_BUFFER_CAST (priv->gather->data);
1314 /* remove from the gather list */
1315 priv->gather = g_list_delete_link (priv->gather, priv->gather);
1316 /* copy to decode queue */
1317 priv->decode = g_list_prepend (priv->decode, gbuf);
1319 /* decode stuff in the decode queue */
1320 gst_audio_decoder_flush_decode (dec);
1323 if (G_LIKELY (buf)) {
1324 GST_DEBUG_OBJECT (dec, "gathering buffer %p of size %u, "
1325 "time %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT, buf,
1326 GST_BUFFER_SIZE (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
1327 GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
1329 /* add buffer to gather queue */
1330 priv->gather = g_list_prepend (priv->gather, buf);
1336 static GstFlowReturn
1337 gst_audio_decoder_chain (GstPad * pad, GstBuffer * buffer)
1339 GstAudioDecoder *dec;
1342 dec = GST_AUDIO_DECODER (GST_PAD_PARENT (pad));
1344 GST_LOG_OBJECT (dec,
1345 "received buffer of size %d with ts %" GST_TIME_FORMAT
1346 ", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buffer),
1347 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
1348 GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
1350 GST_AUDIO_DECODER_STREAM_LOCK (dec);
1352 if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) {
1355 /* track present position */
1356 ts = dec->priv->base_ts;
1357 samples = dec->priv->samples;
1359 GST_DEBUG_OBJECT (dec, "handling discont");
1360 gst_audio_decoder_flush (dec, FALSE);
1361 dec->priv->discont = TRUE;
1363 /* buffer may claim DISCONT loudly, if it can't tell us where we are now,
1364 * we'll stick to where we were ...
1365 * Particularly useful/needed for upstream BYTE based */
1366 if (dec->segment.rate > 0.0 && !GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) {
1367 GST_DEBUG_OBJECT (dec, "... but restoring previous ts tracking");
1368 dec->priv->base_ts = ts;
1369 dec->priv->samples = samples;
1373 if (dec->segment.rate > 0.0)
1374 ret = gst_audio_decoder_chain_forward (dec, buffer);
1376 ret = gst_audio_decoder_chain_reverse (dec, buffer);
1378 GST_AUDIO_DECODER_STREAM_UNLOCK (dec);
1383 /* perform upstream byte <-> time conversion (duration, seeking)
1384 * if subclass allows and if enough data for moderately decent conversion */
1385 static inline gboolean
1386 gst_audio_decoder_do_byte (GstAudioDecoder * dec)
1388 return dec->priv->ctx.do_byte_time && dec->priv->ctx.info.bpf &&
1389 dec->priv->ctx.info.rate <= dec->priv->samples_out;
1393 gst_audio_decoder_sink_eventfunc (GstAudioDecoder * dec, GstEvent * event)
1395 gboolean handled = FALSE;
1397 switch (GST_EVENT_TYPE (event)) {
1398 case GST_EVENT_NEWSEGMENT:
1401 gdouble rate, arate;
1402 gint64 start, stop, time;
1405 GST_AUDIO_DECODER_STREAM_LOCK (dec);
1406 gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
1407 &start, &stop, &time);
1409 if (format == GST_FORMAT_TIME) {
1410 GST_DEBUG_OBJECT (dec, "received TIME NEW_SEGMENT %" GST_TIME_FORMAT
1411 " -- %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT
1412 ", rate %g, applied_rate %g",
1413 GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time),
1416 GstFormat dformat = GST_FORMAT_TIME;
1418 GST_DEBUG_OBJECT (dec, "received NEW_SEGMENT %" G_GINT64_FORMAT
1419 " -- %" G_GINT64_FORMAT ", time %" G_GINT64_FORMAT
1420 ", rate %g, applied_rate %g", start, stop, time, rate, arate);
1421 /* handle newsegment resulting from legacy simple seeking */
1422 /* note that we need to convert this whether or not enough data
1423 * to handle initial newsegment */
1424 if (dec->priv->ctx.do_byte_time &&
1425 gst_pad_query_convert (dec->sinkpad, GST_FORMAT_BYTES, start,
1426 &dformat, &start)) {
1427 /* best attempt convert */
1428 /* as these are only estimates, stop is kept open-ended to avoid
1429 * premature cutting */
1430 GST_DEBUG_OBJECT (dec, "converted to TIME start %" GST_TIME_FORMAT,
1431 GST_TIME_ARGS (start));
1432 format = GST_FORMAT_TIME;
1434 stop = GST_CLOCK_TIME_NONE;
1436 gst_event_unref (event);
1437 event = gst_event_new_new_segment_full (update, rate, arate,
1438 GST_FORMAT_TIME, start, stop, time);
1440 GST_DEBUG_OBJECT (dec, "unsupported format; ignoring");
1441 GST_AUDIO_DECODER_STREAM_UNLOCK (dec);
1446 /* finish current segment */
1447 gst_audio_decoder_drain (dec);
1450 /* time progressed without data, see if we can fill the gap with
1451 * some concealment data */
1452 GST_DEBUG_OBJECT (dec,
1453 "segment update: plc %d, do_plc %d, last_stop %" GST_TIME_FORMAT,
1454 dec->priv->plc, dec->priv->ctx.do_plc,
1455 GST_TIME_ARGS (dec->segment.last_stop));
1456 if (dec->priv->plc && dec->priv->ctx.do_plc &&
1457 dec->segment.rate > 0.0 && dec->segment.last_stop < start) {
1458 GstAudioDecoderClass *klass;
1461 klass = GST_AUDIO_DECODER_GET_CLASS (dec);
1462 /* hand subclass empty frame with duration that needs covering */
1463 buf = gst_buffer_new ();
1464 GST_BUFFER_DURATION (buf) = start - dec->segment.last_stop;
1465 /* best effort, not much error handling */
1466 gst_audio_decoder_handle_frame (dec, klass, buf);
1469 /* prepare for next one */
1470 gst_audio_decoder_flush (dec, FALSE);
1471 /* and that's where we time from,
1472 * in case upstream does not come up with anything better
1473 * (e.g. upstream BYTE) */
1474 if (format != GST_FORMAT_TIME) {
1475 dec->priv->base_ts = start;
1476 dec->priv->samples = 0;
1480 /* and follow along with segment */
1481 gst_segment_set_newsegment_full (&dec->segment, update, rate, arate,
1482 format, start, stop, time);
1484 dec->priv->pending_events =
1485 g_list_append (dec->priv->pending_events, event);
1487 GST_AUDIO_DECODER_STREAM_UNLOCK (dec);
1491 case GST_EVENT_FLUSH_START:
1494 case GST_EVENT_FLUSH_STOP:
1495 GST_AUDIO_DECODER_STREAM_LOCK (dec);
1496 /* prepare for fresh start */
1497 gst_audio_decoder_flush (dec, TRUE);
1499 g_list_foreach (dec->priv->pending_events, (GFunc) gst_event_unref, NULL);
1500 g_list_free (dec->priv->pending_events);
1501 dec->priv->pending_events = NULL;
1502 GST_AUDIO_DECODER_STREAM_UNLOCK (dec);
1506 GST_AUDIO_DECODER_STREAM_LOCK (dec);
1507 gst_audio_decoder_drain (dec);
1508 GST_AUDIO_DECODER_STREAM_UNLOCK (dec);
1519 gst_audio_decoder_sink_event (GstPad * pad, GstEvent * event)
1521 GstAudioDecoder *dec;
1522 GstAudioDecoderClass *klass;
1523 gboolean handled = FALSE;
1524 gboolean ret = TRUE;
1526 dec = GST_AUDIO_DECODER (gst_pad_get_parent (pad));
1527 klass = GST_AUDIO_DECODER_GET_CLASS (dec);
1529 GST_DEBUG_OBJECT (dec, "received event %d, %s", GST_EVENT_TYPE (event),
1530 GST_EVENT_TYPE_NAME (event));
1533 handled = klass->event (dec, event);
1536 handled = gst_audio_decoder_sink_eventfunc (dec, event);
1539 /* Forward non-serialized events and EOS/FLUSH_STOP immediately.
1540 * For EOS this is required because no buffer or serialized event
1541 * will come after EOS and nothing could trigger another
1542 * _finish_frame() call.
1544 * For FLUSH_STOP this is required because it is expected
1545 * to be forwarded immediately and no buffers are queued anyway.
1547 if (!GST_EVENT_IS_SERIALIZED (event)
1548 || GST_EVENT_TYPE (event) == GST_EVENT_EOS
1549 || GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) {
1550 ret = gst_pad_event_default (pad, event);
1552 GST_AUDIO_DECODER_STREAM_LOCK (dec);
1553 dec->priv->pending_events =
1554 g_list_append (dec->priv->pending_events, event);
1555 GST_AUDIO_DECODER_STREAM_UNLOCK (dec);
1560 GST_DEBUG_OBJECT (dec, "event handled");
1562 gst_object_unref (dec);
1567 gst_audio_decoder_do_seek (GstAudioDecoder * dec, GstEvent * event)
1570 GstSeekType start_type, end_type;
1573 gint64 start, start_time, end_time;
1574 GstSegment seek_segment;
1577 gst_event_parse_seek (event, &rate, &format, &flags, &start_type,
1578 &start_time, &end_type, &end_time);
1580 /* we'll handle plain open-ended flushing seeks with the simple approach */
1582 GST_DEBUG_OBJECT (dec, "unsupported seek: rate");
1586 if (start_type != GST_SEEK_TYPE_SET) {
1587 GST_DEBUG_OBJECT (dec, "unsupported seek: start time");
1591 if (end_type != GST_SEEK_TYPE_NONE ||
1592 (end_type == GST_SEEK_TYPE_SET && end_time != GST_CLOCK_TIME_NONE)) {
1593 GST_DEBUG_OBJECT (dec, "unsupported seek: end time");
1597 if (!(flags & GST_SEEK_FLAG_FLUSH)) {
1598 GST_DEBUG_OBJECT (dec, "unsupported seek: not flushing");
1602 memcpy (&seek_segment, &dec->segment, sizeof (seek_segment));
1603 gst_segment_set_seek (&seek_segment, rate, format, flags, start_type,
1604 start_time, end_type, end_time, NULL);
1605 start_time = seek_segment.last_stop;
1607 format = GST_FORMAT_BYTES;
1608 if (!gst_pad_query_convert (dec->sinkpad, GST_FORMAT_TIME, start_time,
1610 GST_DEBUG_OBJECT (dec, "conversion failed");
1614 seqnum = gst_event_get_seqnum (event);
1615 event = gst_event_new_seek (1.0, GST_FORMAT_BYTES, flags,
1616 GST_SEEK_TYPE_SET, start, GST_SEEK_TYPE_NONE, -1);
1617 gst_event_set_seqnum (event, seqnum);
1619 GST_DEBUG_OBJECT (dec, "seeking to %" GST_TIME_FORMAT " at byte offset %"
1620 G_GINT64_FORMAT, GST_TIME_ARGS (start_time), start);
1622 return gst_pad_push_event (dec->sinkpad, event);
1626 gst_audio_decoder_src_event (GstPad * pad, GstEvent * event)
1628 GstAudioDecoder *dec;
1629 gboolean res = FALSE;
1631 dec = GST_AUDIO_DECODER (gst_pad_get_parent (pad));
1632 if (G_UNLIKELY (dec == NULL)) {
1633 gst_event_unref (event);
1637 GST_DEBUG_OBJECT (dec, "received event %d, %s", GST_EVENT_TYPE (event),
1638 GST_EVENT_TYPE_NAME (event));
1640 switch (GST_EVENT_TYPE (event)) {
1641 case GST_EVENT_SEEK:
1643 GstFormat format, tformat;
1646 GstSeekType cur_type, stop_type;
1651 gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
1653 seqnum = gst_event_get_seqnum (event);
1655 /* upstream gets a chance first */
1656 if ((res = gst_pad_push_event (dec->sinkpad, event)))
1659 /* if upstream fails for a time seek, maybe we can help if allowed */
1660 if (format == GST_FORMAT_TIME) {
1661 if (gst_audio_decoder_do_byte (dec))
1662 res = gst_audio_decoder_do_seek (dec, event);
1666 /* ... though a non-time seek can be aided as well */
1667 /* First bring the requested format to time */
1668 tformat = GST_FORMAT_TIME;
1669 if (!(res = gst_pad_query_convert (pad, format, cur, &tformat, &tcur)))
1671 if (!(res = gst_pad_query_convert (pad, format, stop, &tformat, &tstop)))
1674 /* then seek with time on the peer */
1675 event = gst_event_new_seek (rate, GST_FORMAT_TIME,
1676 flags, cur_type, tcur, stop_type, tstop);
1677 gst_event_set_seqnum (event, seqnum);
1679 res = gst_pad_push_event (dec->sinkpad, event);
1683 res = gst_pad_push_event (dec->sinkpad, event);
1687 gst_object_unref (dec);
1694 GST_DEBUG_OBJECT (dec, "cannot convert start/stop for seek");
1700 * gst_audio_encoded_audio_convert:
1701 * @fmt: audio format of the encoded audio
1702 * @bytes: number of encoded bytes
1703 * @samples: number of encoded samples
1704 * @src_format: source format
1705 * @src_value: source value
1706 * @dest_format: destination format
1707 * @dest_value: destination format
1709 * Helper function to convert @src_value in @src_format to @dest_value in
1710 * @dest_format for encoded audio data. Conversion is possible between
1711 * BYTE and TIME format by using estimated bitrate based on
1712 * @samples and @bytes (and @fmt).
1714 /* FIXME: make gst_audio_encoded_audio_convert() public? */
1716 gst_audio_encoded_audio_convert (GstAudioInfo * fmt,
1717 gint64 bytes, gint64 samples, GstFormat src_format,
1718 gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
1720 gboolean res = FALSE;
1722 g_return_val_if_fail (dest_format != NULL, FALSE);
1723 g_return_val_if_fail (dest_value != NULL, FALSE);
1725 if (G_UNLIKELY (src_format == *dest_format || src_value == 0 ||
1728 *dest_value = src_value;
1732 if (samples == 0 || bytes == 0 || fmt->rate == 0) {
1733 GST_DEBUG ("not enough metadata yet to convert");
1739 switch (src_format) {
1740 case GST_FORMAT_BYTES:
1741 switch (*dest_format) {
1742 case GST_FORMAT_TIME:
1743 *dest_value = gst_util_uint64_scale (src_value,
1744 GST_SECOND * samples, bytes);
1751 case GST_FORMAT_TIME:
1752 switch (*dest_format) {
1753 case GST_FORMAT_BYTES:
1754 *dest_value = gst_util_uint64_scale (src_value, bytes,
1755 samples * GST_SECOND);
1771 gst_audio_decoder_sink_query (GstPad * pad, GstQuery * query)
1773 gboolean res = TRUE;
1774 GstAudioDecoder *dec;
1776 dec = GST_AUDIO_DECODER (gst_pad_get_parent (pad));
1778 switch (GST_QUERY_TYPE (query)) {
1779 case GST_QUERY_FORMATS:
1781 gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
1785 case GST_QUERY_CONVERT:
1787 GstFormat src_fmt, dest_fmt;
1788 gint64 src_val, dest_val;
1790 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
1791 if (!(res = gst_audio_encoded_audio_convert (&dec->priv->ctx.info,
1792 dec->priv->bytes_in, dec->priv->samples_out,
1793 src_fmt, src_val, &dest_fmt, &dest_val)))
1795 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
1799 res = gst_pad_query_default (pad, query);
1804 gst_object_unref (dec);
1808 static const GstQueryType *
1809 gst_audio_decoder_get_query_types (GstPad * pad)
1811 static const GstQueryType gst_audio_decoder_src_query_types[] = {
1819 return gst_audio_decoder_src_query_types;
1822 /* FIXME ? are any of these queries (other than latency) a decoder's business ??
1823 * also, the conversion stuff might seem to make sense, but seems to not mind
1824 * segment stuff etc at all
1825 * Supposedly that's backward compatibility ... */
1827 gst_audio_decoder_src_query (GstPad * pad, GstQuery * query)
1829 GstAudioDecoder *dec;
1831 gboolean res = FALSE;
1833 dec = GST_AUDIO_DECODER (GST_PAD_PARENT (pad));
1834 if (G_UNLIKELY (dec == NULL))
1837 peerpad = gst_pad_get_peer (GST_PAD (dec->sinkpad));
1839 GST_LOG_OBJECT (dec, "handling query: %" GST_PTR_FORMAT, query);
1841 switch (GST_QUERY_TYPE (query)) {
1842 case GST_QUERY_DURATION:
1846 /* upstream in any case */
1847 if ((res = gst_pad_query_default (pad, query)))
1850 gst_query_parse_duration (query, &format, NULL);
1851 /* try answering TIME by converting from BYTE if subclass allows */
1852 if (format == GST_FORMAT_TIME && gst_audio_decoder_do_byte (dec)) {
1855 format = GST_FORMAT_BYTES;
1856 if (gst_pad_query_peer_duration (dec->sinkpad, &format, &value)) {
1857 GST_LOG_OBJECT (dec, "upstream size %" G_GINT64_FORMAT, value);
1858 format = GST_FORMAT_TIME;
1859 if (gst_pad_query_convert (dec->sinkpad, GST_FORMAT_BYTES, value,
1861 gst_query_set_duration (query, GST_FORMAT_TIME, value);
1868 case GST_QUERY_POSITION:
1873 if ((res = gst_pad_peer_query (dec->sinkpad, query))) {
1874 GST_LOG_OBJECT (dec, "returning peer response");
1878 /* we start from the last seen time */
1879 time = dec->segment.last_stop;
1880 /* correct for the segment values */
1881 time = gst_segment_to_stream_time (&dec->segment, GST_FORMAT_TIME, time);
1883 GST_LOG_OBJECT (dec,
1884 "query %p: our time: %" GST_TIME_FORMAT, query, GST_TIME_ARGS (time));
1886 /* and convert to the final format */
1887 gst_query_parse_position (query, &format, NULL);
1888 if (!(res = gst_pad_query_convert (pad, GST_FORMAT_TIME, time,
1892 gst_query_set_position (query, format, value);
1894 GST_LOG_OBJECT (dec,
1895 "query %p: we return %" G_GINT64_FORMAT " (format %u)", query, value,
1899 case GST_QUERY_FORMATS:
1901 gst_query_set_formats (query, 3,
1902 GST_FORMAT_TIME, GST_FORMAT_BYTES, GST_FORMAT_DEFAULT);
1906 case GST_QUERY_CONVERT:
1908 GstFormat src_fmt, dest_fmt;
1909 gint64 src_val, dest_val;
1911 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
1912 if (!(res = gst_audio_info_convert (&dec->priv->ctx.info,
1913 src_fmt, src_val, dest_fmt, &dest_val)))
1915 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
1918 case GST_QUERY_LATENCY:
1920 if ((res = gst_pad_peer_query (dec->sinkpad, query))) {
1922 GstClockTime min_latency, max_latency;
1924 gst_query_parse_latency (query, &live, &min_latency, &max_latency);
1925 GST_DEBUG_OBJECT (dec, "Peer latency: live %d, min %"
1926 GST_TIME_FORMAT " max %" GST_TIME_FORMAT, live,
1927 GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency));
1929 GST_OBJECT_LOCK (dec);
1930 /* add our latency */
1931 if (min_latency != -1)
1932 min_latency += dec->priv->ctx.min_latency;
1933 if (max_latency != -1)
1934 max_latency += dec->priv->ctx.max_latency;
1935 GST_OBJECT_UNLOCK (dec);
1937 gst_query_set_latency (query, live, min_latency, max_latency);
1942 res = gst_pad_query_default (pad, query);
1946 gst_object_unref (peerpad);
1951 gst_audio_decoder_stop (GstAudioDecoder * dec)
1953 GstAudioDecoderClass *klass;
1954 gboolean ret = TRUE;
1956 GST_DEBUG_OBJECT (dec, "gst_audio_decoder_stop");
1958 klass = GST_AUDIO_DECODER_GET_CLASS (dec);
1961 ret = klass->stop (dec);
1965 gst_audio_decoder_reset (dec, TRUE);
1968 dec->priv->active = FALSE;
1974 gst_audio_decoder_start (GstAudioDecoder * dec)
1976 GstAudioDecoderClass *klass;
1977 gboolean ret = TRUE;
1979 GST_DEBUG_OBJECT (dec, "gst_audio_decoder_start");
1981 klass = GST_AUDIO_DECODER_GET_CLASS (dec);
1983 /* arrange clean state */
1984 gst_audio_decoder_reset (dec, TRUE);
1987 ret = klass->start (dec);
1991 dec->priv->active = TRUE;
1997 gst_audio_decoder_get_property (GObject * object, guint prop_id,
1998 GValue * value, GParamSpec * pspec)
2000 GstAudioDecoder *dec;
2002 dec = GST_AUDIO_DECODER (object);
2006 g_value_set_int64 (value, dec->priv->latency);
2008 case PROP_TOLERANCE:
2009 g_value_set_int64 (value, dec->priv->tolerance);
2012 g_value_set_boolean (value, dec->priv->plc);
2015 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2021 gst_audio_decoder_set_property (GObject * object, guint prop_id,
2022 const GValue * value, GParamSpec * pspec)
2024 GstAudioDecoder *dec;
2026 dec = GST_AUDIO_DECODER (object);
2030 dec->priv->latency = g_value_get_int64 (value);
2032 case PROP_TOLERANCE:
2033 dec->priv->tolerance = g_value_get_int64 (value);
2036 dec->priv->plc = g_value_get_boolean (value);
2039 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2044 static GstStateChangeReturn
2045 gst_audio_decoder_change_state (GstElement * element, GstStateChange transition)
2047 GstAudioDecoder *codec;
2048 GstStateChangeReturn ret;
2050 codec = GST_AUDIO_DECODER (element);
2052 switch (transition) {
2053 case GST_STATE_CHANGE_NULL_TO_READY:
2055 case GST_STATE_CHANGE_READY_TO_PAUSED:
2056 if (!gst_audio_decoder_start (codec)) {
2060 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
2066 ret = parent_class->change_state (element, transition);
2068 switch (transition) {
2069 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
2071 case GST_STATE_CHANGE_PAUSED_TO_READY:
2072 if (!gst_audio_decoder_stop (codec)) {
2076 case GST_STATE_CHANGE_READY_TO_NULL:
2086 GST_ELEMENT_ERROR (codec, LIBRARY, INIT, (NULL), ("Failed to start codec"));
2087 return GST_STATE_CHANGE_FAILURE;
2091 GST_ELEMENT_ERROR (codec, LIBRARY, INIT, (NULL), ("Failed to stop codec"));
2092 return GST_STATE_CHANGE_FAILURE;
2097 _gst_audio_decoder_error (GstAudioDecoder * dec, gint weight,
2098 GQuark domain, gint code, gchar * txt, gchar * dbg, const gchar * file,
2099 const gchar * function, gint line)
2102 GST_WARNING_OBJECT (dec, "error: %s", txt);
2104 GST_WARNING_OBJECT (dec, "error: %s", dbg);
2105 dec->priv->error_count += weight;
2106 dec->priv->discont = TRUE;
2107 if (dec->priv->ctx.max_errors < dec->priv->error_count) {
2108 gst_element_message_full (GST_ELEMENT (dec), GST_MESSAGE_ERROR,
2109 domain, code, txt, dbg, file, function, line);
2110 return GST_FLOW_ERROR;
2117 * gst_audio_decoder_get_audio_info:
2118 * @dec: a #GstAudioDecoder
2120 * Returns: a #GstAudioInfo describing the input audio format
2125 gst_audio_decoder_get_audio_info (GstAudioDecoder * dec)
2127 g_return_val_if_fail (GST_IS_AUDIO_DECODER (dec), NULL);
2129 return &dec->priv->ctx.info;
2133 * gst_audio_decoder_set_plc_aware:
2134 * @dec: a #GstAudioDecoder
2135 * @plc: new plc state
2137 * Indicates whether or not subclass handles packet loss concealment (plc).
2142 gst_audio_decoder_set_plc_aware (GstAudioDecoder * dec, gboolean plc)
2144 g_return_if_fail (GST_IS_AUDIO_DECODER (dec));
2146 dec->priv->ctx.do_plc = plc;
2150 * gst_audio_decoder_get_plc_aware:
2151 * @dec: a #GstAudioDecoder
2153 * Returns: currently configured plc handling
2158 gst_audio_decoder_get_plc_aware (GstAudioDecoder * dec)
2160 g_return_val_if_fail (GST_IS_AUDIO_DECODER (dec), 0);
2162 return dec->priv->ctx.do_plc;
2166 * gst_audio_decoder_set_byte_time:
2167 * @dec: a #GstAudioDecoder
2168 * @enabled: whether to enable byte to time conversion
2170 * Allows baseclass to perform byte to time estimated conversion.
2175 gst_audio_decoder_set_byte_time (GstAudioDecoder * dec, gboolean enabled)
2177 g_return_if_fail (GST_IS_AUDIO_DECODER (dec));
2179 dec->priv->ctx.do_byte_time = enabled;
2183 * gst_audio_decoder_get_byte_time:
2184 * @dec: a #GstAudioDecoder
2186 * Returns: currently configured byte to time conversion setting
2191 gst_audio_decoder_get_byte_time (GstAudioDecoder * dec)
2193 g_return_val_if_fail (GST_IS_AUDIO_DECODER (dec), 0);
2195 return dec->priv->ctx.do_byte_time;
2199 * gst_audio_decoder_get_delay:
2200 * @dec: a #GstAudioDecoder
2202 * Returns: currently configured decoder delay
2207 gst_audio_decoder_get_delay (GstAudioDecoder * dec)
2209 g_return_val_if_fail (GST_IS_AUDIO_DECODER (dec), 0);
2211 return dec->priv->ctx.delay;
2215 * gst_audio_decoder_set_max_errors:
2216 * @dec: a #GstAudioDecoder
2217 * @num: max tolerated errors
2219 * Sets numbers of tolerated decoder errors, where a tolerated one is then only
2220 * warned about, but more than tolerated will lead to fatal error.
2225 gst_audio_decoder_set_max_errors (GstAudioDecoder * dec, gint num)
2227 g_return_if_fail (GST_IS_AUDIO_DECODER (dec));
2229 dec->priv->ctx.max_errors = num;
2233 * gst_audio_decoder_get_max_errors:
2234 * @dec: a #GstAudioDecoder
2236 * Returns: currently configured decoder tolerated error count.
2241 gst_audio_decoder_get_max_errors (GstAudioDecoder * dec)
2243 g_return_val_if_fail (GST_IS_AUDIO_DECODER (dec), 0);
2245 return dec->priv->ctx.max_errors;
2249 * gst_audio_decoder_set_latency:
2250 * @dec: a #GstAudioDecoder
2251 * @min: minimum latency
2252 * @max: maximum latency
2254 * Sets decoder latency.
2259 gst_audio_decoder_set_latency (GstAudioDecoder * dec,
2260 GstClockTime min, GstClockTime max)
2262 g_return_if_fail (GST_IS_AUDIO_DECODER (dec));
2264 GST_OBJECT_LOCK (dec);
2265 dec->priv->ctx.min_latency = min;
2266 dec->priv->ctx.max_latency = max;
2267 GST_OBJECT_UNLOCK (dec);
2271 * gst_audio_decoder_get_latency:
2272 * @dec: a #GstAudioDecoder
2273 * @min: (out) (allow-none): a pointer to storage to hold minimum latency
2274 * @max: (out) (allow-none): a pointer to storage to hold maximum latency
2276 * Sets the variables pointed to by @min and @max to the currently configured
2282 gst_audio_decoder_get_latency (GstAudioDecoder * dec,
2283 GstClockTime * min, GstClockTime * max)
2285 g_return_if_fail (GST_IS_AUDIO_DECODER (dec));
2287 GST_OBJECT_LOCK (dec);
2289 *min = dec->priv->ctx.min_latency;
2291 *max = dec->priv->ctx.max_latency;
2292 GST_OBJECT_UNLOCK (dec);
2296 * gst_audio_decoder_get_parse_state:
2297 * @dec: a #GstAudioDecoder
2298 * @sync: a pointer to a variable to hold the current sync state
2299 * @eos: a pointer to a variable to hold the current eos state
2301 * Return current parsing (sync and eos) state.
2306 gst_audio_decoder_get_parse_state (GstAudioDecoder * dec,
2307 gboolean * sync, gboolean * eos)
2309 g_return_if_fail (GST_IS_AUDIO_DECODER (dec));
2312 *sync = dec->priv->ctx.sync;
2314 *eos = dec->priv->ctx.eos;
2318 * gst_audio_decoder_set_plc:
2319 * @dec: a #GstAudioDecoder
2320 * @enabled: new state
2322 * Enable or disable decoder packet loss concealment, provided subclass
2323 * and codec are capable and allow handling plc.
2330 gst_audio_decoder_set_plc (GstAudioDecoder * dec, gboolean enabled)
2332 g_return_if_fail (GST_IS_AUDIO_DECODER (dec));
2334 GST_LOG_OBJECT (dec, "enabled: %d", enabled);
2336 GST_OBJECT_LOCK (dec);
2337 dec->priv->plc = enabled;
2338 GST_OBJECT_UNLOCK (dec);
2342 * gst_audio_decoder_get_plc:
2343 * @dec: a #GstAudioDecoder
2345 * Queries decoder packet loss concealment handling.
2347 * Returns: TRUE if packet loss concealment is enabled.
2354 gst_audio_decoder_get_plc (GstAudioDecoder * dec)
2358 g_return_val_if_fail (GST_IS_AUDIO_DECODER (dec), FALSE);
2360 GST_OBJECT_LOCK (dec);
2361 result = dec->priv->plc;
2362 GST_OBJECT_UNLOCK (dec);
2368 * gst_audio_decoder_set_min_latency:
2369 * @dec: a #GstAudioDecoder
2370 * @num: new minimum latency
2372 * Sets decoder minimum aggregation latency.
2379 gst_audio_decoder_set_min_latency (GstAudioDecoder * dec, gint64 num)
2381 g_return_if_fail (GST_IS_AUDIO_DECODER (dec));
2383 GST_OBJECT_LOCK (dec);
2384 dec->priv->latency = num;
2385 GST_OBJECT_UNLOCK (dec);
2389 * gst_audio_decoder_get_min_latency:
2390 * @dec: a #GstAudioDecoder
2392 * Queries decoder's latency aggregation.
2394 * Returns: aggregation latency.
2401 gst_audio_decoder_get_min_latency (GstAudioDecoder * dec)
2405 g_return_val_if_fail (GST_IS_AUDIO_DECODER (dec), FALSE);
2407 GST_OBJECT_LOCK (dec);
2408 result = dec->priv->latency;
2409 GST_OBJECT_UNLOCK (dec);
2415 * gst_audio_decoder_set_tolerance:
2416 * @dec: a #GstAudioDecoder
2417 * @tolerance: new tolerance
2419 * Configures decoder audio jitter tolerance threshold.
2426 gst_audio_decoder_set_tolerance (GstAudioDecoder * dec, gint64 tolerance)
2428 g_return_if_fail (GST_IS_AUDIO_DECODER (dec));
2430 GST_OBJECT_LOCK (dec);
2431 dec->priv->tolerance = tolerance;
2432 GST_OBJECT_UNLOCK (dec);
2436 * gst_audio_decoder_get_tolerance:
2437 * @dec: a #GstAudioDecoder
2439 * Queries current audio jitter tolerance threshold.
2441 * Returns: decoder audio jitter tolerance threshold.
2448 gst_audio_decoder_get_tolerance (GstAudioDecoder * dec)
2452 g_return_val_if_fail (GST_IS_AUDIO_DECODER (dec), 0);
2454 GST_OBJECT_LOCK (dec);
2455 result = dec->priv->tolerance;
2456 GST_OBJECT_UNLOCK (dec);