From 79f4e57290c78f087718dce8fcd2999267a79a3c Mon Sep 17 00:00:00 2001 From: Bhakthavatsala Raghavendra Date: Fri, 29 Jul 2016 19:11:28 -0700 Subject: Bluetooth: Add AAC codec Support in Split-a2dp mode Add AAC codec support in split-a2dp mode Change-Id: I174b0c44cdef8b5d174a2e39fa34fefc55d4807b --- audio_a2dp_hw/bthost_ipc.c | 104 +++++++++++++++++- audio_a2dp_hw/bthost_ipc.h | 14 +++ bta/Android.mk | 1 + bta/av/bta_av_aac.c | 83 +++++++++++++++ bta/include/bta_av_aac.h | 57 ++++++++++ bta/include/bta_av_api.h | 4 + bta/include/bta_av_co.h | 3 + btif/co/bta_av_co.c | 258 ++++++++++++++++++++++++++++++++++++++++++++- btif/include/btif_av_api.h | 2 +- btif/include/btif_av_co.h | 15 ++- btif/include/btif_media.h | 6 ++ btif/src/btif_media_task.c | 76 ++++++++++++- include/bt_target.h | 13 +++ stack/Android.mk | 1 + stack/a2dp/a2d_aac.c | 175 ++++++++++++++++++++++++++++++ stack/include/a2d_aac.h | 149 ++++++++++++++++++++++++++ 16 files changed, 950 insertions(+), 11 deletions(-) create mode 100644 bta/av/bta_av_aac.c create mode 100644 bta/include/bta_av_aac.h create mode 100644 stack/a2dp/a2d_aac.c create mode 100644 stack/include/a2d_aac.h diff --git a/audio_a2dp_hw/bthost_ipc.c b/audio_a2dp_hw/bthost_ipc.c index 08d9a264e..fc0e91483 100644 --- a/audio_a2dp_hw/bthost_ipc.c +++ b/audio_a2dp_hw/bthost_ipc.c @@ -89,6 +89,7 @@ struct a2dp_stream_common audio_stream; audio_sbc_encoder_config sbc_codec; audio_aptx_encoder_config aptx_codec; +audio_aac_encoder_config aac_codec; /***************************************************************************** ** Externs ******************************************************************************/ @@ -269,8 +270,105 @@ static void* a2dp_codec_parser(uint8_t *codec_cfg, audio_format_t *codec_type) sbc_codec.bitrate |= (*p_cfg++ << 16); sbc_codec.bitrate |= (*p_cfg++ << 24); *codec_type = AUDIO_FORMAT_SBC; - INFO("Done copying full codec config"); + INFO("SBC: Done copying full codec config"); return ((void *)(&sbc_codec)); + } else if (codec_cfg[CODEC_OFFSET] == CODEC_TYPE_AAC) + { + uint16_t aac_samp_freq = 0; + uint32_t aac_bit_rate = 0; + memset(&aac_codec,0,sizeof(audio_aac_encoder_config)); + p_cfg++;//skip dev idx + len = *p_cfg++; + p_cfg++;//skip media type + len--; + p_cfg++;//skip codec type + len--; + byte = *p_cfg++; + len--; + switch (byte & A2D_AAC_IE_OBJ_TYPE_MSK) + { + case A2D_AAC_IE_OBJ_TYPE_MPEG_2_AAC_LC: + aac_codec.enc_mode = AUDIO_FORMAT_AAC_SUB_LC; + break; + case A2D_AAC_IE_OBJ_TYPE_MPEG_4_AAC_LC: + aac_codec.enc_mode = AUDIO_FORMAT_AAC_SUB_LC; + break; + case A2D_AAC_IE_OBJ_TYPE_MPEG_4_AAC_LTP: + aac_codec.enc_mode = AUDIO_FORMAT_AAC_SUB_LTP; + break; + case A2D_AAC_IE_OBJ_TYPE_MPEG_4_AAC_SCA: + aac_codec.enc_mode = AUDIO_FORMAT_AAC_SUB_SCALABLE; + break; + default: + ERROR("Unknown encoder mode"); + } + //USE 0 (AAC_LC) as hardcoded value till Audio + //define constants + aac_codec.enc_mode = 0; + //USE LOAS(1) or LATM(4) hardcoded values till + //Audio define proper constants + aac_codec.format_flag = 4; + byte = *p_cfg++; + len--; + aac_samp_freq = byte << 8; //1st byte of sample_freq + byte = *p_cfg++; + len--; + aac_samp_freq |= byte & 0x00F0; //1st nibble of second byte of samp_freq + + switch (aac_samp_freq) { + case 0x8000: aac_codec.sampling_rate = 8000; break; + case 0x4000: aac_codec.sampling_rate = 11025; break; + case 0x2000: aac_codec.sampling_rate = 12000; break; + case 0x1000: aac_codec.sampling_rate = 16000; break; + case 0x0800: aac_codec.sampling_rate = 22050; break; + case 0x0400: aac_codec.sampling_rate = 24000; break; + case 0x0200: aac_codec.sampling_rate = 32000; break; + case 0x0100: aac_codec.sampling_rate = 44100; break; + case 0x0080: aac_codec.sampling_rate = 48000; break; + case 0x0040: aac_codec.sampling_rate = 64000; break; + case 0x0020: aac_codec.sampling_rate = 88200; break; + case 0x0010: aac_codec.sampling_rate = 96000; break; + default: + ERROR("Invalid sample_freq: %x", aac_samp_freq); + } + + switch (byte & A2D_AAC_IE_CHANNELS_MSK) + { + case A2D_AAC_IE_CHANNELS_1: + aac_codec.channels = 1; + break; + case A2D_AAC_IE_CHANNELS_2: + aac_codec.channels = 2; + break; + default: + ERROR("Unknow channel mode"); + } + byte = *p_cfg++; //Move to VBR byte + len--; + switch (byte & A2D_AAC_IE_VBR_MSK) + { + case A2D_AAC_IE_VBR: + break; + default: + ERROR("VBR not supported"); + } + aac_bit_rate = 0x7F&byte; + //Move it 2nd byte of 32 bit word. leaving the VBR bit + aac_bit_rate = aac_bit_rate << 16; + byte = *p_cfg++; //Move to 2nd byteof bitrate + len--; + + //Move it to 3rd byte of 32bit word + aac_bit_rate |= 0x0000FF00 & (((uint32_t)byte)<<8); + byte = *p_cfg++; //Move to 3rd byte of bitrate + len--; + + aac_bit_rate |= 0x000000FF & (((uint32_t)byte)); + aac_codec.bitrate = aac_bit_rate; + + *codec_type = AUDIO_FORMAT_AAC; + INFO("AAC: Done copying full codec config"); + return ((void *)(&aac_codec)); } else if (codec_cfg[CODEC_OFFSET] == NON_A2DP_CODEC_TYPE) { @@ -332,6 +430,8 @@ static void* a2dp_codec_parser(uint8_t *codec_cfg, audio_format_t *codec_type) aptx_codec.bitrate |= (*p_cfg++ << 8); aptx_codec.bitrate |= (*p_cfg++ << 16); aptx_codec.bitrate |= (*p_cfg++ << 24); + + INFO("APTx: Done copying full codec config"); return ((void *)&aptx_codec); } return NULL; @@ -933,7 +1033,7 @@ int audio_stop_stream() return 0; } audio_stream.state = AUDIO_A2DP_STATE_STOPPED; - return -1; + return -1; } int audio_suspend_stream() diff --git a/audio_a2dp_hw/bthost_ipc.h b/audio_a2dp_hw/bthost_ipc.h index d30dfdc88..14ab882d7 100644 --- a/audio_a2dp_hw/bthost_ipc.h +++ b/audio_a2dp_hw/bthost_ipc.h @@ -101,6 +101,20 @@ codec specific definitions #define A2D_APTX_CHAN_STEREO 0x02 #define A2D_APTX_CHAN_MONO 0x01 + +#define A2D_AAC_IE_OBJ_TYPE_MSK 0xF0 /* b7-b4 Object Type */ +#define A2D_AAC_IE_OBJ_TYPE_MPEG_2_AAC_LC 0x80 /* b7:MPEG-2 AAC LC */ +#define A2D_AAC_IE_OBJ_TYPE_MPEG_4_AAC_LC 0x40 /* b7:MPEG-4 AAC LC */ +#define A2D_AAC_IE_OBJ_TYPE_MPEG_4_AAC_LTP 0x20 /* b7:MPEG-4 AAC LTP */ +#define A2D_AAC_IE_OBJ_TYPE_MPEG_4_AAC_SCA 0x10 /* b7:MPEG-4 AAC SCALABLE */ + +#define A2D_AAC_IE_CHANNELS_MSK 0x0C +#define A2D_AAC_IE_CHANNELS_1 0x08 /* Channel 1 */ +#define A2D_AAC_IE_CHANNELS_2 0x04 /* Channel 2 */ + +#define A2D_AAC_IE_VBR_MSK 0x80 +#define A2D_AAC_IE_VBR 0x80 /* supported */ + typedef struct { uint8_t codec_type; uint8_t dev_idx; diff --git a/bta/Android.mk b/bta/Android.mk index bd1b19db8..ba6e68f53 100644 --- a/bta/Android.mk +++ b/bta/Android.mk @@ -57,6 +57,7 @@ LOCAL_SRC_FILES:= \ ./av/bta_av_cfg.c \ ./av/bta_av_ssm.c \ ./av/bta_av_sbc.c \ + ./av/bta_av_aac.c \ ./ar/bta_ar.c \ ./hl/bta_hl_act.c \ ./hl/bta_hl_api.c \ diff --git a/bta/av/bta_av_aac.c b/bta/av/bta_av_aac.c new file mode 100644 index 000000000..3ef088538 --- /dev/null +++ b/bta/av/bta_av_aac.c @@ -0,0 +1,83 @@ +/****************************************************************************** + * + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +#include "a2d_api.h" +#include "a2d_aac.h" +#include "bta_av_aac.h" +#include "utl.h" + +/******************************************************************************* +** +** Function bta_av_aac_cfg_in_cap +** +** Description Checks if AAC codec config is allowed for given caps. +** codec config bits are also checked for sanity +** +** Returns 0 if ok, nonzero if error. +** +*******************************************************************************/ +UINT8 bta_av_aac_cfg_in_cap(UINT8 *p_cfg, tA2D_AAC_CIE *p_cap) +{ + UINT8 status = 0; + tA2D_AAC_CIE cfg_cie; + + /* parse configuration */ + if ((status = A2D_ParsAacInfo(&cfg_cie, p_cfg, FALSE)) != 0) + { + APPL_TRACE_DEBUG("bta_av_aac_cfg_in_cap can't parse %d", status); + return status; + } + + + /* object type */ + if ((cfg_cie.object_type & p_cap->object_type) == 0) + { + status = A2D_NS_OBJ_TYPE; + } + /* frequency */ + else if ((cfg_cie.samp_freq & p_cap->samp_freq) == 0) + { + status = A2D_NS_SAMP_FREQ; + } + /* channels */ + else if ((cfg_cie.channels & p_cap->channels) == 0) + { + status = A2D_NS_CHANNEL; + } + /* block length */ + else if ((cfg_cie.bit_rate & p_cap->bit_rate) == 0) + { + status = A2D_NS_BIT_RATE; + } + APPL_TRACE_DEBUG("bta_av_aac_cfg_in_cap return %d", status); + return status; +} + diff --git a/bta/include/bta_av_aac.h b/bta/include/bta_av_aac.h new file mode 100644 index 000000000..310cbfa23 --- /dev/null +++ b/bta/include/bta_av_aac.h @@ -0,0 +1,57 @@ +/****************************************************************************** + * + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +/****************************************************************************** + * + * Interface to utility functions for AAC codec + * + ******************************************************************************/ +#ifndef BTA_AV_AAC_H +#define BTA_AV_AAC_H + + +/* AAC packet header size */ +#define BTA_AV_AAC_HDR_SIZE A2D_AAC_MPL_HDR_LEN + +/******************************************************************************* +** +** Function bta_av_aac_cfg_in_cap +** +** Description Checks if AAC codec config is allowed for given caps. +** codec config bits are also checked for sanity +** +** Returns 0 if ok, nonzero if error. +** +*******************************************************************************/ +extern UINT8 bta_av_aac_cfg_in_cap(UINT8 *p_cfg, tA2D_AAC_CIE *p_cap); + +#endif /* BTA_AV_AAC_H */ + diff --git a/bta/include/bta_av_api.h b/bta/include/bta_av_api.h index d9974e43b..891535587 100644 --- a/bta/include/bta_av_api.h +++ b/bta/include/bta_av_api.h @@ -109,8 +109,12 @@ typedef UINT8 tBTA_AV_HNDL; #endif #ifndef BTA_AV_MAX_SEPS +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) +#define BTA_AV_MAX_SEPS 3 +#else #define BTA_AV_MAX_SEPS 2 #endif +#endif #ifndef BTA_AV_MAX_A2DP_MTU /*#define BTA_AV_MAX_A2DP_MTU 668 //224 (DM5) * 3 - 4(L2CAP header) */ diff --git a/bta/include/bta_av_co.h b/bta/include/bta_av_co.h index 2510968f7..00fc5ade6 100644 --- a/bta/include/bta_av_co.h +++ b/bta/include/bta_av_co.h @@ -63,6 +63,9 @@ enum { BTIF_SV_AV_AA_SBC_INDEX = 0, BTIF_SV_AV_AA_APTX_INDEX, +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) + BTIF_SV_AV_AA_AAC_INDEX, +#endif BTIF_SV_AV_AA_SRC_SEP_INDEX /* Last index */ }; diff --git a/btif/co/bta_av_co.c b/btif/co/bta_av_co.c index d0a40ca7d..ae042e3fc 100644 --- a/btif/co/bta_av_co.c +++ b/btif/co/bta_av_co.c @@ -45,6 +45,10 @@ #include "bt_utils.h" #include "a2d_aptx.h" +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) +#include "a2d_aac.h" +#include "bta_av_aac.h" +#endif /***************************************************************************** ** Constants @@ -160,6 +164,36 @@ const tA2D_APTX_CIE btif_av_aptx_default_config = A2D_APTX_FUTURE_2 }; +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) +const tA2D_AAC_CIE bta_av_co_aac_caps = +{ + (A2D_AAC_IE_OBJ_TYPE_MPEG_2_AAC_LC|A2D_AAC_IE_OBJ_TYPE_MPEG_4_AAC_LC), /* obj type */ +#ifndef BTA_AV_SPLIT_A2DP_DEF_FREQ_48KHZ + (A2D_AAC_IE_SAMP_FREQ_44100), +#else + (A2D_AAC_IE_SAMP_FREQ_44100 | A2D_AAC_IE_SAMP_FREQ_48000), +#endif + (A2D_AAC_IE_CHANNELS_1 | A2D_AAC_IE_CHANNELS_2 ), /* channels */ + A2D_AAC_IE_BIT_RATE, /* BIT RATE */ + A2D_AAC_IE_VBR_NOT_SUPP /* variable bit rate */ +}; + +/* Default AAC codec configuration */ +const tA2D_AAC_CIE btif_av_aac_default_config = +{ + A2D_AAC_IE_OBJ_TYPE_MPEG_2_AAC_LC, /* obj type */ +#ifndef BTA_AV_SPLIT_A2DP_DEF_FREQ_48KHZ + A2D_AAC_IE_SAMP_FREQ_44100, /* samp_freq */ +#else + A2D_AAC_IE_SAMP_FREQ_48000, /* samp_freq */ +#endif + A2D_AAC_IE_CHANNELS_2, /* channels */ + BTIF_AAC_DEFAULT_BIT_RATE, /* bit rate */ + A2D_AAC_IE_VBR_NOT_SUPP +}; +#endif + + /***************************************************************************** ** Local data *****************************************************************************/ @@ -216,6 +250,10 @@ typedef struct tBTIF_AV_CODEC_INFO codec_cfg_sbc_setconfig; /* remote peer setconfig preference (SBC) */ tBTIF_AV_CODEC_INFO codec_cfg_aptx; tBTIF_AV_CODEC_INFO codec_cfg_aptx_setconfig; /* remote peer setconfig preference (aptX)*/ +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) + tBTIF_AV_CODEC_INFO codec_cfg_aac; + tBTIF_AV_CODEC_INFO codec_cfg_aac_setconfig; /* remote peer setconfig preference (AAC)*/ +#endif tBTA_AV_CO_CP cp; } tBTA_AV_CO_CB; @@ -380,7 +418,13 @@ BOOLEAN bta_av_co_audio_init(UINT8 *p_codec_type, UINT8 *p_codec_info, UINT8 *p_ *p_codec_type = A2D_NON_A2DP_MEDIA_CT; A2D_BldAptxInfo(AVDT_MEDIA_AUDIO, (tA2D_APTX_CIE *) &bta_av_co_aptx_caps, p_codec_info); return TRUE; - +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) + case BTIF_SV_AV_AA_AAC_INDEX: + APPL_TRACE_DEBUG("%s AAC", __func__); + *p_codec_type = BTA_AV_CODEC_M24; + A2D_BldAacInfo(AVDT_MEDIA_AUDIO, (tA2D_AAC_CIE *) &bta_av_co_aac_caps ,p_codec_info); + return TRUE; +#endif #if (BTA_AV_SINK_INCLUDED == TRUE) case BTIF_SV_AV_AA_SBC_SINK_INDEX: *p_codec_type = BTA_AV_CODEC_SBC; @@ -707,6 +751,12 @@ UINT8 bta_av_co_audio_getconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type, } break; } +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) + case BTA_AV_CODEC_M24: + APPL_TRACE_DEBUG("%s: AAC is supported", __func__); + supported = TRUE; + break; +#endif default: break; } @@ -977,7 +1027,17 @@ void bta_av_co_audio_setconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type, } break; } +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) + case BTA_AV_CODEC_M24: + { + APPL_TRACE_DEBUG("%s AAC", __func__); + bta_av_co_cb.codec_cfg_aac_setconfig.id = BTIF_AV_CODEC_M24; + memcpy(bta_av_co_cb.codec_cfg_aac_setconfig.info, p_codec_info, AVDT_CODEC_SIZE); + bta_av_co_cb.codec_cfg_setconfig = &bta_av_co_cb.codec_cfg_aac_setconfig; + APPL_TRACE_DEBUG("%s codec_type = %x", __func__, codec_type); + } break; +#endif default: APPL_TRACE_ERROR("bta_av_co_audio_setconfig unsupported cid %d", bta_av_co_cb.codec_cfg->id); recfg_needed = TRUE; @@ -1259,7 +1319,14 @@ static BOOLEAN bta_av_co_audio_codec_build_config(const UINT8 *p_codec_caps, UIN p_codec_cfg[BTA_AV_CO_SBC_MIN_BITPOOL_OFF], p_codec_caps[BTA_AV_CO_SBC_MAX_BITPOOL_OFF]); break; - +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) + case BTIF_AV_CODEC_M24: + /* only copy the relevant portions for this codec to avoid issues when + comparing codec configs covering larger codec sets than SBC (7 bytes) */ + memcpy(p_codec_cfg, bta_av_co_cb.codec_cfg->info, A2D_AAC_INFO_LEN+1); + APPL_TRACE_DEBUG("%s AAC", __func__); + break; +#endif case A2D_NON_A2DP_MEDIA_CT: { UINT16 codecId; @@ -1317,6 +1384,37 @@ static BOOLEAN bta_av_co_audio_codec_cfg_matches_caps(UINT8 codec_id, const UINT return FALSE; } break; +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) + /* in case of Sink we have to match if Src Cap is a subset of ours */ + case BTA_AV_CODEC_M24: + { + tBTIF_AV_CODEC_INFO *p_local_aac_cfg = (tBTIF_AV_CODEC_INFO*)p_codec_cfg; + tA2D_AAC_CIE p_local_aac_caps; + tA2D_AAC_CIE p_snk_aac_caps; + + if (A2D_ParsAacInfo(&p_local_aac_caps, (UINT8*)p_local_aac_cfg, FALSE) != A2D_SUCCESS) { + APPL_TRACE_ERROR("%s: A2D_BldAacInfo: LOCAL failed", __func__); + } + if (A2D_ParsAacInfo(&p_snk_aac_caps, (UINT8*)p_codec_cfg, FALSE) != A2D_SUCCESS) { + APPL_TRACE_ERROR("%s: A2D_BldAacInfo: SNK failed", __func__); + } + + APPL_TRACE_EVENT("AAC obj_type: snk %x local %x", + p_snk_aac_caps.object_type, p_local_aac_caps.object_type); + APPL_TRACE_EVENT("AAC samp_freq: snk %x local %x", + p_snk_aac_caps.samp_freq, p_local_aac_caps.samp_freq); + APPL_TRACE_EVENT("AAC channels: snk %x local %x", + p_snk_aac_caps.channels, p_local_aac_caps.channels); + APPL_TRACE_EVENT("AAC bit_rate: snk %x local %x", + p_snk_aac_caps.bit_rate, p_local_aac_caps.bit_rate); + APPL_TRACE_EVENT("AAC vbr: snk %x local %x", + p_snk_aac_caps.vbr, p_local_aac_caps.vbr); + return (((p_snk_aac_caps.object_type)&(p_local_aac_caps.object_type))&& + ((p_snk_aac_caps.samp_freq)&(p_local_aac_caps.samp_freq))&& + ((p_snk_aac_caps.channels)&(p_local_aac_caps.channels))); + } + break; +#endif case A2D_NON_A2DP_MEDIA_CT: { UINT16 codecId; @@ -1379,6 +1477,11 @@ static BOOLEAN bta_av_co_audio_codec_match(const UINT8 *p_codec_caps, UINT8 code case BTIF_AV_CODEC_SBC: return bta_av_co_audio_codec_cfg_matches_caps(bta_av_co_cb.codec_cfg_sbc.id, p_codec_caps, bta_av_co_cb.codec_cfg_sbc.info); break; +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) + case BTIF_AV_CODEC_M24: + return bta_av_co_audio_codec_cfg_matches_caps(bta_av_co_cb.codec_cfg_aac.id, p_codec_caps, bta_av_co_cb.codec_cfg_aac.info); + break; +#endif case A2D_NON_A2DP_MEDIA_CT: { UINT16 codecId; @@ -1582,6 +1685,46 @@ static BOOLEAN bta_av_co_audio_peer_supports_codec(tBTA_AV_CO_PEER *p_peer, UINT } else APPL_TRACE_DEBUG("%s aptX is disabled", __func__); +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) + if (bt_split_a2dp_enabled && btif_av_is_codec_offload_supported(AAC)) { + for (index = 0; index < p_peer->num_sup_snks; index++) + { + APPL_TRACE_DEBUG("%s AAC: index: %d, codec_type: %d", __func__, index, p_peer->snks[index].codec_type); + + if (p_peer->snks[index].codec_type == bta_av_co_cb.codec_cfg_aac.id) + { + switch (p_peer->snks[index].codec_type) + { + case BTIF_AV_CODEC_M24: + if (p_snk_index) *p_snk_index = index; + APPL_TRACE_DEBUG("%s AAC", __func__); + if (bta_av_co_audio_codec_match(p_peer->snks[index].codec_caps, BTIF_AV_CODEC_M24)) + { +#if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE) + if (bta_av_co_audio_sink_has_scmst(&p_peer->snks[index])) +#endif + { + bta_av_co_cb.current_codec_id = bta_av_co_cb.codec_cfg_aac.id; + bta_av_co_cb.codec_cfg = &bta_av_co_cb.codec_cfg_aac; + + APPL_TRACE_DEBUG("%s AAC matched", __func__); + return TRUE; + } + } + break; + + default: + APPL_TRACE_ERROR("AAC: bta_av_co_audio_peer_supports_codec: unsupported codec id %d", bta_av_co_cb.codec_cfg->id); + //Fall thru for further SBC check + break; + } + } + } + } else + APPL_TRACE_DEBUG("%s aptX is disabled", __func__); +#endif + + for (index = 0; index < p_peer->num_sup_snks; index++) { if (p_peer->snks[index].codec_type == codec_type || @@ -1720,6 +1863,15 @@ static BOOLEAN bta_av_co_audio_media_supports_config(UINT8 codec_type, const UIN return FALSE; } break; +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) + case BTA_AV_CODEC_M24: + if (bta_av_aac_cfg_in_cap((UINT8 *)p_codec_cfg, (tA2D_AAC_CIE *)&bta_av_co_aac_caps)) + { + APPL_TRACE_DEBUG("%s AAC ",__func__); + return FALSE; + } + break; +#endif case A2D_NON_A2DP_MEDIA_CT: aptx_capabilities = &(((tBTA_AV_CO_SINK*)p_codec_cfg)->codec_caps[0]); codecId = ((tA2D_APTX_CIE*)(aptx_capabilities))->codecId; @@ -1876,7 +2028,15 @@ void bta_av_co_audio_codec_reset(void) APPL_TRACE_ERROR("bta_av_co_audio_codec_reset A2D_BldSbcInfo failed"); } else bta_av_co_cb.codec_cfg = &(bta_av_co_cb.codec_cfg_sbc); - +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) + /* Reset the current configuration to AAC */ + bta_av_co_cb.codec_cfg_aac.id = BTIF_AV_CODEC_M24; + if (A2D_BldAacInfo(A2D_MEDIA_TYPE_AUDIO, (tA2D_AAC_CIE *)&btif_av_aac_default_config, bta_av_co_cb.codec_cfg_aac.info) != A2D_SUCCESS) + { + APPL_TRACE_ERROR("bta_av_co_audio_codec_reset A2D_BldAacInfo failed"); + } else + bta_av_co_cb.codec_cfg = &(bta_av_co_cb.codec_cfg_sbc); +#endif /* Reset the Current configuration to aptX */ bta_av_co_cb.codec_cfg_aptx.id = A2D_NON_A2DP_MEDIA_CT; if (A2D_BldAptxInfo(A2D_MEDIA_TYPE_AUDIO, (tA2D_APTX_CIE *)&btif_av_aptx_default_config, bta_av_co_cb.codec_cfg_aptx.info) != A2D_SUCCESS) @@ -1902,6 +2062,10 @@ BOOLEAN bta_av_co_audio_set_codec(const tBTIF_AV_MEDIA_FEEDINGS *p_feeding, tBTI tBTIF_AV_CODEC_INFO new_cfg_sbc; tA2D_APTX_CIE aptx_config; tBTIF_AV_CODEC_INFO new_cfg_aptx; +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) + tA2D_AAC_CIE aac_config; + tBTIF_AV_CODEC_INFO new_cfg_aac; +#endif FUNC_TRACE(); /* Check AV feeding is supported */ @@ -1930,6 +2094,10 @@ BOOLEAN bta_av_co_audio_set_codec(const tBTIF_AV_MEDIA_FEEDINGS *p_feeding, tBTI } new_cfg_aptx.id = A2D_NON_A2DP_MEDIA_CT; aptx_config = btif_av_aptx_default_config; +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) + new_cfg_aac.id = BTIF_AV_CODEC_M24; + aac_config = btif_av_aac_default_config; +#endif switch (p_feeding->cfg.pcm.sampling_freq) { case 8000: @@ -1940,6 +2108,9 @@ BOOLEAN bta_av_co_audio_set_codec(const tBTIF_AV_MEDIA_FEEDINGS *p_feeding, tBTI case 48000: sbc_config.samp_freq = A2D_SBC_IE_SAMP_FREQ_48; aptx_config.sampleRate = A2D_APTX_SAMPLERATE_48000; +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) + aac_config.samp_freq = A2D_AAC_IE_SAMP_FREQ_48000; +#endif break; case 11025: @@ -1947,6 +2118,9 @@ BOOLEAN bta_av_co_audio_set_codec(const tBTIF_AV_MEDIA_FEEDINGS *p_feeding, tBTI case 44100: sbc_config.samp_freq = A2D_SBC_IE_SAMP_FREQ_44; aptx_config.sampleRate = A2D_APTX_SAMPLERATE_44100; +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) + aac_config.samp_freq = A2D_AAC_IE_SAMP_FREQ_44100; +#endif break; default: APPL_TRACE_ERROR("bta_av_co_audio_set_codec PCM sampling frequency unsupported"); @@ -1964,6 +2138,13 @@ BOOLEAN bta_av_co_audio_set_codec(const tBTIF_AV_MEDIA_FEEDINGS *p_feeding, tBTI APPL_TRACE_ERROR("%s A2D_BldAptxInfo failed", __func__); return FALSE; } +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) + if (A2D_BldAacInfo(A2D_MEDIA_TYPE_AUDIO, &aac_config, new_cfg_aac.info) != A2D_SUCCESS) + { + APPL_TRACE_ERROR("%s A2D_BldAacInfo failed", __func__); + return FALSE; + } +#endif break; @@ -1977,6 +2158,9 @@ BOOLEAN bta_av_co_audio_set_codec(const tBTIF_AV_MEDIA_FEEDINGS *p_feeding, tBTI bta_av_co_cb.codec_cfg_sbc = new_cfg_sbc; bta_av_co_cb.codec_cfg = &bta_av_co_cb.codec_cfg_sbc; bta_av_co_cb.codec_cfg_aptx= new_cfg_aptx; +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) + bta_av_co_cb.codec_cfg_aac = new_cfg_aac; +#endif /* Check all devices support it */ *p_status = BTIF_SUCCESS; @@ -2042,6 +2226,9 @@ BOOLEAN bta_av_co_audio_get_codec_config(UINT8 *p_config, UINT16 *p_minmtu, UINT tBTA_AV_CO_PEER *p_peer; tBTA_AV_CO_SINK *p_sink; tA2D_SBC_CIE *sbc_config; +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) + tA2D_AAC_CIE *aac_config; +#endif APPL_TRACE_EVENT("%s codec 0x%x", __func__, bta_av_co_cb.codec_cfg->id); @@ -2069,6 +2256,17 @@ BOOLEAN bta_av_co_audio_get_codec_config(UINT8 *p_config, UINT16 *p_minmtu, UINT } else { APPL_TRACE_DEBUG("%s vendorId: %d codecId: %d\n", __func__, ((tA2D_APTX_CIE *)p_config)->vendorId, ((tA2D_APTX_CIE *)p_config)->codecId); } +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) + if (type == BTIF_AV_CODEC_M24) + { + APPL_TRACE_DEBUG("%s AAC", __func__); + aac_config = (tA2D_AAC_CIE *)p_config; + if (A2D_ParsAacInfo(aac_config, bta_av_co_cb.codec_cfg_aac.info, FALSE) == A2D_SUCCESS) + result = TRUE; + else + memcpy((tA2D_AAC_CIE *) p_config, &btif_av_aac_default_config, sizeof(tA2D_AAC_CIE)); + } +#endif for (index = 0; index < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); index++) { p_peer = &bta_av_co_cb.peers[index]; @@ -2172,6 +2370,60 @@ BOOLEAN bta_av_co_audio_get_sbc_config(tA2D_SBC_CIE *p_sbc_config, UINT16 *p_min return result; } +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) +/******************************************************************************* + ** + ** Function bta_av_co_audio_get_aac_config + ** + ** Description Retrieves the AAC codec configuration. If the codec in use + ** is not AAC, return the default AAC codec configuration. + ** + ** Returns TRUE if codec is AAC, FALSE otherwise + ** + *******************************************************************************/ +BOOLEAN bta_av_co_audio_get_aac_config(tA2D_AAC_CIE *p_aac_config, UINT16 *p_minmtu) +{ + BOOLEAN result = FALSE; + UINT8 index; + tBTA_AV_CO_PEER *p_peer; + + APPL_TRACE_EVENT("bta_av_co_cb.codec_cfg->id : codec 0x%x", bta_av_co_cb.codec_cfg->id); + + /* Minimum MTU is by default very large */ + *p_minmtu = 0xFFFF; + + mutex_global_lock(); + if (bta_av_co_cb.codec_cfg->id == BTIF_AV_CODEC_M24) + { + if (A2D_ParsAacInfo(p_aac_config, bta_av_co_cb.codec_cfg->info, FALSE) == A2D_SUCCESS) + { + for (index = 0; index < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); index++) + { + p_peer = &bta_av_co_cb.peers[index]; + if (p_peer->opened) + { + APPL_TRACE_EVENT("%s on index= %d", __func__, index); + if (p_peer->mtu < *p_minmtu) + { + *p_minmtu = p_peer->mtu; + } + } + } + result = TRUE; + } + } + + if (!result) + { + /* Not AAC, still return the default values */ + APPL_TRACE_EVENT("%s Not SBC, still return the default values", __func__); + *p_aac_config = btif_av_aac_default_config; + } + mutex_global_unlock(); + + return result; +} +#endif /******************************************************************************* ** diff --git a/btif/include/btif_av_api.h b/btif/include/btif_av_api.h index 99c492395..857fed21c 100644 --- a/btif/include/btif_av_api.h +++ b/btif/include/btif_av_api.h @@ -51,7 +51,7 @@ /* Codec type */ #define BTIF_AV_CODEC_NONE 0xF1 #define BTIF_AV_CODEC_SBC A2D_MEDIA_CT_SBC /* SBC media codec type */ - +#define BTIF_AV_CODEC_M24 A2D_MEDIA_CT_M24 /* AAC media codec type */ #define BTIF_AV_CODEC_PCM 0x5 /* Raw PCM */ typedef UINT8 tBTIF_AV_CODEC_ID; diff --git a/btif/include/btif_av_co.h b/btif/include/btif_av_co.h index 2d2bbc9d4..167e1a5d7 100644 --- a/btif/include/btif_av_co.h +++ b/btif/include/btif_av_co.h @@ -30,7 +30,6 @@ /******************************************************************************* ** Constants & Macros ********************************************************************************/ - /******************************************************************************* ** Functions ********************************************************************************/ @@ -154,6 +153,20 @@ BOOLEAN bta_av_co_audio_get_codec_config(UINT8 *p_sbc_config, UINT16 *p_minmtu, ** *******************************************************************************/ BOOLEAN bta_av_co_audio_get_sbc_config(tA2D_SBC_CIE *p_sbc_config, UINT16 *p_minmtu); +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) +/******************************************************************************* + ** + ** Function bta_av_co_audio_get_aac_config + ** + ** Description Retrieves the AAC codec configuration. If the codec in use + ** is not AAC, return the default SBC codec configuration. + ** + ** Returns TRUE if codec is AAC, FALSE otherwise + ** + *******************************************************************************/ +BOOLEAN bta_av_co_audio_get_aac_config(tA2D_AAC_CIE *p_aac_config, UINT16 *p_minmtu); +#endif + /******************************************************************************* ** diff --git a/btif/include/btif_media.h b/btif/include/btif_media.h index c7e10fe1c..f9ef11e7d 100644 --- a/btif/include/btif_media.h +++ b/btif/include/btif_media.h @@ -39,6 +39,7 @@ #include "bt_common.h" #include "btif_av_api.h" #include "audio_a2dp_hw.h" +#include "a2d_aac.h" /******************************************************************************* ** Constants @@ -83,6 +84,11 @@ typedef struct UINT8 CodecType; /* SBC or Non-A2DP */ UINT8 BluetoothVendorID; /* Bluetooth Vendor ID */ UINT8 BluetoothCodecID; /* Bluetooth Codec ID */ +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) + UINT8 ObjectType; + UINT32 bit_rate; + UINT8 vbr; +#endif } tBTIF_MEDIA_INIT_AUDIO; #if (BTA_AV_INCLUDED == TRUE) diff --git a/btif/src/btif_media_task.c b/btif/src/btif_media_task.c index d1d2f25e5..6180852f9 100644 --- a/btif/src/btif_media_task.c +++ b/btif/src/btif_media_task.c @@ -61,12 +61,14 @@ #include "a2d_int.h" #include "a2d_sbc.h" #include "a2d_aptx.h" +#include "a2d_aac.h" #include "audio_a2dp_hw.h" #include "bt_target.h" #include "bta_api.h" #include "bta_av_api.h" #include "bta_av_ci.h" #include "bta_av_sbc.h" +#include "bta_av_aac.h" #include "bta_sys.h" #include "bta_sys_int.h" #include "btif_av.h" @@ -183,6 +185,12 @@ enum { #define BTIF_MEDIA_AA_SBC_OFFSET (AVDT_MEDIA_OFFSET + BTA_AV_SBC_HDR_SIZE) #endif +#if (BTA_AV_CO_CP_SCMS_T == TRUE) +#define BTIF_MEDIA_AA_AAC_OFFSET (AVDT_MEDIA_OFFSET + BTA_AV_AAC_HDR_SIZE + 1) +#else +#define BTIF_MEDIA_AA_AAC_OFFSET (AVDT_MEDIA_OFFSET + BTA_AV_AAC_HDR_SIZE) +#endif + #if (BTA_AV_CO_CP_SCMS_T == TRUE) #define BTIF_MEDIA_AA_APTX_OFFSET (AVDT_MEDIA_OFFSET + 1) #else @@ -899,6 +907,14 @@ static void btif_recv_ctrl_data(void) A2D_BldSbcInfo(AVDT_MEDIA_AUDIO,&codec_cfg,¶m[1]); bitrate = btif_media_cb.encoder.u16BitRate * 1000; } +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) + else if (codec_id == BTIF_AV_CODEC_M24) { + tA2D_AAC_CIE aac_cfg; + bta_av_co_audio_get_aac_config(&aac_cfg, &min_mtu); + A2D_BldAacInfo(AVDT_MEDIA_AUDIO,&aac_cfg,¶m[1]); + bitrate = btif_media_cb.encoder.u16BitRate * 1000; + } +#endif else if (codec_id == A2D_NON_A2DP_MEDIA_CT) //this is changed to non-a2dp VS codec { //ADD APTX support @@ -913,7 +929,7 @@ static void btif_recv_ctrl_data(void) { tA2D_APTX_CIE* codecInfo = 0; codecInfo = (tA2D_APTX_CIE*) &ptr[3]; - if (codecInfo && codecInfo->vendorId == A2D_APTX_VENDOR_ID + if (codecInfo && codecInfo->vendorId == A2D_APTX_VENDOR_ID && codecInfo->codecId == A2D_APTX_CODEC_ID_BLUETOOTH) { tA2D_APTX_CIE aptx_config; @@ -1116,7 +1132,9 @@ static void btif_a2dp_encoder_init(tBTA_AV_HNDL hdl) tBTIF_MEDIA_INIT_AUDIO msg; tA2D_SBC_CIE sbc_config; tA2D_APTX_CIE* codecInfo = 0; - +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) + tA2D_AAC_CIE aac_config; +#endif /* lookup table for converting channel mode */ UINT16 codec_mode_tbl[5] = { SBC_JOINT_STEREO, SBC_STEREO, SBC_DUAL, 0, SBC_MONO }; @@ -1169,6 +1187,22 @@ static void btif_a2dp_encoder_init(tBTA_AV_HNDL hdl) } }/* if ( A2D_NON_A2DP_MEDIA_CT == codectype) */ + +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) + if (BTIF_AV_CODEC_M24 == codectype) { + ALOGI("%s Selected Codec AAC", __func__); + bta_av_co_audio_get_codec_config ((UINT8*)&aac_config, &minmtu, BTIF_AV_CODEC_M24); + msg.ObjectType = aac_config.object_type; + msg.ChannelMode = (aac_config.channels == A2D_AAC_IE_CHANNELS_2) ? SBC_STEREO : SBC_MONO; + msg.SamplingFreq = freq_block_tbl[aac_config.samp_freq >> 5]; + msg.MtuSize = minmtu; + msg.CodecType = BTIF_AV_CODEC_M24; + msg.bit_rate = aac_config.bit_rate; + btif_media_task_enc_init_req(&msg); + return; + } +#endif + ALOGI("%s Selected Codec SBC", __func__); /* Retrieve the current SBC configuration (default if currently not used) */ @@ -1191,6 +1225,9 @@ static void btif_a2dp_encoder_update(void) { UINT16 minmtu = 0; tA2D_SBC_CIE sbc_config; +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) + tA2D_AAC_CIE aac_config; +#endif tBTIF_MEDIA_UPDATE_AUDIO msg; UINT8 pref_min; UINT8 pref_max; @@ -1218,7 +1255,17 @@ static void btif_a2dp_encoder_update(void) msg.BluetoothCodecID = aptx_config.codecId; } } /* if (ptr) */ - } else { + } +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) + else if (codectype == BTIF_AV_CODEC_M24) { + bta_av_co_audio_get_aac_config(&aac_config, &minmtu); + + APPL_TRACE_DEBUG("btif_a2dp_encoder_update: AAC object_type :%d channels :%d", + aac_config.object_type, aac_config.channels); + msg.CodecType = BTIF_AV_CODEC_M24; + } +#endif + else { /* Retrieve the current SBC configuration (default if currently not used) */ bta_av_co_audio_get_sbc_config(&sbc_config, &minmtu); @@ -2464,7 +2511,16 @@ static void btif_media_task_enc_init(BT_HDR *p_msg) /* do nothing, fall through to SBC */ } } - +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) + else if (pInitAudio->CodecType == BTIF_AV_CODEC_M24) { + /*AAC is supported only in split mode, so only update the + required MTU size for AAC to send down to FW via VSC*/ + btif_media_cb.TxAaMtuSize = ((BTIF_MEDIA_AA_BUF_SIZE-BTIF_MEDIA_AA_AAC_OFFSET-sizeof(BT_HDR)) + < pInitAudio->MtuSize) ? (BTIF_MEDIA_AA_BUF_SIZE - BTIF_MEDIA_AA_AAC_OFFSET + - sizeof(BT_HDR)) : pInitAudio->MtuSize; + return; + } +#endif /* SBC encoder config (enforced even if not used) */ btif_media_cb.encoder.s16ChannelMode = pInitAudio->ChannelMode; btif_media_cb.encoder.s16NumOfSubBands = pInitAudio->NumOfSubBands; @@ -2541,6 +2597,17 @@ static void btif_media_task_enc_update(BT_HDR *p_msg) /* do nothing, fall through to SBC */ } } +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) + else if (pUpdateAudio->CodecType == BTIF_AV_CODEC_M24) { + APPL_TRACE_EVENT("%s AAC" , __func__); + btif_media_cb.TxAaMtuSize = ((BTIF_MEDIA_AA_BUF_SIZE - + BTIF_MEDIA_AA_AAC_OFFSET - sizeof(BT_HDR)) + < pUpdateAudio->MinMtuSize) ? (BTIF_MEDIA_AA_BUF_SIZE - BTIF_MEDIA_AA_AAC_OFFSET + - sizeof(BT_HDR)) : pUpdateAudio->MinMtuSize; + return; + } +#endif + else { if (!pstrEncParams->s16NumOfSubBands) { @@ -2887,6 +2954,7 @@ static void btif_media_task_audio_feeding_init(BT_HDR *p_msg) } } } + btif_media_cb.TxTranscoding = BTIF_MEDIA_TRSCD_PCM_2_SBC; btif_media_task_pcm2sbc_init(p_feeding); break; diff --git a/include/bt_target.h b/include/bt_target.h index 9e495553c..da845bf49 100644 --- a/include/bt_target.h +++ b/include/bt_target.h @@ -175,6 +175,11 @@ #define HL_INCLUDED TRUE #endif +#ifndef AAC_ENCODER_INCLUDED +#define AAC_ENCODER_INCLUDED TRUE +#endif + + #ifndef AG_VOICE_SETTINGS #define AG_VOICE_SETTINGS HCI_DEFAULT_VOICE_SETTINGS #endif @@ -1204,8 +1209,12 @@ * Audio*2 + Video*2 + 1 Additional */ #ifndef AVDT_NUM_SEPS +#if defined(AAC_ENCODER_INCLUDED) && (AAC_ENCODER_INCLUDED == TRUE) +#define AVDT_NUM_SEPS 7 +#else #define AVDT_NUM_SEPS 5 #endif +#endif /* Number of transport channels setup by AVDT for all media streams */ #ifndef AVDT_NUM_TC_TBL @@ -1405,6 +1414,10 @@ #define A2D_INCLUDED TRUE #endif +#ifndef A2D_M24_INCLUDED +#define A2D_M24_INCLUDED A2D_INCLUDED +#endif + /****************************************************************************** ** ** AVCTP diff --git a/stack/Android.mk b/stack/Android.mk index 4eb9ce822..ace03dd0d 100644 --- a/stack/Android.mk +++ b/stack/Android.mk @@ -39,6 +39,7 @@ LOCAL_SRC_FILES:= \ ./a2dp/a2d_api.c \ ./a2dp/a2d_sbc.c \ ./a2dp/a2d_aptx.c \ + ./a2dp/a2d_aac.c \ ./avrc/avrc_api.c \ ./avrc/avrc_sdp.c \ ./avrc/avrc_opt.c \ diff --git a/stack/a2dp/a2d_aac.c b/stack/a2dp/a2d_aac.c new file mode 100644 index 000000000..d299e00cb --- /dev/null +++ b/stack/a2dp/a2d_aac.c @@ -0,0 +1,175 @@ +/****************************************************************************** + * + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ +/****************************************************************************** + * + * Utility functions to help build and parse AAC Codec Information + * + ******************************************************************************/ + +#include "bt_target.h" +#include +#include "a2d_api.h" +#include "a2d_int.h" +#include "a2d_aac.h" +#include "bt_utils.h" + +#if (A2D_M24_INCLUDED == TRUE) +static UINT8 A2D_UINT32_BitsSet(UINT32 num); +/****************************************************************************** +** +** Function A2D_BldAacInfo +** +** Description This function builds byte sequence for +** Aac Codec Capabilities. +** Input : media_type: Audio or MultiMedia. +** p_ie: AAC Codec Information Element +** +** Output : p_result: codec info. +** +** Returns A2D_SUCCESS if successful. +** Error otherwise. +******************************************************************************/ +tA2D_STATUS A2D_BldAacInfo(UINT8 media_type, tA2D_AAC_CIE *p_ie, UINT8 *p_result) +{ + tA2D_STATUS status; + if( p_ie == NULL || p_result == NULL || + (p_ie->object_type & ~A2D_AAC_IE_OBJ_TYPE_MSK) || + (p_ie->samp_freq & ~A2D_AAC_IE_SAMP_FREQ_MSK) || + (p_ie->channels & ~A2D_AAC_IE_CHANNELS_MSK) || + (p_ie->bit_rate & ~A2D_AAC_IE_BIT_RATE_MSK) || + (p_ie->vbr & ~A2D_AAC_IE_VBR_MSK) ) + { + /* return invalid params if invalid bit is set */ + status = A2D_INVALID_PARAMS; + } + else + { + status = A2D_SUCCESS; + *p_result++ = A2D_AAC_INFO_LEN; + *p_result++ = media_type; + *p_result++ = A2D_MEDIA_CT_M24; + + /* Codec information */ + *p_result++ = p_ie->object_type; // object type + + *p_result++ = (UINT8)(p_ie->samp_freq >> 8); + + *p_result++ = (p_ie->samp_freq & 0x00F0)|p_ie->channels; + *p_result++ = p_ie->vbr | ((p_ie->bit_rate >> 16)& 0x007F); + *p_result++ = (p_ie->bit_rate >> 8)& 0x00FF; + *p_result = p_ie->bit_rate & 0x000000FF; + } + return status; +} + +/****************************************************************************** +** +** Function A2D_ParsAacInfo +** +** Description This function parse byte sequence for +** Aac Codec Capabilities. +** Input : p_info: input byte sequence. +** for_caps: True for getcap, false otherwise +** +** Output : p_ie: Aac codec information. +** +** Returns A2D_SUCCESS if successful. +** Error otherwise. +******************************************************************************/ +tA2D_STATUS A2D_ParsAacInfo(tA2D_AAC_CIE *p_ie, UINT8 *p_info, BOOLEAN for_caps) +{ + tA2D_STATUS status; + UINT8 losc; + UINT8 media_type; + + if( p_ie == NULL || p_info == NULL) + status = A2D_INVALID_PARAMS; + else + { + losc = *p_info++; + media_type = *p_info++; + /* Check for wrong length, media type */ + if(losc != A2D_AAC_INFO_LEN || *p_info != A2D_MEDIA_CT_M24) + status = A2D_WRONG_CODEC; + else + { + p_info++; + /* obj type */ + p_ie->object_type = *p_info & A2D_AAC_IE_OBJ_TYPE_MSK; p_info++; + /* samping freq */ + p_ie->samp_freq = *p_info; p_info++; + p_ie->samp_freq = p_ie->samp_freq << 8; + p_ie->samp_freq |= (*p_info & 0xF0); + /* channels */ + p_ie->channels = *p_info & A2D_AAC_IE_CHANNELS_MSK; p_info++; + /* variable bit rate */ + p_ie->vbr = *p_info & A2D_AAC_IE_VBR_MSK; + /* bit rate */ + p_ie->bit_rate = *p_info & 0x7F;p_ie->bit_rate = p_ie->bit_rate << 8; p_info++; + p_ie->bit_rate |= *p_info;p_ie->bit_rate = p_ie->bit_rate << 8; p_info++; + p_ie->bit_rate |= *p_info; + status = A2D_SUCCESS; + + if(for_caps == FALSE) + { + if(A2D_UINT32_BitsSet(p_ie->object_type) != A2D_SET_ONE_BIT) + status = A2D_BAD_OBJ_TYPE; + if(A2D_UINT32_BitsSet(p_ie->samp_freq) != A2D_SET_ONE_BIT) + status = A2D_BAD_SAMP_FREQ; + if(A2D_UINT32_BitsSet(p_ie->channels) != A2D_SET_ONE_BIT) + status = A2D_BAD_CHANNEL; + } + } + } + return status; +} +/****************************************************************************** +** Function A2D_UINT32_BitsSet +** +** Description Check the given number of 32bit for the number of bits set +** Returns A2D_SET_ONE_BIT, if one and only one bit is set +** A2D_SET_ZERO_BIT, if all bits clear +** A2D_SET_MULTL_BIT, if multiple bits are set +******************************************************************************/ +static UINT8 A2D_UINT32_BitsSet(UINT32 num) +{ + UINT8 count; + BOOLEAN res; + if(num == 0) + res = A2D_SET_ZERO_BIT; + else + { + count = (num & (num - 1)); + res = ((count==0)?A2D_SET_ONE_BIT:A2D_SET_MULTL_BIT); + } + return res; +} +#endif /* A2D_M24_INCLUDED == TRUE */ diff --git a/stack/include/a2d_aac.h b/stack/include/a2d_aac.h new file mode 100644 index 000000000..102de6787 --- /dev/null +++ b/stack/include/a2d_aac.h @@ -0,0 +1,149 @@ +/****************************************************************************** + * + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +#ifndef A2D_AAC_H +#define A2D_AAC_H + +/***************************************************************************** +** Constants +*****************************************************************************/ + +#define A2D_AAC_MPL_HDR_LEN 1 + +/* AAC media codec capabilitiy len*/ +#define A2D_AAC_INFO_LEN 8 + +/* AAC Codec Specific */ +#define A2D_AAC_IE_OBJ_TYPE_MSK 0xF0 /* b7-b4 Object Type */ +#define A2D_AAC_IE_OBJ_TYPE_MPEG_2_AAC_LC 0x80 /* b7:MPEG-2 AAC LC */ +#define A2D_AAC_IE_OBJ_TYPE_MPEG_4_AAC_LC 0x40 /* b7:MPEG-4 AAC LC */ +#define A2D_AAC_IE_OBJ_TYPE_MPEG_4_AAC_LTP 0x20 /* b7:MPEG-4 AAC LTP */ +#define A2D_AAC_IE_OBJ_TYPE_MPEG_4_AAC_SCA 0x10 /* b7:MPEG-4 AAC SCALABLE */ + +#define A2D_AAC_IE_SAMP_FREQ_MSK 0xFFF0 /* b15-b4 sampling frequency */ +#define A2D_AAC_IE_SAMP_FREQ_8000 0x8000 /* b15: 8000 */ +#define A2D_AAC_IE_SAMP_FREQ_11025 0x4000 /* b15: 11025 */ +#define A2D_AAC_IE_SAMP_FREQ_12000 0x2000 /* b15: 12000 */ +#define A2D_AAC_IE_SAMP_FREQ_16000 0x1000 /* b15: 16000 */ +#define A2D_AAC_IE_SAMP_FREQ_22050 0x0800 /* b15: 22050 */ +#define A2D_AAC_IE_SAMP_FREQ_24000 0x0400 /* b15: 24000 */ +#define A2D_AAC_IE_SAMP_FREQ_32000 0x0200 /* b15: 32000 */ +#define A2D_AAC_IE_SAMP_FREQ_44100 0x0100 /* b15: 441000 */ +#define A2D_AAC_IE_SAMP_FREQ_48000 0x0080 /* b15: 48000 */ +#define A2D_AAC_IE_SAMP_FREQ_64000 0x0040 /* b15: 64000 */ +#define A2D_AAC_IE_SAMP_FREQ_88200 0x0020 /* b15: 88200 */ +#define A2D_AAC_IE_SAMP_FREQ_96000 0x0010 /* b15: 96000 */ + + +#define A2D_AAC_IE_CHANNELS_MSK 0x0C /* b7-b6 channels supported */ +#define A2D_AAC_IE_CHANNELS_1 0x08 /* Channel 1 */ +#define A2D_AAC_IE_CHANNELS_2 0x04 /* Channel 2 */ + +#define A2D_AAC_IE_VBR_MSK 0x80 /* b7 variable bit rate */ +#define A2D_AAC_IE_VBR_SUPP 0x80 /* supported */ +#define A2D_AAC_IE_VBR_NOT_SUPP 0x00 /* supported */ + +#define A2D_AAC_IE_BIT_RATE_MSK 0x007FFFFF /* bit rate */ +#define A2D_AAC_IE_BIT_RATE 0x007FFFFF + + +#define BTIF_AAC_DEFAULT_BIT_RATE 0x000409B6 + +typedef struct { + INT16 s16SamplingFreq; /* 16k, 32k, 44.1k or 48k*/ + INT16 s16ChannelMode; /* mono, dual, streo or joint streo*/ + UINT16 u16BitRate; + UINT16 *ps16NextPcmBuffer; + UINT8 *pu8Packet; + UINT8 *pu8NextPacket; + UINT16 u16PacketLength; + void* encoder; +} A2D_AAC_ENC_PARAMS; + +/***************************************************************************** +** Type Definitions +*****************************************************************************/ + +/* AAC Codec Information data type */ +typedef struct +{ + UINT8 object_type; /* Object Type */ + UINT16 samp_freq; /* Sampling Frequency */ + UINT8 channels; /* Channels */ + UINT32 bit_rate; /* bit_rate */ + UINT8 vbr; /* variable bit rate */ +} tA2D_AAC_CIE; + + +/***************************************************************************** +** External Function Declarations +*****************************************************************************/ +#ifdef __cplusplus +extern "C" +{ +#endif +/****************************************************************************** +** +** Function A2D_BldAacInfo +** +** Description This function builds byte sequence for +** Aac Codec Capabilities. +** Input : media_type: Audio or MultiMedia. +** p_ie: AAC Codec Information Element +** +** Output : p_result: codec info. +** +** Returns A2D_SUCCESS if successful. +** Error otherwise. +******************************************************************************/ +extern tA2D_STATUS A2D_BldAacInfo(UINT8 media_type, tA2D_AAC_CIE *p_ie, UINT8 *p_result); + +/****************************************************************************** +** +** Function A2D_ParsAacInfo +** +** Description This function parse byte sequence for +** Aac Codec Capabilities. +** Input : p_info: input byte sequence. +** for_caps: True for getcap, false otherwise +** +** Output : p_ie: Aac codec information. +** +** Returns A2D_SUCCESS if successful. +** Error otherwise. +******************************************************************************/ +extern tA2D_STATUS A2D_ParsAacInfo(tA2D_AAC_CIE *p_ie, UINT8 *p_info, BOOLEAN for_caps); + +#ifdef __cplusplus +} +#endif + +#endif /* A2D_AAC_H */ -- cgit v1.2.3