1 /* GStreamer SBC audio encoder
2 * Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
3 * Copyright (C) 2013 Tim-Philipp Müller <tim centricular net>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 */
20
21 /**
22 * SECTION:element-sbenc
23 * @title: sbenc
24 *
25 * This element encodes raw integer PCM audio into a Bluetooth SBC audio.
26 *
27 * Encoding parameters such as blocks, subbands, bitpool, channel-mode, and
28 * allocation-mode can be set by adding a capsfilter element with appropriate
29 * filtercaps after the sbcenc encoder element.
30 *
31 * ## Example pipelines
32 * |[
33 * gst-launch-1.0 -v audiotestsrc ! sbcenc ! rtpsbcpay ! udpsink
34 * ]| Encode a sine wave into SBC, RTP payload it and send over the network using UDP
35 *
36 */
37
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif
41
42 #include <string.h>
43
44 #include "gstsbcenc.h"
45
46 GST_DEBUG_CATEGORY_STATIC (sbc_enc_debug);
47 #define GST_CAT_DEFAULT sbc_enc_debug
48
49 G_DEFINE_TYPE (GstSbcEnc, gst_sbc_enc, GST_TYPE_AUDIO_ENCODER);
50 GST_ELEMENT_REGISTER_DEFINE (sbcenc, "sbcenc", GST_RANK_NONE, GST_TYPE_SBC_ENC);
51
52 static GstStaticPadTemplate sbc_enc_sink_factory =
53 GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
54 GST_STATIC_CAPS ("audio/x-raw, format=" GST_AUDIO_NE (S16) ", "
55 "rate = (int) { 16000, 32000, 44100, 48000 }, "
56 "channels = (int) [ 1, 2 ]"));
57
58 static GstStaticPadTemplate sbc_enc_src_factory =
59 GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
60 GST_STATIC_CAPS ("audio/x-sbc, "
61 "rate = (int) { 16000, 32000, 44100, 48000 }, "
62 "channels = (int) [ 1, 2 ], "
63 "channel-mode = (string) { mono, dual, stereo, joint }, "
64 "blocks = (int) { 4, 8, 12, 16 }, "
65 "subbands = (int) { 4, 8 }, "
66 "allocation-method = (string) { snr, loudness }, "
67 "bitpool = (int) [ 2, 64 ]"));
68
69
70 static gboolean gst_sbc_enc_start (GstAudioEncoder * enc);
71 static gboolean gst_sbc_enc_stop (GstAudioEncoder * enc);
72 static gboolean gst_sbc_enc_set_format (GstAudioEncoder * enc,
73 GstAudioInfo * info);
74 static GstFlowReturn gst_sbc_enc_handle_frame (GstAudioEncoder * enc,
75 GstBuffer * buffer);
76
77 static gboolean
gst_sbc_enc_set_format(GstAudioEncoder * audio_enc,GstAudioInfo * info)78 gst_sbc_enc_set_format (GstAudioEncoder * audio_enc, GstAudioInfo * info)
79 {
80 const gchar *allocation_method, *channel_mode;
81 GstSbcEnc *enc = GST_SBC_ENC (audio_enc);
82 GstStructure *s;
83 GstCaps *caps, *filter_caps;
84 GstCaps *output_caps = NULL;
85 guint sampleframes_per_frame;
86
87 enc->rate = GST_AUDIO_INFO_RATE (info);
88 enc->channels = GST_AUDIO_INFO_CHANNELS (info);
89
90 /* negotiate output format based on downstream caps restrictions */
91 caps = gst_pad_get_allowed_caps (GST_AUDIO_ENCODER_SRC_PAD (enc));
92
93 if (caps == NULL)
94 caps = gst_static_pad_template_get_caps (&sbc_enc_src_factory);
95 else if (gst_caps_is_empty (caps))
96 goto failure;
97
98 /* fixate output caps */
99 filter_caps = gst_caps_new_simple ("audio/x-sbc", "rate", G_TYPE_INT,
100 enc->rate, "channels", G_TYPE_INT, enc->channels, NULL);
101 output_caps = gst_caps_intersect (caps, filter_caps);
102 gst_caps_unref (filter_caps);
103
104 if (output_caps == NULL || gst_caps_is_empty (output_caps)) {
105 GST_WARNING_OBJECT (enc, "Couldn't negotiate output caps with input rate "
106 "%d and input channels %d and allowed output caps %" GST_PTR_FORMAT,
107 enc->rate, enc->channels, caps);
108 goto failure;
109 }
110
111 gst_caps_unref (caps);
112 caps = NULL;
113
114 GST_DEBUG_OBJECT (enc, "fixating caps %" GST_PTR_FORMAT, output_caps);
115 output_caps = gst_caps_truncate (output_caps);
116 s = gst_caps_get_structure (output_caps, 0);
117 if (enc->channels == 1)
118 gst_structure_fixate_field_string (s, "channel-mode", "mono");
119 else
120 gst_structure_fixate_field_string (s, "channel-mode", "joint");
121
122 gst_structure_fixate_field_nearest_int (s, "bitpool", 64);
123 gst_structure_fixate_field_nearest_int (s, "blocks", 16);
124 gst_structure_fixate_field_nearest_int (s, "subbands", 8);
125 gst_structure_fixate_field_string (s, "allocation-method", "loudness");
126 s = NULL;
127
128 /* in case there's anything else left to fixate */
129 output_caps = gst_caps_fixate (output_caps);
130 gst_caps_set_simple (output_caps, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
131
132 GST_INFO_OBJECT (enc, "output caps %" GST_PTR_FORMAT, output_caps);
133
134 /* let's see what we fixated to */
135 s = gst_caps_get_structure (output_caps, 0);
136 gst_structure_get_int (s, "blocks", &enc->blocks);
137 gst_structure_get_int (s, "subbands", &enc->subbands);
138 gst_structure_get_int (s, "bitpool", &enc->bitpool);
139 allocation_method = gst_structure_get_string (s, "allocation-method");
140 channel_mode = gst_structure_get_string (s, "channel-mode");
141
142 /* We want channel-mode and channels coherent */
143 if (enc->channels == 1) {
144 if (g_strcmp0 (channel_mode, "mono") != 0) {
145 GST_ERROR_OBJECT (enc, "Can't have channel-mode '%s' for 1 channel",
146 channel_mode);
147 goto failure;
148 }
149 } else {
150 if (g_strcmp0 (channel_mode, "joint") != 0 &&
151 g_strcmp0 (channel_mode, "stereo") != 0 &&
152 g_strcmp0 (channel_mode, "dual") != 0) {
153 GST_ERROR_OBJECT (enc, "Can't have channel-mode '%s' for 2 channels",
154 channel_mode);
155 goto failure;
156 }
157 }
158
159 /* we want to be handed all available samples in handle_frame, but always
160 * enough to encode a frame */
161 sampleframes_per_frame = enc->blocks * enc->subbands;
162 gst_audio_encoder_set_frame_samples_min (audio_enc, sampleframes_per_frame);
163 gst_audio_encoder_set_frame_samples_max (audio_enc, sampleframes_per_frame);
164 gst_audio_encoder_set_frame_max (audio_enc, 0);
165
166 /* FIXME: what to do with left-over samples at the end? can we encode them? */
167 gst_audio_encoder_set_hard_min (audio_enc, TRUE);
168
169 /* and configure encoder based on the output caps we negotiated */
170 if (enc->rate == 16000)
171 enc->sbc.frequency = SBC_FREQ_16000;
172 else if (enc->rate == 32000)
173 enc->sbc.frequency = SBC_FREQ_32000;
174 else if (enc->rate == 44100)
175 enc->sbc.frequency = SBC_FREQ_44100;
176 else if (enc->rate == 48000)
177 enc->sbc.frequency = SBC_FREQ_48000;
178 else
179 goto failure;
180
181 if (enc->blocks == 4)
182 enc->sbc.blocks = SBC_BLK_4;
183 else if (enc->blocks == 8)
184 enc->sbc.blocks = SBC_BLK_8;
185 else if (enc->blocks == 12)
186 enc->sbc.blocks = SBC_BLK_12;
187 else if (enc->blocks == 16)
188 enc->sbc.blocks = SBC_BLK_16;
189 else
190 goto failure;
191
192 enc->sbc.subbands = (enc->subbands == 4) ? SBC_SB_4 : SBC_SB_8;
193 enc->sbc.bitpool = enc->bitpool;
194
195 if (channel_mode == NULL || allocation_method == NULL)
196 goto failure;
197
198 if (strcmp (channel_mode, "joint") == 0)
199 enc->sbc.mode = SBC_MODE_JOINT_STEREO;
200 else if (strcmp (channel_mode, "stereo") == 0)
201 enc->sbc.mode = SBC_MODE_STEREO;
202 else if (strcmp (channel_mode, "dual") == 0)
203 enc->sbc.mode = SBC_MODE_DUAL_CHANNEL;
204 else if (strcmp (channel_mode, "mono") == 0)
205 enc->sbc.mode = SBC_MODE_MONO;
206 else if (strcmp (channel_mode, "auto") == 0)
207 enc->sbc.mode = SBC_MODE_JOINT_STEREO;
208 else
209 goto failure;
210
211 if (strcmp (allocation_method, "loudness") == 0)
212 enc->sbc.allocation = SBC_AM_LOUDNESS;
213 else if (strcmp (allocation_method, "snr") == 0)
214 enc->sbc.allocation = SBC_AM_SNR;
215 else
216 goto failure;
217
218 if (!gst_audio_encoder_set_output_format (audio_enc, output_caps))
219 goto failure;
220
221 return gst_audio_encoder_negotiate (audio_enc);
222
223 failure:
224 if (output_caps)
225 gst_caps_unref (output_caps);
226 if (caps)
227 gst_caps_unref (caps);
228 return FALSE;
229 }
230
231 static GstFlowReturn
gst_sbc_enc_handle_frame(GstAudioEncoder * audio_enc,GstBuffer * buffer)232 gst_sbc_enc_handle_frame (GstAudioEncoder * audio_enc, GstBuffer * buffer)
233 {
234 GstSbcEnc *enc = GST_SBC_ENC (audio_enc);
235 GstMapInfo in_map, out_map;
236 GstBuffer *outbuf = NULL;
237 guint samples_per_frame, frames, i = 0;
238
239 /* no fancy draining */
240 if (buffer == NULL)
241 return GST_FLOW_OK;
242
243 if (G_UNLIKELY (enc->channels == 0 || enc->blocks == 0 || enc->subbands == 0))
244 return GST_FLOW_NOT_NEGOTIATED;
245
246 samples_per_frame = enc->channels * enc->blocks * enc->subbands;
247
248 if (!gst_buffer_map (buffer, &in_map, GST_MAP_READ))
249 goto map_failed;
250
251 frames = in_map.size / (samples_per_frame * sizeof (gint16));
252
253 GST_LOG_OBJECT (enc,
254 "encoding %" G_GSIZE_FORMAT " samples into %u SBC frames",
255 in_map.size / (enc->channels * sizeof (gint16)), frames);
256
257 if (frames > 0) {
258 gsize frame_len;
259
260 frame_len = sbc_get_frame_length (&enc->sbc);
261 outbuf = gst_audio_encoder_allocate_output_buffer (audio_enc,
262 frames * frame_len);
263
264 if (outbuf == NULL)
265 goto no_buffer;
266
267 gst_buffer_map (outbuf, &out_map, GST_MAP_WRITE);
268
269 for (i = 0; i < frames; ++i) {
270 gssize ret, written = 0;
271
272 ret = sbc_encode (&enc->sbc, in_map.data + (i * samples_per_frame * 2),
273 samples_per_frame * 2, out_map.data + (i * frame_len), frame_len,
274 &written);
275
276 if (ret < 0 || written != frame_len) {
277 GST_WARNING_OBJECT (enc, "encoding error, ret = %" G_GSSIZE_FORMAT ", "
278 "written = %" G_GSSIZE_FORMAT, ret, written);
279 break;
280 }
281 }
282
283 gst_buffer_unmap (outbuf, &out_map);
284
285 if (i > 0)
286 gst_buffer_set_size (outbuf, i * frame_len);
287 else
288 gst_buffer_replace (&outbuf, NULL);
289 }
290
291 gst_buffer_unmap (buffer, &in_map);
292
293 return gst_audio_encoder_finish_frame (audio_enc, outbuf,
294 i * (samples_per_frame / enc->channels));
295
296 /* ERRORS */
297 no_buffer:
298 {
299 gst_buffer_unmap (buffer, &in_map);
300 GST_ELEMENT_ERROR (enc, STREAM, FAILED, (NULL),
301 ("Could not allocate output buffer"));
302 return GST_FLOW_ERROR;
303 }
304 map_failed:
305 {
306 GST_ELEMENT_ERROR (enc, STREAM, FAILED, (NULL),
307 ("Could not allocate output buffer"));
308 return GST_FLOW_ERROR;
309 }
310 }
311
312 static gboolean
gst_sbc_enc_start(GstAudioEncoder * audio_enc)313 gst_sbc_enc_start (GstAudioEncoder * audio_enc)
314 {
315 GstSbcEnc *enc = GST_SBC_ENC (audio_enc);
316
317 GST_INFO_OBJECT (enc, "Setup subband codec");
318 sbc_init (&enc->sbc, 0);
319
320 return TRUE;
321 }
322
323 static gboolean
gst_sbc_enc_stop(GstAudioEncoder * audio_enc)324 gst_sbc_enc_stop (GstAudioEncoder * audio_enc)
325 {
326 GstSbcEnc *enc = GST_SBC_ENC (audio_enc);
327
328 GST_INFO_OBJECT (enc, "Finish subband codec");
329 sbc_finish (&enc->sbc);
330
331 enc->subbands = 0;
332 enc->blocks = 0;
333 enc->rate = 0;
334 enc->channels = 0;
335 enc->bitpool = 0;
336
337 return TRUE;
338 }
339
340 static void
gst_sbc_enc_class_init(GstSbcEncClass * klass)341 gst_sbc_enc_class_init (GstSbcEncClass * klass)
342 {
343 GstAudioEncoderClass *encoder_class = GST_AUDIO_ENCODER_CLASS (klass);
344 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
345
346 encoder_class->start = GST_DEBUG_FUNCPTR (gst_sbc_enc_start);
347 encoder_class->stop = GST_DEBUG_FUNCPTR (gst_sbc_enc_stop);
348 encoder_class->set_format = GST_DEBUG_FUNCPTR (gst_sbc_enc_set_format);
349 encoder_class->handle_frame = GST_DEBUG_FUNCPTR (gst_sbc_enc_handle_frame);
350
351 gst_element_class_add_static_pad_template (element_class,
352 &sbc_enc_sink_factory);
353 gst_element_class_add_static_pad_template (element_class,
354 &sbc_enc_src_factory);
355
356 gst_element_class_set_static_metadata (element_class,
357 "Bluetooth SBC audio encoder", "Codec/Encoder/Audio",
358 "Encode an SBC audio stream", "Marcel Holtmann <marcel@holtmann.org>");
359
360 GST_DEBUG_CATEGORY_INIT (sbc_enc_debug, "sbcenc", 0, "SBC encoding element");
361 }
362
363 static void
gst_sbc_enc_init(GstSbcEnc * self)364 gst_sbc_enc_init (GstSbcEnc * self)
365 {
366 GST_PAD_SET_ACCEPT_TEMPLATE (GST_AUDIO_ENCODER_SINK_PAD (self));
367 self->subbands = 0;
368 self->blocks = 0;
369 self->rate = 0;
370 self->channels = 0;
371 self->bitpool = 0;
372 }
373