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, &params);
1300     update_allocator = TRUE;
1301   } else {
1302     allocator = NULL;
1303     gst_allocation_params_init (&params);
1304     update_allocator = FALSE;
1305   }
1306 
1307   if (update_allocator)
1308     gst_query_set_nth_allocation_param (query, 0, allocator, &params);
1309   else
1310     gst_query_add_allocation_param (query, allocator, &params);
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