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 * <orderedlist>
78 * <listitem>
79 * <itemizedlist><title>Unloaded mode</title>
80 * <listitem><para>
81 * Initial values are set. If a current subsong has already been
82 * defined (for example over the command line with gst-launch), then
83 * the subsong index is copied over to current_subsong .
84 * Same goes for the num-loops and output-mode properties.
85 * Media is NOT loaded yet.
86 * </para></listitem>
87 * <listitem><para>
88 * Once the sinkpad is activated, the process continues. The sinkpad is
89 * activated in push mode, and the class accumulates the incoming media
90 * data in an adapter inside the sinkpad's chain function until either an
91 * EOS event is received from upstream, or the number of bytes reported
92 * by upstream is reached. Then it loads the media, and starts the decoder
93 * output task.
94 * <listitem><para>
95 * If upstream cannot respond to the size query (in bytes) of @load_from_buffer
96 * fails, an error is reported, and the pipeline stops.
97 * </para></listitem>
98 * <listitem><para>
99 * If there are no errors, @load_from_buffer is called to load the media. The
100 * subclass must at least call gst_nonstream_audio_decoder_set_output_audioinfo()
101 * there, and is free to make use of the initial subsong, output mode, and
102 * position. If the actual output mode or position differs from the initial
103 * value,it must set the initial value to the actual one (for example, if
104 * the actual starting position is always 0, set *initial_position to 0).
105 * If loading is unsuccessful, an error is reported, and the pipeline
106 * stops. Otherwise, the base class calls @get_current_subsong to retrieve
107 * the actual current subsong, @get_subsong_duration to report the current
108 * subsong's duration in a duration event and message, and @get_subsong_tags
109 * to send tags downstream in an event (these functions are optional; if
110 * set to NULL, the associated operation is skipped). Afterwards, the base
111 * class switches to loaded mode, and starts the decoder output task.
112 * </para></listitem>
113 * </itemizedlist>
114 * <itemizedlist><title>Loaded mode</title>
115 * <listitem><para>
116 * Inside the decoder output task, the base class repeatedly calls @decode,
117 * which returns a buffer with decoded, ready-to-play samples. If the
118 * subclass reached the end of playback, @decode returns FALSE, otherwise
119 * TRUE.
120 * </para></listitem>
121 * <listitem><para>
122 * Upon reaching a loop end, subclass either ignores that, or loops back
123 * to the beginning of the loop. In the latter case, if the output mode is set
124 * to LOOPING, the subclass must call gst_nonstream_audio_decoder_handle_loop()
125 * *after* the playback position moved to the start of the loop. In
126 * STEADY mode, the subclass must *not* call this function.
127 * Since many decoders only provide a callback for when the looping occurs,
128 * and that looping occurs inside the decoding operation itself, the following
129 * mechanism for subclass is suggested: set a flag inside such a callback.
130 * Then, in the next @decode call, before doing the decoding, check this flag.
131 * If it is set, gst_nonstream_audio_decoder_handle_loop() is called, and the
132 * flag is cleared.
133 * (This function call is necessary in LOOPING mode because it updates the
134 * current segment and makes sure the next buffer that is sent downstream
135 * has its DISCONT flag set.)
136 * </para></listitem>
137 * <listitem><para>
138 * When the current subsong is switched, @set_current_subsong is called.
139 * If it fails, a warning is reported, and nothing else is done. Otherwise,
140 * it calls @get_subsong_duration to get the new current subsongs's
141 * duration, @get_subsong_tags to get its tags, reports a new duration
142 * (i.e. it sends a duration event downstream and generates a duration
143 * message), updates the current segment, and sends the subsong's tags in
144 * an event downstream. (If @set_current_subsong has been set to NULL by
145 * the subclass, attempts to set a current subsong are ignored; likewise,
146 * if @get_subsong_duration is NULL, no duration is reported, and if
147 * @get_subsong_tags is NULL, no tags are sent downstream.)
148 * </para></listitem>
149 * <listitem><para>
150 * When an attempt is made to switch the output mode, it is checked against
151 * the bitmask returned by @get_supported_output_modes. If the proposed
152 * new output mode is supported, the current segment is updated
153 * (it is open-ended in STEADY mode, and covers the (sub)song length in
154 * LOOPING mode), and the subclass' @set_output_mode function is called
155 * unless it is set to NULL. Subclasses should reset internal loop counters
156 * in this function.
157 * </para></listitem>
158 * </itemizedlist>
159 * </listitem>
160 * </orderedlist>
161 *
162 * The relationship between (sub)song duration, output mode, and number of loops
163 * is defined this way (this is all done by the base class automatically):
164 * <itemizedlist>
165 * <listitem><para>
166 * Segments have their duration and stop values set to GST_CLOCK_TIME_NONE in
167 * STEADY mode, and to the duration of the (sub)song in LOOPING mode.
168 * </para></listitem>
169 * <listitem><para>
170 * The duration that is returned to a DURATION query is always the duration
171 * of the (sub)song, regardless of number of loops or output mode. The same
172 * goes for DURATION messages and tags.
173 * </para></listitem>
174 * <listitem><para>
175 * If the number of loops is >0 or -1, durations of TOC entries are set to
176 * the duration of the respective subsong in LOOPING mode and to G_MAXINT64 in
177 * STEADY mode. If the number of loops is 0, entry durations are set to the
178 * subsong duration regardless of the output mode.
179 * </para></listitem>
180 * </itemizedlist>
181 */
182
183 #ifdef HAVE_CONFIG_H
184 #include "config.h"
185 #endif
186
187 #include <stdio.h>
188 #include <gst/gst.h>
189 #include <gst/audio/audio.h>
190
191 #include "gstnonstreamaudiodecoder.h"
192
193
194 GST_DEBUG_CATEGORY (nonstream_audiodecoder_debug);
195 #define GST_CAT_DEFAULT nonstream_audiodecoder_debug
196
197
198 enum
199 {
200 PROP_0,
201 PROP_CURRENT_SUBSONG,
202 PROP_SUBSONG_MODE,
203 PROP_NUM_LOOPS,
204 PROP_OUTPUT_MODE
205 };
206
207 #define DEFAULT_CURRENT_SUBSONG 0
208 #define DEFAULT_SUBSONG_MODE GST_NONSTREAM_AUDIO_SUBSONG_MODE_DECODER_DEFAULT
209 #define DEFAULT_NUM_SUBSONGS 0
210 #define DEFAULT_NUM_LOOPS 0
211 #define DEFAULT_OUTPUT_MODE GST_NONSTREAM_AUDIO_OUTPUT_MODE_STEADY
212
213
214
215
216 static GstElementClass *gst_nonstream_audio_decoder_parent_class = NULL;
217
218 static void
219 gst_nonstream_audio_decoder_class_init (GstNonstreamAudioDecoderClass * klass);
220 static void gst_nonstream_audio_decoder_init (GstNonstreamAudioDecoder * dec,
221 GstNonstreamAudioDecoderClass * klass);
222
223 static void gst_nonstream_audio_decoder_finalize (GObject * object);
224 static void gst_nonstream_audio_decoder_set_property (GObject * object,
225 guint prop_id, GValue const *value, GParamSpec * pspec);
226 static void gst_nonstream_audio_decoder_get_property (GObject * object,
227 guint prop_id, GValue * value, GParamSpec * pspec);
228
229 static GstStateChangeReturn gst_nonstream_audio_decoder_change_state (GstElement
230 * element, GstStateChange transition);
231
232 static gboolean gst_nonstream_audio_decoder_sink_event (GstPad * pad,
233 GstObject * parent, GstEvent * event);
234 static gboolean gst_nonstream_audio_decoder_sink_query (GstPad * pad,
235 GstObject * parent, GstQuery * query);
236 static GstFlowReturn gst_nonstream_audio_decoder_chain (GstPad * pad,
237 GstObject * parent, GstBuffer * buffer);
238
239 static gboolean gst_nonstream_audio_decoder_src_event (GstPad * pad,
240 GstObject * parent, GstEvent * event);
241 static gboolean gst_nonstream_audio_decoder_src_query (GstPad * pad,
242 GstObject * parent, GstQuery * query);
243
244 static void
245 gst_nonstream_audio_decoder_set_initial_state (GstNonstreamAudioDecoder * dec);
246 static void gst_nonstream_audio_decoder_cleanup_state (GstNonstreamAudioDecoder
247 * dec);
248
249 static gboolean gst_nonstream_audio_decoder_negotiate (GstNonstreamAudioDecoder
250 * dec);
251
252 static gboolean
253 gst_nonstream_audio_decoder_negotiate_default (GstNonstreamAudioDecoder * dec);
254 static gboolean
255 gst_nonstream_audio_decoder_decide_allocation_default (GstNonstreamAudioDecoder
256 * dec, GstQuery * query);
257 static gboolean
258 gst_nonstream_audio_decoder_propose_allocation_default (GstNonstreamAudioDecoder
259 * dec, GstQuery * query);
260
261 static gboolean
262 gst_nonstream_audio_decoder_get_upstream_size (GstNonstreamAudioDecoder * dec,
263 gint64 * length);
264 static gboolean
265 gst_nonstream_audio_decoder_load_from_buffer (GstNonstreamAudioDecoder * dec,
266 GstBuffer * buffer);
267 static gboolean
268 gst_nonstream_audio_decoder_load_from_custom (GstNonstreamAudioDecoder * dec);
269 static gboolean
270 gst_nonstream_audio_decoder_finish_load (GstNonstreamAudioDecoder * dec,
271 gboolean load_ok, GstClockTime initial_position,
272 gboolean send_stream_start);
273
274 static gboolean gst_nonstream_audio_decoder_start_task (GstNonstreamAudioDecoder
275 * dec);
276 static gboolean gst_nonstream_audio_decoder_stop_task (GstNonstreamAudioDecoder
277 * dec);
278
279 static gboolean
280 gst_nonstream_audio_decoder_switch_to_subsong (GstNonstreamAudioDecoder * dec,
281 guint new_subsong, guint32 const *seqnum);
282
283 static void gst_nonstream_audio_decoder_update_toc (GstNonstreamAudioDecoder *
284 dec, GstNonstreamAudioDecoderClass * klass);
285 static void
286 gst_nonstream_audio_decoder_update_subsong_duration (GstNonstreamAudioDecoder *
287 dec, GstClockTime duration);
288 static void
289 gst_nonstream_audio_decoder_output_new_segment (GstNonstreamAudioDecoder * dec,
290 GstClockTime start_position);
291 static gboolean gst_nonstream_audio_decoder_do_seek (GstNonstreamAudioDecoder *
292 dec, GstEvent * event);
293
294 static GstTagList
295 * gst_nonstream_audio_decoder_add_main_tags (GstNonstreamAudioDecoder * dec,
296 GstTagList * tags);
297
298 static void gst_nonstream_audio_decoder_output_task (GstNonstreamAudioDecoder *
299 dec);
300
301 static char const *get_seek_type_name (GstSeekType seek_type);
302
303
304
305
306 static GType gst_nonstream_audio_decoder_output_mode_get_type (void);
307 #define GST_TYPE_NONSTREAM_AUDIO_DECODER_OUTPUT_MODE (gst_nonstream_audio_decoder_output_mode_get_type())
308
309 static GType gst_nonstream_audio_decoder_subsong_mode_get_type (void);
310 #define GST_TYPE_NONSTREAM_AUDIO_DECODER_SUBSONG_MODE (gst_nonstream_audio_decoder_subsong_mode_get_type())
311
312
313 static GType
gst_nonstream_audio_decoder_output_mode_get_type(void)314 gst_nonstream_audio_decoder_output_mode_get_type (void)
315 {
316 static GType gst_nonstream_audio_decoder_output_mode_type = 0;
317
318 if (!gst_nonstream_audio_decoder_output_mode_type) {
319 static GEnumValue output_mode_values[] = {
320 {GST_NONSTREAM_AUDIO_OUTPUT_MODE_LOOPING, "Looping output", "looping"},
321 {GST_NONSTREAM_AUDIO_OUTPUT_MODE_STEADY, "Steady output", "steady"},
322 {0, NULL, NULL},
323 };
324
325 gst_nonstream_audio_decoder_output_mode_type =
326 g_enum_register_static ("NonstreamAudioOutputMode", output_mode_values);
327 }
328
329 return gst_nonstream_audio_decoder_output_mode_type;
330 }
331
332
333 static GType
gst_nonstream_audio_decoder_subsong_mode_get_type(void)334 gst_nonstream_audio_decoder_subsong_mode_get_type (void)
335 {
336 static GType gst_nonstream_audio_decoder_subsong_mode_type = 0;
337
338 if (!gst_nonstream_audio_decoder_subsong_mode_type) {
339 static GEnumValue subsong_mode_values[] = {
340 {GST_NONSTREAM_AUDIO_SUBSONG_MODE_SINGLE, "Play single subsong",
341 "single"},
342 {GST_NONSTREAM_AUDIO_SUBSONG_MODE_ALL, "Play all subsongs", "all"},
343 {GST_NONSTREAM_AUDIO_SUBSONG_MODE_DECODER_DEFAULT,
344 "Decoder specific default behavior", "default"},
345 {0, NULL, NULL},
346 };
347
348 gst_nonstream_audio_decoder_subsong_mode_type =
349 g_enum_register_static ("NonstreamAudioSubsongMode",
350 subsong_mode_values);
351 }
352
353 return gst_nonstream_audio_decoder_subsong_mode_type;
354 }
355
356
357
358 /* Manually defining the GType instead of using G_DEFINE_TYPE_WITH_CODE()
359 * because the _init() function needs to be able to access the derived
360 * class' sink- and srcpads */
361
362
363 GType
gst_nonstream_audio_decoder_get_type(void)364 gst_nonstream_audio_decoder_get_type (void)
365 {
366 static volatile gsize nonstream_audio_decoder_type = 0;
367
368 if (g_once_init_enter (&nonstream_audio_decoder_type)) {
369 GType type_;
370 static const GTypeInfo nonstream_audio_decoder_info = {
371 sizeof (GstNonstreamAudioDecoderClass),
372 NULL,
373 NULL,
374 (GClassInitFunc) gst_nonstream_audio_decoder_class_init,
375 NULL,
376 NULL,
377 sizeof (GstNonstreamAudioDecoder),
378 0,
379 (GInstanceInitFunc) gst_nonstream_audio_decoder_init,
380 NULL
381 };
382
383 type_ = g_type_register_static (GST_TYPE_ELEMENT,
384 "GstNonstreamAudioDecoder",
385 &nonstream_audio_decoder_info, G_TYPE_FLAG_ABSTRACT);
386 g_once_init_leave (&nonstream_audio_decoder_type, type_);
387 }
388
389 return nonstream_audio_decoder_type;
390 }
391
392
393
394
395 static void
gst_nonstream_audio_decoder_class_init(GstNonstreamAudioDecoderClass * klass)396 gst_nonstream_audio_decoder_class_init (GstNonstreamAudioDecoderClass * klass)
397 {
398 GObjectClass *object_class;
399 GstElementClass *element_class;
400
401 object_class = G_OBJECT_CLASS (klass);
402 element_class = GST_ELEMENT_CLASS (klass);
403
404 gst_nonstream_audio_decoder_parent_class = g_type_class_peek_parent (klass);
405
406 GST_DEBUG_CATEGORY_INIT (nonstream_audiodecoder_debug,
407 "nonstreamaudiodecoder", 0, "nonstream audio decoder base class");
408
409 object_class->finalize =
410 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_finalize);
411 object_class->set_property =
412 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_set_property);
413 object_class->get_property =
414 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_get_property);
415 element_class->change_state =
416 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_change_state);
417
418 klass->seek = NULL;
419 klass->tell = NULL;
420
421 klass->load_from_buffer = NULL;
422 klass->load_from_custom = NULL;
423
424 klass->get_main_tags = NULL;
425
426 klass->get_current_subsong = NULL;
427 klass->set_current_subsong = NULL;
428
429 klass->get_num_subsongs = NULL;
430 klass->get_subsong_duration = NULL;
431 klass->get_subsong_tags = NULL;
432 klass->set_subsong_mode = NULL;
433
434 klass->set_num_loops = NULL;
435 klass->get_num_loops = NULL;
436
437 klass->decode = NULL;
438
439 klass->negotiate =
440 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_negotiate_default);
441
442 klass->decide_allocation =
443 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_decide_allocation_default);
444 klass->propose_allocation =
445 GST_DEBUG_FUNCPTR
446 (gst_nonstream_audio_decoder_propose_allocation_default);
447
448 klass->loads_from_sinkpad = TRUE;
449
450 g_object_class_install_property (object_class,
451 PROP_CURRENT_SUBSONG,
452 g_param_spec_uint ("current-subsong",
453 "Currently active subsong",
454 "Subsong that is currently selected for playback",
455 0, G_MAXUINT,
456 DEFAULT_CURRENT_SUBSONG, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
457 );
458
459 g_object_class_install_property (object_class,
460 PROP_SUBSONG_MODE,
461 g_param_spec_enum ("subsong-mode",
462 "Subsong mode",
463 "Mode which defines how to treat subsongs",
464 GST_TYPE_NONSTREAM_AUDIO_DECODER_SUBSONG_MODE,
465 DEFAULT_SUBSONG_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
466 );
467
468 g_object_class_install_property (object_class,
469 PROP_NUM_LOOPS,
470 g_param_spec_int ("num-loops",
471 "Number of playback loops",
472 "Number of times a playback loop shall be executed (special values: 0 = no looping; -1 = infinite loop)",
473 -1, G_MAXINT,
474 DEFAULT_NUM_LOOPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
475 );
476
477 g_object_class_install_property (object_class,
478 PROP_OUTPUT_MODE,
479 g_param_spec_enum ("output-mode",
480 "Output mode",
481 "Which mode playback shall use when a loop is encountered; looping = reset position to start of loop, steady = do not reset position",
482 GST_TYPE_NONSTREAM_AUDIO_DECODER_OUTPUT_MODE,
483 DEFAULT_OUTPUT_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
484 );
485 }
486
487
488 static void
gst_nonstream_audio_decoder_init(GstNonstreamAudioDecoder * dec,GstNonstreamAudioDecoderClass * klass)489 gst_nonstream_audio_decoder_init (GstNonstreamAudioDecoder * dec,
490 GstNonstreamAudioDecoderClass * klass)
491 {
492 GstPadTemplate *pad_template;
493
494 /* These are set here, not in gst_nonstream_audio_decoder_set_initial_state(),
495 * because these are values for the properties; they are not supposed to be
496 * reset in the READY->NULL state change */
497 dec->current_subsong = DEFAULT_CURRENT_SUBSONG;
498 dec->subsong_mode = DEFAULT_SUBSONG_MODE;
499 dec->output_mode = DEFAULT_OUTPUT_MODE;
500 dec->num_loops = DEFAULT_NUM_LOOPS;
501
502 /* Calling this here, not in the NULL->READY state change,
503 * to make sure get_property calls return valid values */
504 gst_nonstream_audio_decoder_set_initial_state (dec);
505
506 dec->input_data_adapter = gst_adapter_new ();
507 g_mutex_init (&(dec->mutex));
508
509 {
510 /* set up src pad */
511
512 pad_template =
513 gst_element_class_get_pad_template (GST_ELEMENT_CLASS (klass), "src");
514 g_return_if_fail (pad_template != NULL); /* derived class is supposed to define a src pad template */
515
516 dec->srcpad = gst_pad_new_from_template (pad_template, "src");
517 gst_pad_set_event_function (dec->srcpad,
518 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_src_event));
519 gst_pad_set_query_function (dec->srcpad,
520 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_src_query));
521 gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
522 }
523
524 if (klass->loads_from_sinkpad) {
525 /* set up sink pad if this class loads from a sinkpad */
526
527 pad_template =
528 gst_element_class_get_pad_template (GST_ELEMENT_CLASS (klass), "sink");
529 g_return_if_fail (pad_template != NULL); /* derived class is supposed to define a sink pad template */
530
531 dec->sinkpad = gst_pad_new_from_template (pad_template, "sink");
532 gst_pad_set_event_function (dec->sinkpad,
533 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_sink_event));
534 gst_pad_set_query_function (dec->sinkpad,
535 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_sink_query));
536 gst_pad_set_chain_function (dec->sinkpad,
537 GST_DEBUG_FUNCPTR (gst_nonstream_audio_decoder_chain));
538 gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad);
539 }
540 }
541
542
543
544
545 static void
gst_nonstream_audio_decoder_finalize(GObject * object)546 gst_nonstream_audio_decoder_finalize (GObject * object)
547 {
548 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (object);
549
550 g_mutex_clear (&(dec->mutex));
551 g_object_unref (G_OBJECT (dec->input_data_adapter));
552
553 G_OBJECT_CLASS (gst_nonstream_audio_decoder_parent_class)->finalize (object);
554 }
555
556
557 static void
gst_nonstream_audio_decoder_set_property(GObject * object,guint prop_id,GValue const * value,GParamSpec * pspec)558 gst_nonstream_audio_decoder_set_property (GObject * object, guint prop_id,
559 GValue const *value, GParamSpec * pspec)
560 {
561 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (object);
562 GstNonstreamAudioDecoderClass *klass =
563 GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
564
565 switch (prop_id) {
566 case PROP_OUTPUT_MODE:
567 {
568 GstNonstreamAudioOutputMode new_output_mode;
569 new_output_mode = g_value_get_enum (value);
570
571 g_assert (klass->get_supported_output_modes);
572
573 if ((klass->get_supported_output_modes (dec) & (1u << new_output_mode)) ==
574 0) {
575 GST_WARNING_OBJECT (dec,
576 "could not set output mode to %s (not supported by subclass)",
577 (new_output_mode ==
578 GST_NONSTREAM_AUDIO_OUTPUT_MODE_STEADY) ? "steady" : "looping");
579 break;
580 }
581
582 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
583 if (new_output_mode != dec->output_mode) {
584 gboolean proceed = TRUE;
585
586 if (dec->loaded_mode) {
587 GstClockTime cur_position;
588
589 if (klass->set_output_mode != NULL) {
590 if (klass->set_output_mode (dec, new_output_mode, &cur_position))
591 proceed = TRUE;
592 else {
593 proceed = FALSE;
594 GST_WARNING_OBJECT (dec, "switching to new output mode failed");
595 }
596 } else {
597 GST_DEBUG_OBJECT (dec,
598 "cannot call set_output_mode, since it is NULL");
599 proceed = FALSE;
600 }
601
602 if (proceed) {
603 gst_nonstream_audio_decoder_output_new_segment (dec, cur_position);
604 dec->output_mode = new_output_mode;
605 }
606 }
607
608 if (proceed) {
609 /* store output mode in case the property is set before the media got loaded */
610 dec->output_mode = new_output_mode;
611 }
612 }
613 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
614
615 break;
616 }
617
618 case PROP_CURRENT_SUBSONG:
619 {
620 guint new_subsong = g_value_get_uint (value);
621 gst_nonstream_audio_decoder_switch_to_subsong (dec, new_subsong, NULL);
622
623 break;
624 }
625
626 case PROP_SUBSONG_MODE:
627 {
628 GstNonstreamAudioSubsongMode new_subsong_mode = g_value_get_enum (value);
629
630 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
631 if (new_subsong_mode != dec->subsong_mode) {
632 gboolean proceed = TRUE;
633
634 if (dec->loaded_mode) {
635 GstClockTime cur_position;
636
637 if (klass->set_subsong_mode != NULL) {
638 if (klass->set_subsong_mode (dec, new_subsong_mode, &cur_position))
639 proceed = TRUE;
640 else {
641 proceed = FALSE;
642 GST_WARNING_OBJECT (dec, "switching to new subsong mode failed");
643 }
644 } else {
645 GST_DEBUG_OBJECT (dec,
646 "cannot call set_subsong_mode, since it is NULL");
647 proceed = FALSE;
648 }
649
650 if (proceed) {
651 if (GST_CLOCK_TIME_IS_VALID (cur_position))
652 gst_nonstream_audio_decoder_output_new_segment (dec,
653 cur_position);
654 dec->subsong_mode = new_subsong_mode;
655 }
656 }
657
658 if (proceed) {
659 /* store subsong mode in case the property is set before the media got loaded */
660 dec->subsong_mode = new_subsong_mode;
661 }
662 }
663 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
664
665 break;
666 }
667
668 case PROP_NUM_LOOPS:
669 {
670 gint new_num_loops = g_value_get_int (value);
671
672 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
673 if (new_num_loops != dec->num_loops) {
674 if (dec->loaded_mode) {
675 if (klass->set_num_loops != NULL) {
676 if (!(klass->set_num_loops (dec, new_num_loops)))
677 GST_WARNING_OBJECT (dec, "setting number of loops to %u failed",
678 new_num_loops);
679 } else
680 GST_DEBUG_OBJECT (dec,
681 "cannot call set_num_loops, since it is NULL");
682 }
683
684 /* store number of loops in case the property is set before the media got loaded */
685 dec->num_loops = new_num_loops;
686 }
687 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
688
689 break;
690 }
691
692 default:
693 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
694 break;
695 }
696 }
697
698
699 static void
gst_nonstream_audio_decoder_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)700 gst_nonstream_audio_decoder_get_property (GObject * object, guint prop_id,
701 GValue * value, GParamSpec * pspec)
702 {
703 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (object);
704
705 switch (prop_id) {
706 case PROP_OUTPUT_MODE:
707 {
708 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
709 g_value_set_enum (value, dec->output_mode);
710 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
711 break;
712 }
713
714 case PROP_CURRENT_SUBSONG:
715 {
716 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
717 g_value_set_uint (value, dec->current_subsong);
718 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
719 break;
720 }
721
722 case PROP_SUBSONG_MODE:
723 {
724 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
725 g_value_set_enum (value, dec->subsong_mode);
726 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
727 break;
728 }
729
730 case PROP_NUM_LOOPS:
731 {
732 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
733 g_value_set_int (value, dec->num_loops);
734 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
735 break;
736 }
737
738 default:
739 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
740 break;
741 }
742 }
743
744
745
746 static GstStateChangeReturn
gst_nonstream_audio_decoder_change_state(GstElement * element,GstStateChange transition)747 gst_nonstream_audio_decoder_change_state (GstElement * element,
748 GstStateChange transition)
749 {
750 GstStateChangeReturn ret;
751
752 ret =
753 GST_ELEMENT_CLASS (gst_nonstream_audio_decoder_parent_class)->change_state
754 (element, transition);
755 if (ret == GST_STATE_CHANGE_FAILURE)
756 return ret;
757
758 switch (transition) {
759 case GST_STATE_CHANGE_READY_TO_PAUSED:
760 {
761
762 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (element);
763 GstNonstreamAudioDecoderClass *klass =
764 GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
765
766 /* For decoders that load with some custom method,
767 * this is now the time to load
768 *
769 * It is done *after* calling the parent class' change_state vfunc,
770 * since the pad states need to be set up in order for the loading
771 * to succeed, since it will try to push a new_caps event
772 * downstream etc. (upwards state changes typically are handled
773 * *before* calling the parent class' change_state vfunc ; this is
774 * a special case) */
775 if (!(klass->loads_from_sinkpad) && !(dec->loaded_mode)) {
776 gboolean ret;
777
778 /* load_from_custom is required if loads_from_sinkpad is FALSE */
779 g_assert (klass->load_from_custom != NULL);
780
781 ret = gst_nonstream_audio_decoder_load_from_custom (dec);
782
783 if (!ret) {
784 GST_ERROR_OBJECT (dec, "loading from custom source failed");
785 return GST_STATE_CHANGE_FAILURE;
786 }
787
788 if (!gst_nonstream_audio_decoder_start_task (dec))
789 return GST_STATE_CHANGE_FAILURE;
790
791 }
792
793 break;
794 }
795
796 case GST_STATE_CHANGE_PAUSED_TO_READY:
797 {
798 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (element);
799 if (!gst_nonstream_audio_decoder_stop_task (dec))
800 return GST_STATE_CHANGE_FAILURE;
801 break;
802 }
803
804 case GST_STATE_CHANGE_READY_TO_NULL:
805 {
806 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (element);
807
808 /* In the READY->NULL state change, reset the decoder to an
809 * initial state ensure it can be used for a fresh new session */
810 gst_nonstream_audio_decoder_cleanup_state (dec);
811 break;
812 }
813
814 default:
815 break;
816 }
817
818 return ret;
819 }
820
821
822
823 static gboolean
gst_nonstream_audio_decoder_sink_event(GstPad * pad,GstObject * parent,GstEvent * event)824 gst_nonstream_audio_decoder_sink_event (GstPad * pad, GstObject * parent,
825 GstEvent * event)
826 {
827 gboolean res = FALSE;
828 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (parent);
829
830 switch (GST_EVENT_TYPE (event)) {
831 case GST_EVENT_SEGMENT:
832 {
833 /* Upstream sends in a byte segment, which is uninteresting here,
834 * since a custom segment event is generated anyway */
835 gst_event_unref (event);
836 res = TRUE;
837 break;
838 }
839
840 case GST_EVENT_EOS:
841 {
842 gsize avail_size;
843 GstBuffer *adapter_buffer;
844
845 if (dec->loaded_mode) {
846 /* If media has already been loaded, then the decoder
847 * task has been started; the EOS event can be ignored */
848
849 GST_DEBUG_OBJECT (dec,
850 "EOS received after media was loaded -> ignoring");
851 res = TRUE;
852 } else {
853 /* take all data in the input data adapter,
854 * and try to load the media from it */
855
856 avail_size = gst_adapter_available (dec->input_data_adapter);
857 if (avail_size == 0) {
858 GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL),
859 ("EOS event raised, but no data was received - cannot load anything"));
860 return FALSE;
861 }
862
863 adapter_buffer =
864 gst_adapter_take_buffer (dec->input_data_adapter, avail_size);
865
866 if (!gst_nonstream_audio_decoder_load_from_buffer (dec, adapter_buffer)) {
867 return FALSE;
868 }
869
870 res = gst_nonstream_audio_decoder_start_task (dec);
871 }
872
873 break;
874 }
875
876 default:
877 res = gst_pad_event_default (pad, parent, event);
878 }
879
880 return res;
881 }
882
883
884 static gboolean
gst_nonstream_audio_decoder_sink_query(GstPad * pad,GstObject * parent,GstQuery * query)885 gst_nonstream_audio_decoder_sink_query (GstPad * pad, GstObject * parent,
886 GstQuery * query)
887 {
888 gboolean res = FALSE;
889 GstNonstreamAudioDecoder *dec;
890 GstNonstreamAudioDecoderClass *klass;
891
892 dec = GST_NONSTREAM_AUDIO_DECODER (parent);
893 klass = GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
894
895 switch (GST_QUERY_TYPE (query)) {
896 case GST_QUERY_ALLOCATION:
897 {
898 if (klass->propose_allocation != NULL)
899 res = klass->propose_allocation (dec, query);
900
901 break;
902 }
903
904 default:
905 res = gst_pad_query_default (pad, parent, query);
906 }
907
908 return res;
909 }
910
911
912 static GstFlowReturn
gst_nonstream_audio_decoder_chain(G_GNUC_UNUSED GstPad * pad,GstObject * parent,GstBuffer * buffer)913 gst_nonstream_audio_decoder_chain (G_GNUC_UNUSED GstPad * pad,
914 GstObject * parent, GstBuffer * buffer)
915 {
916 GstFlowReturn flow_ret = GST_FLOW_OK;
917 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (parent);
918
919 /* query upstream size in bytes to know how many bytes to expect
920 * this is a safety measure to prevent the case when upstream never
921 * reaches EOS (or only after a long time) and we keep loading and
922 * loading and eventually run out of memory */
923 if (dec->upstream_size < 0) {
924 if (!gst_nonstream_audio_decoder_get_upstream_size (dec,
925 &(dec->upstream_size))) {
926 GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL),
927 ("Cannot load - upstream size (in bytes) could not be determined"));
928 return GST_FLOW_ERROR;
929 }
930 }
931
932 if (dec->loaded_mode) {
933 /* media is already loaded - discard any incoming
934 * buffers, since they are not needed */
935
936 GST_DEBUG_OBJECT (dec, "received data after media was loaded - ignoring");
937
938 gst_buffer_unref (buffer);
939 } else {
940 /* accumulate data until end-of-stream or the upstream
941 * size is reached, then load media and commence playback */
942
943 gint64 avail_size;
944
945 gst_adapter_push (dec->input_data_adapter, buffer);
946 avail_size = gst_adapter_available (dec->input_data_adapter);
947 if (avail_size >= dec->upstream_size) {
948 GstBuffer *adapter_buffer =
949 gst_adapter_take_buffer (dec->input_data_adapter, avail_size);
950
951 if (gst_nonstream_audio_decoder_load_from_buffer (dec, adapter_buffer))
952 flow_ret =
953 gst_nonstream_audio_decoder_start_task (dec) ? GST_FLOW_OK :
954 GST_FLOW_ERROR;
955 else
956 flow_ret = GST_FLOW_ERROR;
957 }
958 }
959
960 return flow_ret;
961 }
962
963
964
965 static gboolean
gst_nonstream_audio_decoder_src_event(GstPad * pad,GstObject * parent,GstEvent * event)966 gst_nonstream_audio_decoder_src_event (GstPad * pad, GstObject * parent,
967 GstEvent * event)
968 {
969 gboolean res = FALSE;
970 GstNonstreamAudioDecoder *dec = GST_NONSTREAM_AUDIO_DECODER (parent);
971
972 switch (GST_EVENT_TYPE (event)) {
973 case GST_EVENT_SEEK:
974 {
975 res = gst_nonstream_audio_decoder_do_seek (dec, event);
976 break;
977 }
978
979 case GST_EVENT_TOC_SELECT:
980 {
981 /* NOTE: This event may be received multiple times if it
982 * was originally sent to a bin containing multiple sink
983 * elements (for example, playbin). This is OK and does
984 * not break anything. */
985
986 gchar *uid = NULL;
987 guint subsong_idx = 0;
988 guint32 seqnum;
989
990 gst_event_parse_toc_select (event, &uid);
991
992 if ((uid != NULL)
993 && (sscanf (uid, "nonstream-subsong-%05u", &subsong_idx) == 1)) {
994 seqnum = gst_event_get_seqnum (event);
995
996 GST_DEBUG_OBJECT (dec,
997 "received TOC select event (sequence number %" G_GUINT32_FORMAT
998 "), switching to subsong %u", seqnum, subsong_idx);
999
1000 gst_nonstream_audio_decoder_switch_to_subsong (dec, subsong_idx,
1001 &seqnum);
1002 }
1003
1004 g_free (uid);
1005
1006 res = TRUE;
1007
1008 break;
1009 }
1010
1011 default:
1012 res = gst_pad_event_default (pad, parent, event);
1013 }
1014
1015 return res;
1016 }
1017
1018
1019 static gboolean
gst_nonstream_audio_decoder_src_query(GstPad * pad,GstObject * parent,GstQuery * query)1020 gst_nonstream_audio_decoder_src_query (GstPad * pad, GstObject * parent,
1021 GstQuery * query)
1022 {
1023 gboolean res = FALSE;
1024 GstNonstreamAudioDecoder *dec;
1025 GstNonstreamAudioDecoderClass *klass;
1026
1027 dec = GST_NONSTREAM_AUDIO_DECODER (parent);
1028 klass = GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
1029
1030 switch (GST_QUERY_TYPE (query)) {
1031 case GST_QUERY_DURATION:
1032 {
1033 GstFormat format;
1034 GST_TRACE_OBJECT (parent, "duration query");
1035
1036 if (!(dec->loaded_mode)) {
1037 GST_DEBUG_OBJECT (parent,
1038 "cannot respond to duration query: nothing is loaded yet");
1039 break;
1040 }
1041
1042 GST_TRACE_OBJECT (parent, "parsing duration query");
1043 gst_query_parse_duration (query, &format, NULL);
1044
1045 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1046 if ((format == GST_FORMAT_TIME)
1047 && (dec->subsong_duration != GST_CLOCK_TIME_NONE)) {
1048 GST_DEBUG_OBJECT (parent,
1049 "responding to query with duration %" GST_TIME_FORMAT,
1050 GST_TIME_ARGS (dec->subsong_duration));
1051 gst_query_set_duration (query, format, dec->subsong_duration);
1052 res = TRUE;
1053 } else if (format != GST_FORMAT_TIME)
1054 GST_DEBUG_OBJECT (parent,
1055 "cannot respond to duration query: format is %s, expected time format",
1056 gst_format_get_name (format));
1057 else if (dec->subsong_duration == GST_CLOCK_TIME_NONE)
1058 GST_DEBUG_OBJECT (parent,
1059 "cannot respond to duration query: no valid subsong duration available");
1060 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1061
1062 break;
1063 }
1064
1065 case GST_QUERY_POSITION:
1066 {
1067 GstFormat format;
1068 if (!(dec->loaded_mode)) {
1069 GST_DEBUG_OBJECT (parent,
1070 "cannot respond to position query: nothing is loaded yet");
1071 break;
1072 }
1073
1074 if (klass->tell == NULL) {
1075 GST_DEBUG_OBJECT (parent,
1076 "cannot respond to position query: subclass does not have tell() function defined");
1077 break;
1078 }
1079
1080 gst_query_parse_position (query, &format, NULL);
1081 if (format == GST_FORMAT_TIME) {
1082 GstClockTime pos;
1083
1084 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1085 pos = klass->tell (dec);
1086 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1087
1088 GST_DEBUG_OBJECT (parent,
1089 "position query received with format TIME -> reporting position %"
1090 GST_TIME_FORMAT, GST_TIME_ARGS (pos));
1091 gst_query_set_position (query, format, pos);
1092 res = TRUE;
1093 } else {
1094 GST_DEBUG_OBJECT (parent,
1095 "position query received with unsupported format %s -> not reporting anything",
1096 gst_format_get_name (format));
1097 }
1098
1099 break;
1100 }
1101
1102 case GST_QUERY_SEEKING:
1103 {
1104 GstFormat fmt;
1105 GstClockTime duration;
1106
1107 if (!dec->loaded_mode) {
1108 GST_DEBUG_OBJECT (parent,
1109 "cannot respond to seeking query: nothing is loaded yet");
1110 break;
1111 }
1112
1113 if (klass->seek == NULL) {
1114 GST_DEBUG_OBJECT (parent,
1115 "cannot respond to seeking query: subclass does not have seek() function defined");
1116 break;
1117 }
1118
1119 gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
1120
1121 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1122 duration = dec->subsong_duration;
1123 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1124
1125 if (fmt == GST_FORMAT_TIME) {
1126 GST_DEBUG_OBJECT (parent,
1127 "seeking query received with format TIME -> can seek: yes");
1128 gst_query_set_seeking (query, fmt, TRUE, 0, duration);
1129 res = TRUE;
1130 } else {
1131 GST_DEBUG_OBJECT (parent,
1132 "seeking query received with unsupported format %s -> can seek: no",
1133 gst_format_get_name (fmt));
1134 gst_query_set_seeking (query, fmt, FALSE, 0, -1);
1135 res = TRUE;
1136 }
1137
1138 break;
1139 }
1140
1141 default:
1142 res = gst_pad_query_default (pad, parent, query);
1143 }
1144
1145 return res;
1146 }
1147
1148
1149
1150 static void
gst_nonstream_audio_decoder_set_initial_state(GstNonstreamAudioDecoder * dec)1151 gst_nonstream_audio_decoder_set_initial_state (GstNonstreamAudioDecoder * dec)
1152 {
1153 dec->upstream_size = -1;
1154 dec->loaded_mode = FALSE;
1155
1156 dec->subsong_duration = GST_CLOCK_TIME_NONE;
1157
1158 dec->output_format_changed = FALSE;
1159 gst_audio_info_init (&(dec->output_audio_info));
1160 dec->num_decoded_samples = 0;
1161 dec->cur_pos_in_samples = 0;
1162 gst_segment_init (&(dec->cur_segment), GST_FORMAT_TIME);
1163 dec->discont = FALSE;
1164
1165 dec->toc = NULL;
1166
1167 dec->allocator = NULL;
1168 }
1169
1170
1171 static void
gst_nonstream_audio_decoder_cleanup_state(GstNonstreamAudioDecoder * dec)1172 gst_nonstream_audio_decoder_cleanup_state (GstNonstreamAudioDecoder * dec)
1173 {
1174 gst_adapter_clear (dec->input_data_adapter);
1175
1176 if (dec->allocator != NULL) {
1177 gst_object_unref (dec->allocator);
1178 dec->allocator = NULL;
1179 }
1180
1181 if (dec->toc != NULL) {
1182 gst_toc_unref (dec->toc);
1183 dec->toc = NULL;
1184 }
1185
1186 gst_nonstream_audio_decoder_set_initial_state (dec);
1187 }
1188
1189
1190 static gboolean
gst_nonstream_audio_decoder_negotiate(GstNonstreamAudioDecoder * dec)1191 gst_nonstream_audio_decoder_negotiate (GstNonstreamAudioDecoder * dec)
1192 {
1193 /* must be called with lock */
1194
1195 GstNonstreamAudioDecoderClass *klass;
1196 gboolean res = TRUE;
1197
1198 klass = GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
1199
1200 /* protected by a mutex, since the allocator might currently be in use */
1201 if (klass->negotiate != NULL)
1202 res = klass->negotiate (dec);
1203
1204 return res;
1205 }
1206
1207
1208 static gboolean
gst_nonstream_audio_decoder_negotiate_default(GstNonstreamAudioDecoder * dec)1209 gst_nonstream_audio_decoder_negotiate_default (GstNonstreamAudioDecoder * dec)
1210 {
1211 /* mutex is locked when this is called */
1212
1213 GstCaps *caps;
1214 GstNonstreamAudioDecoderClass *klass;
1215 gboolean res = TRUE;
1216 GstQuery *query = NULL;
1217 GstAllocator *allocator;
1218 GstAllocationParams allocation_params;
1219
1220 g_return_val_if_fail (GST_IS_NONSTREAM_AUDIO_DECODER (dec), FALSE);
1221 g_return_val_if_fail (GST_AUDIO_INFO_IS_VALID (&(dec->output_audio_info)),
1222 FALSE);
1223
1224 klass = GST_NONSTREAM_AUDIO_DECODER_CLASS (G_OBJECT_GET_CLASS (dec));
1225
1226 caps = gst_audio_info_to_caps (&(dec->output_audio_info));
1227
1228 GST_DEBUG_OBJECT (dec, "setting src caps %" GST_PTR_FORMAT, (gpointer) caps);
1229
1230 res = gst_pad_push_event (dec->srcpad, gst_event_new_caps (caps));
1231 /* clear any pending reconfigure flag */
1232 gst_pad_check_reconfigure (dec->srcpad);
1233
1234 if (!res) {
1235 GST_WARNING_OBJECT (dec, "could not push new caps event downstream");
1236 goto done;
1237 }
1238
1239 GST_TRACE_OBJECT (dec, "src caps set");
1240
1241 dec->output_format_changed = FALSE;
1242
1243 query = gst_query_new_allocation (caps, TRUE);
1244 if (!gst_pad_peer_query (dec->srcpad, query)) {
1245 GST_DEBUG_OBJECT (dec, "didn't get downstream ALLOCATION hints");
1246 }
1247
1248 g_assert (klass->decide_allocation != NULL);
1249 res = klass->decide_allocation (dec, query);
1250
1251 GST_DEBUG_OBJECT (dec, "ALLOCATION (%d) params: %" GST_PTR_FORMAT, res,
1252 (gpointer) query);
1253
1254 if (!res)
1255 goto no_decide_allocation;
1256
1257 /* we got configuration from our peer or the decide_allocation method,
1258 * parse them */
1259 if (gst_query_get_n_allocation_params (query) > 0) {
1260 gst_query_parse_nth_allocation_param (query, 0, &allocator,
1261 &allocation_params);
1262 } else {
1263 allocator = NULL;
1264 gst_allocation_params_init (&allocation_params);
1265 }
1266
1267 if (dec->allocator != NULL)
1268 gst_object_unref (dec->allocator);
1269 dec->allocator = allocator;
1270 dec->allocation_params = allocation_params;
1271
1272 done:
1273 if (query != NULL)
1274 gst_query_unref (query);
1275 gst_caps_unref (caps);
1276
1277 return res;
1278
1279 no_decide_allocation:
1280 {
1281 GST_WARNING_OBJECT (dec, "subclass failed to decide allocation");
1282 goto done;
1283 }
1284 }
1285
1286
1287 static gboolean
gst_nonstream_audio_decoder_decide_allocation_default(G_GNUC_UNUSED GstNonstreamAudioDecoder * dec,GstQuery * query)1288 gst_nonstream_audio_decoder_decide_allocation_default (G_GNUC_UNUSED
1289 GstNonstreamAudioDecoder * dec, GstQuery * query)
1290 {
1291 GstAllocator *allocator = NULL;
1292 GstAllocationParams params;
1293 gboolean update_allocator;
1294
1295 /* we got configuration from our peer or the decide_allocation method,
1296 * parse them */
1297 if (gst_query_get_n_allocation_params (query) > 0) {
1298 /* try the allocator */
1299 gst_query_parse_nth_allocation_param (query, 0, &allocator, ¶ms);
1300 update_allocator = TRUE;
1301 } else {
1302 allocator = NULL;
1303 gst_allocation_params_init (¶ms);
1304 update_allocator = FALSE;
1305 }
1306
1307 if (update_allocator)
1308 gst_query_set_nth_allocation_param (query, 0, allocator, ¶ms);
1309 else
1310 gst_query_add_allocation_param (query, allocator, ¶ms);
1311
1312 if (allocator)
1313 gst_object_unref (allocator);
1314
1315 return TRUE;
1316 }
1317
1318
1319 static gboolean
gst_nonstream_audio_decoder_propose_allocation_default(G_GNUC_UNUSED GstNonstreamAudioDecoder * dec,G_GNUC_UNUSED GstQuery * query)1320 gst_nonstream_audio_decoder_propose_allocation_default (G_GNUC_UNUSED
1321 GstNonstreamAudioDecoder * dec, G_GNUC_UNUSED GstQuery * query)
1322 {
1323 return TRUE;
1324 }
1325
1326
1327 static gboolean
gst_nonstream_audio_decoder_get_upstream_size(GstNonstreamAudioDecoder * dec,gint64 * length)1328 gst_nonstream_audio_decoder_get_upstream_size (GstNonstreamAudioDecoder * dec,
1329 gint64 * length)
1330 {
1331 return gst_pad_peer_query_duration (dec->sinkpad, GST_FORMAT_BYTES, length)
1332 && (*length >= 0);
1333 }
1334
1335
1336 static gboolean
gst_nonstream_audio_decoder_load_from_buffer(GstNonstreamAudioDecoder * dec,GstBuffer * buffer)1337 gst_nonstream_audio_decoder_load_from_buffer (GstNonstreamAudioDecoder * dec,
1338 GstBuffer * buffer)
1339 {
1340 gboolean load_ok;
1341 GstClockTime initial_position;
1342 GstNonstreamAudioDecoderClass *klass;
1343 gboolean ret;
1344
1345 klass = GST_NONSTREAM_AUDIO_DECODER_CLASS (G_OBJECT_GET_CLASS (dec));
1346 g_assert (klass->load_from_buffer != NULL);
1347
1348 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1349
1350 GST_LOG_OBJECT (dec, "read %" G_GSIZE_FORMAT " bytes from upstream",
1351 gst_buffer_get_size (buffer));
1352
1353 initial_position = 0;
1354 load_ok =
1355 klass->load_from_buffer (dec, buffer, dec->current_subsong,
1356 dec->subsong_mode, &initial_position, &(dec->output_mode),
1357 &(dec->num_loops));
1358 gst_buffer_unref (buffer);
1359
1360 ret =
1361 gst_nonstream_audio_decoder_finish_load (dec, load_ok, initial_position,
1362 FALSE);
1363
1364 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1365
1366 return ret;
1367 }
1368
1369
1370 static gboolean
gst_nonstream_audio_decoder_load_from_custom(GstNonstreamAudioDecoder * dec)1371 gst_nonstream_audio_decoder_load_from_custom (GstNonstreamAudioDecoder * dec)
1372 {
1373 gboolean load_ok;
1374 GstClockTime initial_position;
1375 GstNonstreamAudioDecoderClass *klass;
1376 gboolean ret;
1377
1378 klass = GST_NONSTREAM_AUDIO_DECODER_CLASS (G_OBJECT_GET_CLASS (dec));
1379 g_assert (klass->load_from_custom != NULL);
1380
1381 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1382
1383 GST_LOG_OBJECT (dec,
1384 "reading song from custom source defined by derived class");
1385
1386 initial_position = 0;
1387 load_ok =
1388 klass->load_from_custom (dec, dec->current_subsong, dec->subsong_mode,
1389 &initial_position, &(dec->output_mode), &(dec->num_loops));
1390
1391 ret =
1392 gst_nonstream_audio_decoder_finish_load (dec, load_ok, initial_position,
1393 TRUE);
1394
1395 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1396
1397 return ret;
1398 }
1399
1400
1401 static gboolean
gst_nonstream_audio_decoder_finish_load(GstNonstreamAudioDecoder * dec,gboolean load_ok,GstClockTime initial_position,gboolean send_stream_start)1402 gst_nonstream_audio_decoder_finish_load (GstNonstreamAudioDecoder * dec,
1403 gboolean load_ok, GstClockTime initial_position, gboolean send_stream_start)
1404 {
1405 /* must be called with lock */
1406
1407 GstNonstreamAudioDecoderClass *klass =
1408 GST_NONSTREAM_AUDIO_DECODER_CLASS (G_OBJECT_GET_CLASS (dec));
1409
1410 GST_TRACE_OBJECT (dec, "enter finish_load");
1411
1412
1413 /* Prerequisites */
1414
1415 if (!load_ok) {
1416 GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("Loading failed"));
1417 return FALSE;
1418 }
1419
1420 if (!GST_AUDIO_INFO_IS_VALID (&(dec->output_audio_info))) {
1421 GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL),
1422 ("Audio info is invalid after loading"));
1423 return FALSE;
1424 }
1425
1426
1427 /* Log the number of available subsongs */
1428 if (klass->get_num_subsongs != NULL)
1429 GST_DEBUG_OBJECT (dec, "%u subsong(s) available",
1430 klass->get_num_subsongs (dec));
1431
1432
1433 /* Set the current subsong (or use the default value) */
1434 if (klass->get_current_subsong != NULL) {
1435 GST_TRACE_OBJECT (dec, "requesting current subsong");
1436 dec->current_subsong = klass->get_current_subsong (dec);
1437 }
1438
1439
1440 /* Handle the subsong duration */
1441 if (klass->get_subsong_duration != NULL) {
1442 GstClockTime duration;
1443 GST_TRACE_OBJECT (dec, "requesting subsong duration");
1444 duration = klass->get_subsong_duration (dec, dec->current_subsong);
1445 gst_nonstream_audio_decoder_update_subsong_duration (dec, duration);
1446 }
1447
1448
1449 /* Send tags downstream (if some exist) */
1450 if (klass->get_subsong_tags != NULL) {
1451 /* Subsong tags available */
1452
1453 GstTagList *tags;
1454 GST_TRACE_OBJECT (dec, "requesting subsong tags");
1455 tags = klass->get_subsong_tags (dec, dec->current_subsong);
1456 if (tags != NULL)
1457 tags = gst_nonstream_audio_decoder_add_main_tags (dec, tags);
1458 if (tags != NULL)
1459 gst_pad_push_event (dec->srcpad, gst_event_new_tag (tags));
1460 } else {
1461 /* No subsong tags - just send main tags out */
1462
1463 GstTagList *tags = gst_tag_list_new_empty ();
1464 tags = gst_nonstream_audio_decoder_add_main_tags (dec, tags);
1465 gst_pad_push_event (dec->srcpad, gst_event_new_tag (tags));
1466 }
1467
1468
1469 /* Send stream start downstream if requested */
1470 if (send_stream_start) {
1471 gchar *stream_id;
1472 GstEvent *event;
1473
1474 stream_id =
1475 gst_pad_create_stream_id (dec->srcpad, GST_ELEMENT_CAST (dec), NULL);
1476 GST_DEBUG_OBJECT (dec, "pushing STREAM_START with stream id \"%s\"",
1477 stream_id);
1478
1479 event = gst_event_new_stream_start (stream_id);
1480 gst_event_set_group_id (event, gst_util_group_id_next ());
1481 gst_pad_push_event (dec->srcpad, event);
1482 g_free (stream_id);
1483 }
1484
1485
1486 /* Update the table of contents */
1487 gst_nonstream_audio_decoder_update_toc (dec, klass);
1488
1489
1490 /* Negotiate output caps and an allocator */
1491 GST_TRACE_OBJECT (dec, "negotiating caps and allocator");
1492 if (!gst_nonstream_audio_decoder_negotiate (dec)) {
1493 GST_ERROR_OBJECT (dec, "negotiation failed - aborting load");
1494 return FALSE;
1495 }
1496
1497
1498 /* Send new segment downstream */
1499 gst_nonstream_audio_decoder_output_new_segment (dec, initial_position);
1500
1501 dec->loaded_mode = TRUE;
1502
1503 GST_TRACE_OBJECT (dec, "exit finish_load");
1504
1505 return TRUE;
1506 }
1507
1508
1509 static gboolean
gst_nonstream_audio_decoder_start_task(GstNonstreamAudioDecoder * dec)1510 gst_nonstream_audio_decoder_start_task (GstNonstreamAudioDecoder * dec)
1511 {
1512 if (!gst_pad_start_task (dec->srcpad,
1513 (GstTaskFunction) gst_nonstream_audio_decoder_output_task, dec,
1514 NULL)) {
1515 GST_ERROR_OBJECT (dec, "could not start decoder output task");
1516 return FALSE;
1517 } else
1518 return TRUE;
1519 }
1520
1521
1522 static gboolean
gst_nonstream_audio_decoder_stop_task(GstNonstreamAudioDecoder * dec)1523 gst_nonstream_audio_decoder_stop_task (GstNonstreamAudioDecoder * dec)
1524 {
1525 if (!gst_pad_stop_task (dec->srcpad)) {
1526 GST_ERROR_OBJECT (dec, "could not stop decoder output task");
1527 return FALSE;
1528 } else
1529 return TRUE;
1530 }
1531
1532
1533 static gboolean
gst_nonstream_audio_decoder_switch_to_subsong(GstNonstreamAudioDecoder * dec,guint new_subsong,guint32 const * seqnum)1534 gst_nonstream_audio_decoder_switch_to_subsong (GstNonstreamAudioDecoder * dec,
1535 guint new_subsong, guint32 const *seqnum)
1536 {
1537 gboolean ret = TRUE;
1538 GstNonstreamAudioDecoderClass *klass =
1539 GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
1540
1541
1542 if (klass->set_current_subsong == NULL) {
1543 /* If set_current_subsong wasn't set by the subclass, then
1544 * subsongs are not supported. It is not an error if this
1545 * function is called in that case, since it might happen
1546 * because the current-subsong property was set (and since
1547 * this is a base class property, it is always available). */
1548 GST_DEBUG_OBJECT (dec, "cannot call set_current_subsong, since it is NULL");
1549 goto finish;
1550 }
1551
1552 if (dec->loaded_mode) {
1553 GstEvent *fevent;
1554 GstClockTime new_position;
1555 GstClockTime new_subsong_duration = GST_CLOCK_TIME_NONE;
1556
1557
1558 /* Check if (a) new_subsong is already the current subsong
1559 * and (b) if new_subsong exceeds the number of available
1560 * subsongs. Do this here, when the song is loaded,
1561 * because prior to loading, the number of subsong is usually
1562 * not known (and the loading process might choose a specific
1563 * subsong to be the current one at the start of playback). */
1564
1565 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1566
1567 if (new_subsong == dec->current_subsong) {
1568 GST_DEBUG_OBJECT (dec,
1569 "subsong %u is already the current subsong - ignoring call",
1570 new_subsong);
1571 goto finish_unlock;
1572 }
1573
1574 if (klass->get_num_subsongs) {
1575 guint num_subsongs = klass->get_num_subsongs (dec);
1576
1577 if (new_subsong >= num_subsongs) {
1578 GST_WARNING_OBJECT (dec,
1579 "subsong %u is out of bounds (there are %u subsongs) - not switching",
1580 new_subsong, num_subsongs);
1581 goto finish_unlock;
1582 }
1583 }
1584
1585 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1586
1587
1588 /* Switching subsongs during playback is very similar to a
1589 * flushing seek. Therefore, the stream lock must be taken,
1590 * flush-start/flush-stop events have to be sent, and
1591 * the pad task has to be restarted. */
1592
1593
1594 fevent = gst_event_new_flush_start ();
1595 if (seqnum != NULL) {
1596 gst_event_set_seqnum (fevent, *seqnum);
1597 GST_DEBUG_OBJECT (dec,
1598 "sending flush start event with sequence number %" G_GUINT32_FORMAT,
1599 *seqnum);
1600 } else
1601 GST_DEBUG_OBJECT (dec, "sending flush start event (no sequence number)");
1602
1603 gst_pad_push_event (dec->srcpad, gst_event_ref (fevent));
1604 /* unlock upstream pull_range */
1605 if (klass->loads_from_sinkpad)
1606 gst_pad_push_event (dec->sinkpad, fevent);
1607 else
1608 gst_event_unref (fevent);
1609
1610
1611 GST_PAD_STREAM_LOCK (dec->srcpad);
1612
1613
1614 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1615
1616
1617 if (!(klass->set_current_subsong (dec, new_subsong, &new_position))) {
1618 /* Switch failed. Do _not_ exit early from here - playback must
1619 * continue from the current subsong, and it cannot do that if
1620 * we exit here. Try getting the current position and proceed as
1621 * if the switch succeeded (but set the return value to FALSE.) */
1622
1623 ret = FALSE;
1624 if (klass->tell)
1625 new_position = klass->tell (dec);
1626 else
1627 new_position = 0;
1628 GST_WARNING_OBJECT (dec, "switching to new subsong %u failed",
1629 new_subsong);
1630 }
1631
1632 /* Flushing seek resets the base time, which means num_decoded_samples
1633 * needs to be set to 0, since it defines the segment.base value */
1634 dec->num_decoded_samples = 0;
1635
1636
1637 fevent = gst_event_new_flush_stop (TRUE);
1638 if (seqnum != NULL) {
1639 gst_event_set_seqnum (fevent, *seqnum);
1640 GST_DEBUG_OBJECT (dec,
1641 "sending flush stop event with sequence number %" G_GUINT32_FORMAT,
1642 *seqnum);
1643 } else
1644 GST_DEBUG_OBJECT (dec, "sending flush stop event (no sequence number)");
1645
1646 gst_pad_push_event (dec->srcpad, gst_event_ref (fevent));
1647 /* unlock upstream pull_range */
1648 if (klass->loads_from_sinkpad)
1649 gst_pad_push_event (dec->sinkpad, fevent);
1650 else
1651 gst_event_unref (fevent);
1652
1653
1654 /* use the new subsong's duration (if one exists) */
1655 if (klass->get_subsong_duration != NULL)
1656 new_subsong_duration = klass->get_subsong_duration (dec, new_subsong);
1657 gst_nonstream_audio_decoder_update_subsong_duration (dec,
1658 new_subsong_duration);
1659
1660 /* create a new segment for the new subsong */
1661 gst_nonstream_audio_decoder_output_new_segment (dec, new_position);
1662
1663 /* use the new subsong's tags (if any exist) */
1664 if (klass->get_subsong_tags != NULL) {
1665 GstTagList *subsong_tags = klass->get_subsong_tags (dec, new_subsong);
1666 if (subsong_tags != NULL)
1667 subsong_tags =
1668 gst_nonstream_audio_decoder_add_main_tags (dec, subsong_tags);
1669 if (subsong_tags != NULL)
1670 gst_pad_push_event (dec->srcpad, gst_event_new_tag (subsong_tags));
1671 }
1672
1673 GST_DEBUG_OBJECT (dec, "successfully switched to new subsong %u",
1674 new_subsong);
1675 dec->current_subsong = new_subsong;
1676
1677
1678 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1679
1680
1681 /* Subsong has been switched, and all necessary events have been
1682 * pushed downstream. Restart srcpad task. */
1683 gst_nonstream_audio_decoder_start_task (dec);
1684
1685 /* Unlock stream, we are done */
1686 GST_PAD_STREAM_UNLOCK (dec->srcpad);
1687 } else {
1688 /* If song hasn't been loaded yet, then playback cannot currently
1689 * been happening. In this case, a "switch" is simple - just store
1690 * the current subsong index. When the song is loaded, it will
1691 * start playing this subsong. */
1692
1693 GST_DEBUG_OBJECT (dec,
1694 "playback hasn't started yet - storing subsong index %u as the current subsong",
1695 new_subsong);
1696
1697 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1698 dec->current_subsong = new_subsong;
1699 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1700 }
1701
1702
1703 finish:
1704 return ret;
1705
1706
1707 finish_unlock:
1708 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1709 goto finish;
1710 }
1711
1712
1713 static void
gst_nonstream_audio_decoder_update_toc(GstNonstreamAudioDecoder * dec,GstNonstreamAudioDecoderClass * klass)1714 gst_nonstream_audio_decoder_update_toc (GstNonstreamAudioDecoder * dec,
1715 GstNonstreamAudioDecoderClass * klass)
1716 {
1717 /* must be called with lock */
1718
1719 guint num_subsongs, i;
1720
1721 if (dec->toc != NULL) {
1722 gst_toc_unref (dec->toc);
1723 dec->toc = NULL;
1724 }
1725
1726 if (klass->get_num_subsongs == NULL)
1727 return;
1728
1729 num_subsongs = klass->get_num_subsongs (dec);
1730 if (num_subsongs <= 1) {
1731 GST_DEBUG_OBJECT (dec, "no need for a TOC since there is only one subsong");
1732 return;
1733 }
1734
1735 dec->toc = gst_toc_new (GST_TOC_SCOPE_GLOBAL);
1736
1737 if (klass->get_main_tags) {
1738 GstTagList *main_tags = klass->get_main_tags (dec);
1739 if (main_tags)
1740 gst_toc_set_tags (dec->toc, main_tags);
1741 }
1742
1743 for (i = 0; i < num_subsongs; ++i) {
1744 gchar *uid;
1745 GstTocEntry *entry;
1746 GstClockTime duration;
1747 GstTagList *tags;
1748
1749 duration =
1750 (klass->get_subsong_duration !=
1751 NULL) ? klass->get_subsong_duration (dec, i) : GST_CLOCK_TIME_NONE;
1752 tags =
1753 (klass->get_subsong_tags != NULL) ? klass->get_subsong_tags (dec,
1754 i) : NULL;
1755 if (!tags)
1756 tags = gst_tag_list_new_empty ();
1757
1758 uid = g_strdup_printf ("nonstream-subsong-%05u", i);
1759 entry = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_TRACK, uid);
1760 /* Set the UID as title tag for TOC entry if no title already present */
1761 gst_tag_list_add (tags, GST_TAG_MERGE_KEEP, GST_TAG_TITLE, uid, NULL);
1762 /* Set the subsong duration as duration tag for TOC entry if no duration already present */
1763 if (duration != GST_CLOCK_TIME_NONE)
1764 gst_tag_list_add (tags, GST_TAG_MERGE_KEEP, GST_TAG_DURATION, duration,
1765 NULL);
1766
1767 /* FIXME: TOC does not allow GST_CLOCK_TIME_NONE as a stop value */
1768 if (duration == GST_CLOCK_TIME_NONE)
1769 duration = G_MAXINT64;
1770
1771 /* Subsongs always start at 00:00 */
1772 gst_toc_entry_set_start_stop_times (entry, 0, duration);
1773 gst_toc_entry_set_tags (entry, tags);
1774
1775 /* NOTE: *not* adding loop count via gst_toc_entry_set_loop(), since
1776 * in GstNonstreamAudioDecoder, looping is a playback property, not
1777 * a property of the subsongs themselves */
1778
1779 GST_DEBUG_OBJECT (dec,
1780 "new toc entry: uid: \"%s\" duration: %" GST_TIME_FORMAT " tags: %"
1781 GST_PTR_FORMAT, uid, GST_TIME_ARGS (duration), (gpointer) tags);
1782
1783 gst_toc_append_entry (dec->toc, entry);
1784
1785 g_free (uid);
1786 }
1787
1788 gst_pad_push_event (dec->srcpad, gst_event_new_toc (dec->toc, FALSE));
1789 }
1790
1791
1792 static void
gst_nonstream_audio_decoder_update_subsong_duration(GstNonstreamAudioDecoder * dec,GstClockTime duration)1793 gst_nonstream_audio_decoder_update_subsong_duration (GstNonstreamAudioDecoder *
1794 dec, GstClockTime duration)
1795 {
1796 /* must be called with lock */
1797
1798 dec->subsong_duration = duration;
1799 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1800 gst_element_post_message (GST_ELEMENT (dec),
1801 gst_message_new_duration_changed (GST_OBJECT (dec)));
1802 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1803 }
1804
1805
1806 static void
gst_nonstream_audio_decoder_output_new_segment(GstNonstreamAudioDecoder * dec,GstClockTime start_position)1807 gst_nonstream_audio_decoder_output_new_segment (GstNonstreamAudioDecoder * dec,
1808 GstClockTime start_position)
1809 {
1810 /* must be called with lock */
1811
1812 GstSegment segment;
1813
1814 gst_segment_init (&segment, GST_FORMAT_TIME);
1815
1816 segment.base =
1817 gst_util_uint64_scale_int (dec->num_decoded_samples, GST_SECOND,
1818 dec->output_audio_info.rate);
1819 segment.start = 0;
1820 segment.time = start_position;
1821 segment.offset = 0;
1822 segment.position = 0;
1823
1824 /* note that num_decoded_samples isn't being reset; it is the
1825 * analogue to the segment base value, and thus is supposed to
1826 * monotonically increase, except for when a flushing seek happens
1827 * (since a flushing seek is supposed to be a fresh restart for
1828 * the whole pipeline) */
1829 dec->cur_pos_in_samples = 0;
1830
1831 /* stop/duration members are not set, on purpose - in case of loops,
1832 * new segments will be generated, which automatically put an implicit
1833 * end on the current segment (the segment implicitely "ends" when the
1834 * new one starts), and having a stop value might cause very slight
1835 * gaps occasionally due to slight jitter in the calculation of
1836 * base times etc. */
1837
1838 GST_DEBUG_OBJECT (dec,
1839 "output new segment with base %" GST_TIME_FORMAT " time %"
1840 GST_TIME_FORMAT, GST_TIME_ARGS (segment.base),
1841 GST_TIME_ARGS (segment.time));
1842
1843 dec->cur_segment = segment;
1844 dec->discont = TRUE;
1845
1846 gst_pad_push_event (dec->srcpad, gst_event_new_segment (&segment));
1847 }
1848
1849
1850 static gboolean
gst_nonstream_audio_decoder_do_seek(GstNonstreamAudioDecoder * dec,GstEvent * event)1851 gst_nonstream_audio_decoder_do_seek (GstNonstreamAudioDecoder * dec,
1852 GstEvent * event)
1853 {
1854 gboolean res;
1855 gdouble rate;
1856 GstFormat format;
1857 GstSeekFlags flags;
1858 GstSeekType start_type, stop_type;
1859 GstClockTime new_position;
1860 gint64 start, stop;
1861 GstSegment segment;
1862 guint32 seqnum;
1863 gboolean flush;
1864 GstNonstreamAudioDecoderClass *klass =
1865 GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
1866
1867 if (klass->seek == NULL) {
1868 GST_DEBUG_OBJECT (dec,
1869 "cannot seek: subclass does not have seek() function defined");
1870 return FALSE;
1871 }
1872
1873 if (!dec->loaded_mode) {
1874 GST_DEBUG_OBJECT (dec, "nothing loaded yet - cannot seek");
1875 return FALSE;
1876 }
1877
1878 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1879 if (!GST_AUDIO_INFO_IS_VALID (&(dec->output_audio_info))) {
1880 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1881 GST_DEBUG_OBJECT (dec, "no valid output audioinfo present - cannot seek");
1882 return FALSE;
1883 }
1884 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1885
1886
1887 GST_DEBUG_OBJECT (dec, "starting seek");
1888
1889 gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start,
1890 &stop_type, &stop);
1891 seqnum = gst_event_get_seqnum (event);
1892
1893 GST_DEBUG_OBJECT (dec,
1894 "seek event data: "
1895 "rate %f format %s "
1896 "start type %s start %" GST_TIME_FORMAT " "
1897 "stop type %s stop %" GST_TIME_FORMAT,
1898 rate, gst_format_get_name (format),
1899 get_seek_type_name (start_type), GST_TIME_ARGS (start),
1900 get_seek_type_name (stop_type), GST_TIME_ARGS (stop)
1901 );
1902
1903 if (format != GST_FORMAT_TIME) {
1904 GST_DEBUG_OBJECT (dec, "seeking is only supported in TIME format");
1905 return FALSE;
1906 }
1907
1908 if (rate < 0) {
1909 GST_DEBUG_OBJECT (dec, "only positive seek rates are supported");
1910 return FALSE;
1911 }
1912
1913 flush = ((flags & GST_SEEK_FLAG_FLUSH) == GST_SEEK_FLAG_FLUSH);
1914
1915 if (flush) {
1916 GstEvent *fevent = gst_event_new_flush_start ();
1917 gst_event_set_seqnum (fevent, seqnum);
1918
1919 GST_DEBUG_OBJECT (dec,
1920 "sending flush start event with sequence number %" G_GUINT32_FORMAT,
1921 seqnum);
1922
1923 gst_pad_push_event (dec->srcpad, gst_event_ref (fevent));
1924 /* unlock upstream pull_range */
1925 if (klass->loads_from_sinkpad)
1926 gst_pad_push_event (dec->sinkpad, fevent);
1927 else
1928 gst_event_unref (fevent);
1929 } else
1930 gst_pad_pause_task (dec->srcpad);
1931
1932 GST_PAD_STREAM_LOCK (dec->srcpad);
1933
1934 segment = dec->cur_segment;
1935
1936 if (!gst_segment_do_seek (&segment,
1937 rate, format, flags, start_type, start, stop_type, stop, NULL)) {
1938 GST_DEBUG_OBJECT (dec, "could not seek in segment");
1939 GST_PAD_STREAM_UNLOCK (dec->srcpad);
1940 return FALSE;
1941 }
1942
1943 GST_DEBUG_OBJECT (dec,
1944 "segment data: "
1945 "seek event data: "
1946 "rate %f applied rate %f "
1947 "format %s "
1948 "base %" GST_TIME_FORMAT " "
1949 "offset %" GST_TIME_FORMAT " "
1950 "start %" GST_TIME_FORMAT " "
1951 "stop %" GST_TIME_FORMAT " "
1952 "time %" GST_TIME_FORMAT " "
1953 "position %" GST_TIME_FORMAT " "
1954 "duration %" GST_TIME_FORMAT,
1955 segment.rate, segment.applied_rate,
1956 gst_format_get_name (segment.format),
1957 GST_TIME_ARGS (segment.base),
1958 GST_TIME_ARGS (segment.offset),
1959 GST_TIME_ARGS (segment.start),
1960 GST_TIME_ARGS (segment.stop),
1961 GST_TIME_ARGS (segment.time),
1962 GST_TIME_ARGS (segment.position), GST_TIME_ARGS (segment.duration)
1963 );
1964
1965 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
1966
1967 new_position = segment.position;
1968 res = klass->seek (dec, &new_position);
1969 segment.position = new_position;
1970
1971 dec->cur_segment = segment;
1972 dec->cur_pos_in_samples =
1973 gst_util_uint64_scale_int (dec->cur_segment.position,
1974 dec->output_audio_info.rate, GST_SECOND);
1975 dec->num_decoded_samples = 0;
1976
1977 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
1978
1979 if (flush) {
1980 GstEvent *fevent = gst_event_new_flush_stop (TRUE);
1981 gst_event_set_seqnum (fevent, seqnum);
1982
1983 GST_DEBUG_OBJECT (dec,
1984 "sending flush stop event with sequence number %" G_GUINT32_FORMAT,
1985 seqnum);
1986
1987 gst_pad_push_event (dec->srcpad, gst_event_ref (fevent));
1988 if (klass->loads_from_sinkpad)
1989 gst_pad_push_event (dec->sinkpad, fevent);
1990 else
1991 gst_event_unref (fevent);
1992 }
1993
1994 if (res) {
1995 if (flags & GST_SEEK_FLAG_SEGMENT) {
1996 GST_DEBUG_OBJECT (dec, "posting SEGMENT_START message");
1997
1998 gst_element_post_message (GST_ELEMENT (dec),
1999 gst_message_new_segment_start (GST_OBJECT (dec),
2000 GST_FORMAT_TIME, segment.start)
2001 );
2002 }
2003
2004 gst_pad_push_event (dec->srcpad, gst_event_new_segment (&segment));
2005
2006 GST_INFO_OBJECT (dec, "seek succeeded");
2007
2008 gst_nonstream_audio_decoder_start_task (dec);
2009 } else {
2010 GST_WARNING_OBJECT (dec, "seek failed");
2011 }
2012
2013 GST_PAD_STREAM_UNLOCK (dec->srcpad);
2014
2015 gst_event_unref (event);
2016
2017 return res;
2018 }
2019
2020
2021 static GstTagList *
gst_nonstream_audio_decoder_add_main_tags(GstNonstreamAudioDecoder * dec,GstTagList * tags)2022 gst_nonstream_audio_decoder_add_main_tags (GstNonstreamAudioDecoder * dec,
2023 GstTagList * tags)
2024 {
2025 GstNonstreamAudioDecoderClass *klass =
2026 GST_NONSTREAM_AUDIO_DECODER_GET_CLASS (dec);
2027
2028 if (!klass->get_main_tags)
2029 return tags;
2030
2031 tags = gst_tag_list_make_writable (tags);
2032 if (tags) {
2033 GstClockTime duration;
2034 GstTagList *main_tags;
2035
2036 /* Get main tags. If some exist, merge them with the given tags,
2037 * and return the merged result. Otherwise, just return the given tags. */
2038 main_tags = klass->get_main_tags (dec);
2039 if (main_tags) {
2040 tags = gst_tag_list_merge (main_tags, tags, GST_TAG_MERGE_REPLACE);
2041 gst_tag_list_unref (main_tags);
2042 }
2043
2044 /* Add subsong duration if available */
2045 duration = dec->subsong_duration;
2046 if (GST_CLOCK_TIME_IS_VALID (duration))
2047 gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_DURATION, duration,
2048 NULL);
2049
2050 return tags;
2051 } else {
2052 GST_ERROR_OBJECT (dec, "could not make subsong tags writable");
2053 return NULL;
2054 }
2055 }
2056
2057
2058 static void
gst_nonstream_audio_decoder_output_task(GstNonstreamAudioDecoder * dec)2059 gst_nonstream_audio_decoder_output_task (GstNonstreamAudioDecoder * dec)
2060 {
2061 GstFlowReturn flow;
2062 GstBuffer *outbuf;
2063 guint num_samples;
2064
2065 GstNonstreamAudioDecoderClass *klass;
2066 klass = GST_NONSTREAM_AUDIO_DECODER_CLASS (G_OBJECT_GET_CLASS (dec));
2067 g_assert (klass->decode != NULL);
2068
2069 GST_NONSTREAM_AUDIO_DECODER_LOCK_MUTEX (dec);
2070
2071 /* perform the actual decoding */
2072 if (!(klass->decode (dec, &outbuf, &num_samples))) {
2073 /* EOS case */
2074 GST_INFO_OBJECT (dec, "decode() reports end -> sending EOS event");
2075 gst_pad_push_event (dec->srcpad, gst_event_new_eos ());
2076 goto pause_unlock;
2077 }
2078
2079 if (outbuf == NULL) {
2080 GST_ERROR_OBJECT (outbuf, "decode() produced NULL buffer");
2081 goto pause_unlock;
2082 }
2083
2084 /* set the buffer's metadata */
2085 GST_BUFFER_DURATION (outbuf) =
2086 gst_util_uint64_scale_int (num_samples, GST_SECOND,
2087 dec->output_audio_info.rate);
2088 GST_BUFFER_OFFSET (outbuf) = dec->cur_pos_in_samples;
2089 GST_BUFFER_OFFSET_END (outbuf) = dec->cur_pos_in_samples + num_samples;
2090 GST_BUFFER_PTS (outbuf) =
2091 gst_util_uint64_scale_int (dec->cur_pos_in_samples, GST_SECOND,
2092 dec->output_audio_info.rate);
2093 GST_BUFFER_DTS (outbuf) = GST_BUFFER_PTS (outbuf);
2094
2095 if (G_UNLIKELY (dec->discont)) {
2096 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
2097 dec->discont = FALSE;
2098 }
2099
2100 GST_LOG_OBJECT (dec,
2101 "output buffer stats: num_samples = %u duration = %" GST_TIME_FORMAT
2102 " cur_pos_in_samples = %" G_GUINT64_FORMAT " timestamp = %"
2103 GST_TIME_FORMAT, num_samples,
2104 GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)), dec->cur_pos_in_samples,
2105 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf))
2106 );
2107
2108 /* increment sample counters */
2109 dec->cur_pos_in_samples += num_samples;
2110 dec->num_decoded_samples += num_samples;
2111
2112 /* the decode() call might have set a new output format -> renegotiate
2113 * before sending the new buffer downstream */
2114 if (G_UNLIKELY (dec->output_format_changed ||
2115 (GST_AUDIO_INFO_IS_VALID (&(dec->output_audio_info))
2116 && gst_pad_check_reconfigure (dec->srcpad))
2117 )) {
2118 if (!gst_nonstream_audio_decoder_negotiate (dec)) {
2119 gst_buffer_unref (outbuf);
2120 GST_LOG_OBJECT (dec, "could not push output buffer: negotiation failed");
2121 goto pause_unlock;
2122 }
2123 }
2124
2125 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
2126
2127 /* push new samples downstream
2128 * no need to unref buffer - gst_pad_push() does it in
2129 * all cases (success and failure) */
2130 flow = gst_pad_push (dec->srcpad, outbuf);
2131 switch (flow) {
2132 case GST_FLOW_OK:
2133 break;
2134
2135 case GST_FLOW_FLUSHING:
2136 GST_LOG_OBJECT (dec, "pipeline is being flushed - pausing task");
2137 goto pause;
2138
2139 case GST_FLOW_NOT_NEGOTIATED:
2140 if (gst_pad_needs_reconfigure (dec->srcpad)) {
2141 GST_DEBUG_OBJECT (dec, "trying to renegotiate");
2142 break;
2143 }
2144 /* fallthrough to default */
2145
2146 default:
2147 GST_ELEMENT_ERROR (dec, STREAM, FAILED, ("Internal data flow error."),
2148 ("streaming task paused, reason %s (%d)", gst_flow_get_name (flow),
2149 flow));
2150 }
2151
2152 return;
2153
2154 pause:
2155 GST_INFO_OBJECT (dec, "pausing task");
2156 /* NOT using stop_task here, since that would cause a deadlock.
2157 * See the gst_pad_stop_task() documentation for details. */
2158 gst_pad_pause_task (dec->srcpad);
2159 return;
2160 pause_unlock:
2161 GST_NONSTREAM_AUDIO_DECODER_UNLOCK_MUTEX (dec);
2162 goto pause;
2163 }
2164
2165
2166 static char const *
get_seek_type_name(GstSeekType seek_type)2167 get_seek_type_name (GstSeekType seek_type)
2168 {
2169 switch (seek_type) {
2170 case GST_SEEK_TYPE_NONE:
2171 return "none";
2172 case GST_SEEK_TYPE_SET:
2173 return "set";
2174 case GST_SEEK_TYPE_END:
2175 return "end";
2176 default:
2177 return "<unknown>";
2178 }
2179 }
2180
2181
2182
2183
2184 /**
2185 * gst_nonstream_audio_decoder_handle_loop:
2186 * @dec: a #GstNonstreamAudioDecoder
2187 * @new_position New position the next loop starts with
2188 *
2189 * Reports that a loop has been completed and creates a new appropriate
2190 * segment for the next loop.
2191 *
2192 * @new_position exists because a loop may not start at the beginning.
2193 *
2194 * This function is only useful for subclasses which can be in the
2195 * GST_NONSTREAM_AUDIO_OUTPUT_MODE_LOOPING output mode, since in the
2196 * GST_NONSTREAM_AUDIO_OUTPUT_MODE_STEADY output mode, this function
2197 * does nothing. See #GstNonstreamAudioOutputMode for more details.
2198 *
2199 * The subclass calls this during playback when it loops. It produces
2200 * a new segment with updated base time and internal time values, to allow
2201 * for seamless looping. It does *not* check the number of elapsed loops;
2202 * this is up the subclass.
2203 *
2204 * Note that if this function is called, then it must be done after the
2205 * last samples of the loop have been decoded and pushed downstream.
2206 *
2207 * This function must be called with the decoder mutex lock held, since it
2208 * is typically called from within @decode (which in turn are called with
2209 * the lock already held).
2210 */
2211 void
gst_nonstream_audio_decoder_handle_loop(GstNonstreamAudioDecoder * dec,GstClockTime new_position)2212 gst_nonstream_audio_decoder_handle_loop (GstNonstreamAudioDecoder * dec,
2213 GstClockTime new_position)
2214 {
2215 if (dec->output_mode == GST_NONSTREAM_AUDIO_OUTPUT_MODE_STEADY) {
2216 /* handle_loop makes no sense with open-ended decoders */
2217 GST_WARNING_OBJECT (dec,
2218 "ignoring handle_loop() call, since the decoder output mode is \"steady\"");
2219 return;
2220 }
2221
2222 GST_DEBUG_OBJECT (dec,
2223 "handle_loop() invoked with new_position = %" GST_TIME_FORMAT,
2224 GST_TIME_ARGS (new_position));
2225
2226 dec->discont = TRUE;
2227
2228 gst_nonstream_audio_decoder_output_new_segment (dec, new_position);
2229 }
2230
2231
2232 /**
2233 * gst_nonstream_audio_decoder_set_output_format:
2234 * @dec: a #GstNonstreamAudioDecoder
2235 * @audio_info: Valid audio info structure containing the output format
2236 *
2237 * Sets the output caps by means of a GstAudioInfo structure.
2238 *
2239 * This must be called latest in the first @decode call, to ensure src caps are
2240 * set before decoded samples are sent downstream. Typically, this is called
2241 * from inside @load_from_buffer or @load_from_custom.
2242 *
2243 * This function must be called with the decoder mutex lock held, since it
2244 * is typically called from within the aforementioned vfuncs (which in turn
2245 * are called with the lock already held).
2246 *
2247 * Returns: TRUE if setting the output format succeeded, FALSE otherwise
2248 */
2249 gboolean
gst_nonstream_audio_decoder_set_output_format(GstNonstreamAudioDecoder * dec,GstAudioInfo const * audio_info)2250 gst_nonstream_audio_decoder_set_output_format (GstNonstreamAudioDecoder * dec,
2251 GstAudioInfo const *audio_info)
2252 {
2253 GstCaps *caps;
2254 GstCaps *templ_caps;
2255 gboolean caps_ok;
2256 gboolean res = TRUE;
2257
2258 g_return_val_if_fail (GST_IS_NONSTREAM_AUDIO_DECODER (dec), FALSE);
2259
2260 caps = gst_audio_info_to_caps (audio_info);
2261 if (caps == NULL) {
2262 GST_WARNING_OBJECT (dec, "Could not create caps out of audio info");
2263 return FALSE;
2264 }
2265
2266 templ_caps = gst_pad_get_pad_template_caps (dec->srcpad);
2267 caps_ok = gst_caps_is_subset (caps, templ_caps);
2268
2269 if (caps_ok) {
2270 dec->output_audio_info = *audio_info;
2271 dec->output_format_changed = TRUE;
2272
2273 GST_INFO_OBJECT (dec, "setting output format to %" GST_PTR_FORMAT,
2274 (gpointer) caps);
2275 } else {
2276 GST_WARNING_OBJECT (dec,
2277 "requested output format %" GST_PTR_FORMAT " does not match template %"
2278 GST_PTR_FORMAT, (gpointer) caps, (gpointer) templ_caps);
2279
2280 res = FALSE;
2281 }
2282
2283 gst_caps_unref (caps);
2284 gst_caps_unref (templ_caps);
2285
2286 return res;
2287 }
2288
2289
2290 /**
2291 * gst_nonstream_audio_decoder_set_output_format_simple:
2292 * @dec: a #GstNonstreamAudioDecoder
2293 * @sample_rate: Output sample rate to use, in Hz
2294 * @sample_format: Output sample format to use
2295 * @num_channels: Number of output channels to use
2296 *
2297 * Convenience function; sets the output caps by means of common parameters.
2298 *
2299 * Internally, this fills a GstAudioInfo structure and calls
2300 * gst_nonstream_audio_decoder_set_output_format().
2301 *
2302 * Returns: TRUE if setting the output format succeeded, FALSE otherwise
2303 */
2304 gboolean
gst_nonstream_audio_decoder_set_output_format_simple(GstNonstreamAudioDecoder * dec,guint sample_rate,GstAudioFormat sample_format,guint num_channels)2305 gst_nonstream_audio_decoder_set_output_format_simple (GstNonstreamAudioDecoder *
2306 dec, guint sample_rate, GstAudioFormat sample_format, guint num_channels)
2307 {
2308 GstAudioInfo output_audio_info;
2309
2310 gst_audio_info_init (&output_audio_info);
2311
2312 gst_audio_info_set_format (&output_audio_info,
2313 sample_format, sample_rate, num_channels, NULL);
2314
2315 return gst_nonstream_audio_decoder_set_output_format (dec,
2316 &output_audio_info);
2317 }
2318
2319
2320 /**
2321 * gst_nonstream_audio_decoder_get_downstream_info:
2322 * @dec: a #GstNonstreamAudioDecoder
2323 * @format: #GstAudioFormat value to fill with a sample format
2324 * @sample_rate: Integer to fill with a sample rate
2325 * @num_channels: Integer to fill with a channel count
2326 *
2327 * Gets sample format, sample rate, channel count from the allowed srcpad caps.
2328 *
2329 * This is useful for when the subclass wishes to adjust one or more output
2330 * parameters to whatever downstream is supporting. For example, the output
2331 * sample rate is often a freely adjustable value in module players.
2332 *
2333 * This function tries to find a value inside the srcpad peer's caps for
2334 * @format, @sample_rate, @num_chnanels . Any of these can be NULL; they
2335 * (and the corresponding downstream caps) are then skipped while retrieving
2336 * information. Non-fixated caps are fixated first; the value closest to
2337 * their present value is then chosen. For example, if the variables pointed
2338 * to by the arguments are GST_AUDIO_FORMAT_16, 48000 Hz, and 2 channels,
2339 * and the downstream caps are:
2340 *
2341 * "audio/x-raw, format={S16LE,S32LE}, rate=[1,32000], channels=[1,MAX]"
2342 *
2343 * Then @format and @channels stay the same, while @sample_rate is set to 32000 Hz.
2344 * This way, the initial values the the variables pointed to by the arguments
2345 * are set to can be used as default output values. Note that if no downstream
2346 * caps can be retrieved, then this function does nothing, therefore it is
2347 * necessary to ensure that @format, @sample_rate, and @channels have valid
2348 * initial values.
2349 *
2350 * Decoder lock is not held by this function, so it can be called from within
2351 * any of the class vfuncs.
2352 */
2353 void
gst_nonstream_audio_decoder_get_downstream_info(GstNonstreamAudioDecoder * dec,GstAudioFormat * format,gint * sample_rate,gint * num_channels)2354 gst_nonstream_audio_decoder_get_downstream_info (GstNonstreamAudioDecoder * dec,
2355 GstAudioFormat * format, gint * sample_rate, gint * num_channels)
2356 {
2357 GstCaps *allowed_srccaps;
2358 guint structure_nr, num_structures;
2359 gboolean ds_format_found = FALSE, ds_rate_found = FALSE, ds_channels_found =
2360 FALSE;
2361
2362 g_return_if_fail (GST_IS_NONSTREAM_AUDIO_DECODER (dec));
2363
2364 allowed_srccaps = gst_pad_get_allowed_caps (dec->srcpad);
2365 if (allowed_srccaps == NULL) {
2366 GST_INFO_OBJECT (dec,
2367 "no downstream caps available - not modifying arguments");
2368 return;
2369 }
2370
2371 num_structures = gst_caps_get_size (allowed_srccaps);
2372 GST_DEBUG_OBJECT (dec, "%u structure(s) in downstream caps", num_structures);
2373 for (structure_nr = 0; structure_nr < num_structures; ++structure_nr) {
2374 GstStructure *structure;
2375
2376 ds_format_found = FALSE;
2377 ds_rate_found = FALSE;
2378 ds_channels_found = FALSE;
2379
2380 structure = gst_caps_get_structure (allowed_srccaps, structure_nr);
2381
2382 /* If all formats which need to be queried are present in the structure,
2383 * check its contents */
2384 if (((format == NULL) || gst_structure_has_field (structure, "format")) &&
2385 ((sample_rate == NULL) || gst_structure_has_field (structure, "rate"))
2386 && ((num_channels == NULL)
2387 || gst_structure_has_field (structure, "channels"))) {
2388 gint fixated_sample_rate;
2389 gint fixated_num_channels;
2390 GstAudioFormat fixated_format = 0;
2391 GstStructure *fixated_str;
2392 gboolean passed = TRUE;
2393
2394 /* Make a copy of the structure, since we need to modify
2395 * (fixate) values inside */
2396 fixated_str = gst_structure_copy (structure);
2397
2398 /* Try to fixate and retrieve the sample format */
2399 if (passed && (format != NULL)) {
2400 passed = FALSE;
2401
2402 if ((gst_structure_get_field_type (fixated_str,
2403 "format") == G_TYPE_STRING)
2404 || gst_structure_fixate_field_string (fixated_str, "format",
2405 gst_audio_format_to_string (*format))) {
2406 gchar const *fmt_str =
2407 gst_structure_get_string (fixated_str, "format");
2408 if (fmt_str
2409 && ((fixated_format =
2410 gst_audio_format_from_string (fmt_str)) !=
2411 GST_AUDIO_FORMAT_UNKNOWN)) {
2412 GST_DEBUG_OBJECT (dec, "found fixated format: %s", fmt_str);
2413 ds_format_found = TRUE;
2414 passed = TRUE;
2415 }
2416 }
2417 }
2418
2419 /* Try to fixate and retrieve the sample rate */
2420 if (passed && (sample_rate != NULL)) {
2421 passed = FALSE;
2422
2423 if ((gst_structure_get_field_type (fixated_str, "rate") == G_TYPE_INT)
2424 || gst_structure_fixate_field_nearest_int (fixated_str, "rate",
2425 *sample_rate)) {
2426 if (gst_structure_get_int (fixated_str, "rate", &fixated_sample_rate)) {
2427 GST_DEBUG_OBJECT (dec, "found fixated sample rate: %d",
2428 fixated_sample_rate);
2429 ds_rate_found = TRUE;
2430 passed = TRUE;
2431 }
2432 }
2433 }
2434
2435 /* Try to fixate and retrieve the channel count */
2436 if (passed && (num_channels != NULL)) {
2437 passed = FALSE;
2438
2439 if ((gst_structure_get_field_type (fixated_str,
2440 "channels") == G_TYPE_INT)
2441 || gst_structure_fixate_field_nearest_int (fixated_str, "channels",
2442 *num_channels)) {
2443 if (gst_structure_get_int (fixated_str, "channels",
2444 &fixated_num_channels)) {
2445 GST_DEBUG_OBJECT (dec, "found fixated channel count: %d",
2446 fixated_num_channels);
2447 ds_channels_found = TRUE;
2448 passed = TRUE;
2449 }
2450 }
2451 }
2452
2453 gst_structure_free (fixated_str);
2454
2455 if (ds_format_found && ds_rate_found && ds_channels_found) {
2456 *format = fixated_format;
2457 *sample_rate = fixated_sample_rate;
2458 *num_channels = fixated_num_channels;
2459 break;
2460 }
2461 }
2462 }
2463
2464 gst_caps_unref (allowed_srccaps);
2465
2466 if ((format != NULL) && !ds_format_found)
2467 GST_INFO_OBJECT (dec,
2468 "downstream did not specify format - using default (%s)",
2469 gst_audio_format_to_string (*format));
2470 if ((sample_rate != NULL) && !ds_rate_found)
2471 GST_INFO_OBJECT (dec,
2472 "downstream did not specify sample rate - using default (%d Hz)",
2473 *sample_rate);
2474 if ((num_channels != NULL) && !ds_channels_found)
2475 GST_INFO_OBJECT (dec,
2476 "downstream did not specify number of channels - using default (%d channels)",
2477 *num_channels);
2478 }
2479
2480
2481 /**
2482 * gst_nonstream_audio_decoder_allocate_output_buffer:
2483 * @dec: Decoder instance
2484 * @size: Size of the output buffer, in bytes
2485 *
2486 * Allocates an output buffer with the internally configured buffer pool.
2487 *
2488 * This function may only be called from within @load_from_buffer,
2489 * @load_from_custom, and @decode.
2490 *
2491 * Returns: Newly allocated output buffer, or NULL if allocation failed
2492 */
2493 GstBuffer *
gst_nonstream_audio_decoder_allocate_output_buffer(GstNonstreamAudioDecoder * dec,gsize size)2494 gst_nonstream_audio_decoder_allocate_output_buffer (GstNonstreamAudioDecoder *
2495 dec, gsize size)
2496 {
2497 if (G_UNLIKELY (dec->output_format_changed ||
2498 (GST_AUDIO_INFO_IS_VALID (&(dec->output_audio_info))
2499 && gst_pad_check_reconfigure (dec->srcpad))
2500 )) {
2501 /* renegotiate if necessary, before allocating,
2502 * to make sure the right allocator and the right allocation
2503 * params are used */
2504 if (!gst_nonstream_audio_decoder_negotiate (dec)) {
2505 GST_ERROR_OBJECT (dec,
2506 "could not allocate output buffer because negotation failed");
2507 return NULL;
2508 }
2509 }
2510
2511 return gst_buffer_new_allocate (dec->allocator, size,
2512 &(dec->allocation_params));
2513 }
2514