blob: 36d8f729eb3524869c1c81c094a14a8ff19e770a [file] [log] [blame]
Antoine SOULIER4e34d052023-09-29 19:10:07 +00001/*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "A2dpOffloadCodecSbc.h"
18
19#include <algorithm>
20
21#include "A2dpBits.h"
22
23namespace aidl::android::hardware::bluetooth::audio {
24
25/**
26 * SBC Local Capabilities
27 */
28
29enum : bool {
30 kEnableSamplingFrequency44100 = true,
31 kEnableSamplingFrequency48000 = true,
32};
33
34enum : bool {
35 kEnableChannelModeMono = true,
36 kEnableChannelModeDualChannel = true,
37 kEnableChannelModeStereo = true,
38 kEnableChannelModeJointStereo = true,
39};
40
41enum : bool {
42 kEnableBlockLength4 = true,
43 kEnableBlockLength8 = true,
44 kEnableBlockLength12 = true,
45 kEnableBlockLength16 = true,
46};
47
48enum : bool {
49 kEnableSubbands4 = true,
50 kEnableSubbands8 = true,
51};
52
53enum : bool {
54 kEnableAllocationMethodSnr = true,
55 kEnableAllocationMethodLoudness = true,
56};
57
58enum : uint8_t {
59 kDefaultMinimumBitpool = 2,
60 kDefaultMaximumBitpool = 250,
61};
62
63enum : int {
64 kBitdepth = 16,
65};
66
67/**
68 * SBC Signaling format [A2DP - 4.3]
69 */
70
71// clang-format off
72
73constexpr A2dpBits::Range kSamplingFrequency ( 0, 3 );
74constexpr A2dpBits::Range kChannelMode ( 4, 7 );
75constexpr A2dpBits::Range kBlockLength ( 8, 11 );
76constexpr A2dpBits::Range kSubbands ( 12, 13 );
77constexpr A2dpBits::Range kAllocationMethod ( 14, 15 );
78constexpr A2dpBits::Range kMinimumBitpool ( 16, 23 );
79constexpr A2dpBits::Range kMaximumBitpool ( 24, 31 );
80constexpr size_t kCapabilitiesSize = 32/8;
81
82// clang-format on
83
84enum {
85 kSamplingFrequency16000 = kSamplingFrequency.first,
86 kSamplingFrequency32000,
87 kSamplingFrequency44100,
88 kSamplingFrequency48000
89};
90
91enum {
92 kChannelModeMono = kChannelMode.first,
93 kChannelModeDualChannel,
94 kChannelModeStereo,
95 kChannelModeJointStereo
96};
97
98enum {
99 kBlockLength4 = kBlockLength.first,
100 kBlockLength8,
101 kBlockLength12,
102 kBlockLength16
103};
104
105enum { kSubbands8 = kSubbands.first, kSubbands4 };
106
107enum {
108 kAllocationMethodSnr = kAllocationMethod.first,
109 kAllocationMethodLoudness
110};
111
112/**
113 * SBC Conversion functions
114 */
115
116static int GetSamplingFrequencyBit(int32_t sampling_frequency) {
117 switch (sampling_frequency) {
118 case 16000:
119 return kSamplingFrequency16000;
120 case 32000:
121 return kSamplingFrequency32000;
122 case 44100:
123 return kSamplingFrequency44100;
124 case 48000:
125 return kSamplingFrequency48000;
126 default:
127 return -1;
128 }
129}
130
131static int32_t GetSamplingFrequencyValue(int sampling_frequency) {
132 switch (sampling_frequency) {
133 case kSamplingFrequency16000:
134 return 16000;
135 case kSamplingFrequency32000:
136 return 32000;
137 case kSamplingFrequency44100:
138 return 44100;
139 case kSamplingFrequency48000:
140 return 48000;
141 default:
142 return 0;
143 }
144}
145
146static int GetChannelModeBit(ChannelMode channel_mode) {
147 switch (channel_mode) {
148 case ChannelMode::STEREO:
149 return kChannelModeJointStereo | kChannelModeStereo;
150 case ChannelMode::DUALMONO:
151 return kChannelModeDualChannel;
152 case ChannelMode::MONO:
153 return kChannelModeMono;
154 default:
155 return -1;
156 }
157}
158
159static ChannelMode GetChannelModeEnum(int channel_mode) {
160 switch (channel_mode) {
161 case kChannelModeMono:
162 return ChannelMode::MONO;
163 case kChannelModeDualChannel:
164 return ChannelMode::DUALMONO;
165 case kChannelModeStereo:
166 case kChannelModeJointStereo:
167 return ChannelMode::STEREO;
168 default:
169 return ChannelMode::UNKNOWN;
170 }
171}
172
173static int32_t GetBlockLengthValue(int block_length) {
174 switch (block_length) {
175 case kBlockLength4:
176 return 4;
177 case kBlockLength8:
178 return 8;
179 case kBlockLength12:
180 return 12;
181 case kBlockLength16:
182 return 16;
183 default:
184 return 0;
185 }
186}
187
188static int32_t GetSubbandsValue(int subbands) {
189 switch (subbands) {
190 case kSubbands4:
191 return 4;
192 case kSubbands8:
193 return 8;
194 default:
195 return 0;
196 }
197}
198
199static SbcParameters::AllocationMethod GetAllocationMethodEnum(
200 int allocation_method) {
201 switch (allocation_method) {
202 case kAllocationMethodSnr:
203 return SbcParameters::AllocationMethod::SNR;
204 case kAllocationMethodLoudness:
205 default:
206 return SbcParameters::AllocationMethod::LOUDNESS;
207 }
208}
209
210static int32_t GetSamplingFrequencyValue(const A2dpBits& configuration) {
211 return GetSamplingFrequencyValue(
212 configuration.find_active_bit(kSamplingFrequency));
213}
214
215static int32_t GetBlockLengthValue(const A2dpBits& configuration) {
216 return GetBlockLengthValue(configuration.find_active_bit(kBlockLength));
217}
218
219static int32_t GetSubbandsValue(const A2dpBits& configuration) {
220 return GetSubbandsValue(configuration.find_active_bit(kSubbands));
221}
222
223static int GetFrameSize(const A2dpBits& configuration, int bitpool) {
224 const int kSbcHeaderSize = 4;
225 int subbands = GetSubbandsValue(configuration);
226 int blocks = GetBlockLengthValue(configuration);
227
228 unsigned bits =
229 ((4 * subbands) << !configuration.get(kChannelModeMono)) +
230 ((blocks * bitpool) << configuration.get(kChannelModeDualChannel)) +
231 ((configuration.get(kChannelModeJointStereo) ? subbands : 0));
232
233 return kSbcHeaderSize + ((bits + 7) >> 3);
234}
235
236static int GetBitrate(const A2dpBits& configuration, int bitpool) {
237 int sampling_frequency = GetSamplingFrequencyValue(configuration);
238 int subbands = GetSubbandsValue(configuration);
239 int blocks = GetBlockLengthValue(configuration);
240 int bits = 8 * GetFrameSize(configuration, bitpool);
241
242 return (bits * sampling_frequency) / (blocks * subbands);
243}
244
245static uint8_t GetBitpool(const A2dpBits& configuration, int bitrate) {
246 int bitpool = 0;
247
248 for (int i = 128; i; i >>= 1)
249 if (bitrate > GetBitrate(configuration, bitpool + i)) {
250 bitpool += i;
251 }
252
253 return std::clamp(bitpool, 2, 250);
254}
255
256/**
257 * SBC Class implementation
258 */
259
260const A2dpOffloadCodecSbc* A2dpOffloadCodecSbc::GetInstance() {
261 static A2dpOffloadCodecSbc instance;
262 return &instance;
263}
264
265A2dpOffloadCodecSbc::A2dpOffloadCodecSbc()
266 : A2dpOffloadCodec(info_),
267 info_({.id = CodecId(CodecId::A2dp::SBC), .name = "SBC"}) {
268 info_.transport.set<CodecInfo::Transport::Tag::a2dp>();
269 auto& a2dp_info = info_.transport.get<CodecInfo::Transport::Tag::a2dp>();
270
271 /* --- Setup Capabilities --- */
272
273 a2dp_info.capabilities.resize(kCapabilitiesSize);
274 std::fill(begin(a2dp_info.capabilities), end(a2dp_info.capabilities), 0);
275
276 auto capabilities = A2dpBits(a2dp_info.capabilities);
277
278 capabilities.set(kSamplingFrequency44100, kEnableSamplingFrequency44100);
279 capabilities.set(kSamplingFrequency48000, kEnableSamplingFrequency48000);
280
281 capabilities.set(kChannelModeMono, kEnableChannelModeMono);
282 capabilities.set(kChannelModeDualChannel, kEnableChannelModeDualChannel);
283 capabilities.set(kChannelModeStereo, kEnableChannelModeStereo);
284 capabilities.set(kChannelModeJointStereo, kEnableChannelModeJointStereo);
285
286 capabilities.set(kBlockLength4, kEnableBlockLength4);
287 capabilities.set(kBlockLength8, kEnableBlockLength8);
288 capabilities.set(kBlockLength12, kEnableBlockLength12);
289 capabilities.set(kBlockLength16, kEnableBlockLength16);
290
291 capabilities.set(kSubbands4, kEnableSubbands4);
292 capabilities.set(kSubbands8, kEnableSubbands8);
293
294 capabilities.set(kSubbands4, kEnableSubbands4);
295 capabilities.set(kSubbands8, kEnableSubbands8);
296
297 capabilities.set(kAllocationMethodSnr, kEnableAllocationMethodSnr);
298 capabilities.set(kAllocationMethodLoudness, kEnableAllocationMethodLoudness);
299
300 capabilities.set(kMinimumBitpool, kDefaultMinimumBitpool);
301 capabilities.set(kMaximumBitpool, kDefaultMaximumBitpool);
302
303 /* --- Setup Sampling Frequencies --- */
304
305 auto& sampling_frequency = a2dp_info.samplingFrequencyHz;
306
307 for (auto v : {16000, 32000, 44100, 48000})
308 if (capabilities.get(GetSamplingFrequencyBit(int32_t(v))))
309 sampling_frequency.push_back(v);
310
311 /* --- Setup Channel Modes --- */
312
313 auto& channel_modes = a2dp_info.channelMode;
314
315 for (auto v : {ChannelMode::MONO, ChannelMode::DUALMONO, ChannelMode::STEREO})
316 if (capabilities.get(GetChannelModeBit(v))) channel_modes.push_back(v);
317
318 /* --- Setup Bitdepth --- */
319
320 a2dp_info.bitdepth.push_back(kBitdepth);
321}
322
323A2dpStatus A2dpOffloadCodecSbc::ParseConfiguration(
324 const std::vector<uint8_t>& configuration,
325 CodecParameters* codec_parameters, SbcParameters* sbc_parameters) const {
326 auto& a2dp_info = info.transport.get<CodecInfo::Transport::Tag::a2dp>();
327
328 if (configuration.size() != a2dp_info.capabilities.size())
329 return A2dpStatus::BAD_LENGTH;
330
331 auto config = A2dpBits(configuration);
332 auto lcaps = A2dpBits(a2dp_info.capabilities);
333
334 /* --- Check Sampling Frequency --- */
335
336 int sampling_frequency = config.find_active_bit(kSamplingFrequency);
337 if (sampling_frequency < 0) return A2dpStatus::INVALID_SAMPLING_FREQUENCY;
338 if (!lcaps.get(sampling_frequency))
339 return A2dpStatus::NOT_SUPPORTED_SAMPLING_FREQUENCY;
340
341 /* --- Check Channel Mode --- */
342
343 int channel_mode = config.find_active_bit(kChannelMode);
344 if (channel_mode < 0) return A2dpStatus::INVALID_CHANNEL_MODE;
345 if (!lcaps.get(channel_mode)) return A2dpStatus::NOT_SUPPORTED_CHANNEL_MODE;
346
347 /* --- Check Block Length --- */
348
349 int block_length = config.find_active_bit(kBlockLength);
350 if (block_length < 0) return A2dpStatus::INVALID_BLOCK_LENGTH;
351
352 /* --- Check Subbands --- */
353
354 int subbands = config.find_active_bit(kSubbands);
355 if (subbands < 0) return A2dpStatus::INVALID_SUBBANDS;
356 if (!lcaps.get(subbands)) return A2dpStatus::NOT_SUPPORTED_SUBBANDS;
357
358 /* --- Check Allocation Method --- */
359
360 int allocation_method = config.find_active_bit(kAllocationMethod);
361 if (allocation_method < 0) return A2dpStatus::INVALID_ALLOCATION_METHOD;
362 if (!lcaps.get(allocation_method))
363 return A2dpStatus::NOT_SUPPORTED_ALLOCATION_METHOD;
364
365 /* --- Check Bitpool --- */
366
367 uint8_t min_bitpool = config.get(kMinimumBitpool);
368 if (min_bitpool < 2 || min_bitpool > 250)
369 return A2dpStatus::INVALID_MINIMUM_BITPOOL_VALUE;
370 if (min_bitpool < lcaps.get(kMinimumBitpool))
371 return A2dpStatus::NOT_SUPPORTED_MINIMUM_BITPOOL_VALUE;
372
373 uint8_t max_bitpool = config.get(kMaximumBitpool);
374 if (max_bitpool < 2 || max_bitpool > 250)
375 return A2dpStatus::INVALID_MAXIMUM_BITPOOL_VALUE;
376 if (max_bitpool > lcaps.get(kMaximumBitpool))
377 return A2dpStatus::NOT_SUPPORTED_MAXIMUM_BITPOOL_VALUE;
378
379 /* --- Return --- */
380
381 codec_parameters->channelMode = GetChannelModeEnum(channel_mode);
382 codec_parameters->samplingFrequencyHz =
383 GetSamplingFrequencyValue(sampling_frequency);
384 codec_parameters->bitdepth = kBitdepth;
385
386 codec_parameters->minBitrate = GetBitrate(config, min_bitpool);
387 codec_parameters->maxBitrate = GetBitrate(config, max_bitpool);
388
389 if (sbc_parameters) {
390 sbc_parameters->block_length = GetBlockLengthValue(block_length);
391 sbc_parameters->subbands = GetSubbandsValue(subbands);
392 sbc_parameters->allocation_method =
393 GetAllocationMethodEnum(allocation_method);
394 sbc_parameters->min_bitpool = min_bitpool;
395 sbc_parameters->max_bitpool = max_bitpool;
396 }
397
398 return A2dpStatus::OK;
399}
400
401bool A2dpOffloadCodecSbc::BuildConfiguration(
402 const std::vector<uint8_t>& remote_capabilities,
403 const std::optional<CodecParameters>& hint,
404 std::vector<uint8_t>* configuration) const {
405 auto& a2dp_info = info.transport.get<CodecInfo::Transport::Tag::a2dp>();
406
407 if (remote_capabilities.size() != a2dp_info.capabilities.size()) return false;
408
409 auto lcaps = A2dpBits(a2dp_info.capabilities);
410 auto rcaps = A2dpBits(remote_capabilities);
411
412 configuration->resize(a2dp_info.capabilities.size());
413 std::fill(begin(*configuration), end(*configuration), 0);
414 auto config = A2dpBits(*configuration);
415
416 /* --- Select Sampling Frequency --- */
417
418 auto sf_hint = hint ? GetSamplingFrequencyBit(hint->samplingFrequencyHz) : -1;
419
420 if (sf_hint >= 0 && lcaps.get(sf_hint) && rcaps.get(sf_hint))
421 config.set(sf_hint);
422 else if (lcaps.get(kSamplingFrequency44100) &&
423 rcaps.get(kSamplingFrequency44100))
424 config.set(kSamplingFrequency44100);
425 else if (lcaps.get(kSamplingFrequency48000) &&
426 rcaps.get(kSamplingFrequency48000))
427 config.set(kSamplingFrequency48000);
428 else
429 return false;
430
431 /* --- Select Channel Mode --- */
432
433 auto cm_hint = hint ? GetChannelModeBit(hint->channelMode) : -1;
434
435 if (cm_hint >= 0 && lcaps.get(cm_hint) && rcaps.get(cm_hint))
436 config.set(cm_hint);
437 else if (lcaps.get(kChannelModeJointStereo) &&
438 rcaps.get(kChannelModeJointStereo))
439 config.set(kChannelModeJointStereo);
440 else if (lcaps.get(kChannelModeStereo) && rcaps.get(kChannelModeStereo))
441 config.set(kChannelModeStereo);
442 else if (lcaps.get(kChannelModeDualChannel) &&
443 rcaps.get(kChannelModeDualChannel))
444 config.set(kChannelModeDualChannel);
445 else if (lcaps.get(kChannelModeMono) && rcaps.get(kChannelModeMono))
446 config.set(kChannelModeMono);
447 else
448 return false;
449
450 /* --- Select Block Length --- */
451
452 if (lcaps.get(kBlockLength16) && rcaps.get(kBlockLength16))
453 config.set(kBlockLength16);
454 else if (lcaps.get(kBlockLength12) && rcaps.get(kBlockLength12))
455 config.set(kBlockLength12);
456 else if (lcaps.get(kBlockLength8) && rcaps.get(kBlockLength8))
457 config.set(kBlockLength8);
458 else if (lcaps.get(kBlockLength4) && rcaps.get(kBlockLength4))
459 config.set(kBlockLength4);
460 else
461 return false;
462
463 /* --- Select Subbands --- */
464
465 if (lcaps.get(kSubbands8) && rcaps.get(kSubbands8))
466 config.set(kSubbands8);
467 else if (lcaps.get(kSubbands4) && rcaps.get(kSubbands4))
468 config.set(kSubbands4);
469 else
470 return false;
471
472 /* --- Select Allocation method --- */
473
474 if (lcaps.get(kAllocationMethodLoudness) &&
475 rcaps.get(kAllocationMethodLoudness))
476 config.set(kAllocationMethodLoudness);
477 else if (lcaps.get(kAllocationMethodSnr) && rcaps.get(kAllocationMethodSnr))
478 config.set(kAllocationMethodSnr);
479 else
480 return false;
481
482 /* --- Select Bitpool --- */
483
484 uint8_t min_bitpool = rcaps.get(kMinimumBitpool);
485 uint8_t max_bitpool = rcaps.get(kMaximumBitpool);
486
487 if (min_bitpool < 2 || min_bitpool > 250 || max_bitpool < 2 ||
488 max_bitpool > 250 || min_bitpool > max_bitpool) {
489 min_bitpool = 2;
490 max_bitpool = 250;
491 }
492
493 min_bitpool = std::max(min_bitpool, uint8_t(lcaps.get(kMinimumBitpool)));
494 max_bitpool = std::max(max_bitpool, uint8_t(lcaps.get(kMaximumBitpool)));
495
496 if (hint) {
497 min_bitpool =
498 std::max(min_bitpool, GetBitpool(*configuration, hint->minBitrate));
499 if (hint->maxBitrate && hint->maxBitrate >= hint->minBitrate)
500 max_bitpool =
501 std::min(max_bitpool, GetBitpool(*configuration, hint->maxBitrate));
502 }
503
504 config.set(kMinimumBitpool, min_bitpool);
505 config.set(kMaximumBitpool, max_bitpool);
506
507 return true;
508}
509
510} // namespace aidl::android::hardware::bluetooth::audio