Initialize Tizen 2.3
[framework/connectivity/bluez.git] / wearable / audio / gstsbcutil.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 <math.h>
29 #include "gstsbcutil.h"
30
31 /*
32  * Selects one rate from a list of possible rates
33  * TODO - use a better approach to this (it is selecting the last element)
34  */
35 gint gst_sbc_select_rate_from_list(const GValue *value)
36 {
37         guint size = gst_value_list_get_size(value);
38         return g_value_get_int(gst_value_list_get_value(value, size-1));
39 }
40
41 /*
42  * Selects one number of channels option from a range of possible numbers
43  * TODO - use a better approach to this (it is selecting the maximum value)
44  */
45 gint gst_sbc_select_channels_from_range(const GValue *value)
46 {
47         return gst_value_get_int_range_max(value);
48 }
49
50 /*
51  * Selects one number of blocks from a list of possible blocks
52  * TODO - use a better approach to this (it is selecting the last element)
53  */
54 gint gst_sbc_select_blocks_from_list(const GValue *value)
55 {
56         guint size = gst_value_list_get_size(value);
57         return g_value_get_int(gst_value_list_get_value(value, size-1));
58 }
59
60 /*
61  * Selects one number of subbands from a list
62  * TODO - use a better approach to this (it is selecting the last element)
63  */
64 gint gst_sbc_select_subbands_from_list(const GValue *value)
65 {
66         guint size = gst_value_list_get_size(value);
67         return g_value_get_int(gst_value_list_get_value(value, size-1));
68 }
69
70 /*
71  * Selects one bitpool option from a range
72  * TODO - use a better approach to this (it is selecting the maximum value)
73  */
74 gint gst_sbc_select_bitpool_from_range(const GValue *value)
75 {
76         return gst_value_get_int_range_max(value);
77 }
78
79 /*
80  * Selects one allocation mode from the ones on the list
81  * TODO - use a better approach
82  */
83 const gchar *gst_sbc_get_allocation_from_list(const GValue *value)
84 {
85         guint size = gst_value_list_get_size(value);
86         return g_value_get_string(gst_value_list_get_value(value, size-1));
87 }
88
89 /*
90  * Selects one mode from the ones on the list
91  */
92 const gchar *gst_sbc_get_mode_from_list(const GValue *list, gint channels)
93 {
94         unsigned int i;
95         const GValue *value;
96         const gchar *aux;
97         gboolean joint, stereo, dual, mono;
98         guint size = gst_value_list_get_size(list);
99
100         joint = stereo = dual = mono = FALSE;
101
102         for (i = 0; i < size; i++) {
103                 value = gst_value_list_get_value(list, i);
104                 aux = g_value_get_string(value);
105                 if (strcmp("joint", aux) == 0)
106                         joint = TRUE;
107                 else if (strcmp("stereo", aux) == 0)
108                         stereo = TRUE;
109                 else if (strcmp("dual", aux) == 0)
110                         dual = TRUE;
111                 else if (strcmp("mono", aux) == 0)
112                         mono = TRUE;
113         }
114
115         if (channels == 1 && mono)
116                 return "mono";
117         else if (channels == 2) {
118                 if (joint)
119                         return "joint";
120                 else if (stereo)
121                         return "stereo";
122                 else if (dual)
123                         return "dual";
124         }
125
126         return NULL;
127 }
128
129 gint gst_sbc_parse_rate_from_sbc(gint frequency)
130 {
131         switch (frequency) {
132         case SBC_FREQ_16000:
133                 return 16000;
134         case SBC_FREQ_32000:
135                 return 32000;
136         case SBC_FREQ_44100:
137                 return 44100;
138         case SBC_FREQ_48000:
139                 return 48000;
140         default:
141                 return 0;
142         }
143 }
144
145 gint gst_sbc_parse_rate_to_sbc(gint rate)
146 {
147         switch (rate) {
148         case 16000:
149                 return SBC_FREQ_16000;
150         case 32000:
151                 return SBC_FREQ_32000;
152         case 44100:
153                 return SBC_FREQ_44100;
154         case 48000:
155                 return SBC_FREQ_48000;
156         default:
157                 return -1;
158         }
159 }
160
161 gint gst_sbc_get_channel_number(gint mode)
162 {
163         switch (mode) {
164         case SBC_MODE_JOINT_STEREO:
165         case SBC_MODE_STEREO:
166         case SBC_MODE_DUAL_CHANNEL:
167                 return 2;
168         case SBC_MODE_MONO:
169                 return 1;
170         default:
171                 return 0;
172         }
173 }
174
175 gint gst_sbc_parse_subbands_from_sbc(gint subbands)
176 {
177         switch (subbands) {
178         case SBC_SB_4:
179                 return 4;
180         case SBC_SB_8:
181                 return 8;
182         default:
183                 return 0;
184         }
185 }
186
187 gint gst_sbc_parse_subbands_to_sbc(gint subbands)
188 {
189         switch (subbands) {
190         case 4:
191                 return SBC_SB_4;
192         case 8:
193                 return SBC_SB_8;
194         default:
195                 return -1;
196         }
197 }
198
199 gint gst_sbc_parse_blocks_from_sbc(gint blocks)
200 {
201         switch (blocks) {
202         case SBC_BLK_4:
203                 return 4;
204         case SBC_BLK_8:
205                 return 8;
206         case SBC_BLK_12:
207                 return 12;
208         case SBC_BLK_16:
209                 return 16;
210         default:
211                 return 0;
212         }
213 }
214
215 gint gst_sbc_parse_blocks_to_sbc(gint blocks)
216 {
217         switch (blocks) {
218         case 4:
219                 return SBC_BLK_4;
220         case 8:
221                 return SBC_BLK_8;
222         case 12:
223                 return SBC_BLK_12;
224         case 16:
225                 return SBC_BLK_16;
226         default:
227                 return -1;
228         }
229 }
230
231 const gchar *gst_sbc_parse_mode_from_sbc(gint mode)
232 {
233         switch (mode) {
234         case SBC_MODE_MONO:
235                 return "mono";
236         case SBC_MODE_DUAL_CHANNEL:
237                 return "dual";
238         case SBC_MODE_STEREO:
239                 return "stereo";
240         case SBC_MODE_JOINT_STEREO:
241         case SBC_MODE_AUTO:
242                 return "joint";
243         default:
244                 return NULL;
245         }
246 }
247
248 gint gst_sbc_parse_mode_to_sbc(const gchar *mode)
249 {
250         if (g_ascii_strcasecmp(mode, "joint") == 0)
251                 return SBC_MODE_JOINT_STEREO;
252         else if (g_ascii_strcasecmp(mode, "stereo") == 0)
253                 return SBC_MODE_STEREO;
254         else if (g_ascii_strcasecmp(mode, "dual") == 0)
255                 return SBC_MODE_DUAL_CHANNEL;
256         else if (g_ascii_strcasecmp(mode, "mono") == 0)
257                 return SBC_MODE_MONO;
258         else if (g_ascii_strcasecmp(mode, "auto") == 0)
259                 return SBC_MODE_JOINT_STEREO;
260         else
261                 return -1;
262 }
263
264 const gchar *gst_sbc_parse_allocation_from_sbc(gint alloc)
265 {
266         switch (alloc) {
267         case SBC_AM_LOUDNESS:
268                 return "loudness";
269         case SBC_AM_SNR:
270                 return "snr";
271         case SBC_AM_AUTO:
272                 return "loudness";
273         default:
274                 return NULL;
275         }
276 }
277
278 gint gst_sbc_parse_allocation_to_sbc(const gchar *allocation)
279 {
280         if (g_ascii_strcasecmp(allocation, "loudness") == 0)
281                 return SBC_AM_LOUDNESS;
282         else if (g_ascii_strcasecmp(allocation, "snr") == 0)
283                 return SBC_AM_SNR;
284         else
285                 return SBC_AM_LOUDNESS;
286 }
287
288 GstCaps *gst_sbc_parse_caps_from_sbc(sbc_t *sbc)
289 {
290         GstCaps *caps;
291         const gchar *mode_str;
292         const gchar *allocation_str;
293
294         mode_str = gst_sbc_parse_mode_from_sbc(sbc->mode);
295         allocation_str = gst_sbc_parse_allocation_from_sbc(sbc->allocation);
296         caps = gst_caps_new_simple("audio/x-sbc",
297                                 "rate", G_TYPE_INT,
298                                 gst_sbc_parse_rate_from_sbc(sbc->frequency),
299                                 "channels", G_TYPE_INT,
300                                 gst_sbc_get_channel_number(sbc->mode),
301                                 "mode", G_TYPE_STRING, mode_str,
302                                 "subbands", G_TYPE_INT,
303                                 gst_sbc_parse_subbands_from_sbc(sbc->subbands),
304                                 "blocks", G_TYPE_INT,
305                                 gst_sbc_parse_blocks_from_sbc(sbc->blocks),
306                                 "allocation", G_TYPE_STRING, allocation_str,
307                                 "bitpool", G_TYPE_INT, sbc->bitpool,
308                                 NULL);
309
310         return caps;
311 }
312
313 /*
314  * Given a GstCaps, this will return a fixed GstCaps on successful conversion.
315  * If an error occurs, it will return NULL and error_message will contain the
316  * error message.
317  *
318  * error_message must be passed NULL, if an error occurs, the caller has the
319  * ownership of the error_message, it must be freed after use.
320  */
321 GstCaps *gst_sbc_util_caps_fixate(GstCaps *caps, gchar **error_message)
322 {
323         GstCaps *result;
324         GstStructure *structure;
325         const GValue *value;
326         gboolean error = FALSE;
327         gint temp, rate, channels, blocks, subbands, bitpool;
328         const gchar *allocation = NULL;
329         const gchar *mode = NULL;
330
331         g_assert(*error_message == NULL);
332
333         structure = gst_caps_get_structure(caps, 0);
334
335         if (!gst_structure_has_field(structure, "rate")) {
336                 error = TRUE;
337                 *error_message = g_strdup("no rate");
338                 goto error;
339         } else {
340                 value = gst_structure_get_value(structure, "rate");
341                 if (GST_VALUE_HOLDS_LIST(value))
342                         temp = gst_sbc_select_rate_from_list(value);
343                 else
344                         temp = g_value_get_int(value);
345                 rate = temp;
346         }
347
348         if (!gst_structure_has_field(structure, "channels")) {
349                 error = TRUE;
350                 *error_message = g_strdup("no channels");
351                 goto error;
352         } else {
353                 value = gst_structure_get_value(structure, "channels");
354                 if (GST_VALUE_HOLDS_INT_RANGE(value))
355                         temp = gst_sbc_select_channels_from_range(value);
356                 else
357                         temp = g_value_get_int(value);
358                 channels = temp;
359         }
360
361         if (!gst_structure_has_field(structure, "blocks")) {
362                 error = TRUE;
363                 *error_message = g_strdup("no blocks.");
364                 goto error;
365         } else {
366                 value = gst_structure_get_value(structure, "blocks");
367                 if (GST_VALUE_HOLDS_LIST(value))
368                         temp = gst_sbc_select_blocks_from_list(value);
369                 else
370                         temp = g_value_get_int(value);
371                 blocks = temp;
372         }
373
374         if (!gst_structure_has_field(structure, "subbands")) {
375                 error = TRUE;
376                 *error_message = g_strdup("no subbands");
377                 goto error;
378         } else {
379                 value = gst_structure_get_value(structure, "subbands");
380                 if (GST_VALUE_HOLDS_LIST(value))
381                         temp = gst_sbc_select_subbands_from_list(value);
382                 else
383                         temp = g_value_get_int(value);
384                 subbands = temp;
385         }
386
387         if (!gst_structure_has_field(structure, "bitpool")) {
388                 error = TRUE;
389                 *error_message = g_strdup("no bitpool");
390                 goto error;
391         } else {
392                 value = gst_structure_get_value(structure, "bitpool");
393                 if (GST_VALUE_HOLDS_INT_RANGE(value))
394                         temp = gst_sbc_select_bitpool_from_range(value);
395                 else
396                         temp = g_value_get_int(value);
397                 bitpool = temp;
398         }
399
400         if (!gst_structure_has_field(structure, "allocation")) {
401                 error = TRUE;
402                 *error_message = g_strdup("no allocation");
403                 goto error;
404         } else {
405                 value = gst_structure_get_value(structure, "allocation");
406                 if (GST_VALUE_HOLDS_LIST(value))
407                         allocation = gst_sbc_get_allocation_from_list(value);
408                 else
409                         allocation = g_value_get_string(value);
410         }
411
412         if (!gst_structure_has_field(structure, "mode")) {
413                 error = TRUE;
414                 *error_message = g_strdup("no mode");
415                 goto error;
416         } else {
417                 value = gst_structure_get_value(structure, "mode");
418                 if (GST_VALUE_HOLDS_LIST(value)) {
419                         mode = gst_sbc_get_mode_from_list(value, channels);
420                 } else
421                         mode = g_value_get_string(value);
422         }
423
424         /* perform validation
425          * if channels is 1, we must have channel mode = mono
426          * if channels is 2, we can't have channel mode = mono */
427         if ( (channels == 1 && (strcmp(mode, "mono") != 0) ) ||
428                         ( channels == 2 && ( strcmp(mode, "mono") == 0))) {
429                 *error_message = g_strdup_printf("Invalid combination of "
430                                         "channels (%d) and channel mode (%s)",
431                                         channels, mode);
432                 error = TRUE;
433         }
434
435 error:
436         if (error)
437                 return NULL;
438
439         result = gst_caps_new_simple("audio/x-sbc",
440                                         "rate", G_TYPE_INT, rate,
441                                         "channels", G_TYPE_INT, channels,
442                                         "mode", G_TYPE_STRING, mode,
443                                         "blocks", G_TYPE_INT, blocks,
444                                         "subbands", G_TYPE_INT, subbands,
445                                         "allocation", G_TYPE_STRING, allocation,
446                                         "bitpool", G_TYPE_INT, bitpool,
447                                         NULL);
448
449         return result;
450 }
451
452 /**
453  * Sets the int field_value to the  param "field" on the structure.
454  * value is used to do the operation, it must be a uninitialized (zero-filled)
455  * GValue, it will be left unitialized at the end of the function.
456  */
457 void gst_sbc_util_set_structure_int_param(GstStructure *structure,
458                         const gchar *field, gint field_value,
459                         GValue *value)
460 {
461         value = g_value_init(value, G_TYPE_INT);
462         g_value_set_int(value, field_value);
463         gst_structure_set_value(structure, field, value);
464         g_value_unset(value);
465 }
466
467 /**
468  * Sets the string field_value to the  param "field" on the structure.
469  * value is used to do the operation, it must be a uninitialized (zero-filled)
470  * GValue, it will be left unitialized at the end of the function.
471  */
472 void gst_sbc_util_set_structure_string_param(GstStructure *structure,
473                         const gchar *field, const gchar *field_value,
474                         GValue *value)
475 {
476         value = g_value_init(value, G_TYPE_STRING);
477         g_value_set_string(value, field_value);
478         gst_structure_set_value(structure, field, value);
479         g_value_unset(value);
480 }
481
482 gboolean gst_sbc_util_fill_sbc_params(sbc_t *sbc, GstCaps *caps)
483 {
484         GstStructure *structure;
485         gint rate, channels, subbands, blocks, bitpool;
486         const gchar *mode;
487         const gchar *allocation;
488
489         g_assert(gst_caps_is_fixed(caps));
490
491         structure = gst_caps_get_structure(caps, 0);
492
493         if (!gst_structure_get_int(structure, "rate", &rate))
494                 return FALSE;
495         if (!gst_structure_get_int(structure, "channels", &channels))
496                 return FALSE;
497         if (!gst_structure_get_int(structure, "subbands", &subbands))
498                 return FALSE;
499         if (!gst_structure_get_int(structure, "blocks", &blocks))
500                 return FALSE;
501         if (!gst_structure_get_int(structure, "bitpool", &bitpool))
502                 return FALSE;
503
504         if (!(mode = gst_structure_get_string(structure, "mode")))
505                 return FALSE;
506         if (!(allocation = gst_structure_get_string(structure, "allocation")))
507                 return FALSE;
508
509         if (channels == 1 && strcmp(mode, "mono") != 0)
510                 return FALSE;
511
512         sbc->frequency = gst_sbc_parse_rate_to_sbc(rate);
513         sbc->blocks = gst_sbc_parse_blocks_to_sbc(blocks);
514         sbc->subbands = gst_sbc_parse_subbands_to_sbc(subbands);
515         sbc->bitpool = bitpool;
516         sbc->mode = gst_sbc_parse_mode_to_sbc(mode);
517         sbc->allocation = gst_sbc_parse_allocation_to_sbc(allocation);
518
519         return TRUE;
520 }