Loading system/bta/le_audio/broadcaster/broadcaster.cc +22 −3 Original line number Diff line number Diff line Loading @@ -421,9 +421,15 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { LeAudioContextType::MEDIA | LeAudioContextType::CONVERSATIONAL; } /* Subgroups with different audio qualities is not being supported now, * if any subgroup preferred to use standard audio config, choose * the standard audio config instead */ uint8_t BIG_audio_quality = bluetooth::le_audio::QUALITY_HIGH; for (const uint8_t quality : subgroup_quality) { if (quality == bluetooth::le_audio::QUALITY_STANDARD) { public_features |= bluetooth::le_audio::kLeAudioQualityStandard; BIG_audio_quality = bluetooth::le_audio::QUALITY_STANDARD; } else if (quality == bluetooth::le_audio::QUALITY_HIGH) { public_features |= bluetooth::le_audio::kLeAudioQualityHigh; } Loading Loading @@ -481,13 +487,15 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { subgroup_ltvs.push_back(ltv); } auto codec_qos_pair = [](AudioContexts context_type) auto codec_qos_pair = [](AudioContexts context_type, uint8_t BIG_audio_quality) -> std::optional< std::pair<const BroadcastCodecWrapper, const BroadcastQosConfig>> { if (CodecManager::GetInstance()->GetCodecLocation() == CodecLocation::ADSP) { auto offload_config = CodecManager::GetInstance()->GetBroadcastOffloadConfig(); CodecManager::GetInstance()->GetBroadcastOffloadConfig( BIG_audio_quality); if (offload_config == nullptr) { return std::nullopt; } Loading @@ -509,13 +517,24 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { } else { return le_audio::broadcaster::getStreamConfigForContext(context_type); } }(context_type); }(context_type, BIG_audio_quality); if (!codec_qos_pair) { LOG_ERROR("No valid broadcast offload config"); callbacks_->OnBroadcastCreated(bluetooth::le_audio::kBroadcastIdInvalid, false); return; } if (BIG_audio_quality == bluetooth::le_audio::QUALITY_HIGH && codec_qos_pair->first.GetSampleRate() != 48000) { LOG_WARN( "Preferred quality isn't supported. Fallback to standard audio " "quality"); public_features &= (0xFFFF & ~bluetooth::le_audio::kLeAudioQualityHigh); public_features |= bluetooth::le_audio::kLeAudioQualityStandard; } BroadcastStateMachineConfig msg = { .is_public = is_public, .broadcast_id = broadcast_id, Loading system/bta/le_audio/codec_manager.cc +75 −12 Original line number Diff line number Diff line Loading @@ -235,32 +235,93 @@ struct codec_manager_impl { } } const broadcast_offload_config* GetBroadcastOffloadConfig() { const broadcast_offload_config* GetBroadcastOffloadConfig( uint8_t preferred_quality) { if (supported_broadcast_config.empty()) { LOG_ERROR("There is no valid broadcast offload config"); return nullptr; } /* Broadcast audio config selection based on source broadcast capability * * If the preferred_quality is HIGH, the configs ranking is * 48_4 > 48_2 > 24_2(sink mandatory) > 16_2(source & sink mandatory) * * If the preferred_quality is STANDARD, the configs ranking is * 24_2(sink mandatory) > 16_2(source & sink mandatory) */ broadcast_target_config = -1; for (int i = 0; i < (int)supported_broadcast_config.size(); i++) { if (supported_broadcast_config[i].sampling_rate == 48000u) { if (preferred_quality == bluetooth::le_audio::QUALITY_STANDARD) continue; if (supported_broadcast_config[i].octets_per_frame == 120) { // 48_4 broadcast_target_config = i; break; } else if (supported_broadcast_config[i].octets_per_frame == 100) { // 48_2 broadcast_target_config = i; } } else if (supported_broadcast_config[i].sampling_rate == 24000u && supported_broadcast_config[i].octets_per_frame == 60) { // 24_2 if (preferred_quality == bluetooth::le_audio::QUALITY_STANDARD) { broadcast_target_config = i; break; } else if (broadcast_target_config == -1) { // preferred_quality is QUALITY_HIGH, and // haven't get the 48_4 or 48_2 broadcast_target_config = i; } } else if (supported_broadcast_config[i].sampling_rate == 16000u && supported_broadcast_config[i].octets_per_frame == 40) { // 16_2 if (preferred_quality == bluetooth::le_audio::QUALITY_STANDARD) { broadcast_target_config = i; } else if (broadcast_target_config == -1 || supported_broadcast_config[broadcast_target_config] .sampling_rate != 24000u) { // preferred_quality is QUALITY_HIGH, and // haven't get the 48_4 or 48_2 or 24_2 broadcast_target_config = i; } } } if (broadcast_target_config == -1) { LOG_ERROR( "There is no valid broadcast offload config with preferred_quality"); return nullptr; } LOG_INFO( "stream_map.size(): %zu, sampling_rate: %d, frame_duration(us): %d, " "octets_per_frame: %d, blocks_per_sdu %d, " "retransmission_number: %d, max_transport_latency: %d", supported_broadcast_config[0].stream_map.size(), supported_broadcast_config[0].sampling_rate, supported_broadcast_config[0].frame_duration, supported_broadcast_config[0].octets_per_frame, (int)supported_broadcast_config[0].blocks_per_sdu, (int)supported_broadcast_config[0].retransmission_number, supported_broadcast_config[0].max_transport_latency); supported_broadcast_config[broadcast_target_config].stream_map.size(), supported_broadcast_config[broadcast_target_config].sampling_rate, supported_broadcast_config[broadcast_target_config].frame_duration, supported_broadcast_config[broadcast_target_config].octets_per_frame, (int)supported_broadcast_config[broadcast_target_config].blocks_per_sdu, (int)supported_broadcast_config[broadcast_target_config] .retransmission_number, supported_broadcast_config[broadcast_target_config] .max_transport_latency); return &supported_broadcast_config[0]; return &supported_broadcast_config[broadcast_target_config]; } void UpdateBroadcastConnHandle( const std::vector<uint16_t>& conn_handle, std::function<void(const ::le_audio::broadcast_offload_config& config)> update_receiver) { auto broadcast_config = supported_broadcast_config[0]; if (broadcast_target_config == -1 || broadcast_target_config >= (int)supported_broadcast_config.size()) { LOG_ERROR("There is no valid broadcast offload config"); return; } auto broadcast_config = supported_broadcast_config[broadcast_target_config]; LOG_ASSERT(conn_handle.size() == broadcast_config.stream_map.size()); if (broadcast_config.stream_map.size() == Loading Loading @@ -639,6 +700,7 @@ struct codec_manager_impl { std::vector<btle_audio_codec_config_t> codec_input_capa = {}; std::vector<btle_audio_codec_config_t> codec_output_capa = {}; int broadcast_target_config = -1; }; // namespace le_audio struct CodecManager::impl { Loading Loading @@ -728,9 +790,10 @@ const AudioSetConfigurations* CodecManager::GetOffloadCodecConfig( } const ::le_audio::broadcast_offload_config* CodecManager::GetBroadcastOffloadConfig() { CodecManager::GetBroadcastOffloadConfig(uint8_t preferred_quality) { if (pimpl_->IsRunning()) { return pimpl_->codec_manager_impl_->GetBroadcastOffloadConfig(); return pimpl_->codec_manager_impl_->GetBroadcastOffloadConfig( preferred_quality); } return nullptr; Loading system/bta/le_audio/codec_manager.h +2 −2 Original line number Diff line number Diff line Loading @@ -78,8 +78,8 @@ class CodecManager { update_receiver); virtual const ::le_audio::set_configurations::AudioSetConfigurations* GetOffloadCodecConfig(::le_audio::types::LeAudioContextType ctx_type); virtual const ::le_audio::broadcast_offload_config* GetBroadcastOffloadConfig(); virtual const ::le_audio::broadcast_offload_config* GetBroadcastOffloadConfig( uint8_t preferred_quality); virtual void UpdateBroadcastConnHandle( const std::vector<uint16_t>& conn_handle, std::function<void(const ::le_audio::broadcast_offload_config& config)> Loading system/bta/le_audio/mock_codec_manager.cc +2 −2 Original line number Diff line number Diff line Loading @@ -63,9 +63,9 @@ CodecManager::GetOffloadCodecConfig(types::LeAudioContextType ctx_type) { } const ::le_audio::broadcast_offload_config* CodecManager::GetBroadcastOffloadConfig() { CodecManager::GetBroadcastOffloadConfig(uint8_t preferred_quality) { if (!pimpl_) return nullptr; return pimpl_->GetBroadcastOffloadConfig(); return pimpl_->GetBroadcastOffloadConfig(preferred_quality); } std::vector<bluetooth::le_audio::btle_audio_codec_config_t> Loading system/bta/le_audio/mock_codec_manager.h +1 −1 Original line number Diff line number Diff line Loading @@ -43,7 +43,7 @@ class MockCodecManager { GetOffloadCodecConfig, (le_audio::types::LeAudioContextType ctx_type), (const)); MOCK_METHOD((le_audio::broadcast_offload_config*), GetBroadcastOffloadConfig, (), (const)); (uint8_t preferred_quality), (const)); MOCK_METHOD((std::vector<bluetooth::le_audio::btle_audio_codec_config_t>), GetLocalAudioOutputCodecCapa, ()); MOCK_METHOD((std::vector<bluetooth::le_audio::btle_audio_codec_config_t>), Loading Loading
system/bta/le_audio/broadcaster/broadcaster.cc +22 −3 Original line number Diff line number Diff line Loading @@ -421,9 +421,15 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { LeAudioContextType::MEDIA | LeAudioContextType::CONVERSATIONAL; } /* Subgroups with different audio qualities is not being supported now, * if any subgroup preferred to use standard audio config, choose * the standard audio config instead */ uint8_t BIG_audio_quality = bluetooth::le_audio::QUALITY_HIGH; for (const uint8_t quality : subgroup_quality) { if (quality == bluetooth::le_audio::QUALITY_STANDARD) { public_features |= bluetooth::le_audio::kLeAudioQualityStandard; BIG_audio_quality = bluetooth::le_audio::QUALITY_STANDARD; } else if (quality == bluetooth::le_audio::QUALITY_HIGH) { public_features |= bluetooth::le_audio::kLeAudioQualityHigh; } Loading Loading @@ -481,13 +487,15 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { subgroup_ltvs.push_back(ltv); } auto codec_qos_pair = [](AudioContexts context_type) auto codec_qos_pair = [](AudioContexts context_type, uint8_t BIG_audio_quality) -> std::optional< std::pair<const BroadcastCodecWrapper, const BroadcastQosConfig>> { if (CodecManager::GetInstance()->GetCodecLocation() == CodecLocation::ADSP) { auto offload_config = CodecManager::GetInstance()->GetBroadcastOffloadConfig(); CodecManager::GetInstance()->GetBroadcastOffloadConfig( BIG_audio_quality); if (offload_config == nullptr) { return std::nullopt; } Loading @@ -509,13 +517,24 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { } else { return le_audio::broadcaster::getStreamConfigForContext(context_type); } }(context_type); }(context_type, BIG_audio_quality); if (!codec_qos_pair) { LOG_ERROR("No valid broadcast offload config"); callbacks_->OnBroadcastCreated(bluetooth::le_audio::kBroadcastIdInvalid, false); return; } if (BIG_audio_quality == bluetooth::le_audio::QUALITY_HIGH && codec_qos_pair->first.GetSampleRate() != 48000) { LOG_WARN( "Preferred quality isn't supported. Fallback to standard audio " "quality"); public_features &= (0xFFFF & ~bluetooth::le_audio::kLeAudioQualityHigh); public_features |= bluetooth::le_audio::kLeAudioQualityStandard; } BroadcastStateMachineConfig msg = { .is_public = is_public, .broadcast_id = broadcast_id, Loading
system/bta/le_audio/codec_manager.cc +75 −12 Original line number Diff line number Diff line Loading @@ -235,32 +235,93 @@ struct codec_manager_impl { } } const broadcast_offload_config* GetBroadcastOffloadConfig() { const broadcast_offload_config* GetBroadcastOffloadConfig( uint8_t preferred_quality) { if (supported_broadcast_config.empty()) { LOG_ERROR("There is no valid broadcast offload config"); return nullptr; } /* Broadcast audio config selection based on source broadcast capability * * If the preferred_quality is HIGH, the configs ranking is * 48_4 > 48_2 > 24_2(sink mandatory) > 16_2(source & sink mandatory) * * If the preferred_quality is STANDARD, the configs ranking is * 24_2(sink mandatory) > 16_2(source & sink mandatory) */ broadcast_target_config = -1; for (int i = 0; i < (int)supported_broadcast_config.size(); i++) { if (supported_broadcast_config[i].sampling_rate == 48000u) { if (preferred_quality == bluetooth::le_audio::QUALITY_STANDARD) continue; if (supported_broadcast_config[i].octets_per_frame == 120) { // 48_4 broadcast_target_config = i; break; } else if (supported_broadcast_config[i].octets_per_frame == 100) { // 48_2 broadcast_target_config = i; } } else if (supported_broadcast_config[i].sampling_rate == 24000u && supported_broadcast_config[i].octets_per_frame == 60) { // 24_2 if (preferred_quality == bluetooth::le_audio::QUALITY_STANDARD) { broadcast_target_config = i; break; } else if (broadcast_target_config == -1) { // preferred_quality is QUALITY_HIGH, and // haven't get the 48_4 or 48_2 broadcast_target_config = i; } } else if (supported_broadcast_config[i].sampling_rate == 16000u && supported_broadcast_config[i].octets_per_frame == 40) { // 16_2 if (preferred_quality == bluetooth::le_audio::QUALITY_STANDARD) { broadcast_target_config = i; } else if (broadcast_target_config == -1 || supported_broadcast_config[broadcast_target_config] .sampling_rate != 24000u) { // preferred_quality is QUALITY_HIGH, and // haven't get the 48_4 or 48_2 or 24_2 broadcast_target_config = i; } } } if (broadcast_target_config == -1) { LOG_ERROR( "There is no valid broadcast offload config with preferred_quality"); return nullptr; } LOG_INFO( "stream_map.size(): %zu, sampling_rate: %d, frame_duration(us): %d, " "octets_per_frame: %d, blocks_per_sdu %d, " "retransmission_number: %d, max_transport_latency: %d", supported_broadcast_config[0].stream_map.size(), supported_broadcast_config[0].sampling_rate, supported_broadcast_config[0].frame_duration, supported_broadcast_config[0].octets_per_frame, (int)supported_broadcast_config[0].blocks_per_sdu, (int)supported_broadcast_config[0].retransmission_number, supported_broadcast_config[0].max_transport_latency); supported_broadcast_config[broadcast_target_config].stream_map.size(), supported_broadcast_config[broadcast_target_config].sampling_rate, supported_broadcast_config[broadcast_target_config].frame_duration, supported_broadcast_config[broadcast_target_config].octets_per_frame, (int)supported_broadcast_config[broadcast_target_config].blocks_per_sdu, (int)supported_broadcast_config[broadcast_target_config] .retransmission_number, supported_broadcast_config[broadcast_target_config] .max_transport_latency); return &supported_broadcast_config[0]; return &supported_broadcast_config[broadcast_target_config]; } void UpdateBroadcastConnHandle( const std::vector<uint16_t>& conn_handle, std::function<void(const ::le_audio::broadcast_offload_config& config)> update_receiver) { auto broadcast_config = supported_broadcast_config[0]; if (broadcast_target_config == -1 || broadcast_target_config >= (int)supported_broadcast_config.size()) { LOG_ERROR("There is no valid broadcast offload config"); return; } auto broadcast_config = supported_broadcast_config[broadcast_target_config]; LOG_ASSERT(conn_handle.size() == broadcast_config.stream_map.size()); if (broadcast_config.stream_map.size() == Loading Loading @@ -639,6 +700,7 @@ struct codec_manager_impl { std::vector<btle_audio_codec_config_t> codec_input_capa = {}; std::vector<btle_audio_codec_config_t> codec_output_capa = {}; int broadcast_target_config = -1; }; // namespace le_audio struct CodecManager::impl { Loading Loading @@ -728,9 +790,10 @@ const AudioSetConfigurations* CodecManager::GetOffloadCodecConfig( } const ::le_audio::broadcast_offload_config* CodecManager::GetBroadcastOffloadConfig() { CodecManager::GetBroadcastOffloadConfig(uint8_t preferred_quality) { if (pimpl_->IsRunning()) { return pimpl_->codec_manager_impl_->GetBroadcastOffloadConfig(); return pimpl_->codec_manager_impl_->GetBroadcastOffloadConfig( preferred_quality); } return nullptr; Loading
system/bta/le_audio/codec_manager.h +2 −2 Original line number Diff line number Diff line Loading @@ -78,8 +78,8 @@ class CodecManager { update_receiver); virtual const ::le_audio::set_configurations::AudioSetConfigurations* GetOffloadCodecConfig(::le_audio::types::LeAudioContextType ctx_type); virtual const ::le_audio::broadcast_offload_config* GetBroadcastOffloadConfig(); virtual const ::le_audio::broadcast_offload_config* GetBroadcastOffloadConfig( uint8_t preferred_quality); virtual void UpdateBroadcastConnHandle( const std::vector<uint16_t>& conn_handle, std::function<void(const ::le_audio::broadcast_offload_config& config)> Loading
system/bta/le_audio/mock_codec_manager.cc +2 −2 Original line number Diff line number Diff line Loading @@ -63,9 +63,9 @@ CodecManager::GetOffloadCodecConfig(types::LeAudioContextType ctx_type) { } const ::le_audio::broadcast_offload_config* CodecManager::GetBroadcastOffloadConfig() { CodecManager::GetBroadcastOffloadConfig(uint8_t preferred_quality) { if (!pimpl_) return nullptr; return pimpl_->GetBroadcastOffloadConfig(); return pimpl_->GetBroadcastOffloadConfig(preferred_quality); } std::vector<bluetooth::le_audio::btle_audio_codec_config_t> Loading
system/bta/le_audio/mock_codec_manager.h +1 −1 Original line number Diff line number Diff line Loading @@ -43,7 +43,7 @@ class MockCodecManager { GetOffloadCodecConfig, (le_audio::types::LeAudioContextType ctx_type), (const)); MOCK_METHOD((le_audio::broadcast_offload_config*), GetBroadcastOffloadConfig, (), (const)); (uint8_t preferred_quality), (const)); MOCK_METHOD((std::vector<bluetooth::le_audio::btle_audio_codec_config_t>), GetLocalAudioOutputCodecCapa, ()); MOCK_METHOD((std::vector<bluetooth::le_audio::btle_audio_codec_config_t>), Loading