1 /*  GStreamer SBC audio decoder
2  *
3  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
4  *  Copyright (C) 2013       Tim-Philipp Müller <tim centricular net>
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2.1 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21 
22 /**
23  * SECTION:element-sbdec
24  * @title: sbdec
25  *
26  * This element decodes a Bluetooth SBC audio streams to raw integer PCM audio
27  *
28  * ## Example pipelines
29  * |[
30  * gst-launch-1.0 -v filesrc location=audio.sbc ! sbcparse ! sbcdec ! audioconvert ! audioresample ! autoaudiosink
31  * ]| Decode a raw SBC file.
32  *
33  */
34 
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38 
39 #include <string.h>
40 
41 #include "gstsbcdec.h"
42 
43 /* FIXME: where does this come from? how is it derived? */
44 #define BUF_SIZE 8192
45 
46 GST_DEBUG_CATEGORY_STATIC (sbc_dec_debug);
47 #define GST_CAT_DEFAULT sbc_dec_debug
48 
49 #define parent_class gst_sbc_dec_parent_class
50 G_DEFINE_TYPE (GstSbcDec, gst_sbc_dec, GST_TYPE_AUDIO_DECODER);
51 
52 static GstStaticPadTemplate sbc_dec_sink_factory =
53 GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
54     GST_STATIC_CAPS ("audio/x-sbc, channels = (int) [ 1, 2 ], "
55         "rate = (int) { 16000, 32000, 44100, 48000 }, "
56         "parsed = (boolean) true"));
57 
58 static GstStaticPadTemplate sbc_dec_src_factory =
59 GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
60     GST_STATIC_CAPS ("audio/x-raw, format=" GST_AUDIO_NE (S16) ", "
61         "rate = (int) { 16000, 32000, 44100, 48000 }, "
62         "channels = (int) [ 1, 2 ], layout=interleaved"));
63 
64 static GstFlowReturn
gst_sbc_dec_handle_frame(GstAudioDecoder * audio_dec,GstBuffer * buf)65 gst_sbc_dec_handle_frame (GstAudioDecoder * audio_dec, GstBuffer * buf)
66 {
67   GstSbcDec *dec = GST_SBC_DEC (audio_dec);
68   GstBuffer *outbuf = NULL;
69   GstMapInfo out_map;
70   GstMapInfo in_map;
71   gsize output_size;
72   guint num_frames, i;
73 
74   /* no fancy draining */
75   if (G_UNLIKELY (buf == NULL))
76     return GST_FLOW_OK;
77 
78   gst_buffer_map (buf, &in_map, GST_MAP_READ);
79 
80   if (G_UNLIKELY (in_map.size == 0))
81     goto done;
82 
83   /* we assume all frames are of the same size, this is implied by the
84    * input caps applying to the whole input buffer, and the parser should
85    * also have made sure of that */
86   if (G_UNLIKELY (in_map.size % dec->frame_len != 0))
87     goto mixed_frames;
88 
89   num_frames = in_map.size / dec->frame_len;
90   output_size = num_frames * dec->samples_per_frame * sizeof (gint16);
91 
92   outbuf = gst_audio_decoder_allocate_output_buffer (audio_dec, output_size);
93 
94   if (outbuf == NULL)
95     goto no_buffer;
96 
97   gst_buffer_map (outbuf, &out_map, GST_MAP_WRITE);
98 
99   for (i = 0; i < num_frames; ++i) {
100     gssize ret;
101     gsize written;
102 
103     ret = sbc_decode (&dec->sbc, in_map.data + (i * dec->frame_len),
104         dec->frame_len, out_map.data + (i * dec->samples_per_frame * 2),
105         dec->samples_per_frame * 2, &written);
106 
107     if (ret <= 0 || written != (dec->samples_per_frame * 2)) {
108       GST_WARNING_OBJECT (dec, "decoding error, ret = %" G_GSSIZE_FORMAT ", "
109           "written = %" G_GSSIZE_FORMAT, ret, written);
110       break;
111     }
112   }
113 
114   gst_buffer_unmap (outbuf, &out_map);
115 
116   if (i > 0)
117     gst_buffer_set_size (outbuf, i * dec->samples_per_frame * 2);
118   else
119     gst_buffer_replace (&outbuf, NULL);
120 
121 done:
122 
123   gst_buffer_unmap (buf, &in_map);
124 
125   return gst_audio_decoder_finish_frame (audio_dec, outbuf, 1);
126 
127 /* ERRORS */
128 mixed_frames:
129   {
130     GST_WARNING_OBJECT (dec, "inconsistent input data/frames, skipping");
131     goto done;
132   }
133 no_buffer:
134   {
135     GST_ERROR_OBJECT (dec, "could not allocate output buffer");
136     goto done;
137   }
138 }
139 
140 static gboolean
gst_sbc_dec_set_format(GstAudioDecoder * audio_dec,GstCaps * caps)141 gst_sbc_dec_set_format (GstAudioDecoder * audio_dec, GstCaps * caps)
142 {
143   GstSbcDec *dec = GST_SBC_DEC (audio_dec);
144   const gchar *channel_mode;
145   GstAudioInfo info;
146   GstStructure *s;
147   gint channels, rate, subbands, blocks, bitpool;
148 
149   s = gst_caps_get_structure (caps, 0);
150   gst_structure_get_int (s, "channels", &channels);
151   gst_structure_get_int (s, "rate", &rate);
152 
153   /* save input format */
154   channel_mode = gst_structure_get_string (s, "channel-mode");
155   if (channel_mode == NULL ||
156       !gst_structure_get_int (s, "subbands", &subbands) ||
157       !gst_structure_get_int (s, "blocks", &blocks) ||
158       !gst_structure_get_int (s, "bitpool", &bitpool))
159     return FALSE;
160 
161   if (strcmp (channel_mode, "mono") == 0) {
162     dec->frame_len = 4 + (subbands * 1) / 2 + ((blocks * 1 * bitpool) + 7) / 8;
163   } else if (strcmp (channel_mode, "dual") == 0) {
164     dec->frame_len = 4 + (subbands * 2) / 2 + ((blocks * 2 * bitpool) + 7) / 8;
165   } else if (strcmp (channel_mode, "stereo") == 0) {
166     dec->frame_len = 4 + (subbands * 2) / 2 + ((blocks * bitpool) + 7) / 8;
167   } else if (strcmp (channel_mode, "joint") == 0) {
168     dec->frame_len =
169         4 + (subbands * 2) / 2 + ((subbands + blocks * bitpool) + 7) / 8;
170   } else {
171     return FALSE;
172   }
173 
174   dec->samples_per_frame = channels * blocks * subbands;
175 
176   GST_INFO_OBJECT (dec, "frame len: %" G_GSIZE_FORMAT ", samples per frame "
177       "%" G_GSIZE_FORMAT, dec->frame_len, dec->samples_per_frame);
178 
179   /* set up output format */
180   gst_audio_info_init (&info);
181   gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_S16, rate, channels, NULL);
182   gst_audio_decoder_set_output_format (audio_dec, &info);
183 
184   return TRUE;
185 }
186 
187 static gboolean
gst_sbc_dec_start(GstAudioDecoder * dec)188 gst_sbc_dec_start (GstAudioDecoder * dec)
189 {
190   GstSbcDec *sbcdec = GST_SBC_DEC (dec);
191 
192   GST_INFO_OBJECT (dec, "Setup subband codec");
193   sbc_init (&sbcdec->sbc, 0);
194 
195   return TRUE;
196 }
197 
198 static gboolean
gst_sbc_dec_stop(GstAudioDecoder * dec)199 gst_sbc_dec_stop (GstAudioDecoder * dec)
200 {
201   GstSbcDec *sbcdec = GST_SBC_DEC (dec);
202 
203   GST_INFO_OBJECT (sbcdec, "Finish subband codec");
204   sbc_finish (&sbcdec->sbc);
205   sbcdec->samples_per_frame = 0;
206   sbcdec->frame_len = 0;
207 
208   return TRUE;
209 }
210 
211 static void
gst_sbc_dec_class_init(GstSbcDecClass * klass)212 gst_sbc_dec_class_init (GstSbcDecClass * klass)
213 {
214   GstAudioDecoderClass *audio_decoder_class = (GstAudioDecoderClass *) klass;
215   GstElementClass *element_class = (GstElementClass *) klass;
216 
217   audio_decoder_class->start = GST_DEBUG_FUNCPTR (gst_sbc_dec_start);
218   audio_decoder_class->stop = GST_DEBUG_FUNCPTR (gst_sbc_dec_stop);
219   audio_decoder_class->set_format = GST_DEBUG_FUNCPTR (gst_sbc_dec_set_format);
220   audio_decoder_class->handle_frame =
221       GST_DEBUG_FUNCPTR (gst_sbc_dec_handle_frame);
222 
223   gst_element_class_add_static_pad_template (element_class,
224       &sbc_dec_sink_factory);
225   gst_element_class_add_static_pad_template (element_class,
226       &sbc_dec_src_factory);
227 
228   gst_element_class_set_static_metadata (element_class,
229       "Bluetooth SBC audio decoder", "Codec/Decoder/Audio",
230       "Decode an SBC audio stream", "Marcel Holtmann <marcel@holtmann.org>");
231 
232   GST_DEBUG_CATEGORY_INIT (sbc_dec_debug, "sbcdec", 0, "SBC decoding element");
233 }
234 
235 static void
gst_sbc_dec_init(GstSbcDec * dec)236 gst_sbc_dec_init (GstSbcDec * dec)
237 {
238   gst_audio_decoder_set_needs_format (GST_AUDIO_DECODER (dec), TRUE);
239   gst_audio_decoder_set_use_default_pad_acceptcaps (GST_AUDIO_DECODER_CAST
240       (dec), TRUE);
241   GST_PAD_SET_ACCEPT_TEMPLATE (GST_AUDIO_DECODER_SINK_PAD (dec));
242 
243   dec->samples_per_frame = 0;
244   dec->frame_len = 0;
245 }
246