1 /* GStreamer
2 * Copyright (C) <2016> 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 * SECTION:element-rawaudioparse
22 * @title: rawaudioparse
23 *
24 * This element parses incoming data as raw audio samples and timestamps it.
25 * It also handles seek queries in said raw audio data, and ensures that output
26 * buffers contain an integer number of samples, even if the input buffers don't.
27 * For example, with sample format S16LE and 2 channels, an input buffer of 411
28 * bytes contains 102.75 samples. rawaudioparse will then output 102 samples
29 * (= 408 bytes) and keep the remaining 3 bytes. These will then be prepended to
30 * the next input data.
31 *
32 * Currently, this parser supports raw data in a-law, mu-law, or linear PCM format.
33 *
34 * To facilitate operation with the unalignedaudioparse element, rawaudioparse
35 * supports the "audio/x-unaligned-raw" media type. This is treated identically to
36 * "audio/x-raw", except that it is used by source elements which do not guarantee
37 * that the buffers they push out are timestamped and contain an integer amount of
38 * samples (see the 411 bytes example above). By using a different media type, it
39 * is guaranteed that unalignedaudioparse is autoplugged, making sure that the
40 * autoplugged chain does not push unparsed content downstream. The source caps'
41 * media type with linear PCM data is always "audio/x-raw", even if the sink caps
42 * use "audio/x-unaligned-raw".
43 *
44 * The channel-positions property can be used to set explicit position information
45 * for each channel. If the array that is passed to this property does not match
46 * the number of channels indicated by num-channels, then said number of channels
47 * is updated to the array length. If channel-positions is NULL, then the default
48 * GStreamer positioning is used. This property is also useful for swapping left
49 * and right in a stereo signal for example.
50 *
51 * ## Example pipelines
52 * |[
53 * gst-launch-1.0 souphttpsrc http://my-dlna-server/track.l16 \
54 * rawaudioparse ! audioconvert ! audioresample ! autoaudiosink
55 * ]|
56 * Receive L16 data from a DLNA server, parse and timestamp it with
57 * rawaudioparse, and play it. use-sink-caps is set to true since souphttpsrc
58 * will set its source pad's caps to audio/x-unaligned-raw for the L16 stream.
59 * |[
60 * gst-launch-1.0 filesrc location=audio.raw ! rawaudioparse use-sink-caps=false \
61 * format=pcm pcm-format=s16le sample-rate=48000 num-channels=2 \
62 * audioconvert ! audioresample ! autoaudiosink
63 * ]|
64 * Read raw data from a local file and parse it as PCM data with 48000 Hz sample
65 * rate, signed 16 bit integer samples, and 2 channels. use-sink-caps is set to
66 * false to ensure the property information is used and the parser does not expect
67 * audio/x-raw or audio/x-unaligned-raw caps.
68 *
69 */
70
71 #ifdef HAVE_CONFIG_H
72 # include "config.h"
73 #endif
74
75 /* FIXME: GValueArray is deprecated, but there is currently no viabla alternative
76 * See https://bugzilla.gnome.org/show_bug.cgi?id=667228 */
77 #define GLIB_DISABLE_DEPRECATION_WARNINGS
78
79 #include <string.h>
80 #include "gstrawparseelements.h"
81 #include "gstrawaudioparse.h"
82 #include "unalignedaudio.h"
83
84 GST_DEBUG_CATEGORY_STATIC (raw_audio_parse_debug);
85 #define GST_CAT_DEFAULT raw_audio_parse_debug
86
87 enum
88 {
89 PROP_0,
90 PROP_FORMAT,
91 PROP_PCM_FORMAT,
92 PROP_SAMPLE_RATE,
93 PROP_NUM_CHANNELS,
94 PROP_INTERLEAVED,
95 PROP_CHANNEL_POSITIONS
96 };
97
98 #define DEFAULT_FORMAT GST_RAW_AUDIO_PARSE_FORMAT_PCM
99 #define DEFAULT_PCM_FORMAT GST_AUDIO_FORMAT_S16
100 #define DEFAULT_SAMPLE_RATE 44100
101 #define DEFAULT_NUM_CHANNELS 2
102 #define DEFAULT_INTERLEAVED TRUE
103
104 #define GST_RAW_AUDIO_PARSE_CAPS \
105 GST_AUDIO_CAPS_MAKE(GST_AUDIO_FORMATS_ALL) \
106 ", layout = (string) { interleaved, non-interleaved }; " \
107 "audio/x-alaw, rate = (int) [ 1, MAX ], channels = (int) [ 1, MAX ]; " \
108 "audio/x-mulaw, rate = (int) [ 1, MAX ], channels = (int) [ 1, MAX ]; "
109
110 static GstStaticPadTemplate static_sink_template =
111 GST_STATIC_PAD_TEMPLATE ("sink",
112 GST_PAD_SINK,
113 GST_PAD_ALWAYS,
114 GST_STATIC_CAPS (GST_UNALIGNED_RAW_AUDIO_CAPS "; " GST_RAW_AUDIO_PARSE_CAPS)
115 );
116
117 static GstStaticPadTemplate static_src_template =
118 GST_STATIC_PAD_TEMPLATE ("src",
119 GST_PAD_SRC,
120 GST_PAD_ALWAYS,
121 GST_STATIC_CAPS (GST_RAW_AUDIO_PARSE_CAPS)
122 );
123
124 #define gst_raw_audio_parse_parent_class parent_class
125 G_DEFINE_TYPE (GstRawAudioParse, gst_raw_audio_parse, GST_TYPE_RAW_BASE_PARSE);
126 GST_ELEMENT_REGISTER_DEFINE (rawaudioparse, "rawaudioparse",
127 GST_RANK_NONE, GST_TYPE_RAW_AUDIO_PARSE);
128
129 static void gst_raw_audio_parse_set_property (GObject * object, guint prop_id,
130 GValue const *value, GParamSpec * pspec);
131 static void gst_raw_audio_parse_get_property (GObject * object, guint prop_id,
132 GValue * value, GParamSpec * pspec);
133
134 static gboolean gst_raw_audio_parse_stop (GstBaseParse * parse);
135
136 static gboolean gst_raw_audio_parse_set_current_config (GstRawBaseParse *
137 raw_base_parse, GstRawBaseParseConfig config);
138 static GstRawBaseParseConfig
139 gst_raw_audio_parse_get_current_config (GstRawBaseParse * raw_base_parse);
140 static gboolean gst_raw_audio_parse_set_config_from_caps (GstRawBaseParse *
141 raw_base_parse, GstRawBaseParseConfig config, GstCaps * caps);
142 static gboolean gst_raw_audio_parse_get_caps_from_config (GstRawBaseParse *
143 raw_base_parse, GstRawBaseParseConfig config, GstCaps ** caps);
144 static gsize gst_raw_audio_parse_get_config_frame_size (GstRawBaseParse *
145 raw_base_parse, GstRawBaseParseConfig config);
146 static gboolean gst_raw_audio_parse_is_config_ready (GstRawBaseParse *
147 raw_base_parse, GstRawBaseParseConfig config);
148 static gboolean gst_raw_audio_parse_process (GstRawBaseParse * raw_base_parse,
149 GstRawBaseParseConfig config, GstBuffer * in_data, gsize total_num_in_bytes,
150 gsize num_valid_in_bytes, GstBuffer ** processed_data);
151 static gboolean gst_raw_audio_parse_is_unit_format_supported (GstRawBaseParse *
152 raw_base_parse, GstFormat format);
153 static void gst_raw_audio_parse_get_units_per_second (GstRawBaseParse *
154 raw_base_parse, GstFormat format, GstRawBaseParseConfig config,
155 gsize * units_per_sec_n, gsize * units_per_sec_d);
156 static gint gst_raw_audio_parse_get_alignment (GstRawBaseParse * raw_base_parse,
157 GstRawBaseParseConfig config);
158
159 static gboolean gst_raw_audio_parse_is_using_sink_caps (GstRawAudioParse *
160 raw_audio_parse);
161 static GstRawAudioParseConfig
162 * gst_raw_audio_parse_get_config_ptr (GstRawAudioParse * raw_audio_parse,
163 GstRawBaseParseConfig config);
164
165 static void gst_raw_audio_parse_init_config (GstRawAudioParseConfig * config);
166 static gboolean gst_raw_audio_parse_set_config_channels (GstRawAudioParseConfig
167 * config, guint num_channels, guint64 channel_mask, gboolean set_positions);
168 static gboolean
169 gst_raw_audio_parse_update_channel_reordering_flag (GstRawAudioParseConfig *
170 config);
171 static void gst_raw_audio_parse_update_config_bpf (GstRawAudioParseConfig *
172 config);
173 static gboolean gst_raw_audio_parse_caps_to_config (GstRawAudioParse *
174 raw_audio_parse, GstCaps * caps, GstRawAudioParseConfig * config);
175 static gboolean gst_raw_audio_parse_config_to_caps (GstRawAudioParse *
176 raw_audio_parse, GstCaps ** caps, GstRawAudioParseConfig * config);
177
178 static void
gst_raw_audio_parse_class_init(GstRawAudioParseClass * klass)179 gst_raw_audio_parse_class_init (GstRawAudioParseClass * klass)
180 {
181 GObjectClass *object_class;
182 GstElementClass *element_class;
183 GstBaseParseClass *baseparse_class;
184 GstRawBaseParseClass *rawbaseparse_class;
185
186 GST_DEBUG_CATEGORY_INIT (raw_audio_parse_debug, "rawaudioparse", 0,
187 "rawaudioparse element");
188
189 object_class = G_OBJECT_CLASS (klass);
190 element_class = GST_ELEMENT_CLASS (klass);
191 baseparse_class = GST_BASE_PARSE_CLASS (klass);
192 rawbaseparse_class = GST_RAW_BASE_PARSE_CLASS (klass);
193
194 gst_element_class_add_pad_template (element_class,
195 gst_static_pad_template_get (&static_sink_template));
196 gst_element_class_add_pad_template (element_class,
197 gst_static_pad_template_get (&static_src_template));
198
199 object_class->set_property =
200 GST_DEBUG_FUNCPTR (gst_raw_audio_parse_set_property);
201 object_class->get_property =
202 GST_DEBUG_FUNCPTR (gst_raw_audio_parse_get_property);
203
204 baseparse_class->stop = GST_DEBUG_FUNCPTR (gst_raw_audio_parse_stop);
205
206 rawbaseparse_class->set_current_config =
207 GST_DEBUG_FUNCPTR (gst_raw_audio_parse_set_current_config);
208 rawbaseparse_class->get_current_config =
209 GST_DEBUG_FUNCPTR (gst_raw_audio_parse_get_current_config);
210 rawbaseparse_class->set_config_from_caps =
211 GST_DEBUG_FUNCPTR (gst_raw_audio_parse_set_config_from_caps);
212 rawbaseparse_class->get_caps_from_config =
213 GST_DEBUG_FUNCPTR (gst_raw_audio_parse_get_caps_from_config);
214 rawbaseparse_class->get_config_frame_size =
215 GST_DEBUG_FUNCPTR (gst_raw_audio_parse_get_config_frame_size);
216 rawbaseparse_class->is_config_ready =
217 GST_DEBUG_FUNCPTR (gst_raw_audio_parse_is_config_ready);
218 rawbaseparse_class->process = GST_DEBUG_FUNCPTR (gst_raw_audio_parse_process);
219 rawbaseparse_class->is_unit_format_supported =
220 GST_DEBUG_FUNCPTR (gst_raw_audio_parse_is_unit_format_supported);
221 rawbaseparse_class->get_units_per_second =
222 GST_DEBUG_FUNCPTR (gst_raw_audio_parse_get_units_per_second);
223 rawbaseparse_class->get_alignment =
224 GST_DEBUG_FUNCPTR (gst_raw_audio_parse_get_alignment);
225
226 g_object_class_install_property (object_class,
227 PROP_FORMAT,
228 g_param_spec_enum ("format",
229 "Format",
230 "Format of the raw audio stream",
231 GST_TYPE_RAW_AUDIO_PARSE_FORMAT,
232 GST_RAW_AUDIO_PARSE_FORMAT_PCM,
233 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
234 );
235 g_object_class_install_property (object_class,
236 PROP_PCM_FORMAT,
237 g_param_spec_enum ("pcm-format",
238 "PCM format",
239 "Format of audio samples in PCM stream (ignored if format property is not set to pcm)",
240 GST_TYPE_AUDIO_FORMAT,
241 GST_RAW_AUDIO_PARSE_FORMAT_PCM,
242 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
243 );
244 g_object_class_install_property (object_class,
245 PROP_SAMPLE_RATE,
246 g_param_spec_int ("sample-rate",
247 "Sample rate",
248 "Rate of audio samples in raw stream",
249 1, INT_MAX,
250 DEFAULT_SAMPLE_RATE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
251 );
252 g_object_class_install_property (object_class,
253 PROP_NUM_CHANNELS,
254 g_param_spec_int ("num-channels",
255 "Number of channels",
256 "Number of channels in raw stream",
257 1, INT_MAX,
258 DEFAULT_NUM_CHANNELS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
259 );
260 g_object_class_install_property (object_class,
261 PROP_INTERLEAVED,
262 g_param_spec_boolean ("interleaved",
263 "Interleaved layout",
264 "True if audio has interleaved layout",
265 DEFAULT_INTERLEAVED, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
266 );
267 g_object_class_install_property (object_class,
268 PROP_CHANNEL_POSITIONS,
269 g_param_spec_value_array ("channel-positions",
270 "Channel positions",
271 "Channel positions used on the output",
272 g_param_spec_enum ("channel-position",
273 "Channel position",
274 "Channel position of the n-th input",
275 GST_TYPE_AUDIO_CHANNEL_POSITION,
276 GST_AUDIO_CHANNEL_POSITION_NONE,
277 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS),
278 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
279 );
280
281 gst_element_class_set_static_metadata (element_class,
282 "rawaudioparse",
283 "Codec/Parser/Audio",
284 "Converts unformatted data streams into timestamped raw audio frames",
285 "Carlos Rafael Giani <dv@pseudoterminal.org>");
286
287 gst_type_mark_as_plugin_api (GST_TYPE_RAW_AUDIO_PARSE_FORMAT, 0);
288 }
289
290 static void
gst_raw_audio_parse_init(GstRawAudioParse * raw_audio_parse)291 gst_raw_audio_parse_init (GstRawAudioParse * raw_audio_parse)
292 {
293 /* Setup configs and select which one shall be the current one from the start. */
294 gst_raw_audio_parse_init_config (&(raw_audio_parse->properties_config));
295 gst_raw_audio_parse_init_config (&(raw_audio_parse->sink_caps_config));
296 /* As required by GstRawBaseParse, ensure that the current configuration
297 * is initially set to be the properties config */
298 raw_audio_parse->current_config = &(raw_audio_parse->properties_config);
299
300 /* Properties config must be valid from the start, so set its ready value
301 * to TRUE, and make sure its bpf value is valid. */
302 raw_audio_parse->properties_config.ready = TRUE;
303 gst_raw_audio_parse_update_config_bpf (&(raw_audio_parse->properties_config));
304 }
305
306 static void
gst_raw_audio_parse_set_property(GObject * object,guint prop_id,GValue const * value,GParamSpec * pspec)307 gst_raw_audio_parse_set_property (GObject * object, guint prop_id,
308 GValue const *value, GParamSpec * pspec)
309 {
310 GstBaseParse *base_parse = GST_BASE_PARSE (object);
311 GstRawBaseParse *raw_base_parse = GST_RAW_BASE_PARSE (object);
312 GstRawAudioParse *raw_audio_parse = GST_RAW_AUDIO_PARSE (object);
313
314 /* All properties are handled similarly:
315 * - if the new value is the same as the current value, nothing is done
316 * - the parser lock is held while the new value is set
317 * - if the properties config is the current config, the source caps are
318 * invalidated to ensure that the code in handle_frame pushes a new CAPS
319 * event out
320 * - properties that affect the bpf value call the function to update
321 * the bpf and also call gst_base_parse_set_min_frame_size() to ensure
322 * that the minimum frame size can hold 1 frame (= one sample for each
323 * channel)
324 */
325
326 switch (prop_id) {
327 case PROP_FORMAT:
328 {
329 GstRawAudioParseFormat new_format = g_value_get_enum (value);
330
331 GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (object);
332
333 if (new_format != raw_audio_parse->properties_config.format) {
334 raw_audio_parse->properties_config.format = new_format;
335 gst_raw_audio_parse_update_config_bpf (&
336 (raw_audio_parse->properties_config));
337
338 if (!gst_raw_audio_parse_is_using_sink_caps (raw_audio_parse)) {
339 gst_raw_base_parse_invalidate_src_caps (raw_base_parse);
340 gst_base_parse_set_min_frame_size (base_parse,
341 raw_audio_parse->properties_config.bpf);
342 }
343 }
344
345 GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (object);
346 break;
347 }
348
349 case PROP_PCM_FORMAT:
350 {
351 GstAudioFormat new_pcm_format = g_value_get_enum (value);
352
353 GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (object);
354
355 if (new_pcm_format != raw_audio_parse->properties_config.pcm_format) {
356 raw_audio_parse->properties_config.pcm_format = new_pcm_format;
357 gst_raw_audio_parse_update_config_bpf (&
358 (raw_audio_parse->properties_config));
359
360 if (!gst_raw_audio_parse_is_using_sink_caps (raw_audio_parse)) {
361 gst_raw_base_parse_invalidate_src_caps (raw_base_parse);
362 gst_base_parse_set_min_frame_size (base_parse,
363 raw_audio_parse->properties_config.bpf);
364 }
365 }
366
367 GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (object);
368 break;
369 }
370
371 case PROP_SAMPLE_RATE:
372 {
373 guint new_sample_rate = g_value_get_int (value);
374
375 GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (object);
376
377 if (new_sample_rate != raw_audio_parse->properties_config.sample_rate) {
378 raw_audio_parse->properties_config.sample_rate = new_sample_rate;
379
380 if (!gst_raw_audio_parse_is_using_sink_caps (raw_audio_parse))
381 gst_raw_base_parse_invalidate_src_caps (raw_base_parse);
382 }
383
384 GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (object);
385 break;
386 }
387
388 case PROP_NUM_CHANNELS:
389 {
390 guint new_num_channels = g_value_get_int (value);
391
392 GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (object);
393
394 if (new_num_channels != raw_audio_parse->properties_config.num_channels) {
395 gst_raw_audio_parse_set_config_channels (&
396 (raw_audio_parse->properties_config), new_num_channels, 0, TRUE);
397
398 raw_audio_parse->properties_config.num_channels = new_num_channels;
399 gst_raw_audio_parse_update_config_bpf (&
400 (raw_audio_parse->properties_config));
401
402 if (!gst_raw_audio_parse_is_using_sink_caps (raw_audio_parse)) {
403 gst_raw_base_parse_invalidate_src_caps (raw_base_parse);
404 gst_base_parse_set_min_frame_size (base_parse,
405 raw_audio_parse->properties_config.bpf);
406 }
407 }
408
409 GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (object);
410 break;
411 }
412
413 case PROP_INTERLEAVED:
414 {
415 gboolean new_interleaved = g_value_get_boolean (value);
416
417 GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (object);
418
419 if (new_interleaved != raw_audio_parse->properties_config.interleaved) {
420 raw_audio_parse->properties_config.interleaved = new_interleaved;
421
422 if (!gst_raw_audio_parse_is_using_sink_caps (raw_audio_parse))
423 gst_raw_base_parse_invalidate_src_caps (raw_base_parse);
424 }
425
426 GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (object);
427 break;
428 }
429
430 case PROP_CHANNEL_POSITIONS:
431 {
432 GValueArray *valarray = g_value_get_boxed (value);
433 GstRawAudioParseConfig *config = &(raw_audio_parse->properties_config);
434
435 /* Sanity check - reject empty arrays */
436 if ((valarray != NULL) && (valarray->n_values == 0)) {
437 GST_ELEMENT_ERROR (raw_audio_parse, LIBRARY, SETTINGS,
438 ("channel position property holds an empty array"), (NULL));
439 break;
440 }
441
442 GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (object);
443
444 if ((valarray == NULL) && (config->num_channels > 0)) {
445 /* NULL value given, and number of channels is nonzero.
446 * Use the default GStreamer positioning. Call
447 * set_config_channels with the set_positions parameter
448 * set to TRUE to ensure the position values are filled. */
449 gst_raw_audio_parse_set_config_channels (&
450 (raw_audio_parse->properties_config), config->num_channels, 0,
451 TRUE);
452 } else if (valarray != NULL) {
453 /* Non-NULL value given. Make sure the channel_positions
454 * array in the properties config has enough room, and that
455 * the num_channels value equals the array length. Then copy
456 * the values from the valarray to channel_positions, and
457 * produce a copy of that array in case its channel positions
458 * are not in a valid GStreamer order (to be able to apply
459 * channel reordering later).
460 */
461
462 guint i;
463
464 if (valarray->n_values != config->num_channels) {
465 /* Call with set_positions == FALSE to ensure that
466 * the array is properly allocated but not filled
467 * (it is filled below) */
468 gst_raw_audio_parse_set_config_channels (config, valarray->n_values,
469 0, FALSE);
470 }
471
472 for (i = 0; i < config->num_channels; ++i) {
473 GValue *val = g_value_array_get_nth (valarray, i);
474 config->channel_positions[i] = g_value_get_enum (val);
475 }
476
477 gst_raw_audio_parse_update_channel_reordering_flag (config);
478 }
479
480 gst_raw_audio_parse_update_config_bpf (&
481 (raw_audio_parse->properties_config));
482
483 if (!gst_raw_audio_parse_is_using_sink_caps (raw_audio_parse)) {
484 gst_raw_base_parse_invalidate_src_caps (raw_base_parse);
485 gst_base_parse_set_min_frame_size (base_parse,
486 raw_audio_parse->properties_config.bpf);
487 }
488
489 GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (object);
490 break;
491 }
492
493 default:
494 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
495 break;
496 }
497 }
498
499 static void
gst_raw_audio_parse_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)500 gst_raw_audio_parse_get_property (GObject * object, guint prop_id,
501 GValue * value, GParamSpec * pspec)
502 {
503 GstRawAudioParse *raw_audio_parse = GST_RAW_AUDIO_PARSE (object);
504
505 switch (prop_id) {
506 case PROP_FORMAT:
507 GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (object);
508 g_value_set_enum (value, raw_audio_parse->properties_config.format);
509 GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (object);
510 break;
511
512 case PROP_PCM_FORMAT:
513 GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (object);
514 g_value_set_enum (value, raw_audio_parse->properties_config.pcm_format);
515 GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (object);
516 break;
517
518 case PROP_SAMPLE_RATE:
519 GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (object);
520 g_value_set_int (value, raw_audio_parse->properties_config.sample_rate);
521 GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (object);
522 break;
523
524 case PROP_NUM_CHANNELS:
525 GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (object);
526 g_value_set_int (value, raw_audio_parse->properties_config.num_channels);
527 GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (object);
528 break;
529
530 case PROP_INTERLEAVED:
531 GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (object);
532 g_value_set_boolean (value,
533 raw_audio_parse->properties_config.interleaved);
534 GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (object);
535 break;
536
537 case PROP_CHANNEL_POSITIONS:
538 {
539 GstRawAudioParseConfig *config;
540 GValueArray *valarray;
541
542 GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (object);
543
544 valarray = NULL;
545 config = &(raw_audio_parse->properties_config);
546
547 /* Copy channel positions into the valuearray */
548 if (config->num_channels > 0) {
549 guint i;
550 GValue val = G_VALUE_INIT;
551 g_assert (config->channel_positions);
552
553 g_value_init (&val, GST_TYPE_AUDIO_CHANNEL_POSITION);
554 valarray = g_value_array_new (config->num_channels);
555
556 for (i = 0; i < config->num_channels; ++i) {
557 g_value_set_enum (&val, config->channel_positions[i]);
558 g_value_array_insert (valarray, i, &val);
559 }
560
561 g_value_unset (&val);
562 }
563
564 GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (object);
565
566 /* Pass on ownership to the value array,
567 * since we don't need it anymore */
568 g_value_take_boxed (value, valarray);
569
570 break;
571 }
572
573 default:
574 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
575 break;
576 }
577 }
578
579 static gboolean
gst_raw_audio_parse_stop(GstBaseParse * parse)580 gst_raw_audio_parse_stop (GstBaseParse * parse)
581 {
582 GstRawAudioParse *raw_audio_parse = GST_RAW_AUDIO_PARSE (parse);
583
584 /* Sink caps config is not ready until caps come in.
585 * We are stopping processing, the element is being reset,
586 * so the config has to be un-readied.
587 * (Since the properties config is not depending on caps,
588 * its ready status is always TRUE.) */
589 raw_audio_parse->sink_caps_config.ready = FALSE;
590
591 return GST_BASE_PARSE_CLASS (parent_class)->stop (parse);
592 }
593
594 static gboolean
gst_raw_audio_parse_set_current_config(GstRawBaseParse * raw_base_parse,GstRawBaseParseConfig config)595 gst_raw_audio_parse_set_current_config (GstRawBaseParse * raw_base_parse,
596 GstRawBaseParseConfig config)
597 {
598 GstRawAudioParse *raw_audio_parse = GST_RAW_AUDIO_PARSE (raw_base_parse);
599
600 switch (config) {
601 case GST_RAW_BASE_PARSE_CONFIG_PROPERTIES:
602 raw_audio_parse->current_config = &(raw_audio_parse->properties_config);
603 break;
604
605 case GST_RAW_BASE_PARSE_CONFIG_SINKCAPS:
606 raw_audio_parse->current_config = &(raw_audio_parse->sink_caps_config);
607 break;
608
609 default:
610 g_assert_not_reached ();
611 }
612
613 return TRUE;
614 }
615
616 static GstRawBaseParseConfig
gst_raw_audio_parse_get_current_config(GstRawBaseParse * raw_base_parse)617 gst_raw_audio_parse_get_current_config (GstRawBaseParse * raw_base_parse)
618 {
619 GstRawAudioParse *raw_audio_parse = GST_RAW_AUDIO_PARSE (raw_base_parse);
620 return gst_raw_audio_parse_is_using_sink_caps (raw_audio_parse) ?
621 GST_RAW_BASE_PARSE_CONFIG_SINKCAPS : GST_RAW_BASE_PARSE_CONFIG_PROPERTIES;
622 }
623
624 static gboolean
gst_raw_audio_parse_set_config_from_caps(GstRawBaseParse * raw_base_parse,GstRawBaseParseConfig config,GstCaps * caps)625 gst_raw_audio_parse_set_config_from_caps (GstRawBaseParse * raw_base_parse,
626 GstRawBaseParseConfig config, GstCaps * caps)
627 {
628 GstRawAudioParse *raw_audio_parse = GST_RAW_AUDIO_PARSE (raw_base_parse);
629 return gst_raw_audio_parse_caps_to_config (raw_audio_parse, caps,
630 gst_raw_audio_parse_get_config_ptr (raw_audio_parse, config));
631 }
632
633 static gboolean
gst_raw_audio_parse_get_caps_from_config(GstRawBaseParse * raw_base_parse,GstRawBaseParseConfig config,GstCaps ** caps)634 gst_raw_audio_parse_get_caps_from_config (GstRawBaseParse * raw_base_parse,
635 GstRawBaseParseConfig config, GstCaps ** caps)
636 {
637 GstRawAudioParse *raw_audio_parse = GST_RAW_AUDIO_PARSE (raw_base_parse);
638 return gst_raw_audio_parse_config_to_caps (raw_audio_parse, caps,
639 gst_raw_audio_parse_get_config_ptr (raw_audio_parse, config));
640 }
641
642 static gsize
gst_raw_audio_parse_get_config_frame_size(GstRawBaseParse * raw_base_parse,GstRawBaseParseConfig config)643 gst_raw_audio_parse_get_config_frame_size (GstRawBaseParse * raw_base_parse,
644 GstRawBaseParseConfig config)
645 {
646 GstRawAudioParse *raw_audio_parse = GST_RAW_AUDIO_PARSE (raw_base_parse);
647 return gst_raw_audio_parse_get_config_ptr (raw_audio_parse, config)->bpf;
648 }
649
650 static gboolean
gst_raw_audio_parse_is_config_ready(GstRawBaseParse * raw_base_parse,GstRawBaseParseConfig config)651 gst_raw_audio_parse_is_config_ready (GstRawBaseParse * raw_base_parse,
652 GstRawBaseParseConfig config)
653 {
654 GstRawAudioParse *raw_audio_parse = GST_RAW_AUDIO_PARSE (raw_base_parse);
655 return gst_raw_audio_parse_get_config_ptr (raw_audio_parse, config)->ready;
656 }
657
658 static guint
round_up_pow2(guint n)659 round_up_pow2 (guint n)
660 {
661 n = n - 1;
662 n = n | (n >> 1);
663 n = n | (n >> 2);
664 n = n | (n >> 4);
665 n = n | (n >> 8);
666 n = n | (n >> 16);
667 return n + 1;
668 }
669
670 static gint
gst_raw_audio_parse_get_alignment(GstRawBaseParse * raw_base_parse,GstRawBaseParseConfig config)671 gst_raw_audio_parse_get_alignment (GstRawBaseParse * raw_base_parse,
672 GstRawBaseParseConfig config)
673 {
674 GstRawAudioParse *raw_audio_parse = GST_RAW_AUDIO_PARSE (raw_base_parse);
675 GstRawAudioParseConfig *config_ptr =
676 gst_raw_audio_parse_get_config_ptr (raw_audio_parse, config);
677 gint width;
678
679 if (config_ptr->format != GST_RAW_AUDIO_PARSE_FORMAT_PCM)
680 return 1;
681
682 width =
683 GST_AUDIO_FORMAT_INFO_WIDTH (gst_audio_format_get_info
684 (config_ptr->pcm_format)) / 8;
685 width = GST_ROUND_UP_8 (width);
686 width = round_up_pow2 (width);
687
688 return width;
689 }
690
691 static gboolean
gst_raw_audio_parse_process(GstRawBaseParse * raw_base_parse,GstRawBaseParseConfig config,GstBuffer * in_data,gsize total_num_in_bytes,gsize num_valid_in_bytes,GstBuffer ** processed_data)692 gst_raw_audio_parse_process (GstRawBaseParse * raw_base_parse,
693 GstRawBaseParseConfig config, GstBuffer * in_data, gsize total_num_in_bytes,
694 gsize num_valid_in_bytes, GstBuffer ** processed_data)
695 {
696 GstRawAudioParse *raw_audio_parse = GST_RAW_AUDIO_PARSE (raw_base_parse);
697 GstRawAudioParseConfig *config_ptr =
698 gst_raw_audio_parse_get_config_ptr (raw_audio_parse, config);
699
700 if ((config_ptr->format == GST_RAW_AUDIO_PARSE_FORMAT_PCM)
701 && config_ptr->needs_channel_reordering) {
702 /* Need to reorder samples, since they are in an invalid
703 * channel order. */
704
705 GstBuffer *outbuf;
706
707 GST_LOG_OBJECT (raw_audio_parse,
708 "using %" G_GSIZE_FORMAT " bytes out of the %" G_GSIZE_FORMAT
709 " bytes from the input buffer with reordering", num_valid_in_bytes,
710 total_num_in_bytes);
711
712 outbuf =
713 gst_buffer_copy_region (in_data,
714 GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS |
715 GST_BUFFER_COPY_META | GST_BUFFER_COPY_MEMORY, 0, num_valid_in_bytes);
716
717 gst_audio_buffer_reorder_channels (outbuf,
718 config_ptr->pcm_format,
719 config_ptr->num_channels,
720 config_ptr->channel_positions, config_ptr->reordered_channel_positions);
721
722 *processed_data = outbuf;
723 } else {
724 /* Nothing needs to be done with the sample data.
725 * Instruct the baseparse class to just take out_size bytes
726 * from the input buffer */
727
728 GST_LOG_OBJECT (raw_audio_parse,
729 "using %" G_GSIZE_FORMAT " bytes out of the %" G_GSIZE_FORMAT
730 " bytes from the input buffer without reordering", num_valid_in_bytes,
731 total_num_in_bytes);
732
733 *processed_data = NULL;
734 }
735
736 return TRUE;
737 }
738
739 static gboolean
gst_raw_audio_parse_is_unit_format_supported(G_GNUC_UNUSED GstRawBaseParse * raw_base_parse,GstFormat format)740 gst_raw_audio_parse_is_unit_format_supported (G_GNUC_UNUSED GstRawBaseParse *
741 raw_base_parse, GstFormat format)
742 {
743 switch (format) {
744 case GST_FORMAT_BYTES:
745 case GST_FORMAT_DEFAULT:
746 return TRUE;
747 default:
748 return FALSE;
749 }
750 }
751
752 static void
gst_raw_audio_parse_get_units_per_second(GstRawBaseParse * raw_base_parse,GstFormat format,GstRawBaseParseConfig config,gsize * units_per_sec_n,gsize * units_per_sec_d)753 gst_raw_audio_parse_get_units_per_second (GstRawBaseParse * raw_base_parse,
754 GstFormat format, GstRawBaseParseConfig config, gsize * units_per_sec_n,
755 gsize * units_per_sec_d)
756 {
757 GstRawAudioParse *raw_audio_parse = GST_RAW_AUDIO_PARSE (raw_base_parse);
758 GstRawAudioParseConfig *config_ptr =
759 gst_raw_audio_parse_get_config_ptr (raw_audio_parse, config);
760
761 switch (format) {
762 case GST_FORMAT_BYTES:
763 *units_per_sec_n = config_ptr->sample_rate * config_ptr->bpf;
764 *units_per_sec_d = 1;
765 break;
766
767 case GST_FORMAT_DEFAULT:
768 *units_per_sec_n = config_ptr->sample_rate;
769 *units_per_sec_d = 1;
770 break;
771
772 default:
773 g_assert_not_reached ();
774 }
775 }
776
777 static gboolean
gst_raw_audio_parse_is_using_sink_caps(GstRawAudioParse * raw_audio_parse)778 gst_raw_audio_parse_is_using_sink_caps (GstRawAudioParse * raw_audio_parse)
779 {
780 return raw_audio_parse->current_config ==
781 &(raw_audio_parse->sink_caps_config);
782 }
783
784 static GstRawAudioParseConfig *
gst_raw_audio_parse_get_config_ptr(GstRawAudioParse * raw_audio_parse,GstRawBaseParseConfig config)785 gst_raw_audio_parse_get_config_ptr (GstRawAudioParse * raw_audio_parse,
786 GstRawBaseParseConfig config)
787 {
788 g_assert (raw_audio_parse->current_config != NULL);
789
790 switch (config) {
791 case GST_RAW_BASE_PARSE_CONFIG_PROPERTIES:
792 return &(raw_audio_parse->properties_config);
793
794 case GST_RAW_BASE_PARSE_CONFIG_SINKCAPS:
795 return &(raw_audio_parse->sink_caps_config);
796
797 default:
798 g_assert (raw_audio_parse->current_config != NULL);
799 return raw_audio_parse->current_config;
800 }
801 }
802
803 static void
gst_raw_audio_parse_init_config(GstRawAudioParseConfig * config)804 gst_raw_audio_parse_init_config (GstRawAudioParseConfig * config)
805 {
806 config->ready = FALSE;
807 config->format = DEFAULT_FORMAT;
808 config->pcm_format = DEFAULT_PCM_FORMAT;
809 config->bpf = 0;
810 config->sample_rate = DEFAULT_SAMPLE_RATE;
811 config->num_channels = DEFAULT_NUM_CHANNELS;
812 config->interleaved = DEFAULT_INTERLEAVED;
813 config->needs_channel_reordering = FALSE;
814
815 gst_raw_audio_parse_set_config_channels (config, config->num_channels, 0,
816 TRUE);
817 }
818
819 static gboolean
gst_raw_audio_parse_set_config_channels(GstRawAudioParseConfig * config,guint num_channels,guint64 channel_mask,gboolean set_positions)820 gst_raw_audio_parse_set_config_channels (GstRawAudioParseConfig * config,
821 guint num_channels, guint64 channel_mask, gboolean set_positions)
822 {
823 g_assert (num_channels > 0);
824
825 config->num_channels = num_channels;
826 /* Setting this to FALSE, since initially, after setting the channels,
827 * the default GStreamer channel ordering is used. */
828 config->needs_channel_reordering = FALSE;
829
830 /* Set the channel positions based on the given channel mask if set_positions
831 * is set to TRUE. A channel mask of 0 signifies that a fallback mask should be
832 * used for the given number of channels. */
833 if (set_positions) {
834 if (channel_mask == 0)
835 channel_mask = gst_audio_channel_get_fallback_mask (config->num_channels);
836
837 return gst_audio_channel_positions_from_mask (config->num_channels,
838 channel_mask, config->channel_positions);
839 } else {
840 return TRUE;
841 }
842 }
843
844 static gboolean
gst_raw_audio_parse_update_channel_reordering_flag(GstRawAudioParseConfig * config)845 gst_raw_audio_parse_update_channel_reordering_flag (GstRawAudioParseConfig *
846 config)
847 {
848 g_assert (config->num_channels > 0);
849
850 /* If the channel_positions array contains channel positions which are in an
851 * order that conforms to the valid GStreamer order, ensure that channel
852 * reordering is disabled.
853 * Otherwise, if the order of the positions in the channel_positions array
854 * does not conform to the GStreamer order, ensure it is enabled.
855 */
856
857 if (gst_audio_check_valid_channel_positions (config->channel_positions,
858 config->num_channels, TRUE)) {
859
860 config->needs_channel_reordering = FALSE;
861
862 return TRUE;
863 } else {
864 config->needs_channel_reordering = TRUE;
865 memcpy (config->reordered_channel_positions, config->channel_positions,
866 sizeof (GstAudioChannelPosition) * config->num_channels);
867 return
868 gst_audio_channel_positions_to_valid_order
869 (config->reordered_channel_positions, config->num_channels);
870 }
871 }
872
873 static void
gst_raw_audio_parse_update_config_bpf(GstRawAudioParseConfig * config)874 gst_raw_audio_parse_update_config_bpf (GstRawAudioParseConfig * config)
875 {
876 switch (config->format) {
877 case GST_RAW_AUDIO_PARSE_FORMAT_PCM:
878 {
879 GstAudioFormatInfo const *fmt_info =
880 gst_audio_format_get_info (config->pcm_format);
881 g_assert (fmt_info != NULL);
882
883 config->bpf =
884 GST_AUDIO_FORMAT_INFO_WIDTH (fmt_info) * config->num_channels / 8;
885
886 break;
887 }
888
889 case GST_RAW_AUDIO_PARSE_FORMAT_ALAW:
890 case GST_RAW_AUDIO_PARSE_FORMAT_MULAW:
891 /* A-law and mu-law both use 1 byte per sample */
892 config->bpf = 1 * config->num_channels;
893 break;
894
895 default:
896 g_assert_not_reached ();
897 }
898 }
899
900 static gboolean
gst_raw_audio_parse_caps_to_config(GstRawAudioParse * raw_audio_parse,GstCaps * caps,GstRawAudioParseConfig * config)901 gst_raw_audio_parse_caps_to_config (GstRawAudioParse * raw_audio_parse,
902 GstCaps * caps, GstRawAudioParseConfig * config)
903 {
904 gboolean ret = FALSE;
905 GstStructure *structure;
906
907 /* Caps might get copied, and the copy needs to be unref'd.
908 * Also, the caller retains ownership over the original caps.
909 * So, to make this mechanism also work with cases where the
910 * caps are *not* copied, ref the original caps here first. */
911 gst_caps_ref (caps);
912
913 structure = gst_caps_get_structure (caps, 0);
914
915 /* For unaligned raw data, the output caps stay the same,
916 * except that audio/x-unaligned-raw becomes audio/x-raw,
917 * since the parser aligns the sample data */
918 if (gst_structure_has_name (structure, "audio/x-unaligned-raw")) {
919 /* Copy the caps to be able to modify them */
920 GstCaps *new_caps = gst_caps_copy (caps);
921 gst_caps_unref (caps);
922 caps = new_caps;
923
924 /* Change the media type to audio/x-raw , otherwise
925 * gst_audio_info_from_caps() won't work */
926 structure = gst_caps_get_structure (caps, 0);
927 gst_structure_set_name (structure, "audio/x-raw");
928 }
929
930 if (gst_structure_has_name (structure, "audio/x-raw")) {
931 guint num_channels;
932 GstAudioInfo info;
933 if (!gst_audio_info_from_caps (&info, caps)) {
934 GST_ERROR_OBJECT (raw_audio_parse,
935 "failed to parse caps %" GST_PTR_FORMAT, (gpointer) caps);
936 goto done;
937 }
938
939 num_channels = GST_AUDIO_INFO_CHANNELS (&info);
940
941 config->format = GST_RAW_AUDIO_PARSE_FORMAT_PCM;
942 config->pcm_format = GST_AUDIO_INFO_FORMAT (&info);
943 config->bpf = GST_AUDIO_INFO_BPF (&info);
944 config->sample_rate = GST_AUDIO_INFO_RATE (&info);
945 config->interleaved =
946 (GST_AUDIO_INFO_LAYOUT (&info) == GST_AUDIO_LAYOUT_INTERLEAVED);
947
948 gst_raw_audio_parse_set_config_channels (config, num_channels, 0, FALSE);
949 memcpy (config->channel_positions, &(GST_AUDIO_INFO_POSITION (&info, 0)),
950 sizeof (GstAudioChannelPosition) * num_channels);
951 } else if (gst_structure_has_name (structure, "audio/x-alaw")
952 || gst_structure_has_name (structure, "audio/x-mulaw")) {
953 gint i;
954 guint64 channel_mask;
955 guint num_channels;
956
957 config->format =
958 gst_structure_has_name (structure,
959 "audio/x-alaw") ? GST_RAW_AUDIO_PARSE_FORMAT_ALAW :
960 GST_RAW_AUDIO_PARSE_FORMAT_MULAW;
961
962 if (!gst_structure_get_int (structure, "rate", &i)) {
963 GST_ERROR_OBJECT (raw_audio_parse,
964 "missing rate value in caps %" GST_PTR_FORMAT, (gpointer) caps);
965 goto done;
966 }
967 config->sample_rate = i;
968
969 if (!gst_structure_get_int (structure, "channels", &i)) {
970 GST_ERROR_OBJECT (raw_audio_parse,
971 "missing channels value in caps %" GST_PTR_FORMAT, (gpointer) caps);
972 goto done;
973 }
974 num_channels = i;
975
976 if (!gst_structure_get (structure, "channel-mask", GST_TYPE_BITMASK,
977 &channel_mask, NULL)) {
978 channel_mask = gst_audio_channel_get_fallback_mask (num_channels);
979 GST_DEBUG_OBJECT (raw_audio_parse,
980 "input caps have no channel mask - using fallback mask %#"
981 G_GINT64_MODIFIER "x for %u channels", channel_mask, num_channels);
982 }
983
984 if (!gst_raw_audio_parse_set_config_channels (config, num_channels,
985 channel_mask, TRUE)) {
986 GST_ERROR_OBJECT (raw_audio_parse,
987 "could not use channel mask %#" G_GINT64_MODIFIER
988 "x for channel positions", channel_mask);
989 goto done;
990 }
991
992 /* A-law and mu-law both use 1 byte per sample */
993 config->bpf = 1 * num_channels;
994 } else {
995 GST_ERROR_OBJECT (raw_audio_parse,
996 "caps %" GST_PTR_FORMAT " have an unsupported media type",
997 (gpointer) caps);
998 goto done;
999 }
1000
1001 ret = TRUE;
1002
1003 done:
1004 gst_caps_unref (caps);
1005 if (ret)
1006 config->ready = TRUE;
1007 return ret;
1008 }
1009
1010 static gboolean
gst_raw_audio_parse_config_to_caps(GstRawAudioParse * raw_audio_parse,GstCaps ** caps,GstRawAudioParseConfig * config)1011 gst_raw_audio_parse_config_to_caps (GstRawAudioParse * raw_audio_parse,
1012 GstCaps ** caps, GstRawAudioParseConfig * config)
1013 {
1014 gboolean ret = TRUE;
1015 GstAudioChannelPosition *channel_positions;
1016
1017 g_assert (caps != NULL);
1018
1019 if (config->bpf == 0) {
1020 GST_ERROR_OBJECT (raw_audio_parse,
1021 "cannot convert config to caps - config not filled with valid values");
1022 *caps = NULL;
1023 return FALSE;
1024 }
1025
1026 channel_positions =
1027 config->needs_channel_reordering ? &(config->
1028 reordered_channel_positions[0]) : &(config->channel_positions[0]);
1029
1030 switch (config->format) {
1031 case GST_RAW_AUDIO_PARSE_FORMAT_PCM:
1032 {
1033 GstAudioInfo info;
1034 gst_audio_info_init (&info);
1035 gst_audio_info_set_format (&info,
1036 config->pcm_format,
1037 config->sample_rate, config->num_channels, channel_positions);
1038
1039 *caps = gst_audio_info_to_caps (&info);
1040
1041 break;
1042 }
1043
1044 case GST_RAW_AUDIO_PARSE_FORMAT_ALAW:
1045 case GST_RAW_AUDIO_PARSE_FORMAT_MULAW:
1046 {
1047 guint64 channel_mask;
1048
1049 if (!gst_audio_channel_positions_to_mask (channel_positions,
1050 config->num_channels, TRUE, &channel_mask)) {
1051 GST_ERROR_OBJECT (raw_audio_parse, "invalid channel positions");
1052 ret = FALSE;
1053 break;
1054 }
1055
1056 *caps = gst_caps_new_simple (
1057 (config->format ==
1058 GST_RAW_AUDIO_PARSE_FORMAT_ALAW) ? "audio/x-alaw" :
1059 "audio/x-mulaw", "rate", G_TYPE_INT, config->sample_rate, "channels",
1060 G_TYPE_INT, config->num_channels, "channel-mask", GST_TYPE_BITMASK,
1061 channel_mask, NULL);
1062
1063 break;
1064 }
1065
1066 default:
1067 g_assert_not_reached ();
1068 ret = FALSE;
1069 }
1070
1071 if (!ret)
1072 *caps = NULL;
1073
1074 return ret;
1075 }
1076
1077 GType
gst_raw_audio_parse_format_get_type(void)1078 gst_raw_audio_parse_format_get_type (void)
1079 {
1080 static GType audio_parse_format_gtype = 0;
1081 static const GEnumValue types[] = {
1082 {GST_RAW_AUDIO_PARSE_FORMAT_PCM, "PCM", "pcm"},
1083 {GST_RAW_AUDIO_PARSE_FORMAT_ALAW, "A-Law", "alaw"},
1084 {GST_RAW_AUDIO_PARSE_FORMAT_MULAW, "\302\265-Law", "mulaw"},
1085 {0, NULL, NULL}
1086 };
1087
1088 if (!audio_parse_format_gtype)
1089 audio_parse_format_gtype =
1090 g_enum_register_static ("GstRawAudioParseFormat", types);
1091
1092 return audio_parse_format_gtype;
1093 }
1094