2 * Copyright (C) <2017> Carlos Rafael Giani <dv at pseudoterminal dot org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
22 * SECTION:gstnonstreamaudiodecoder
23 * @short_description: Base class for decoding of non-streaming audio
24 * @see_also: #GstAudioDecoder
26 * This base class is for decoders which do not operate on a streaming model.
27 * That is: they load the encoded media at once, as part of an initialization,
28 * and afterwards can decode samples (sometimes referred to as "rendering the
31 * This sets it apart from GstAudioDecoder, which is a base class for
32 * streaming audio decoders.
34 * The base class is conceptually a mix between decoder and parser. This is
35 * unavoidable, since virtually no format that isn't streaming based has a
36 * clear distinction between parsing and decoding. As a result, this class
37 * also handles seeking.
39 * Non-streaming audio formats tend to have some characteristics unknown to
40 * more "regular" bitstreams. These include subsongs and looping.
42 * Subsongs are a set of songs-within-a-song. An analogy would be a multitrack
43 * recording, where each track is its own song. The first subsong is typically
44 * the "main" one. Subsongs were popular for video games to enable context-
45 * aware music; for example, subsong `#0` would be the "main" song, `#1` would be
46 * an alternate song playing when a fight started, `#2` would be heard during
47 * conversations etc. The base class is designed to always have at least one
48 * subsong. If the subclass doesn't provide any, the base class creates a
49 * "pseudo" subsong, which is actually the whole song.
50 * Downstream is informed about the subsong using a table of contents (TOC),
51 * but only if there are at least 2 subsongs.
53 * Looping refers to jumps within the song, typically backwards to the loop
54 * start (although bi-directional looping is possible). The loop is defined
55 * by a chronological start and end; once the playback position reaches the
56 * loop end, it jumps back to the loop start.
57 * Depending on the subclass, looping may not be possible at all, or it
58 * may only be possible to enable/disable it (that is, either no looping, or
59 * an infinite amount of loops), or it may allow for defining a finite number
60 * of times the loop is repeated.
61 * Looping can affect output in two ways. Either, the playback position is
62 * reset to the start of the loop, similar to what happens after a seek event.
63 * Or, it is not reset, so the pipeline sees playback steadily moving forwards,
64 * the playback position monotonically increasing. However, seeking must
65 * always happen within the confines of the defined subsong duration; for
66 * example, if a subsong is 2 minutes long, steady playback is at 5 minutes
67 * (because infinite looping is enabled), then seeking will still place the
68 * position within the 2 minute period.
69 * Loop count 0 means no looping. Loop count -1 means infinite looping.
70 * Nonzero positive values indicate how often a loop shall occur.
72 * If the initial subsong and loop count are set to values the subclass does
73 * not support, the subclass has a chance to correct these values.
74 * @get_property then reports the corrected versions.
76 * The base class operates as follows:
78 * - Initial values are set. If a current subsong has already been
79 * defined (for example over the command line with gst-launch), then
80 * the subsong index is copied over to current_subsong .
81 * Same goes for the num-loops and output-mode properties.
82 * Media is NOT loaded yet.
83 * - Once the sinkpad is activated, the process continues. The sinkpad is
84 * activated in push mode, and the class accumulates the incoming media
85 * data in an adapter inside the sinkpad's chain function until either an
86 * EOS event is received from upstream, or the number of bytes reported
87 * by upstream is reached. Then it loads the media, and starts the decoder
89 * - If upstream cannot respond to the size query (in bytes) of @load_from_buffer
90 * fails, an error is reported, and the pipeline stops.
91 * - If there are no errors, @load_from_buffer is called to load the media. The
92 * subclass must at least call gst_nonstream_audio_decoder_set_output_format()
93 * there, and is free to make use of the initial subsong, output mode, and
94 * position. If the actual output mode or position differs from the initial
95 * value,it must set the initial value to the actual one (for example, if
96 * the actual starting position is always 0, set *initial_position to 0).
97 * If loading is unsuccessful, an error is reported, and the pipeline
98 * stops. Otherwise, the base class calls @get_current_subsong to retrieve
99 * the actual current subsong, @get_subsong_duration to report the current
100 * subsong's duration in a duration event and message, and @get_subsong_tags
101 * to send tags downstream in an event (these functions are optional; if
102 * set to NULL, the associated operation is skipped). Afterwards, the base
103 * class switches to loaded mode, and starts the decoder output task.
105 * * Loaded mode</title>
106 * - Inside the decoder output task, the base class repeatedly calls @decode,
107 * which returns a buffer with decoded, ready-to-play samples. If the
108 * subclass reached the end of playback, @decode returns FALSE, otherwise
110 * - Upon reaching a loop end, subclass either ignores that, or loops back
111 * to the beginning of the loop. In the latter case, if the output mode is set
112 * to LOOPING, the subclass must call gst_nonstream_audio_decoder_handle_loop()
113 * *after* the playback position moved to the start of the loop. In
114 * STEADY mode, the subclass must *not* call this function.
115 * Since many decoders only provide a callback for when the looping occurs,
116 * and that looping occurs inside the decoding operation itself, the following
117 * mechanism for subclass is suggested: set a flag inside such a callback.
118 * Then, in the next @decode call, before doing the decoding, check this flag.
119 * If it is set, gst_nonstream_audio_decoder_handle_loop() is called, and the
121 * (This function call is necessary in LOOPING mode because it updates the
122 * current segment and makes sure the next buffer that is sent downstream
123 * has its DISCONT flag set.)
124 * - When the current subsong is switched, @set_current_subsong is called.
125 * If it fails, a warning is reported, and nothing else is done. Otherwise,
126 * it calls @get_subsong_duration to get the new current subsongs's
127 * duration, @get_subsong_tags to get its tags, reports a new duration
128 * (i.e. it sends a duration event downstream and generates a duration
129 * message), updates the current segment, and sends the subsong's tags in
130 * an event downstream. (If @set_current_subsong has been set to NULL by
131 * the subclass, attempts to set a current subsong are ignored; likewise,
132 * if @get_subsong_duration is NULL, no duration is reported, and if
133 * @get_subsong_tags is NULL, no tags are sent downstream.)
134 * - When an attempt is made to switch the output mode, it is checked against
135 * the bitmask returned by @get_supported_output_modes. If the proposed
136 * new output mode is supported, the current segment is updated
137 * (it is open-ended in STEADY mode, and covers the (sub)song length in
138 * LOOPING mode), and the subclass' @set_output_mode function is called
139 * unless it is set to NULL. Subclasses should reset internal loop counters
142 * The relationship between (sub)song duration, output mode, and number of loops
143 * is defined this way (this is all done by the base class automatically):
145 * * Segments have their duration and stop values set to GST_CLOCK_TIME_NONE in
146 * STEADY mode, and to the duration of the (sub)song in LOOPING mode.
148 * * The duration that is returned to a DURATION query is always the duration
149 * of the (sub)song, regardless of number of loops or output mode. The same
150 * goes for DURATION messages and tags.
152 * * If the number of loops is >0 or -1, durations of TOC entries are set to
153 * the duration of the respective subsong in LOOPING mode and to G_MAXINT64 in
154 * STEADY mode. If the number of loops is 0, entry durations are set to the
155 * subsong duration regardless of the output mode.
164 #include <gst/audio/audio.h>
166 #include "gstnonstreamaudiodecoder.h"
169 GST_DEBUG_CATEGORY (nonstream_audiodecoder_debug);
170 #define GST_CAT_DEFAULT nonstream_audiodecoder_debug
176 PROP_CURRENT_SUBSONG,
182 #define DEFAULT_CURRENT_SUBSONG 0
183 #define DEFAULT_SUBSONG_MODE GST_NONSTREAM_AUDIO_SUBSONG_MODE_DECODER_DEFAULT
184 #define DEFAULT_NUM_SUBSONGS 0
185 #define DEFAULT_NUM_LOOPS 0
186 #define DEFAULT_OUTPUT_MODE GST_NONSTREAM_AUDIO_OUTPUT_MODE_STEADY
191 static GstElementClass *gst_nonstream_audio_decoder_parent_class = NULL;
194 gst_nonstream_audio_decoder_class_init (GstNonstreamAudioDecoderClass * klass);
195 static void gst_nonstream_audio_decoder_init (GstNonstreamAudioDecoder * dec,
196 GstNonstreamAudioDecoderClass * klass);
198 static void gst_nonstream_audio_decoder_finalize (GObject * object);
199 static void gst_nonstream_audio_decoder_set_property (GObject * object,
200 guint prop_id, GValue const *value, GParamSpec * pspec);
201 static void gst_nonstream_audio_decoder_get_property (GObject * object,
202 guint prop_id, GValue * value, GParamSpec * pspec);
204 static GstStateChangeReturn gst_nonstream_audio_decoder_change_state (GstElement
205 * element, GstStateChange transition);
207 static gboolean gst_nonstream_audio_decoder_sink_event (GstPad * pad,
208 GstObject * parent, GstEvent * event);
209 static gboolean gst_nonstream_audio_decoder_sink_query (GstPad * pad,
210 GstObject * parent, GstQuery * query);
211 static GstFlowReturn gst_nonstream_audio_decoder_chain (GstPad * pad,
212 GstObject * parent, GstBuffer * buffer);
214 static gboolean gst_nonstream_audio_decoder_src_event (GstPad * pad,
215 GstObject * parent, GstEvent * event);
216 static gboolean gst_nonstream_audio_decoder_src_query (GstPad * pad,
217 GstObject * parent, GstQuery * query);
220 gst_nonstream_audio_decoder_set_initial_state (GstNonstreamAudioDecoder * dec);
221 static void gst_nonstream_audio_decoder_cleanup_state (GstNonstreamAudioDecoder
224 static gboolean gst_nonstream_audio_decoder_negotiate (GstNonstreamAudioDecoder
228 gst_nonstream_audio_decoder_negotiate_default (GstNonstreamAudioDecoder * dec);
230 gst_nonstream_audio_decoder_decide_allocation_default (GstNonstreamAudioDecoder
231 * dec, GstQuery * query);
233 gst_nonstream_audio_decoder_propose_allocation_default (GstNonstreamAudioDecoder
234 * dec, GstQuery * query);
237 gst_nonstream_audio_decoder_get_upstream_size (GstNonstreamAudioDecoder * dec,
240 gst_nonstream_audio_decoder_load_from_buffer (GstNonstreamAudioDecoder * dec,
243 gst_nonstream_audio_decoder_load_from_custom (GstNonstreamAudioDecoder * dec);
245 gst_nonstream_audio_decoder_finish_load (GstNonstreamAudioDecoder * dec,
246 gboolean load_ok, GstClockTime initial_position,
247 gboolean send_stream_start);
249 static gboolean gst_nonstream_audio_decoder_start_task (GstNonstreamAudioDecoder
251 static gboolean gst_nonstream_audio_decoder_stop_task (GstNonstreamAudioDecoder
255 gst_nonstream_audio_decoder_switch_to_subsong (GstNonstreamAudioDecoder * dec,
256 guint new_subsong, guint32 const *seqnum);
258 static void gst_nonstream_audio_decoder_update_toc (GstNonstreamAudioDecoder *
259 dec, GstNonstreamAudioDecoderClass * klass);
261 gst_nonstream_audio_decoder_update_subsong_duration (GstNonstreamAudioDecoder *
262 dec, GstClockTime duration);
264 gst_nonstream_audio_decoder_output_new_segment (GstNonstreamAudioDecoder * dec,
265 GstClockTime start_position);
266 static gboolean gst_nonstream_audio_decoder_do_seek (GstNonstreamAudioDecoder *
267 dec, GstEvent * event);
270 * gst_nonstream_audio_decoder_add_main_tags (GstNonstreamAudioDecoder * dec,
273 static void gst_nonstream_audio_decoder_output_task (GstNonstreamAudioDecoder *
276 static char const *get_seek_type_name (GstSeekType seek_type);
281 static GType gst_nonstream_audio_decoder_output_mode_get_type (void);
282 #define GST_TYPE_NONSTREAM_AUDIO_DECODER_OUTPUT_MODE (gst_nonstream_audio_decoder_output_mode_get_type())
284 static GType gst_nonstream_audio_decoder_subsong_mode_get_type (void);
285 #define GST_TYPE_NONSTREAM_AUDIO_DECODER_SUBSONG_MODE (gst_nonstream_audio_decoder_subsong_mode_get_type())
289 gst_nonstream_audio_decoder_output_mode_get_type (void)
291 static GType gst_nonstream_audio_decoder_output_mode_type = 0;
293 if (!gst_nonstream_audio_decoder_output_mode_type) {
294 static GEnumValue output_mode_values[] = {
295 {GST_NONSTREAM_AUDIO_OUTPUT_MODE_LOOPING, "Looping output", "looping"},
296 {GST_NONSTREAM_AUDIO_OUTPUT_MODE_STEADY, "Steady output", "steady"},
300 gst_nonstream_audio_decoder_output_mode_type =
301 g_enum_register_static ("GstNonstreamAudioOutputMode",
305 return gst_nonstream_audio_decoder_output_mode_type;
310 gst_nonstream_audio_decoder_subsong_mode_get_type (void)
312 static GType gst_nonstream_audio_decoder_subsong_mode_type = 0;
314 if (!gst_nonstream_audio_decoder_subsong_mode_type) {
315 static GEnumValue subsong_mode_values[] = {
316 {GST_NONSTREAM_AUDIO_SUBSONG_MODE_SINGLE, "Play single subsong",
318 {GST_NONSTREAM_AUDIO_SUBSONG_MODE_ALL, "Play all subsongs", "all"},
319 {GST_NONSTREAM_AUDIO_SUBSONG_MODE_DECODER_DEFAULT,
320 "Decoder specific default behavior", "default"},
324 gst_nonstream_audio_decoder_subsong_mode_type =
325 g_enum_register_static ("GstNonstreamAudioSubsongMode",
326 subsong_mode_values);
329 return gst_nonstream_audio_decoder_subsong_mode_type;
334 /* Manually defining the GType instead of using G_DEFINE_TYPE_WITH_CODE()
335 * because the _init() function needs to be able to access the derived
336 * class' sink- and srcpads */
340 gst_nonstream_audio_decoder_get_type (void)
342 static gsize nonstream_audio_decoder_type = 0;
344 if (g_once_init_enter (&nonstream_audio_decoder_type)) {
346 static const GTypeInfo nonstream_audio_decoder_info = {
347 sizeof (GstNonstreamAudioDecoderClass),
350 (GClassInitFunc) gst_nonstream_audio_decoder_class_init,
353 sizeof (GstNonstreamAudioDecoder),
355 (GInstanceInitFunc) gst_nonstream_audio_decoder_init,
359 type_ = g_type_register_static (GST_TYPE_ELEMENT,
360 "GstNonstreamAudioDecoder",
361 &nonstream_audio_decoder_info, G_TYPE_FLAG_ABSTRACT);
362 g_once_init_leave (&nonstream_audio_decoder_type, type_);
365 return nonstream_audio_decoder_type;
372 gst_nonstream_audio_decoder_class_init (GstNonstreamAudioDecoderClass * klass)
374 GObjectClass *object_class;
375 GstElementClass *element_class;
377 object_class = G_OBJECT_CLASS (klass);
378 element_class = GST_ELEMENT_CLASS (klass);
380 gst_nonstream_audio_decoder_parent_class = g_type_class_peek_parent (klass);
382 GST_DEBUG_CATEGORY_INIT (nonstream_audiodecoder_debug,
383 "nonstreamaudiodecoder", 0, "nonstream audio decoder base class");
385 object_class->finalize =
386 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_finalize);
387 object_class->set_property =
388 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_set_property);
389 object_class->get_property =
390 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_get_property);
391 element_class->change_state =
392 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_change_state);
397 klass->load_from_buffer = NULL;
398 klass->load_from_custom = NULL;
400 klass->get_main_tags = NULL;
402 klass->get_current_subsong = NULL;
403 klass->set_current_subsong = NULL;
405 klass->get_num_subsongs = NULL;
406 klass->get_subsong_duration = NULL;
407 klass->get_subsong_tags = NULL;
408 klass->set_subsong_mode = NULL;
410 klass->set_num_loops = NULL;
411 klass->get_num_loops = NULL;
413 klass->decode = NULL;
416 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_negotiate_default);
418 klass->decide_allocation =
419 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_decide_allocation_default);
420 klass->propose_allocation =
422 (gst_nonstream_audio_decoder_propose_allocation_default);
424 klass->loads_from_sinkpad = TRUE;
426 g_object_class_install_property (object_class,
427 PROP_CURRENT_SUBSONG,
428 g_param_spec_uint ("current-subsong",
429 "Currently active subsong",
430 "Subsong that is currently selected for playback",
432 DEFAULT_CURRENT_SUBSONG, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
435 g_object_class_install_property (object_class,
437 g_param_spec_enum ("subsong-mode",
439 "Mode which defines how to treat subsongs",
440 GST_TYPE_NONSTREAM_AUDIO_DECODER_SUBSONG_MODE,
441 DEFAULT_SUBSONG_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
444 g_object_class_install_property (object_class,
446 g_param_spec_int ("num-loops",
447 "Number of playback loops",
448 "Number of times a playback loop shall be executed (special values: 0 = no looping; -1 = infinite loop)",
450 DEFAULT_NUM_LOOPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
453 g_object_class_install_property (object_class,
455 g_param_spec_enum ("output-mode",
457 "Which mode playback shall use when a loop is encountered; looping = reset position to start of loop, steady = do not reset position",
458 GST_TYPE_NONSTREAM_AUDIO_DECODER_OUTPUT_MODE,
459 DEFAULT_OUTPUT_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
465 gst_nonstream_audio_decoder_init (GstNonstreamAudioDecoder * dec,
466 GstNonstreamAudioDecoderClass * klass)
468 GstPadTemplate *pad_template;
470 /* These are set here, not in gst_nonstream_audio_decoder_set_initial_state(),
471 * because these are values for the properties; they are not supposed to be
472 * reset in the READY->NULL state change */
473 dec->current_subsong = DEFAULT_CURRENT_SUBSONG;
474 dec->subsong_mode = DEFAULT_SUBSONG_MODE;
475 dec->output_mode = DEFAULT_OUTPUT_MODE;
476 dec->num_loops = DEFAULT_NUM_LOOPS;
478 /* Calling this here, not in the NULL->READY state change,
479 * to make sure get_property calls return valid values */
480 gst_nonstream_audio_decoder_set_initial_state (dec);
482 dec->input_data_adapter = gst_adapter_new ();
483 g_mutex_init (&(dec->mutex));
489 gst_element_class_get_pad_template (GST_ELEMENT_CLASS (klass), "src");
490 g_return_if_fail (pad_template != NULL); /* derived class is supposed to define a src pad template */
492 dec->srcpad = gst_pad_new_from_template (pad_template, "src");
493 gst_pad_set_event_function (dec->srcpad,
494 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_src_event));
495 gst_pad_set_query_function (dec->srcpad,
496 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_src_query));
497 gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
500 if (klass->loads_from_sinkpad) {
501 /* set up sink pad if this class loads from a sinkpad */
504 gst_element_class_get_pad_template (GST_ELEMENT_CLASS (klass), "sink");
505 g_return_if_fail (pad_template != NULL); /* derived class is supposed to define a sink pad template */
507 dec->sinkpad = gst_pad_new_from_template (pad_template, "sink");
508 gst_pad_set_event_function (dec->sinkpad,
509 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_sink_event));
510 gst_pad_set_query_function (dec->sinkpad,
511 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_sink_query));
512 gst_pad_set_chain_function (dec->sinkpad,
513 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_chain));
514 gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad);
522 gst_nonstream_audio_decoder_finalize (GObject * object)
524 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (object);
526 g_mutex_clear (&(dec->mutex));
527 g_object_unref (G_OBJECT (dec->input_data_adapter));
529 G_OBJECT_CLASS (gst_nonstream_audio_decoder_parent_class)->finalize (object);
534 gst_nonstream_audio_decoder_set_property (GObject * object, guint prop_id,
535 GValue const *value, GParamSpec * pspec)
537 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (object);
538 GstNonstreamAudioDecoderClass *klass =
539 GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
542 case PROP_OUTPUT_MODE:
544 GstNonstreamAudioOutputMode new_output_mode;
545 new_output_mode = g_value_get_enum (value);
547 g_assert (klass->get_supported_output_modes);
549 if ((klass->get_supported_output_modes (dec) & (1u << new_output_mode)) ==
551 GST_WARNING_OBJECT (dec,
552 "could not set output mode to %s (not supported by subclass)",
554 GST_NONSTREAM_AUDIO_OUTPUT_MODE_STEADY) ? "steady" : "looping");
558 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
559 if (new_output_mode != dec->output_mode) {
560 gboolean proceed = TRUE;
562 if (dec->loaded_mode) {
563 GstClockTime cur_position;
565 if (klass->set_output_mode != NULL) {
566 if (klass->set_output_mode (dec, new_output_mode, &cur_position))
570 GST_WARNING_OBJECT (dec, "switching to new output mode failed");
573 GST_DEBUG_OBJECT (dec,
574 "cannot call set_output_mode, since it is NULL");
579 gst_nonstream_audio_decoder_output_new_segment (dec, cur_position);
580 dec->output_mode = new_output_mode;
585 /* store output mode in case the property is set before the media got loaded */
586 dec->output_mode = new_output_mode;
589 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
594 case PROP_CURRENT_SUBSONG:
596 guint new_subsong = g_value_get_uint (value);
597 gst_nonstream_audio_decoder_switch_to_subsong (dec, new_subsong, NULL);
602 case PROP_SUBSONG_MODE:
604 GstNonstreamAudioSubsongMode new_subsong_mode = g_value_get_enum (value);
606 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
607 if (new_subsong_mode != dec->subsong_mode) {
608 gboolean proceed = TRUE;
610 if (dec->loaded_mode) {
611 GstClockTime cur_position;
613 if (klass->set_subsong_mode != NULL) {
614 if (klass->set_subsong_mode (dec, new_subsong_mode, &cur_position))
618 GST_WARNING_OBJECT (dec, "switching to new subsong mode failed");
621 GST_DEBUG_OBJECT (dec,
622 "cannot call set_subsong_mode, since it is NULL");
627 if (GST_CLOCK_TIME_IS_VALID (cur_position))
628 gst_nonstream_audio_decoder_output_new_segment (dec,
630 dec->subsong_mode = new_subsong_mode;
635 /* store subsong mode in case the property is set before the media got loaded */
636 dec->subsong_mode = new_subsong_mode;
639 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
646 gint new_num_loops = g_value_get_int (value);
648 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
649 if (new_num_loops != dec->num_loops) {
650 if (dec->loaded_mode) {
651 if (klass->set_num_loops != NULL) {
652 if (!(klass->set_num_loops (dec, new_num_loops)))
653 GST_WARNING_OBJECT (dec, "setting number of loops to %u failed",
656 GST_DEBUG_OBJECT (dec,
657 "cannot call set_num_loops, since it is NULL");
660 /* store number of loops in case the property is set before the media got loaded */
661 dec->num_loops = new_num_loops;
663 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
669 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
676 gst_nonstream_audio_decoder_get_property (GObject * object, guint prop_id,
677 GValue * value, GParamSpec * pspec)
679 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (object);
682 case PROP_OUTPUT_MODE:
684 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
685 g_value_set_enum (value, dec->output_mode);
686 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
690 case PROP_CURRENT_SUBSONG:
692 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
693 g_value_set_uint (value, dec->current_subsong);
694 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
698 case PROP_SUBSONG_MODE:
700 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
701 g_value_set_enum (value, dec->subsong_mode);
702 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
708 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
709 g_value_set_int (value, dec->num_loops);
710 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
715 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
722 static GstStateChangeReturn
723 gst_nonstream_audio_decoder_change_state (GstElement * element,
724 GstStateChange transition)
726 GstStateChangeReturn ret;
729 GST_ELEMENT_CLASS (gst_nonstream_audio_decoder_parent_class)->change_state
730 (element, transition);
731 if (ret == GST_STATE_CHANGE_FAILURE)
734 switch (transition) {
735 case GST_STATE_CHANGE_READY_TO_PAUSED:
738 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (element);
739 GstNonstreamAudioDecoderClass *klass =
740 GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
742 /* For decoders that load with some custom method,
743 * this is now the time to load
745 * It is done *after* calling the parent class' change_state vfunc,
746 * since the pad states need to be set up in order for the loading
747 * to succeed, since it will try to push a new_caps event
748 * downstream etc. (upwards state changes typically are handled
749 * *before* calling the parent class' change_state vfunc ; this is
751 if (!(klass->loads_from_sinkpad) && !(dec->loaded_mode)) {
754 /* load_from_custom is required if loads_from_sinkpad is FALSE */
755 g_assert (klass->load_from_custom != NULL);
757 ret = gst_nonstream_audio_decoder_load_from_custom (dec);
760 GST_ERROR_OBJECT (dec, "loading from custom source failed");
761 return GST_STATE_CHANGE_FAILURE;
764 if (!gst_nonstream_audio_decoder_start_task (dec))
765 return GST_STATE_CHANGE_FAILURE;
772 case GST_STATE_CHANGE_PAUSED_TO_READY:
774 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (element);
775 if (!gst_nonstream_audio_decoder_stop_task (dec))
776 return GST_STATE_CHANGE_FAILURE;
780 case GST_STATE_CHANGE_READY_TO_NULL:
782 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (element);
784 /* In the READY->NULL state change, reset the decoder to an
785 * initial state ensure it can be used for a fresh new session */
786 gst_nonstream_audio_decoder_cleanup_state (dec);
800 gst_nonstream_audio_decoder_sink_event (GstPad * pad, GstObject * parent,
803 gboolean res = FALSE;
804 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (parent);
806 switch (GST_EVENT_TYPE (event)) {
807 case GST_EVENT_SEGMENT:
809 /* Upstream sends in a byte segment, which is uninteresting here,
810 * since a custom segment event is generated anyway */
811 gst_event_unref (event);
819 GstBuffer *adapter_buffer;
821 if (dec->loaded_mode) {
822 /* If media has already been loaded, then the decoder
823 * task has been started; the EOS event can be ignored */
825 GST_DEBUG_OBJECT (dec,
826 "EOS received after media was loaded -> ignoring");
829 /* take all data in the input data adapter,
830 * and try to load the media from it */
832 avail_size = gst_adapter_available (dec->input_data_adapter);
833 if (avail_size == 0) {
834 GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL),
835 ("EOS event raised, but no data was received - cannot load anything"));
840 gst_adapter_take_buffer (dec->input_data_adapter, avail_size);
842 if (!gst_nonstream_audio_decoder_load_from_buffer (dec, adapter_buffer)) {
846 res = gst_nonstream_audio_decoder_start_task (dec);
853 res = gst_pad_event_default (pad, parent, event);
861 gst_nonstream_audio_decoder_sink_query (GstPad * pad, GstObject * parent,
864 gboolean res = FALSE;
865 GstNonstreamAudioDecoder *dec;
866 GstNonstreamAudioDecoderClass *klass;
868 dec = GST_NONSTREAM_AUDIO_DECODER (parent);
869 klass = GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
871 switch (GST_QUERY_TYPE (query)) {
872 case GST_QUERY_ALLOCATION:
874 if (klass->propose_allocation != NULL)
875 res = klass->propose_allocation (dec, query);
881 res = gst_pad_query_default (pad, parent, query);
889 gst_nonstream_audio_decoder_chain (G_GNUC_UNUSED GstPad * pad,
890 GstObject * parent, GstBuffer * buffer)
892 GstFlowReturn flow_ret = GST_FLOW_OK;
893 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (parent);
895 /* query upstream size in bytes to know how many bytes to expect
896 * this is a safety measure to prevent the case when upstream never
897 * reaches EOS (or only after a long time) and we keep loading and
898 * loading and eventually run out of memory */
899 if (dec->upstream_size < 0) {
900 if (!gst_nonstream_audio_decoder_get_upstream_size (dec,
901 &(dec->upstream_size))) {
902 GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL),
903 ("Cannot load - upstream size (in bytes) could not be determined"));
904 return GST_FLOW_ERROR;
908 if (dec->loaded_mode) {
909 /* media is already loaded - discard any incoming
910 * buffers, since they are not needed */
912 GST_DEBUG_OBJECT (dec, "received data after media was loaded - ignoring");
914 gst_buffer_unref (buffer);
916 /* accumulate data until end-of-stream or the upstream
917 * size is reached, then load media and commence playback */
921 gst_adapter_push (dec->input_data_adapter, buffer);
922 avail_size = gst_adapter_available (dec->input_data_adapter);
923 if (avail_size >= dec->upstream_size) {
924 GstBuffer *adapter_buffer =
925 gst_adapter_take_buffer (dec->input_data_adapter, avail_size);
927 if (gst_nonstream_audio_decoder_load_from_buffer (dec, adapter_buffer))
929 gst_nonstream_audio_decoder_start_task (dec) ? GST_FLOW_OK :
932 flow_ret = GST_FLOW_ERROR;
942 gst_nonstream_audio_decoder_src_event (GstPad * pad, GstObject * parent,
945 gboolean res = FALSE;
946 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (parent);
948 switch (GST_EVENT_TYPE (event)) {
951 res = gst_nonstream_audio_decoder_do_seek (dec, event);
955 case GST_EVENT_TOC_SELECT:
957 /* NOTE: This event may be received multiple times if it
958 * was originally sent to a bin containing multiple sink
959 * elements (for example, playbin). This is OK and does
960 * not break anything. */
963 guint subsong_idx = 0;
966 gst_event_parse_toc_select (event, &uid);
969 && (sscanf (uid, "nonstream-subsong-%05u", &subsong_idx) == 1)) {
970 seqnum = gst_event_get_seqnum (event);
972 GST_DEBUG_OBJECT (dec,
973 "received TOC select event (sequence number %" G_GUINT32_FORMAT
974 "), switching to subsong %u", seqnum, subsong_idx);
976 gst_nonstream_audio_decoder_switch_to_subsong (dec, subsong_idx,
988 res = gst_pad_event_default (pad, parent, event);
996 gst_nonstream_audio_decoder_src_query (GstPad * pad, GstObject * parent,
999 gboolean res = FALSE;
1000 GstNonstreamAudioDecoder *dec;
1001 GstNonstreamAudioDecoderClass *klass;
1003 dec = GST_NONSTREAM_AUDIO_DECODER (parent);
1004 klass = GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
1006 switch (GST_QUERY_TYPE (query)) {
1007 case GST_QUERY_DURATION:
1010 GST_TRACE_OBJECT (parent, "duration query");
1012 if (!(dec->loaded_mode)) {
1013 GST_DEBUG_OBJECT (parent,
1014 "cannot respond to duration query: nothing is loaded yet");
1018 GST_TRACE_OBJECT (parent, "parsing duration query");
1019 gst_query_parse_duration (query, &format, NULL);
1021 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1022 if ((format == GST_FORMAT_TIME)
1023 && (dec->subsong_duration != GST_CLOCK_TIME_NONE)) {
1024 GST_DEBUG_OBJECT (parent,
1025 "responding to query with duration %" GST_TIME_FORMAT,
1026 GST_TIME_ARGS (dec->subsong_duration));
1027 gst_query_set_duration (query, format, dec->subsong_duration);
1029 } else if (format != GST_FORMAT_TIME)
1030 GST_DEBUG_OBJECT (parent,
1031 "cannot respond to duration query: format is %s, expected time format",
1032 gst_format_get_name (format));
1033 else if (dec->subsong_duration == GST_CLOCK_TIME_NONE)
1034 GST_DEBUG_OBJECT (parent,
1035 "cannot respond to duration query: no valid subsong duration available");
1036 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1041 case GST_QUERY_POSITION:
1044 if (!(dec->loaded_mode)) {
1045 GST_DEBUG_OBJECT (parent,
1046 "cannot respond to position query: nothing is loaded yet");
1050 if (klass->tell == NULL) {
1051 GST_DEBUG_OBJECT (parent,
1052 "cannot respond to position query: subclass does not have tell() function defined");
1056 gst_query_parse_position (query, &format, NULL);
1057 if (format == GST_FORMAT_TIME) {
1060 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1061 pos = klass->tell (dec);
1062 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1064 GST_DEBUG_OBJECT (parent,
1065 "position query received with format TIME -> reporting position %"
1066 GST_TIME_FORMAT, GST_TIME_ARGS (pos));
1067 gst_query_set_position (query, format, pos);
1070 GST_DEBUG_OBJECT (parent,
1071 "position query received with unsupported format %s -> not reporting anything",
1072 gst_format_get_name (format));
1078 case GST_QUERY_SEEKING:
1081 GstClockTime duration;
1083 if (!dec->loaded_mode) {
1084 GST_DEBUG_OBJECT (parent,
1085 "cannot respond to seeking query: nothing is loaded yet");
1089 if (klass->seek == NULL) {
1090 GST_DEBUG_OBJECT (parent,
1091 "cannot respond to seeking query: subclass does not have seek() function defined");
1095 gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
1097 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1098 duration = dec->subsong_duration;
1099 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1101 if (fmt == GST_FORMAT_TIME) {
1102 GST_DEBUG_OBJECT (parent,
1103 "seeking query received with format TIME -> can seek: yes");
1104 gst_query_set_seeking (query, fmt, TRUE, 0, duration);
1107 GST_DEBUG_OBJECT (parent,
1108 "seeking query received with unsupported format %s -> can seek: no",
1109 gst_format_get_name (fmt));
1110 gst_query_set_seeking (query, fmt, FALSE, 0, -1);
1118 res = gst_pad_query_default (pad, parent, query);
1127 gst_nonstream_audio_decoder_set_initial_state (GstNonstreamAudioDecoder * dec)
1129 dec->upstream_size = -1;
1130 dec->loaded_mode = FALSE;
1132 dec->subsong_duration = GST_CLOCK_TIME_NONE;
1134 dec->output_format_changed = FALSE;
1135 gst_audio_info_init (&(dec->output_audio_info));
1136 dec->num_decoded_samples = 0;
1137 dec->cur_pos_in_samples = 0;
1138 gst_segment_init (&(dec->cur_segment), GST_FORMAT_TIME);
1139 dec->discont = FALSE;
1143 dec->allocator = NULL;
1148 gst_nonstream_audio_decoder_cleanup_state (GstNonstreamAudioDecoder * dec)
1150 gst_adapter_clear (dec->input_data_adapter);
1152 if (dec->allocator != NULL) {
1153 gst_object_unref (dec->allocator);
1154 dec->allocator = NULL;
1157 if (dec->toc != NULL) {
1158 gst_toc_unref (dec->toc);
1162 gst_nonstream_audio_decoder_set_initial_state (dec);
1167 gst_nonstream_audio_decoder_negotiate (GstNonstreamAudioDecoder * dec)
1169 /* must be called with lock */
1171 GstNonstreamAudioDecoderClass *klass;
1172 gboolean res = TRUE;
1174 klass = GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
1176 /* protected by a mutex, since the allocator might currently be in use */
1177 if (klass->negotiate != NULL)
1178 res = klass->negotiate (dec);
1185 gst_nonstream_audio_decoder_negotiate_default (GstNonstreamAudioDecoder * dec)
1187 /* mutex is locked when this is called */
1190 GstNonstreamAudioDecoderClass *klass;
1191 gboolean res = TRUE;
1192 GstQuery *query = NULL;
1193 GstAllocator *allocator;
1194 GstAllocationParams allocation_params;
1196 g_return_val_if_fail (GST_IS_NONSTREAM_AUDIO_DECODER (dec), FALSE);
1197 g_return_val_if_fail (GST_AUDIO_INFO_IS_VALID (&(dec->output_audio_info)),
1200 klass = GST_NONSTREAM_AUDIO_DECODER_CLASS (G_OBJECT_GET_CLASS (dec));
1202 caps = gst_audio_info_to_caps (&(dec->output_audio_info));
1204 GST_DEBUG_OBJECT (dec, "setting src caps %" GST_PTR_FORMAT, (gpointer) caps);
1206 res = gst_pad_push_event (dec->srcpad, gst_event_new_caps (caps));
1207 /* clear any pending reconfigure flag */
1208 gst_pad_check_reconfigure (dec->srcpad);
1211 GST_WARNING_OBJECT (dec, "could not push new caps event downstream");
1215 GST_TRACE_OBJECT (dec, "src caps set");
1217 dec->output_format_changed = FALSE;
1219 query = gst_query_new_allocation (caps, TRUE);
1220 if (!gst_pad_peer_query (dec->srcpad, query)) {
1221 GST_DEBUG_OBJECT (dec, "didn't get downstream ALLOCATION hints");
1224 g_assert (klass->decide_allocation != NULL);
1225 res = klass->decide_allocation (dec, query);
1227 GST_DEBUG_OBJECT (dec, "ALLOCATION (%d) params: %" GST_PTR_FORMAT, res,
1231 goto no_decide_allocation;
1233 /* we got configuration from our peer or the decide_allocation method,
1235 if (gst_query_get_n_allocation_params (query) > 0) {
1236 gst_query_parse_nth_allocation_param (query, 0, &allocator,
1237 &allocation_params);
1240 gst_allocation_params_init (&allocation_params);
1243 if (dec->allocator != NULL)
1244 gst_object_unref (dec->allocator);
1245 dec->allocator = allocator;
1246 dec->allocation_params = allocation_params;
1250 gst_query_unref (query);
1251 gst_caps_unref (caps);
1255 no_decide_allocation:
1257 GST_WARNING_OBJECT (dec, "subclass failed to decide allocation");
1264 gst_nonstream_audio_decoder_decide_allocation_default (G_GNUC_UNUSED
1265 GstNonstreamAudioDecoder * dec, GstQuery * query)
1267 GstAllocator *allocator = NULL;
1268 GstAllocationParams params;
1269 gboolean update_allocator;
1271 /* we got configuration from our peer or the decide_allocation method,
1273 if (gst_query_get_n_allocation_params (query) > 0) {
1274 /* try the allocator */
1275 gst_query_parse_nth_allocation_param (query, 0, &allocator, ¶ms);
1276 update_allocator = TRUE;
1279 gst_allocation_params_init (¶ms);
1280 update_allocator = FALSE;
1283 if (update_allocator)
1284 gst_query_set_nth_allocation_param (query, 0, allocator, ¶ms);
1286 gst_query_add_allocation_param (query, allocator, ¶ms);
1289 gst_object_unref (allocator);
1296 gst_nonstream_audio_decoder_propose_allocation_default (G_GNUC_UNUSED
1297 GstNonstreamAudioDecoder * dec, G_GNUC_UNUSED GstQuery * query)
1304 gst_nonstream_audio_decoder_get_upstream_size (GstNonstreamAudioDecoder * dec,
1307 return gst_pad_peer_query_duration (dec->sinkpad, GST_FORMAT_BYTES, length)
1313 gst_nonstream_audio_decoder_load_from_buffer (GstNonstreamAudioDecoder * dec,
1317 GstClockTime initial_position;
1318 GstNonstreamAudioDecoderClass *klass;
1321 klass = GST_NONSTREAM_AUDIO_DECODER_CLASS (G_OBJECT_GET_CLASS (dec));
1322 g_assert (klass->load_from_buffer != NULL);
1324 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1326 GST_LOG_OBJECT (dec, "read %" G_GSIZE_FORMAT " bytes from upstream",
1327 gst_buffer_get_size (buffer));
1329 initial_position = 0;
1331 klass->load_from_buffer (dec, buffer, dec->current_subsong,
1332 dec->subsong_mode, &initial_position, &(dec->output_mode),
1334 gst_buffer_unref (buffer);
1337 gst_nonstream_audio_decoder_finish_load (dec, load_ok, initial_position,
1340 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1347 gst_nonstream_audio_decoder_load_from_custom (GstNonstreamAudioDecoder * dec)
1350 GstClockTime initial_position;
1351 GstNonstreamAudioDecoderClass *klass;
1354 klass = GST_NONSTREAM_AUDIO_DECODER_CLASS (G_OBJECT_GET_CLASS (dec));
1355 g_assert (klass->load_from_custom != NULL);
1357 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1359 GST_LOG_OBJECT (dec,
1360 "reading song from custom source defined by derived class");
1362 initial_position = 0;
1364 klass->load_from_custom (dec, dec->current_subsong, dec->subsong_mode,
1365 &initial_position, &(dec->output_mode), &(dec->num_loops));
1368 gst_nonstream_audio_decoder_finish_load (dec, load_ok, initial_position,
1371 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1378 gst_nonstream_audio_decoder_finish_load (GstNonstreamAudioDecoder * dec,
1379 gboolean load_ok, GstClockTime initial_position, gboolean send_stream_start)
1381 /* must be called with lock */
1383 GstNonstreamAudioDecoderClass *klass =
1384 GST_NONSTREAM_AUDIO_DECODER_CLASS (G_OBJECT_GET_CLASS (dec));
1386 GST_TRACE_OBJECT (dec, "enter finish_load");
1392 GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("Loading failed"));
1396 if (!GST_AUDIO_INFO_IS_VALID (&(dec->output_audio_info))) {
1397 GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL),
1398 ("Audio info is invalid after loading"));
1403 /* Log the number of available subsongs */
1404 if (klass->get_num_subsongs != NULL)
1405 GST_DEBUG_OBJECT (dec, "%u subsong(s) available",
1406 klass->get_num_subsongs (dec));
1409 /* Set the current subsong (or use the default value) */
1410 if (klass->get_current_subsong != NULL) {
1411 GST_TRACE_OBJECT (dec, "requesting current subsong");
1412 dec->current_subsong = klass->get_current_subsong (dec);
1416 /* Handle the subsong duration */
1417 if (klass->get_subsong_duration != NULL) {
1418 GstClockTime duration;
1419 GST_TRACE_OBJECT (dec, "requesting subsong duration");
1420 duration = klass->get_subsong_duration (dec, dec->current_subsong);
1421 gst_nonstream_audio_decoder_update_subsong_duration (dec, duration);
1425 /* Send tags downstream (if some exist) */
1426 if (klass->get_subsong_tags != NULL) {
1427 /* Subsong tags available */
1430 GST_TRACE_OBJECT (dec, "requesting subsong tags");
1431 tags = klass->get_subsong_tags (dec, dec->current_subsong);
1433 tags = gst_nonstream_audio_decoder_add_main_tags (dec, tags);
1435 gst_pad_push_event (dec->srcpad, gst_event_new_tag (tags));
1437 /* No subsong tags - just send main tags out */
1439 GstTagList *tags = gst_tag_list_new_empty ();
1440 tags = gst_nonstream_audio_decoder_add_main_tags (dec, tags);
1441 gst_pad_push_event (dec->srcpad, gst_event_new_tag (tags));
1445 /* Send stream start downstream if requested */
1446 if (send_stream_start) {
1451 gst_pad_create_stream_id (dec->srcpad, GST_ELEMENT_CAST (dec), NULL);
1452 GST_DEBUG_OBJECT (dec, "pushing STREAM_START with stream id \"%s\"",
1455 event = gst_event_new_stream_start (stream_id);
1456 gst_event_set_group_id (event, gst_util_group_id_next ());
1457 gst_pad_push_event (dec->srcpad, event);
1462 /* Update the table of contents */
1463 gst_nonstream_audio_decoder_update_toc (dec, klass);
1466 /* Negotiate output caps and an allocator */
1467 GST_TRACE_OBJECT (dec, "negotiating caps and allocator");
1468 if (!gst_nonstream_audio_decoder_negotiate (dec)) {
1469 GST_ERROR_OBJECT (dec, "negotiation failed - aborting load");
1474 /* Send new segment downstream */
1475 gst_nonstream_audio_decoder_output_new_segment (dec, initial_position);
1477 dec->loaded_mode = TRUE;
1479 GST_TRACE_OBJECT (dec, "exit finish_load");
1486 gst_nonstream_audio_decoder_start_task (GstNonstreamAudioDecoder * dec)
1488 if (!gst_pad_start_task (dec->srcpad,
1489 (GstTaskFunction) gst_nonstream_audio_decoder_output_task, dec,
1491 GST_ERROR_OBJECT (dec, "could not start decoder output task");
1499 gst_nonstream_audio_decoder_stop_task (GstNonstreamAudioDecoder * dec)
1501 if (!gst_pad_stop_task (dec->srcpad)) {
1502 GST_ERROR_OBJECT (dec, "could not stop decoder output task");
1510 gst_nonstream_audio_decoder_switch_to_subsong (GstNonstreamAudioDecoder * dec,
1511 guint new_subsong, guint32 const *seqnum)
1513 gboolean ret = TRUE;
1514 GstNonstreamAudioDecoderClass *klass =
1515 GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
1518 if (klass->set_current_subsong == NULL) {
1519 /* If set_current_subsong wasn't set by the subclass, then
1520 * subsongs are not supported. It is not an error if this
1521 * function is called in that case, since it might happen
1522 * because the current-subsong property was set (and since
1523 * this is a base class property, it is always available). */
1524 GST_DEBUG_OBJECT (dec, "cannot call set_current_subsong, since it is NULL");
1528 if (dec->loaded_mode) {
1530 GstClockTime new_position;
1531 GstClockTime new_subsong_duration = GST_CLOCK_TIME_NONE;
1534 /* Check if (a) new_subsong is already the current subsong
1535 * and (b) if new_subsong exceeds the number of available
1536 * subsongs. Do this here, when the song is loaded,
1537 * because prior to loading, the number of subsong is usually
1538 * not known (and the loading process might choose a specific
1539 * subsong to be the current one at the start of playback). */
1541 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1543 if (new_subsong == dec->current_subsong) {
1544 GST_DEBUG_OBJECT (dec,
1545 "subsong %u is already the current subsong - ignoring call",
1550 if (klass->get_num_subsongs) {
1551 guint num_subsongs = klass->get_num_subsongs (dec);
1553 if (new_subsong >= num_subsongs) {
1554 GST_WARNING_OBJECT (dec,
1555 "subsong %u is out of bounds (there are %u subsongs) - not switching",
1556 new_subsong, num_subsongs);
1561 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1564 /* Switching subsongs during playback is very similar to a
1565 * flushing seek. Therefore, the stream lock must be taken,
1566 * flush-start/flush-stop events have to be sent, and
1567 * the pad task has to be restarted. */
1570 fevent = gst_event_new_flush_start ();
1571 if (seqnum != NULL) {
1572 gst_event_set_seqnum (fevent, *seqnum);
1573 GST_DEBUG_OBJECT (dec,
1574 "sending flush start event with sequence number %" G_GUINT32_FORMAT,
1577 GST_DEBUG_OBJECT (dec, "sending flush start event (no sequence number)");
1579 gst_pad_push_event (dec->srcpad, gst_event_ref (fevent));
1580 /* unlock upstream pull_range */
1581 if (klass->loads_from_sinkpad)
1582 gst_pad_push_event (dec->sinkpad, fevent);
1584 gst_event_unref (fevent);
1587 GST_PAD_STREAM_LOCK (dec->srcpad);
1590 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1593 if (!(klass->set_current_subsong (dec, new_subsong, &new_position))) {
1594 /* Switch failed. Do _not_ exit early from here - playback must
1595 * continue from the current subsong, and it cannot do that if
1596 * we exit here. Try getting the current position and proceed as
1597 * if the switch succeeded (but set the return value to FALSE.) */
1601 new_position = klass->tell (dec);
1604 GST_WARNING_OBJECT (dec, "switching to new subsong %u failed",
1608 /* Flushing seek resets the base time, which means num_decoded_samples
1609 * needs to be set to 0, since it defines the segment.base value */
1610 dec->num_decoded_samples = 0;
1613 fevent = gst_event_new_flush_stop (TRUE);
1614 if (seqnum != NULL) {
1615 gst_event_set_seqnum (fevent, *seqnum);
1616 GST_DEBUG_OBJECT (dec,
1617 "sending flush stop event with sequence number %" G_GUINT32_FORMAT,
1620 GST_DEBUG_OBJECT (dec, "sending flush stop event (no sequence number)");
1622 gst_pad_push_event (dec->srcpad, gst_event_ref (fevent));
1623 /* unlock upstream pull_range */
1624 if (klass->loads_from_sinkpad)
1625 gst_pad_push_event (dec->sinkpad, fevent);
1627 gst_event_unref (fevent);
1630 /* use the new subsong's duration (if one exists) */
1631 if (klass->get_subsong_duration != NULL)
1632 new_subsong_duration = klass->get_subsong_duration (dec, new_subsong);
1633 gst_nonstream_audio_decoder_update_subsong_duration (dec,
1634 new_subsong_duration);
1636 /* create a new segment for the new subsong */
1637 gst_nonstream_audio_decoder_output_new_segment (dec, new_position);
1639 /* use the new subsong's tags (if any exist) */
1640 if (klass->get_subsong_tags != NULL) {
1641 GstTagList *subsong_tags = klass->get_subsong_tags (dec, new_subsong);
1642 if (subsong_tags != NULL)
1644 gst_nonstream_audio_decoder_add_main_tags (dec, subsong_tags);
1645 if (subsong_tags != NULL)
1646 gst_pad_push_event (dec->srcpad, gst_event_new_tag (subsong_tags));
1649 GST_DEBUG_OBJECT (dec, "successfully switched to new subsong %u",
1651 dec->current_subsong = new_subsong;
1654 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1657 /* Subsong has been switched, and all necessary events have been
1658 * pushed downstream. Restart srcpad task. */
1659 gst_nonstream_audio_decoder_start_task (dec);
1661 /* Unlock stream, we are done */
1662 GST_PAD_STREAM_UNLOCK (dec->srcpad);
1664 /* If song hasn't been loaded yet, then playback cannot currently
1665 * been happening. In this case, a "switch" is simple - just store
1666 * the current subsong index. When the song is loaded, it will
1667 * start playing this subsong. */
1669 GST_DEBUG_OBJECT (dec,
1670 "playback hasn't started yet - storing subsong index %u as the current subsong",
1673 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1674 dec->current_subsong = new_subsong;
1675 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1684 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1690 gst_nonstream_audio_decoder_update_toc (GstNonstreamAudioDecoder * dec,
1691 GstNonstreamAudioDecoderClass * klass)
1693 /* must be called with lock */
1695 guint num_subsongs, i;
1697 if (dec->toc != NULL) {
1698 gst_toc_unref (dec->toc);
1702 if (klass->get_num_subsongs == NULL)
1705 num_subsongs = klass->get_num_subsongs (dec);
1706 if (num_subsongs <= 1) {
1707 GST_DEBUG_OBJECT (dec, "no need for a TOC since there is only one subsong");
1711 dec->toc = gst_toc_new (GST_TOC_SCOPE_GLOBAL);
1713 if (klass->get_main_tags) {
1714 GstTagList *main_tags = klass->get_main_tags (dec);
1716 gst_toc_set_tags (dec->toc, main_tags);
1719 for (i = 0; i < num_subsongs; ++i) {
1722 GstClockTime duration;
1726 (klass->get_subsong_duration !=
1727 NULL) ? klass->get_subsong_duration (dec, i) : GST_CLOCK_TIME_NONE;
1729 (klass->get_subsong_tags != NULL) ? klass->get_subsong_tags (dec,
1732 tags = gst_tag_list_new_empty ();
1734 uid = g_strdup_printf ("nonstream-subsong-%05u", i);
1735 entry = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_TRACK, uid);
1736 /* Set the UID as title tag for TOC entry if no title already present */
1737 gst_tag_list_add (tags, GST_TAG_MERGE_KEEP, GST_TAG_TITLE, uid, NULL);
1738 /* Set the subsong duration as duration tag for TOC entry if no duration already present */
1739 if (duration != GST_CLOCK_TIME_NONE)
1740 gst_tag_list_add (tags, GST_TAG_MERGE_KEEP, GST_TAG_DURATION, duration,
1743 /* FIXME: TOC does not allow GST_CLOCK_TIME_NONE as a stop value */
1744 if (duration == GST_CLOCK_TIME_NONE)
1745 duration = G_MAXINT64;
1747 /* Subsongs always start at 00:00 */
1748 gst_toc_entry_set_start_stop_times (entry, 0, duration);
1749 gst_toc_entry_set_tags (entry, tags);
1751 /* NOTE: *not* adding loop count via gst_toc_entry_set_loop(), since
1752 * in GstNonstreamAudioDecoder, looping is a playback property, not
1753 * a property of the subsongs themselves */
1755 GST_DEBUG_OBJECT (dec,
1756 "new toc entry: uid: \"%s\" duration: %" GST_TIME_FORMAT " tags: %"
1757 GST_PTR_FORMAT, uid, GST_TIME_ARGS (duration), (gpointer) tags);
1759 gst_toc_append_entry (dec->toc, entry);
1764 gst_pad_push_event (dec->srcpad, gst_event_new_toc (dec->toc, FALSE));
1769 gst_nonstream_audio_decoder_update_subsong_duration (GstNonstreamAudioDecoder *
1770 dec, GstClockTime duration)
1772 /* must be called with lock */
1774 dec->subsong_duration = duration;
1775 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1776 gst_element_post_message (GST_ELEMENT (dec),
1777 gst_message_new_duration_changed (GST_OBJECT (dec)));
1778 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1783 gst_nonstream_audio_decoder_output_new_segment (GstNonstreamAudioDecoder * dec,
1784 GstClockTime start_position)
1786 /* must be called with lock */
1790 gst_segment_init (&segment, GST_FORMAT_TIME);
1793 gst_util_uint64_scale_int (dec->num_decoded_samples, GST_SECOND,
1794 dec->output_audio_info.rate);
1796 segment.time = start_position;
1798 segment.position = 0;
1800 /* note that num_decoded_samples isn't being reset; it is the
1801 * analogue to the segment base value, and thus is supposed to
1802 * monotonically increase, except for when a flushing seek happens
1803 * (since a flushing seek is supposed to be a fresh restart for
1804 * the whole pipeline) */
1805 dec->cur_pos_in_samples = 0;
1807 /* stop/duration members are not set, on purpose - in case of loops,
1808 * new segments will be generated, which automatically put an implicit
1809 * end on the current segment (the segment implicitly "ends" when the
1810 * new one starts), and having a stop value might cause very slight
1811 * gaps occasionally due to slight jitter in the calculation of
1812 * base times etc. */
1814 GST_DEBUG_OBJECT (dec,
1815 "output new segment with base %" GST_TIME_FORMAT " time %"
1816 GST_TIME_FORMAT, GST_TIME_ARGS (segment.base),
1817 GST_TIME_ARGS (segment.time));
1819 dec->cur_segment = segment;
1820 dec->discont = TRUE;
1822 gst_pad_push_event (dec->srcpad, gst_event_new_segment (&segment));
1827 gst_nonstream_audio_decoder_do_seek (GstNonstreamAudioDecoder * dec,
1834 GstSeekType start_type, stop_type;
1835 GstClockTime new_position;
1840 GstNonstreamAudioDecoderClass *klass =
1841 GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
1843 if (klass->seek == NULL) {
1844 GST_DEBUG_OBJECT (dec,
1845 "cannot seek: subclass does not have seek() function defined");
1849 if (!dec->loaded_mode) {
1850 GST_DEBUG_OBJECT (dec, "nothing loaded yet - cannot seek");
1854 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1855 if (!GST_AUDIO_INFO_IS_VALID (&(dec->output_audio_info))) {
1856 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1857 GST_DEBUG_OBJECT (dec, "no valid output audioinfo present - cannot seek");
1860 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1863 GST_DEBUG_OBJECT (dec, "starting seek");
1865 gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start,
1867 seqnum = gst_event_get_seqnum (event);
1869 GST_DEBUG_OBJECT (dec,
1871 "rate %f format %s "
1872 "start type %s start %" GST_TIME_FORMAT " "
1873 "stop type %s stop %" GST_TIME_FORMAT,
1874 rate, gst_format_get_name (format),
1875 get_seek_type_name (start_type), GST_TIME_ARGS (start),
1876 get_seek_type_name (stop_type), GST_TIME_ARGS (stop)
1879 if (format != GST_FORMAT_TIME) {
1880 GST_DEBUG_OBJECT (dec, "seeking is only supported in TIME format");
1885 GST_DEBUG_OBJECT (dec, "only positive seek rates are supported");
1889 flush = ((flags & GST_SEEK_FLAG_FLUSH) == GST_SEEK_FLAG_FLUSH);
1892 GstEvent *fevent = gst_event_new_flush_start ();
1893 gst_event_set_seqnum (fevent, seqnum);
1895 GST_DEBUG_OBJECT (dec,
1896 "sending flush start event with sequence number %" G_GUINT32_FORMAT,
1899 gst_pad_push_event (dec->srcpad, gst_event_ref (fevent));
1900 /* unlock upstream pull_range */
1901 if (klass->loads_from_sinkpad)
1902 gst_pad_push_event (dec->sinkpad, fevent);
1904 gst_event_unref (fevent);
1906 gst_pad_pause_task (dec->srcpad);
1908 GST_PAD_STREAM_LOCK (dec->srcpad);
1910 segment = dec->cur_segment;
1912 if (!gst_segment_do_seek (&segment,
1913 rate, format, flags, start_type, start, stop_type, stop, NULL)) {
1914 GST_DEBUG_OBJECT (dec, "could not seek in segment");
1915 GST_PAD_STREAM_UNLOCK (dec->srcpad);
1919 GST_DEBUG_OBJECT (dec,
1922 "rate %f applied rate %f "
1924 "base %" GST_TIME_FORMAT " "
1925 "offset %" GST_TIME_FORMAT " "
1926 "start %" GST_TIME_FORMAT " "
1927 "stop %" GST_TIME_FORMAT " "
1928 "time %" GST_TIME_FORMAT " "
1929 "position %" GST_TIME_FORMAT " "
1930 "duration %" GST_TIME_FORMAT,
1931 segment.rate, segment.applied_rate,
1932 gst_format_get_name (segment.format),
1933 GST_TIME_ARGS (segment.base),
1934 GST_TIME_ARGS (segment.offset),
1935 GST_TIME_ARGS (segment.start),
1936 GST_TIME_ARGS (segment.stop),
1937 GST_TIME_ARGS (segment.time),
1938 GST_TIME_ARGS (segment.position), GST_TIME_ARGS (segment.duration)
1941 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1943 new_position = segment.position;
1944 res = klass->seek (dec, &new_position);
1945 segment.position = new_position;
1947 dec->cur_segment = segment;
1948 dec->cur_pos_in_samples =
1949 gst_util_uint64_scale_int (dec->cur_segment.position,
1950 dec->output_audio_info.rate, GST_SECOND);
1951 dec->num_decoded_samples = 0;
1953 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1956 GstEvent *fevent = gst_event_new_flush_stop (TRUE);
1957 gst_event_set_seqnum (fevent, seqnum);
1959 GST_DEBUG_OBJECT (dec,
1960 "sending flush stop event with sequence number %" G_GUINT32_FORMAT,
1963 gst_pad_push_event (dec->srcpad, gst_event_ref (fevent));
1964 if (klass->loads_from_sinkpad)
1965 gst_pad_push_event (dec->sinkpad, fevent);
1967 gst_event_unref (fevent);
1971 if (flags & GST_SEEK_FLAG_SEGMENT) {
1972 GST_DEBUG_OBJECT (dec, "posting SEGMENT_START message");
1974 gst_element_post_message (GST_ELEMENT (dec),
1975 gst_message_new_segment_start (GST_OBJECT (dec),
1976 GST_FORMAT_TIME, segment.start)
1980 gst_pad_push_event (dec->srcpad, gst_event_new_segment (&segment));
1982 GST_INFO_OBJECT (dec, "seek succeeded");
1984 gst_nonstream_audio_decoder_start_task (dec);
1986 GST_WARNING_OBJECT (dec, "seek failed");
1989 GST_PAD_STREAM_UNLOCK (dec->srcpad);
1991 gst_event_unref (event);
1998 gst_nonstream_audio_decoder_add_main_tags (GstNonstreamAudioDecoder * dec,
2001 GstNonstreamAudioDecoderClass *klass =
2002 GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
2004 if (!klass->get_main_tags)
2007 tags = gst_tag_list_make_writable (tags);
2009 GstClockTime duration;
2010 GstTagList *main_tags;
2012 /* Get main tags. If some exist, merge them with the given tags,
2013 * and return the merged result. Otherwise, just return the given tags. */
2014 main_tags = klass->get_main_tags (dec);
2016 tags = gst_tag_list_merge (main_tags, tags, GST_TAG_MERGE_REPLACE);
2017 gst_tag_list_unref (main_tags);
2020 /* Add subsong duration if available */
2021 duration = dec->subsong_duration;
2022 if (GST_CLOCK_TIME_IS_VALID (duration))
2023 gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_DURATION, duration,
2028 GST_ERROR_OBJECT (dec, "could not make subsong tags writable");
2035 gst_nonstream_audio_decoder_output_task (GstNonstreamAudioDecoder * dec)
2041 GstNonstreamAudioDecoderClass *klass;
2042 klass = GST_NONSTREAM_AUDIO_DECODER_CLASS (G_OBJECT_GET_CLASS (dec));
2043 g_assert (klass->decode != NULL);
2045 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
2047 /* perform the actual decoding */
2048 if (!(klass->decode (dec, &outbuf, &num_samples))) {
2050 GST_INFO_OBJECT (dec, "decode() reports end -> sending EOS event");
2051 gst_pad_push_event (dec->srcpad, gst_event_new_eos ());
2055 if (outbuf == NULL) {
2056 GST_ERROR_OBJECT (outbuf, "decode() produced NULL buffer");
2060 /* set the buffer's metadata */
2061 GST_BUFFER_DURATION (outbuf) =
2062 gst_util_uint64_scale_int (num_samples, GST_SECOND,
2063 dec->output_audio_info.rate);
2064 GST_BUFFER_OFFSET (outbuf) = dec->cur_pos_in_samples;
2065 GST_BUFFER_OFFSET_END (outbuf) = dec->cur_pos_in_samples + num_samples;
2066 GST_BUFFER_PTS (outbuf) =
2067 gst_util_uint64_scale_int (dec->cur_pos_in_samples, GST_SECOND,
2068 dec->output_audio_info.rate);
2069 GST_BUFFER_DTS (outbuf) = GST_BUFFER_PTS (outbuf);
2071 if (G_UNLIKELY (dec->discont)) {
2072 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
2073 dec->discont = FALSE;
2076 GST_LOG_OBJECT (dec,
2077 "output buffer stats: num_samples = %u duration = %" GST_TIME_FORMAT
2078 " cur_pos_in_samples = %" G_GUINT64_FORMAT " timestamp = %"
2079 GST_TIME_FORMAT, num_samples,
2080 GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)), dec->cur_pos_in_samples,
2081 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf))
2084 /* increment sample counters */
2085 dec->cur_pos_in_samples += num_samples;
2086 dec->num_decoded_samples += num_samples;
2088 /* the decode() call might have set a new output format -> renegotiate
2089 * before sending the new buffer downstream */
2090 if (G_UNLIKELY (dec->output_format_changed ||
2091 (GST_AUDIO_INFO_IS_VALID (&(dec->output_audio_info))
2092 && gst_pad_check_reconfigure (dec->srcpad))
2094 if (!gst_nonstream_audio_decoder_negotiate (dec)) {
2095 gst_buffer_unref (outbuf);
2096 GST_LOG_OBJECT (dec, "could not push output buffer: negotiation failed");
2101 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
2103 /* push new samples downstream
2104 * no need to unref buffer - gst_pad_push() does it in
2105 * all cases (success and failure) */
2106 flow = gst_pad_push (dec->srcpad, outbuf);
2111 case GST_FLOW_FLUSHING:
2112 GST_LOG_OBJECT (dec, "pipeline is being flushed - pausing task");
2115 case GST_FLOW_NOT_NEGOTIATED:
2116 if (gst_pad_needs_reconfigure (dec->srcpad)) {
2117 GST_DEBUG_OBJECT (dec, "trying to renegotiate");
2120 /* fallthrough to default */
2123 GST_ELEMENT_ERROR (dec, STREAM, FAILED, ("Internal data flow error."),
2124 ("streaming task paused, reason %s (%d)", gst_flow_get_name (flow),
2131 GST_INFO_OBJECT (dec, "pausing task");
2132 /* NOT using stop_task here, since that would cause a deadlock.
2133 * See the gst_pad_stop_task() documentation for details. */
2134 gst_pad_pause_task (dec->srcpad);
2137 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
2143 get_seek_type_name (GstSeekType seek_type)
2145 switch (seek_type) {
2146 case GST_SEEK_TYPE_NONE:
2148 case GST_SEEK_TYPE_SET:
2150 case GST_SEEK_TYPE_END:
2161 * gst_nonstream_audio_decoder_handle_loop:
2162 * @dec: a #GstNonstreamAudioDecoder
2163 * @new_position New position the next loop starts with
2165 * Reports that a loop has been completed and creates a new appropriate
2166 * segment for the next loop.
2168 * @new_position exists because a loop may not start at the beginning.
2170 * This function is only useful for subclasses which can be in the
2171 * GST_NONSTREAM_AUDIO_OUTPUT_MODE_LOOPING output mode, since in the
2172 * GST_NONSTREAM_AUDIO_OUTPUT_MODE_STEADY output mode, this function
2173 * does nothing. See #GstNonstreamAudioOutputMode for more details.
2175 * The subclass calls this during playback when it loops. It produces
2176 * a new segment with updated base time and internal time values, to allow
2177 * for seamless looping. It does *not* check the number of elapsed loops;
2178 * this is up the subclass.
2180 * Note that if this function is called, then it must be done after the
2181 * last samples of the loop have been decoded and pushed downstream.
2183 * This function must be called with the decoder mutex lock held, since it
2184 * is typically called from within @decode (which in turn are called with
2185 * the lock already held).
2188 gst_nonstream_audio_decoder_handle_loop (GstNonstreamAudioDecoder * dec,
2189 GstClockTime new_position)
2191 if (dec->output_mode == GST_NONSTREAM_AUDIO_OUTPUT_MODE_STEADY) {
2192 /* handle_loop makes no sense with open-ended decoders */
2193 GST_WARNING_OBJECT (dec,
2194 "ignoring handle_loop() call, since the decoder output mode is \"steady\"");
2198 GST_DEBUG_OBJECT (dec,
2199 "handle_loop() invoked with new_position = %" GST_TIME_FORMAT,
2200 GST_TIME_ARGS (new_position));
2202 dec->discont = TRUE;
2204 gst_nonstream_audio_decoder_output_new_segment (dec, new_position);
2209 * gst_nonstream_audio_decoder_set_output_format:
2210 * @dec: a #GstNonstreamAudioDecoder
2211 * @audio_info: Valid audio info structure containing the output format
2213 * Sets the output caps by means of a GstAudioInfo structure.
2215 * This must be called latest in the first @decode call, to ensure src caps are
2216 * set before decoded samples are sent downstream. Typically, this is called
2217 * from inside @load_from_buffer or @load_from_custom.
2219 * This function must be called with the decoder mutex lock held, since it
2220 * is typically called from within the aforementioned vfuncs (which in turn
2221 * are called with the lock already held).
2223 * Returns: TRUE if setting the output format succeeded, FALSE otherwise
2226 gst_nonstream_audio_decoder_set_output_format (GstNonstreamAudioDecoder * dec,
2227 GstAudioInfo const *audio_info)
2230 GstCaps *templ_caps;
2232 gboolean res = TRUE;
2234 g_return_val_if_fail (GST_IS_NONSTREAM_AUDIO_DECODER (dec), FALSE);
2236 caps = gst_audio_info_to_caps (audio_info);
2238 GST_WARNING_OBJECT (dec, "Could not create caps out of audio info");
2242 templ_caps = gst_pad_get_pad_template_caps (dec->srcpad);
2243 caps_ok = gst_caps_is_subset (caps, templ_caps);
2246 dec->output_audio_info = *audio_info;
2247 dec->output_format_changed = TRUE;
2249 GST_INFO_OBJECT (dec, "setting output format to %" GST_PTR_FORMAT,
2252 GST_WARNING_OBJECT (dec,
2253 "requested output format %" GST_PTR_FORMAT " does not match template %"
2254 GST_PTR_FORMAT, (gpointer) caps, (gpointer) templ_caps);
2259 gst_caps_unref (caps);
2260 gst_caps_unref (templ_caps);
2267 * gst_nonstream_audio_decoder_set_output_format_simple:
2268 * @dec: a #GstNonstreamAudioDecoder
2269 * @sample_rate: Output sample rate to use, in Hz
2270 * @sample_format: Output sample format to use
2271 * @num_channels: Number of output channels to use
2273 * Convenience function; sets the output caps by means of common parameters.
2275 * Internally, this fills a GstAudioInfo structure and calls
2276 * gst_nonstream_audio_decoder_set_output_format().
2278 * Returns: TRUE if setting the output format succeeded, FALSE otherwise
2281 gst_nonstream_audio_decoder_set_output_format_simple (GstNonstreamAudioDecoder *
2282 dec, guint sample_rate, GstAudioFormat sample_format, guint num_channels)
2284 GstAudioInfo output_audio_info;
2286 gst_audio_info_init (&output_audio_info);
2288 gst_audio_info_set_format (&output_audio_info,
2289 sample_format, sample_rate, num_channels, NULL);
2291 return gst_nonstream_audio_decoder_set_output_format (dec,
2292 &output_audio_info);
2297 * gst_nonstream_audio_decoder_get_downstream_info:
2298 * @dec: a #GstNonstreamAudioDecoder
2299 * @format: #GstAudioFormat value to fill with a sample format
2300 * @sample_rate: Integer to fill with a sample rate
2301 * @num_channels: Integer to fill with a channel count
2303 * Gets sample format, sample rate, channel count from the allowed srcpad caps.
2305 * This is useful for when the subclass wishes to adjust one or more output
2306 * parameters to whatever downstream is supporting. For example, the output
2307 * sample rate is often a freely adjustable value in module players.
2309 * This function tries to find a value inside the srcpad peer's caps for
2310 * @format, @sample_rate, @num_chnanels . Any of these can be NULL; they
2311 * (and the corresponding downstream caps) are then skipped while retrieving
2312 * information. Non-fixated caps are fixated first; the value closest to
2313 * their present value is then chosen. For example, if the variables pointed
2314 * to by the arguments are GST_AUDIO_FORMAT_16, 48000 Hz, and 2 channels,
2315 * and the downstream caps are:
2317 * "audio/x-raw, format={S16LE,S32LE}, rate=[1,32000], channels=[1,MAX]"
2319 * Then @format and @channels stay the same, while @sample_rate is set to 32000 Hz.
2320 * This way, the initial values the the variables pointed to by the arguments
2321 * are set to can be used as default output values. Note that if no downstream
2322 * caps can be retrieved, then this function does nothing, therefore it is
2323 * necessary to ensure that @format, @sample_rate, and @channels have valid
2326 * Decoder lock is not held by this function, so it can be called from within
2327 * any of the class vfuncs.
2330 gst_nonstream_audio_decoder_get_downstream_info (GstNonstreamAudioDecoder * dec,
2331 GstAudioFormat * format, gint * sample_rate, gint * num_channels)
2333 GstCaps *allowed_srccaps;
2334 guint structure_nr, num_structures;
2335 gboolean ds_format_found = FALSE, ds_rate_found = FALSE, ds_channels_found =
2338 g_return_if_fail (GST_IS_NONSTREAM_AUDIO_DECODER (dec));
2340 allowed_srccaps = gst_pad_get_allowed_caps (dec->srcpad);
2341 if (allowed_srccaps == NULL) {
2342 GST_INFO_OBJECT (dec,
2343 "no downstream caps available - not modifying arguments");
2347 num_structures = gst_caps_get_size (allowed_srccaps);
2348 GST_DEBUG_OBJECT (dec, "%u structure(s) in downstream caps", num_structures);
2349 for (structure_nr = 0; structure_nr < num_structures; ++structure_nr) {
2350 GstStructure *structure;
2352 ds_format_found = FALSE;
2353 ds_rate_found = FALSE;
2354 ds_channels_found = FALSE;
2356 structure = gst_caps_get_structure (allowed_srccaps, structure_nr);
2358 /* If all formats which need to be queried are present in the structure,
2359 * check its contents */
2360 if (((format == NULL) || gst_structure_has_field (structure, "format")) &&
2361 ((sample_rate == NULL) || gst_structure_has_field (structure, "rate"))
2362 && ((num_channels == NULL)
2363 || gst_structure_has_field (structure, "channels"))) {
2364 gint fixated_sample_rate;
2365 gint fixated_num_channels;
2366 GstAudioFormat fixated_format = 0;
2367 GstStructure *fixated_str;
2368 gboolean passed = TRUE;
2370 /* Make a copy of the structure, since we need to modify
2371 * (fixate) values inside */
2372 fixated_str = gst_structure_copy (structure);
2374 /* Try to fixate and retrieve the sample format */
2375 if (passed && (format != NULL)) {
2378 if ((gst_structure_get_field_type (fixated_str,
2379 "format") == G_TYPE_STRING)
2380 || gst_structure_fixate_field_string (fixated_str, "format",
2381 gst_audio_format_to_string (*format))) {
2382 gchar const *fmt_str =
2383 gst_structure_get_string (fixated_str, "format");
2385 && ((fixated_format =
2386 gst_audio_format_from_string (fmt_str)) !=
2387 GST_AUDIO_FORMAT_UNKNOWN)) {
2388 GST_DEBUG_OBJECT (dec, "found fixated format: %s", fmt_str);
2389 ds_format_found = TRUE;
2395 /* Try to fixate and retrieve the sample rate */
2396 if (passed && (sample_rate != NULL)) {
2399 if ((gst_structure_get_field_type (fixated_str, "rate") == G_TYPE_INT)
2400 || gst_structure_fixate_field_nearest_int (fixated_str, "rate",
2402 if (gst_structure_get_int (fixated_str, "rate", &fixated_sample_rate)) {
2403 GST_DEBUG_OBJECT (dec, "found fixated sample rate: %d",
2404 fixated_sample_rate);
2405 ds_rate_found = TRUE;
2411 /* Try to fixate and retrieve the channel count */
2412 if (passed && (num_channels != NULL)) {
2415 if ((gst_structure_get_field_type (fixated_str,
2416 "channels") == G_TYPE_INT)
2417 || gst_structure_fixate_field_nearest_int (fixated_str, "channels",
2419 if (gst_structure_get_int (fixated_str, "channels",
2420 &fixated_num_channels)) {
2421 GST_DEBUG_OBJECT (dec, "found fixated channel count: %d",
2422 fixated_num_channels);
2423 ds_channels_found = TRUE;
2429 gst_structure_free (fixated_str);
2431 if (ds_format_found && ds_rate_found && ds_channels_found) {
2432 *format = fixated_format;
2433 *sample_rate = fixated_sample_rate;
2434 *num_channels = fixated_num_channels;
2440 gst_caps_unref (allowed_srccaps);
2442 if ((format != NULL) && !ds_format_found)
2443 GST_INFO_OBJECT (dec,
2444 "downstream did not specify format - using default (%s)",
2445 gst_audio_format_to_string (*format));
2446 if ((sample_rate != NULL) && !ds_rate_found)
2447 GST_INFO_OBJECT (dec,
2448 "downstream did not specify sample rate - using default (%d Hz)",
2450 if ((num_channels != NULL) && !ds_channels_found)
2451 GST_INFO_OBJECT (dec,
2452 "downstream did not specify number of channels - using default (%d channels)",
2458 * gst_nonstream_audio_decoder_allocate_output_buffer:
2459 * @dec: Decoder instance
2460 * @size: Size of the output buffer, in bytes
2462 * Allocates an output buffer with the internally configured buffer pool.
2464 * This function may only be called from within @load_from_buffer,
2465 * @load_from_custom, and @decode.
2467 * Returns: Newly allocated output buffer, or NULL if allocation failed
2470 gst_nonstream_audio_decoder_allocate_output_buffer (GstNonstreamAudioDecoder *
2473 if (G_UNLIKELY (dec->output_format_changed ||
2474 (GST_AUDIO_INFO_IS_VALID (&(dec->output_audio_info))
2475 && gst_pad_check_reconfigure (dec->srcpad))
2477 /* renegotiate if necessary, before allocating,
2478 * to make sure the right allocator and the right allocation
2479 * params are used */
2480 if (!gst_nonstream_audio_decoder_negotiate (dec)) {
2481 GST_ERROR_OBJECT (dec,
2482 "could not allocate output buffer because negotiation failed");
2487 return gst_buffer_new_allocate (dec->allocator, size,
2488 &(dec->allocation_params));