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 ("NonstreamAudioOutputMode", output_mode_values);
304 return gst_nonstream_audio_decoder_output_mode_type;
309 gst_nonstream_audio_decoder_subsong_mode_get_type (void)
311 static GType gst_nonstream_audio_decoder_subsong_mode_type = 0;
313 if (!gst_nonstream_audio_decoder_subsong_mode_type) {
314 static GEnumValue subsong_mode_values[] = {
315 {GST_NONSTREAM_AUDIO_SUBSONG_MODE_SINGLE, "Play single subsong",
317 {GST_NONSTREAM_AUDIO_SUBSONG_MODE_ALL, "Play all subsongs", "all"},
318 {GST_NONSTREAM_AUDIO_SUBSONG_MODE_DECODER_DEFAULT,
319 "Decoder specific default behavior", "default"},
323 gst_nonstream_audio_decoder_subsong_mode_type =
324 g_enum_register_static ("NonstreamAudioSubsongMode",
325 subsong_mode_values);
328 return gst_nonstream_audio_decoder_subsong_mode_type;
333 /* Manually defining the GType instead of using G_DEFINE_TYPE_WITH_CODE()
334 * because the _init() function needs to be able to access the derived
335 * class' sink- and srcpads */
339 gst_nonstream_audio_decoder_get_type (void)
341 static volatile gsize nonstream_audio_decoder_type = 0;
343 if (g_once_init_enter (&nonstream_audio_decoder_type)) {
345 static const GTypeInfo nonstream_audio_decoder_info = {
346 sizeof (GstNonstreamAudioDecoderClass),
349 (GClassInitFunc) gst_nonstream_audio_decoder_class_init,
352 sizeof (GstNonstreamAudioDecoder),
354 (GInstanceInitFunc) gst_nonstream_audio_decoder_init,
358 type_ = g_type_register_static (GST_TYPE_ELEMENT,
359 "GstNonstreamAudioDecoder",
360 &nonstream_audio_decoder_info, G_TYPE_FLAG_ABSTRACT);
361 g_once_init_leave (&nonstream_audio_decoder_type, type_);
364 return nonstream_audio_decoder_type;
371 gst_nonstream_audio_decoder_class_init (GstNonstreamAudioDecoderClass * klass)
373 GObjectClass *object_class;
374 GstElementClass *element_class;
376 object_class = G_OBJECT_CLASS (klass);
377 element_class = GST_ELEMENT_CLASS (klass);
379 gst_nonstream_audio_decoder_parent_class = g_type_class_peek_parent (klass);
381 GST_DEBUG_CATEGORY_INIT (nonstream_audiodecoder_debug,
382 "nonstreamaudiodecoder", 0, "nonstream audio decoder base class");
384 object_class->finalize =
385 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_finalize);
386 object_class->set_property =
387 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_set_property);
388 object_class->get_property =
389 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_get_property);
390 element_class->change_state =
391 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_change_state);
396 klass->load_from_buffer = NULL;
397 klass->load_from_custom = NULL;
399 klass->get_main_tags = NULL;
401 klass->get_current_subsong = NULL;
402 klass->set_current_subsong = NULL;
404 klass->get_num_subsongs = NULL;
405 klass->get_subsong_duration = NULL;
406 klass->get_subsong_tags = NULL;
407 klass->set_subsong_mode = NULL;
409 klass->set_num_loops = NULL;
410 klass->get_num_loops = NULL;
412 klass->decode = NULL;
415 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_negotiate_default);
417 klass->decide_allocation =
418 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_decide_allocation_default);
419 klass->propose_allocation =
421 (gst_nonstream_audio_decoder_propose_allocation_default);
423 klass->loads_from_sinkpad = TRUE;
425 g_object_class_install_property (object_class,
426 PROP_CURRENT_SUBSONG,
427 g_param_spec_uint ("current-subsong",
428 "Currently active subsong",
429 "Subsong that is currently selected for playback",
431 DEFAULT_CURRENT_SUBSONG, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
434 g_object_class_install_property (object_class,
436 g_param_spec_enum ("subsong-mode",
438 "Mode which defines how to treat subsongs",
439 GST_TYPE_NONSTREAM_AUDIO_DECODER_SUBSONG_MODE,
440 DEFAULT_SUBSONG_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
443 g_object_class_install_property (object_class,
445 g_param_spec_int ("num-loops",
446 "Number of playback loops",
447 "Number of times a playback loop shall be executed (special values: 0 = no looping; -1 = infinite loop)",
449 DEFAULT_NUM_LOOPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
452 g_object_class_install_property (object_class,
454 g_param_spec_enum ("output-mode",
456 "Which mode playback shall use when a loop is encountered; looping = reset position to start of loop, steady = do not reset position",
457 GST_TYPE_NONSTREAM_AUDIO_DECODER_OUTPUT_MODE,
458 DEFAULT_OUTPUT_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
464 gst_nonstream_audio_decoder_init (GstNonstreamAudioDecoder * dec,
465 GstNonstreamAudioDecoderClass * klass)
467 GstPadTemplate *pad_template;
469 /* These are set here, not in gst_nonstream_audio_decoder_set_initial_state(),
470 * because these are values for the properties; they are not supposed to be
471 * reset in the READY->NULL state change */
472 dec->current_subsong = DEFAULT_CURRENT_SUBSONG;
473 dec->subsong_mode = DEFAULT_SUBSONG_MODE;
474 dec->output_mode = DEFAULT_OUTPUT_MODE;
475 dec->num_loops = DEFAULT_NUM_LOOPS;
477 /* Calling this here, not in the NULL->READY state change,
478 * to make sure get_property calls return valid values */
479 gst_nonstream_audio_decoder_set_initial_state (dec);
481 dec->input_data_adapter = gst_adapter_new ();
482 g_mutex_init (&(dec->mutex));
488 gst_element_class_get_pad_template (GST_ELEMENT_CLASS (klass), "src");
489 g_return_if_fail (pad_template != NULL); /* derived class is supposed to define a src pad template */
491 dec->srcpad = gst_pad_new_from_template (pad_template, "src");
492 gst_pad_set_event_function (dec->srcpad,
493 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_src_event));
494 gst_pad_set_query_function (dec->srcpad,
495 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_src_query));
496 gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
499 if (klass->loads_from_sinkpad) {
500 /* set up sink pad if this class loads from a sinkpad */
503 gst_element_class_get_pad_template (GST_ELEMENT_CLASS (klass), "sink");
504 g_return_if_fail (pad_template != NULL); /* derived class is supposed to define a sink pad template */
506 dec->sinkpad = gst_pad_new_from_template (pad_template, "sink");
507 gst_pad_set_event_function (dec->sinkpad,
508 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_sink_event));
509 gst_pad_set_query_function (dec->sinkpad,
510 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_sink_query));
511 gst_pad_set_chain_function (dec->sinkpad,
512 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_chain));
513 gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad);
521 gst_nonstream_audio_decoder_finalize (GObject * object)
523 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (object);
525 g_mutex_clear (&(dec->mutex));
526 g_object_unref (G_OBJECT (dec->input_data_adapter));
528 G_OBJECT_CLASS (gst_nonstream_audio_decoder_parent_class)->finalize (object);
533 gst_nonstream_audio_decoder_set_property (GObject * object, guint prop_id,
534 GValue const *value, GParamSpec * pspec)
536 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (object);
537 GstNonstreamAudioDecoderClass *klass =
538 GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
541 case PROP_OUTPUT_MODE:
543 GstNonstreamAudioOutputMode new_output_mode;
544 new_output_mode = g_value_get_enum (value);
546 g_assert (klass->get_supported_output_modes);
548 if ((klass->get_supported_output_modes (dec) & (1u << new_output_mode)) ==
550 GST_WARNING_OBJECT (dec,
551 "could not set output mode to %s (not supported by subclass)",
553 GST_NONSTREAM_AUDIO_OUTPUT_MODE_STEADY) ? "steady" : "looping");
557 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
558 if (new_output_mode != dec->output_mode) {
559 gboolean proceed = TRUE;
561 if (dec->loaded_mode) {
562 GstClockTime cur_position;
564 if (klass->set_output_mode != NULL) {
565 if (klass->set_output_mode (dec, new_output_mode, &cur_position))
569 GST_WARNING_OBJECT (dec, "switching to new output mode failed");
572 GST_DEBUG_OBJECT (dec,
573 "cannot call set_output_mode, since it is NULL");
578 gst_nonstream_audio_decoder_output_new_segment (dec, cur_position);
579 dec->output_mode = new_output_mode;
584 /* store output mode in case the property is set before the media got loaded */
585 dec->output_mode = new_output_mode;
588 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
593 case PROP_CURRENT_SUBSONG:
595 guint new_subsong = g_value_get_uint (value);
596 gst_nonstream_audio_decoder_switch_to_subsong (dec, new_subsong, NULL);
601 case PROP_SUBSONG_MODE:
603 GstNonstreamAudioSubsongMode new_subsong_mode = g_value_get_enum (value);
605 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
606 if (new_subsong_mode != dec->subsong_mode) {
607 gboolean proceed = TRUE;
609 if (dec->loaded_mode) {
610 GstClockTime cur_position;
612 if (klass->set_subsong_mode != NULL) {
613 if (klass->set_subsong_mode (dec, new_subsong_mode, &cur_position))
617 GST_WARNING_OBJECT (dec, "switching to new subsong mode failed");
620 GST_DEBUG_OBJECT (dec,
621 "cannot call set_subsong_mode, since it is NULL");
626 if (GST_CLOCK_TIME_IS_VALID (cur_position))
627 gst_nonstream_audio_decoder_output_new_segment (dec,
629 dec->subsong_mode = new_subsong_mode;
634 /* store subsong mode in case the property is set before the media got loaded */
635 dec->subsong_mode = new_subsong_mode;
638 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
645 gint new_num_loops = g_value_get_int (value);
647 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
648 if (new_num_loops != dec->num_loops) {
649 if (dec->loaded_mode) {
650 if (klass->set_num_loops != NULL) {
651 if (!(klass->set_num_loops (dec, new_num_loops)))
652 GST_WARNING_OBJECT (dec, "setting number of loops to %u failed",
655 GST_DEBUG_OBJECT (dec,
656 "cannot call set_num_loops, since it is NULL");
659 /* store number of loops in case the property is set before the media got loaded */
660 dec->num_loops = new_num_loops;
662 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
668 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
675 gst_nonstream_audio_decoder_get_property (GObject * object, guint prop_id,
676 GValue * value, GParamSpec * pspec)
678 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (object);
681 case PROP_OUTPUT_MODE:
683 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
684 g_value_set_enum (value, dec->output_mode);
685 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
689 case PROP_CURRENT_SUBSONG:
691 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
692 g_value_set_uint (value, dec->current_subsong);
693 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
697 case PROP_SUBSONG_MODE:
699 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
700 g_value_set_enum (value, dec->subsong_mode);
701 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
707 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
708 g_value_set_int (value, dec->num_loops);
709 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
714 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
721 static GstStateChangeReturn
722 gst_nonstream_audio_decoder_change_state (GstElement * element,
723 GstStateChange transition)
725 GstStateChangeReturn ret;
728 GST_ELEMENT_CLASS (gst_nonstream_audio_decoder_parent_class)->change_state
729 (element, transition);
730 if (ret == GST_STATE_CHANGE_FAILURE)
733 switch (transition) {
734 case GST_STATE_CHANGE_READY_TO_PAUSED:
737 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (element);
738 GstNonstreamAudioDecoderClass *klass =
739 GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
741 /* For decoders that load with some custom method,
742 * this is now the time to load
744 * It is done *after* calling the parent class' change_state vfunc,
745 * since the pad states need to be set up in order for the loading
746 * to succeed, since it will try to push a new_caps event
747 * downstream etc. (upwards state changes typically are handled
748 * *before* calling the parent class' change_state vfunc ; this is
750 if (!(klass->loads_from_sinkpad) && !(dec->loaded_mode)) {
753 /* load_from_custom is required if loads_from_sinkpad is FALSE */
754 g_assert (klass->load_from_custom != NULL);
756 ret = gst_nonstream_audio_decoder_load_from_custom (dec);
759 GST_ERROR_OBJECT (dec, "loading from custom source failed");
760 return GST_STATE_CHANGE_FAILURE;
763 if (!gst_nonstream_audio_decoder_start_task (dec))
764 return GST_STATE_CHANGE_FAILURE;
771 case GST_STATE_CHANGE_PAUSED_TO_READY:
773 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (element);
774 if (!gst_nonstream_audio_decoder_stop_task (dec))
775 return GST_STATE_CHANGE_FAILURE;
779 case GST_STATE_CHANGE_READY_TO_NULL:
781 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (element);
783 /* In the READY->NULL state change, reset the decoder to an
784 * initial state ensure it can be used for a fresh new session */
785 gst_nonstream_audio_decoder_cleanup_state (dec);
799 gst_nonstream_audio_decoder_sink_event (GstPad * pad, GstObject * parent,
802 gboolean res = FALSE;
803 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (parent);
805 switch (GST_EVENT_TYPE (event)) {
806 case GST_EVENT_SEGMENT:
808 /* Upstream sends in a byte segment, which is uninteresting here,
809 * since a custom segment event is generated anyway */
810 gst_event_unref (event);
818 GstBuffer *adapter_buffer;
820 if (dec->loaded_mode) {
821 /* If media has already been loaded, then the decoder
822 * task has been started; the EOS event can be ignored */
824 GST_DEBUG_OBJECT (dec,
825 "EOS received after media was loaded -> ignoring");
828 /* take all data in the input data adapter,
829 * and try to load the media from it */
831 avail_size = gst_adapter_available (dec->input_data_adapter);
832 if (avail_size == 0) {
833 GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL),
834 ("EOS event raised, but no data was received - cannot load anything"));
839 gst_adapter_take_buffer (dec->input_data_adapter, avail_size);
841 if (!gst_nonstream_audio_decoder_load_from_buffer (dec, adapter_buffer)) {
845 res = gst_nonstream_audio_decoder_start_task (dec);
852 res = gst_pad_event_default (pad, parent, event);
860 gst_nonstream_audio_decoder_sink_query (GstPad * pad, GstObject * parent,
863 gboolean res = FALSE;
864 GstNonstreamAudioDecoder *dec;
865 GstNonstreamAudioDecoderClass *klass;
867 dec = GST_NONSTREAM_AUDIO_DECODER (parent);
868 klass = GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
870 switch (GST_QUERY_TYPE (query)) {
871 case GST_QUERY_ALLOCATION:
873 if (klass->propose_allocation != NULL)
874 res = klass->propose_allocation (dec, query);
880 res = gst_pad_query_default (pad, parent, query);
888 gst_nonstream_audio_decoder_chain (G_GNUC_UNUSED GstPad * pad,
889 GstObject * parent, GstBuffer * buffer)
891 GstFlowReturn flow_ret = GST_FLOW_OK;
892 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (parent);
894 /* query upstream size in bytes to know how many bytes to expect
895 * this is a safety measure to prevent the case when upstream never
896 * reaches EOS (or only after a long time) and we keep loading and
897 * loading and eventually run out of memory */
898 if (dec->upstream_size < 0) {
899 if (!gst_nonstream_audio_decoder_get_upstream_size (dec,
900 &(dec->upstream_size))) {
901 GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL),
902 ("Cannot load - upstream size (in bytes) could not be determined"));
903 return GST_FLOW_ERROR;
907 if (dec->loaded_mode) {
908 /* media is already loaded - discard any incoming
909 * buffers, since they are not needed */
911 GST_DEBUG_OBJECT (dec, "received data after media was loaded - ignoring");
913 gst_buffer_unref (buffer);
915 /* accumulate data until end-of-stream or the upstream
916 * size is reached, then load media and commence playback */
920 gst_adapter_push (dec->input_data_adapter, buffer);
921 avail_size = gst_adapter_available (dec->input_data_adapter);
922 if (avail_size >= dec->upstream_size) {
923 GstBuffer *adapter_buffer =
924 gst_adapter_take_buffer (dec->input_data_adapter, avail_size);
926 if (gst_nonstream_audio_decoder_load_from_buffer (dec, adapter_buffer))
928 gst_nonstream_audio_decoder_start_task (dec) ? GST_FLOW_OK :
931 flow_ret = GST_FLOW_ERROR;
941 gst_nonstream_audio_decoder_src_event (GstPad * pad, GstObject * parent,
944 gboolean res = FALSE;
945 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (parent);
947 switch (GST_EVENT_TYPE (event)) {
950 res = gst_nonstream_audio_decoder_do_seek (dec, event);
954 case GST_EVENT_TOC_SELECT:
956 /* NOTE: This event may be received multiple times if it
957 * was originally sent to a bin containing multiple sink
958 * elements (for example, playbin). This is OK and does
959 * not break anything. */
962 guint subsong_idx = 0;
965 gst_event_parse_toc_select (event, &uid);
968 && (sscanf (uid, "nonstream-subsong-%05u", &subsong_idx) == 1)) {
969 seqnum = gst_event_get_seqnum (event);
971 GST_DEBUG_OBJECT (dec,
972 "received TOC select event (sequence number %" G_GUINT32_FORMAT
973 "), switching to subsong %u", seqnum, subsong_idx);
975 gst_nonstream_audio_decoder_switch_to_subsong (dec, subsong_idx,
987 res = gst_pad_event_default (pad, parent, event);
995 gst_nonstream_audio_decoder_src_query (GstPad * pad, GstObject * parent,
998 gboolean res = FALSE;
999 GstNonstreamAudioDecoder *dec;
1000 GstNonstreamAudioDecoderClass *klass;
1002 dec = GST_NONSTREAM_AUDIO_DECODER (parent);
1003 klass = GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
1005 switch (GST_QUERY_TYPE (query)) {
1006 case GST_QUERY_DURATION:
1009 GST_TRACE_OBJECT (parent, "duration query");
1011 if (!(dec->loaded_mode)) {
1012 GST_DEBUG_OBJECT (parent,
1013 "cannot respond to duration query: nothing is loaded yet");
1017 GST_TRACE_OBJECT (parent, "parsing duration query");
1018 gst_query_parse_duration (query, &format, NULL);
1020 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1021 if ((format == GST_FORMAT_TIME)
1022 && (dec->subsong_duration != GST_CLOCK_TIME_NONE)) {
1023 GST_DEBUG_OBJECT (parent,
1024 "responding to query with duration %" GST_TIME_FORMAT,
1025 GST_TIME_ARGS (dec->subsong_duration));
1026 gst_query_set_duration (query, format, dec->subsong_duration);
1028 } else if (format != GST_FORMAT_TIME)
1029 GST_DEBUG_OBJECT (parent,
1030 "cannot respond to duration query: format is %s, expected time format",
1031 gst_format_get_name (format));
1032 else if (dec->subsong_duration == GST_CLOCK_TIME_NONE)
1033 GST_DEBUG_OBJECT (parent,
1034 "cannot respond to duration query: no valid subsong duration available");
1035 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1040 case GST_QUERY_POSITION:
1043 if (!(dec->loaded_mode)) {
1044 GST_DEBUG_OBJECT (parent,
1045 "cannot respond to position query: nothing is loaded yet");
1049 if (klass->tell == NULL) {
1050 GST_DEBUG_OBJECT (parent,
1051 "cannot respond to position query: subclass does not have tell() function defined");
1055 gst_query_parse_position (query, &format, NULL);
1056 if (format == GST_FORMAT_TIME) {
1059 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1060 pos = klass->tell (dec);
1061 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1063 GST_DEBUG_OBJECT (parent,
1064 "position query received with format TIME -> reporting position %"
1065 GST_TIME_FORMAT, GST_TIME_ARGS (pos));
1066 gst_query_set_position (query, format, pos);
1069 GST_DEBUG_OBJECT (parent,
1070 "position query received with unsupported format %s -> not reporting anything",
1071 gst_format_get_name (format));
1077 case GST_QUERY_SEEKING:
1080 GstClockTime duration;
1082 if (!dec->loaded_mode) {
1083 GST_DEBUG_OBJECT (parent,
1084 "cannot respond to seeking query: nothing is loaded yet");
1088 if (klass->seek == NULL) {
1089 GST_DEBUG_OBJECT (parent,
1090 "cannot respond to seeking query: subclass does not have seek() function defined");
1094 gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
1096 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1097 duration = dec->subsong_duration;
1098 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1100 if (fmt == GST_FORMAT_TIME) {
1101 GST_DEBUG_OBJECT (parent,
1102 "seeking query received with format TIME -> can seek: yes");
1103 gst_query_set_seeking (query, fmt, TRUE, 0, duration);
1106 GST_DEBUG_OBJECT (parent,
1107 "seeking query received with unsupported format %s -> can seek: no",
1108 gst_format_get_name (fmt));
1109 gst_query_set_seeking (query, fmt, FALSE, 0, -1);
1117 res = gst_pad_query_default (pad, parent, query);
1126 gst_nonstream_audio_decoder_set_initial_state (GstNonstreamAudioDecoder * dec)
1128 dec->upstream_size = -1;
1129 dec->loaded_mode = FALSE;
1131 dec->subsong_duration = GST_CLOCK_TIME_NONE;
1133 dec->output_format_changed = FALSE;
1134 gst_audio_info_init (&(dec->output_audio_info));
1135 dec->num_decoded_samples = 0;
1136 dec->cur_pos_in_samples = 0;
1137 gst_segment_init (&(dec->cur_segment), GST_FORMAT_TIME);
1138 dec->discont = FALSE;
1142 dec->allocator = NULL;
1147 gst_nonstream_audio_decoder_cleanup_state (GstNonstreamAudioDecoder * dec)
1149 gst_adapter_clear (dec->input_data_adapter);
1151 if (dec->allocator != NULL) {
1152 gst_object_unref (dec->allocator);
1153 dec->allocator = NULL;
1156 if (dec->toc != NULL) {
1157 gst_toc_unref (dec->toc);
1161 gst_nonstream_audio_decoder_set_initial_state (dec);
1166 gst_nonstream_audio_decoder_negotiate (GstNonstreamAudioDecoder * dec)
1168 /* must be called with lock */
1170 GstNonstreamAudioDecoderClass *klass;
1171 gboolean res = TRUE;
1173 klass = GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
1175 /* protected by a mutex, since the allocator might currently be in use */
1176 if (klass->negotiate != NULL)
1177 res = klass->negotiate (dec);
1184 gst_nonstream_audio_decoder_negotiate_default (GstNonstreamAudioDecoder * dec)
1186 /* mutex is locked when this is called */
1189 GstNonstreamAudioDecoderClass *klass;
1190 gboolean res = TRUE;
1191 GstQuery *query = NULL;
1192 GstAllocator *allocator;
1193 GstAllocationParams allocation_params;
1195 g_return_val_if_fail (GST_IS_NONSTREAM_AUDIO_DECODER (dec), FALSE);
1196 g_return_val_if_fail (GST_AUDIO_INFO_IS_VALID (&(dec->output_audio_info)),
1199 klass = GST_NONSTREAM_AUDIO_DECODER_CLASS (G_OBJECT_GET_CLASS (dec));
1201 caps = gst_audio_info_to_caps (&(dec->output_audio_info));
1203 GST_DEBUG_OBJECT (dec, "setting src caps %" GST_PTR_FORMAT, (gpointer) caps);
1205 res = gst_pad_push_event (dec->srcpad, gst_event_new_caps (caps));
1206 /* clear any pending reconfigure flag */
1207 gst_pad_check_reconfigure (dec->srcpad);
1210 GST_WARNING_OBJECT (dec, "could not push new caps event downstream");
1214 GST_TRACE_OBJECT (dec, "src caps set");
1216 dec->output_format_changed = FALSE;
1218 query = gst_query_new_allocation (caps, TRUE);
1219 if (!gst_pad_peer_query (dec->srcpad, query)) {
1220 GST_DEBUG_OBJECT (dec, "didn't get downstream ALLOCATION hints");
1223 g_assert (klass->decide_allocation != NULL);
1224 res = klass->decide_allocation (dec, query);
1226 GST_DEBUG_OBJECT (dec, "ALLOCATION (%d) params: %" GST_PTR_FORMAT, res,
1230 goto no_decide_allocation;
1232 /* we got configuration from our peer or the decide_allocation method,
1234 if (gst_query_get_n_allocation_params (query) > 0) {
1235 gst_query_parse_nth_allocation_param (query, 0, &allocator,
1236 &allocation_params);
1239 gst_allocation_params_init (&allocation_params);
1242 if (dec->allocator != NULL)
1243 gst_object_unref (dec->allocator);
1244 dec->allocator = allocator;
1245 dec->allocation_params = allocation_params;
1249 gst_query_unref (query);
1250 gst_caps_unref (caps);
1254 no_decide_allocation:
1256 GST_WARNING_OBJECT (dec, "subclass failed to decide allocation");
1263 gst_nonstream_audio_decoder_decide_allocation_default (G_GNUC_UNUSED
1264 GstNonstreamAudioDecoder * dec, GstQuery * query)
1266 GstAllocator *allocator = NULL;
1267 GstAllocationParams params;
1268 gboolean update_allocator;
1270 /* we got configuration from our peer or the decide_allocation method,
1272 if (gst_query_get_n_allocation_params (query) > 0) {
1273 /* try the allocator */
1274 gst_query_parse_nth_allocation_param (query, 0, &allocator, ¶ms);
1275 update_allocator = TRUE;
1278 gst_allocation_params_init (¶ms);
1279 update_allocator = FALSE;
1282 if (update_allocator)
1283 gst_query_set_nth_allocation_param (query, 0, allocator, ¶ms);
1285 gst_query_add_allocation_param (query, allocator, ¶ms);
1288 gst_object_unref (allocator);
1295 gst_nonstream_audio_decoder_propose_allocation_default (G_GNUC_UNUSED
1296 GstNonstreamAudioDecoder * dec, G_GNUC_UNUSED GstQuery * query)
1303 gst_nonstream_audio_decoder_get_upstream_size (GstNonstreamAudioDecoder * dec,
1306 return gst_pad_peer_query_duration (dec->sinkpad, GST_FORMAT_BYTES, length)
1312 gst_nonstream_audio_decoder_load_from_buffer (GstNonstreamAudioDecoder * dec,
1316 GstClockTime initial_position;
1317 GstNonstreamAudioDecoderClass *klass;
1320 klass = GST_NONSTREAM_AUDIO_DECODER_CLASS (G_OBJECT_GET_CLASS (dec));
1321 g_assert (klass->load_from_buffer != NULL);
1323 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1325 GST_LOG_OBJECT (dec, "read %" G_GSIZE_FORMAT " bytes from upstream",
1326 gst_buffer_get_size (buffer));
1328 initial_position = 0;
1330 klass->load_from_buffer (dec, buffer, dec->current_subsong,
1331 dec->subsong_mode, &initial_position, &(dec->output_mode),
1333 gst_buffer_unref (buffer);
1336 gst_nonstream_audio_decoder_finish_load (dec, load_ok, initial_position,
1339 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1346 gst_nonstream_audio_decoder_load_from_custom (GstNonstreamAudioDecoder * dec)
1349 GstClockTime initial_position;
1350 GstNonstreamAudioDecoderClass *klass;
1353 klass = GST_NONSTREAM_AUDIO_DECODER_CLASS (G_OBJECT_GET_CLASS (dec));
1354 g_assert (klass->load_from_custom != NULL);
1356 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1358 GST_LOG_OBJECT (dec,
1359 "reading song from custom source defined by derived class");
1361 initial_position = 0;
1363 klass->load_from_custom (dec, dec->current_subsong, dec->subsong_mode,
1364 &initial_position, &(dec->output_mode), &(dec->num_loops));
1367 gst_nonstream_audio_decoder_finish_load (dec, load_ok, initial_position,
1370 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1377 gst_nonstream_audio_decoder_finish_load (GstNonstreamAudioDecoder * dec,
1378 gboolean load_ok, GstClockTime initial_position, gboolean send_stream_start)
1380 /* must be called with lock */
1382 GstNonstreamAudioDecoderClass *klass =
1383 GST_NONSTREAM_AUDIO_DECODER_CLASS (G_OBJECT_GET_CLASS (dec));
1385 GST_TRACE_OBJECT (dec, "enter finish_load");
1391 GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("Loading failed"));
1395 if (!GST_AUDIO_INFO_IS_VALID (&(dec->output_audio_info))) {
1396 GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL),
1397 ("Audio info is invalid after loading"));
1402 /* Log the number of available subsongs */
1403 if (klass->get_num_subsongs != NULL)
1404 GST_DEBUG_OBJECT (dec, "%u subsong(s) available",
1405 klass->get_num_subsongs (dec));
1408 /* Set the current subsong (or use the default value) */
1409 if (klass->get_current_subsong != NULL) {
1410 GST_TRACE_OBJECT (dec, "requesting current subsong");
1411 dec->current_subsong = klass->get_current_subsong (dec);
1415 /* Handle the subsong duration */
1416 if (klass->get_subsong_duration != NULL) {
1417 GstClockTime duration;
1418 GST_TRACE_OBJECT (dec, "requesting subsong duration");
1419 duration = klass->get_subsong_duration (dec, dec->current_subsong);
1420 gst_nonstream_audio_decoder_update_subsong_duration (dec, duration);
1424 /* Send tags downstream (if some exist) */
1425 if (klass->get_subsong_tags != NULL) {
1426 /* Subsong tags available */
1429 GST_TRACE_OBJECT (dec, "requesting subsong tags");
1430 tags = klass->get_subsong_tags (dec, dec->current_subsong);
1432 tags = gst_nonstream_audio_decoder_add_main_tags (dec, tags);
1434 gst_pad_push_event (dec->srcpad, gst_event_new_tag (tags));
1436 /* No subsong tags - just send main tags out */
1438 GstTagList *tags = gst_tag_list_new_empty ();
1439 tags = gst_nonstream_audio_decoder_add_main_tags (dec, tags);
1440 gst_pad_push_event (dec->srcpad, gst_event_new_tag (tags));
1444 /* Send stream start downstream if requested */
1445 if (send_stream_start) {
1450 gst_pad_create_stream_id (dec->srcpad, GST_ELEMENT_CAST (dec), NULL);
1451 GST_DEBUG_OBJECT (dec, "pushing STREAM_START with stream id \"%s\"",
1454 event = gst_event_new_stream_start (stream_id);
1455 gst_event_set_group_id (event, gst_util_group_id_next ());
1456 gst_pad_push_event (dec->srcpad, event);
1461 /* Update the table of contents */
1462 gst_nonstream_audio_decoder_update_toc (dec, klass);
1465 /* Negotiate output caps and an allocator */
1466 GST_TRACE_OBJECT (dec, "negotiating caps and allocator");
1467 if (!gst_nonstream_audio_decoder_negotiate (dec)) {
1468 GST_ERROR_OBJECT (dec, "negotiation failed - aborting load");
1473 /* Send new segment downstream */
1474 gst_nonstream_audio_decoder_output_new_segment (dec, initial_position);
1476 dec->loaded_mode = TRUE;
1478 GST_TRACE_OBJECT (dec, "exit finish_load");
1485 gst_nonstream_audio_decoder_start_task (GstNonstreamAudioDecoder * dec)
1487 if (!gst_pad_start_task (dec->srcpad,
1488 (GstTaskFunction) gst_nonstream_audio_decoder_output_task, dec,
1490 GST_ERROR_OBJECT (dec, "could not start decoder output task");
1498 gst_nonstream_audio_decoder_stop_task (GstNonstreamAudioDecoder * dec)
1500 if (!gst_pad_stop_task (dec->srcpad)) {
1501 GST_ERROR_OBJECT (dec, "could not stop decoder output task");
1509 gst_nonstream_audio_decoder_switch_to_subsong (GstNonstreamAudioDecoder * dec,
1510 guint new_subsong, guint32 const *seqnum)
1512 gboolean ret = TRUE;
1513 GstNonstreamAudioDecoderClass *klass =
1514 GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
1517 if (klass->set_current_subsong == NULL) {
1518 /* If set_current_subsong wasn't set by the subclass, then
1519 * subsongs are not supported. It is not an error if this
1520 * function is called in that case, since it might happen
1521 * because the current-subsong property was set (and since
1522 * this is a base class property, it is always available). */
1523 GST_DEBUG_OBJECT (dec, "cannot call set_current_subsong, since it is NULL");
1527 if (dec->loaded_mode) {
1529 GstClockTime new_position;
1530 GstClockTime new_subsong_duration = GST_CLOCK_TIME_NONE;
1533 /* Check if (a) new_subsong is already the current subsong
1534 * and (b) if new_subsong exceeds the number of available
1535 * subsongs. Do this here, when the song is loaded,
1536 * because prior to loading, the number of subsong is usually
1537 * not known (and the loading process might choose a specific
1538 * subsong to be the current one at the start of playback). */
1540 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1542 if (new_subsong == dec->current_subsong) {
1543 GST_DEBUG_OBJECT (dec,
1544 "subsong %u is already the current subsong - ignoring call",
1549 if (klass->get_num_subsongs) {
1550 guint num_subsongs = klass->get_num_subsongs (dec);
1552 if (new_subsong >= num_subsongs) {
1553 GST_WARNING_OBJECT (dec,
1554 "subsong %u is out of bounds (there are %u subsongs) - not switching",
1555 new_subsong, num_subsongs);
1560 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1563 /* Switching subsongs during playback is very similar to a
1564 * flushing seek. Therefore, the stream lock must be taken,
1565 * flush-start/flush-stop events have to be sent, and
1566 * the pad task has to be restarted. */
1569 fevent = gst_event_new_flush_start ();
1570 if (seqnum != NULL) {
1571 gst_event_set_seqnum (fevent, *seqnum);
1572 GST_DEBUG_OBJECT (dec,
1573 "sending flush start event with sequence number %" G_GUINT32_FORMAT,
1576 GST_DEBUG_OBJECT (dec, "sending flush start event (no sequence number)");
1578 gst_pad_push_event (dec->srcpad, gst_event_ref (fevent));
1579 /* unlock upstream pull_range */
1580 if (klass->loads_from_sinkpad)
1581 gst_pad_push_event (dec->sinkpad, fevent);
1583 gst_event_unref (fevent);
1586 GST_PAD_STREAM_LOCK (dec->srcpad);
1589 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1592 if (!(klass->set_current_subsong (dec, new_subsong, &new_position))) {
1593 /* Switch failed. Do _not_ exit early from here - playback must
1594 * continue from the current subsong, and it cannot do that if
1595 * we exit here. Try getting the current position and proceed as
1596 * if the switch succeeded (but set the return value to FALSE.) */
1600 new_position = klass->tell (dec);
1603 GST_WARNING_OBJECT (dec, "switching to new subsong %u failed",
1607 /* Flushing seek resets the base time, which means num_decoded_samples
1608 * needs to be set to 0, since it defines the segment.base value */
1609 dec->num_decoded_samples = 0;
1612 fevent = gst_event_new_flush_stop (TRUE);
1613 if (seqnum != NULL) {
1614 gst_event_set_seqnum (fevent, *seqnum);
1615 GST_DEBUG_OBJECT (dec,
1616 "sending flush stop event with sequence number %" G_GUINT32_FORMAT,
1619 GST_DEBUG_OBJECT (dec, "sending flush stop event (no sequence number)");
1621 gst_pad_push_event (dec->srcpad, gst_event_ref (fevent));
1622 /* unlock upstream pull_range */
1623 if (klass->loads_from_sinkpad)
1624 gst_pad_push_event (dec->sinkpad, fevent);
1626 gst_event_unref (fevent);
1629 /* use the new subsong's duration (if one exists) */
1630 if (klass->get_subsong_duration != NULL)
1631 new_subsong_duration = klass->get_subsong_duration (dec, new_subsong);
1632 gst_nonstream_audio_decoder_update_subsong_duration (dec,
1633 new_subsong_duration);
1635 /* create a new segment for the new subsong */
1636 gst_nonstream_audio_decoder_output_new_segment (dec, new_position);
1638 /* use the new subsong's tags (if any exist) */
1639 if (klass->get_subsong_tags != NULL) {
1640 GstTagList *subsong_tags = klass->get_subsong_tags (dec, new_subsong);
1641 if (subsong_tags != NULL)
1643 gst_nonstream_audio_decoder_add_main_tags (dec, subsong_tags);
1644 if (subsong_tags != NULL)
1645 gst_pad_push_event (dec->srcpad, gst_event_new_tag (subsong_tags));
1648 GST_DEBUG_OBJECT (dec, "successfully switched to new subsong %u",
1650 dec->current_subsong = new_subsong;
1653 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1656 /* Subsong has been switched, and all necessary events have been
1657 * pushed downstream. Restart srcpad task. */
1658 gst_nonstream_audio_decoder_start_task (dec);
1660 /* Unlock stream, we are done */
1661 GST_PAD_STREAM_UNLOCK (dec->srcpad);
1663 /* If song hasn't been loaded yet, then playback cannot currently
1664 * been happening. In this case, a "switch" is simple - just store
1665 * the current subsong index. When the song is loaded, it will
1666 * start playing this subsong. */
1668 GST_DEBUG_OBJECT (dec,
1669 "playback hasn't started yet - storing subsong index %u as the current subsong",
1672 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1673 dec->current_subsong = new_subsong;
1674 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1683 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1689 gst_nonstream_audio_decoder_update_toc (GstNonstreamAudioDecoder * dec,
1690 GstNonstreamAudioDecoderClass * klass)
1692 /* must be called with lock */
1694 guint num_subsongs, i;
1696 if (dec->toc != NULL) {
1697 gst_toc_unref (dec->toc);
1701 if (klass->get_num_subsongs == NULL)
1704 num_subsongs = klass->get_num_subsongs (dec);
1705 if (num_subsongs <= 1) {
1706 GST_DEBUG_OBJECT (dec, "no need for a TOC since there is only one subsong");
1710 dec->toc = gst_toc_new (GST_TOC_SCOPE_GLOBAL);
1712 if (klass->get_main_tags) {
1713 GstTagList *main_tags = klass->get_main_tags (dec);
1715 gst_toc_set_tags (dec->toc, main_tags);
1718 for (i = 0; i < num_subsongs; ++i) {
1721 GstClockTime duration;
1725 (klass->get_subsong_duration !=
1726 NULL) ? klass->get_subsong_duration (dec, i) : GST_CLOCK_TIME_NONE;
1728 (klass->get_subsong_tags != NULL) ? klass->get_subsong_tags (dec,
1731 tags = gst_tag_list_new_empty ();
1733 uid = g_strdup_printf ("nonstream-subsong-%05u", i);
1734 entry = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_TRACK, uid);
1735 /* Set the UID as title tag for TOC entry if no title already present */
1736 gst_tag_list_add (tags, GST_TAG_MERGE_KEEP, GST_TAG_TITLE, uid, NULL);
1737 /* Set the subsong duration as duration tag for TOC entry if no duration already present */
1738 if (duration != GST_CLOCK_TIME_NONE)
1739 gst_tag_list_add (tags, GST_TAG_MERGE_KEEP, GST_TAG_DURATION, duration,
1742 /* FIXME: TOC does not allow GST_CLOCK_TIME_NONE as a stop value */
1743 if (duration == GST_CLOCK_TIME_NONE)
1744 duration = G_MAXINT64;
1746 /* Subsongs always start at 00:00 */
1747 gst_toc_entry_set_start_stop_times (entry, 0, duration);
1748 gst_toc_entry_set_tags (entry, tags);
1750 /* NOTE: *not* adding loop count via gst_toc_entry_set_loop(), since
1751 * in GstNonstreamAudioDecoder, looping is a playback property, not
1752 * a property of the subsongs themselves */
1754 GST_DEBUG_OBJECT (dec,
1755 "new toc entry: uid: \"%s\" duration: %" GST_TIME_FORMAT " tags: %"
1756 GST_PTR_FORMAT, uid, GST_TIME_ARGS (duration), (gpointer) tags);
1758 gst_toc_append_entry (dec->toc, entry);
1763 gst_pad_push_event (dec->srcpad, gst_event_new_toc (dec->toc, FALSE));
1768 gst_nonstream_audio_decoder_update_subsong_duration (GstNonstreamAudioDecoder *
1769 dec, GstClockTime duration)
1771 /* must be called with lock */
1773 dec->subsong_duration = duration;
1774 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1775 gst_element_post_message (GST_ELEMENT (dec),
1776 gst_message_new_duration_changed (GST_OBJECT (dec)));
1777 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1782 gst_nonstream_audio_decoder_output_new_segment (GstNonstreamAudioDecoder * dec,
1783 GstClockTime start_position)
1785 /* must be called with lock */
1789 gst_segment_init (&segment, GST_FORMAT_TIME);
1792 gst_util_uint64_scale_int (dec->num_decoded_samples, GST_SECOND,
1793 dec->output_audio_info.rate);
1795 segment.time = start_position;
1797 segment.position = 0;
1799 /* note that num_decoded_samples isn't being reset; it is the
1800 * analogue to the segment base value, and thus is supposed to
1801 * monotonically increase, except for when a flushing seek happens
1802 * (since a flushing seek is supposed to be a fresh restart for
1803 * the whole pipeline) */
1804 dec->cur_pos_in_samples = 0;
1806 /* stop/duration members are not set, on purpose - in case of loops,
1807 * new segments will be generated, which automatically put an implicit
1808 * end on the current segment (the segment implicitely "ends" when the
1809 * new one starts), and having a stop value might cause very slight
1810 * gaps occasionally due to slight jitter in the calculation of
1811 * base times etc. */
1813 GST_DEBUG_OBJECT (dec,
1814 "output new segment with base %" GST_TIME_FORMAT " time %"
1815 GST_TIME_FORMAT, GST_TIME_ARGS (segment.base),
1816 GST_TIME_ARGS (segment.time));
1818 dec->cur_segment = segment;
1819 dec->discont = TRUE;
1821 gst_pad_push_event (dec->srcpad, gst_event_new_segment (&segment));
1826 gst_nonstream_audio_decoder_do_seek (GstNonstreamAudioDecoder * dec,
1833 GstSeekType start_type, stop_type;
1834 GstClockTime new_position;
1839 GstNonstreamAudioDecoderClass *klass =
1840 GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
1842 if (klass->seek == NULL) {
1843 GST_DEBUG_OBJECT (dec,
1844 "cannot seek: subclass does not have seek() function defined");
1848 if (!dec->loaded_mode) {
1849 GST_DEBUG_OBJECT (dec, "nothing loaded yet - cannot seek");
1853 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1854 if (!GST_AUDIO_INFO_IS_VALID (&(dec->output_audio_info))) {
1855 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1856 GST_DEBUG_OBJECT (dec, "no valid output audioinfo present - cannot seek");
1859 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1862 GST_DEBUG_OBJECT (dec, "starting seek");
1864 gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start,
1866 seqnum = gst_event_get_seqnum (event);
1868 GST_DEBUG_OBJECT (dec,
1870 "rate %f format %s "
1871 "start type %s start %" GST_TIME_FORMAT " "
1872 "stop type %s stop %" GST_TIME_FORMAT,
1873 rate, gst_format_get_name (format),
1874 get_seek_type_name (start_type), GST_TIME_ARGS (start),
1875 get_seek_type_name (stop_type), GST_TIME_ARGS (stop)
1878 if (format != GST_FORMAT_TIME) {
1879 GST_DEBUG_OBJECT (dec, "seeking is only supported in TIME format");
1884 GST_DEBUG_OBJECT (dec, "only positive seek rates are supported");
1888 flush = ((flags & GST_SEEK_FLAG_FLUSH) == GST_SEEK_FLAG_FLUSH);
1891 GstEvent *fevent = gst_event_new_flush_start ();
1892 gst_event_set_seqnum (fevent, seqnum);
1894 GST_DEBUG_OBJECT (dec,
1895 "sending flush start event with sequence number %" G_GUINT32_FORMAT,
1898 gst_pad_push_event (dec->srcpad, gst_event_ref (fevent));
1899 /* unlock upstream pull_range */
1900 if (klass->loads_from_sinkpad)
1901 gst_pad_push_event (dec->sinkpad, fevent);
1903 gst_event_unref (fevent);
1905 gst_pad_pause_task (dec->srcpad);
1907 GST_PAD_STREAM_LOCK (dec->srcpad);
1909 segment = dec->cur_segment;
1911 if (!gst_segment_do_seek (&segment,
1912 rate, format, flags, start_type, start, stop_type, stop, NULL)) {
1913 GST_DEBUG_OBJECT (dec, "could not seek in segment");
1914 GST_PAD_STREAM_UNLOCK (dec->srcpad);
1918 GST_DEBUG_OBJECT (dec,
1921 "rate %f applied rate %f "
1923 "base %" GST_TIME_FORMAT " "
1924 "offset %" GST_TIME_FORMAT " "
1925 "start %" GST_TIME_FORMAT " "
1926 "stop %" GST_TIME_FORMAT " "
1927 "time %" GST_TIME_FORMAT " "
1928 "position %" GST_TIME_FORMAT " "
1929 "duration %" GST_TIME_FORMAT,
1930 segment.rate, segment.applied_rate,
1931 gst_format_get_name (segment.format),
1932 GST_TIME_ARGS (segment.base),
1933 GST_TIME_ARGS (segment.offset),
1934 GST_TIME_ARGS (segment.start),
1935 GST_TIME_ARGS (segment.stop),
1936 GST_TIME_ARGS (segment.time),
1937 GST_TIME_ARGS (segment.position), GST_TIME_ARGS (segment.duration)
1940 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1942 new_position = segment.position;
1943 res = klass->seek (dec, &new_position);
1944 segment.position = new_position;
1946 dec->cur_segment = segment;
1947 dec->cur_pos_in_samples =
1948 gst_util_uint64_scale_int (dec->cur_segment.position,
1949 dec->output_audio_info.rate, GST_SECOND);
1950 dec->num_decoded_samples = 0;
1952 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1955 GstEvent *fevent = gst_event_new_flush_stop (TRUE);
1956 gst_event_set_seqnum (fevent, seqnum);
1958 GST_DEBUG_OBJECT (dec,
1959 "sending flush stop event with sequence number %" G_GUINT32_FORMAT,
1962 gst_pad_push_event (dec->srcpad, gst_event_ref (fevent));
1963 if (klass->loads_from_sinkpad)
1964 gst_pad_push_event (dec->sinkpad, fevent);
1966 gst_event_unref (fevent);
1970 if (flags & GST_SEEK_FLAG_SEGMENT) {
1971 GST_DEBUG_OBJECT (dec, "posting SEGMENT_START message");
1973 gst_element_post_message (GST_ELEMENT (dec),
1974 gst_message_new_segment_start (GST_OBJECT (dec),
1975 GST_FORMAT_TIME, segment.start)
1979 gst_pad_push_event (dec->srcpad, gst_event_new_segment (&segment));
1981 GST_INFO_OBJECT (dec, "seek succeeded");
1983 gst_nonstream_audio_decoder_start_task (dec);
1985 GST_WARNING_OBJECT (dec, "seek failed");
1988 GST_PAD_STREAM_UNLOCK (dec->srcpad);
1990 gst_event_unref (event);
1997 gst_nonstream_audio_decoder_add_main_tags (GstNonstreamAudioDecoder * dec,
2000 GstNonstreamAudioDecoderClass *klass =
2001 GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
2003 if (!klass->get_main_tags)
2006 tags = gst_tag_list_make_writable (tags);
2008 GstClockTime duration;
2009 GstTagList *main_tags;
2011 /* Get main tags. If some exist, merge them with the given tags,
2012 * and return the merged result. Otherwise, just return the given tags. */
2013 main_tags = klass->get_main_tags (dec);
2015 tags = gst_tag_list_merge (main_tags, tags, GST_TAG_MERGE_REPLACE);
2016 gst_tag_list_unref (main_tags);
2019 /* Add subsong duration if available */
2020 duration = dec->subsong_duration;
2021 if (GST_CLOCK_TIME_IS_VALID (duration))
2022 gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_DURATION, duration,
2027 GST_ERROR_OBJECT (dec, "could not make subsong tags writable");
2034 gst_nonstream_audio_decoder_output_task (GstNonstreamAudioDecoder * dec)
2040 GstNonstreamAudioDecoderClass *klass;
2041 klass = GST_NONSTREAM_AUDIO_DECODER_CLASS (G_OBJECT_GET_CLASS (dec));
2042 g_assert (klass->decode != NULL);
2044 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
2046 /* perform the actual decoding */
2047 if (!(klass->decode (dec, &outbuf, &num_samples))) {
2049 GST_INFO_OBJECT (dec, "decode() reports end -> sending EOS event");
2050 gst_pad_push_event (dec->srcpad, gst_event_new_eos ());
2054 if (outbuf == NULL) {
2055 GST_ERROR_OBJECT (outbuf, "decode() produced NULL buffer");
2059 /* set the buffer's metadata */
2060 GST_BUFFER_DURATION (outbuf) =
2061 gst_util_uint64_scale_int (num_samples, GST_SECOND,
2062 dec->output_audio_info.rate);
2063 GST_BUFFER_OFFSET (outbuf) = dec->cur_pos_in_samples;
2064 GST_BUFFER_OFFSET_END (outbuf) = dec->cur_pos_in_samples + num_samples;
2065 GST_BUFFER_PTS (outbuf) =
2066 gst_util_uint64_scale_int (dec->cur_pos_in_samples, GST_SECOND,
2067 dec->output_audio_info.rate);
2068 GST_BUFFER_DTS (outbuf) = GST_BUFFER_PTS (outbuf);
2070 if (G_UNLIKELY (dec->discont)) {
2071 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
2072 dec->discont = FALSE;
2075 GST_LOG_OBJECT (dec,
2076 "output buffer stats: num_samples = %u duration = %" GST_TIME_FORMAT
2077 " cur_pos_in_samples = %" G_GUINT64_FORMAT " timestamp = %"
2078 GST_TIME_FORMAT, num_samples,
2079 GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)), dec->cur_pos_in_samples,
2080 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf))
2083 /* increment sample counters */
2084 dec->cur_pos_in_samples += num_samples;
2085 dec->num_decoded_samples += num_samples;
2087 /* the decode() call might have set a new output format -> renegotiate
2088 * before sending the new buffer downstream */
2089 if (G_UNLIKELY (dec->output_format_changed ||
2090 (GST_AUDIO_INFO_IS_VALID (&(dec->output_audio_info))
2091 && gst_pad_check_reconfigure (dec->srcpad))
2093 if (!gst_nonstream_audio_decoder_negotiate (dec)) {
2094 gst_buffer_unref (outbuf);
2095 GST_LOG_OBJECT (dec, "could not push output buffer: negotiation failed");
2100 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
2102 /* push new samples downstream
2103 * no need to unref buffer - gst_pad_push() does it in
2104 * all cases (success and failure) */
2105 flow = gst_pad_push (dec->srcpad, outbuf);
2110 case GST_FLOW_FLUSHING:
2111 GST_LOG_OBJECT (dec, "pipeline is being flushed - pausing task");
2114 case GST_FLOW_NOT_NEGOTIATED:
2115 if (gst_pad_needs_reconfigure (dec->srcpad)) {
2116 GST_DEBUG_OBJECT (dec, "trying to renegotiate");
2119 /* fallthrough to default */
2122 GST_ELEMENT_ERROR (dec, STREAM, FAILED, ("Internal data flow error."),
2123 ("streaming task paused, reason %s (%d)", gst_flow_get_name (flow),
2130 GST_INFO_OBJECT (dec, "pausing task");
2131 /* NOT using stop_task here, since that would cause a deadlock.
2132 * See the gst_pad_stop_task() documentation for details. */
2133 gst_pad_pause_task (dec->srcpad);
2136 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
2142 get_seek_type_name (GstSeekType seek_type)
2144 switch (seek_type) {
2145 case GST_SEEK_TYPE_NONE:
2147 case GST_SEEK_TYPE_SET:
2149 case GST_SEEK_TYPE_END:
2160 * gst_nonstream_audio_decoder_handle_loop:
2161 * @dec: a #GstNonstreamAudioDecoder
2162 * @new_position New position the next loop starts with
2164 * Reports that a loop has been completed and creates a new appropriate
2165 * segment for the next loop.
2167 * @new_position exists because a loop may not start at the beginning.
2169 * This function is only useful for subclasses which can be in the
2170 * GST_NONSTREAM_AUDIO_OUTPUT_MODE_LOOPING output mode, since in the
2171 * GST_NONSTREAM_AUDIO_OUTPUT_MODE_STEADY output mode, this function
2172 * does nothing. See #GstNonstreamAudioOutputMode for more details.
2174 * The subclass calls this during playback when it loops. It produces
2175 * a new segment with updated base time and internal time values, to allow
2176 * for seamless looping. It does *not* check the number of elapsed loops;
2177 * this is up the subclass.
2179 * Note that if this function is called, then it must be done after the
2180 * last samples of the loop have been decoded and pushed downstream.
2182 * This function must be called with the decoder mutex lock held, since it
2183 * is typically called from within @decode (which in turn are called with
2184 * the lock already held).
2187 gst_nonstream_audio_decoder_handle_loop (GstNonstreamAudioDecoder * dec,
2188 GstClockTime new_position)
2190 if (dec->output_mode == GST_NONSTREAM_AUDIO_OUTPUT_MODE_STEADY) {
2191 /* handle_loop makes no sense with open-ended decoders */
2192 GST_WARNING_OBJECT (dec,
2193 "ignoring handle_loop() call, since the decoder output mode is \"steady\"");
2197 GST_DEBUG_OBJECT (dec,
2198 "handle_loop() invoked with new_position = %" GST_TIME_FORMAT,
2199 GST_TIME_ARGS (new_position));
2201 dec->discont = TRUE;
2203 gst_nonstream_audio_decoder_output_new_segment (dec, new_position);
2208 * gst_nonstream_audio_decoder_set_output_format:
2209 * @dec: a #GstNonstreamAudioDecoder
2210 * @audio_info: Valid audio info structure containing the output format
2212 * Sets the output caps by means of a GstAudioInfo structure.
2214 * This must be called latest in the first @decode call, to ensure src caps are
2215 * set before decoded samples are sent downstream. Typically, this is called
2216 * from inside @load_from_buffer or @load_from_custom.
2218 * This function must be called with the decoder mutex lock held, since it
2219 * is typically called from within the aforementioned vfuncs (which in turn
2220 * are called with the lock already held).
2222 * Returns: TRUE if setting the output format succeeded, FALSE otherwise
2225 gst_nonstream_audio_decoder_set_output_format (GstNonstreamAudioDecoder * dec,
2226 GstAudioInfo const *audio_info)
2229 GstCaps *templ_caps;
2231 gboolean res = TRUE;
2233 g_return_val_if_fail (GST_IS_NONSTREAM_AUDIO_DECODER (dec), FALSE);
2235 caps = gst_audio_info_to_caps (audio_info);
2237 GST_WARNING_OBJECT (dec, "Could not create caps out of audio info");
2241 templ_caps = gst_pad_get_pad_template_caps (dec->srcpad);
2242 caps_ok = gst_caps_is_subset (caps, templ_caps);
2245 dec->output_audio_info = *audio_info;
2246 dec->output_format_changed = TRUE;
2248 GST_INFO_OBJECT (dec, "setting output format to %" GST_PTR_FORMAT,
2251 GST_WARNING_OBJECT (dec,
2252 "requested output format %" GST_PTR_FORMAT " does not match template %"
2253 GST_PTR_FORMAT, (gpointer) caps, (gpointer) templ_caps);
2258 gst_caps_unref (caps);
2259 gst_caps_unref (templ_caps);
2266 * gst_nonstream_audio_decoder_set_output_format_simple:
2267 * @dec: a #GstNonstreamAudioDecoder
2268 * @sample_rate: Output sample rate to use, in Hz
2269 * @sample_format: Output sample format to use
2270 * @num_channels: Number of output channels to use
2272 * Convenience function; sets the output caps by means of common parameters.
2274 * Internally, this fills a GstAudioInfo structure and calls
2275 * gst_nonstream_audio_decoder_set_output_format().
2277 * Returns: TRUE if setting the output format succeeded, FALSE otherwise
2280 gst_nonstream_audio_decoder_set_output_format_simple (GstNonstreamAudioDecoder *
2281 dec, guint sample_rate, GstAudioFormat sample_format, guint num_channels)
2283 GstAudioInfo output_audio_info;
2285 gst_audio_info_init (&output_audio_info);
2287 gst_audio_info_set_format (&output_audio_info,
2288 sample_format, sample_rate, num_channels, NULL);
2290 return gst_nonstream_audio_decoder_set_output_format (dec,
2291 &output_audio_info);
2296 * gst_nonstream_audio_decoder_get_downstream_info:
2297 * @dec: a #GstNonstreamAudioDecoder
2298 * @format: #GstAudioFormat value to fill with a sample format
2299 * @sample_rate: Integer to fill with a sample rate
2300 * @num_channels: Integer to fill with a channel count
2302 * Gets sample format, sample rate, channel count from the allowed srcpad caps.
2304 * This is useful for when the subclass wishes to adjust one or more output
2305 * parameters to whatever downstream is supporting. For example, the output
2306 * sample rate is often a freely adjustable value in module players.
2308 * This function tries to find a value inside the srcpad peer's caps for
2309 * @format, @sample_rate, @num_chnanels . Any of these can be NULL; they
2310 * (and the corresponding downstream caps) are then skipped while retrieving
2311 * information. Non-fixated caps are fixated first; the value closest to
2312 * their present value is then chosen. For example, if the variables pointed
2313 * to by the arguments are GST_AUDIO_FORMAT_16, 48000 Hz, and 2 channels,
2314 * and the downstream caps are:
2316 * "audio/x-raw, format={S16LE,S32LE}, rate=[1,32000], channels=[1,MAX]"
2318 * Then @format and @channels stay the same, while @sample_rate is set to 32000 Hz.
2319 * This way, the initial values the the variables pointed to by the arguments
2320 * are set to can be used as default output values. Note that if no downstream
2321 * caps can be retrieved, then this function does nothing, therefore it is
2322 * necessary to ensure that @format, @sample_rate, and @channels have valid
2325 * Decoder lock is not held by this function, so it can be called from within
2326 * any of the class vfuncs.
2329 gst_nonstream_audio_decoder_get_downstream_info (GstNonstreamAudioDecoder * dec,
2330 GstAudioFormat * format, gint * sample_rate, gint * num_channels)
2332 GstCaps *allowed_srccaps;
2333 guint structure_nr, num_structures;
2334 gboolean ds_format_found = FALSE, ds_rate_found = FALSE, ds_channels_found =
2337 g_return_if_fail (GST_IS_NONSTREAM_AUDIO_DECODER (dec));
2339 allowed_srccaps = gst_pad_get_allowed_caps (dec->srcpad);
2340 if (allowed_srccaps == NULL) {
2341 GST_INFO_OBJECT (dec,
2342 "no downstream caps available - not modifying arguments");
2346 num_structures = gst_caps_get_size (allowed_srccaps);
2347 GST_DEBUG_OBJECT (dec, "%u structure(s) in downstream caps", num_structures);
2348 for (structure_nr = 0; structure_nr < num_structures; ++structure_nr) {
2349 GstStructure *structure;
2351 ds_format_found = FALSE;
2352 ds_rate_found = FALSE;
2353 ds_channels_found = FALSE;
2355 structure = gst_caps_get_structure (allowed_srccaps, structure_nr);
2357 /* If all formats which need to be queried are present in the structure,
2358 * check its contents */
2359 if (((format == NULL) || gst_structure_has_field (structure, "format")) &&
2360 ((sample_rate == NULL) || gst_structure_has_field (structure, "rate"))
2361 && ((num_channels == NULL)
2362 || gst_structure_has_field (structure, "channels"))) {
2363 gint fixated_sample_rate;
2364 gint fixated_num_channels;
2365 GstAudioFormat fixated_format = 0;
2366 GstStructure *fixated_str;
2367 gboolean passed = TRUE;
2369 /* Make a copy of the structure, since we need to modify
2370 * (fixate) values inside */
2371 fixated_str = gst_structure_copy (structure);
2373 /* Try to fixate and retrieve the sample format */
2374 if (passed && (format != NULL)) {
2377 if ((gst_structure_get_field_type (fixated_str,
2378 "format") == G_TYPE_STRING)
2379 || gst_structure_fixate_field_string (fixated_str, "format",
2380 gst_audio_format_to_string (*format))) {
2381 gchar const *fmt_str =
2382 gst_structure_get_string (fixated_str, "format");
2384 && ((fixated_format =
2385 gst_audio_format_from_string (fmt_str)) !=
2386 GST_AUDIO_FORMAT_UNKNOWN)) {
2387 GST_DEBUG_OBJECT (dec, "found fixated format: %s", fmt_str);
2388 ds_format_found = TRUE;
2394 /* Try to fixate and retrieve the sample rate */
2395 if (passed && (sample_rate != NULL)) {
2398 if ((gst_structure_get_field_type (fixated_str, "rate") == G_TYPE_INT)
2399 || gst_structure_fixate_field_nearest_int (fixated_str, "rate",
2401 if (gst_structure_get_int (fixated_str, "rate", &fixated_sample_rate)) {
2402 GST_DEBUG_OBJECT (dec, "found fixated sample rate: %d",
2403 fixated_sample_rate);
2404 ds_rate_found = TRUE;
2410 /* Try to fixate and retrieve the channel count */
2411 if (passed && (num_channels != NULL)) {
2414 if ((gst_structure_get_field_type (fixated_str,
2415 "channels") == G_TYPE_INT)
2416 || gst_structure_fixate_field_nearest_int (fixated_str, "channels",
2418 if (gst_structure_get_int (fixated_str, "channels",
2419 &fixated_num_channels)) {
2420 GST_DEBUG_OBJECT (dec, "found fixated channel count: %d",
2421 fixated_num_channels);
2422 ds_channels_found = TRUE;
2428 gst_structure_free (fixated_str);
2430 if (ds_format_found && ds_rate_found && ds_channels_found) {
2431 *format = fixated_format;
2432 *sample_rate = fixated_sample_rate;
2433 *num_channels = fixated_num_channels;
2439 gst_caps_unref (allowed_srccaps);
2441 if ((format != NULL) && !ds_format_found)
2442 GST_INFO_OBJECT (dec,
2443 "downstream did not specify format - using default (%s)",
2444 gst_audio_format_to_string (*format));
2445 if ((sample_rate != NULL) && !ds_rate_found)
2446 GST_INFO_OBJECT (dec,
2447 "downstream did not specify sample rate - using default (%d Hz)",
2449 if ((num_channels != NULL) && !ds_channels_found)
2450 GST_INFO_OBJECT (dec,
2451 "downstream did not specify number of channels - using default (%d channels)",
2457 * gst_nonstream_audio_decoder_allocate_output_buffer:
2458 * @dec: Decoder instance
2459 * @size: Size of the output buffer, in bytes
2461 * Allocates an output buffer with the internally configured buffer pool.
2463 * This function may only be called from within @load_from_buffer,
2464 * @load_from_custom, and @decode.
2466 * Returns: Newly allocated output buffer, or NULL if allocation failed
2469 gst_nonstream_audio_decoder_allocate_output_buffer (GstNonstreamAudioDecoder *
2472 if (G_UNLIKELY (dec->output_format_changed ||
2473 (GST_AUDIO_INFO_IS_VALID (&(dec->output_audio_info))
2474 && gst_pad_check_reconfigure (dec->srcpad))
2476 /* renegotiate if necessary, before allocating,
2477 * to make sure the right allocator and the right allocation
2478 * params are used */
2479 if (!gst_nonstream_audio_decoder_negotiate (dec)) {
2480 GST_ERROR_OBJECT (dec,
2481 "could not allocate output buffer because negotation failed");
2486 return gst_buffer_new_allocate (dec->allocator, size,
2487 &(dec->allocation_params));