gst-plugins-good  1.20.3
About: GStreamer (Good Plugins) is a library for constructing of graphs of media-handling components. A set of good-quality plug-ins (under LGPL license).
  Fossies Dox: gst-plugins-good-1.20.3.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

gstsbcparse.c
Go to the documentation of this file.
1/* GStreamer SBC audio parser
2 * Copyright (C) 2012 Collabora Ltd. <tim.muller@collabora.co.uk>
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#ifdef HAVE_CONFIG_H
21#include "config.h"
22#endif
23
24/**
25 * SECTION:element-sbcparse
26 * @title: sbcparse
27 * @see_also: sbcdec, sbcenc
28 *
29 * The sbcparse element will parse a bluetooth SBC audio stream into
30 * frames and timestamp them properly.
31 *
32 * Since: 1.2.0
33 */
34
35#ifdef HAVE_CONFIG_H
36#include "config.h"
37#endif
38
40#include "gstsbcparse.h"
41
42#include <string.h>
43#include <gst/tag/tag.h>
44#include <gst/audio/audio.h>
45#include <gst/base/base.h>
46#include <gst/pbutils/pbutils.h>
47
48#define SBC_SYNCBYTE 0x9C
49
51#define GST_CAT_DEFAULT sbcparse_debug
52
53static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
54 GST_PAD_SRC,
55 GST_PAD_ALWAYS,
56 GST_STATIC_CAPS ("audio/x-sbc, parsed = (boolean) true, "
57 "channels = (int) [ 1, 2 ], "
58 "rate = (int) { 16000, 32000, 44100, 48000 }")
59 );
60
61static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
62 GST_PAD_SINK,
63 GST_PAD_ALWAYS,
64 GST_STATIC_CAPS ("audio/x-sbc")
65 );
66
67static gboolean gst_sbc_parse_start (GstBaseParse * parse);
68static gboolean gst_sbc_parse_stop (GstBaseParse * parse);
69static GstFlowReturn gst_sbc_parse_handle_frame (GstBaseParse * parse,
70 GstBaseParseFrame * frame, gint * skipsize);
71static GstFlowReturn gst_sbc_parse_pre_push_frame (GstBaseParse * parse,
72 GstBaseParseFrame * frame);
73static GstCaps *gst_sbc_parse_get_sink_caps (GstBaseParse * parse,
74 GstCaps * filter);
75
76static guint8 gst_sbc_calculate_crc8 (const guint8 * data, gint bits_crc);
77static gsize gst_sbc_calc_framelen (guint subbands, GstSbcChannelMode ch_mode,
78 guint blocks, guint bitpool);
79static gsize gst_sbc_parse_header (const guint8 * data, guint * rate,
80 guint * n_blocks, GstSbcChannelMode * ch_mode,
81 GstSbcAllocationMethod * alloc_method, guint * n_subbands, guint * bitpool);
82
83#define parent_class gst_sbc_parse_parent_class
84G_DEFINE_TYPE (GstSbcParse, gst_sbc_parse, GST_TYPE_BASE_PARSE);
85GST_ELEMENT_REGISTER_DEFINE (sbcparse, "sbcparse",
86 GST_RANK_PRIMARY + 1, GST_TYPE_SBC_PARSE);
87
88static void
90{
91 GstBaseParseClass *baseparse_class = GST_BASE_PARSE_CLASS (klass);
92 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
93
94 GST_DEBUG_CATEGORY_INIT (sbcparse_debug, "sbcparse", 0, "SBC audio parser");
95
96 baseparse_class->start = GST_DEBUG_FUNCPTR (gst_sbc_parse_start);
97 baseparse_class->stop = GST_DEBUG_FUNCPTR (gst_sbc_parse_stop);
98 baseparse_class->pre_push_frame =
99 GST_DEBUG_FUNCPTR (gst_sbc_parse_pre_push_frame);
100 baseparse_class->handle_frame =
101 GST_DEBUG_FUNCPTR (gst_sbc_parse_handle_frame);
102 baseparse_class->get_sink_caps =
103 GST_DEBUG_FUNCPTR (gst_sbc_parse_get_sink_caps);
104
105 gst_element_class_add_static_pad_template (element_class, &src_factory);
106 gst_element_class_add_static_pad_template (element_class, &sink_factory);
107
108 gst_element_class_set_static_metadata (element_class, "SBC audio parser",
109 "Codec/Parser/Audio", "Parses an SBC bluetooth audio stream",
110 "Tim-Philipp Müller <tim.muller@collabora.co.uk>");
111}
112
113static void
115{
118 sbcparse->rate = -1;
119 sbcparse->n_blocks = -1;
120 sbcparse->n_subbands = -1;
121 sbcparse->bitpool = -1;
122 sbcparse->sent_codec_tag = FALSE;
123}
124
125static void
127{
128 gst_sbc_parse_reset (sbcparse);
129 GST_PAD_SET_ACCEPT_INTERSECT (GST_BASE_PARSE_SINK_PAD (sbcparse));
130 GST_PAD_SET_ACCEPT_TEMPLATE (GST_BASE_PARSE_SINK_PAD (sbcparse));
131}
132
133static gboolean
134gst_sbc_parse_start (GstBaseParse * parse)
135{
136 gst_base_parse_set_min_frame_size (parse,
138
139 gst_base_parse_set_has_timing_info (parse, FALSE);
140
141 gst_base_parse_set_syncable (parse, TRUE);
142
143 return TRUE;
144}
145
146static gboolean
147gst_sbc_parse_stop (GstBaseParse * parse)
148{
150 return TRUE;
151}
152
153static const gchar *
155{
156 switch (ch_mode) {
158 return "mono";
160 return "dual";
162 return "stereo";
164 return "joint";
165 default:
166 break;
167 }
168 return "invalid";
169}
170
171static const gchar *
173{
174 switch (alloc_method) {
176 return "snr";
178 return "loudness";
179 default:
180 break;
181 }
182 return "invalid";
183}
184
185static GstFlowReturn
186gst_sbc_parse_handle_frame (GstBaseParse * parse, GstBaseParseFrame * frame,
187 gint * skipsize)
188{
189 GstSbcParse *sbcparse = GST_SBC_PARSE (parse);
192 GstMapInfo map;
193 guint rate = 0, n_blocks = 0, n_subbands = 0, bitpool = 0;
194 gsize frame_len, next_len;
195 gint i, max_frames;
196
197 gst_buffer_map (frame->buffer, &map, GST_MAP_READ);
198
199 g_assert (map.size >= 6);
200
201 frame_len = gst_sbc_parse_header (map.data, &rate, &n_blocks, &ch_mode,
202 &alloc_method, &n_subbands, &bitpool);
203
204 GST_LOG_OBJECT (parse, "frame_len: %u", (guint) frame_len);
205
206 if (frame_len == 0)
207 goto resync;
208
209 if (sbcparse->alloc_method != alloc_method
210 || sbcparse->ch_mode != ch_mode
211 || sbcparse->rate != rate
212 || sbcparse->n_blocks != n_blocks
213 || sbcparse->n_subbands != n_subbands || sbcparse->bitpool != bitpool) {
214 guint avg_bitrate;
215 GstCaps *caps;
216
217 /* FIXME: do all of these need to be in the caps? */
218 caps = gst_caps_new_simple ("audio/x-sbc", "rate", G_TYPE_INT, rate,
219 "channels", G_TYPE_INT, (ch_mode == GST_SBC_CHANNEL_MODE_MONO) ? 1 : 2,
220 "channel-mode", G_TYPE_STRING, gst_sbc_channel_mode_get_name (ch_mode),
221 "blocks", G_TYPE_INT, n_blocks, "subbands", G_TYPE_INT, n_subbands,
222 "allocation-method", G_TYPE_STRING,
224 "bitpool", G_TYPE_INT, bitpool, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
225
226 GST_INFO_OBJECT (sbcparse, "caps changed to %" GST_PTR_FORMAT, caps);
227
228 gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (sbcparse),
229 gst_event_new_caps (caps));
230
231 avg_bitrate = (8 * frame_len * rate) / (n_subbands * n_blocks);
232 gst_base_parse_set_average_bitrate (parse, avg_bitrate);
233
234 gst_base_parse_set_frame_rate (parse, rate, n_subbands * n_blocks, 0, 0);
235
236 sbcparse->alloc_method = alloc_method;
237 sbcparse->ch_mode = ch_mode;
238 sbcparse->rate = rate;
239 sbcparse->n_blocks = n_blocks;
240 sbcparse->n_subbands = n_subbands;
241 sbcparse->bitpool = bitpool;
242
243 gst_caps_unref (caps);
244 }
245
246 if (frame_len > map.size)
247 goto need_more_data;
248
249 GST_BUFFER_OFFSET (frame->buffer) = GST_BUFFER_OFFSET_NONE;
250 GST_BUFFER_OFFSET_END (frame->buffer) = GST_BUFFER_OFFSET_NONE;
251
252 /* completely arbitrary limit, we only process data we already have,
253 * so we aren't introducing latency here */
254 max_frames = MIN (map.size / frame_len, n_blocks * n_subbands * 5);
255 GST_LOG_OBJECT (sbcparse, "parsing up to %d frames", max_frames);
256
257 for (i = 1; i < max_frames; ++i) {
258 next_len = gst_sbc_parse_header (map.data + (i * frame_len), &rate,
259 &n_blocks, &ch_mode, &alloc_method, &n_subbands, &bitpool);
260
261 if (next_len != frame_len || sbcparse->alloc_method != alloc_method ||
262 sbcparse->ch_mode != ch_mode || sbcparse->rate != rate ||
263 sbcparse->n_blocks != n_blocks || sbcparse->n_subbands != n_subbands ||
264 sbcparse->bitpool != bitpool) {
265 break;
266 }
267 }
268 GST_LOG_OBJECT (sbcparse, "packing %d SBC frames into next output buffer", i);
269
270 /* Note: local n_subbands and n_blocks variables might be tainted if we
271 * bailed out of the loop above because of a header configuration mismatch */
272 gst_base_parse_set_frame_rate (parse, rate,
273 sbcparse->n_subbands * sbcparse->n_blocks * i, 0, 0);
274
275 gst_buffer_unmap (frame->buffer, &map);
276 return gst_base_parse_finish_frame (parse, frame, i * frame_len);
277
278resync:
279 {
280 const guint8 *possible_sync;
281
282 GST_DEBUG_OBJECT (parse, "no sync, resyncing");
283
284 possible_sync = memchr (map.data, SBC_SYNCBYTE, map.size);
285
286 if (possible_sync != NULL)
287 *skipsize = (gint) (possible_sync - map.data);
288 else
289 *skipsize = map.size;
290
291 gst_buffer_unmap (frame->buffer, &map);
292
293 /* we could optimise things here by looping over the data and checking
294 * whether the sync is good or not instead of handing control back to
295 * the base class just to be called again */
296 return GST_FLOW_OK;
297 }
298need_more_data:
299 {
300 GST_LOG_OBJECT (parse,
301 "need %" G_GSIZE_FORMAT " bytes, but only have %" G_GSIZE_FORMAT,
302 frame_len, map.size);
303 gst_base_parse_set_min_frame_size (parse, frame_len);
304 gst_buffer_unmap (frame->buffer, &map);
305 return GST_FLOW_OK;
306 }
307}
308
309static void
310remove_fields (GstCaps * caps)
311{
312 guint i, n;
313
314 n = gst_caps_get_size (caps);
315 for (i = 0; i < n; i++) {
316 GstStructure *s = gst_caps_get_structure (caps, i);
317
318 gst_structure_remove_field (s, "parsed");
319 }
320}
321
322static GstCaps *
323gst_sbc_parse_get_sink_caps (GstBaseParse * parse, GstCaps * filter)
324{
325 GstCaps *peercaps, *templ;
326 GstCaps *res;
327
328 templ = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse));
329 if (filter) {
330 GstCaps *fcopy = gst_caps_copy (filter);
331 /* Remove the fields we convert */
332 remove_fields (fcopy);
333 peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), fcopy);
334 gst_caps_unref (fcopy);
335 } else
336 peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), NULL);
337
338 if (peercaps) {
339 /* Remove the parsed field */
340 peercaps = gst_caps_make_writable (peercaps);
341 remove_fields (peercaps);
342
343 res = gst_caps_intersect_full (peercaps, templ, GST_CAPS_INTERSECT_FIRST);
344 gst_caps_unref (peercaps);
345 gst_caps_unref (templ);
346 } else {
347 res = templ;
348 }
349
350 if (filter) {
351 GstCaps *intersection;
352
353 intersection =
354 gst_caps_intersect_full (filter, res, GST_CAPS_INTERSECT_FIRST);
355 gst_caps_unref (res);
356 res = intersection;
357 }
358
359 return res;
360}
361
362static const guint8 crc_table[256] = {
363 0x00, 0x1D, 0x3A, 0x27, 0x74, 0x69, 0x4E, 0x53,
364 0xE8, 0xF5, 0xD2, 0xCF, 0x9C, 0x81, 0xA6, 0xBB,
365 0xCD, 0xD0, 0xF7, 0xEA, 0xB9, 0xA4, 0x83, 0x9E,
366 0x25, 0x38, 0x1F, 0x02, 0x51, 0x4C, 0x6B, 0x76,
367 0x87, 0x9A, 0xBD, 0xA0, 0xF3, 0xEE, 0xC9, 0xD4,
368 0x6F, 0x72, 0x55, 0x48, 0x1B, 0x06, 0x21, 0x3C,
369 0x4A, 0x57, 0x70, 0x6D, 0x3E, 0x23, 0x04, 0x19,
370 0xA2, 0xBF, 0x98, 0x85, 0xD6, 0xCB, 0xEC, 0xF1,
371 0x13, 0x0E, 0x29, 0x34, 0x67, 0x7A, 0x5D, 0x40,
372 0xFB, 0xE6, 0xC1, 0xDC, 0x8F, 0x92, 0xB5, 0xA8,
373 0xDE, 0xC3, 0xE4, 0xF9, 0xAA, 0xB7, 0x90, 0x8D,
374 0x36, 0x2B, 0x0C, 0x11, 0x42, 0x5F, 0x78, 0x65,
375 0x94, 0x89, 0xAE, 0xB3, 0xE0, 0xFD, 0xDA, 0xC7,
376 0x7C, 0x61, 0x46, 0x5B, 0x08, 0x15, 0x32, 0x2F,
377 0x59, 0x44, 0x63, 0x7E, 0x2D, 0x30, 0x17, 0x0A,
378 0xB1, 0xAC, 0x8B, 0x96, 0xC5, 0xD8, 0xFF, 0xE2,
379 0x26, 0x3B, 0x1C, 0x01, 0x52, 0x4F, 0x68, 0x75,
380 0xCE, 0xD3, 0xF4, 0xE9, 0xBA, 0xA7, 0x80, 0x9D,
381 0xEB, 0xF6, 0xD1, 0xCC, 0x9F, 0x82, 0xA5, 0xB8,
382 0x03, 0x1E, 0x39, 0x24, 0x77, 0x6A, 0x4D, 0x50,
383 0xA1, 0xBC, 0x9B, 0x86, 0xD5, 0xC8, 0xEF, 0xF2,
384 0x49, 0x54, 0x73, 0x6E, 0x3D, 0x20, 0x07, 0x1A,
385 0x6C, 0x71, 0x56, 0x4B, 0x18, 0x05, 0x22, 0x3F,
386 0x84, 0x99, 0xBE, 0xA3, 0xF0, 0xED, 0xCA, 0xD7,
387 0x35, 0x28, 0x0F, 0x12, 0x41, 0x5C, 0x7B, 0x66,
388 0xDD, 0xC0, 0xE7, 0xFA, 0xA9, 0xB4, 0x93, 0x8E,
389 0xF8, 0xE5, 0xC2, 0xDF, 0x8C, 0x91, 0xB6, 0xAB,
390 0x10, 0x0D, 0x2A, 0x37, 0x64, 0x79, 0x5E, 0x43,
391 0xB2, 0xAF, 0x88, 0x95, 0xC6, 0xDB, 0xFC, 0xE1,
392 0x5A, 0x47, 0x60, 0x7D, 0x2E, 0x33, 0x14, 0x09,
393 0x7F, 0x62, 0x45, 0x58, 0x0B, 0x16, 0x31, 0x2C,
394 0x97, 0x8A, 0xAD, 0xB0, 0xE3, 0xFE, 0xD9, 0xC4
395};
396
397static guint8
398gst_sbc_calculate_crc8 (const guint8 * data, gint crc_bits)
399{
400 guint8 crc = 0x0f;
401 guint8 octet;
402
403 while (crc_bits >= 8) {
404 crc = crc_table[crc ^ *data];
405 crc_bits -= 8;
406 ++data;
407 }
408
409 octet = *data;
410 while (crc_bits > 0) {
411 gchar bit = ((octet ^ crc) & 0x80) >> 7;
412
413 crc = ((crc & 0x7f) << 1) ^ (bit ? 0x1d : 0);
414
415 octet = octet << 1;
416 --crc_bits;
417 }
418
419 return crc;
420}
421
422static gsize
424 guint blocks, guint bitpool)
425{
426 switch (ch_mode) {
428 return 4 + (subbands * 1) / 2 + ((blocks * 1 * bitpool) + 7) / 8;
430 return 4 + (subbands * 2) / 2 + ((blocks * 2 * bitpool) + 7) / 8;
432 return 4 + (subbands * 2) / 2 + ((blocks * bitpool) + 7) / 8;
434 return 4 + (subbands * 2) / 2 + ((subbands + blocks * bitpool) + 7) / 8;
435 default:
436 break;
437 }
438
439 g_return_val_if_reached (0);
440}
441
442static gsize
443gst_sbc_parse_header (const guint8 * data, guint * rate, guint * n_blocks,
444 GstSbcChannelMode * ch_mode, GstSbcAllocationMethod * alloc_method,
445 guint * n_subbands, guint * bitpool)
446{
447 static const guint16 sbc_rates[4] = { 16000, 32000, 44100, 48000 };
448 static const guint8 sbc_blocks[4] = { 4, 8, 12, 16 };
449 guint8 crc_data[2 + 1 + 8], crc_bits, i;
450
451 GST_MEMDUMP ("header", data, 8);
452
453 if (data[0] != SBC_SYNCBYTE)
454 return 0;
455
456 *rate = sbc_rates[(data[1] >> 6) & 0x03];
457 *n_blocks = sbc_blocks[(data[1] >> 4) & 0x03];
458 *ch_mode = (GstSbcChannelMode) ((data[1] >> 2) & 0x03);
459 *alloc_method = (data[1] >> 1) & 0x01;
460 *n_subbands = (data[1] & 0x01) ? 8 : 4;
461 *bitpool = data[2];
462
463 GST_TRACE ("rate=%u, n_blocks=%u, ch_mode=%u, alloc_method=%u, "
464 "n_subbands=%u, bitpool=%u", *rate, *n_blocks, *ch_mode, *alloc_method,
465 *n_subbands, *bitpool);
466
467 if (*bitpool < 2)
468 return 0;
469
470 /* check CRC */
471 crc_data[0] = data[1];
472 crc_data[1] = data[2];
473 crc_bits = 16;
474
475 /* joint flags and RFA */
476 if (*ch_mode == GST_SBC_CHANNEL_MODE_JOINT_STEREO)
477 crc_bits += *n_subbands;
478
479 /* scale factors */
480 if (*ch_mode == GST_SBC_CHANNEL_MODE_MONO)
481 crc_bits += *n_subbands * 1 * 4;
482 else
483 crc_bits += *n_subbands * 2 * 4;
484
485 for (i = 16; i < crc_bits; i += 8) {
486 crc_data[i / 8] = data[1 + (i / 8) + 1];
487 }
488
489 if (i > crc_bits) {
490 crc_data[(i / 8) - 1] &= 0xF0;
491 }
492
493 GST_MEMDUMP ("crc bytes", crc_data, GST_ROUND_UP_8 (crc_bits) / 8);
494 if (gst_sbc_calculate_crc8 (crc_data, crc_bits) != data[3]) {
495 GST_LOG ("header CRC check failed, bits=%u, got 0x%02x, expected 0x%02x",
496 crc_bits, gst_sbc_calculate_crc8 (crc_data, crc_bits), data[3]);
497 return 0;
498 }
499
500 return gst_sbc_calc_framelen (*n_subbands, *ch_mode, *n_blocks, *bitpool);
501}
502
503static GstFlowReturn
504gst_sbc_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
505{
506 GstSbcParse *sbcparse = GST_SBC_PARSE (parse);
507
508 if (!sbcparse->sent_codec_tag) {
509 GstTagList *taglist;
510 GstCaps *caps;
511
512 /* codec tag */
513 caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (parse));
514 if (G_UNLIKELY (caps == NULL)) {
515 if (GST_PAD_IS_FLUSHING (GST_BASE_PARSE_SRC_PAD (parse))) {
516 GST_INFO_OBJECT (parse, "Src pad is flushing");
517 return GST_FLOW_FLUSHING;
518 } else {
519 GST_INFO_OBJECT (parse, "Src pad is not negotiated!");
520 return GST_FLOW_NOT_NEGOTIATED;
521 }
522 }
523
524 taglist = gst_tag_list_new_empty ();
525 gst_pb_utils_add_codec_description_to_tag_list (taglist,
526 GST_TAG_AUDIO_CODEC, caps);
527 gst_caps_unref (caps);
528
529 gst_base_parse_merge_tags (parse, taglist, GST_TAG_MERGE_REPLACE);
530 gst_tag_list_unref (taglist);
531
532 /* also signals the end of first-frame processing */
533 sbcparse->sent_codec_tag = TRUE;
534 }
535
536 frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
537
538 return GST_FLOW_OK;
539}
static guint8 gst_sbc_calculate_crc8(const guint8 *data, gint bits_crc)
Definition: gstsbcparse.c:398
#define SBC_SYNCBYTE
Definition: gstsbcparse.c:48
static gboolean gst_sbc_parse_stop(GstBaseParse *parse)
Definition: gstsbcparse.c:147
static GstFlowReturn gst_sbc_parse_pre_push_frame(GstBaseParse *parse, GstBaseParseFrame *frame)
Definition: gstsbcparse.c:504
static gsize gst_sbc_calc_framelen(guint subbands, GstSbcChannelMode ch_mode, guint blocks, guint bitpool)
Definition: gstsbcparse.c:423
static void gst_sbc_parse_class_init(GstSbcParseClass *klass)
Definition: gstsbcparse.c:89
static void gst_sbc_parse_init(GstSbcParse *sbcparse)
Definition: gstsbcparse.c:126
static GstStaticPadTemplate src_factory
Definition: gstsbcparse.c:53
static void remove_fields(GstCaps *caps)
Definition: gstsbcparse.c:310
static gsize gst_sbc_parse_header(const guint8 *data, guint *rate, guint *n_blocks, GstSbcChannelMode *ch_mode, GstSbcAllocationMethod *alloc_method, guint *n_subbands, guint *bitpool)
Definition: gstsbcparse.c:443
static const guint8 crc_table[256]
Definition: gstsbcparse.c:362
static GstStaticPadTemplate sink_factory
Definition: gstsbcparse.c:61
static const gchar * gst_sbc_allocation_method_get_name(GstSbcAllocationMethod alloc_method)
Definition: gstsbcparse.c:172
static GstFlowReturn gst_sbc_parse_handle_frame(GstBaseParse *parse, GstBaseParseFrame *frame, gint *skipsize)
Definition: gstsbcparse.c:186
GST_ELEMENT_REGISTER_DEFINE(sbcparse, "sbcparse", GST_RANK_PRIMARY+1,(gst_sbc_parse_get_type()))
GST_DEBUG_CATEGORY_STATIC(sbcparse_debug)
static void gst_sbc_parse_reset(GstSbcParse *sbcparse)
Definition: gstsbcparse.c:114
static const gchar * gst_sbc_channel_mode_get_name(GstSbcChannelMode ch_mode)
Definition: gstsbcparse.c:154
static gboolean gst_sbc_parse_start(GstBaseParse *parse)
Definition: gstsbcparse.c:134
G_DEFINE_TYPE(GstSbcParse, gst_sbc_parse, GST_TYPE_BASE_PARSE)
static GstCaps * gst_sbc_parse_get_sink_caps(GstBaseParse *parse, GstCaps *filter)
Definition: gstsbcparse.c:323
#define GST_SBC_PARSE(obj)
Definition: gstsbcparse.h:30
GstSbcAllocationMethod
Definition: gstsbcparse.h:45
@ GST_SBC_ALLOCATION_METHOD_SNR
Definition: gstsbcparse.h:48
@ GST_SBC_ALLOCATION_METHOD_LOUDNESS
Definition: gstsbcparse.h:47
@ GST_SBC_ALLOCATION_METHOD_INVALID
Definition: gstsbcparse.h:46
GstSbcChannelMode
Definition: gstsbcparse.h:37
@ GST_SBC_CHANNEL_MODE_DUAL
Definition: gstsbcparse.h:40
@ GST_SBC_CHANNEL_MODE_STEREO
Definition: gstsbcparse.h:41
@ GST_SBC_CHANNEL_MODE_JOINT_STEREO
Definition: gstsbcparse.h:42
@ GST_SBC_CHANNEL_MODE_INVALID
Definition: gstsbcparse.h:38
@ GST_SBC_CHANNEL_MODE_MONO
Definition: gstsbcparse.h:39
#define GST_TYPE_SBC_PARSE
Definition: gstsbcparse.h:29
GstSbcChannelMode ch_mode
Definition: gstsbcparse.h:59
gint n_subbands
Definition: gstsbcparse.h:62
gboolean sent_codec_tag
Definition: gstsbcparse.h:65
GstSbcAllocationMethod alloc_method
Definition: gstsbcparse.h:58