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 <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 (at) 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 } 602 603 604