1*4d7e907cSAndroid Build Coastguard Worker /*
2*4d7e907cSAndroid Build Coastguard Worker * Copyright (C) 2023 The Android Open Source Project
3*4d7e907cSAndroid Build Coastguard Worker *
4*4d7e907cSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*4d7e907cSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*4d7e907cSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*4d7e907cSAndroid Build Coastguard Worker *
8*4d7e907cSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*4d7e907cSAndroid Build Coastguard Worker *
10*4d7e907cSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*4d7e907cSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*4d7e907cSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4d7e907cSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*4d7e907cSAndroid Build Coastguard Worker * limitations under the License.
15*4d7e907cSAndroid Build Coastguard Worker */
16*4d7e907cSAndroid Build Coastguard Worker
17*4d7e907cSAndroid Build Coastguard Worker #include "A2dpOffloadCodecAac.h"
18*4d7e907cSAndroid Build Coastguard Worker
19*4d7e907cSAndroid Build Coastguard Worker #include "A2dpBits.h"
20*4d7e907cSAndroid Build Coastguard Worker
21*4d7e907cSAndroid Build Coastguard Worker namespace aidl::android::hardware::bluetooth::audio {
22*4d7e907cSAndroid Build Coastguard Worker
23*4d7e907cSAndroid Build Coastguard Worker /**
24*4d7e907cSAndroid Build Coastguard Worker * AAC Local Capabilities
25*4d7e907cSAndroid Build Coastguard Worker */
26*4d7e907cSAndroid Build Coastguard Worker
27*4d7e907cSAndroid Build Coastguard Worker enum : bool {
28*4d7e907cSAndroid Build Coastguard Worker kEnableObjectTypeMpeg2AacLc = true,
29*4d7e907cSAndroid Build Coastguard Worker kEnableObjectTypeMpeg4AacLc = true,
30*4d7e907cSAndroid Build Coastguard Worker };
31*4d7e907cSAndroid Build Coastguard Worker
32*4d7e907cSAndroid Build Coastguard Worker enum : bool {
33*4d7e907cSAndroid Build Coastguard Worker kEnableSamplingFrequency44100 = true,
34*4d7e907cSAndroid Build Coastguard Worker kEnableSamplingFrequency48000 = true,
35*4d7e907cSAndroid Build Coastguard Worker kEnableSamplingFrequency88200 = false,
36*4d7e907cSAndroid Build Coastguard Worker kEnableSamplingFrequency96000 = false,
37*4d7e907cSAndroid Build Coastguard Worker };
38*4d7e907cSAndroid Build Coastguard Worker
39*4d7e907cSAndroid Build Coastguard Worker enum : bool {
40*4d7e907cSAndroid Build Coastguard Worker kEnableChannels1 = true,
41*4d7e907cSAndroid Build Coastguard Worker kEnableChannels2 = true,
42*4d7e907cSAndroid Build Coastguard Worker };
43*4d7e907cSAndroid Build Coastguard Worker
44*4d7e907cSAndroid Build Coastguard Worker enum : bool {
45*4d7e907cSAndroid Build Coastguard Worker kEnableVbrSupported = true,
46*4d7e907cSAndroid Build Coastguard Worker };
47*4d7e907cSAndroid Build Coastguard Worker
48*4d7e907cSAndroid Build Coastguard Worker enum : int {
49*4d7e907cSAndroid Build Coastguard Worker kBitdepth = 24,
50*4d7e907cSAndroid Build Coastguard Worker };
51*4d7e907cSAndroid Build Coastguard Worker
52*4d7e907cSAndroid Build Coastguard Worker /**
53*4d7e907cSAndroid Build Coastguard Worker * AAC Signaling format [A2DP - 4.5]
54*4d7e907cSAndroid Build Coastguard Worker */
55*4d7e907cSAndroid Build Coastguard Worker
56*4d7e907cSAndroid Build Coastguard Worker // clang-format off
57*4d7e907cSAndroid Build Coastguard Worker
58*4d7e907cSAndroid Build Coastguard Worker constexpr A2dpBits::Range kObjectType ( 0, 6 );
59*4d7e907cSAndroid Build Coastguard Worker constexpr A2dpBits::Range kDrcEnable ( 7 );
60*4d7e907cSAndroid Build Coastguard Worker constexpr A2dpBits::Range kSamplingFrequency ( 8, 19 );
61*4d7e907cSAndroid Build Coastguard Worker constexpr A2dpBits::Range kChannels ( 20, 23 );
62*4d7e907cSAndroid Build Coastguard Worker constexpr A2dpBits::Range kVbrSupported ( 24 );
63*4d7e907cSAndroid Build Coastguard Worker constexpr A2dpBits::Range kBitrate ( 25, 47 );
64*4d7e907cSAndroid Build Coastguard Worker constexpr size_t kCapabilitiesSize = 48/8;
65*4d7e907cSAndroid Build Coastguard Worker
66*4d7e907cSAndroid Build Coastguard Worker // clang-format on
67*4d7e907cSAndroid Build Coastguard Worker
68*4d7e907cSAndroid Build Coastguard Worker enum {
69*4d7e907cSAndroid Build Coastguard Worker kObjectTypeMpeg2AacLc = kObjectType.first,
70*4d7e907cSAndroid Build Coastguard Worker kObjectTypeMpeg4AacLc,
71*4d7e907cSAndroid Build Coastguard Worker kObjectTypeMpeg4AacLtp,
72*4d7e907cSAndroid Build Coastguard Worker kObjectTypeMpeg4AacScalable,
73*4d7e907cSAndroid Build Coastguard Worker kObjectTypeMpeg4AacHeV1,
74*4d7e907cSAndroid Build Coastguard Worker kObjectTypeMpeg4AacHeV2,
75*4d7e907cSAndroid Build Coastguard Worker kObjectTypeMpeg4AacEldV2
76*4d7e907cSAndroid Build Coastguard Worker };
77*4d7e907cSAndroid Build Coastguard Worker
78*4d7e907cSAndroid Build Coastguard Worker enum {
79*4d7e907cSAndroid Build Coastguard Worker kSamplingFrequency8000 = kSamplingFrequency.first,
80*4d7e907cSAndroid Build Coastguard Worker kSamplingFrequency11025,
81*4d7e907cSAndroid Build Coastguard Worker kSamplingFrequency12000,
82*4d7e907cSAndroid Build Coastguard Worker kSamplingFrequency16000,
83*4d7e907cSAndroid Build Coastguard Worker kSamplingFrequency22050,
84*4d7e907cSAndroid Build Coastguard Worker kSamplingFrequency24000,
85*4d7e907cSAndroid Build Coastguard Worker kSamplingFrequency32000,
86*4d7e907cSAndroid Build Coastguard Worker kSamplingFrequency44100,
87*4d7e907cSAndroid Build Coastguard Worker kSamplingFrequency48000,
88*4d7e907cSAndroid Build Coastguard Worker kSamplingFrequency64000,
89*4d7e907cSAndroid Build Coastguard Worker kSamplingFrequency88200,
90*4d7e907cSAndroid Build Coastguard Worker kSamplingFrequency96000
91*4d7e907cSAndroid Build Coastguard Worker };
92*4d7e907cSAndroid Build Coastguard Worker
93*4d7e907cSAndroid Build Coastguard Worker enum { kChannels1 = kChannels.first, kChannels2, kChannels51, kChannels71 };
94*4d7e907cSAndroid Build Coastguard Worker
95*4d7e907cSAndroid Build Coastguard Worker /**
96*4d7e907cSAndroid Build Coastguard Worker * AAC Conversion functions
97*4d7e907cSAndroid Build Coastguard Worker */
98*4d7e907cSAndroid Build Coastguard Worker
GetObjectTypeEnum(int object_type)99*4d7e907cSAndroid Build Coastguard Worker static AacParameters::ObjectType GetObjectTypeEnum(int object_type) {
100*4d7e907cSAndroid Build Coastguard Worker switch (object_type) {
101*4d7e907cSAndroid Build Coastguard Worker case kObjectTypeMpeg2AacLc:
102*4d7e907cSAndroid Build Coastguard Worker return AacParameters::ObjectType::MPEG2_AAC_LC;
103*4d7e907cSAndroid Build Coastguard Worker case kObjectTypeMpeg4AacLc:
104*4d7e907cSAndroid Build Coastguard Worker default:
105*4d7e907cSAndroid Build Coastguard Worker return AacParameters::ObjectType::MPEG4_AAC_LC;
106*4d7e907cSAndroid Build Coastguard Worker }
107*4d7e907cSAndroid Build Coastguard Worker }
108*4d7e907cSAndroid Build Coastguard Worker
GetSamplingFrequencyBit(int32_t sampling_frequency)109*4d7e907cSAndroid Build Coastguard Worker static int GetSamplingFrequencyBit(int32_t sampling_frequency) {
110*4d7e907cSAndroid Build Coastguard Worker switch (sampling_frequency) {
111*4d7e907cSAndroid Build Coastguard Worker case 8000:
112*4d7e907cSAndroid Build Coastguard Worker return kSamplingFrequency8000;
113*4d7e907cSAndroid Build Coastguard Worker case 11025:
114*4d7e907cSAndroid Build Coastguard Worker return kSamplingFrequency11025;
115*4d7e907cSAndroid Build Coastguard Worker case 12000:
116*4d7e907cSAndroid Build Coastguard Worker return kSamplingFrequency12000;
117*4d7e907cSAndroid Build Coastguard Worker case 16000:
118*4d7e907cSAndroid Build Coastguard Worker return kSamplingFrequency16000;
119*4d7e907cSAndroid Build Coastguard Worker case 22050:
120*4d7e907cSAndroid Build Coastguard Worker return kSamplingFrequency22050;
121*4d7e907cSAndroid Build Coastguard Worker case 24000:
122*4d7e907cSAndroid Build Coastguard Worker return kSamplingFrequency24000;
123*4d7e907cSAndroid Build Coastguard Worker case 32000:
124*4d7e907cSAndroid Build Coastguard Worker return kSamplingFrequency32000;
125*4d7e907cSAndroid Build Coastguard Worker case 44100:
126*4d7e907cSAndroid Build Coastguard Worker return kSamplingFrequency44100;
127*4d7e907cSAndroid Build Coastguard Worker case 48000:
128*4d7e907cSAndroid Build Coastguard Worker return kSamplingFrequency48000;
129*4d7e907cSAndroid Build Coastguard Worker case 64000:
130*4d7e907cSAndroid Build Coastguard Worker return kSamplingFrequency64000;
131*4d7e907cSAndroid Build Coastguard Worker case 88200:
132*4d7e907cSAndroid Build Coastguard Worker return kSamplingFrequency88200;
133*4d7e907cSAndroid Build Coastguard Worker case 96000:
134*4d7e907cSAndroid Build Coastguard Worker return kSamplingFrequency96000;
135*4d7e907cSAndroid Build Coastguard Worker default:
136*4d7e907cSAndroid Build Coastguard Worker return -1;
137*4d7e907cSAndroid Build Coastguard Worker }
138*4d7e907cSAndroid Build Coastguard Worker }
139*4d7e907cSAndroid Build Coastguard Worker
GetSamplingFrequencyValue(int sampling_frequency)140*4d7e907cSAndroid Build Coastguard Worker static int32_t GetSamplingFrequencyValue(int sampling_frequency) {
141*4d7e907cSAndroid Build Coastguard Worker switch (sampling_frequency) {
142*4d7e907cSAndroid Build Coastguard Worker case kSamplingFrequency8000:
143*4d7e907cSAndroid Build Coastguard Worker return 8000;
144*4d7e907cSAndroid Build Coastguard Worker case kSamplingFrequency11025:
145*4d7e907cSAndroid Build Coastguard Worker return 11025;
146*4d7e907cSAndroid Build Coastguard Worker case kSamplingFrequency12000:
147*4d7e907cSAndroid Build Coastguard Worker return 12000;
148*4d7e907cSAndroid Build Coastguard Worker case kSamplingFrequency16000:
149*4d7e907cSAndroid Build Coastguard Worker return 16000;
150*4d7e907cSAndroid Build Coastguard Worker case kSamplingFrequency22050:
151*4d7e907cSAndroid Build Coastguard Worker return 22050;
152*4d7e907cSAndroid Build Coastguard Worker case kSamplingFrequency24000:
153*4d7e907cSAndroid Build Coastguard Worker return 24000;
154*4d7e907cSAndroid Build Coastguard Worker case kSamplingFrequency32000:
155*4d7e907cSAndroid Build Coastguard Worker return 32000;
156*4d7e907cSAndroid Build Coastguard Worker case kSamplingFrequency44100:
157*4d7e907cSAndroid Build Coastguard Worker return 44100;
158*4d7e907cSAndroid Build Coastguard Worker case kSamplingFrequency48000:
159*4d7e907cSAndroid Build Coastguard Worker return 48000;
160*4d7e907cSAndroid Build Coastguard Worker case kSamplingFrequency64000:
161*4d7e907cSAndroid Build Coastguard Worker return 64000;
162*4d7e907cSAndroid Build Coastguard Worker case kSamplingFrequency88200:
163*4d7e907cSAndroid Build Coastguard Worker return 88200;
164*4d7e907cSAndroid Build Coastguard Worker case kSamplingFrequency96000:
165*4d7e907cSAndroid Build Coastguard Worker return 96000;
166*4d7e907cSAndroid Build Coastguard Worker default:
167*4d7e907cSAndroid Build Coastguard Worker return 0;
168*4d7e907cSAndroid Build Coastguard Worker }
169*4d7e907cSAndroid Build Coastguard Worker }
170*4d7e907cSAndroid Build Coastguard Worker
GetChannelsBit(ChannelMode channel_mode)171*4d7e907cSAndroid Build Coastguard Worker static int GetChannelsBit(ChannelMode channel_mode) {
172*4d7e907cSAndroid Build Coastguard Worker switch (channel_mode) {
173*4d7e907cSAndroid Build Coastguard Worker case ChannelMode::MONO:
174*4d7e907cSAndroid Build Coastguard Worker return kChannels1;
175*4d7e907cSAndroid Build Coastguard Worker case ChannelMode::STEREO:
176*4d7e907cSAndroid Build Coastguard Worker return kChannels2;
177*4d7e907cSAndroid Build Coastguard Worker default:
178*4d7e907cSAndroid Build Coastguard Worker return -1;
179*4d7e907cSAndroid Build Coastguard Worker }
180*4d7e907cSAndroid Build Coastguard Worker }
181*4d7e907cSAndroid Build Coastguard Worker
GetChannelModeEnum(int channel_mode)182*4d7e907cSAndroid Build Coastguard Worker static ChannelMode GetChannelModeEnum(int channel_mode) {
183*4d7e907cSAndroid Build Coastguard Worker switch (channel_mode) {
184*4d7e907cSAndroid Build Coastguard Worker case kChannels1:
185*4d7e907cSAndroid Build Coastguard Worker return ChannelMode::MONO;
186*4d7e907cSAndroid Build Coastguard Worker case kChannels2:
187*4d7e907cSAndroid Build Coastguard Worker return ChannelMode::STEREO;
188*4d7e907cSAndroid Build Coastguard Worker default:
189*4d7e907cSAndroid Build Coastguard Worker return ChannelMode::UNKNOWN;
190*4d7e907cSAndroid Build Coastguard Worker }
191*4d7e907cSAndroid Build Coastguard Worker }
192*4d7e907cSAndroid Build Coastguard Worker
193*4d7e907cSAndroid Build Coastguard Worker /**
194*4d7e907cSAndroid Build Coastguard Worker * AAC Class implementation
195*4d7e907cSAndroid Build Coastguard Worker */
196*4d7e907cSAndroid Build Coastguard Worker
A2dpOffloadCodecAac()197*4d7e907cSAndroid Build Coastguard Worker A2dpOffloadCodecAac::A2dpOffloadCodecAac()
198*4d7e907cSAndroid Build Coastguard Worker : A2dpOffloadCodec(info_),
199*4d7e907cSAndroid Build Coastguard Worker info_({.id = CodecId(CodecId::A2dp::AAC), .name = "AAC"}) {
200*4d7e907cSAndroid Build Coastguard Worker info_.transport.set<CodecInfo::Transport::Tag::a2dp>();
201*4d7e907cSAndroid Build Coastguard Worker auto& a2dp_info = info_.transport.get<CodecInfo::Transport::Tag::a2dp>();
202*4d7e907cSAndroid Build Coastguard Worker
203*4d7e907cSAndroid Build Coastguard Worker /* --- Setup Capabilities --- */
204*4d7e907cSAndroid Build Coastguard Worker
205*4d7e907cSAndroid Build Coastguard Worker a2dp_info.capabilities.resize(kCapabilitiesSize);
206*4d7e907cSAndroid Build Coastguard Worker std::fill(begin(a2dp_info.capabilities), end(a2dp_info.capabilities), 0);
207*4d7e907cSAndroid Build Coastguard Worker
208*4d7e907cSAndroid Build Coastguard Worker auto capabilities = A2dpBits(a2dp_info.capabilities);
209*4d7e907cSAndroid Build Coastguard Worker
210*4d7e907cSAndroid Build Coastguard Worker capabilities.set(kObjectTypeMpeg2AacLc, kEnableObjectTypeMpeg2AacLc);
211*4d7e907cSAndroid Build Coastguard Worker capabilities.set(kObjectTypeMpeg4AacLc, kEnableObjectTypeMpeg4AacLc);
212*4d7e907cSAndroid Build Coastguard Worker
213*4d7e907cSAndroid Build Coastguard Worker capabilities.set(kSamplingFrequency44100, kEnableSamplingFrequency44100);
214*4d7e907cSAndroid Build Coastguard Worker capabilities.set(kSamplingFrequency48000, kEnableSamplingFrequency48000);
215*4d7e907cSAndroid Build Coastguard Worker capabilities.set(kSamplingFrequency88200, kEnableSamplingFrequency88200);
216*4d7e907cSAndroid Build Coastguard Worker capabilities.set(kSamplingFrequency96000, kEnableSamplingFrequency96000);
217*4d7e907cSAndroid Build Coastguard Worker
218*4d7e907cSAndroid Build Coastguard Worker capabilities.set(kChannels1, kEnableChannels1);
219*4d7e907cSAndroid Build Coastguard Worker capabilities.set(kChannels2, kEnableChannels2);
220*4d7e907cSAndroid Build Coastguard Worker
221*4d7e907cSAndroid Build Coastguard Worker capabilities.set(kVbrSupported, kEnableVbrSupported);
222*4d7e907cSAndroid Build Coastguard Worker
223*4d7e907cSAndroid Build Coastguard Worker /* --- Setup Sampling Frequencies --- */
224*4d7e907cSAndroid Build Coastguard Worker
225*4d7e907cSAndroid Build Coastguard Worker auto& sampling_frequency = a2dp_info.samplingFrequencyHz;
226*4d7e907cSAndroid Build Coastguard Worker
227*4d7e907cSAndroid Build Coastguard Worker for (auto v : {8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000,
228*4d7e907cSAndroid Build Coastguard Worker 64000, 88200, 96000})
229*4d7e907cSAndroid Build Coastguard Worker if (capabilities.get(GetSamplingFrequencyBit(int32_t(v))))
230*4d7e907cSAndroid Build Coastguard Worker sampling_frequency.push_back(v);
231*4d7e907cSAndroid Build Coastguard Worker
232*4d7e907cSAndroid Build Coastguard Worker /* --- Setup Channel Modes --- */
233*4d7e907cSAndroid Build Coastguard Worker
234*4d7e907cSAndroid Build Coastguard Worker auto& channel_modes = a2dp_info.channelMode;
235*4d7e907cSAndroid Build Coastguard Worker
236*4d7e907cSAndroid Build Coastguard Worker for (auto v : {ChannelMode::MONO, ChannelMode::STEREO})
237*4d7e907cSAndroid Build Coastguard Worker if (capabilities.get(GetChannelsBit(v))) channel_modes.push_back(v);
238*4d7e907cSAndroid Build Coastguard Worker
239*4d7e907cSAndroid Build Coastguard Worker /* --- Setup Bitdepth --- */
240*4d7e907cSAndroid Build Coastguard Worker
241*4d7e907cSAndroid Build Coastguard Worker a2dp_info.bitdepth.push_back(kBitdepth);
242*4d7e907cSAndroid Build Coastguard Worker }
243*4d7e907cSAndroid Build Coastguard Worker
ParseConfiguration(const std::vector<uint8_t> & configuration,CodecParameters * codec_parameters,AacParameters * aac_parameters) const244*4d7e907cSAndroid Build Coastguard Worker A2dpStatus A2dpOffloadCodecAac::ParseConfiguration(
245*4d7e907cSAndroid Build Coastguard Worker const std::vector<uint8_t>& configuration,
246*4d7e907cSAndroid Build Coastguard Worker CodecParameters* codec_parameters, AacParameters* aac_parameters) const {
247*4d7e907cSAndroid Build Coastguard Worker auto& a2dp_info = info.transport.get<CodecInfo::Transport::Tag::a2dp>();
248*4d7e907cSAndroid Build Coastguard Worker
249*4d7e907cSAndroid Build Coastguard Worker if (configuration.size() != a2dp_info.capabilities.size())
250*4d7e907cSAndroid Build Coastguard Worker return A2dpStatus::BAD_LENGTH;
251*4d7e907cSAndroid Build Coastguard Worker
252*4d7e907cSAndroid Build Coastguard Worker auto config = A2dpBits(configuration);
253*4d7e907cSAndroid Build Coastguard Worker auto lcaps = A2dpBits(a2dp_info.capabilities);
254*4d7e907cSAndroid Build Coastguard Worker
255*4d7e907cSAndroid Build Coastguard Worker /* --- Check Object Type --- */
256*4d7e907cSAndroid Build Coastguard Worker
257*4d7e907cSAndroid Build Coastguard Worker int object_type = config.find_active_bit(kObjectType);
258*4d7e907cSAndroid Build Coastguard Worker if (object_type < 0) return A2dpStatus::INVALID_OBJECT_TYPE;
259*4d7e907cSAndroid Build Coastguard Worker if (!lcaps.get(object_type)) return A2dpStatus::NOT_SUPPORTED_OBJECT_TYPE;
260*4d7e907cSAndroid Build Coastguard Worker
261*4d7e907cSAndroid Build Coastguard Worker /* --- Check Sampling Frequency --- */
262*4d7e907cSAndroid Build Coastguard Worker
263*4d7e907cSAndroid Build Coastguard Worker int sampling_frequency = config.find_active_bit(kSamplingFrequency);
264*4d7e907cSAndroid Build Coastguard Worker if (sampling_frequency < 0) return A2dpStatus::INVALID_SAMPLING_FREQUENCY;
265*4d7e907cSAndroid Build Coastguard Worker if (!lcaps.get(sampling_frequency))
266*4d7e907cSAndroid Build Coastguard Worker return A2dpStatus::NOT_SUPPORTED_SAMPLING_FREQUENCY;
267*4d7e907cSAndroid Build Coastguard Worker
268*4d7e907cSAndroid Build Coastguard Worker /* --- Check Channels --- */
269*4d7e907cSAndroid Build Coastguard Worker
270*4d7e907cSAndroid Build Coastguard Worker int channels = config.find_active_bit(kChannels);
271*4d7e907cSAndroid Build Coastguard Worker if (channels < 0) return A2dpStatus::INVALID_CHANNELS;
272*4d7e907cSAndroid Build Coastguard Worker if (!lcaps.get(channels)) return A2dpStatus::NOT_SUPPORTED_CHANNELS;
273*4d7e907cSAndroid Build Coastguard Worker
274*4d7e907cSAndroid Build Coastguard Worker /* --- Check Bitrate --- */
275*4d7e907cSAndroid Build Coastguard Worker
276*4d7e907cSAndroid Build Coastguard Worker bool vbr = config.get(kVbrSupported);
277*4d7e907cSAndroid Build Coastguard Worker if (vbr && !lcaps.get(kVbrSupported)) return A2dpStatus::NOT_SUPPORTED_VBR;
278*4d7e907cSAndroid Build Coastguard Worker
279*4d7e907cSAndroid Build Coastguard Worker int bitrate = config.get(kBitrate);
280*4d7e907cSAndroid Build Coastguard Worker if (vbr && lcaps.get(kBitrate) && bitrate > lcaps.get(kBitrate))
281*4d7e907cSAndroid Build Coastguard Worker return A2dpStatus::NOT_SUPPORTED_BIT_RATE;
282*4d7e907cSAndroid Build Coastguard Worker
283*4d7e907cSAndroid Build Coastguard Worker /* --- Return --- */
284*4d7e907cSAndroid Build Coastguard Worker
285*4d7e907cSAndroid Build Coastguard Worker codec_parameters->channelMode = GetChannelModeEnum(channels);
286*4d7e907cSAndroid Build Coastguard Worker codec_parameters->samplingFrequencyHz =
287*4d7e907cSAndroid Build Coastguard Worker GetSamplingFrequencyValue(sampling_frequency);
288*4d7e907cSAndroid Build Coastguard Worker codec_parameters->bitdepth = kBitdepth;
289*4d7e907cSAndroid Build Coastguard Worker
290*4d7e907cSAndroid Build Coastguard Worker codec_parameters->minBitrate = vbr ? 0 : bitrate;
291*4d7e907cSAndroid Build Coastguard Worker codec_parameters->maxBitrate = bitrate;
292*4d7e907cSAndroid Build Coastguard Worker
293*4d7e907cSAndroid Build Coastguard Worker if (aac_parameters)
294*4d7e907cSAndroid Build Coastguard Worker aac_parameters->object_type = GetObjectTypeEnum(object_type);
295*4d7e907cSAndroid Build Coastguard Worker
296*4d7e907cSAndroid Build Coastguard Worker return A2dpStatus::OK;
297*4d7e907cSAndroid Build Coastguard Worker }
298*4d7e907cSAndroid Build Coastguard Worker
BuildConfiguration(const std::vector<uint8_t> & remote_capabilities,const std::optional<CodecParameters> & hint,std::vector<uint8_t> * configuration) const299*4d7e907cSAndroid Build Coastguard Worker bool A2dpOffloadCodecAac::BuildConfiguration(
300*4d7e907cSAndroid Build Coastguard Worker const std::vector<uint8_t>& remote_capabilities,
301*4d7e907cSAndroid Build Coastguard Worker const std::optional<CodecParameters>& hint,
302*4d7e907cSAndroid Build Coastguard Worker std::vector<uint8_t>* configuration) const {
303*4d7e907cSAndroid Build Coastguard Worker auto& a2dp_info = info_.transport.get<CodecInfo::Transport::Tag::a2dp>();
304*4d7e907cSAndroid Build Coastguard Worker
305*4d7e907cSAndroid Build Coastguard Worker if (remote_capabilities.size() != a2dp_info.capabilities.size()) return false;
306*4d7e907cSAndroid Build Coastguard Worker
307*4d7e907cSAndroid Build Coastguard Worker auto lcaps = A2dpBits(a2dp_info.capabilities);
308*4d7e907cSAndroid Build Coastguard Worker auto rcaps = A2dpBits(remote_capabilities);
309*4d7e907cSAndroid Build Coastguard Worker
310*4d7e907cSAndroid Build Coastguard Worker configuration->resize(a2dp_info.capabilities.size());
311*4d7e907cSAndroid Build Coastguard Worker std::fill(begin(*configuration), end(*configuration), 0);
312*4d7e907cSAndroid Build Coastguard Worker auto config = A2dpBits(*configuration);
313*4d7e907cSAndroid Build Coastguard Worker
314*4d7e907cSAndroid Build Coastguard Worker /* --- Select Object Type --- */
315*4d7e907cSAndroid Build Coastguard Worker
316*4d7e907cSAndroid Build Coastguard Worker if (lcaps.get(kObjectTypeMpeg2AacLc) && rcaps.get(kObjectTypeMpeg2AacLc))
317*4d7e907cSAndroid Build Coastguard Worker config.set(kObjectTypeMpeg2AacLc);
318*4d7e907cSAndroid Build Coastguard Worker else if (lcaps.get(kObjectTypeMpeg4AacLc) && rcaps.get(kObjectTypeMpeg4AacLc))
319*4d7e907cSAndroid Build Coastguard Worker config.set(kObjectTypeMpeg4AacLc);
320*4d7e907cSAndroid Build Coastguard Worker else
321*4d7e907cSAndroid Build Coastguard Worker return false;
322*4d7e907cSAndroid Build Coastguard Worker
323*4d7e907cSAndroid Build Coastguard Worker /* --- Select Sampling Frequency --- */
324*4d7e907cSAndroid Build Coastguard Worker
325*4d7e907cSAndroid Build Coastguard Worker auto sf_hint = hint ? GetSamplingFrequencyBit(hint->samplingFrequencyHz) : -1;
326*4d7e907cSAndroid Build Coastguard Worker
327*4d7e907cSAndroid Build Coastguard Worker if (sf_hint >= 0 && lcaps.get(sf_hint) && rcaps.get(sf_hint))
328*4d7e907cSAndroid Build Coastguard Worker config.set(sf_hint);
329*4d7e907cSAndroid Build Coastguard Worker else if (lcaps.get(kSamplingFrequency96000) &&
330*4d7e907cSAndroid Build Coastguard Worker rcaps.get(kSamplingFrequency96000))
331*4d7e907cSAndroid Build Coastguard Worker config.set(kSamplingFrequency96000);
332*4d7e907cSAndroid Build Coastguard Worker else if (lcaps.get(kSamplingFrequency88200) &&
333*4d7e907cSAndroid Build Coastguard Worker rcaps.get(kSamplingFrequency88200))
334*4d7e907cSAndroid Build Coastguard Worker config.set(kSamplingFrequency88200);
335*4d7e907cSAndroid Build Coastguard Worker else if (lcaps.get(kSamplingFrequency48000) &&
336*4d7e907cSAndroid Build Coastguard Worker rcaps.get(kSamplingFrequency48000))
337*4d7e907cSAndroid Build Coastguard Worker config.set(kSamplingFrequency48000);
338*4d7e907cSAndroid Build Coastguard Worker else if (lcaps.get(kSamplingFrequency44100) &&
339*4d7e907cSAndroid Build Coastguard Worker rcaps.get(kSamplingFrequency44100))
340*4d7e907cSAndroid Build Coastguard Worker config.set(kSamplingFrequency44100);
341*4d7e907cSAndroid Build Coastguard Worker else
342*4d7e907cSAndroid Build Coastguard Worker return false;
343*4d7e907cSAndroid Build Coastguard Worker
344*4d7e907cSAndroid Build Coastguard Worker /* --- Select Channels --- */
345*4d7e907cSAndroid Build Coastguard Worker
346*4d7e907cSAndroid Build Coastguard Worker auto ch_hint = hint ? GetChannelsBit(hint->channelMode) : -1;
347*4d7e907cSAndroid Build Coastguard Worker
348*4d7e907cSAndroid Build Coastguard Worker if (ch_hint >= 0 && lcaps.get(ch_hint) && rcaps.get(ch_hint))
349*4d7e907cSAndroid Build Coastguard Worker config.set(ch_hint);
350*4d7e907cSAndroid Build Coastguard Worker else if (lcaps.get(kChannels2) && rcaps.get(kChannels2))
351*4d7e907cSAndroid Build Coastguard Worker config.set(kChannels2);
352*4d7e907cSAndroid Build Coastguard Worker else if (lcaps.get(kChannels1) && rcaps.get(kChannels1))
353*4d7e907cSAndroid Build Coastguard Worker config.set(kChannels1);
354*4d7e907cSAndroid Build Coastguard Worker else
355*4d7e907cSAndroid Build Coastguard Worker return false;
356*4d7e907cSAndroid Build Coastguard Worker
357*4d7e907cSAndroid Build Coastguard Worker /* --- Select Bitrate --- */
358*4d7e907cSAndroid Build Coastguard Worker
359*4d7e907cSAndroid Build Coastguard Worker if (!hint || hint->minBitrate == 0)
360*4d7e907cSAndroid Build Coastguard Worker config.set(kVbrSupported,
361*4d7e907cSAndroid Build Coastguard Worker lcaps.get(kVbrSupported) && rcaps.get(kVbrSupported));
362*4d7e907cSAndroid Build Coastguard Worker
363*4d7e907cSAndroid Build Coastguard Worker int32_t bitrate = lcaps.get(kBitrate);
364*4d7e907cSAndroid Build Coastguard Worker if (hint && hint->maxBitrate > 0 && bitrate)
365*4d7e907cSAndroid Build Coastguard Worker bitrate = std::min(hint->maxBitrate, bitrate);
366*4d7e907cSAndroid Build Coastguard Worker else if (hint && hint->maxBitrate > 0)
367*4d7e907cSAndroid Build Coastguard Worker bitrate = hint->maxBitrate;
368*4d7e907cSAndroid Build Coastguard Worker config.set(kBitrate, bitrate);
369*4d7e907cSAndroid Build Coastguard Worker
370*4d7e907cSAndroid Build Coastguard Worker return true;
371*4d7e907cSAndroid Build Coastguard Worker }
372*4d7e907cSAndroid Build Coastguard Worker
373*4d7e907cSAndroid Build Coastguard Worker } // namespace aidl::android::hardware::bluetooth::audio
374