1 /* GStreamer SBC audio parser
2 * Copyright (C) 2012 Collabora Ltd. <tim.muller@collabora.co.uk>
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.
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.
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.
25 * SECTION:element-sbcparse
26 * @see_also: sbcdec, sbcenc
28 * The sbcparse element will parse a bluetooth SBC audio stream into
29 * frames and timestamp them properly.
38 #include "gstsbcparse.h"
41 #include <gst/tag/tag.h>
42 #include <gst/audio/audio.h>
44 #include <gst/base/gstbitreader.h>
45 #include <gst/base/gstbytereader.h>
47 #define SBC_SYNCBYTE 0x9C
49 GST_DEBUG_CATEGORY_STATIC (sbcparse_debug);
50 #define GST_CAT_DEFAULT sbcparse_debug
52 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
55 GST_STATIC_CAPS ("audio/x-sbc, parsed = (boolean) true, "
56 "channels = (int) [ 1, 2 ], "
57 "rate = (int) { 16000, 32000, 44100, 48000 }")
60 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
63 GST_STATIC_CAPS ("audio/x-sbc")
66 static gboolean gst_sbc_parse_start (GstBaseParse * parse);
67 static gboolean gst_sbc_parse_stop (GstBaseParse * parse);
68 static GstFlowReturn gst_sbc_parse_handle_frame (GstBaseParse * parse,
69 GstBaseParseFrame * frame, gint * skipsize);
70 static GstCaps *gst_sbc_parse_get_sink_caps (GstBaseParse * parse,
73 static guint8 gst_sbc_calculate_crc8 (const guint8 * data, gint bits_crc);
74 static gsize gst_sbc_calc_framelen (guint subbands, GstSbcChannelMode ch_mode,
75 guint blocks, guint bitpool);
76 static gsize gst_sbc_parse_header (const guint8 * data, guint * rate,
77 guint * n_blocks, GstSbcChannelMode * ch_mode,
78 GstSbcAllocationMethod * alloc_method, guint * n_subbands, guint * bitpool);
80 #define parent_class gst_sbc_parse_parent_class
81 G_DEFINE_TYPE (GstSbcParse, gst_sbc_parse, GST_TYPE_BASE_PARSE);
84 gst_sbc_parse_class_init (GstSbcParseClass * klass)
86 GstBaseParseClass *baseparse_class = GST_BASE_PARSE_CLASS (klass);
87 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
89 GST_DEBUG_CATEGORY_INIT (sbcparse_debug, "sbcparse", 0, "SBC audio parser");
91 baseparse_class->start = GST_DEBUG_FUNCPTR (gst_sbc_parse_start);
92 baseparse_class->stop = GST_DEBUG_FUNCPTR (gst_sbc_parse_stop);
94 baseparse_class->handle_frame =
95 GST_DEBUG_FUNCPTR (gst_sbc_parse_handle_frame);
96 baseparse_class->get_sink_caps =
97 GST_DEBUG_FUNCPTR (gst_sbc_parse_get_sink_caps);
99 gst_element_class_add_pad_template (element_class,
100 gst_static_pad_template_get (&src_factory));
101 gst_element_class_add_pad_template (element_class,
102 gst_static_pad_template_get (&sink_factory));
104 gst_element_class_set_static_metadata (element_class, "SBC audio parser",
105 "Codec/Parser/Audio", "Parses an SBC bluetooth audio stream",
106 "Tim-Philipp Müller <tim.muller@collabora.co.uk>");
110 gst_sbc_parse_reset (GstSbcParse * sbcparse)
112 sbcparse->alloc_method = GST_SBC_ALLOCATION_METHOD_INVALID;
113 sbcparse->ch_mode = GST_SBC_CHANNEL_MODE_INVALID;
115 sbcparse->n_blocks = -1;
116 sbcparse->n_subbands = -1;
117 sbcparse->bitpool = -1;
121 gst_sbc_parse_init (GstSbcParse * sbcparse)
123 gst_sbc_parse_reset (sbcparse);
124 GST_PAD_SET_ACCEPT_INTERSECT (GST_BASE_PARSE_SINK_PAD (sbcparse));
128 gst_sbc_parse_start (GstBaseParse * parse)
130 gst_base_parse_set_min_frame_size (parse,
131 gst_sbc_calc_framelen (4, GST_SBC_CHANNEL_MODE_MONO, 4, 2));
133 gst_base_parse_set_has_timing_info (parse, FALSE);
135 gst_base_parse_set_syncable (parse, TRUE);
141 gst_sbc_parse_stop (GstBaseParse * parse)
143 gst_sbc_parse_reset (GST_SBC_PARSE (parse));
148 gst_sbc_channel_mode_get_name (GstSbcChannelMode ch_mode)
151 case GST_SBC_CHANNEL_MODE_MONO:
153 case GST_SBC_CHANNEL_MODE_DUAL:
155 case GST_SBC_CHANNEL_MODE_STEREO:
157 case GST_SBC_CHANNEL_MODE_JOINT_STEREO:
166 gst_sbc_allocation_method_get_name (GstSbcAllocationMethod alloc_method)
168 switch (alloc_method) {
169 case GST_SBC_ALLOCATION_METHOD_SNR:
171 case GST_SBC_ALLOCATION_METHOD_LOUDNESS:
180 gst_sbc_parse_handle_frame (GstBaseParse * parse, GstBaseParseFrame * frame,
183 GstSbcParse *sbcparse = GST_SBC_PARSE (parse);
184 GstSbcAllocationMethod alloc_method = GST_SBC_ALLOCATION_METHOD_INVALID;
185 GstSbcChannelMode ch_mode = GST_SBC_CHANNEL_MODE_INVALID;
187 guint rate = 0, n_blocks = 0, n_subbands = 0, bitpool = 0;
188 gsize frame_len, next_len;
191 gst_buffer_map (frame->buffer, &map, GST_MAP_READ);
193 g_assert (map.size >= 6);
195 frame_len = gst_sbc_parse_header (map.data, &rate, &n_blocks, &ch_mode,
196 &alloc_method, &n_subbands, &bitpool);
198 GST_LOG_OBJECT (parse, "frame_len: %u", (guint) frame_len);
203 if (sbcparse->alloc_method != alloc_method
204 || sbcparse->ch_mode != ch_mode
205 || sbcparse->rate != rate
206 || sbcparse->n_blocks != n_blocks
207 || sbcparse->n_subbands != n_subbands || sbcparse->bitpool != bitpool) {
211 /* FIXME: do all of these need to be in the caps? */
212 caps = gst_caps_new_simple ("audio/x-sbc", "rate", G_TYPE_INT, rate,
213 "channels", G_TYPE_INT, (ch_mode == GST_SBC_CHANNEL_MODE_MONO) ? 1 : 2,
214 "channel-mode", G_TYPE_STRING, gst_sbc_channel_mode_get_name (ch_mode),
215 "blocks", G_TYPE_INT, n_blocks, "subbands", G_TYPE_INT, n_subbands,
216 "allocation-method", G_TYPE_STRING,
217 gst_sbc_allocation_method_get_name (alloc_method),
218 "bitpool", G_TYPE_INT, bitpool, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
220 GST_INFO_OBJECT (sbcparse, "caps changed to %" GST_PTR_FORMAT, caps);
222 gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (sbcparse),
223 gst_event_new_caps (caps));
225 avg_bitrate = (8 * frame_len * rate) / (n_subbands * n_blocks);
226 gst_base_parse_set_average_bitrate (parse, avg_bitrate);
228 gst_base_parse_set_frame_rate (parse, rate, n_subbands * n_blocks, 0, 0);
230 sbcparse->alloc_method = alloc_method;
231 sbcparse->ch_mode = ch_mode;
232 sbcparse->rate = rate;
233 sbcparse->n_blocks = n_blocks;
234 sbcparse->n_subbands = n_subbands;
235 sbcparse->bitpool = bitpool;
237 gst_caps_unref (caps);
240 if (frame_len > map.size)
243 GST_BUFFER_OFFSET (frame->buffer) = GST_BUFFER_OFFSET_NONE;
244 GST_BUFFER_OFFSET_END (frame->buffer) = GST_BUFFER_OFFSET_NONE;
246 /* completely arbitrary limit, we only process data we already have,
247 * so we aren't introducing latency here */
248 max_frames = MIN (map.size / frame_len, n_blocks * n_subbands * 5);
249 GST_LOG_OBJECT (sbcparse, "parsing up to %d frames", max_frames);
251 for (i = 1; i < max_frames; ++i) {
252 next_len = gst_sbc_parse_header (map.data + (i * frame_len), &rate,
253 &n_blocks, &ch_mode, &alloc_method, &n_subbands, &bitpool);
255 if (next_len != frame_len || sbcparse->alloc_method != alloc_method ||
256 sbcparse->ch_mode != ch_mode || sbcparse->rate != rate ||
257 sbcparse->n_blocks != n_blocks || sbcparse->n_subbands != n_subbands ||
258 sbcparse->bitpool != bitpool) {
262 GST_LOG_OBJECT (sbcparse, "packing %d SBC frames into next output buffer", i);
264 /* Note: local n_subbands and n_blocks variables might be tainted if we
265 * bailed out of the loop above because of a header configuration mismatch */
266 gst_base_parse_set_frame_rate (parse, rate,
267 sbcparse->n_subbands * sbcparse->n_blocks * i, 0, 0);
269 gst_buffer_unmap (frame->buffer, &map);
270 return gst_base_parse_finish_frame (parse, frame, i * frame_len);
274 const guint8 *possible_sync;
276 GST_DEBUG_OBJECT (parse, "no sync, resyncing");
278 possible_sync = memchr (map.data, SBC_SYNCBYTE, map.size);
280 if (possible_sync != NULL)
281 *skipsize = (gint) (possible_sync - map.data);
283 *skipsize = map.size;
285 gst_buffer_unmap (frame->buffer, &map);
287 /* we could optimise things here by looping over the data and checking
288 * whether the sync is good or not instead of handing control back to
289 * the base class just to be called again */
294 GST_LOG_OBJECT (parse,
295 "need %" G_GSIZE_FORMAT " bytes, but only have %" G_GSIZE_FORMAT,
296 frame_len, map.size);
297 gst_base_parse_set_min_frame_size (parse, frame_len);
298 gst_buffer_unmap (frame->buffer, &map);
304 remove_fields (GstCaps * caps)
308 n = gst_caps_get_size (caps);
309 for (i = 0; i < n; i++) {
310 GstStructure *s = gst_caps_get_structure (caps, i);
312 gst_structure_remove_field (s, "parsed");
317 gst_sbc_parse_get_sink_caps (GstBaseParse * parse, GstCaps * filter)
319 GstCaps *peercaps, *templ;
322 templ = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse));
324 GstCaps *fcopy = gst_caps_copy (filter);
325 /* Remove the fields we convert */
326 remove_fields (fcopy);
327 peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), fcopy);
328 gst_caps_unref (fcopy);
330 peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), NULL);
333 /* Remove the parsed field */
334 peercaps = gst_caps_make_writable (peercaps);
335 remove_fields (peercaps);
337 res = gst_caps_intersect_full (peercaps, templ, GST_CAPS_INTERSECT_FIRST);
338 gst_caps_unref (peercaps);
344 GstCaps *intersection;
347 gst_caps_intersect_full (filter, res, GST_CAPS_INTERSECT_FIRST);
348 gst_caps_unref (res);
355 static const guint8 crc_table[256] = {
356 0x00, 0x1D, 0x3A, 0x27, 0x74, 0x69, 0x4E, 0x53,
357 0xE8, 0xF5, 0xD2, 0xCF, 0x9C, 0x81, 0xA6, 0xBB,
358 0xCD, 0xD0, 0xF7, 0xEA, 0xB9, 0xA4, 0x83, 0x9E,
359 0x25, 0x38, 0x1F, 0x02, 0x51, 0x4C, 0x6B, 0x76,
360 0x87, 0x9A, 0xBD, 0xA0, 0xF3, 0xEE, 0xC9, 0xD4,
361 0x6F, 0x72, 0x55, 0x48, 0x1B, 0x06, 0x21, 0x3C,
362 0x4A, 0x57, 0x70, 0x6D, 0x3E, 0x23, 0x04, 0x19,
363 0xA2, 0xBF, 0x98, 0x85, 0xD6, 0xCB, 0xEC, 0xF1,
364 0x13, 0x0E, 0x29, 0x34, 0x67, 0x7A, 0x5D, 0x40,
365 0xFB, 0xE6, 0xC1, 0xDC, 0x8F, 0x92, 0xB5, 0xA8,
366 0xDE, 0xC3, 0xE4, 0xF9, 0xAA, 0xB7, 0x90, 0x8D,
367 0x36, 0x2B, 0x0C, 0x11, 0x42, 0x5F, 0x78, 0x65,
368 0x94, 0x89, 0xAE, 0xB3, 0xE0, 0xFD, 0xDA, 0xC7,
369 0x7C, 0x61, 0x46, 0x5B, 0x08, 0x15, 0x32, 0x2F,
370 0x59, 0x44, 0x63, 0x7E, 0x2D, 0x30, 0x17, 0x0A,
371 0xB1, 0xAC, 0x8B, 0x96, 0xC5, 0xD8, 0xFF, 0xE2,
372 0x26, 0x3B, 0x1C, 0x01, 0x52, 0x4F, 0x68, 0x75,
373 0xCE, 0xD3, 0xF4, 0xE9, 0xBA, 0xA7, 0x80, 0x9D,
374 0xEB, 0xF6, 0xD1, 0xCC, 0x9F, 0x82, 0xA5, 0xB8,
375 0x03, 0x1E, 0x39, 0x24, 0x77, 0x6A, 0x4D, 0x50,
376 0xA1, 0xBC, 0x9B, 0x86, 0xD5, 0xC8, 0xEF, 0xF2,
377 0x49, 0x54, 0x73, 0x6E, 0x3D, 0x20, 0x07, 0x1A,
378 0x6C, 0x71, 0x56, 0x4B, 0x18, 0x05, 0x22, 0x3F,
379 0x84, 0x99, 0xBE, 0xA3, 0xF0, 0xED, 0xCA, 0xD7,
380 0x35, 0x28, 0x0F, 0x12, 0x41, 0x5C, 0x7B, 0x66,
381 0xDD, 0xC0, 0xE7, 0xFA, 0xA9, 0xB4, 0x93, 0x8E,
382 0xF8, 0xE5, 0xC2, 0xDF, 0x8C, 0x91, 0xB6, 0xAB,
383 0x10, 0x0D, 0x2A, 0x37, 0x64, 0x79, 0x5E, 0x43,
384 0xB2, 0xAF, 0x88, 0x95, 0xC6, 0xDB, 0xFC, 0xE1,
385 0x5A, 0x47, 0x60, 0x7D, 0x2E, 0x33, 0x14, 0x09,
386 0x7F, 0x62, 0x45, 0x58, 0x0B, 0x16, 0x31, 0x2C,
387 0x97, 0x8A, 0xAD, 0xB0, 0xE3, 0xFE, 0xD9, 0xC4
391 gst_sbc_calculate_crc8 (const guint8 * data, gint crc_bits)
396 while (crc_bits >= 8) {
397 crc = crc_table[crc ^ *data];
403 while (crc_bits > 0) {
404 gchar bit = ((octet ^ crc) & 0x80) >> 7;
406 crc = ((crc & 0x7f) << 1) ^ (bit ? 0x1d : 0);
416 gst_sbc_calc_framelen (guint subbands, GstSbcChannelMode ch_mode,
417 guint blocks, guint bitpool)
420 case GST_SBC_CHANNEL_MODE_MONO:
421 return 4 + (subbands * 1) / 2 + (blocks * 1 * bitpool) / 8;
422 case GST_SBC_CHANNEL_MODE_DUAL:
423 return 4 + (subbands * 2) / 2 + (blocks * 2 * bitpool) / 8;
424 case GST_SBC_CHANNEL_MODE_STEREO:
425 return 4 + (subbands * 2) / 2 + (blocks * bitpool) / 8;
426 case GST_SBC_CHANNEL_MODE_JOINT_STEREO:
427 return 4 + (subbands * 2) / 2 + (subbands + blocks * bitpool) / 8;
432 g_return_val_if_reached (0);
436 gst_sbc_parse_header (const guint8 * data, guint * rate, guint * n_blocks,
437 GstSbcChannelMode * ch_mode, GstSbcAllocationMethod * alloc_method,
438 guint * n_subbands, guint * bitpool)
440 static const guint16 sbc_rates[4] = { 16000, 32000, 44100, 48000 };
441 static const guint8 sbc_blocks[4] = { 4, 8, 12, 16 };
442 guint8 crc_data[2 + 1 + 8], crc_bits, i;
444 GST_MEMDUMP ("header", data, 8);
446 if (data[0] != SBC_SYNCBYTE)
449 *rate = sbc_rates[(data[1] >> 6) & 0x03];
450 *n_blocks = sbc_blocks[(data[1] >> 4) & 0x03];
451 *ch_mode = (GstSbcChannelMode) ((data[1] >> 2) & 0x03);
452 *alloc_method = (data[1] >> 1) & 0x01;
453 *n_subbands = (data[1] & 0x01) ? 8 : 4;
456 GST_TRACE ("rate=%u, n_blocks=%u, ch_mode=%u, alloc_method=%u, "
457 "n_subbands=%u, bitpool=%u", *rate, *n_blocks, *ch_mode, *alloc_method,
458 *n_subbands, *bitpool);
464 crc_data[0] = data[1];
465 crc_data[1] = data[2];
468 /* joint flags and RFA */
469 if (*ch_mode == GST_SBC_CHANNEL_MODE_JOINT_STEREO)
470 crc_bits += *n_subbands;
473 if (*ch_mode == GST_SBC_CHANNEL_MODE_MONO)
474 crc_bits += *n_subbands * 1 * 4;
476 crc_bits += *n_subbands * 2 * 4;
478 for (i = 16; i < crc_bits; i += 8) {
479 crc_data[i / 8] = data[1 + (i / 8) + 1];
483 crc_data[(i / 8) - 1] &= 0xF0;
486 GST_MEMDUMP ("crc bytes", crc_data, GST_ROUND_UP_8 (crc_bits) / 8);
487 if (gst_sbc_calculate_crc8 (crc_data, crc_bits) != data[3]) {
488 GST_LOG ("header CRC check failed, bits=%u, got 0x%02x, expected 0x%02x",
489 crc_bits, gst_sbc_calculate_crc8 (crc_data, crc_bits), data[3]);
493 return gst_sbc_calc_framelen (*n_subbands, *ch_mode, *n_blocks, *bitpool);