1 /*
2 * Copyright 2016 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 /**
18 * A2DP Codecs Configuration
19 */
20
21 #define LOG_TAG "a2dp_codec"
22
23 #include "a2dp_codec_api.h"
24
25 #include <base/logging.h>
26 #include <inttypes.h>
27
28 #include "a2dp_aac.h"
29 #include "a2dp_sbc.h"
30 #include "a2dp_vendor.h"
31 #include "a2dp_vendor_aptx.h"
32 #include "a2dp_vendor_aptx_hd.h"
33 #include "a2dp_vendor_ldac.h"
34 #include "bta/av/bta_av_int.h"
35 #include "osi/include/log.h"
36 #include "osi/include/properties.h"
37
38 /* The Media Type offset within the codec info byte array */
39 #define A2DP_MEDIA_TYPE_OFFSET 1
40
41 /* A2DP Offload enabled in stack */
42 static bool a2dp_offload_status;
43
44 // Initializes the codec config.
45 // |codec_config| is the codec config to initialize.
46 // |codec_index| and |codec_priority| are the codec type and priority to use
47 // for the initialization.
48
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)49 static void init_btav_a2dp_codec_config(
50 btav_a2dp_codec_config_t* codec_config, btav_a2dp_codec_index_t codec_index,
51 btav_a2dp_codec_priority_t codec_priority) {
52 memset(codec_config, 0, sizeof(btav_a2dp_codec_config_t));
53 codec_config->codec_type = codec_index;
54 codec_config->codec_priority = codec_priority;
55 }
56
A2dpCodecConfig(btav_a2dp_codec_index_t codec_index,const std::string & name,btav_a2dp_codec_priority_t codec_priority)57 A2dpCodecConfig::A2dpCodecConfig(btav_a2dp_codec_index_t codec_index,
58 const std::string& name,
59 btav_a2dp_codec_priority_t codec_priority)
60 : codec_index_(codec_index),
61 name_(name),
62 default_codec_priority_(codec_priority) {
63 setCodecPriority(codec_priority);
64
65 init_btav_a2dp_codec_config(&codec_config_, codec_index_, codecPriority());
66 init_btav_a2dp_codec_config(&codec_capability_, codec_index_,
67 codecPriority());
68 init_btav_a2dp_codec_config(&codec_local_capability_, codec_index_,
69 codecPriority());
70 init_btav_a2dp_codec_config(&codec_selectable_capability_, codec_index_,
71 codecPriority());
72 init_btav_a2dp_codec_config(&codec_user_config_, codec_index_,
73 BTAV_A2DP_CODEC_PRIORITY_DEFAULT);
74 init_btav_a2dp_codec_config(&codec_audio_config_, codec_index_,
75 BTAV_A2DP_CODEC_PRIORITY_DEFAULT);
76
77 memset(ota_codec_config_, 0, sizeof(ota_codec_config_));
78 memset(ota_codec_peer_capability_, 0, sizeof(ota_codec_peer_capability_));
79 memset(ota_codec_peer_config_, 0, sizeof(ota_codec_peer_config_));
80 }
81
~A2dpCodecConfig()82 A2dpCodecConfig::~A2dpCodecConfig() {}
83
setCodecPriority(btav_a2dp_codec_priority_t codec_priority)84 void A2dpCodecConfig::setCodecPriority(
85 btav_a2dp_codec_priority_t codec_priority) {
86 if (codec_priority == BTAV_A2DP_CODEC_PRIORITY_DEFAULT) {
87 // Compute the default codec priority
88 setDefaultCodecPriority();
89 } else {
90 codec_priority_ = codec_priority;
91 }
92 codec_config_.codec_priority = codec_priority_;
93 }
94
setDefaultCodecPriority()95 void A2dpCodecConfig::setDefaultCodecPriority() {
96 if (default_codec_priority_ != BTAV_A2DP_CODEC_PRIORITY_DEFAULT) {
97 codec_priority_ = default_codec_priority_;
98 } else {
99 // Compute the default codec priority
100 uint32_t priority = 1000 * (codec_index_ + 1) + 1;
101 codec_priority_ = static_cast<btav_a2dp_codec_priority_t>(priority);
102 }
103 codec_config_.codec_priority = codec_priority_;
104 }
105
createCodec(btav_a2dp_codec_index_t codec_index,btav_a2dp_codec_priority_t codec_priority)106 A2dpCodecConfig* A2dpCodecConfig::createCodec(
107 btav_a2dp_codec_index_t codec_index,
108 btav_a2dp_codec_priority_t codec_priority) {
109 LOG_DEBUG(LOG_TAG, "%s: codec %s", __func__, A2DP_CodecIndexStr(codec_index));
110
111 A2dpCodecConfig* codec_config = nullptr;
112 switch (codec_index) {
113 case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
114 codec_config = new A2dpCodecConfigSbcSource(codec_priority);
115 break;
116 case BTAV_A2DP_CODEC_INDEX_SINK_SBC:
117 codec_config = new A2dpCodecConfigSbcSink(codec_priority);
118 break;
119 case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC:
120 codec_config = new A2dpCodecConfigAacSource(codec_priority);
121 break;
122 case BTAV_A2DP_CODEC_INDEX_SINK_AAC:
123 codec_config = new A2dpCodecConfigAacSink(codec_priority);
124 break;
125 case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX:
126 codec_config = new A2dpCodecConfigAptx(codec_priority);
127 break;
128 case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD:
129 codec_config = new A2dpCodecConfigAptxHd(codec_priority);
130 break;
131 case BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC:
132 codec_config = new A2dpCodecConfigLdacSource(codec_priority);
133 break;
134 case BTAV_A2DP_CODEC_INDEX_SINK_LDAC:
135 codec_config = new A2dpCodecConfigLdacSink(codec_priority);
136 break;
137 case BTAV_A2DP_CODEC_INDEX_MAX:
138 break;
139 }
140
141 if (codec_config != nullptr) {
142 if (!codec_config->init()) {
143 delete codec_config;
144 codec_config = nullptr;
145 }
146 }
147
148 return codec_config;
149 }
150
getTrackBitRate() const151 int A2dpCodecConfig::getTrackBitRate() const {
152 uint8_t p_codec_info[AVDT_CODEC_SIZE];
153 memcpy(p_codec_info, ota_codec_config_, sizeof(ota_codec_config_));
154 tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
155
156 LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
157
158 switch (codec_type) {
159 case A2DP_MEDIA_CT_SBC:
160 return A2DP_GetBitrateSbc();
161 case A2DP_MEDIA_CT_AAC:
162 return A2DP_GetBitRateAac(p_codec_info);
163 case A2DP_MEDIA_CT_NON_A2DP:
164 return A2DP_VendorGetBitRate(p_codec_info);
165 default:
166 break;
167 }
168
169 LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
170 return -1;
171 }
172
getCodecSpecificConfig(tBT_A2DP_OFFLOAD * p_a2dp_offload)173 bool A2dpCodecConfig::getCodecSpecificConfig(tBT_A2DP_OFFLOAD* p_a2dp_offload) {
174 std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
175
176 uint8_t codec_config[AVDT_CODEC_SIZE];
177 uint32_t vendor_id;
178 uint16_t codec_id;
179
180 memset(p_a2dp_offload->codec_info, 0, sizeof(p_a2dp_offload->codec_info));
181
182 if (!A2DP_IsSourceCodecValid(ota_codec_config_)) {
183 return false;
184 }
185
186 memcpy(codec_config, ota_codec_config_, sizeof(ota_codec_config_));
187 tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(codec_config);
188 switch (codec_type) {
189 case A2DP_MEDIA_CT_SBC:
190 p_a2dp_offload->codec_info[0] =
191 codec_config[4]; // blk_len | subbands | Alloc Method
192 p_a2dp_offload->codec_info[1] = codec_config[5]; // Min bit pool
193 p_a2dp_offload->codec_info[2] = codec_config[6]; // Max bit pool
194 p_a2dp_offload->codec_info[3] =
195 codec_config[3]; // Sample freq | channel mode
196 break;
197 case A2DP_MEDIA_CT_AAC:
198 p_a2dp_offload->codec_info[0] = codec_config[3]; // object type
199 p_a2dp_offload->codec_info[1] = codec_config[6]; // VBR | BR
200 break;
201 case A2DP_MEDIA_CT_NON_A2DP:
202 vendor_id = A2DP_VendorCodecGetVendorId(codec_config);
203 codec_id = A2DP_VendorCodecGetCodecId(codec_config);
204 p_a2dp_offload->codec_info[0] = (vendor_id & 0x000000FF);
205 p_a2dp_offload->codec_info[1] = (vendor_id & 0x0000FF00) >> 8;
206 p_a2dp_offload->codec_info[2] = (vendor_id & 0x00FF0000) >> 16;
207 p_a2dp_offload->codec_info[3] = (vendor_id & 0xFF000000) >> 24;
208 p_a2dp_offload->codec_info[4] = (codec_id & 0x000000FF);
209 p_a2dp_offload->codec_info[5] = (codec_id & 0x0000FF00) >> 8;
210 if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) {
211 if (codec_config_.codec_specific_1 == 0) { // default is 0, ABR
212 p_a2dp_offload->codec_info[6] =
213 A2DP_LDAC_QUALITY_ABR_OFFLOAD; // ABR in offload
214 } else {
215 switch (codec_config_.codec_specific_1 % 10) {
216 case 0:
217 p_a2dp_offload->codec_info[6] =
218 A2DP_LDAC_QUALITY_HIGH; // High bitrate
219 break;
220 case 1:
221 p_a2dp_offload->codec_info[6] =
222 A2DP_LDAC_QUALITY_MID; // Mid birate
223 break;
224 case 2:
225 p_a2dp_offload->codec_info[6] =
226 A2DP_LDAC_QUALITY_LOW; // Low birate
227 break;
228 case 3:
229 FALLTHROUGH_INTENDED; /* FALLTHROUGH */
230 default:
231 p_a2dp_offload->codec_info[6] =
232 A2DP_LDAC_QUALITY_ABR_OFFLOAD; // ABR in offload
233 break;
234 }
235 }
236 p_a2dp_offload->codec_info[7] =
237 codec_config[10]; // LDAC specific channel mode
238 LOG_VERBOSE(LOG_TAG, "%s: Ldac specific channelmode =%d", __func__,
239 p_a2dp_offload->codec_info[7]);
240 }
241 break;
242 default:
243 break;
244 }
245 return true;
246 }
247
isValid() const248 bool A2dpCodecConfig::isValid() const { return true; }
249
copyOutOtaCodecConfig(uint8_t * p_codec_info)250 bool A2dpCodecConfig::copyOutOtaCodecConfig(uint8_t* p_codec_info) {
251 std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
252
253 // TODO: We should use a mechanism to verify codec config,
254 // not codec capability.
255 if (!A2DP_IsSourceCodecValid(ota_codec_config_)) {
256 return false;
257 }
258 memcpy(p_codec_info, ota_codec_config_, sizeof(ota_codec_config_));
259 return true;
260 }
261
getCodecConfig()262 btav_a2dp_codec_config_t A2dpCodecConfig::getCodecConfig() {
263 std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
264
265 // TODO: We should check whether the codec config is valid
266 return codec_config_;
267 }
268
getCodecCapability()269 btav_a2dp_codec_config_t A2dpCodecConfig::getCodecCapability() {
270 std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
271
272 // TODO: We should check whether the codec capability is valid
273 return codec_capability_;
274 }
275
getCodecLocalCapability()276 btav_a2dp_codec_config_t A2dpCodecConfig::getCodecLocalCapability() {
277 std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
278
279 // TODO: We should check whether the codec capability is valid
280 return codec_local_capability_;
281 }
282
getCodecSelectableCapability()283 btav_a2dp_codec_config_t A2dpCodecConfig::getCodecSelectableCapability() {
284 std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
285
286 // TODO: We should check whether the codec capability is valid
287 return codec_selectable_capability_;
288 }
289
getCodecUserConfig()290 btav_a2dp_codec_config_t A2dpCodecConfig::getCodecUserConfig() {
291 std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
292
293 return codec_user_config_;
294 }
295
getCodecAudioConfig()296 btav_a2dp_codec_config_t A2dpCodecConfig::getCodecAudioConfig() {
297 std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
298
299 return codec_audio_config_;
300 }
301
getAudioBitsPerSample()302 uint8_t A2dpCodecConfig::getAudioBitsPerSample() {
303 std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
304
305 switch (codec_config_.bits_per_sample) {
306 case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16:
307 return 16;
308 case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24:
309 return 24;
310 case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32:
311 return 32;
312 case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE:
313 break;
314 }
315 return 0;
316 }
317
isCodecConfigEmpty(const btav_a2dp_codec_config_t & codec_config)318 bool A2dpCodecConfig::isCodecConfigEmpty(
319 const btav_a2dp_codec_config_t& codec_config) {
320 return (
321 (codec_config.codec_priority == BTAV_A2DP_CODEC_PRIORITY_DEFAULT) &&
322 (codec_config.sample_rate == BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) &&
323 (codec_config.bits_per_sample == BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE) &&
324 (codec_config.channel_mode == BTAV_A2DP_CODEC_CHANNEL_MODE_NONE) &&
325 (codec_config.codec_specific_1 == 0) &&
326 (codec_config.codec_specific_2 == 0) &&
327 (codec_config.codec_specific_3 == 0) &&
328 (codec_config.codec_specific_4 == 0));
329 }
330
setCodecUserConfig(const btav_a2dp_codec_config_t & codec_user_config,const btav_a2dp_codec_config_t & codec_audio_config,const tA2DP_ENCODER_INIT_PEER_PARAMS * p_peer_params,const uint8_t * p_peer_codec_info,bool is_capability,uint8_t * p_result_codec_config,bool * p_restart_input,bool * p_restart_output,bool * p_config_updated)331 bool A2dpCodecConfig::setCodecUserConfig(
332 const btav_a2dp_codec_config_t& codec_user_config,
333 const btav_a2dp_codec_config_t& codec_audio_config,
334 const tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params,
335 const uint8_t* p_peer_codec_info, bool is_capability,
336 uint8_t* p_result_codec_config, bool* p_restart_input,
337 bool* p_restart_output, bool* p_config_updated) {
338 std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
339 *p_restart_input = false;
340 *p_restart_output = false;
341 *p_config_updated = false;
342
343 // Save copies of the current codec config, and the OTA codec config, so they
344 // can be compared for changes.
345 btav_a2dp_codec_config_t saved_codec_config = getCodecConfig();
346 uint8_t saved_ota_codec_config[AVDT_CODEC_SIZE];
347 memcpy(saved_ota_codec_config, ota_codec_config_, sizeof(ota_codec_config_));
348
349 btav_a2dp_codec_config_t saved_codec_user_config = codec_user_config_;
350 codec_user_config_ = codec_user_config;
351 btav_a2dp_codec_config_t saved_codec_audio_config = codec_audio_config_;
352 codec_audio_config_ = codec_audio_config;
353 bool success =
354 setCodecConfig(p_peer_codec_info, is_capability, p_result_codec_config);
355 if (!success) {
356 // Restore the local copy of the user and audio config
357 codec_user_config_ = saved_codec_user_config;
358 codec_audio_config_ = saved_codec_audio_config;
359 return false;
360 }
361
362 //
363 // The input (audio data) should be restarted if the audio format has changed
364 //
365 btav_a2dp_codec_config_t new_codec_config = getCodecConfig();
366 if ((saved_codec_config.sample_rate != new_codec_config.sample_rate) ||
367 (saved_codec_config.bits_per_sample !=
368 new_codec_config.bits_per_sample) ||
369 (saved_codec_config.channel_mode != new_codec_config.channel_mode)) {
370 *p_restart_input = true;
371 }
372
373 //
374 // The output (the connection) should be restarted if OTA codec config
375 // has changed.
376 //
377 if (!A2DP_CodecEquals(saved_ota_codec_config, p_result_codec_config)) {
378 *p_restart_output = true;
379 }
380
381 bool encoder_restart_input = *p_restart_input;
382 bool encoder_restart_output = *p_restart_output;
383 bool encoder_config_updated = *p_config_updated;
384
385 if (!a2dp_offload_status) {
386 if (updateEncoderUserConfig(p_peer_params, &encoder_restart_input,
387 &encoder_restart_output,
388 &encoder_config_updated)) {
389 if (encoder_restart_input) *p_restart_input = true;
390 if (encoder_restart_output) *p_restart_output = true;
391 if (encoder_config_updated) *p_config_updated = true;
392 }
393 }
394 if (*p_restart_input || *p_restart_output) *p_config_updated = true;
395
396 return true;
397 }
398
codecConfigIsValid(const btav_a2dp_codec_config_t & codec_config)399 bool A2dpCodecConfig::codecConfigIsValid(
400 const btav_a2dp_codec_config_t& codec_config) {
401 return (codec_config.codec_type < BTAV_A2DP_CODEC_INDEX_MAX) &&
402 (codec_config.sample_rate != BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) &&
403 (codec_config.bits_per_sample !=
404 BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE) &&
405 (codec_config.channel_mode != BTAV_A2DP_CODEC_CHANNEL_MODE_NONE);
406 }
407
codecConfig2Str(const btav_a2dp_codec_config_t & codec_config)408 std::string A2dpCodecConfig::codecConfig2Str(
409 const btav_a2dp_codec_config_t& codec_config) {
410 std::string result;
411
412 if (!codecConfigIsValid(codec_config)) return "Invalid";
413
414 result.append("Rate=");
415 result.append(codecSampleRate2Str(codec_config.sample_rate));
416 result.append(" Bits=");
417 result.append(codecBitsPerSample2Str(codec_config.bits_per_sample));
418 result.append(" Mode=");
419 result.append(codecChannelMode2Str(codec_config.channel_mode));
420
421 return result;
422 }
423
codecSampleRate2Str(btav_a2dp_codec_sample_rate_t codec_sample_rate)424 std::string A2dpCodecConfig::codecSampleRate2Str(
425 btav_a2dp_codec_sample_rate_t codec_sample_rate) {
426 std::string result;
427
428 if (codec_sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_44100) {
429 if (!result.empty()) result += "|";
430 result += "44100";
431 }
432 if (codec_sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_48000) {
433 if (!result.empty()) result += "|";
434 result += "48000";
435 }
436 if (codec_sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_88200) {
437 if (!result.empty()) result += "|";
438 result += "88200";
439 }
440 if (codec_sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_96000) {
441 if (!result.empty()) result += "|";
442 result += "96000";
443 }
444 if (codec_sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_176400) {
445 if (!result.empty()) result += "|";
446 result += "176400";
447 }
448 if (codec_sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_192000) {
449 if (!result.empty()) result += "|";
450 result += "192000";
451 }
452 if (result.empty()) {
453 std::stringstream ss;
454 ss << "UnknownSampleRate(0x" << std::hex << codec_sample_rate << ")";
455 ss >> result;
456 }
457
458 return result;
459 }
460
codecBitsPerSample2Str(btav_a2dp_codec_bits_per_sample_t codec_bits_per_sample)461 std::string A2dpCodecConfig::codecBitsPerSample2Str(
462 btav_a2dp_codec_bits_per_sample_t codec_bits_per_sample) {
463 std::string result;
464
465 if (codec_bits_per_sample & BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16) {
466 if (!result.empty()) result += "|";
467 result += "16";
468 }
469 if (codec_bits_per_sample & BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24) {
470 if (!result.empty()) result += "|";
471 result += "24";
472 }
473 if (codec_bits_per_sample & BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32) {
474 if (!result.empty()) result += "|";
475 result += "32";
476 }
477 if (result.empty()) {
478 std::stringstream ss;
479 ss << "UnknownBitsPerSample(0x" << std::hex << codec_bits_per_sample << ")";
480 ss >> result;
481 }
482
483 return result;
484 }
485
codecChannelMode2Str(btav_a2dp_codec_channel_mode_t codec_channel_mode)486 std::string A2dpCodecConfig::codecChannelMode2Str(
487 btav_a2dp_codec_channel_mode_t codec_channel_mode) {
488 std::string result;
489
490 if (codec_channel_mode & BTAV_A2DP_CODEC_CHANNEL_MODE_MONO) {
491 if (!result.empty()) result += "|";
492 result += "MONO";
493 }
494 if (codec_channel_mode & BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO) {
495 if (!result.empty()) result += "|";
496 result += "STEREO";
497 }
498 if (result.empty()) {
499 std::stringstream ss;
500 ss << "UnknownChannelMode(0x" << std::hex << codec_channel_mode << ")";
501 ss >> result;
502 }
503
504 return result;
505 }
506
debug_codec_dump(int fd)507 void A2dpCodecConfig::debug_codec_dump(int fd) {
508 std::string result;
509 dprintf(fd, "\nA2DP %s State:\n", name().c_str());
510 dprintf(fd, " Priority: %d\n", codecPriority());
511 dprintf(fd, " Encoder interval (ms): %" PRIu64 "\n", encoderIntervalMs());
512 dprintf(fd, " Effective MTU: %d\n", getEffectiveMtu());
513
514 result = codecConfig2Str(getCodecConfig());
515 dprintf(fd, " Config: %s\n", result.c_str());
516
517 result = codecConfig2Str(getCodecSelectableCapability());
518 dprintf(fd, " Selectable: %s\n", result.c_str());
519
520 result = codecConfig2Str(getCodecLocalCapability());
521 dprintf(fd, " Local capability: %s\n", result.c_str());
522 }
523
524 //
525 // Compares two codecs |lhs| and |rhs| based on their priority.
526 // Returns true if |lhs| has higher priority (larger priority value).
527 // If |lhs| and |rhs| have same priority, the unique codec index is used
528 // as a tie-breaker: larger codec index value means higher priority.
529 //
compare_codec_priority(const A2dpCodecConfig * lhs,const A2dpCodecConfig * rhs)530 static bool compare_codec_priority(const A2dpCodecConfig* lhs,
531 const A2dpCodecConfig* rhs) {
532 if (lhs->codecPriority() > rhs->codecPriority()) return true;
533 if (lhs->codecPriority() < rhs->codecPriority()) return false;
534 return (lhs->codecIndex() > rhs->codecIndex());
535 }
536
A2dpCodecs(const std::vector<btav_a2dp_codec_config_t> & codec_priorities)537 A2dpCodecs::A2dpCodecs(
538 const std::vector<btav_a2dp_codec_config_t>& codec_priorities)
539 : current_codec_config_(nullptr) {
540 for (auto config : codec_priorities) {
541 codec_priorities_.insert(
542 std::make_pair(config.codec_type, config.codec_priority));
543 }
544 }
545
~A2dpCodecs()546 A2dpCodecs::~A2dpCodecs() {
547 std::unique_lock<std::recursive_mutex> lock(codec_mutex_);
548 for (const auto& iter : indexed_codecs_) {
549 delete iter.second;
550 }
551 for (const auto& iter : disabled_codecs_) {
552 delete iter.second;
553 }
554 lock.unlock();
555 }
556
init()557 bool A2dpCodecs::init() {
558 LOG_DEBUG(LOG_TAG, "%s", __func__);
559 std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
560 char* tok = NULL;
561 char* tmp_token = NULL;
562 bool offload_codec_support[BTAV_A2DP_CODEC_INDEX_MAX] = {false};
563 char value_sup[PROPERTY_VALUE_MAX], value_dis[PROPERTY_VALUE_MAX];
564
565 osi_property_get("ro.bluetooth.a2dp_offload.supported", value_sup, "false");
566 osi_property_get("persist.bluetooth.a2dp_offload.disabled", value_dis,
567 "false");
568 a2dp_offload_status =
569 (strcmp(value_sup, "true") == 0) && (strcmp(value_dis, "false") == 0);
570
571 if (a2dp_offload_status) {
572 char value_cap[PROPERTY_VALUE_MAX];
573 osi_property_get("persist.bluetooth.a2dp_offload.cap", value_cap, "");
574 tok = strtok_r((char*)value_cap, "-", &tmp_token);
575 while (tok != NULL) {
576 if (strcmp(tok, "sbc") == 0) {
577 LOG_INFO(LOG_TAG, "%s: SBC offload supported", __func__);
578 offload_codec_support[BTAV_A2DP_CODEC_INDEX_SOURCE_SBC] = true;
579 } else if (strcmp(tok, "aac") == 0) {
580 LOG_INFO(LOG_TAG, "%s: AAC offload supported", __func__);
581 offload_codec_support[BTAV_A2DP_CODEC_INDEX_SOURCE_AAC] = true;
582 } else if (strcmp(tok, "aptx") == 0) {
583 LOG_INFO(LOG_TAG, "%s: APTX offload supported", __func__);
584 offload_codec_support[BTAV_A2DP_CODEC_INDEX_SOURCE_APTX] = true;
585 } else if (strcmp(tok, "aptxhd") == 0) {
586 LOG_INFO(LOG_TAG, "%s: APTXHD offload supported", __func__);
587 offload_codec_support[BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD] = true;
588 } else if (strcmp(tok, "ldac") == 0) {
589 LOG_INFO(LOG_TAG, "%s: LDAC offload supported", __func__);
590 offload_codec_support[BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC] = true;
591 }
592 tok = strtok_r(NULL, "-", &tmp_token);
593 };
594 }
595
596 for (int i = BTAV_A2DP_CODEC_INDEX_MIN; i < BTAV_A2DP_CODEC_INDEX_MAX; i++) {
597 btav_a2dp_codec_index_t codec_index =
598 static_cast<btav_a2dp_codec_index_t>(i);
599
600 // Select the codec priority if explicitly configured
601 btav_a2dp_codec_priority_t codec_priority =
602 BTAV_A2DP_CODEC_PRIORITY_DEFAULT;
603 auto cp_iter = codec_priorities_.find(codec_index);
604 if (cp_iter != codec_priorities_.end()) {
605 codec_priority = cp_iter->second;
606 }
607
608 // In offload mode, disable the codecs based on the property
609 if ((codec_index < BTAV_A2DP_CODEC_INDEX_SOURCE_MAX) &&
610 a2dp_offload_status && (offload_codec_support[i] != true)) {
611 codec_priority = BTAV_A2DP_CODEC_PRIORITY_DISABLED;
612 }
613
614 A2dpCodecConfig* codec_config =
615 A2dpCodecConfig::createCodec(codec_index, codec_priority);
616 if (codec_config == nullptr) continue;
617
618 if (codec_priority != BTAV_A2DP_CODEC_PRIORITY_DEFAULT) {
619 LOG_INFO(LOG_TAG, "%s: updated %s codec priority to %d", __func__,
620 codec_config->name().c_str(), codec_priority);
621 }
622
623 // Test if the codec is disabled
624 if (codec_config->codecPriority() == BTAV_A2DP_CODEC_PRIORITY_DISABLED) {
625 disabled_codecs_.insert(std::make_pair(codec_index, codec_config));
626 continue;
627 }
628
629 indexed_codecs_.insert(std::make_pair(codec_index, codec_config));
630
631 if (codec_index < BTAV_A2DP_CODEC_INDEX_SOURCE_MAX) {
632 ordered_source_codecs_.push_back(codec_config);
633 ordered_source_codecs_.sort(compare_codec_priority);
634 } else {
635 ordered_sink_codecs_.push_back(codec_config);
636 ordered_sink_codecs_.sort(compare_codec_priority);
637 }
638 }
639
640 if (ordered_source_codecs_.empty()) {
641 LOG_ERROR(LOG_TAG, "%s: no Source codecs were initialized", __func__);
642 } else {
643 for (auto iter : ordered_source_codecs_) {
644 LOG_INFO(LOG_TAG, "%s: initialized Source codec %s", __func__,
645 iter->name().c_str());
646 }
647 }
648 if (ordered_sink_codecs_.empty()) {
649 LOG_ERROR(LOG_TAG, "%s: no Sink codecs were initialized", __func__);
650 } else {
651 for (auto iter : ordered_sink_codecs_) {
652 LOG_INFO(LOG_TAG, "%s: initialized Sink codec %s", __func__,
653 iter->name().c_str());
654 }
655 }
656
657 return (!ordered_source_codecs_.empty() && !ordered_sink_codecs_.empty());
658 }
659
findSourceCodecConfig(const uint8_t * p_codec_info)660 A2dpCodecConfig* A2dpCodecs::findSourceCodecConfig(
661 const uint8_t* p_codec_info) {
662 std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
663 btav_a2dp_codec_index_t codec_index = A2DP_SourceCodecIndex(p_codec_info);
664 if (codec_index == BTAV_A2DP_CODEC_INDEX_MAX) return nullptr;
665
666 auto iter = indexed_codecs_.find(codec_index);
667 if (iter == indexed_codecs_.end()) return nullptr;
668 return iter->second;
669 }
670
findSinkCodecConfig(const uint8_t * p_codec_info)671 A2dpCodecConfig* A2dpCodecs::findSinkCodecConfig(const uint8_t* p_codec_info) {
672 std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
673 btav_a2dp_codec_index_t codec_index = A2DP_SinkCodecIndex(p_codec_info);
674 if (codec_index == BTAV_A2DP_CODEC_INDEX_MAX) return nullptr;
675
676 auto iter = indexed_codecs_.find(codec_index);
677 if (iter == indexed_codecs_.end()) return nullptr;
678 return iter->second;
679 }
680
isSupportedCodec(btav_a2dp_codec_index_t codec_index)681 bool A2dpCodecs::isSupportedCodec(btav_a2dp_codec_index_t codec_index) {
682 std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
683 return indexed_codecs_.find(codec_index) != indexed_codecs_.end();
684 }
685
setCodecConfig(const uint8_t * p_peer_codec_info,bool is_capability,uint8_t * p_result_codec_config,bool select_current_codec)686 bool A2dpCodecs::setCodecConfig(const uint8_t* p_peer_codec_info,
687 bool is_capability,
688 uint8_t* p_result_codec_config,
689 bool select_current_codec) {
690 std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
691 A2dpCodecConfig* a2dp_codec_config = findSourceCodecConfig(p_peer_codec_info);
692 if (a2dp_codec_config == nullptr) return false;
693 if (!a2dp_codec_config->setCodecConfig(p_peer_codec_info, is_capability,
694 p_result_codec_config)) {
695 return false;
696 }
697 if (select_current_codec) {
698 current_codec_config_ = a2dp_codec_config;
699 }
700 return true;
701 }
702
setSinkCodecConfig(const uint8_t * p_peer_codec_info,bool is_capability,uint8_t * p_result_codec_config,bool select_current_codec)703 bool A2dpCodecs::setSinkCodecConfig(const uint8_t* p_peer_codec_info,
704 bool is_capability,
705 uint8_t* p_result_codec_config,
706 bool select_current_codec) {
707 std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
708 A2dpCodecConfig* a2dp_codec_config = findSinkCodecConfig(p_peer_codec_info);
709 if (a2dp_codec_config == nullptr) return false;
710 if (!a2dp_codec_config->setCodecConfig(p_peer_codec_info, is_capability,
711 p_result_codec_config)) {
712 return false;
713 }
714 if (select_current_codec) {
715 current_codec_config_ = a2dp_codec_config;
716 }
717 return true;
718 }
719
setCodecUserConfig(const btav_a2dp_codec_config_t & codec_user_config,const tA2DP_ENCODER_INIT_PEER_PARAMS * p_peer_params,const uint8_t * p_peer_sink_capabilities,uint8_t * p_result_codec_config,bool * p_restart_input,bool * p_restart_output,bool * p_config_updated)720 bool A2dpCodecs::setCodecUserConfig(
721 const btav_a2dp_codec_config_t& codec_user_config,
722 const tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params,
723 const uint8_t* p_peer_sink_capabilities, uint8_t* p_result_codec_config,
724 bool* p_restart_input, bool* p_restart_output, bool* p_config_updated) {
725 std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
726 btav_a2dp_codec_config_t codec_audio_config;
727 A2dpCodecConfig* a2dp_codec_config = nullptr;
728 A2dpCodecConfig* last_codec_config = current_codec_config_;
729 *p_restart_input = false;
730 *p_restart_output = false;
731 *p_config_updated = false;
732
733 LOG_DEBUG(LOG_TAG, "%s: Configuring: %s", __func__,
734 codec_user_config.ToString().c_str());
735
736 if (codec_user_config.codec_type < BTAV_A2DP_CODEC_INDEX_MAX) {
737 auto iter = indexed_codecs_.find(codec_user_config.codec_type);
738 if (iter == indexed_codecs_.end()) goto fail;
739 a2dp_codec_config = iter->second;
740 } else {
741 // Update the default codec
742 a2dp_codec_config = current_codec_config_;
743 }
744 if (a2dp_codec_config == nullptr) goto fail;
745
746 // Reuse the existing codec audio config
747 codec_audio_config = a2dp_codec_config->getCodecAudioConfig();
748 if (!a2dp_codec_config->setCodecUserConfig(
749 codec_user_config, codec_audio_config, p_peer_params,
750 p_peer_sink_capabilities, true, p_result_codec_config,
751 p_restart_input, p_restart_output, p_config_updated)) {
752 goto fail;
753 }
754
755 // Update the codec priorities, and eventually restart the connection
756 // if a new codec needs to be selected.
757 do {
758 // Update the codec priority
759 btav_a2dp_codec_priority_t old_priority =
760 a2dp_codec_config->codecPriority();
761 btav_a2dp_codec_priority_t new_priority = codec_user_config.codec_priority;
762 a2dp_codec_config->setCodecPriority(new_priority);
763 // Get the actual (recomputed) priority
764 new_priority = a2dp_codec_config->codecPriority();
765
766 // Check if there was no previous codec
767 if (last_codec_config == nullptr) {
768 current_codec_config_ = a2dp_codec_config;
769 *p_restart_input = true;
770 *p_restart_output = true;
771 break;
772 }
773
774 // Check if the priority of the current codec was updated
775 if (a2dp_codec_config == last_codec_config) {
776 if (old_priority == new_priority) break; // No change in priority
777
778 *p_config_updated = true;
779 if (new_priority < old_priority) {
780 // The priority has become lower - restart the connection to
781 // select a new codec.
782 *p_restart_output = true;
783 }
784 break;
785 }
786
787 if (new_priority <= old_priority) {
788 // No change in priority, or the priority has become lower.
789 // This wasn't the current codec, so we shouldn't select a new codec.
790 if (*p_restart_input || *p_restart_output ||
791 (old_priority != new_priority)) {
792 *p_config_updated = true;
793 }
794 *p_restart_input = false;
795 *p_restart_output = false;
796 break;
797 }
798
799 *p_config_updated = true;
800 if (new_priority >= last_codec_config->codecPriority()) {
801 // The new priority is higher than the current codec. Restart the
802 // connection to select a new codec.
803 current_codec_config_ = a2dp_codec_config;
804 last_codec_config->setDefaultCodecPriority();
805 *p_restart_input = true;
806 *p_restart_output = true;
807 }
808 } while (false);
809 ordered_source_codecs_.sort(compare_codec_priority);
810
811 if (*p_restart_input || *p_restart_output) *p_config_updated = true;
812
813 LOG_DEBUG(LOG_TAG,
814 "%s: Configured: restart_input = %d restart_output = %d "
815 "config_updated = %d",
816 __func__, *p_restart_input, *p_restart_output, *p_config_updated);
817
818 return true;
819
820 fail:
821 current_codec_config_ = last_codec_config;
822 return false;
823 }
824
setCodecAudioConfig(const btav_a2dp_codec_config_t & codec_audio_config,const tA2DP_ENCODER_INIT_PEER_PARAMS * p_peer_params,const uint8_t * p_peer_sink_capabilities,uint8_t * p_result_codec_config,bool * p_restart_output,bool * p_config_updated)825 bool A2dpCodecs::setCodecAudioConfig(
826 const btav_a2dp_codec_config_t& codec_audio_config,
827 const tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params,
828 const uint8_t* p_peer_sink_capabilities, uint8_t* p_result_codec_config,
829 bool* p_restart_output, bool* p_config_updated) {
830 std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
831 btav_a2dp_codec_config_t codec_user_config;
832 A2dpCodecConfig* a2dp_codec_config = current_codec_config_;
833 *p_restart_output = false;
834 *p_config_updated = false;
835
836 if (a2dp_codec_config == nullptr) return false;
837
838 // Reuse the existing codec user config
839 codec_user_config = a2dp_codec_config->getCodecUserConfig();
840 bool restart_input = false; // Flag ignored - input was just restarted
841 if (!a2dp_codec_config->setCodecUserConfig(
842 codec_user_config, codec_audio_config, p_peer_params,
843 p_peer_sink_capabilities, true, p_result_codec_config, &restart_input,
844 p_restart_output, p_config_updated)) {
845 return false;
846 }
847
848 return true;
849 }
850
setCodecOtaConfig(const uint8_t * p_ota_codec_config,const tA2DP_ENCODER_INIT_PEER_PARAMS * p_peer_params,uint8_t * p_result_codec_config,bool * p_restart_input,bool * p_restart_output,bool * p_config_updated)851 bool A2dpCodecs::setCodecOtaConfig(
852 const uint8_t* p_ota_codec_config,
853 const tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params,
854 uint8_t* p_result_codec_config, bool* p_restart_input,
855 bool* p_restart_output, bool* p_config_updated) {
856 std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
857 btav_a2dp_codec_index_t codec_type;
858 btav_a2dp_codec_config_t codec_user_config;
859 btav_a2dp_codec_config_t codec_audio_config;
860 A2dpCodecConfig* a2dp_codec_config = nullptr;
861 A2dpCodecConfig* last_codec_config = current_codec_config_;
862 *p_restart_input = false;
863 *p_restart_output = false;
864 *p_config_updated = false;
865
866 // Check whether the current codec config is explicitly configured by
867 // user configuration. If yes, then the OTA codec configuration is ignored.
868 if (current_codec_config_ != nullptr) {
869 codec_user_config = current_codec_config_->getCodecUserConfig();
870 if (!A2dpCodecConfig::isCodecConfigEmpty(codec_user_config)) {
871 LOG_WARN(LOG_TAG,
872 "%s: ignoring peer OTA configuration for codec %s: "
873 "existing user configuration for current codec %s",
874 __func__, A2DP_CodecName(p_ota_codec_config),
875 current_codec_config_->name().c_str());
876 goto fail;
877 }
878 }
879
880 // Check whether the codec config for the same codec is explicitly configured
881 // by user configuration. If yes, then the OTA codec configuration is
882 // ignored.
883 codec_type = A2DP_SourceCodecIndex(p_ota_codec_config);
884 if (codec_type == BTAV_A2DP_CODEC_INDEX_MAX) {
885 LOG_WARN(LOG_TAG,
886 "%s: ignoring peer OTA codec configuration: "
887 "invalid codec",
888 __func__);
889 goto fail; // Invalid codec
890 } else {
891 auto iter = indexed_codecs_.find(codec_type);
892 if (iter == indexed_codecs_.end()) {
893 LOG_WARN(LOG_TAG,
894 "%s: cannot find codec configuration for peer OTA codec %s",
895 __func__, A2DP_CodecName(p_ota_codec_config));
896 goto fail;
897 }
898 a2dp_codec_config = iter->second;
899 }
900 if (a2dp_codec_config == nullptr) goto fail;
901 codec_user_config = a2dp_codec_config->getCodecUserConfig();
902 if (!A2dpCodecConfig::isCodecConfigEmpty(codec_user_config)) {
903 LOG_WARN(LOG_TAG,
904 "%s: ignoring peer OTA configuration for codec %s: "
905 "existing user configuration for same codec",
906 __func__, A2DP_CodecName(p_ota_codec_config));
907 goto fail;
908 }
909 current_codec_config_ = a2dp_codec_config;
910
911 // Reuse the existing codec user config and codec audio config
912 codec_audio_config = a2dp_codec_config->getCodecAudioConfig();
913 if (!a2dp_codec_config->setCodecUserConfig(
914 codec_user_config, codec_audio_config, p_peer_params,
915 p_ota_codec_config, false, p_result_codec_config, p_restart_input,
916 p_restart_output, p_config_updated)) {
917 LOG_WARN(LOG_TAG,
918 "%s: cannot set codec configuration for peer OTA codec %s",
919 __func__, A2DP_CodecName(p_ota_codec_config));
920 goto fail;
921 }
922 CHECK(current_codec_config_ != nullptr);
923
924 if (*p_restart_input || *p_restart_output) *p_config_updated = true;
925
926 return true;
927
928 fail:
929 current_codec_config_ = last_codec_config;
930 return false;
931 }
932
setPeerSinkCodecCapabilities(const uint8_t * p_peer_codec_capabilities)933 bool A2dpCodecs::setPeerSinkCodecCapabilities(
934 const uint8_t* p_peer_codec_capabilities) {
935 std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
936
937 if (!A2DP_IsPeerSinkCodecValid(p_peer_codec_capabilities)) return false;
938 A2dpCodecConfig* a2dp_codec_config =
939 findSourceCodecConfig(p_peer_codec_capabilities);
940 if (a2dp_codec_config == nullptr) return false;
941 return a2dp_codec_config->setPeerCodecCapabilities(p_peer_codec_capabilities);
942 }
943
setPeerSourceCodecCapabilities(const uint8_t * p_peer_codec_capabilities)944 bool A2dpCodecs::setPeerSourceCodecCapabilities(
945 const uint8_t* p_peer_codec_capabilities) {
946 std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
947
948 if (!A2DP_IsPeerSourceCodecValid(p_peer_codec_capabilities)) return false;
949 A2dpCodecConfig* a2dp_codec_config =
950 findSinkCodecConfig(p_peer_codec_capabilities);
951 if (a2dp_codec_config == nullptr) return false;
952 return a2dp_codec_config->setPeerCodecCapabilities(p_peer_codec_capabilities);
953 }
954
getCodecConfigAndCapabilities(btav_a2dp_codec_config_t * p_codec_config,std::vector<btav_a2dp_codec_config_t> * p_codecs_local_capabilities,std::vector<btav_a2dp_codec_config_t> * p_codecs_selectable_capabilities)955 bool A2dpCodecs::getCodecConfigAndCapabilities(
956 btav_a2dp_codec_config_t* p_codec_config,
957 std::vector<btav_a2dp_codec_config_t>* p_codecs_local_capabilities,
958 std::vector<btav_a2dp_codec_config_t>* p_codecs_selectable_capabilities) {
959 std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
960
961 if (current_codec_config_ != nullptr) {
962 *p_codec_config = current_codec_config_->getCodecConfig();
963 } else {
964 btav_a2dp_codec_config_t codec_config;
965 memset(&codec_config, 0, sizeof(codec_config));
966 *p_codec_config = codec_config;
967 }
968
969 std::vector<btav_a2dp_codec_config_t> codecs_capabilities;
970 for (auto codec : orderedSourceCodecs()) {
971 codecs_capabilities.push_back(codec->getCodecLocalCapability());
972 }
973 *p_codecs_local_capabilities = codecs_capabilities;
974
975 codecs_capabilities.clear();
976 for (auto codec : orderedSourceCodecs()) {
977 btav_a2dp_codec_config_t codec_capability =
978 codec->getCodecSelectableCapability();
979 // Don't add entries that cannot be used
980 if ((codec_capability.sample_rate == BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) ||
981 (codec_capability.bits_per_sample ==
982 BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE) ||
983 (codec_capability.channel_mode == BTAV_A2DP_CODEC_CHANNEL_MODE_NONE)) {
984 continue;
985 }
986 codecs_capabilities.push_back(codec_capability);
987 }
988 *p_codecs_selectable_capabilities = codecs_capabilities;
989
990 return true;
991 }
992
debug_codec_dump(int fd)993 void A2dpCodecs::debug_codec_dump(int fd) {
994 std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
995 dprintf(fd, "\nA2DP Codecs State:\n");
996
997 // Print the current codec name
998 if (current_codec_config_ != nullptr) {
999 dprintf(fd, " Current Codec: %s\n", current_codec_config_->name().c_str());
1000 } else {
1001 dprintf(fd, " Current Codec: None\n");
1002 }
1003
1004 // Print the codec-specific state
1005 for (auto codec_config : ordered_source_codecs_) {
1006 codec_config->debug_codec_dump(fd);
1007 }
1008 }
1009
A2DP_GetCodecType(const uint8_t * p_codec_info)1010 tA2DP_CODEC_TYPE A2DP_GetCodecType(const uint8_t* p_codec_info) {
1011 return (tA2DP_CODEC_TYPE)(p_codec_info[AVDT_CODEC_TYPE_INDEX]);
1012 }
1013
A2DP_IsSourceCodecValid(const uint8_t * p_codec_info)1014 bool A2DP_IsSourceCodecValid(const uint8_t* p_codec_info) {
1015 tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1016
1017 LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
1018
1019 switch (codec_type) {
1020 case A2DP_MEDIA_CT_SBC:
1021 return A2DP_IsSourceCodecValidSbc(p_codec_info);
1022 case A2DP_MEDIA_CT_AAC:
1023 return A2DP_IsSourceCodecValidAac(p_codec_info);
1024 case A2DP_MEDIA_CT_NON_A2DP:
1025 return A2DP_IsVendorSourceCodecValid(p_codec_info);
1026 default:
1027 break;
1028 }
1029
1030 return false;
1031 }
1032
A2DP_IsSinkCodecValid(const uint8_t * p_codec_info)1033 bool A2DP_IsSinkCodecValid(const uint8_t* p_codec_info) {
1034 tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1035
1036 LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
1037
1038 switch (codec_type) {
1039 case A2DP_MEDIA_CT_SBC:
1040 return A2DP_IsSinkCodecValidSbc(p_codec_info);
1041 case A2DP_MEDIA_CT_AAC:
1042 return A2DP_IsSinkCodecValidAac(p_codec_info);
1043 case A2DP_MEDIA_CT_NON_A2DP:
1044 return A2DP_IsVendorSinkCodecValid(p_codec_info);
1045 default:
1046 break;
1047 }
1048
1049 return false;
1050 }
1051
A2DP_IsPeerSourceCodecValid(const uint8_t * p_codec_info)1052 bool A2DP_IsPeerSourceCodecValid(const uint8_t* p_codec_info) {
1053 tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1054
1055 LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
1056
1057 switch (codec_type) {
1058 case A2DP_MEDIA_CT_SBC:
1059 return A2DP_IsPeerSourceCodecValidSbc(p_codec_info);
1060 case A2DP_MEDIA_CT_AAC:
1061 return A2DP_IsPeerSourceCodecValidAac(p_codec_info);
1062 case A2DP_MEDIA_CT_NON_A2DP:
1063 return A2DP_IsVendorPeerSourceCodecValid(p_codec_info);
1064 default:
1065 break;
1066 }
1067
1068 return false;
1069 }
1070
A2DP_IsPeerSinkCodecValid(const uint8_t * p_codec_info)1071 bool A2DP_IsPeerSinkCodecValid(const uint8_t* p_codec_info) {
1072 tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1073
1074 LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
1075
1076 switch (codec_type) {
1077 case A2DP_MEDIA_CT_SBC:
1078 return A2DP_IsPeerSinkCodecValidSbc(p_codec_info);
1079 case A2DP_MEDIA_CT_AAC:
1080 return A2DP_IsPeerSinkCodecValidAac(p_codec_info);
1081 case A2DP_MEDIA_CT_NON_A2DP:
1082 return A2DP_IsVendorPeerSinkCodecValid(p_codec_info);
1083 default:
1084 break;
1085 }
1086
1087 return false;
1088 }
1089
A2DP_IsSinkCodecSupported(const uint8_t * p_codec_info)1090 bool A2DP_IsSinkCodecSupported(const uint8_t* p_codec_info) {
1091 tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1092
1093 LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
1094
1095 switch (codec_type) {
1096 case A2DP_MEDIA_CT_SBC:
1097 return A2DP_IsSinkCodecSupportedSbc(p_codec_info);
1098 case A2DP_MEDIA_CT_AAC:
1099 return A2DP_IsSinkCodecSupportedAac(p_codec_info);
1100 case A2DP_MEDIA_CT_NON_A2DP:
1101 return A2DP_IsVendorSinkCodecSupported(p_codec_info);
1102 default:
1103 break;
1104 }
1105
1106 LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
1107 return false;
1108 }
1109
A2DP_IsPeerSourceCodecSupported(const uint8_t * p_codec_info)1110 bool A2DP_IsPeerSourceCodecSupported(const uint8_t* p_codec_info) {
1111 tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1112
1113 LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
1114
1115 switch (codec_type) {
1116 case A2DP_MEDIA_CT_SBC:
1117 return A2DP_IsPeerSourceCodecSupportedSbc(p_codec_info);
1118 case A2DP_MEDIA_CT_AAC:
1119 return A2DP_IsPeerSourceCodecSupportedAac(p_codec_info);
1120 case A2DP_MEDIA_CT_NON_A2DP:
1121 return A2DP_IsVendorPeerSourceCodecSupported(p_codec_info);
1122 default:
1123 break;
1124 }
1125
1126 LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
1127 return false;
1128 }
1129
A2DP_InitDefaultCodec(uint8_t * p_codec_info)1130 void A2DP_InitDefaultCodec(uint8_t* p_codec_info) {
1131 A2DP_InitDefaultCodecSbc(p_codec_info);
1132 }
1133
A2DP_UsesRtpHeader(bool content_protection_enabled,const uint8_t * p_codec_info)1134 bool A2DP_UsesRtpHeader(bool content_protection_enabled,
1135 const uint8_t* p_codec_info) {
1136 tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1137
1138 if (codec_type != A2DP_MEDIA_CT_NON_A2DP) return true;
1139
1140 return A2DP_VendorUsesRtpHeader(content_protection_enabled, p_codec_info);
1141 }
1142
A2DP_GetMediaType(const uint8_t * p_codec_info)1143 uint8_t A2DP_GetMediaType(const uint8_t* p_codec_info) {
1144 uint8_t media_type = (p_codec_info[A2DP_MEDIA_TYPE_OFFSET] >> 4) & 0x0f;
1145 return media_type;
1146 }
1147
A2DP_CodecName(const uint8_t * p_codec_info)1148 const char* A2DP_CodecName(const uint8_t* p_codec_info) {
1149 tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1150
1151 LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
1152
1153 switch (codec_type) {
1154 case A2DP_MEDIA_CT_SBC:
1155 return A2DP_CodecNameSbc(p_codec_info);
1156 case A2DP_MEDIA_CT_AAC:
1157 return A2DP_CodecNameAac(p_codec_info);
1158 case A2DP_MEDIA_CT_NON_A2DP:
1159 return A2DP_VendorCodecName(p_codec_info);
1160 default:
1161 break;
1162 }
1163
1164 LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
1165 return "UNKNOWN CODEC";
1166 }
1167
A2DP_CodecTypeEquals(const uint8_t * p_codec_info_a,const uint8_t * p_codec_info_b)1168 bool A2DP_CodecTypeEquals(const uint8_t* p_codec_info_a,
1169 const uint8_t* p_codec_info_b) {
1170 tA2DP_CODEC_TYPE codec_type_a = A2DP_GetCodecType(p_codec_info_a);
1171 tA2DP_CODEC_TYPE codec_type_b = A2DP_GetCodecType(p_codec_info_b);
1172
1173 if (codec_type_a != codec_type_b) return false;
1174
1175 switch (codec_type_a) {
1176 case A2DP_MEDIA_CT_SBC:
1177 return A2DP_CodecTypeEqualsSbc(p_codec_info_a, p_codec_info_b);
1178 case A2DP_MEDIA_CT_AAC:
1179 return A2DP_CodecTypeEqualsAac(p_codec_info_a, p_codec_info_b);
1180 case A2DP_MEDIA_CT_NON_A2DP:
1181 return A2DP_VendorCodecTypeEquals(p_codec_info_a, p_codec_info_b);
1182 default:
1183 break;
1184 }
1185
1186 LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type_a);
1187 return false;
1188 }
1189
A2DP_CodecEquals(const uint8_t * p_codec_info_a,const uint8_t * p_codec_info_b)1190 bool A2DP_CodecEquals(const uint8_t* p_codec_info_a,
1191 const uint8_t* p_codec_info_b) {
1192 tA2DP_CODEC_TYPE codec_type_a = A2DP_GetCodecType(p_codec_info_a);
1193 tA2DP_CODEC_TYPE codec_type_b = A2DP_GetCodecType(p_codec_info_b);
1194
1195 if (codec_type_a != codec_type_b) return false;
1196
1197 switch (codec_type_a) {
1198 case A2DP_MEDIA_CT_SBC:
1199 return A2DP_CodecEqualsSbc(p_codec_info_a, p_codec_info_b);
1200 case A2DP_MEDIA_CT_AAC:
1201 return A2DP_CodecEqualsAac(p_codec_info_a, p_codec_info_b);
1202 case A2DP_MEDIA_CT_NON_A2DP:
1203 return A2DP_VendorCodecEquals(p_codec_info_a, p_codec_info_b);
1204 default:
1205 break;
1206 }
1207
1208 LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type_a);
1209 return false;
1210 }
1211
A2DP_GetTrackSampleRate(const uint8_t * p_codec_info)1212 int A2DP_GetTrackSampleRate(const uint8_t* p_codec_info) {
1213 tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1214
1215 LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
1216
1217 switch (codec_type) {
1218 case A2DP_MEDIA_CT_SBC:
1219 return A2DP_GetTrackSampleRateSbc(p_codec_info);
1220 case A2DP_MEDIA_CT_AAC:
1221 return A2DP_GetTrackSampleRateAac(p_codec_info);
1222 case A2DP_MEDIA_CT_NON_A2DP:
1223 return A2DP_VendorGetTrackSampleRate(p_codec_info);
1224 default:
1225 break;
1226 }
1227
1228 LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
1229 return -1;
1230 }
1231
A2DP_GetTrackBitsPerSample(const uint8_t * p_codec_info)1232 int A2DP_GetTrackBitsPerSample(const uint8_t* p_codec_info) {
1233 tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1234
1235 LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
1236
1237 switch (codec_type) {
1238 case A2DP_MEDIA_CT_SBC:
1239 return A2DP_GetTrackBitsPerSampleSbc(p_codec_info);
1240 case A2DP_MEDIA_CT_AAC:
1241 return A2DP_GetTrackBitsPerSampleAac(p_codec_info);
1242 case A2DP_MEDIA_CT_NON_A2DP:
1243 return A2DP_VendorGetTrackBitsPerSample(p_codec_info);
1244 default:
1245 break;
1246 }
1247
1248 LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
1249 return -1;
1250 }
1251
A2DP_GetTrackChannelCount(const uint8_t * p_codec_info)1252 int A2DP_GetTrackChannelCount(const uint8_t* p_codec_info) {
1253 tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1254
1255 LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
1256
1257 switch (codec_type) {
1258 case A2DP_MEDIA_CT_SBC:
1259 return A2DP_GetTrackChannelCountSbc(p_codec_info);
1260 case A2DP_MEDIA_CT_AAC:
1261 return A2DP_GetTrackChannelCountAac(p_codec_info);
1262 case A2DP_MEDIA_CT_NON_A2DP:
1263 return A2DP_VendorGetTrackChannelCount(p_codec_info);
1264 default:
1265 break;
1266 }
1267
1268 LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
1269 return -1;
1270 }
1271
A2DP_GetSinkTrackChannelType(const uint8_t * p_codec_info)1272 int A2DP_GetSinkTrackChannelType(const uint8_t* p_codec_info) {
1273 tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1274
1275 LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
1276
1277 switch (codec_type) {
1278 case A2DP_MEDIA_CT_SBC:
1279 return A2DP_GetSinkTrackChannelTypeSbc(p_codec_info);
1280 case A2DP_MEDIA_CT_AAC:
1281 return A2DP_GetSinkTrackChannelTypeAac(p_codec_info);
1282 case A2DP_MEDIA_CT_NON_A2DP:
1283 return A2DP_VendorGetSinkTrackChannelType(p_codec_info);
1284 default:
1285 break;
1286 }
1287
1288 LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
1289 return -1;
1290 }
1291
A2DP_GetPacketTimestamp(const uint8_t * p_codec_info,const uint8_t * p_data,uint32_t * p_timestamp)1292 bool A2DP_GetPacketTimestamp(const uint8_t* p_codec_info, const uint8_t* p_data,
1293 uint32_t* p_timestamp) {
1294 tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1295
1296 switch (codec_type) {
1297 case A2DP_MEDIA_CT_SBC:
1298 return A2DP_GetPacketTimestampSbc(p_codec_info, p_data, p_timestamp);
1299 case A2DP_MEDIA_CT_AAC:
1300 return A2DP_GetPacketTimestampAac(p_codec_info, p_data, p_timestamp);
1301 case A2DP_MEDIA_CT_NON_A2DP:
1302 return A2DP_VendorGetPacketTimestamp(p_codec_info, p_data, p_timestamp);
1303 default:
1304 break;
1305 }
1306
1307 LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
1308 return false;
1309 }
1310
A2DP_BuildCodecHeader(const uint8_t * p_codec_info,BT_HDR * p_buf,uint16_t frames_per_packet)1311 bool A2DP_BuildCodecHeader(const uint8_t* p_codec_info, BT_HDR* p_buf,
1312 uint16_t frames_per_packet) {
1313 tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1314
1315 switch (codec_type) {
1316 case A2DP_MEDIA_CT_SBC:
1317 return A2DP_BuildCodecHeaderSbc(p_codec_info, p_buf, frames_per_packet);
1318 case A2DP_MEDIA_CT_AAC:
1319 return A2DP_BuildCodecHeaderAac(p_codec_info, p_buf, frames_per_packet);
1320 case A2DP_MEDIA_CT_NON_A2DP:
1321 return A2DP_VendorBuildCodecHeader(p_codec_info, p_buf,
1322 frames_per_packet);
1323 default:
1324 break;
1325 }
1326
1327 LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
1328 return false;
1329 }
1330
A2DP_GetEncoderInterface(const uint8_t * p_codec_info)1331 const tA2DP_ENCODER_INTERFACE* A2DP_GetEncoderInterface(
1332 const uint8_t* p_codec_info) {
1333 tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1334
1335 LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
1336
1337 switch (codec_type) {
1338 case A2DP_MEDIA_CT_SBC:
1339 return A2DP_GetEncoderInterfaceSbc(p_codec_info);
1340 case A2DP_MEDIA_CT_AAC:
1341 return A2DP_GetEncoderInterfaceAac(p_codec_info);
1342 case A2DP_MEDIA_CT_NON_A2DP:
1343 return A2DP_VendorGetEncoderInterface(p_codec_info);
1344 default:
1345 break;
1346 }
1347
1348 LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
1349 return NULL;
1350 }
1351
A2DP_GetDecoderInterface(const uint8_t * p_codec_info)1352 const tA2DP_DECODER_INTERFACE* A2DP_GetDecoderInterface(
1353 const uint8_t* p_codec_info) {
1354 tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1355
1356 LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
1357
1358 switch (codec_type) {
1359 case A2DP_MEDIA_CT_SBC:
1360 return A2DP_GetDecoderInterfaceSbc(p_codec_info);
1361 case A2DP_MEDIA_CT_AAC:
1362 return A2DP_GetDecoderInterfaceAac(p_codec_info);
1363 case A2DP_MEDIA_CT_NON_A2DP:
1364 return A2DP_VendorGetDecoderInterface(p_codec_info);
1365 default:
1366 break;
1367 }
1368
1369 LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
1370 return NULL;
1371 }
1372
A2DP_AdjustCodec(uint8_t * p_codec_info)1373 bool A2DP_AdjustCodec(uint8_t* p_codec_info) {
1374 tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1375
1376 switch (codec_type) {
1377 case A2DP_MEDIA_CT_SBC:
1378 return A2DP_AdjustCodecSbc(p_codec_info);
1379 case A2DP_MEDIA_CT_AAC:
1380 return A2DP_AdjustCodecAac(p_codec_info);
1381 case A2DP_MEDIA_CT_NON_A2DP:
1382 return A2DP_VendorAdjustCodec(p_codec_info);
1383 default:
1384 break;
1385 }
1386
1387 LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
1388 return false;
1389 }
1390
A2DP_SourceCodecIndex(const uint8_t * p_codec_info)1391 btav_a2dp_codec_index_t A2DP_SourceCodecIndex(const uint8_t* p_codec_info) {
1392 tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1393
1394 LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
1395
1396 switch (codec_type) {
1397 case A2DP_MEDIA_CT_SBC:
1398 return A2DP_SourceCodecIndexSbc(p_codec_info);
1399 case A2DP_MEDIA_CT_AAC:
1400 return A2DP_SourceCodecIndexAac(p_codec_info);
1401 case A2DP_MEDIA_CT_NON_A2DP:
1402 return A2DP_VendorSourceCodecIndex(p_codec_info);
1403 default:
1404 break;
1405 }
1406
1407 LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
1408 return BTAV_A2DP_CODEC_INDEX_MAX;
1409 }
1410
A2DP_SinkCodecIndex(const uint8_t * p_codec_info)1411 btav_a2dp_codec_index_t A2DP_SinkCodecIndex(const uint8_t* p_codec_info) {
1412 tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1413
1414 LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
1415
1416 switch (codec_type) {
1417 case A2DP_MEDIA_CT_SBC:
1418 return A2DP_SinkCodecIndexSbc(p_codec_info);
1419 case A2DP_MEDIA_CT_AAC:
1420 return A2DP_SinkCodecIndexAac(p_codec_info);
1421 case A2DP_MEDIA_CT_NON_A2DP:
1422 return A2DP_VendorSinkCodecIndex(p_codec_info);
1423 default:
1424 break;
1425 }
1426
1427 LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
1428 return BTAV_A2DP_CODEC_INDEX_MAX;
1429 }
1430
A2DP_CodecIndexStr(btav_a2dp_codec_index_t codec_index)1431 const char* A2DP_CodecIndexStr(btav_a2dp_codec_index_t codec_index) {
1432 switch (codec_index) {
1433 case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
1434 return A2DP_CodecIndexStrSbc();
1435 case BTAV_A2DP_CODEC_INDEX_SINK_SBC:
1436 return A2DP_CodecIndexStrSbcSink();
1437 case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC:
1438 return A2DP_CodecIndexStrAac();
1439 case BTAV_A2DP_CODEC_INDEX_SINK_AAC:
1440 return A2DP_CodecIndexStrAacSink();
1441 default:
1442 break;
1443 }
1444
1445 if (codec_index < BTAV_A2DP_CODEC_INDEX_MAX)
1446 return A2DP_VendorCodecIndexStr(codec_index);
1447
1448 return "UNKNOWN CODEC INDEX";
1449 }
1450
A2DP_InitCodecConfig(btav_a2dp_codec_index_t codec_index,AvdtpSepConfig * p_cfg)1451 bool A2DP_InitCodecConfig(btav_a2dp_codec_index_t codec_index,
1452 AvdtpSepConfig* p_cfg) {
1453 LOG_VERBOSE(LOG_TAG, "%s: codec %s", __func__,
1454 A2DP_CodecIndexStr(codec_index));
1455
1456 /* Default: no content protection info */
1457 p_cfg->num_protect = 0;
1458 p_cfg->protect_info[0] = 0;
1459
1460 switch (codec_index) {
1461 case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
1462 return A2DP_InitCodecConfigSbc(p_cfg);
1463 case BTAV_A2DP_CODEC_INDEX_SINK_SBC:
1464 return A2DP_InitCodecConfigSbcSink(p_cfg);
1465 case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC:
1466 return A2DP_InitCodecConfigAac(p_cfg);
1467 case BTAV_A2DP_CODEC_INDEX_SINK_AAC:
1468 return A2DP_InitCodecConfigAacSink(p_cfg);
1469 default:
1470 break;
1471 }
1472
1473 if (codec_index < BTAV_A2DP_CODEC_INDEX_MAX)
1474 return A2DP_VendorInitCodecConfig(codec_index, p_cfg);
1475
1476 return false;
1477 }
1478
A2DP_CodecInfoString(const uint8_t * p_codec_info)1479 std::string A2DP_CodecInfoString(const uint8_t* p_codec_info) {
1480 tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1481
1482 switch (codec_type) {
1483 case A2DP_MEDIA_CT_SBC:
1484 return A2DP_CodecInfoStringSbc(p_codec_info);
1485 case A2DP_MEDIA_CT_AAC:
1486 return A2DP_CodecInfoStringAac(p_codec_info);
1487 case A2DP_MEDIA_CT_NON_A2DP:
1488 return A2DP_VendorCodecInfoString(p_codec_info);
1489 default:
1490 break;
1491 }
1492
1493 return "Unsupported codec type: " + loghex(codec_type);
1494 }
1495