From 826d18c87c5588178295609cd1f5e3d2eb3901cf Mon Sep 17 00:00:00 2001 From: yangfeng Date: Mon, 17 Aug 2026 16:53:09 +0800 Subject: [PATCH] fix(bt): Fix the processing of bit rate being 0 in A2DP AAC --- .../bt/host/bluedroid/bta/av/bta_av_m24.c | 28 ++++++++++--------- .../bluedroid/bta/include/bta/bta_av_m24.h | 13 +++++++++ .../btc/profile/std/a2dp/bta_av_co.c | 8 ++++-- 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/components/bt/host/bluedroid/bta/av/bta_av_m24.c b/components/bt/host/bluedroid/bta/av/bta_av_m24.c index fc5330e302b..23fb80359c6 100644 --- a/components/bt/host/bluedroid/bta/av/bta_av_m24.c +++ b/components/bt/host/bluedroid/bta/av/bta_av_m24.c @@ -53,6 +53,18 @@ void bta_av_m24_set_br_info(UINT8 *codec_info, UINT32 bit_rate) codec_info[BTA_AV_M24_BR3_OFF] = (UINT8)(bit_rate & A2D_M24_IE_BR3_MSK); } +UINT32 bta_av_m24_br_min(UINT32 br1, UINT32 br2) +{ + /* A2DP MPEG-2/4 AAC: bit rate 0 means "not known", not an upper bound of 0. */ + if (br1 == 0) { + return br2; + } + if (br2 == 0) { + return br1; + } + return (br1 < br2) ? br1 : br2; +} + UINT8 bta_av_m24_cap_matches_cap(UINT8 *p_cap1, UINT8 *p_cap2) { tA2D_M24_CIE cap1; @@ -62,8 +74,6 @@ UINT8 bta_av_m24_cap_matches_cap(UINT8 *p_cap1, UINT8 *p_cap2) UINT8 cap2_sf1; UINT8 cap1_sf2; UINT8 cap2_sf2; - UINT32 cap1_br; - UINT32 cap2_br; st = A2D_ParsM24Info(&cap1, p_cap1, TRUE); if (st != A2D_SUCCESS) { @@ -90,13 +100,6 @@ UINT8 bta_av_m24_cap_matches_cap(UINT8 *p_cap1, UINT8 *p_cap2) return A2D_NS_CHANNEL; } - cap1_br = bta_av_m24_br(&cap1); - cap2_br = bta_av_m24_br(&cap2); - - if (!cap1_br || !cap2_br) { - return A2D_NS_BIT_RATE; - } - return A2D_SUCCESS; } @@ -147,7 +150,8 @@ UINT8 bta_av_m24_cfg_in_external_codec_cap(UINT8 *p_cfg, UINT8 *p_cap) cfg_br = bta_av_m24_br(&cfg); cap_br = bta_av_m24_br(&cap); - if (cfg_br > cap_br) { + /* Cap 0 = unknown/unlimited; cfg 0 = bit rate not known in SetConfiguration. */ + if (cap_br != 0 && cfg_br > cap_br) { return A2D_NS_BIT_RATE; } @@ -243,9 +247,7 @@ got_sf: src_br_max = bta_av_m24_br(src_cap); p_pref_br = bta_av_m24_br(p_pref); - if (p_pref_br > src_br_max) { - p_pref_br = src_br_max; - } + p_pref_br = bta_av_m24_br_min(p_pref_br, src_br_max); bta_av_m24_set_br(p_pref, p_pref_br, (UINT8)(p_pref->vbr & A2D_M24_IE_VBR_MSK)); diff --git a/components/bt/host/bluedroid/bta/include/bta/bta_av_m24.h b/components/bt/host/bluedroid/bta/include/bta/bta_av_m24.h index a67eb0c3711..5754f7abff6 100644 --- a/components/bt/host/bluedroid/bta/include/bta/bta_av_m24.h +++ b/components/bt/host/bluedroid/bta/include/bta/bta_av_m24.h @@ -41,6 +41,19 @@ extern UINT32 bta_av_m24_br_info(const UINT8 *codec_info); *******************************************************************************/ extern void bta_av_m24_set_br_info(UINT8 *codec_info, UINT32 bit_rate); +/******************************************************************************* +** +** Function bta_av_m24_br_min +** +** Description Select the negotiated AAC bit rate from two values. +** Per A2DP, bit rate 0 means "not known" (no upper bound), +** so it is ignored when the other value is non-zero. +** +** Returns Negotiated bit rate (0 only if both inputs are 0). +** +*******************************************************************************/ +extern UINT32 bta_av_m24_br_min(UINT32 br1, UINT32 br2); + /******************************************************************************* ** ** Function bta_av_m24_cap_matches_cap diff --git a/components/bt/host/bluedroid/btc/profile/std/a2dp/bta_av_co.c b/components/bt/host/bluedroid/btc/profile/std/a2dp/bta_av_co.c index 6f94a19d997..874bc0945ee 100644 --- a/components/bt/host/bluedroid/btc/profile/std/a2dp/bta_av_co.c +++ b/components/bt/host/bluedroid/btc/profile/std/a2dp/bta_av_co.c @@ -1286,17 +1286,21 @@ static BOOLEAN bta_av_co_audio_codec_build_config(const UINT8 *p_codec_caps, UIN case BTC_AV_CODEC_M24: { UINT32 cfg_bit_rate; UINT32 cap_bit_rate; + UINT32 nego_bit_rate; /* LOSC(1) + media(1) + codec(1) + CIE(6) = 9 octets */ memcpy(p_codec_cfg, bta_av_co_cb.codec_cfg.info, BTA_AV_CO_M24_INFO_LEN); cfg_bit_rate = bta_av_m24_br_info(p_codec_cfg); cap_bit_rate = bta_av_m24_br_info(p_codec_caps); + /* Bit rate 0 means "not known" per A2DP; do not treat it as min=0. */ + nego_bit_rate = bta_av_m24_br_min(cfg_bit_rate, cap_bit_rate); - bta_av_m24_set_br_info(p_codec_cfg, BTA_AV_CO_MIN(cfg_bit_rate, cap_bit_rate)); + bta_av_m24_set_br_info(p_codec_cfg, nego_bit_rate); p_codec_cfg[BTA_AV_CO_M24_VBR_BR1_OFF] &= (p_codec_caps[BTA_AV_CO_M24_VBR_BR1_OFF] & A2D_M24_IE_VBR_MSK) | ~A2D_M24_IE_VBR_MSK; - APPL_TRACE_EVENT("bta_av_co_audio_codec_build_config bit rate: 0x%u(cfg_br: %u/cap_br: %u, min: %u)", bta_av_m24_br_info(p_codec_cfg), cfg_bit_rate, cap_bit_rate, BTA_AV_CO_MIN(cfg_bit_rate, cap_bit_rate)); + APPL_TRACE_EVENT("bta_av_co_audio_codec_build_config bit rate: %u(cfg_br: %u/cap_br: %u, nego: %u)", + bta_av_m24_br_info(p_codec_cfg), cfg_bit_rate, cap_bit_rate, nego_bit_rate); break; } #endif