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