/******************************************************************************* ** ** Function bta_av_co_audio_get_sbc_config ** ** Description Retrieves the SBC codec configuration. If the codec in use ** is not SBC, return the default SBC codec configuration. ** ** Returns TRUE if codec is SBC, FALSE otherwise ** *******************************************************************************/ BOOLEAN bta_av_co_audio_get_sbc_config(tA2D_SBC_CIE *p_sbc_config, UINT16 *p_minmtu) { BOOLEAN result = FALSE; UINT8 index, jndex; tBTA_AV_CO_PEER *p_peer; tBTA_AV_CO_SINK *p_sink; APPL_TRACE_EVENT1("bta_av_co_cb.codec_cfg.id : codec 0x%x", bta_av_co_cb.codec_cfg.id); /* Minimum MTU is by default very large */ *p_minmtu = 0xFFFF; GKI_disable(); if (bta_av_co_cb.codec_cfg.id == BTIF_AV_CODEC_SBC) { if (A2D_ParsSbcInfo(p_sbc_config, bta_av_co_cb.codec_cfg.info, FALSE) == A2D_SUCCESS) { for (index = 0; index < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); index++) { p_peer = &bta_av_co_cb.peers[index]; if (p_peer->opened) { if (p_peer->mtu < *p_minmtu) { *p_minmtu = p_peer->mtu; } for (jndex = 0; jndex < p_peer->num_sup_snks; jndex++) { p_sink = &p_peer->snks[jndex]; if (p_sink->codec_type == A2D_MEDIA_CT_SBC) { /* Update the bitpool boundaries of the current config */ p_sbc_config->min_bitpool = BTA_AV_CO_MAX(p_sink->codec_caps[BTA_AV_CO_SBC_MIN_BITPOOL_OFF], p_sbc_config->min_bitpool); p_sbc_config->max_bitpool = BTA_AV_CO_MIN(p_sink->codec_caps[BTA_AV_CO_SBC_MAX_BITPOOL_OFF], p_sbc_config->max_bitpool); APPL_TRACE_EVENT2("bta_av_co_audio_get_sbc_config : sink bitpool min %d, max %d", p_sbc_config->min_bitpool, p_sbc_config->max_bitpool); break; } } } } result = TRUE; } } if (!result) { /* Not SBC, still return the default values */ *p_sbc_config = btif_av_sbc_default_config; } GKI_enable(); return result; }
/******************************************************************************* ** ** Function btc_a2dp_sink_handle_decoder_reset ** ** Description ** ** Returns void ** *******************************************************************************/ static void btc_a2dp_sink_handle_decoder_reset(tBTC_MEDIA_SINK_CFG_UPDATE *p_msg) { tBTC_MEDIA_SINK_CFG_UPDATE *p_buf = p_msg; tA2D_STATUS a2d_status; tA2D_SBC_CIE sbc_cie; OI_STATUS status; UINT32 freq_multiple = 48 * 20; /* frequency multiple for 20ms of data , initialize with 48K*/ UINT32 num_blocks = 16; UINT32 num_subbands = 8; APPL_TRACE_EVENT("%s p_codec_info[%x:%x:%x:%x:%x:%x]\n", __FUNCTION__, p_buf->codec_info[1], p_buf->codec_info[2], p_buf->codec_info[3], p_buf->codec_info[4], p_buf->codec_info[5], p_buf->codec_info[6]); a2d_status = A2D_ParsSbcInfo(&sbc_cie, p_buf->codec_info, FALSE); if (a2d_status != A2D_SUCCESS) { APPL_TRACE_ERROR("ERROR dump_codec_info A2D_ParsSbcInfo fail:%d\n", a2d_status); return; } btc_aa_snk_cb.sample_rate = btc_a2dp_sink_get_track_frequency(sbc_cie.samp_freq); btc_aa_snk_cb.channel_count = btc_a2dp_sink_get_track_channel_count(sbc_cie.ch_mode); btc_aa_snk_cb.rx_flush = FALSE; APPL_TRACE_EVENT("Reset to sink role"); status = OI_CODEC_SBC_DecoderReset(&context, contextData, sizeof(contextData), 2, 2, FALSE); if (!OI_SUCCESS(status)) { APPL_TRACE_ERROR("OI_CODEC_SBC_DecoderReset failed with error code %d\n", status); } btc_a2dp_control_set_datachnl_stat(TRUE); switch (sbc_cie.samp_freq) { case A2D_SBC_IE_SAMP_FREQ_16: APPL_TRACE_DEBUG("\tsamp_freq:%d (16000)\n", sbc_cie.samp_freq); freq_multiple = 16 * 20; break; case A2D_SBC_IE_SAMP_FREQ_32: APPL_TRACE_DEBUG("\tsamp_freq:%d (32000)\n", sbc_cie.samp_freq); freq_multiple = 32 * 20; break; case A2D_SBC_IE_SAMP_FREQ_44: APPL_TRACE_DEBUG("\tsamp_freq:%d (44100)\n", sbc_cie.samp_freq); freq_multiple = 441 * 2; break; case A2D_SBC_IE_SAMP_FREQ_48: APPL_TRACE_DEBUG("\tsamp_freq:%d (48000)\n", sbc_cie.samp_freq); freq_multiple = 48 * 20; break; default: APPL_TRACE_DEBUG(" Unknown Frequency "); break; } switch (sbc_cie.ch_mode) { case A2D_SBC_IE_CH_MD_MONO: APPL_TRACE_DEBUG("\tch_mode:%d (Mono)\n", sbc_cie.ch_mode); break; case A2D_SBC_IE_CH_MD_DUAL: APPL_TRACE_DEBUG("\tch_mode:%d (DUAL)\n", sbc_cie.ch_mode); break; case A2D_SBC_IE_CH_MD_STEREO: APPL_TRACE_DEBUG("\tch_mode:%d (STEREO)\n", sbc_cie.ch_mode); break; case A2D_SBC_IE_CH_MD_JOINT: APPL_TRACE_DEBUG("\tch_mode:%d (JOINT)\n", sbc_cie.ch_mode); break; default: APPL_TRACE_DEBUG(" Unknown Mode "); break; } switch (sbc_cie.block_len) { case A2D_SBC_IE_BLOCKS_4: APPL_TRACE_DEBUG("\tblock_len:%d (4)\n", sbc_cie.block_len); num_blocks = 4; break; case A2D_SBC_IE_BLOCKS_8: APPL_TRACE_DEBUG("\tblock_len:%d (8)\n", sbc_cie.block_len); num_blocks = 8; break; case A2D_SBC_IE_BLOCKS_12: APPL_TRACE_DEBUG("\tblock_len:%d (12)\n", sbc_cie.block_len); num_blocks = 12; break; case A2D_SBC_IE_BLOCKS_16: APPL_TRACE_DEBUG("\tblock_len:%d (16)\n", sbc_cie.block_len); num_blocks = 16; break; default: APPL_TRACE_DEBUG(" Unknown BlockLen "); break; } switch (sbc_cie.num_subbands) { case A2D_SBC_IE_SUBBAND_4: APPL_TRACE_DEBUG("\tnum_subbands:%d (4)\n", sbc_cie.num_subbands); num_subbands = 4; break; case A2D_SBC_IE_SUBBAND_8: APPL_TRACE_DEBUG("\tnum_subbands:%d (8)\n", sbc_cie.num_subbands); num_subbands = 8; break; default: APPL_TRACE_DEBUG(" Unknown SubBands "); break; } switch (sbc_cie.alloc_mthd) { case A2D_SBC_IE_ALLOC_MD_S: APPL_TRACE_DEBUG("\talloc_mthd:%d (SNR)\n", sbc_cie.alloc_mthd); break; case A2D_SBC_IE_ALLOC_MD_L: APPL_TRACE_DEBUG("\talloc_mthd:%d (Loudness)\n", sbc_cie.alloc_mthd); break; default: APPL_TRACE_DEBUG(" Unknown Allocation Method"); break; } APPL_TRACE_EVENT("\tBit pool Min:%d Max:%d\n", sbc_cie.min_bitpool, sbc_cie.max_bitpool); int frames_to_process = ((freq_multiple) / (num_blocks * num_subbands)) + 1; APPL_TRACE_EVENT(" Frames to be processed in 20 ms %d\n", frames_to_process); }