Loading system/btif/co/bta_av_co.cc +90 −18 Original line number Diff line number Diff line Loading @@ -132,6 +132,8 @@ static const tBTA_AV_CO_SINK* bta_av_co_find_peer_src_supports_codec( static tBTA_AV_CO_SINK* bta_av_co_audio_set_codec(tBTA_AV_CO_PEER* p_peer); static tBTA_AV_CO_SINK* bta_av_co_audio_codec_selected( A2dpCodecConfig& codec_config, tBTA_AV_CO_PEER* p_peer); static bool bta_av_co_audio_update_selectable_codec( A2dpCodecConfig& codec_config, const tBTA_AV_CO_PEER* p_peer); static void bta_av_co_save_new_codec_config(tBTA_AV_CO_PEER* p_peer, const uint8_t* new_codec_config, uint8_t num_protect, Loading Loading @@ -848,21 +850,39 @@ static const tBTA_AV_CO_SINK* bta_av_co_find_peer_src_supports_codec( // // Select the current codec configuration based on peer codec support. // Return true on success, otherwise false. // Furthermore, the local state for the remaining non-selected codecs is // updated to reflect whether the codec is selectable. // Return a pointer to the corresponding |tBTA_AV_CO_SINK| sink entry // on success, otherwise NULL. // static tBTA_AV_CO_SINK* bta_av_co_audio_set_codec(tBTA_AV_CO_PEER* p_peer) { tBTA_AV_CO_SINK* p_sink = NULL; // Update all selectable codecs. // This is needed to update the selectable parameters for each codec. // NOTE: The selectable codec info is used only for informational purpose. for (const auto& iter : bta_av_co_cb.codecs->orderedSourceCodecs()) { APPL_TRACE_DEBUG("%s: updating selectable codec %s", __func__, iter->name().c_str()); bta_av_co_audio_update_selectable_codec(*iter, p_peer); } // Select the codec for (const auto& iter : bta_av_co_cb.codecs->orderedSourceCodecs()) { APPL_TRACE_DEBUG("%s: trying codec %s", __func__, iter->name().c_str()); // Try to select an open device for the codec tBTA_AV_CO_SINK* p_sink = bta_av_co_audio_codec_selected(*iter, p_peer); p_sink = bta_av_co_audio_codec_selected(*iter, p_peer); if (p_sink != NULL) { APPL_TRACE_DEBUG("%s: selected codec %s", __func__, iter->name().c_str()); return p_sink; break; } APPL_TRACE_DEBUG("%s: cannot use codec %s", __func__, iter->name().c_str()); } return NULL; // NOTE: Unconditionally dispatch the event to make sure a callback with // the most recent codec info is generated. btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0); return p_sink; } // Select an open device for the preferred codec specified by |codec_config|. Loading Loading @@ -896,8 +916,9 @@ static tBTA_AV_CO_SINK* bta_av_co_audio_codec_selected( codec_config.name().c_str()); return NULL; } if (!bta_av_co_cb.codecs->setCodecConfig(p_sink->codec_caps, true, new_codec_config)) { if (!bta_av_co_cb.codecs->setCodecConfig( p_sink->codec_caps, true /* is_capability */, new_codec_config, true /* select_current_codec */)) { APPL_TRACE_DEBUG("%s: cannot set source codec %s", __func__, codec_config.name().c_str()); return NULL; Loading @@ -906,11 +927,52 @@ static tBTA_AV_CO_SINK* bta_av_co_audio_codec_selected( bta_av_co_save_new_codec_config(p_peer, new_codec_config, p_sink->num_protect, p_sink->protect_info); btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0); // NOTE: Event BTIF_AV_SOURCE_CONFIG_UPDATED_EVT is dispatched by the caller return p_sink; } // Update a selectable codec |codec_config| with the corresponding codec // information from a peer device |p_peer|. // Returns true if the codec is updated, otherwise false. static bool bta_av_co_audio_update_selectable_codec( A2dpCodecConfig& codec_config, const tBTA_AV_CO_PEER* p_peer) { uint8_t new_codec_config[AVDT_CODEC_SIZE]; APPL_TRACE_DEBUG("%s", __func__); // Find the peer sink for the codec const tBTA_AV_CO_SINK* p_sink = NULL; for (size_t index = 0; index < p_peer->num_sup_sinks; index++) { btav_a2dp_codec_index_t peer_codec_index = A2DP_SourceCodecIndex(p_peer->sinks[index].codec_caps); if (peer_codec_index != codec_config.codecIndex()) { continue; } if (!bta_av_co_audio_sink_supports_cp(&p_peer->sinks[index])) { APPL_TRACE_DEBUG( "%s: peer sink for codec %s does not support " "Copy Protection", __func__, codec_config.name().c_str()); continue; } p_sink = &p_peer->sinks[index]; break; } if (p_sink == NULL) { // The peer sink device does not support this codec return false; } if (!bta_av_co_cb.codecs->setCodecConfig( p_sink->codec_caps, true /* is_capability */, new_codec_config, false /* select_current_codec */)) { APPL_TRACE_DEBUG("%s: cannot update source codec %s", __func__, codec_config.name().c_str()); return false; } return true; } static void bta_av_co_save_new_codec_config(tBTA_AV_CO_PEER* p_peer, const uint8_t* new_codec_config, uint8_t num_protect, Loading Loading @@ -973,9 +1035,11 @@ const tA2DP_ENCODER_INTERFACE* bta_av_co_get_encoder_interface(void) { bool bta_av_co_set_codec_user_config( const btav_a2dp_codec_config_t& codec_user_config) { uint8_t result_codec_config[AVDT_CODEC_SIZE]; const tBTA_AV_CO_SINK* p_sink = nullptr; bool restart_input = false; bool restart_output = false; bool config_updated = false; bool success = true; // Find the peer that is currently open tBTA_AV_CO_PEER* p_peer = nullptr; Loading @@ -988,11 +1052,11 @@ bool bta_av_co_set_codec_user_config( } if (p_peer == nullptr) { APPL_TRACE_ERROR("%s: no open peer to configure", __func__); return false; success = false; goto done; } // Find the peer SEP codec to use const tBTA_AV_CO_SINK* p_sink = nullptr; if (codec_user_config.codec_type < BTAV_A2DP_CODEC_INDEX_MAX) { for (size_t index = 0; index < p_peer->num_sup_sinks; index++) { btav_a2dp_codec_index_t peer_codec_index = Loading @@ -1008,7 +1072,8 @@ bool bta_av_co_set_codec_user_config( } if (p_sink == nullptr) { APPL_TRACE_ERROR("%s: cannot find peer SEP to configure", __func__); return false; success = false; goto done; } tA2DP_ENCODER_INIT_PEER_PARAMS peer_params; Loading @@ -1017,7 +1082,8 @@ bool bta_av_co_set_codec_user_config( codec_user_config, &peer_params, p_sink->codec_caps, result_codec_config, &restart_input, &restart_output, &config_updated)) { return false; success = false; goto done; } if (restart_output) { Loading @@ -1034,13 +1100,15 @@ bool bta_av_co_set_codec_user_config( p_peer->codec_config, num_protect, bta_av_co_cp_scmst); } if (restart_input || config_updated) { done: // NOTE: We uncoditionally send the upcall even if there is no change // or the user config failed. Thus, the caller would always know whether the // request succeeded or failed. // NOTE: Currently, the input is restarted by sending an upcall // and informing the Media Framework about the change. btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0); } return true; return success; } // Sets the Over-The-Air preferred codec configuration. Loading Loading @@ -1211,4 +1279,8 @@ void bta_av_co_init(void) { bta_av_co_cb.codecs->init(); A2DP_InitDefaultCodec(bta_av_co_cb.codec_config); mutex_global_unlock(); // NOTE: Unconditionally dispatch the event to make sure a callback with // the most recent codec info is generated. btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0); } system/btif/src/btif_av.cc +6 −4 Original line number Diff line number Diff line Loading @@ -296,12 +296,14 @@ static void btif_update_source_codec(void* p_data) { static void btif_report_source_codec_state(UNUSED_ATTR void* p_data) { btav_a2dp_codec_config_t codec_config; std::vector<btav_a2dp_codec_config_t> codec_capabilities; std::vector<btav_a2dp_codec_config_t> codecs_local_capabilities; std::vector<btav_a2dp_codec_config_t> codecs_selectable_capabilities; A2dpCodecs* a2dp_codecs = bta_av_get_a2dp_codecs(); if (a2dp_codecs == nullptr) return; if (!a2dp_codecs->getCodecConfigAndCapabilities(&codec_config, &codec_capabilities)) { if (!a2dp_codecs->getCodecConfigAndCapabilities( &codec_config, &codecs_local_capabilities, &codecs_selectable_capabilities)) { BTIF_TRACE_WARNING( "BTIF_AV_SOURCE_CONFIG_UPDATED_EVT failed: " "cannot get codec config and capabilities"); Loading @@ -309,7 +311,7 @@ static void btif_report_source_codec_state(UNUSED_ATTR void* p_data) { } if (bt_av_src_callbacks != NULL) { HAL_CBACK(bt_av_src_callbacks, audio_config_cb, codec_config, codec_capabilities); codecs_local_capabilities, codecs_selectable_capabilities); } } Loading system/stack/a2dp/a2dp_aac.cc +57 −1 Original line number Diff line number Diff line Loading @@ -650,7 +650,28 @@ UNUSED_ATTR static void build_codec_config(const tA2DP_AAC_CIE& config_cie, } A2dpCodecConfigAac::A2dpCodecConfigAac() : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_AAC, "AAC") {} : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_AAC, "AAC") { // Compute the local capability if (a2dp_aac_caps.sampleRate & A2DP_AAC_SAMPLING_FREQ_44100) { codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100; } if (a2dp_aac_caps.sampleRate & A2DP_AAC_SAMPLING_FREQ_48000) { codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000; } if (a2dp_aac_caps.sampleRate & A2DP_AAC_SAMPLING_FREQ_88200) { codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_88200; } if (a2dp_aac_caps.sampleRate & A2DP_AAC_SAMPLING_FREQ_96000) { codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_96000; } codec_local_capability_.bits_per_sample = a2dp_aac_caps.bits_per_sample; if (a2dp_aac_caps.channelMode & A2DP_AAC_CHANNEL_MODE_MONO) { codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO; } if (a2dp_aac_caps.channelMode & A2DP_AAC_CHANNEL_MODE_STEREO) { codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; } } A2dpCodecConfigAac::~A2dpCodecConfigAac() {} Loading Loading @@ -873,6 +894,8 @@ bool A2dpCodecConfigAac::setCodecConfig(const uint8_t* p_peer_codec_info, // Save the internal state btav_a2dp_codec_config_t saved_codec_config = codec_config_; btav_a2dp_codec_config_t saved_codec_capability = codec_capability_; btav_a2dp_codec_config_t saved_codec_selectable_capability = codec_selectable_capability_; btav_a2dp_codec_config_t saved_codec_user_config = codec_user_config_; btav_a2dp_codec_config_t saved_codec_audio_config = codec_audio_config_; uint8_t saved_ota_codec_config[AVDT_CODEC_SIZE]; Loading Loading @@ -953,6 +976,24 @@ bool A2dpCodecConfigAac::setCodecConfig(const uint8_t* p_peer_codec_info, // Select the sample frequency if there is no user preference do { // Compute the selectable capability if (sampleRate & A2DP_AAC_SAMPLING_FREQ_44100) { codec_selectable_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100; } if (sampleRate & A2DP_AAC_SAMPLING_FREQ_48000) { codec_selectable_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000; } if (sampleRate & A2DP_AAC_SAMPLING_FREQ_88200) { codec_selectable_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_88200; } if (sampleRate & A2DP_AAC_SAMPLING_FREQ_96000) { codec_selectable_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_96000; } if (codec_config_.sample_rate != BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) break; // Compute the common capability Loading Loading @@ -1030,6 +1071,10 @@ bool A2dpCodecConfigAac::setCodecConfig(const uint8_t* p_peer_codec_info, // Select the bits per sample if there is no user preference do { // Compute the selectable capability codec_selectable_capability_.bits_per_sample = a2dp_aac_caps.bits_per_sample; if (codec_config_.bits_per_sample != BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE) break; Loading Loading @@ -1092,6 +1137,16 @@ bool A2dpCodecConfigAac::setCodecConfig(const uint8_t* p_peer_codec_info, // Select the channel mode if there is no user preference do { // Compute the selectable capability if (channelMode & A2DP_AAC_CHANNEL_MODE_MONO) { codec_selectable_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO; } if (channelMode & A2DP_AAC_CHANNEL_MODE_STEREO) { codec_selectable_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; } if (codec_config_.channel_mode != BTAV_A2DP_CODEC_CHANNEL_MODE_NONE) break; // Compute the common capability Loading Loading @@ -1164,6 +1219,7 @@ fail: // Restore the internal state codec_config_ = saved_codec_config; codec_capability_ = saved_codec_capability; codec_selectable_capability_ = saved_codec_selectable_capability; codec_user_config_ = saved_codec_user_config; codec_audio_config_ = saved_codec_audio_config; memcpy(ota_codec_config_, saved_ota_codec_config, sizeof(ota_codec_config_)); Loading system/stack/a2dp/a2dp_codec_config.cc +66 −20 Original line number Diff line number Diff line Loading @@ -35,22 +35,34 @@ /* The Media Type offset within the codec info byte array */ #define A2DP_MEDIA_TYPE_OFFSET 1 // Initializes the codec config. // |codec_config| is the codec config to initialize. // |codec_index| and |codec_priority| are the codec type and priority to use // for the initialization. static void init_btav_a2dp_codec_config( btav_a2dp_codec_config_t* codec_config, btav_a2dp_codec_index_t codec_index, btav_a2dp_codec_priority_t codec_priority) { memset(codec_config, 0, sizeof(btav_a2dp_codec_config_t)); codec_config->codec_type = codec_index; codec_config->codec_priority = codec_priority; } A2dpCodecConfig::A2dpCodecConfig(btav_a2dp_codec_index_t codec_index, const std::string& name) : codec_index_(codec_index), name_(name) { setDefaultCodecPriority(); memset(&codec_config_, 0, sizeof(codec_config_)); codec_config_.codec_type = codec_index_; memset(&codec_capability_, 0, sizeof(codec_capability_)); codec_capability_.codec_type = codec_index_; memset(&codec_user_config_, 0, sizeof(codec_user_config_)); codec_user_config_.codec_type = codec_index_; memset(&codec_audio_config_, 0, sizeof(codec_audio_config_)); codec_audio_config_.codec_type = codec_index_; init_btav_a2dp_codec_config(&codec_config_, codec_index_, codecPriority()); init_btav_a2dp_codec_config(&codec_capability_, codec_index_, codecPriority()); init_btav_a2dp_codec_config(&codec_local_capability_, codec_index_, codecPriority()); init_btav_a2dp_codec_config(&codec_selectable_capability_, codec_index_, codecPriority()); init_btav_a2dp_codec_config(&codec_user_config_, codec_index_, BTAV_A2DP_CODEC_PRIORITY_DEFAULT); init_btav_a2dp_codec_config(&codec_audio_config_, codec_index_, BTAV_A2DP_CODEC_PRIORITY_DEFAULT); memset(ota_codec_config_, 0, sizeof(ota_codec_config_)); memset(ota_codec_peer_capability_, 0, sizeof(ota_codec_peer_capability_)); Loading @@ -61,7 +73,7 @@ A2dpCodecConfig::~A2dpCodecConfig() {} void A2dpCodecConfig::setCodecPriority( btav_a2dp_codec_priority_t codec_priority) { if (codec_priority == 0) { if (codec_priority == BTAV_A2DP_CODEC_PRIORITY_DEFAULT) { // Compute the default codec priority setDefaultCodecPriority(); } else { Loading @@ -71,7 +83,8 @@ void A2dpCodecConfig::setCodecPriority( void A2dpCodecConfig::setDefaultCodecPriority() { // Compute the default codec priority codec_priority_ = 1000 * codec_index_ + 1; uint32_t priority = 1000 * codec_index_ + 1; codec_priority_ = static_cast<btav_a2dp_codec_priority_t>(priority); } A2dpCodecConfig* A2dpCodecConfig::createCodec( Loading Loading @@ -141,6 +154,20 @@ btav_a2dp_codec_config_t A2dpCodecConfig::getCodecCapability() { return codec_capability_; } btav_a2dp_codec_config_t A2dpCodecConfig::getCodecLocalCapability() { std::lock_guard<std::recursive_mutex> lock(codec_mutex_); // TODO: We should check whether the codec capability is valid return codec_local_capability_; } btav_a2dp_codec_config_t A2dpCodecConfig::getCodecSelectableCapability() { std::lock_guard<std::recursive_mutex> lock(codec_mutex_); // TODO: We should check whether the codec capability is valid return codec_selectable_capability_; } btav_a2dp_codec_config_t A2dpCodecConfig::getCodecUserConfig() { std::lock_guard<std::recursive_mutex> lock(codec_mutex_); Loading Loading @@ -172,7 +199,7 @@ uint8_t A2dpCodecConfig::getAudioBitsPerSample() { bool A2dpCodecConfig::isCodecConfigEmpty( const btav_a2dp_codec_config_t& codec_config) { return ( (codec_config.codec_priority == 0) && (codec_config.codec_priority == BTAV_A2DP_CODEC_PRIORITY_DEFAULT) && (codec_config.sample_rate == BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) && (codec_config.bits_per_sample == BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE) && (codec_config.channel_mode == BTAV_A2DP_CODEC_CHANNEL_MODE_NONE) && Loading Loading @@ -324,7 +351,8 @@ A2dpCodecConfig* A2dpCodecs::findSourceCodecConfig( bool A2dpCodecs::setCodecConfig(const uint8_t* p_peer_codec_info, bool is_capability, uint8_t* p_result_codec_config) { uint8_t* p_result_codec_config, bool select_current_codec) { std::lock_guard<std::recursive_mutex> lock(codec_mutex_); A2dpCodecConfig* a2dp_codec_config = findSourceCodecConfig(p_peer_codec_info); if (a2dp_codec_config == nullptr) return false; Loading @@ -332,7 +360,9 @@ bool A2dpCodecs::setCodecConfig(const uint8_t* p_peer_codec_info, p_result_codec_config)) { return false; } if (select_current_codec) { current_codec_config_ = a2dp_codec_config; } return true; } Loading Loading @@ -522,7 +552,8 @@ fail: bool A2dpCodecs::getCodecConfigAndCapabilities( btav_a2dp_codec_config_t* p_codec_config, std::vector<btav_a2dp_codec_config_t>* p_codec_capabilities) { std::vector<btav_a2dp_codec_config_t>* p_codecs_local_capabilities, std::vector<btav_a2dp_codec_config_t>* p_codecs_selectable_capabilities) { std::lock_guard<std::recursive_mutex> lock(codec_mutex_); if (current_codec_config_ != nullptr) { Loading @@ -533,11 +564,26 @@ bool A2dpCodecs::getCodecConfigAndCapabilities( *p_codec_config = codec_config; } std::vector<btav_a2dp_codec_config_t> codec_capabilities; std::vector<btav_a2dp_codec_config_t> codecs_capabilities; for (auto codec : orderedSourceCodecs()) { codec_capabilities.push_back(codec->getCodecCapability()); codecs_capabilities.push_back(codec->getCodecLocalCapability()); } *p_codec_capabilities = codec_capabilities; *p_codecs_local_capabilities = codecs_capabilities; codecs_capabilities.clear(); for (auto codec : orderedSourceCodecs()) { btav_a2dp_codec_config_t codec_capability = codec->getCodecSelectableCapability(); // Don't add entries that cannot be used if ((codec_capability.sample_rate == BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) || (codec_capability.bits_per_sample == BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE) || (codec_capability.channel_mode == BTAV_A2DP_CODEC_CHANNEL_MODE_NONE)) { continue; } codecs_capabilities.push_back(codec_capability); } *p_codecs_selectable_capabilities = codecs_capabilities; return true; } Loading system/stack/a2dp/a2dp_sbc.cc +77 −17 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ typedef struct { uint8_t alloc_method; /* Allocation method */ uint8_t min_bitpool; /* Minimum bitpool */ uint8_t max_bitpool; /* Maximum bitpool */ btav_a2dp_codec_bits_per_sample_t bits_per_sample; } tA2DP_SBC_CIE; /* SBC SRC codec capabilities */ Loading @@ -59,7 +60,8 @@ static const tA2DP_SBC_CIE a2dp_sbc_caps = { A2DP_SBC_IE_SUBBAND_8, /* num_subbands */ A2DP_SBC_IE_ALLOC_MD_L, /* alloc_method */ A2DP_SBC_IE_MIN_BITPOOL, /* min_bitpool */ A2DP_SBC_MAX_BITPOOL /* max_bitpool */ A2DP_SBC_MAX_BITPOOL, /* max_bitpool */ BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16 /* bits_per_sample */ }; /* SBC SINK codec capabilities */ Loading @@ -72,7 +74,8 @@ static const tA2DP_SBC_CIE a2dp_sbc_sink_caps = { (A2DP_SBC_IE_SUBBAND_4 | A2DP_SBC_IE_SUBBAND_8), /* num_subbands */ (A2DP_SBC_IE_ALLOC_MD_L | A2DP_SBC_IE_ALLOC_MD_S), /* alloc_method */ A2DP_SBC_IE_MIN_BITPOOL, /* min_bitpool */ A2DP_SBC_MAX_BITPOOL /* max_bitpool */ A2DP_SBC_MAX_BITPOOL, /* max_bitpool */ BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16 /* bits_per_sample */ }; /* Default SBC codec configuration */ Loading @@ -83,7 +86,8 @@ const tA2DP_SBC_CIE a2dp_sbc_default_config = { A2DP_SBC_IE_SUBBAND_8, /* num_subbands */ A2DP_SBC_IE_ALLOC_MD_L, /* alloc_method */ A2DP_SBC_IE_MIN_BITPOOL, /* min_bitpool */ A2DP_SBC_MAX_BITPOOL /* max_bitpool */ A2DP_SBC_MAX_BITPOOL, /* max_bitpool */ BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16 /* bits_per_sample */ }; static const tA2DP_ENCODER_INTERFACE a2dp_encoder_interface_sbc = { Loading Loading @@ -1014,7 +1018,7 @@ UNUSED_ATTR static void build_codec_config(const tA2DP_SBC_CIE& config_cie, if (config_cie.samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) result->sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000; result->bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16; result->bits_per_sample = config_cie.bits_per_sample; if (config_cie.ch_mode & A2DP_SBC_IE_CH_MD_MONO) result->channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO; Loading @@ -1026,7 +1030,28 @@ UNUSED_ATTR static void build_codec_config(const tA2DP_SBC_CIE& config_cie, } A2dpCodecConfigSbc::A2dpCodecConfigSbc() : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_SBC, "SBC") {} : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_SBC, "SBC") { // Compute the local capability if (a2dp_sbc_caps.samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) { codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100; } if (a2dp_sbc_caps.samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) { codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000; } codec_local_capability_.bits_per_sample = a2dp_sbc_caps.bits_per_sample; if (a2dp_sbc_caps.ch_mode & A2DP_SBC_IE_CH_MD_MONO) { codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO; } if (a2dp_sbc_caps.ch_mode & A2DP_SBC_IE_CH_MD_JOINT) { codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; } if (a2dp_sbc_caps.ch_mode & A2DP_SBC_IE_CH_MD_STEREO) { codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; } if (a2dp_sbc_caps.ch_mode & A2DP_SBC_IE_CH_MD_DUAL) { codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; } } A2dpCodecConfigSbc::~A2dpCodecConfigSbc() {} Loading Loading @@ -1214,6 +1239,8 @@ bool A2dpCodecConfigSbc::setCodecConfig(const uint8_t* p_peer_codec_info, // Save the internal state btav_a2dp_codec_config_t saved_codec_config = codec_config_; btav_a2dp_codec_config_t saved_codec_capability = codec_capability_; btav_a2dp_codec_config_t saved_codec_selectable_capability = codec_selectable_capability_; btav_a2dp_codec_config_t saved_codec_user_config = codec_user_config_; btav_a2dp_codec_config_t saved_codec_audio_config = codec_audio_config_; uint8_t saved_ota_codec_config[AVDT_CODEC_SIZE]; Loading Loading @@ -1270,6 +1297,16 @@ bool A2dpCodecConfigSbc::setCodecConfig(const uint8_t* p_peer_codec_info, // Select the sample frequency if there is no user preference do { // Compute the selectable capability if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) { codec_selectable_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100; } if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) { codec_selectable_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000; } if (codec_config_.sample_rate != BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) break; // Compute the common capability Loading Loading @@ -1326,6 +1363,10 @@ bool A2dpCodecConfigSbc::setCodecConfig(const uint8_t* p_peer_codec_info, // Select the bits per sample if there is no user preference do { // Compute the selectable capability codec_selectable_capability_.bits_per_sample = a2dp_sbc_caps.bits_per_sample; if (codec_config_.bits_per_sample != BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE) break; Loading Loading @@ -1396,6 +1437,24 @@ bool A2dpCodecConfigSbc::setCodecConfig(const uint8_t* p_peer_codec_info, // Select the channel mode if there is no user preference do { // Compute the selectable capability if (ch_mode & A2DP_SBC_IE_CH_MD_MONO) { codec_selectable_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO; } if (ch_mode & A2DP_SBC_IE_CH_MD_JOINT) { codec_selectable_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; } if (ch_mode & A2DP_SBC_IE_CH_MD_STEREO) { codec_selectable_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; } if (ch_mode & A2DP_SBC_IE_CH_MD_DUAL) { codec_selectable_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; } if (codec_config_.channel_mode != BTAV_A2DP_CODEC_CHANNEL_MODE_NONE) break; // Compute the common capability Loading Loading @@ -1538,6 +1597,7 @@ fail: // Restore the internal state codec_config_ = saved_codec_config; codec_capability_ = saved_codec_capability; codec_selectable_capability_ = saved_codec_selectable_capability; codec_user_config_ = saved_codec_user_config; codec_audio_config_ = saved_codec_audio_config; memcpy(ota_codec_config_, saved_ota_codec_config, sizeof(ota_codec_config_)); Loading Loading
system/btif/co/bta_av_co.cc +90 −18 Original line number Diff line number Diff line Loading @@ -132,6 +132,8 @@ static const tBTA_AV_CO_SINK* bta_av_co_find_peer_src_supports_codec( static tBTA_AV_CO_SINK* bta_av_co_audio_set_codec(tBTA_AV_CO_PEER* p_peer); static tBTA_AV_CO_SINK* bta_av_co_audio_codec_selected( A2dpCodecConfig& codec_config, tBTA_AV_CO_PEER* p_peer); static bool bta_av_co_audio_update_selectable_codec( A2dpCodecConfig& codec_config, const tBTA_AV_CO_PEER* p_peer); static void bta_av_co_save_new_codec_config(tBTA_AV_CO_PEER* p_peer, const uint8_t* new_codec_config, uint8_t num_protect, Loading Loading @@ -848,21 +850,39 @@ static const tBTA_AV_CO_SINK* bta_av_co_find_peer_src_supports_codec( // // Select the current codec configuration based on peer codec support. // Return true on success, otherwise false. // Furthermore, the local state for the remaining non-selected codecs is // updated to reflect whether the codec is selectable. // Return a pointer to the corresponding |tBTA_AV_CO_SINK| sink entry // on success, otherwise NULL. // static tBTA_AV_CO_SINK* bta_av_co_audio_set_codec(tBTA_AV_CO_PEER* p_peer) { tBTA_AV_CO_SINK* p_sink = NULL; // Update all selectable codecs. // This is needed to update the selectable parameters for each codec. // NOTE: The selectable codec info is used only for informational purpose. for (const auto& iter : bta_av_co_cb.codecs->orderedSourceCodecs()) { APPL_TRACE_DEBUG("%s: updating selectable codec %s", __func__, iter->name().c_str()); bta_av_co_audio_update_selectable_codec(*iter, p_peer); } // Select the codec for (const auto& iter : bta_av_co_cb.codecs->orderedSourceCodecs()) { APPL_TRACE_DEBUG("%s: trying codec %s", __func__, iter->name().c_str()); // Try to select an open device for the codec tBTA_AV_CO_SINK* p_sink = bta_av_co_audio_codec_selected(*iter, p_peer); p_sink = bta_av_co_audio_codec_selected(*iter, p_peer); if (p_sink != NULL) { APPL_TRACE_DEBUG("%s: selected codec %s", __func__, iter->name().c_str()); return p_sink; break; } APPL_TRACE_DEBUG("%s: cannot use codec %s", __func__, iter->name().c_str()); } return NULL; // NOTE: Unconditionally dispatch the event to make sure a callback with // the most recent codec info is generated. btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0); return p_sink; } // Select an open device for the preferred codec specified by |codec_config|. Loading Loading @@ -896,8 +916,9 @@ static tBTA_AV_CO_SINK* bta_av_co_audio_codec_selected( codec_config.name().c_str()); return NULL; } if (!bta_av_co_cb.codecs->setCodecConfig(p_sink->codec_caps, true, new_codec_config)) { if (!bta_av_co_cb.codecs->setCodecConfig( p_sink->codec_caps, true /* is_capability */, new_codec_config, true /* select_current_codec */)) { APPL_TRACE_DEBUG("%s: cannot set source codec %s", __func__, codec_config.name().c_str()); return NULL; Loading @@ -906,11 +927,52 @@ static tBTA_AV_CO_SINK* bta_av_co_audio_codec_selected( bta_av_co_save_new_codec_config(p_peer, new_codec_config, p_sink->num_protect, p_sink->protect_info); btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0); // NOTE: Event BTIF_AV_SOURCE_CONFIG_UPDATED_EVT is dispatched by the caller return p_sink; } // Update a selectable codec |codec_config| with the corresponding codec // information from a peer device |p_peer|. // Returns true if the codec is updated, otherwise false. static bool bta_av_co_audio_update_selectable_codec( A2dpCodecConfig& codec_config, const tBTA_AV_CO_PEER* p_peer) { uint8_t new_codec_config[AVDT_CODEC_SIZE]; APPL_TRACE_DEBUG("%s", __func__); // Find the peer sink for the codec const tBTA_AV_CO_SINK* p_sink = NULL; for (size_t index = 0; index < p_peer->num_sup_sinks; index++) { btav_a2dp_codec_index_t peer_codec_index = A2DP_SourceCodecIndex(p_peer->sinks[index].codec_caps); if (peer_codec_index != codec_config.codecIndex()) { continue; } if (!bta_av_co_audio_sink_supports_cp(&p_peer->sinks[index])) { APPL_TRACE_DEBUG( "%s: peer sink for codec %s does not support " "Copy Protection", __func__, codec_config.name().c_str()); continue; } p_sink = &p_peer->sinks[index]; break; } if (p_sink == NULL) { // The peer sink device does not support this codec return false; } if (!bta_av_co_cb.codecs->setCodecConfig( p_sink->codec_caps, true /* is_capability */, new_codec_config, false /* select_current_codec */)) { APPL_TRACE_DEBUG("%s: cannot update source codec %s", __func__, codec_config.name().c_str()); return false; } return true; } static void bta_av_co_save_new_codec_config(tBTA_AV_CO_PEER* p_peer, const uint8_t* new_codec_config, uint8_t num_protect, Loading Loading @@ -973,9 +1035,11 @@ const tA2DP_ENCODER_INTERFACE* bta_av_co_get_encoder_interface(void) { bool bta_av_co_set_codec_user_config( const btav_a2dp_codec_config_t& codec_user_config) { uint8_t result_codec_config[AVDT_CODEC_SIZE]; const tBTA_AV_CO_SINK* p_sink = nullptr; bool restart_input = false; bool restart_output = false; bool config_updated = false; bool success = true; // Find the peer that is currently open tBTA_AV_CO_PEER* p_peer = nullptr; Loading @@ -988,11 +1052,11 @@ bool bta_av_co_set_codec_user_config( } if (p_peer == nullptr) { APPL_TRACE_ERROR("%s: no open peer to configure", __func__); return false; success = false; goto done; } // Find the peer SEP codec to use const tBTA_AV_CO_SINK* p_sink = nullptr; if (codec_user_config.codec_type < BTAV_A2DP_CODEC_INDEX_MAX) { for (size_t index = 0; index < p_peer->num_sup_sinks; index++) { btav_a2dp_codec_index_t peer_codec_index = Loading @@ -1008,7 +1072,8 @@ bool bta_av_co_set_codec_user_config( } if (p_sink == nullptr) { APPL_TRACE_ERROR("%s: cannot find peer SEP to configure", __func__); return false; success = false; goto done; } tA2DP_ENCODER_INIT_PEER_PARAMS peer_params; Loading @@ -1017,7 +1082,8 @@ bool bta_av_co_set_codec_user_config( codec_user_config, &peer_params, p_sink->codec_caps, result_codec_config, &restart_input, &restart_output, &config_updated)) { return false; success = false; goto done; } if (restart_output) { Loading @@ -1034,13 +1100,15 @@ bool bta_av_co_set_codec_user_config( p_peer->codec_config, num_protect, bta_av_co_cp_scmst); } if (restart_input || config_updated) { done: // NOTE: We uncoditionally send the upcall even if there is no change // or the user config failed. Thus, the caller would always know whether the // request succeeded or failed. // NOTE: Currently, the input is restarted by sending an upcall // and informing the Media Framework about the change. btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0); } return true; return success; } // Sets the Over-The-Air preferred codec configuration. Loading Loading @@ -1211,4 +1279,8 @@ void bta_av_co_init(void) { bta_av_co_cb.codecs->init(); A2DP_InitDefaultCodec(bta_av_co_cb.codec_config); mutex_global_unlock(); // NOTE: Unconditionally dispatch the event to make sure a callback with // the most recent codec info is generated. btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0); }
system/btif/src/btif_av.cc +6 −4 Original line number Diff line number Diff line Loading @@ -296,12 +296,14 @@ static void btif_update_source_codec(void* p_data) { static void btif_report_source_codec_state(UNUSED_ATTR void* p_data) { btav_a2dp_codec_config_t codec_config; std::vector<btav_a2dp_codec_config_t> codec_capabilities; std::vector<btav_a2dp_codec_config_t> codecs_local_capabilities; std::vector<btav_a2dp_codec_config_t> codecs_selectable_capabilities; A2dpCodecs* a2dp_codecs = bta_av_get_a2dp_codecs(); if (a2dp_codecs == nullptr) return; if (!a2dp_codecs->getCodecConfigAndCapabilities(&codec_config, &codec_capabilities)) { if (!a2dp_codecs->getCodecConfigAndCapabilities( &codec_config, &codecs_local_capabilities, &codecs_selectable_capabilities)) { BTIF_TRACE_WARNING( "BTIF_AV_SOURCE_CONFIG_UPDATED_EVT failed: " "cannot get codec config and capabilities"); Loading @@ -309,7 +311,7 @@ static void btif_report_source_codec_state(UNUSED_ATTR void* p_data) { } if (bt_av_src_callbacks != NULL) { HAL_CBACK(bt_av_src_callbacks, audio_config_cb, codec_config, codec_capabilities); codecs_local_capabilities, codecs_selectable_capabilities); } } Loading
system/stack/a2dp/a2dp_aac.cc +57 −1 Original line number Diff line number Diff line Loading @@ -650,7 +650,28 @@ UNUSED_ATTR static void build_codec_config(const tA2DP_AAC_CIE& config_cie, } A2dpCodecConfigAac::A2dpCodecConfigAac() : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_AAC, "AAC") {} : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_AAC, "AAC") { // Compute the local capability if (a2dp_aac_caps.sampleRate & A2DP_AAC_SAMPLING_FREQ_44100) { codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100; } if (a2dp_aac_caps.sampleRate & A2DP_AAC_SAMPLING_FREQ_48000) { codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000; } if (a2dp_aac_caps.sampleRate & A2DP_AAC_SAMPLING_FREQ_88200) { codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_88200; } if (a2dp_aac_caps.sampleRate & A2DP_AAC_SAMPLING_FREQ_96000) { codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_96000; } codec_local_capability_.bits_per_sample = a2dp_aac_caps.bits_per_sample; if (a2dp_aac_caps.channelMode & A2DP_AAC_CHANNEL_MODE_MONO) { codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO; } if (a2dp_aac_caps.channelMode & A2DP_AAC_CHANNEL_MODE_STEREO) { codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; } } A2dpCodecConfigAac::~A2dpCodecConfigAac() {} Loading Loading @@ -873,6 +894,8 @@ bool A2dpCodecConfigAac::setCodecConfig(const uint8_t* p_peer_codec_info, // Save the internal state btav_a2dp_codec_config_t saved_codec_config = codec_config_; btav_a2dp_codec_config_t saved_codec_capability = codec_capability_; btav_a2dp_codec_config_t saved_codec_selectable_capability = codec_selectable_capability_; btav_a2dp_codec_config_t saved_codec_user_config = codec_user_config_; btav_a2dp_codec_config_t saved_codec_audio_config = codec_audio_config_; uint8_t saved_ota_codec_config[AVDT_CODEC_SIZE]; Loading Loading @@ -953,6 +976,24 @@ bool A2dpCodecConfigAac::setCodecConfig(const uint8_t* p_peer_codec_info, // Select the sample frequency if there is no user preference do { // Compute the selectable capability if (sampleRate & A2DP_AAC_SAMPLING_FREQ_44100) { codec_selectable_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100; } if (sampleRate & A2DP_AAC_SAMPLING_FREQ_48000) { codec_selectable_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000; } if (sampleRate & A2DP_AAC_SAMPLING_FREQ_88200) { codec_selectable_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_88200; } if (sampleRate & A2DP_AAC_SAMPLING_FREQ_96000) { codec_selectable_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_96000; } if (codec_config_.sample_rate != BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) break; // Compute the common capability Loading Loading @@ -1030,6 +1071,10 @@ bool A2dpCodecConfigAac::setCodecConfig(const uint8_t* p_peer_codec_info, // Select the bits per sample if there is no user preference do { // Compute the selectable capability codec_selectable_capability_.bits_per_sample = a2dp_aac_caps.bits_per_sample; if (codec_config_.bits_per_sample != BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE) break; Loading Loading @@ -1092,6 +1137,16 @@ bool A2dpCodecConfigAac::setCodecConfig(const uint8_t* p_peer_codec_info, // Select the channel mode if there is no user preference do { // Compute the selectable capability if (channelMode & A2DP_AAC_CHANNEL_MODE_MONO) { codec_selectable_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO; } if (channelMode & A2DP_AAC_CHANNEL_MODE_STEREO) { codec_selectable_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; } if (codec_config_.channel_mode != BTAV_A2DP_CODEC_CHANNEL_MODE_NONE) break; // Compute the common capability Loading Loading @@ -1164,6 +1219,7 @@ fail: // Restore the internal state codec_config_ = saved_codec_config; codec_capability_ = saved_codec_capability; codec_selectable_capability_ = saved_codec_selectable_capability; codec_user_config_ = saved_codec_user_config; codec_audio_config_ = saved_codec_audio_config; memcpy(ota_codec_config_, saved_ota_codec_config, sizeof(ota_codec_config_)); Loading
system/stack/a2dp/a2dp_codec_config.cc +66 −20 Original line number Diff line number Diff line Loading @@ -35,22 +35,34 @@ /* The Media Type offset within the codec info byte array */ #define A2DP_MEDIA_TYPE_OFFSET 1 // Initializes the codec config. // |codec_config| is the codec config to initialize. // |codec_index| and |codec_priority| are the codec type and priority to use // for the initialization. static void init_btav_a2dp_codec_config( btav_a2dp_codec_config_t* codec_config, btav_a2dp_codec_index_t codec_index, btav_a2dp_codec_priority_t codec_priority) { memset(codec_config, 0, sizeof(btav_a2dp_codec_config_t)); codec_config->codec_type = codec_index; codec_config->codec_priority = codec_priority; } A2dpCodecConfig::A2dpCodecConfig(btav_a2dp_codec_index_t codec_index, const std::string& name) : codec_index_(codec_index), name_(name) { setDefaultCodecPriority(); memset(&codec_config_, 0, sizeof(codec_config_)); codec_config_.codec_type = codec_index_; memset(&codec_capability_, 0, sizeof(codec_capability_)); codec_capability_.codec_type = codec_index_; memset(&codec_user_config_, 0, sizeof(codec_user_config_)); codec_user_config_.codec_type = codec_index_; memset(&codec_audio_config_, 0, sizeof(codec_audio_config_)); codec_audio_config_.codec_type = codec_index_; init_btav_a2dp_codec_config(&codec_config_, codec_index_, codecPriority()); init_btav_a2dp_codec_config(&codec_capability_, codec_index_, codecPriority()); init_btav_a2dp_codec_config(&codec_local_capability_, codec_index_, codecPriority()); init_btav_a2dp_codec_config(&codec_selectable_capability_, codec_index_, codecPriority()); init_btav_a2dp_codec_config(&codec_user_config_, codec_index_, BTAV_A2DP_CODEC_PRIORITY_DEFAULT); init_btav_a2dp_codec_config(&codec_audio_config_, codec_index_, BTAV_A2DP_CODEC_PRIORITY_DEFAULT); memset(ota_codec_config_, 0, sizeof(ota_codec_config_)); memset(ota_codec_peer_capability_, 0, sizeof(ota_codec_peer_capability_)); Loading @@ -61,7 +73,7 @@ A2dpCodecConfig::~A2dpCodecConfig() {} void A2dpCodecConfig::setCodecPriority( btav_a2dp_codec_priority_t codec_priority) { if (codec_priority == 0) { if (codec_priority == BTAV_A2DP_CODEC_PRIORITY_DEFAULT) { // Compute the default codec priority setDefaultCodecPriority(); } else { Loading @@ -71,7 +83,8 @@ void A2dpCodecConfig::setCodecPriority( void A2dpCodecConfig::setDefaultCodecPriority() { // Compute the default codec priority codec_priority_ = 1000 * codec_index_ + 1; uint32_t priority = 1000 * codec_index_ + 1; codec_priority_ = static_cast<btav_a2dp_codec_priority_t>(priority); } A2dpCodecConfig* A2dpCodecConfig::createCodec( Loading Loading @@ -141,6 +154,20 @@ btav_a2dp_codec_config_t A2dpCodecConfig::getCodecCapability() { return codec_capability_; } btav_a2dp_codec_config_t A2dpCodecConfig::getCodecLocalCapability() { std::lock_guard<std::recursive_mutex> lock(codec_mutex_); // TODO: We should check whether the codec capability is valid return codec_local_capability_; } btav_a2dp_codec_config_t A2dpCodecConfig::getCodecSelectableCapability() { std::lock_guard<std::recursive_mutex> lock(codec_mutex_); // TODO: We should check whether the codec capability is valid return codec_selectable_capability_; } btav_a2dp_codec_config_t A2dpCodecConfig::getCodecUserConfig() { std::lock_guard<std::recursive_mutex> lock(codec_mutex_); Loading Loading @@ -172,7 +199,7 @@ uint8_t A2dpCodecConfig::getAudioBitsPerSample() { bool A2dpCodecConfig::isCodecConfigEmpty( const btav_a2dp_codec_config_t& codec_config) { return ( (codec_config.codec_priority == 0) && (codec_config.codec_priority == BTAV_A2DP_CODEC_PRIORITY_DEFAULT) && (codec_config.sample_rate == BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) && (codec_config.bits_per_sample == BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE) && (codec_config.channel_mode == BTAV_A2DP_CODEC_CHANNEL_MODE_NONE) && Loading Loading @@ -324,7 +351,8 @@ A2dpCodecConfig* A2dpCodecs::findSourceCodecConfig( bool A2dpCodecs::setCodecConfig(const uint8_t* p_peer_codec_info, bool is_capability, uint8_t* p_result_codec_config) { uint8_t* p_result_codec_config, bool select_current_codec) { std::lock_guard<std::recursive_mutex> lock(codec_mutex_); A2dpCodecConfig* a2dp_codec_config = findSourceCodecConfig(p_peer_codec_info); if (a2dp_codec_config == nullptr) return false; Loading @@ -332,7 +360,9 @@ bool A2dpCodecs::setCodecConfig(const uint8_t* p_peer_codec_info, p_result_codec_config)) { return false; } if (select_current_codec) { current_codec_config_ = a2dp_codec_config; } return true; } Loading Loading @@ -522,7 +552,8 @@ fail: bool A2dpCodecs::getCodecConfigAndCapabilities( btav_a2dp_codec_config_t* p_codec_config, std::vector<btav_a2dp_codec_config_t>* p_codec_capabilities) { std::vector<btav_a2dp_codec_config_t>* p_codecs_local_capabilities, std::vector<btav_a2dp_codec_config_t>* p_codecs_selectable_capabilities) { std::lock_guard<std::recursive_mutex> lock(codec_mutex_); if (current_codec_config_ != nullptr) { Loading @@ -533,11 +564,26 @@ bool A2dpCodecs::getCodecConfigAndCapabilities( *p_codec_config = codec_config; } std::vector<btav_a2dp_codec_config_t> codec_capabilities; std::vector<btav_a2dp_codec_config_t> codecs_capabilities; for (auto codec : orderedSourceCodecs()) { codec_capabilities.push_back(codec->getCodecCapability()); codecs_capabilities.push_back(codec->getCodecLocalCapability()); } *p_codec_capabilities = codec_capabilities; *p_codecs_local_capabilities = codecs_capabilities; codecs_capabilities.clear(); for (auto codec : orderedSourceCodecs()) { btav_a2dp_codec_config_t codec_capability = codec->getCodecSelectableCapability(); // Don't add entries that cannot be used if ((codec_capability.sample_rate == BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) || (codec_capability.bits_per_sample == BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE) || (codec_capability.channel_mode == BTAV_A2DP_CODEC_CHANNEL_MODE_NONE)) { continue; } codecs_capabilities.push_back(codec_capability); } *p_codecs_selectable_capabilities = codecs_capabilities; return true; } Loading
system/stack/a2dp/a2dp_sbc.cc +77 −17 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ typedef struct { uint8_t alloc_method; /* Allocation method */ uint8_t min_bitpool; /* Minimum bitpool */ uint8_t max_bitpool; /* Maximum bitpool */ btav_a2dp_codec_bits_per_sample_t bits_per_sample; } tA2DP_SBC_CIE; /* SBC SRC codec capabilities */ Loading @@ -59,7 +60,8 @@ static const tA2DP_SBC_CIE a2dp_sbc_caps = { A2DP_SBC_IE_SUBBAND_8, /* num_subbands */ A2DP_SBC_IE_ALLOC_MD_L, /* alloc_method */ A2DP_SBC_IE_MIN_BITPOOL, /* min_bitpool */ A2DP_SBC_MAX_BITPOOL /* max_bitpool */ A2DP_SBC_MAX_BITPOOL, /* max_bitpool */ BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16 /* bits_per_sample */ }; /* SBC SINK codec capabilities */ Loading @@ -72,7 +74,8 @@ static const tA2DP_SBC_CIE a2dp_sbc_sink_caps = { (A2DP_SBC_IE_SUBBAND_4 | A2DP_SBC_IE_SUBBAND_8), /* num_subbands */ (A2DP_SBC_IE_ALLOC_MD_L | A2DP_SBC_IE_ALLOC_MD_S), /* alloc_method */ A2DP_SBC_IE_MIN_BITPOOL, /* min_bitpool */ A2DP_SBC_MAX_BITPOOL /* max_bitpool */ A2DP_SBC_MAX_BITPOOL, /* max_bitpool */ BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16 /* bits_per_sample */ }; /* Default SBC codec configuration */ Loading @@ -83,7 +86,8 @@ const tA2DP_SBC_CIE a2dp_sbc_default_config = { A2DP_SBC_IE_SUBBAND_8, /* num_subbands */ A2DP_SBC_IE_ALLOC_MD_L, /* alloc_method */ A2DP_SBC_IE_MIN_BITPOOL, /* min_bitpool */ A2DP_SBC_MAX_BITPOOL /* max_bitpool */ A2DP_SBC_MAX_BITPOOL, /* max_bitpool */ BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16 /* bits_per_sample */ }; static const tA2DP_ENCODER_INTERFACE a2dp_encoder_interface_sbc = { Loading Loading @@ -1014,7 +1018,7 @@ UNUSED_ATTR static void build_codec_config(const tA2DP_SBC_CIE& config_cie, if (config_cie.samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) result->sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000; result->bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16; result->bits_per_sample = config_cie.bits_per_sample; if (config_cie.ch_mode & A2DP_SBC_IE_CH_MD_MONO) result->channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO; Loading @@ -1026,7 +1030,28 @@ UNUSED_ATTR static void build_codec_config(const tA2DP_SBC_CIE& config_cie, } A2dpCodecConfigSbc::A2dpCodecConfigSbc() : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_SBC, "SBC") {} : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_SBC, "SBC") { // Compute the local capability if (a2dp_sbc_caps.samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) { codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100; } if (a2dp_sbc_caps.samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) { codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000; } codec_local_capability_.bits_per_sample = a2dp_sbc_caps.bits_per_sample; if (a2dp_sbc_caps.ch_mode & A2DP_SBC_IE_CH_MD_MONO) { codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO; } if (a2dp_sbc_caps.ch_mode & A2DP_SBC_IE_CH_MD_JOINT) { codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; } if (a2dp_sbc_caps.ch_mode & A2DP_SBC_IE_CH_MD_STEREO) { codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; } if (a2dp_sbc_caps.ch_mode & A2DP_SBC_IE_CH_MD_DUAL) { codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; } } A2dpCodecConfigSbc::~A2dpCodecConfigSbc() {} Loading Loading @@ -1214,6 +1239,8 @@ bool A2dpCodecConfigSbc::setCodecConfig(const uint8_t* p_peer_codec_info, // Save the internal state btav_a2dp_codec_config_t saved_codec_config = codec_config_; btav_a2dp_codec_config_t saved_codec_capability = codec_capability_; btav_a2dp_codec_config_t saved_codec_selectable_capability = codec_selectable_capability_; btav_a2dp_codec_config_t saved_codec_user_config = codec_user_config_; btav_a2dp_codec_config_t saved_codec_audio_config = codec_audio_config_; uint8_t saved_ota_codec_config[AVDT_CODEC_SIZE]; Loading Loading @@ -1270,6 +1297,16 @@ bool A2dpCodecConfigSbc::setCodecConfig(const uint8_t* p_peer_codec_info, // Select the sample frequency if there is no user preference do { // Compute the selectable capability if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) { codec_selectable_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100; } if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) { codec_selectable_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000; } if (codec_config_.sample_rate != BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) break; // Compute the common capability Loading Loading @@ -1326,6 +1363,10 @@ bool A2dpCodecConfigSbc::setCodecConfig(const uint8_t* p_peer_codec_info, // Select the bits per sample if there is no user preference do { // Compute the selectable capability codec_selectable_capability_.bits_per_sample = a2dp_sbc_caps.bits_per_sample; if (codec_config_.bits_per_sample != BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE) break; Loading Loading @@ -1396,6 +1437,24 @@ bool A2dpCodecConfigSbc::setCodecConfig(const uint8_t* p_peer_codec_info, // Select the channel mode if there is no user preference do { // Compute the selectable capability if (ch_mode & A2DP_SBC_IE_CH_MD_MONO) { codec_selectable_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO; } if (ch_mode & A2DP_SBC_IE_CH_MD_JOINT) { codec_selectable_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; } if (ch_mode & A2DP_SBC_IE_CH_MD_STEREO) { codec_selectable_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; } if (ch_mode & A2DP_SBC_IE_CH_MD_DUAL) { codec_selectable_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; } if (codec_config_.channel_mode != BTAV_A2DP_CODEC_CHANNEL_MODE_NONE) break; // Compute the common capability Loading Loading @@ -1538,6 +1597,7 @@ fail: // Restore the internal state codec_config_ = saved_codec_config; codec_capability_ = saved_codec_capability; codec_selectable_capability_ = saved_codec_selectable_capability; codec_user_config_ = saved_codec_user_config; codec_audio_config_ = saved_codec_audio_config; memcpy(ota_codec_config_, saved_ota_codec_config, sizeof(ota_codec_config_)); Loading