1 /* 2 * 3 * BlueZ - Bluetooth protocol stack for Linux 4 * 5 * Copyright (C) 2004-2010 Marcel Holtmann <marcel (at) 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 sucessfull 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 } 521 522