/* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "A2dpOffloadCodecAac.h" #include "A2dpBits.h" namespace aidl::android::hardware::bluetooth::audio { /** * AAC Local Capabilities */ enum : bool { kEnableObjectTypeMpeg2AacLc = true, kEnableObjectTypeMpeg4AacLc = true, }; enum : bool { kEnableSamplingFrequency44100 = true, kEnableSamplingFrequency48000 = true, kEnableSamplingFrequency88200 = false, kEnableSamplingFrequency96000 = false, }; enum : bool { kEnableChannels1 = true, kEnableChannels2 = true, }; enum : bool { kEnableVbrSupported = true, }; enum : int { kBitdepth = 24, }; /** * AAC Signaling format [A2DP - 4.5] */ // clang-format off constexpr A2dpBits::Range kObjectType ( 0, 6 ); constexpr A2dpBits::Range kDrcEnable ( 7 ); constexpr A2dpBits::Range kSamplingFrequency ( 8, 19 ); constexpr A2dpBits::Range kChannels ( 20, 23 ); constexpr A2dpBits::Range kVbrSupported ( 24 ); constexpr A2dpBits::Range kBitrate ( 25, 47 ); constexpr size_t kCapabilitiesSize = 48/8; // clang-format on enum { kObjectTypeMpeg2AacLc = kObjectType.first, kObjectTypeMpeg4AacLc, kObjectTypeMpeg4AacLtp, kObjectTypeMpeg4AacScalable, kObjectTypeMpeg4AacHeV1, kObjectTypeMpeg4AacHeV2, kObjectTypeMpeg4AacEldV2 }; enum { kSamplingFrequency8000 = kSamplingFrequency.first, kSamplingFrequency11025, kSamplingFrequency12000, kSamplingFrequency16000, kSamplingFrequency22050, kSamplingFrequency24000, kSamplingFrequency32000, kSamplingFrequency44100, kSamplingFrequency48000, kSamplingFrequency64000, kSamplingFrequency88200, kSamplingFrequency96000 }; enum { kChannels1 = kChannels.first, kChannels2, kChannels51, kChannels71 }; /** * AAC Conversion functions */ static AacParameters::ObjectType GetObjectTypeEnum(int object_type) { switch (object_type) { case kObjectTypeMpeg2AacLc: return AacParameters::ObjectType::MPEG2_AAC_LC; case kObjectTypeMpeg4AacLc: default: return AacParameters::ObjectType::MPEG4_AAC_LC; } } static int GetSamplingFrequencyBit(int32_t sampling_frequency) { switch (sampling_frequency) { case 8000: return kSamplingFrequency8000; case 11025: return kSamplingFrequency11025; case 12000: return kSamplingFrequency12000; case 16000: return kSamplingFrequency16000; case 22050: return kSamplingFrequency22050; case 24000: return kSamplingFrequency24000; case 32000: return kSamplingFrequency32000; case 44100: return kSamplingFrequency44100; case 48000: return kSamplingFrequency48000; case 64000: return kSamplingFrequency64000; case 88200: return kSamplingFrequency88200; case 96000: return kSamplingFrequency96000; default: return -1; } } static int32_t GetSamplingFrequencyValue(int sampling_frequency) { switch (sampling_frequency) { case kSamplingFrequency8000: return 8000; case kSamplingFrequency11025: return 11025; case kSamplingFrequency12000: return 12000; case kSamplingFrequency16000: return 16000; case kSamplingFrequency22050: return 22050; case kSamplingFrequency24000: return 24000; case kSamplingFrequency32000: return 32000; case kSamplingFrequency44100: return 44100; case kSamplingFrequency48000: return 48000; case kSamplingFrequency64000: return 64000; case kSamplingFrequency88200: return 88200; case kSamplingFrequency96000: return 96000; default: return 0; } } static int GetChannelsBit(ChannelMode channel_mode) { switch (channel_mode) { case ChannelMode::MONO: return kChannels1; case ChannelMode::STEREO: return kChannels2; default: return -1; } } static ChannelMode GetChannelModeEnum(int channel_mode) { switch (channel_mode) { case kChannels1: return ChannelMode::MONO; case kChannels2: return ChannelMode::STEREO; default: return ChannelMode::UNKNOWN; } } /** * AAC Class implementation */ A2dpOffloadCodecAac::A2dpOffloadCodecAac() : A2dpOffloadCodec(info_), info_({.id = CodecId(CodecId::A2dp::AAC), .name = "AAC"}) { info_.transport.set(); auto& a2dp_info = info_.transport.get(); /* --- Setup Capabilities --- */ a2dp_info.capabilities.resize(kCapabilitiesSize); std::fill(begin(a2dp_info.capabilities), end(a2dp_info.capabilities), 0); auto capabilities = A2dpBits(a2dp_info.capabilities); capabilities.set(kObjectTypeMpeg2AacLc, kEnableObjectTypeMpeg2AacLc); capabilities.set(kObjectTypeMpeg4AacLc, kEnableObjectTypeMpeg4AacLc); capabilities.set(kSamplingFrequency44100, kEnableSamplingFrequency44100); capabilities.set(kSamplingFrequency48000, kEnableSamplingFrequency48000); capabilities.set(kSamplingFrequency88200, kEnableSamplingFrequency88200); capabilities.set(kSamplingFrequency96000, kEnableSamplingFrequency96000); capabilities.set(kChannels1, kEnableChannels1); capabilities.set(kChannels2, kEnableChannels2); capabilities.set(kVbrSupported, kEnableVbrSupported); /* --- Setup Sampling Frequencies --- */ auto& sampling_frequency = a2dp_info.samplingFrequencyHz; for (auto v : {8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000}) if (capabilities.get(GetSamplingFrequencyBit(int32_t(v)))) sampling_frequency.push_back(v); /* --- Setup Channel Modes --- */ auto& channel_modes = a2dp_info.channelMode; for (auto v : {ChannelMode::MONO, ChannelMode::STEREO}) if (capabilities.get(GetChannelsBit(v))) channel_modes.push_back(v); /* --- Setup Bitdepth --- */ a2dp_info.bitdepth.push_back(kBitdepth); } A2dpStatus A2dpOffloadCodecAac::ParseConfiguration( const std::vector& configuration, CodecParameters* codec_parameters, AacParameters* aac_parameters) const { auto& a2dp_info = info.transport.get(); if (configuration.size() != a2dp_info.capabilities.size()) return A2dpStatus::BAD_LENGTH; auto config = A2dpBits(configuration); auto lcaps = A2dpBits(a2dp_info.capabilities); /* --- Check Object Type --- */ int object_type = config.find_active_bit(kObjectType); if (object_type < 0) return A2dpStatus::INVALID_OBJECT_TYPE; if (!lcaps.get(object_type)) return A2dpStatus::NOT_SUPPORTED_OBJECT_TYPE; /* --- Check Sampling Frequency --- */ int sampling_frequency = config.find_active_bit(kSamplingFrequency); if (sampling_frequency < 0) return A2dpStatus::INVALID_SAMPLING_FREQUENCY; if (!lcaps.get(sampling_frequency)) return A2dpStatus::NOT_SUPPORTED_SAMPLING_FREQUENCY; /* --- Check Channels --- */ int channels = config.find_active_bit(kChannels); if (channels < 0) return A2dpStatus::INVALID_CHANNELS; if (!lcaps.get(channels)) return A2dpStatus::NOT_SUPPORTED_CHANNELS; /* --- Check Bitrate --- */ bool vbr = config.get(kVbrSupported); if (vbr && !lcaps.get(kVbrSupported)) return A2dpStatus::NOT_SUPPORTED_VBR; int bitrate = config.get(kBitrate); if (vbr && lcaps.get(kBitrate) && bitrate > lcaps.get(kBitrate)) return A2dpStatus::NOT_SUPPORTED_BIT_RATE; /* --- Return --- */ codec_parameters->channelMode = GetChannelModeEnum(channels); codec_parameters->samplingFrequencyHz = GetSamplingFrequencyValue(sampling_frequency); codec_parameters->bitdepth = kBitdepth; codec_parameters->minBitrate = vbr ? 0 : bitrate; codec_parameters->maxBitrate = bitrate; if (aac_parameters) aac_parameters->object_type = GetObjectTypeEnum(object_type); return A2dpStatus::OK; } bool A2dpOffloadCodecAac::BuildConfiguration( const std::vector& remote_capabilities, const std::optional& hint, std::vector* configuration) const { auto& a2dp_info = info_.transport.get(); if (remote_capabilities.size() != a2dp_info.capabilities.size()) return false; auto lcaps = A2dpBits(a2dp_info.capabilities); auto rcaps = A2dpBits(remote_capabilities); configuration->resize(a2dp_info.capabilities.size()); std::fill(begin(*configuration), end(*configuration), 0); auto config = A2dpBits(*configuration); /* --- Select Object Type --- */ if (lcaps.get(kObjectTypeMpeg2AacLc) && rcaps.get(kObjectTypeMpeg2AacLc)) config.set(kObjectTypeMpeg2AacLc); else if (lcaps.get(kObjectTypeMpeg4AacLc) && rcaps.get(kObjectTypeMpeg4AacLc)) config.set(kObjectTypeMpeg4AacLc); else return false; /* --- Select Sampling Frequency --- */ auto sf_hint = hint ? GetSamplingFrequencyBit(hint->samplingFrequencyHz) : -1; if (sf_hint >= 0 && lcaps.get(sf_hint) && rcaps.get(sf_hint)) config.set(sf_hint); else if (lcaps.get(kSamplingFrequency96000) && rcaps.get(kSamplingFrequency96000)) config.set(kSamplingFrequency96000); else if (lcaps.get(kSamplingFrequency88200) && rcaps.get(kSamplingFrequency88200)) config.set(kSamplingFrequency88200); else if (lcaps.get(kSamplingFrequency48000) && rcaps.get(kSamplingFrequency48000)) config.set(kSamplingFrequency48000); else if (lcaps.get(kSamplingFrequency44100) && rcaps.get(kSamplingFrequency44100)) config.set(kSamplingFrequency44100); else return false; /* --- Select Channels --- */ auto ch_hint = hint ? GetChannelsBit(hint->channelMode) : -1; if (ch_hint >= 0 && lcaps.get(ch_hint) && rcaps.get(ch_hint)) config.set(ch_hint); else if (lcaps.get(kChannels2) && rcaps.get(kChannels2)) config.set(kChannels2); else if (lcaps.get(kChannels1) && rcaps.get(kChannels1)) config.set(kChannels1); else return false; /* --- Select Bitrate --- */ if (!hint || hint->minBitrate == 0) config.set(kVbrSupported, lcaps.get(kVbrSupported) && rcaps.get(kVbrSupported)); int32_t bitrate = lcaps.get(kBitrate); if (hint && hint->maxBitrate > 0 && bitrate) bitrate = std::min(hint->maxBitrate, bitrate); else if (hint && hint->maxBitrate > 0) bitrate = hint->maxBitrate; config.set(kBitrate, bitrate); return true; } } // namespace aidl::android::hardware::bluetooth::audio