1 /* GStreamer
2 * Copyright (C) <2017> Carlos Rafael Giani <dv at pseudoterminal dot org>
3 *
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.
8 *
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.
13 *
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.
18 */
19
20
21 /**
22 * SECTION:gstnonstreamaudiodecoder
23 * @short_description: Base class for decoding of non-streaming audio
24 * @see_also: #GstAudioDecoder
25 *
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
29 * samples").
30 *
31 * This sets it apart from GstAudioDecoder, which is a base class for
32 * streaming audio decoders.
33 *
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.
38 *
39 * Non-streaming audio formats tend to have some characteristics unknown to
40 * more "regular" bitstreams. These include subsongs and looping.
41 *
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.
52 *
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.
71 *
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.
75 *
76 * The base class operates as follows:
77 * * Unloaded mode
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
88 * output task.
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.
104 *
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
109 * TRUE.
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
120 * flag is cleared.
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
140 * in this function.
141 *
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):
144 *
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.
147 *
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.
151 *
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.
156 */
157
158 #ifdef HAVE_CONFIG_H
159 #include "config.h"
160 #endif
161
162 #include <stdio.h>
163 #include <gst/gst.h>
164 #include <gst/audio/audio.h>
165
166 #include "gstnonstreamaudiodecoder.h"
167
168
169 GST_DEBUG_CATEGORY (nonstream_audiodecoder_debug);
170 #define GST_CAT_DEFAULT nonstream_audiodecoder_debug
171
172
173 enum
174 {
175 PROP_0,
176 PROP_CURRENT_SUBSONG,
177 PROP_SUBSONG_MODE,
178 PROP_NUM_LOOPS,
179 PROP_OUTPUT_MODE
180 };
181
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
187
188
189
190
191 static GstElementClass *gst_nonstream_audio_decoder_parent_class = NULL;
192
193 static void
194 gst_nonstream_audio_decoder_class_init (GstNonstreamAudioDecoderClass * klass);
195 static void gst_nonstream_audio_decoder_init (GstNonstreamAudioDecoder * dec,
196 GstNonstreamAudioDecoderClass * klass);
197
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);
203
204 static GstStateChangeReturn gst_nonstream_audio_decoder_change_state (GstElement
205 * element, GstStateChange transition);
206
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);
213
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);
218
219 static void
220 gst_nonstream_audio_decoder_set_initial_state (GstNonstreamAudioDecoder * dec);
221 static void gst_nonstream_audio_decoder_cleanup_state (GstNonstreamAudioDecoder
222 * dec);
223
224 static gboolean gst_nonstream_audio_decoder_negotiate (GstNonstreamAudioDecoder
225 * dec);
226
227 static gboolean
228 gst_nonstream_audio_decoder_negotiate_default (GstNonstreamAudioDecoder * dec);
229 static gboolean
230 gst_nonstream_audio_decoder_decide_allocation_default (GstNonstreamAudioDecoder
231 * dec, GstQuery * query);
232 static gboolean
233 gst_nonstream_audio_decoder_propose_allocation_default (GstNonstreamAudioDecoder
234 * dec, GstQuery * query);
235
236 static gboolean
237 gst_nonstream_audio_decoder_get_upstream_size (GstNonstreamAudioDecoder * dec,
238 gint64 * length);
239 static gboolean
240 gst_nonstream_audio_decoder_load_from_buffer (GstNonstreamAudioDecoder * dec,
241 GstBuffer * buffer);
242 static gboolean
243 gst_nonstream_audio_decoder_load_from_custom (GstNonstreamAudioDecoder * dec);
244 static gboolean
245 gst_nonstream_audio_decoder_finish_load (GstNonstreamAudioDecoder * dec,
246 gboolean load_ok, GstClockTime initial_position,
247 gboolean send_stream_start);
248
249 static gboolean gst_nonstream_audio_decoder_start_task (GstNonstreamAudioDecoder
250 * dec);
251 static gboolean gst_nonstream_audio_decoder_stop_task (GstNonstreamAudioDecoder
252 * dec);
253
254 static gboolean
255 gst_nonstream_audio_decoder_switch_to_subsong (GstNonstreamAudioDecoder * dec,
256 guint new_subsong, guint32 const *seqnum);
257
258 static void gst_nonstream_audio_decoder_update_toc (GstNonstreamAudioDecoder *
259 dec, GstNonstreamAudioDecoderClass * klass);
260 static void
261 gst_nonstream_audio_decoder_update_subsong_duration (GstNonstreamAudioDecoder *
262 dec, GstClockTime duration);
263 static void
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);
268
269 static GstTagList
270 * gst_nonstream_audio_decoder_add_main_tags (GstNonstreamAudioDecoder * dec,
271 GstTagList * tags);
272
273 static void gst_nonstream_audio_decoder_output_task (GstNonstreamAudioDecoder *
274 dec);
275
276 static char const *get_seek_type_name (GstSeekType seek_type);
277
278
279
280
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())
283
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())
286
287
288 static GType
gst_nonstream_audio_decoder_output_mode_get_type(void)289 gst_nonstream_audio_decoder_output_mode_get_type (void)
290 {
291 static GType gst_nonstream_audio_decoder_output_mode_type = 0;
292
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"},
297 {0, NULL, NULL},
298 };
299
300 gst_nonstream_audio_decoder_output_mode_type =
301 g_enum_register_static ("GstNonstreamAudioOutputMode",
302 output_mode_values);
303 }
304
305 return gst_nonstream_audio_decoder_output_mode_type;
306 }
307
308
309 static GType
gst_nonstream_audio_decoder_subsong_mode_get_type(void)310 gst_nonstream_audio_decoder_subsong_mode_get_type (void)
311 {
312 static GType gst_nonstream_audio_decoder_subsong_mode_type = 0;
313
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",
317 "single"},
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"},
321 {0, NULL, NULL},
322 };
323
324 gst_nonstream_audio_decoder_subsong_mode_type =
325 g_enum_register_static ("GstNonstreamAudioSubsongMode",
326 subsong_mode_values);
327 }
328
329 return gst_nonstream_audio_decoder_subsong_mode_type;
330 }
331
332
333
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 */
337
338
339 GType
gst_nonstream_audio_decoder_get_type(void)340 gst_nonstream_audio_decoder_get_type (void)
341 {
342 static gsize nonstream_audio_decoder_type = 0;
343
344 if (g_once_init_enter (&nonstream_audio_decoder_type)) {
345 GType type_;
346 static const GTypeInfo nonstream_audio_decoder_info = {
347 sizeof (GstNonstreamAudioDecoderClass),
348 NULL,
349 NULL,
350 (GClassInitFunc) gst_nonstream_audio_decoder_class_init,
351 NULL,
352 NULL,
353 sizeof (GstNonstreamAudioDecoder),
354 0,
355 (GInstanceInitFunc) gst_nonstream_audio_decoder_init,
356 NULL
357 };
358
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_);
363 }
364
365 return nonstream_audio_decoder_type;
366 }
367
368
369
370
371 static void
gst_nonstream_audio_decoder_class_init(GstNonstreamAudioDecoderClass * klass)372 gst_nonstream_audio_decoder_class_init (GstNonstreamAudioDecoderClass * klass)
373 {
374 GObjectClass *object_class;
375 GstElementClass *element_class;
376
377 object_class = G_OBJECT_CLASS (klass);
378 element_class = GST_ELEMENT_CLASS (klass);
379
380 gst_nonstream_audio_decoder_parent_class = g_type_class_peek_parent (klass);
381
382 GST_DEBUG_CATEGORY_INIT (nonstream_audiodecoder_debug,
383 "nonstreamaudiodecoder", 0, "nonstream audio decoder base class");
384
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);
393
394 klass->seek = NULL;
395 klass->tell = NULL;
396
397 klass->load_from_buffer = NULL;
398 klass->load_from_custom = NULL;
399
400 klass->get_main_tags = NULL;
401
402 klass->get_current_subsong = NULL;
403 klass->set_current_subsong = NULL;
404
405 klass->get_num_subsongs = NULL;
406 klass->get_subsong_duration = NULL;
407 klass->get_subsong_tags = NULL;
408 klass->set_subsong_mode = NULL;
409
410 klass->set_num_loops = NULL;
411 klass->get_num_loops = NULL;
412
413 klass->decode = NULL;
414
415 klass->negotiate =
416 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_negotiate_default);
417
418 klass->decide_allocation =
419 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_decide_allocation_default);
420 klass->propose_allocation =
421 GST_DEBUG_FUNCPTR
422 (gst_nonstream_audio_decoder_propose_allocation_default);
423
424 klass->loads_from_sinkpad = TRUE;
425
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",
431 0, G_MAXUINT,
432 DEFAULT_CURRENT_SUBSONG, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
433 );
434
435 g_object_class_install_property (object_class,
436 PROP_SUBSONG_MODE,
437 g_param_spec_enum ("subsong-mode",
438 "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)
442 );
443
444 g_object_class_install_property (object_class,
445 PROP_NUM_LOOPS,
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)",
449 -1, G_MAXINT,
450 DEFAULT_NUM_LOOPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
451 );
452
453 g_object_class_install_property (object_class,
454 PROP_OUTPUT_MODE,
455 g_param_spec_enum ("output-mode",
456 "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)
460 );
461 }
462
463
464 static void
gst_nonstream_audio_decoder_init(GstNonstreamAudioDecoder * dec,GstNonstreamAudioDecoderClass * klass)465 gst_nonstream_audio_decoder_init (GstNonstreamAudioDecoder * dec,
466 GstNonstreamAudioDecoderClass * klass)
467 {
468 GstPadTemplate *pad_template;
469
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;
477
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);
481
482 dec->input_data_adapter = gst_adapter_new ();
483 g_mutex_init (&(dec->mutex));
484
485 {
486 /* set up src pad */
487
488 pad_template =
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 */
491
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);
498 }
499
500 if (klass->loads_from_sinkpad) {
501 /* set up sink pad if this class loads from a sinkpad */
502
503 pad_template =
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 */
506
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);
515 }
516 }
517
518
519
520
521 static void
gst_nonstream_audio_decoder_finalize(GObject * object)522 gst_nonstream_audio_decoder_finalize (GObject * object)
523 {
524 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (object);
525
526 g_mutex_clear (&(dec->mutex));
527 g_object_unref (G_OBJECT (dec->input_data_adapter));
528
529 G_OBJECT_CLASS (gst_nonstream_audio_decoder_parent_class)->finalize (object);
530 }
531
532
533 static void
gst_nonstream_audio_decoder_set_property(GObject * object,guint prop_id,GValue const * value,GParamSpec * pspec)534 gst_nonstream_audio_decoder_set_property (GObject * object, guint prop_id,
535 GValue const *value, GParamSpec * pspec)
536 {
537 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (object);
538 GstNonstreamAudioDecoderClass *klass =
539 GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
540
541 switch (prop_id) {
542 case PROP_OUTPUT_MODE:
543 {
544 GstNonstreamAudioOutputMode new_output_mode;
545 new_output_mode = g_value_get_enum (value);
546
547 g_assert (klass->get_supported_output_modes);
548
549 if ((klass->get_supported_output_modes (dec) & (1u << new_output_mode)) ==
550 0) {
551 GST_WARNING_OBJECT (dec,
552 "could not set output mode to %s (not supported by subclass)",
553 (new_output_mode ==
554 GST_NONSTREAM_AUDIO_OUTPUT_MODE_STEADY) ? "steady" : "looping");
555 break;
556 }
557
558 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
559 if (new_output_mode != dec->output_mode) {
560 gboolean proceed = TRUE;
561
562 if (dec->loaded_mode) {
563 GstClockTime cur_position;
564
565 if (klass->set_output_mode != NULL) {
566 if (klass->set_output_mode (dec, new_output_mode, &cur_position))
567 proceed = TRUE;
568 else {
569 proceed = FALSE;
570 GST_WARNING_OBJECT (dec, "switching to new output mode failed");
571 }
572 } else {
573 GST_DEBUG_OBJECT (dec,
574 "cannot call set_output_mode, since it is NULL");
575 proceed = FALSE;
576 }
577
578 if (proceed) {
579 gst_nonstream_audio_decoder_output_new_segment (dec, cur_position);
580 dec->output_mode = new_output_mode;
581 }
582 }
583
584 if (proceed) {
585 /* store output mode in case the property is set before the media got loaded */
586 dec->output_mode = new_output_mode;
587 }
588 }
589 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
590
591 break;
592 }
593
594 case PROP_CURRENT_SUBSONG:
595 {
596 guint new_subsong = g_value_get_uint (value);
597 gst_nonstream_audio_decoder_switch_to_subsong (dec, new_subsong, NULL);
598
599 break;
600 }
601
602 case PROP_SUBSONG_MODE:
603 {
604 GstNonstreamAudioSubsongMode new_subsong_mode = g_value_get_enum (value);
605
606 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
607 if (new_subsong_mode != dec->subsong_mode) {
608 gboolean proceed = TRUE;
609
610 if (dec->loaded_mode) {
611 GstClockTime cur_position;
612
613 if (klass->set_subsong_mode != NULL) {
614 if (klass->set_subsong_mode (dec, new_subsong_mode, &cur_position))
615 proceed = TRUE;
616 else {
617 proceed = FALSE;
618 GST_WARNING_OBJECT (dec, "switching to new subsong mode failed");
619 }
620 } else {
621 GST_DEBUG_OBJECT (dec,
622 "cannot call set_subsong_mode, since it is NULL");
623 proceed = FALSE;
624 }
625
626 if (proceed) {
627 if (GST_CLOCK_TIME_IS_VALID (cur_position))
628 gst_nonstream_audio_decoder_output_new_segment (dec,
629 cur_position);
630 dec->subsong_mode = new_subsong_mode;
631 }
632 }
633
634 if (proceed) {
635 /* store subsong mode in case the property is set before the media got loaded */
636 dec->subsong_mode = new_subsong_mode;
637 }
638 }
639 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
640
641 break;
642 }
643
644 case PROP_NUM_LOOPS:
645 {
646 gint new_num_loops = g_value_get_int (value);
647
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",
654 new_num_loops);
655 } else
656 GST_DEBUG_OBJECT (dec,
657 "cannot call set_num_loops, since it is NULL");
658 }
659
660 /* store number of loops in case the property is set before the media got loaded */
661 dec->num_loops = new_num_loops;
662 }
663 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
664
665 break;
666 }
667
668 default:
669 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
670 break;
671 }
672 }
673
674
675 static void
gst_nonstream_audio_decoder_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)676 gst_nonstream_audio_decoder_get_property (GObject * object, guint prop_id,
677 GValue * value, GParamSpec * pspec)
678 {
679 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (object);
680
681 switch (prop_id) {
682 case PROP_OUTPUT_MODE:
683 {
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);
687 break;
688 }
689
690 case PROP_CURRENT_SUBSONG:
691 {
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);
695 break;
696 }
697
698 case PROP_SUBSONG_MODE:
699 {
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);
703 break;
704 }
705
706 case PROP_NUM_LOOPS:
707 {
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);
711 break;
712 }
713
714 default:
715 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
716 break;
717 }
718 }
719
720
721
722 static GstStateChangeReturn
gst_nonstream_audio_decoder_change_state(GstElement * element,GstStateChange transition)723 gst_nonstream_audio_decoder_change_state (GstElement * element,
724 GstStateChange transition)
725 {
726 GstStateChangeReturn ret;
727
728 ret =
729 GST_ELEMENT_CLASS (gst_nonstream_audio_decoder_parent_class)->change_state
730 (element, transition);
731 if (ret == GST_STATE_CHANGE_FAILURE)
732 return ret;
733
734 switch (transition) {
735 case GST_STATE_CHANGE_READY_TO_PAUSED:
736 {
737
738 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (element);
739 GstNonstreamAudioDecoderClass *klass =
740 GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
741
742 /* For decoders that load with some custom method,
743 * this is now the time to load
744 *
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
750 * a special case) */
751 if (!(klass->loads_from_sinkpad) && !(dec->loaded_mode)) {
752 gboolean ret;
753
754 /* load_from_custom is required if loads_from_sinkpad is FALSE */
755 g_assert (klass->load_from_custom != NULL);
756
757 ret = gst_nonstream_audio_decoder_load_from_custom (dec);
758
759 if (!ret) {
760 GST_ERROR_OBJECT (dec, "loading from custom source failed");
761 return GST_STATE_CHANGE_FAILURE;
762 }
763
764 if (!gst_nonstream_audio_decoder_start_task (dec))
765 return GST_STATE_CHANGE_FAILURE;
766
767 }
768
769 break;
770 }
771
772 case GST_STATE_CHANGE_PAUSED_TO_READY:
773 {
774 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (element);
775 if (!gst_nonstream_audio_decoder_stop_task (dec))
776 return GST_STATE_CHANGE_FAILURE;
777 break;
778 }
779
780 case GST_STATE_CHANGE_READY_TO_NULL:
781 {
782 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (element);
783
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);
787 break;
788 }
789
790 default:
791 break;
792 }
793
794 return ret;
795 }
796
797
798
799 static gboolean
gst_nonstream_audio_decoder_sink_event(GstPad * pad,GstObject * parent,GstEvent * event)800 gst_nonstream_audio_decoder_sink_event (GstPad * pad, GstObject * parent,
801 GstEvent * event)
802 {
803 gboolean res = FALSE;
804 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (parent);
805
806 switch (GST_EVENT_TYPE (event)) {
807 case GST_EVENT_SEGMENT:
808 {
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);
812 res = TRUE;
813 break;
814 }
815
816 case GST_EVENT_EOS:
817 {
818 gsize avail_size;
819 GstBuffer *adapter_buffer;
820
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 */
824
825 GST_DEBUG_OBJECT (dec,
826 "EOS received after media was loaded -> ignoring");
827 res = TRUE;
828 } else {
829 /* take all data in the input data adapter,
830 * and try to load the media from it */
831
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"));
836 return FALSE;
837 }
838
839 adapter_buffer =
840 gst_adapter_take_buffer (dec->input_data_adapter, avail_size);
841
842 if (!gst_nonstream_audio_decoder_load_from_buffer (dec, adapter_buffer)) {
843 return FALSE;
844 }
845
846 res = gst_nonstream_audio_decoder_start_task (dec);
847 }
848
849 break;
850 }
851
852 default:
853 res = gst_pad_event_default (pad, parent, event);
854 }
855
856 return res;
857 }
858
859
860 static gboolean
gst_nonstream_audio_decoder_sink_query(GstPad * pad,GstObject * parent,GstQuery * query)861 gst_nonstream_audio_decoder_sink_query (GstPad * pad, GstObject * parent,
862 GstQuery * query)
863 {
864 gboolean res = FALSE;
865 GstNonstreamAudioDecoder *dec;
866 GstNonstreamAudioDecoderClass *klass;
867
868 dec = GST_NONSTREAM_AUDIO_DECODER (parent);
869 klass = GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
870
871 switch (GST_QUERY_TYPE (query)) {
872 case GST_QUERY_ALLOCATION:
873 {
874 if (klass->propose_allocation != NULL)
875 res = klass->propose_allocation (dec, query);
876
877 break;
878 }
879
880 default:
881 res = gst_pad_query_default (pad, parent, query);
882 }
883
884 return res;
885 }
886
887
888 static GstFlowReturn
gst_nonstream_audio_decoder_chain(G_GNUC_UNUSED GstPad * pad,GstObject * parent,GstBuffer * buffer)889 gst_nonstream_audio_decoder_chain (G_GNUC_UNUSED GstPad * pad,
890 GstObject * parent, GstBuffer * buffer)
891 {
892 GstFlowReturn flow_ret = GST_FLOW_OK;
893 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (parent);
894
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;
905 }
906 }
907
908 if (dec->loaded_mode) {
909 /* media is already loaded - discard any incoming
910 * buffers, since they are not needed */
911
912 GST_DEBUG_OBJECT (dec, "received data after media was loaded - ignoring");
913
914 gst_buffer_unref (buffer);
915 } else {
916 /* accumulate data until end-of-stream or the upstream
917 * size is reached, then load media and commence playback */
918
919 gint64 avail_size;
920
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);
926
927 if (gst_nonstream_audio_decoder_load_from_buffer (dec, adapter_buffer))
928 flow_ret =
929 gst_nonstream_audio_decoder_start_task (dec) ? GST_FLOW_OK :
930 GST_FLOW_ERROR;
931 else
932 flow_ret = GST_FLOW_ERROR;
933 }
934 }
935
936 return flow_ret;
937 }
938
939
940
941 static gboolean
gst_nonstream_audio_decoder_src_event(GstPad * pad,GstObject * parent,GstEvent * event)942 gst_nonstream_audio_decoder_src_event (GstPad * pad, GstObject * parent,
943 GstEvent * event)
944 {
945 gboolean res = FALSE;
946 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (parent);
947
948 switch (GST_EVENT_TYPE (event)) {
949 case GST_EVENT_SEEK:
950 {
951 res = gst_nonstream_audio_decoder_do_seek (dec, event);
952 break;
953 }
954
955 case GST_EVENT_TOC_SELECT:
956 {
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. */
961
962 gchar *uid = NULL;
963 guint subsong_idx = 0;
964 guint32 seqnum;
965
966 gst_event_parse_toc_select (event, &uid);
967
968 if ((uid != NULL)
969 && (sscanf (uid, "nonstream-subsong-%05u", &subsong_idx) == 1)) {
970 seqnum = gst_event_get_seqnum (event);
971
972 GST_DEBUG_OBJECT (dec,
973 "received TOC select event (sequence number %" G_GUINT32_FORMAT
974 "), switching to subsong %u", seqnum, subsong_idx);
975
976 gst_nonstream_audio_decoder_switch_to_subsong (dec, subsong_idx,
977 &seqnum);
978 }
979
980 g_free (uid);
981
982 res = TRUE;
983
984 break;
985 }
986
987 default:
988 res = gst_pad_event_default (pad, parent, event);
989 }
990
991 return res;
992 }
993
994
995 static gboolean
gst_nonstream_audio_decoder_src_query(GstPad * pad,GstObject * parent,GstQuery * query)996 gst_nonstream_audio_decoder_src_query (GstPad * pad, GstObject * parent,
997 GstQuery * query)
998 {
999 gboolean res = FALSE;
1000 GstNonstreamAudioDecoder *dec;
1001 GstNonstreamAudioDecoderClass *klass;
1002
1003 dec = GST_NONSTREAM_AUDIO_DECODER (parent);
1004 klass = GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
1005
1006 switch (GST_QUERY_TYPE (query)) {
1007 case GST_QUERY_DURATION:
1008 {
1009 GstFormat format;
1010 GST_TRACE_OBJECT (parent, "duration query");
1011
1012 if (!(dec->loaded_mode)) {
1013 GST_DEBUG_OBJECT (parent,
1014 "cannot respond to duration query: nothing is loaded yet");
1015 break;
1016 }
1017
1018 GST_TRACE_OBJECT (parent, "parsing duration query");
1019 gst_query_parse_duration (query, &format, NULL);
1020
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);
1028 res = TRUE;
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);
1037
1038 break;
1039 }
1040
1041 case GST_QUERY_POSITION:
1042 {
1043 GstFormat format;
1044 if (!(dec->loaded_mode)) {
1045 GST_DEBUG_OBJECT (parent,
1046 "cannot respond to position query: nothing is loaded yet");
1047 break;
1048 }
1049
1050 if (klass->tell == NULL) {
1051 GST_DEBUG_OBJECT (parent,
1052 "cannot respond to position query: subclass does not have tell() function defined");
1053 break;
1054 }
1055
1056 gst_query_parse_position (query, &format, NULL);
1057 if (format == GST_FORMAT_TIME) {
1058 GstClockTime pos;
1059
1060 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1061 pos = klass->tell (dec);
1062 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1063
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);
1068 res = TRUE;
1069 } else {
1070 GST_DEBUG_OBJECT (parent,
1071 "position query received with unsupported format %s -> not reporting anything",
1072 gst_format_get_name (format));
1073 }
1074
1075 break;
1076 }
1077
1078 case GST_QUERY_SEEKING:
1079 {
1080 GstFormat fmt;
1081 GstClockTime duration;
1082
1083 if (!dec->loaded_mode) {
1084 GST_DEBUG_OBJECT (parent,
1085 "cannot respond to seeking query: nothing is loaded yet");
1086 break;
1087 }
1088
1089 if (klass->seek == NULL) {
1090 GST_DEBUG_OBJECT (parent,
1091 "cannot respond to seeking query: subclass does not have seek() function defined");
1092 break;
1093 }
1094
1095 gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
1096
1097 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1098 duration = dec->subsong_duration;
1099 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1100
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);
1105 res = TRUE;
1106 } else {
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);
1111 res = TRUE;
1112 }
1113
1114 break;
1115 }
1116
1117 default:
1118 res = gst_pad_query_default (pad, parent, query);
1119 }
1120
1121 return res;
1122 }
1123
1124
1125
1126 static void
gst_nonstream_audio_decoder_set_initial_state(GstNonstreamAudioDecoder * dec)1127 gst_nonstream_audio_decoder_set_initial_state (GstNonstreamAudioDecoder * dec)
1128 {
1129 dec->upstream_size = -1;
1130 dec->loaded_mode = FALSE;
1131
1132 dec->subsong_duration = GST_CLOCK_TIME_NONE;
1133
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;
1140
1141 dec->toc = NULL;
1142
1143 dec->allocator = NULL;
1144 }
1145
1146
1147 static void
gst_nonstream_audio_decoder_cleanup_state(GstNonstreamAudioDecoder * dec)1148 gst_nonstream_audio_decoder_cleanup_state (GstNonstreamAudioDecoder * dec)
1149 {
1150 gst_adapter_clear (dec->input_data_adapter);
1151
1152 if (dec->allocator != NULL) {
1153 gst_object_unref (dec->allocator);
1154 dec->allocator = NULL;
1155 }
1156
1157 if (dec->toc != NULL) {
1158 gst_toc_unref (dec->toc);
1159 dec->toc = NULL;
1160 }
1161
1162 gst_nonstream_audio_decoder_set_initial_state (dec);
1163 }
1164
1165
1166 static gboolean
gst_nonstream_audio_decoder_negotiate(GstNonstreamAudioDecoder * dec)1167 gst_nonstream_audio_decoder_negotiate (GstNonstreamAudioDecoder * dec)
1168 {
1169 /* must be called with lock */
1170
1171 GstNonstreamAudioDecoderClass *klass;
1172 gboolean res = TRUE;
1173
1174 klass = GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
1175
1176 /* protected by a mutex, since the allocator might currently be in use */
1177 if (klass->negotiate != NULL)
1178 res = klass->negotiate (dec);
1179
1180 return res;
1181 }
1182
1183
1184 static gboolean
gst_nonstream_audio_decoder_negotiate_default(GstNonstreamAudioDecoder * dec)1185 gst_nonstream_audio_decoder_negotiate_default (GstNonstreamAudioDecoder * dec)
1186 {
1187 /* mutex is locked when this is called */
1188
1189 GstCaps *caps;
1190 GstNonstreamAudioDecoderClass *klass;
1191 gboolean res = TRUE;
1192 GstQuery *query = NULL;
1193 GstAllocator *allocator;
1194 GstAllocationParams allocation_params;
1195
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)),
1198 FALSE);
1199
1200 klass = GST_NONSTREAM_AUDIO_DECODER_CLASS (G_OBJECT_GET_CLASS (dec));
1201
1202 caps = gst_audio_info_to_caps (&(dec->output_audio_info));
1203
1204 GST_DEBUG_OBJECT (dec, "setting src caps %" GST_PTR_FORMAT, (gpointer) caps);
1205
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);
1209
1210 if (!res) {
1211 GST_WARNING_OBJECT (dec, "could not push new caps event downstream");
1212 goto done;
1213 }
1214
1215 GST_TRACE_OBJECT (dec, "src caps set");
1216
1217 dec->output_format_changed = FALSE;
1218
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");
1222 }
1223
1224 g_assert (klass->decide_allocation != NULL);
1225 res = klass->decide_allocation (dec, query);
1226
1227 GST_DEBUG_OBJECT (dec, "ALLOCATION (%d) params: %" GST_PTR_FORMAT, res,
1228 (gpointer) query);
1229
1230 if (!res)
1231 goto no_decide_allocation;
1232
1233 /* we got configuration from our peer or the decide_allocation method,
1234 * parse them */
1235 if (gst_query_get_n_allocation_params (query) > 0) {
1236 gst_query_parse_nth_allocation_param (query, 0, &allocator,
1237 &allocation_params);
1238 } else {
1239 allocator = NULL;
1240 gst_allocation_params_init (&allocation_params);
1241 }
1242
1243 if (dec->allocator != NULL)
1244 gst_object_unref (dec->allocator);
1245 dec->allocator = allocator;
1246 dec->allocation_params = allocation_params;
1247
1248 done:
1249 if (query != NULL)
1250 gst_query_unref (query);
1251 gst_caps_unref (caps);
1252
1253 return res;
1254
1255 no_decide_allocation:
1256 {
1257 GST_WARNING_OBJECT (dec, "subclass failed to decide allocation");
1258 goto done;
1259 }
1260 }
1261
1262
1263 static gboolean
gst_nonstream_audio_decoder_decide_allocation_default(G_GNUC_UNUSED GstNonstreamAudioDecoder * dec,GstQuery * query)1264 gst_nonstream_audio_decoder_decide_allocation_default (G_GNUC_UNUSED
1265 GstNonstreamAudioDecoder * dec, GstQuery * query)
1266 {
1267 GstAllocator *allocator = NULL;
1268 GstAllocationParams params;
1269 gboolean update_allocator;
1270
1271 /* we got configuration from our peer or the decide_allocation method,
1272 * parse them */
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;
1277 } else {
1278 allocator = NULL;
1279 gst_allocation_params_init (¶ms);
1280 update_allocator = FALSE;
1281 }
1282
1283 if (update_allocator)
1284 gst_query_set_nth_allocation_param (query, 0, allocator, ¶ms);
1285 else
1286 gst_query_add_allocation_param (query, allocator, ¶ms);
1287
1288 if (allocator)
1289 gst_object_unref (allocator);
1290
1291 return TRUE;
1292 }
1293
1294
1295 static gboolean
gst_nonstream_audio_decoder_propose_allocation_default(G_GNUC_UNUSED GstNonstreamAudioDecoder * dec,G_GNUC_UNUSED GstQuery * query)1296 gst_nonstream_audio_decoder_propose_allocation_default (G_GNUC_UNUSED
1297 GstNonstreamAudioDecoder * dec, G_GNUC_UNUSED GstQuery * query)
1298 {
1299 return TRUE;
1300 }
1301
1302
1303 static gboolean
gst_nonstream_audio_decoder_get_upstream_size(GstNonstreamAudioDecoder * dec,gint64 * length)1304 gst_nonstream_audio_decoder_get_upstream_size (GstNonstreamAudioDecoder * dec,
1305 gint64 * length)
1306 {
1307 return gst_pad_peer_query_duration (dec->sinkpad, GST_FORMAT_BYTES, length)
1308 && (*length >= 0);
1309 }
1310
1311
1312 static gboolean
gst_nonstream_audio_decoder_load_from_buffer(GstNonstreamAudioDecoder * dec,GstBuffer * buffer)1313 gst_nonstream_audio_decoder_load_from_buffer (GstNonstreamAudioDecoder * dec,
1314 GstBuffer * buffer)
1315 {
1316 gboolean load_ok;
1317 GstClockTime initial_position;
1318 GstNonstreamAudioDecoderClass *klass;
1319 gboolean ret;
1320
1321 klass = GST_NONSTREAM_AUDIO_DECODER_CLASS (G_OBJECT_GET_CLASS (dec));
1322 g_assert (klass->load_from_buffer != NULL);
1323
1324 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1325
1326 GST_LOG_OBJECT (dec, "read %" G_GSIZE_FORMAT " bytes from upstream",
1327 gst_buffer_get_size (buffer));
1328
1329 initial_position = 0;
1330 load_ok =
1331 klass->load_from_buffer (dec, buffer, dec->current_subsong,
1332 dec->subsong_mode, &initial_position, &(dec->output_mode),
1333 &(dec->num_loops));
1334 gst_buffer_unref (buffer);
1335
1336 ret =
1337 gst_nonstream_audio_decoder_finish_load (dec, load_ok, initial_position,
1338 FALSE);
1339
1340 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1341
1342 return ret;
1343 }
1344
1345
1346 static gboolean
gst_nonstream_audio_decoder_load_from_custom(GstNonstreamAudioDecoder * dec)1347 gst_nonstream_audio_decoder_load_from_custom (GstNonstreamAudioDecoder * dec)
1348 {
1349 gboolean load_ok;
1350 GstClockTime initial_position;
1351 GstNonstreamAudioDecoderClass *klass;
1352 gboolean ret;
1353
1354 klass = GST_NONSTREAM_AUDIO_DECODER_CLASS (G_OBJECT_GET_CLASS (dec));
1355 g_assert (klass->load_from_custom != NULL);
1356
1357 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1358
1359 GST_LOG_OBJECT (dec,
1360 "reading song from custom source defined by derived class");
1361
1362 initial_position = 0;
1363 load_ok =
1364 klass->load_from_custom (dec, dec->current_subsong, dec->subsong_mode,
1365 &initial_position, &(dec->output_mode), &(dec->num_loops));
1366
1367 ret =
1368 gst_nonstream_audio_decoder_finish_load (dec, load_ok, initial_position,
1369 TRUE);
1370
1371 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1372
1373 return ret;
1374 }
1375
1376
1377 static gboolean
gst_nonstream_audio_decoder_finish_load(GstNonstreamAudioDecoder * dec,gboolean load_ok,GstClockTime initial_position,gboolean send_stream_start)1378 gst_nonstream_audio_decoder_finish_load (GstNonstreamAudioDecoder * dec,
1379 gboolean load_ok, GstClockTime initial_position, gboolean send_stream_start)
1380 {
1381 /* must be called with lock */
1382
1383 GstNonstreamAudioDecoderClass *klass =
1384 GST_NONSTREAM_AUDIO_DECODER_CLASS (G_OBJECT_GET_CLASS (dec));
1385
1386 GST_TRACE_OBJECT (dec, "enter finish_load");
1387
1388
1389 /* Prerequisites */
1390
1391 if (!load_ok) {
1392 GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("Loading failed"));
1393 return FALSE;
1394 }
1395
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"));
1399 return FALSE;
1400 }
1401
1402
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));
1407
1408
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);
1413 }
1414
1415
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);
1422 }
1423
1424
1425 /* Send tags downstream (if some exist) */
1426 if (klass->get_subsong_tags != NULL) {
1427 /* Subsong tags available */
1428
1429 GstTagList *tags;
1430 GST_TRACE_OBJECT (dec, "requesting subsong tags");
1431 tags = klass->get_subsong_tags (dec, dec->current_subsong);
1432 if (tags != NULL)
1433 tags = gst_nonstream_audio_decoder_add_main_tags (dec, tags);
1434 if (tags != NULL)
1435 gst_pad_push_event (dec->srcpad, gst_event_new_tag (tags));
1436 } else {
1437 /* No subsong tags - just send main tags out */
1438
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));
1442 }
1443
1444
1445 /* Send stream start downstream if requested */
1446 if (send_stream_start) {
1447 gchar *stream_id;
1448 GstEvent *event;
1449
1450 stream_id =
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\"",
1453 stream_id);
1454
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);
1458 g_free (stream_id);
1459 }
1460
1461
1462 /* Update the table of contents */
1463 gst_nonstream_audio_decoder_update_toc (dec, klass);
1464
1465
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");
1470 return FALSE;
1471 }
1472
1473
1474 /* Send new segment downstream */
1475 gst_nonstream_audio_decoder_output_new_segment (dec, initial_position);
1476
1477 dec->loaded_mode = TRUE;
1478
1479 GST_TRACE_OBJECT (dec, "exit finish_load");
1480
1481 return TRUE;
1482 }
1483
1484
1485 static gboolean
gst_nonstream_audio_decoder_start_task(GstNonstreamAudioDecoder * dec)1486 gst_nonstream_audio_decoder_start_task (GstNonstreamAudioDecoder * dec)
1487 {
1488 if (!gst_pad_start_task (dec->srcpad,
1489 (GstTaskFunction) gst_nonstream_audio_decoder_output_task, dec,
1490 NULL)) {
1491 GST_ERROR_OBJECT (dec, "could not start decoder output task");
1492 return FALSE;
1493 } else
1494 return TRUE;
1495 }
1496
1497
1498 static gboolean
gst_nonstream_audio_decoder_stop_task(GstNonstreamAudioDecoder * dec)1499 gst_nonstream_audio_decoder_stop_task (GstNonstreamAudioDecoder * dec)
1500 {
1501 if (!gst_pad_stop_task (dec->srcpad)) {
1502 GST_ERROR_OBJECT (dec, "could not stop decoder output task");
1503 return FALSE;
1504 } else
1505 return TRUE;
1506 }
1507
1508
1509 static gboolean
gst_nonstream_audio_decoder_switch_to_subsong(GstNonstreamAudioDecoder * dec,guint new_subsong,guint32 const * seqnum)1510 gst_nonstream_audio_decoder_switch_to_subsong (GstNonstreamAudioDecoder * dec,
1511 guint new_subsong, guint32 const *seqnum)
1512 {
1513 gboolean ret = TRUE;
1514 GstNonstreamAudioDecoderClass *klass =
1515 GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
1516
1517
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");
1525 goto finish;
1526 }
1527
1528 if (dec->loaded_mode) {
1529 GstEvent *fevent;
1530 GstClockTime new_position;
1531 GstClockTime new_subsong_duration = GST_CLOCK_TIME_NONE;
1532
1533
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). */
1540
1541 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1542
1543 if (new_subsong == dec->current_subsong) {
1544 GST_DEBUG_OBJECT (dec,
1545 "subsong %u is already the current subsong - ignoring call",
1546 new_subsong);
1547 goto finish_unlock;
1548 }
1549
1550 if (klass->get_num_subsongs) {
1551 guint num_subsongs = klass->get_num_subsongs (dec);
1552
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);
1557 goto finish_unlock;
1558 }
1559 }
1560
1561 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1562
1563
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. */
1568
1569
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,
1575 *seqnum);
1576 } else
1577 GST_DEBUG_OBJECT (dec, "sending flush start event (no sequence number)");
1578
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);
1583 else
1584 gst_event_unref (fevent);
1585
1586
1587 GST_PAD_STREAM_LOCK (dec->srcpad);
1588
1589
1590 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1591
1592
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.) */
1598
1599 ret = FALSE;
1600 if (klass->tell)
1601 new_position = klass->tell (dec);
1602 else
1603 new_position = 0;
1604 GST_WARNING_OBJECT (dec, "switching to new subsong %u failed",
1605 new_subsong);
1606 }
1607
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;
1611
1612
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,
1618 *seqnum);
1619 } else
1620 GST_DEBUG_OBJECT (dec, "sending flush stop event (no sequence number)");
1621
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);
1626 else
1627 gst_event_unref (fevent);
1628
1629
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);
1635
1636 /* create a new segment for the new subsong */
1637 gst_nonstream_audio_decoder_output_new_segment (dec, new_position);
1638
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)
1643 subsong_tags =
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));
1647 }
1648
1649 GST_DEBUG_OBJECT (dec, "successfully switched to new subsong %u",
1650 new_subsong);
1651 dec->current_subsong = new_subsong;
1652
1653
1654 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1655
1656
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);
1660
1661 /* Unlock stream, we are done */
1662 GST_PAD_STREAM_UNLOCK (dec->srcpad);
1663 } else {
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. */
1668
1669 GST_DEBUG_OBJECT (dec,
1670 "playback hasn't started yet - storing subsong index %u as the current subsong",
1671 new_subsong);
1672
1673 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1674 dec->current_subsong = new_subsong;
1675 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1676 }
1677
1678
1679 finish:
1680 return ret;
1681
1682
1683 finish_unlock:
1684 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1685 goto finish;
1686 }
1687
1688
1689 static void
gst_nonstream_audio_decoder_update_toc(GstNonstreamAudioDecoder * dec,GstNonstreamAudioDecoderClass * klass)1690 gst_nonstream_audio_decoder_update_toc (GstNonstreamAudioDecoder * dec,
1691 GstNonstreamAudioDecoderClass * klass)
1692 {
1693 /* must be called with lock */
1694
1695 guint num_subsongs, i;
1696
1697 if (dec->toc != NULL) {
1698 gst_toc_unref (dec->toc);
1699 dec->toc = NULL;
1700 }
1701
1702 if (klass->get_num_subsongs == NULL)
1703 return;
1704
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");
1708 return;
1709 }
1710
1711 dec->toc = gst_toc_new (GST_TOC_SCOPE_GLOBAL);
1712
1713 if (klass->get_main_tags) {
1714 GstTagList *main_tags = klass->get_main_tags (dec);
1715 if (main_tags)
1716 gst_toc_set_tags (dec->toc, main_tags);
1717 }
1718
1719 for (i = 0; i < num_subsongs; ++i) {
1720 gchar *uid;
1721 GstTocEntry *entry;
1722 GstClockTime duration;
1723 GstTagList *tags;
1724
1725 duration =
1726 (klass->get_subsong_duration !=
1727 NULL) ? klass->get_subsong_duration (dec, i) : GST_CLOCK_TIME_NONE;
1728 tags =
1729 (klass->get_subsong_tags != NULL) ? klass->get_subsong_tags (dec,
1730 i) : NULL;
1731 if (!tags)
1732 tags = gst_tag_list_new_empty ();
1733
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,
1741 NULL);
1742
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;
1746
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);
1750
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 */
1754
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);
1758
1759 gst_toc_append_entry (dec->toc, entry);
1760
1761 g_free (uid);
1762 }
1763
1764 gst_pad_push_event (dec->srcpad, gst_event_new_toc (dec->toc, FALSE));
1765 }
1766
1767
1768 static void
gst_nonstream_audio_decoder_update_subsong_duration(GstNonstreamAudioDecoder * dec,GstClockTime duration)1769 gst_nonstream_audio_decoder_update_subsong_duration (GstNonstreamAudioDecoder *
1770 dec, GstClockTime duration)
1771 {
1772 /* must be called with lock */
1773
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);
1779 }
1780
1781
1782 static void
gst_nonstream_audio_decoder_output_new_segment(GstNonstreamAudioDecoder * dec,GstClockTime start_position)1783 gst_nonstream_audio_decoder_output_new_segment (GstNonstreamAudioDecoder * dec,
1784 GstClockTime start_position)
1785 {
1786 /* must be called with lock */
1787
1788 GstSegment segment;
1789
1790 gst_segment_init (&segment, GST_FORMAT_TIME);
1791
1792 segment.base =
1793 gst_util_uint64_scale_int (dec->num_decoded_samples, GST_SECOND,
1794 dec->output_audio_info.rate);
1795 segment.start = 0;
1796 segment.time = start_position;
1797 segment.offset = 0;
1798 segment.position = 0;
1799
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;
1806
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. */
1813
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));
1818
1819 dec->cur_segment = segment;
1820 dec->discont = TRUE;
1821
1822 gst_pad_push_event (dec->srcpad, gst_event_new_segment (&segment));
1823 }
1824
1825
1826 static gboolean
gst_nonstream_audio_decoder_do_seek(GstNonstreamAudioDecoder * dec,GstEvent * event)1827 gst_nonstream_audio_decoder_do_seek (GstNonstreamAudioDecoder * dec,
1828 GstEvent * event)
1829 {
1830 gboolean res;
1831 gdouble rate;
1832 GstFormat format;
1833 GstSeekFlags flags;
1834 GstSeekType start_type, stop_type;
1835 GstClockTime new_position;
1836 gint64 start, stop;
1837 GstSegment segment;
1838 guint32 seqnum;
1839 gboolean flush;
1840 GstNonstreamAudioDecoderClass *klass =
1841 GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
1842
1843 if (klass->seek == NULL) {
1844 GST_DEBUG_OBJECT (dec,
1845 "cannot seek: subclass does not have seek() function defined");
1846 return FALSE;
1847 }
1848
1849 if (!dec->loaded_mode) {
1850 GST_DEBUG_OBJECT (dec, "nothing loaded yet - cannot seek");
1851 return FALSE;
1852 }
1853
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");
1858 return FALSE;
1859 }
1860 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1861
1862
1863 GST_DEBUG_OBJECT (dec, "starting seek");
1864
1865 gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start,
1866 &stop_type, &stop);
1867 seqnum = gst_event_get_seqnum (event);
1868
1869 GST_DEBUG_OBJECT (dec,
1870 "seek event data: "
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)
1877 );
1878
1879 if (format != GST_FORMAT_TIME) {
1880 GST_DEBUG_OBJECT (dec, "seeking is only supported in TIME format");
1881 return FALSE;
1882 }
1883
1884 if (rate < 0) {
1885 GST_DEBUG_OBJECT (dec, "only positive seek rates are supported");
1886 return FALSE;
1887 }
1888
1889 flush = ((flags & GST_SEEK_FLAG_FLUSH) == GST_SEEK_FLAG_FLUSH);
1890
1891 if (flush) {
1892 GstEvent *fevent = gst_event_new_flush_start ();
1893 gst_event_set_seqnum (fevent, seqnum);
1894
1895 GST_DEBUG_OBJECT (dec,
1896 "sending flush start event with sequence number %" G_GUINT32_FORMAT,
1897 seqnum);
1898
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);
1903 else
1904 gst_event_unref (fevent);
1905 } else
1906 gst_pad_pause_task (dec->srcpad);
1907
1908 GST_PAD_STREAM_LOCK (dec->srcpad);
1909
1910 segment = dec->cur_segment;
1911
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);
1916 return FALSE;
1917 }
1918
1919 GST_DEBUG_OBJECT (dec,
1920 "segment data: "
1921 "seek event data: "
1922 "rate %f applied rate %f "
1923 "format %s "
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)
1939 );
1940
1941 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1942
1943 new_position = segment.position;
1944 res = klass->seek (dec, &new_position);
1945 segment.position = new_position;
1946
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;
1952
1953 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1954
1955 if (flush) {
1956 GstEvent *fevent = gst_event_new_flush_stop (TRUE);
1957 gst_event_set_seqnum (fevent, seqnum);
1958
1959 GST_DEBUG_OBJECT (dec,
1960 "sending flush stop event with sequence number %" G_GUINT32_FORMAT,
1961 seqnum);
1962
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);
1966 else
1967 gst_event_unref (fevent);
1968 }
1969
1970 if (res) {
1971 if (flags & GST_SEEK_FLAG_SEGMENT) {
1972 GST_DEBUG_OBJECT (dec, "posting SEGMENT_START message");
1973
1974 gst_element_post_message (GST_ELEMENT (dec),
1975 gst_message_new_segment_start (GST_OBJECT (dec),
1976 GST_FORMAT_TIME, segment.start)
1977 );
1978 }
1979
1980 gst_pad_push_event (dec->srcpad, gst_event_new_segment (&segment));
1981
1982 GST_INFO_OBJECT (dec, "seek succeeded");
1983
1984 gst_nonstream_audio_decoder_start_task (dec);
1985 } else {
1986 GST_WARNING_OBJECT (dec, "seek failed");
1987 }
1988
1989 GST_PAD_STREAM_UNLOCK (dec->srcpad);
1990
1991 gst_event_unref (event);
1992
1993 return res;
1994 }
1995
1996
1997 static GstTagList *
gst_nonstream_audio_decoder_add_main_tags(GstNonstreamAudioDecoder * dec,GstTagList * tags)1998 gst_nonstream_audio_decoder_add_main_tags (GstNonstreamAudioDecoder * dec,
1999 GstTagList * tags)
2000 {
2001 GstNonstreamAudioDecoderClass *klass =
2002 GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
2003
2004 if (!klass->get_main_tags)
2005 return tags;
2006
2007 tags = gst_tag_list_make_writable (tags);
2008 if (tags) {
2009 GstClockTime duration;
2010 GstTagList *main_tags;
2011
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);
2015 if (main_tags) {
2016 tags = gst_tag_list_merge (main_tags, tags, GST_TAG_MERGE_REPLACE);
2017 gst_tag_list_unref (main_tags);
2018 }
2019
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,
2024 NULL);
2025
2026 return tags;
2027 } else {
2028 GST_ERROR_OBJECT (dec, "could not make subsong tags writable");
2029 return NULL;
2030 }
2031 }
2032
2033
2034 static void
gst_nonstream_audio_decoder_output_task(GstNonstreamAudioDecoder * dec)2035 gst_nonstream_audio_decoder_output_task (GstNonstreamAudioDecoder * dec)
2036 {
2037 GstFlowReturn flow;
2038 GstBuffer *outbuf;
2039 guint num_samples;
2040
2041 GstNonstreamAudioDecoderClass *klass;
2042 klass = GST_NONSTREAM_AUDIO_DECODER_CLASS (G_OBJECT_GET_CLASS (dec));
2043 g_assert (klass->decode != NULL);
2044
2045 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
2046
2047 /* perform the actual decoding */
2048 if (!(klass->decode (dec, &outbuf, &num_samples))) {
2049 /* EOS case */
2050 GST_INFO_OBJECT (dec, "decode() reports end -> sending EOS event");
2051 gst_pad_push_event (dec->srcpad, gst_event_new_eos ());
2052 goto pause_unlock;
2053 }
2054
2055 if (outbuf == NULL) {
2056 GST_ERROR_OBJECT (outbuf, "decode() produced NULL buffer");
2057 goto pause_unlock;
2058 }
2059
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);
2070
2071 if (G_UNLIKELY (dec->discont)) {
2072 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
2073 dec->discont = FALSE;
2074 }
2075
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))
2082 );
2083
2084 /* increment sample counters */
2085 dec->cur_pos_in_samples += num_samples;
2086 dec->num_decoded_samples += num_samples;
2087
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))
2093 )) {
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");
2097 goto pause_unlock;
2098 }
2099 }
2100
2101 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
2102
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);
2107 switch (flow) {
2108 case GST_FLOW_OK:
2109 break;
2110
2111 case GST_FLOW_FLUSHING:
2112 GST_LOG_OBJECT (dec, "pipeline is being flushed - pausing task");
2113 goto pause;
2114
2115 case GST_FLOW_NOT_NEGOTIATED:
2116 if (gst_pad_needs_reconfigure (dec->srcpad)) {
2117 GST_DEBUG_OBJECT (dec, "trying to renegotiate");
2118 break;
2119 }
2120 /* fallthrough to default */
2121
2122 default:
2123 GST_ELEMENT_ERROR (dec, STREAM, FAILED, ("Internal data flow error."),
2124 ("streaming task paused, reason %s (%d)", gst_flow_get_name (flow),
2125 flow));
2126 }
2127
2128 return;
2129
2130 pause:
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);
2135 return;
2136 pause_unlock:
2137 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
2138 goto pause;
2139 }
2140
2141
2142 static char const *
get_seek_type_name(GstSeekType seek_type)2143 get_seek_type_name (GstSeekType seek_type)
2144 {
2145 switch (seek_type) {
2146 case GST_SEEK_TYPE_NONE:
2147 return "none";
2148 case GST_SEEK_TYPE_SET:
2149 return "set";
2150 case GST_SEEK_TYPE_END:
2151 return "end";
2152 default:
2153 return "<unknown>";
2154 }
2155 }
2156
2157
2158
2159
2160 /**
2161 * gst_nonstream_audio_decoder_handle_loop:
2162 * @dec: a #GstNonstreamAudioDecoder
2163 * @new_position New position the next loop starts with
2164 *
2165 * Reports that a loop has been completed and creates a new appropriate
2166 * segment for the next loop.
2167 *
2168 * @new_position exists because a loop may not start at the beginning.
2169 *
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.
2174 *
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.
2179 *
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.
2182 *
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).
2186 */
2187 void
gst_nonstream_audio_decoder_handle_loop(GstNonstreamAudioDecoder * dec,GstClockTime new_position)2188 gst_nonstream_audio_decoder_handle_loop (GstNonstreamAudioDecoder * dec,
2189 GstClockTime new_position)
2190 {
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\"");
2195 return;
2196 }
2197
2198 GST_DEBUG_OBJECT (dec,
2199 "handle_loop() invoked with new_position = %" GST_TIME_FORMAT,
2200 GST_TIME_ARGS (new_position));
2201
2202 dec->discont = TRUE;
2203
2204 gst_nonstream_audio_decoder_output_new_segment (dec, new_position);
2205 }
2206
2207
2208 /**
2209 * gst_nonstream_audio_decoder_set_output_format:
2210 * @dec: a #GstNonstreamAudioDecoder
2211 * @audio_info: Valid audio info structure containing the output format
2212 *
2213 * Sets the output caps by means of a GstAudioInfo structure.
2214 *
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.
2218 *
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).
2222 *
2223 * Returns: TRUE if setting the output format succeeded, FALSE otherwise
2224 */
2225 gboolean
gst_nonstream_audio_decoder_set_output_format(GstNonstreamAudioDecoder * dec,GstAudioInfo const * audio_info)2226 gst_nonstream_audio_decoder_set_output_format (GstNonstreamAudioDecoder * dec,
2227 GstAudioInfo const *audio_info)
2228 {
2229 GstCaps *caps;
2230 GstCaps *templ_caps;
2231 gboolean caps_ok;
2232 gboolean res = TRUE;
2233
2234 g_return_val_if_fail (GST_IS_NONSTREAM_AUDIO_DECODER (dec), FALSE);
2235
2236 caps = gst_audio_info_to_caps (audio_info);
2237 if (caps == NULL) {
2238 GST_WARNING_OBJECT (dec, "Could not create caps out of audio info");
2239 return FALSE;
2240 }
2241
2242 templ_caps = gst_pad_get_pad_template_caps (dec->srcpad);
2243 caps_ok = gst_caps_is_subset (caps, templ_caps);
2244
2245 if (caps_ok) {
2246 dec->output_audio_info = *audio_info;
2247 dec->output_format_changed = TRUE;
2248
2249 GST_INFO_OBJECT (dec, "setting output format to %" GST_PTR_FORMAT,
2250 (gpointer) caps);
2251 } else {
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);
2255
2256 res = FALSE;
2257 }
2258
2259 gst_caps_unref (caps);
2260 gst_caps_unref (templ_caps);
2261
2262 return res;
2263 }
2264
2265
2266 /**
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
2272 *
2273 * Convenience function; sets the output caps by means of common parameters.
2274 *
2275 * Internally, this fills a GstAudioInfo structure and calls
2276 * gst_nonstream_audio_decoder_set_output_format().
2277 *
2278 * Returns: TRUE if setting the output format succeeded, FALSE otherwise
2279 */
2280 gboolean
gst_nonstream_audio_decoder_set_output_format_simple(GstNonstreamAudioDecoder * dec,guint sample_rate,GstAudioFormat sample_format,guint num_channels)2281 gst_nonstream_audio_decoder_set_output_format_simple (GstNonstreamAudioDecoder *
2282 dec, guint sample_rate, GstAudioFormat sample_format, guint num_channels)
2283 {
2284 GstAudioInfo output_audio_info;
2285
2286 gst_audio_info_init (&output_audio_info);
2287
2288 gst_audio_info_set_format (&output_audio_info,
2289 sample_format, sample_rate, num_channels, NULL);
2290
2291 return gst_nonstream_audio_decoder_set_output_format (dec,
2292 &output_audio_info);
2293 }
2294
2295
2296 /**
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
2302 *
2303 * Gets sample format, sample rate, channel count from the allowed srcpad caps.
2304 *
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.
2308 *
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:
2316 *
2317 * "audio/x-raw, format={S16LE,S32LE}, rate=[1,32000], channels=[1,MAX]"
2318 *
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
2324 * initial values.
2325 *
2326 * Decoder lock is not held by this function, so it can be called from within
2327 * any of the class vfuncs.
2328 */
2329 void
gst_nonstream_audio_decoder_get_downstream_info(GstNonstreamAudioDecoder * dec,GstAudioFormat * format,gint * sample_rate,gint * num_channels)2330 gst_nonstream_audio_decoder_get_downstream_info (GstNonstreamAudioDecoder * dec,
2331 GstAudioFormat * format, gint * sample_rate, gint * num_channels)
2332 {
2333 GstCaps *allowed_srccaps;
2334 guint structure_nr, num_structures;
2335 gboolean ds_format_found = FALSE, ds_rate_found = FALSE, ds_channels_found =
2336 FALSE;
2337
2338 g_return_if_fail (GST_IS_NONSTREAM_AUDIO_DECODER (dec));
2339
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");
2344 return;
2345 }
2346
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;
2351
2352 ds_format_found = FALSE;
2353 ds_rate_found = FALSE;
2354 ds_channels_found = FALSE;
2355
2356 structure = gst_caps_get_structure (allowed_srccaps, structure_nr);
2357
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;
2369
2370 /* Make a copy of the structure, since we need to modify
2371 * (fixate) values inside */
2372 fixated_str = gst_structure_copy (structure);
2373
2374 /* Try to fixate and retrieve the sample format */
2375 if (passed && (format != NULL)) {
2376 passed = FALSE;
2377
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");
2384 if (fmt_str
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;
2390 passed = TRUE;
2391 }
2392 }
2393 }
2394
2395 /* Try to fixate and retrieve the sample rate */
2396 if (passed && (sample_rate != NULL)) {
2397 passed = FALSE;
2398
2399 if ((gst_structure_get_field_type (fixated_str, "rate") == G_TYPE_INT)
2400 || gst_structure_fixate_field_nearest_int (fixated_str, "rate",
2401 *sample_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;
2406 passed = TRUE;
2407 }
2408 }
2409 }
2410
2411 /* Try to fixate and retrieve the channel count */
2412 if (passed && (num_channels != NULL)) {
2413 passed = FALSE;
2414
2415 if ((gst_structure_get_field_type (fixated_str,
2416 "channels") == G_TYPE_INT)
2417 || gst_structure_fixate_field_nearest_int (fixated_str, "channels",
2418 *num_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;
2424 passed = TRUE;
2425 }
2426 }
2427 }
2428
2429 gst_structure_free (fixated_str);
2430
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;
2435 break;
2436 }
2437 }
2438 }
2439
2440 gst_caps_unref (allowed_srccaps);
2441
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)",
2449 *sample_rate);
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)",
2453 *num_channels);
2454 }
2455
2456
2457 /**
2458 * gst_nonstream_audio_decoder_allocate_output_buffer:
2459 * @dec: Decoder instance
2460 * @size: Size of the output buffer, in bytes
2461 *
2462 * Allocates an output buffer with the internally configured buffer pool.
2463 *
2464 * This function may only be called from within @load_from_buffer,
2465 * @load_from_custom, and @decode.
2466 *
2467 * Returns: Newly allocated output buffer, or NULL if allocation failed
2468 */
2469 GstBuffer *
gst_nonstream_audio_decoder_allocate_output_buffer(GstNonstreamAudioDecoder * dec,gsize size)2470 gst_nonstream_audio_decoder_allocate_output_buffer (GstNonstreamAudioDecoder *
2471 dec, gsize size)
2472 {
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))
2476 )) {
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");
2483 return NULL;
2484 }
2485 }
2486
2487 return gst_buffer_new_allocate (dec->allocator, size,
2488 &(dec->allocation_params));
2489 }
2490