Fix build break for rpm
[framework/connectivity/bluez.git] / audio / gstsbcenc.c
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
6  *
7  *
8  *  This library is free software; you can redistribute it and/or
9  *  modify it under the terms of the GNU Lesser General Public
10  *  License as published by the Free Software Foundation; either
11  *  version 2.1 of the License, or (at your option) any later version.
12  *
13  *  This library is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  *  Lesser General Public License for more details.
17  *
18  *  You should have received a copy of the GNU Lesser General Public
19  *  License along with this library; if not, write to the Free Software
20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <string.h>
29
30 #include "gstpragma.h"
31 #include "gstsbcutil.h"
32 #include "gstsbcenc.h"
33
34 #define SBC_ENC_DEFAULT_MODE SBC_MODE_AUTO
35 #define SBC_ENC_DEFAULT_BLOCKS 0
36 #define SBC_ENC_DEFAULT_SUB_BANDS 0
37 #define SBC_ENC_DEFAULT_ALLOCATION SBC_AM_AUTO
38 #define SBC_ENC_DEFAULT_RATE 0
39 #define SBC_ENC_DEFAULT_CHANNELS 0
40
41 #define SBC_ENC_BITPOOL_AUTO 1
42 #define SBC_ENC_BITPOOL_MIN 2
43 #define SBC_ENC_BITPOOL_MIN_STR "2"
44 #define SBC_ENC_BITPOOL_MAX 64
45 #define SBC_ENC_BITPOOL_MAX_STR "64"
46
47 GST_DEBUG_CATEGORY_STATIC(sbc_enc_debug);
48 #define GST_CAT_DEFAULT sbc_enc_debug
49
50 #define GST_TYPE_SBC_MODE (gst_sbc_mode_get_type())
51
52 static GType gst_sbc_mode_get_type(void)
53 {
54         static GType sbc_mode_type = 0;
55         static GEnumValue sbc_modes[] = {
56                 {  SBC_MODE_MONO,               "Mono",         "mono"  },
57                 {  SBC_MODE_DUAL_CHANNEL,       "Dual Channel", "dual"  },
58                 {  SBC_MODE_STEREO,             "Stereo",       "stereo"},
59                 {  SBC_MODE_JOINT_STEREO,       "Joint Stereo", "joint" },
60                 {  SBC_MODE_AUTO,               "Auto",         "auto"  },
61                 { -1, NULL, NULL}
62         };
63
64         if (!sbc_mode_type)
65                 sbc_mode_type = g_enum_register_static("GstSbcMode", sbc_modes);
66
67         return sbc_mode_type;
68 }
69
70 #define GST_TYPE_SBC_ALLOCATION (gst_sbc_allocation_get_type())
71
72 static GType gst_sbc_allocation_get_type(void)
73 {
74         static GType sbc_allocation_type = 0;
75         static GEnumValue sbc_allocations[] = {
76                 { SBC_AM_LOUDNESS,      "Loudness",     "loudness" },
77                 { SBC_AM_SNR,           "SNR",          "snr" },
78                 { SBC_AM_AUTO,          "Auto",         "auto" },
79                 { -1, NULL, NULL}
80         };
81
82         if (!sbc_allocation_type)
83                 sbc_allocation_type = g_enum_register_static(
84                                 "GstSbcAllocation", sbc_allocations);
85
86         return sbc_allocation_type;
87 }
88
89 #define GST_TYPE_SBC_BLOCKS (gst_sbc_blocks_get_type())
90
91 static GType gst_sbc_blocks_get_type(void)
92 {
93         static GType sbc_blocks_type = 0;
94         static GEnumValue sbc_blocks[] = {
95                 { 0,    "Auto",         "auto" },
96                 { 4,    "4",            "4" },
97                 { 8,    "8",            "8" },
98                 { 12,   "12",           "12" },
99                 { 16,   "16",           "16" },
100                 { -1, NULL, NULL}
101         };
102
103         if (!sbc_blocks_type)
104                 sbc_blocks_type = g_enum_register_static(
105                                 "GstSbcBlocks", sbc_blocks);
106
107         return sbc_blocks_type;
108 }
109
110 #define GST_TYPE_SBC_SUBBANDS (gst_sbc_subbands_get_type())
111
112 static GType gst_sbc_subbands_get_type(void)
113 {
114         static GType sbc_subbands_type = 0;
115         static GEnumValue sbc_subbands[] = {
116                 { 0,    "Auto",         "auto" },
117                 { 4,    "4 subbands",   "4" },
118                 { 8,    "8 subbands",   "8" },
119                 { -1, NULL, NULL}
120         };
121
122         if (!sbc_subbands_type)
123                 sbc_subbands_type = g_enum_register_static(
124                                 "GstSbcSubbands", sbc_subbands);
125
126         return sbc_subbands_type;
127 }
128
129 enum {
130         PROP_0,
131         PROP_MODE,
132         PROP_ALLOCATION,
133         PROP_BLOCKS,
134         PROP_SUBBANDS,
135         PROP_BITPOOL
136 };
137
138 GST_BOILERPLATE(GstSbcEnc, gst_sbc_enc, GstElement, GST_TYPE_ELEMENT);
139
140 static const GstElementDetails sbc_enc_details =
141         GST_ELEMENT_DETAILS("Bluetooth SBC encoder",
142                                 "Codec/Encoder/Audio",
143                                 "Encode a SBC audio stream",
144                                 "Marcel Holtmann <marcel@holtmann.org>");
145
146 static GstStaticPadTemplate sbc_enc_sink_factory =
147         GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
148                 GST_STATIC_CAPS("audio/x-raw-int, "
149                                 "rate = (int) { 16000, 32000, 44100, 48000 }, "
150                                 "channels = (int) [ 1, 2 ], "
151                                 "endianness = (int) BYTE_ORDER, "
152                                 "signed = (boolean) true, "
153                                 "width = (int) 16, "
154                                 "depth = (int) 16"));
155
156 static GstStaticPadTemplate sbc_enc_src_factory =
157         GST_STATIC_PAD_TEMPLATE("src", GST_PAD_SRC, GST_PAD_ALWAYS,
158                 GST_STATIC_CAPS("audio/x-sbc, "
159                                 "rate = (int) { 16000, 32000, 44100, 48000 }, "
160                                 "channels = (int) [ 1, 2 ], "
161                                 "mode = (string) { \"mono\", \"dual\", \"stereo\", \"joint\" }, "
162                                 "blocks = (int) { 4, 8, 12, 16 }, "
163                                 "subbands = (int) { 4, 8 }, "
164                                 "allocation = (string) { \"snr\", \"loudness\" }, "
165                                 "bitpool = (int) [ " SBC_ENC_BITPOOL_MIN_STR
166                                 ", " SBC_ENC_BITPOOL_MAX_STR " ]"));
167
168 gboolean gst_sbc_enc_fill_sbc_params(GstSbcEnc *enc, GstCaps *caps);
169
170 static GstCaps *sbc_enc_generate_srcpad_caps(GstSbcEnc *enc)
171 {
172         GstCaps *src_caps;
173         GstStructure *structure;
174         GEnumValue *enum_value;
175         GEnumClass *enum_class;
176         GValue *value;
177
178         src_caps = gst_caps_copy(gst_pad_get_pad_template_caps(enc->srcpad));
179         structure = gst_caps_get_structure(src_caps, 0);
180
181         value = g_new0(GValue, 1);
182
183         if (enc->rate != 0)
184                 gst_sbc_util_set_structure_int_param(structure, "rate",
185                         enc->rate, value);
186
187         if (enc->channels != 0)
188                 gst_sbc_util_set_structure_int_param(structure, "channels",
189                         enc->channels, value);
190
191         if (enc->subbands != 0)
192                 gst_sbc_util_set_structure_int_param(structure, "subbands",
193                         enc->subbands, value);
194
195         if (enc->blocks != 0)
196                 gst_sbc_util_set_structure_int_param(structure, "blocks",
197                         enc->blocks, value);
198
199         if (enc->bitpool != SBC_ENC_BITPOOL_AUTO)
200                 gst_sbc_util_set_structure_int_param(structure, "bitpool",
201                         enc->bitpool, value);
202
203         if (enc->mode != SBC_ENC_DEFAULT_MODE) {
204                 enum_class = g_type_class_ref(GST_TYPE_SBC_MODE);
205                 enum_value = g_enum_get_value(enum_class, enc->mode);
206                 gst_sbc_util_set_structure_string_param(structure, "mode",
207                         enum_value->value_nick, value);
208                 g_type_class_unref(enum_class);
209         }
210
211         if (enc->allocation != SBC_AM_AUTO) {
212                 enum_class = g_type_class_ref(GST_TYPE_SBC_ALLOCATION);
213                 enum_value = g_enum_get_value(enum_class, enc->allocation);
214                 gst_sbc_util_set_structure_string_param(structure, "allocation",
215                         enum_value->value_nick, value);
216                 g_type_class_unref(enum_class);
217         }
218
219         g_free(value);
220
221         return src_caps;
222 }
223
224 static GstCaps *sbc_enc_src_getcaps(GstPad *pad)
225 {
226         GstSbcEnc *enc;
227
228         enc = GST_SBC_ENC(GST_PAD_PARENT(pad));
229
230         return sbc_enc_generate_srcpad_caps(enc);
231 }
232
233 static gboolean sbc_enc_src_setcaps(GstPad *pad, GstCaps *caps)
234 {
235         GstSbcEnc *enc = GST_SBC_ENC(GST_PAD_PARENT(pad));
236
237         GST_LOG_OBJECT(enc, "setting srcpad caps");
238
239         return gst_sbc_enc_fill_sbc_params(enc, caps);
240 }
241
242 static GstCaps *sbc_enc_src_caps_fixate(GstSbcEnc *enc, GstCaps *caps)
243 {
244         gchar *error_message = NULL;
245         GstCaps *result;
246
247         result = gst_sbc_util_caps_fixate(caps, &error_message);
248
249         if (!result) {
250                 GST_WARNING_OBJECT(enc, "Invalid input caps caused parsing "
251                                 "error: %s", error_message);
252                 g_free(error_message);
253                 return NULL;
254         }
255
256         return result;
257 }
258
259 static GstCaps *sbc_enc_get_fixed_srcpad_caps(GstSbcEnc *enc)
260 {
261         GstCaps *caps;
262         gboolean res = TRUE;
263         GstCaps *result_caps = NULL;
264
265         caps = gst_pad_get_allowed_caps(enc->srcpad);
266         if (caps == NULL)
267                 caps = sbc_enc_src_getcaps(enc->srcpad);
268
269         if (caps == GST_CAPS_NONE || gst_caps_is_empty(caps)) {
270                 res = FALSE;
271                 goto done;
272         }
273
274         result_caps = sbc_enc_src_caps_fixate(enc, caps);
275
276 done:
277         gst_caps_unref(caps);
278
279         if (!res)
280                 return NULL;
281
282         return result_caps;
283 }
284
285 static gboolean sbc_enc_sink_setcaps(GstPad *pad, GstCaps *caps)
286 {
287         GstSbcEnc *enc;
288         GstStructure *structure;
289         GstCaps *src_caps;
290         gint rate, channels;
291         gboolean res;
292
293         enc = GST_SBC_ENC(GST_PAD_PARENT(pad));
294         structure = gst_caps_get_structure(caps, 0);
295
296         if (!gst_structure_get_int(structure, "rate", &rate))
297                 return FALSE;
298         if (!gst_structure_get_int(structure, "channels", &channels))
299                 return FALSE;
300
301         enc->rate = rate;
302         enc->channels = channels;
303
304         src_caps = sbc_enc_get_fixed_srcpad_caps(enc);
305         if (!src_caps)
306                 return FALSE;
307         res = gst_pad_set_caps(enc->srcpad, src_caps);
308         gst_caps_unref(src_caps);
309
310         return res;
311 }
312
313 gboolean gst_sbc_enc_fill_sbc_params(GstSbcEnc *enc, GstCaps *caps)
314 {
315         if (!gst_caps_is_fixed(caps)) {
316                 GST_DEBUG_OBJECT(enc, "didn't receive fixed caps, "
317                                 "returning false");
318                 return FALSE;
319         }
320
321         if (!gst_sbc_util_fill_sbc_params(&enc->sbc, caps))
322                 return FALSE;
323
324         if (enc->rate != 0 && gst_sbc_parse_rate_from_sbc(enc->sbc.frequency)
325                                  != enc->rate)
326                 goto fail;
327
328         if (enc->channels != 0 && gst_sbc_get_channel_number(enc->sbc.mode)
329                                 != enc->channels)
330                 goto fail;
331
332         if (enc->blocks != 0 && gst_sbc_parse_blocks_from_sbc(enc->sbc.blocks)
333                                  != enc->blocks)
334                 goto fail;
335
336         if (enc->subbands != 0 && gst_sbc_parse_subbands_from_sbc(
337                                 enc->sbc.subbands) != enc->subbands)
338                 goto fail;
339
340         if (enc->mode != SBC_ENC_DEFAULT_MODE && enc->sbc.mode != enc->mode)
341                 goto fail;
342
343         if (enc->allocation != SBC_AM_AUTO &&
344                                 enc->sbc.allocation != enc->allocation)
345                 goto fail;
346
347         if (enc->bitpool != SBC_ENC_BITPOOL_AUTO &&
348                                 enc->sbc.bitpool != enc->bitpool)
349                 goto fail;
350
351         enc->codesize = sbc_get_codesize(&enc->sbc);
352         enc->frame_length = sbc_get_frame_length(&enc->sbc);
353         enc->frame_duration = sbc_get_frame_duration(&enc->sbc);
354
355         GST_DEBUG_OBJECT(enc, "codesize: %d, frame_length: %d, frame_duration:"
356                         " %d", enc->codesize, enc->frame_length,
357                         enc->frame_duration);
358
359         return TRUE;
360
361 fail:
362         memset(&enc->sbc, 0, sizeof(sbc_t));
363         return FALSE;
364 }
365
366 static GstFlowReturn sbc_enc_chain(GstPad *pad, GstBuffer *buffer)
367 {
368         GstSbcEnc *enc = GST_SBC_ENC(gst_pad_get_parent(pad));
369         GstAdapter *adapter = enc->adapter;
370         GstFlowReturn res = GST_FLOW_OK;
371
372         gst_adapter_push(adapter, buffer);
373
374         while (gst_adapter_available(adapter) >= enc->codesize &&
375                                                         res == GST_FLOW_OK) {
376                 GstBuffer *output;
377                 GstCaps *caps;
378                 const guint8 *data;
379                 gint consumed;
380
381                 caps = GST_PAD_CAPS(enc->srcpad);
382                 res = gst_pad_alloc_buffer_and_set_caps(enc->srcpad,
383                                                 GST_BUFFER_OFFSET_NONE,
384                                                 enc->frame_length, caps,
385                                                 &output);
386                 if (res != GST_FLOW_OK)
387                         goto done;
388
389                 data = gst_adapter_peek(adapter, enc->codesize);
390
391                 consumed = sbc_encode(&enc->sbc, (gpointer) data,
392                                         enc->codesize,
393                                         GST_BUFFER_DATA(output),
394                                         GST_BUFFER_SIZE(output), NULL);
395                 if (consumed <= 0) {
396                         GST_DEBUG_OBJECT(enc, "comsumed < 0, codesize: %d",
397                                         enc->codesize);
398                         break;
399                 }
400                 gst_adapter_flush(adapter, consumed);
401
402                 GST_BUFFER_TIMESTAMP(output) = GST_BUFFER_TIMESTAMP(buffer);
403                 /* we have only 1 frame */
404                 GST_BUFFER_DURATION(output) = enc->frame_duration;
405
406                 res = gst_pad_push(enc->srcpad, output);
407
408                 if (res != GST_FLOW_OK)
409                         goto done;
410         }
411
412 done:
413         gst_object_unref(enc);
414
415         return res;
416 }
417
418 static GstStateChangeReturn sbc_enc_change_state(GstElement *element,
419                                                 GstStateChange transition)
420 {
421         GstSbcEnc *enc = GST_SBC_ENC(element);
422
423         switch (transition) {
424         case GST_STATE_CHANGE_READY_TO_PAUSED:
425                 GST_DEBUG("Setup subband codec");
426                 sbc_init(&enc->sbc, 0);
427                 break;
428
429         case GST_STATE_CHANGE_PAUSED_TO_READY:
430                 GST_DEBUG("Finish subband codec");
431                 sbc_finish(&enc->sbc);
432                 break;
433
434         default:
435                 break;
436         }
437
438         return parent_class->change_state(element, transition);
439 }
440
441 static void gst_sbc_enc_dispose(GObject *object)
442 {
443         GstSbcEnc *enc = GST_SBC_ENC(object);
444
445         if (enc->adapter != NULL)
446                 g_object_unref(G_OBJECT(enc->adapter));
447
448         enc->adapter = NULL;
449 }
450
451 static void gst_sbc_enc_base_init(gpointer g_class)
452 {
453         GstElementClass *element_class = GST_ELEMENT_CLASS(g_class);
454
455         gst_element_class_add_pad_template(element_class,
456                 gst_static_pad_template_get(&sbc_enc_sink_factory));
457
458         gst_element_class_add_pad_template(element_class,
459                 gst_static_pad_template_get(&sbc_enc_src_factory));
460
461         gst_element_class_set_details(element_class, &sbc_enc_details);
462 }
463
464 static void gst_sbc_enc_set_property(GObject *object, guint prop_id,
465                                         const GValue *value, GParamSpec *pspec)
466 {
467         GstSbcEnc *enc = GST_SBC_ENC(object);
468
469         /* changes to those properties will only happen on the next caps
470          * negotiation */
471
472         switch (prop_id) {
473         case PROP_MODE:
474                 enc->mode = g_value_get_enum(value);
475                 break;
476         case PROP_ALLOCATION:
477                 enc->allocation = g_value_get_enum(value);
478                 break;
479         case PROP_BLOCKS:
480                 enc->blocks = g_value_get_enum(value);
481                 break;
482         case PROP_SUBBANDS:
483                 enc->subbands = g_value_get_enum(value);
484                 break;
485         case PROP_BITPOOL:
486                 enc->bitpool = g_value_get_int(value);
487                 break;
488         default:
489                 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
490                 break;
491         }
492 }
493
494 static void gst_sbc_enc_get_property(GObject *object, guint prop_id,
495                                         GValue *value, GParamSpec *pspec)
496 {
497         GstSbcEnc *enc = GST_SBC_ENC(object);
498
499         switch (prop_id) {
500         case PROP_MODE:
501                 g_value_set_enum(value, enc->mode);
502                 break;
503         case PROP_ALLOCATION:
504                 g_value_set_enum(value, enc->allocation);
505                 break;
506         case PROP_BLOCKS:
507                 g_value_set_enum(value, enc->blocks);
508                 break;
509         case PROP_SUBBANDS:
510                 g_value_set_enum(value, enc->subbands);
511                 break;
512         case PROP_BITPOOL:
513                 g_value_set_int(value, enc->bitpool);
514                 break;
515         default:
516                 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
517                 break;
518         }
519 }
520
521 static void gst_sbc_enc_class_init(GstSbcEncClass *klass)
522 {
523         GObjectClass *object_class = G_OBJECT_CLASS(klass);
524         GstElementClass *element_class = GST_ELEMENT_CLASS(klass);
525
526         parent_class = g_type_class_peek_parent(klass);
527
528         object_class->set_property = GST_DEBUG_FUNCPTR(gst_sbc_enc_set_property);
529         object_class->get_property = GST_DEBUG_FUNCPTR(gst_sbc_enc_get_property);
530         object_class->dispose = GST_DEBUG_FUNCPTR(gst_sbc_enc_dispose);
531
532         element_class->change_state = GST_DEBUG_FUNCPTR(sbc_enc_change_state);
533
534         g_object_class_install_property(object_class, PROP_MODE,
535                         g_param_spec_enum("mode", "Mode",
536                                 "Encoding mode", GST_TYPE_SBC_MODE,
537                                 SBC_ENC_DEFAULT_MODE, G_PARAM_READWRITE));
538
539         g_object_class_install_property(object_class, PROP_ALLOCATION,
540                         g_param_spec_enum("allocation", "Allocation",
541                                 "Allocation method", GST_TYPE_SBC_ALLOCATION,
542                                 SBC_ENC_DEFAULT_ALLOCATION, G_PARAM_READWRITE));
543
544         g_object_class_install_property(object_class, PROP_BLOCKS,
545                         g_param_spec_enum("blocks", "Blocks",
546                                 "Blocks", GST_TYPE_SBC_BLOCKS,
547                                 SBC_ENC_DEFAULT_BLOCKS, G_PARAM_READWRITE));
548
549         g_object_class_install_property(object_class, PROP_SUBBANDS,
550                         g_param_spec_enum("subbands", "Sub bands",
551                                 "Number of sub bands", GST_TYPE_SBC_SUBBANDS,
552                                 SBC_ENC_DEFAULT_SUB_BANDS, G_PARAM_READWRITE));
553
554         g_object_class_install_property(object_class, PROP_BITPOOL,
555                         g_param_spec_int("bitpool", "Bitpool",
556                                 "Bitpool (use 1 for automatic selection)",
557                                 SBC_ENC_BITPOOL_AUTO, SBC_ENC_BITPOOL_MAX,
558                                 SBC_ENC_BITPOOL_AUTO, G_PARAM_READWRITE));
559
560         GST_DEBUG_CATEGORY_INIT(sbc_enc_debug, "sbcenc", 0,
561                                                 "SBC encoding element");
562 }
563
564 static void gst_sbc_enc_init(GstSbcEnc *self, GstSbcEncClass *klass)
565 {
566         self->sinkpad = gst_pad_new_from_static_template(
567                 &sbc_enc_sink_factory, "sink");
568         gst_pad_set_setcaps_function(self->sinkpad,
569                         GST_DEBUG_FUNCPTR(sbc_enc_sink_setcaps));
570         gst_element_add_pad(GST_ELEMENT(self), self->sinkpad);
571
572         self->srcpad = gst_pad_new_from_static_template(
573                 &sbc_enc_src_factory, "src");
574         gst_pad_set_getcaps_function(self->srcpad,
575                 GST_DEBUG_FUNCPTR(sbc_enc_src_getcaps));
576         gst_pad_set_setcaps_function(self->srcpad,
577                 GST_DEBUG_FUNCPTR(sbc_enc_src_setcaps));
578         gst_element_add_pad(GST_ELEMENT(self), self->srcpad);
579
580         gst_pad_set_chain_function(self->sinkpad,
581                 GST_DEBUG_FUNCPTR(sbc_enc_chain));
582
583         self->subbands = SBC_ENC_DEFAULT_SUB_BANDS;
584         self->blocks = SBC_ENC_DEFAULT_BLOCKS;
585         self->mode = SBC_ENC_DEFAULT_MODE;
586         self->allocation = SBC_ENC_DEFAULT_ALLOCATION;
587         self->rate = SBC_ENC_DEFAULT_RATE;
588         self->channels = SBC_ENC_DEFAULT_CHANNELS;
589         self->bitpool = SBC_ENC_BITPOOL_AUTO;
590
591         self->frame_length = 0;
592         self->frame_duration = 0;
593
594         self->adapter = gst_adapter_new();
595 }
596
597 gboolean gst_sbc_enc_plugin_init(GstPlugin *plugin)
598 {
599         return gst_element_register(plugin, "sbcenc",
600                         GST_RANK_NONE, GST_TYPE_SBC_ENC);
601 }