}
}
-OI_CODEC_SBC_DECODER_CONTEXT context;
-OI_UINT32 contextData[CODEC_DATA_WORDS(2, SBC_CODEC_FAST_FILTER_BUFFERS)];
-OI_INT16 pcmData[15 * SBC_MAX_SAMPLES_PER_FRAME * SBC_MAX_CHANNELS];
+#define BTC_SBC_DEC_CONTEXT_DATA_LEN (CODEC_DATA_WORDS(2, SBC_CODEC_FAST_FILTER_BUFFERS))
+#define BTC_SBC_DEC_PCM_DATA_LEN (15 * SBC_MAX_SAMPLES_PER_FRAME * SBC_MAX_CHANNELS)
+
+#if BTC_SBC_DEC_DYNAMIC_MEMORY == FALSE
+static OI_CODEC_SBC_DECODER_CONTEXT btc_sbc_decoder_context;
+static OI_UINT32 btc_sbc_decoder_context_data[BTC_SBC_DEC_CONTEXT_DATA_LEN];
+static OI_INT16 btc_sbc_pcm_data[BTC_SBC_DEC_PCM_DATA_LEN];
+#else
+static OI_CODEC_SBC_DECODER_CONTEXT *btc_sbc_decoder_context_ptr;
+static OI_UINT32 *btc_sbc_decoder_context_data;
+static OI_INT16 *btc_sbc_pcm_data;
+#define btc_sbc_decoder_context (*btc_sbc_decoder_context_ptr)
+#endif /* BTC_SBC_DEC_DYNAMIC_MEMORY == FALSE */
+
+
/*****************************************************************************
** Misc helper functions
APPL_TRACE_EVENT("## A2DP SINK START MEDIA THREAD ##");
+#if (BTC_SBC_DEC_DYNAMIC_MEMORY == TRUE)
+ btc_sbc_decoder_context_ptr = osi_calloc(sizeof(OI_CODEC_SBC_DECODER_CONTEXT));
+ btc_sbc_decoder_context_data = osi_calloc(BTC_SBC_DEC_CONTEXT_DATA_LEN * sizeof(OI_UINT32));
+ btc_sbc_pcm_data = osi_calloc(BTC_SBC_DEC_PCM_DATA_LEN * sizeof(OI_INT16));
+ if (!btc_sbc_decoder_context_ptr || !btc_sbc_decoder_context_data || !btc_sbc_pcm_data) {
+ APPL_TRACE_ERROR("failed to allocate SBC decoder");
+ goto error_exit;
+ }
+#endif /* BTC_SBC_DEC_DYNAMIC_MEMORY == TRUE */
+
btc_aa_snk_queue_set = xQueueCreateSet(BTC_A2DP_SINK_TASK_QUEUE_SET_LEN);
configASSERT(btc_aa_snk_queue_set);
btc_aa_snk_data_queue = xQueueCreate(BTC_A2DP_SINK_DATA_QUEUE_LEN, sizeof(int32_t));
vQueueDelete(btc_aa_snk_queue_set);
btc_aa_snk_queue_set = NULL;
}
+#if (BTC_SBC_DEC_DYNAMIC_MEMORY == TRUE)
+ if (btc_sbc_decoder_context_ptr) {
+ osi_free(btc_sbc_decoder_context_ptr);
+ btc_sbc_decoder_context_ptr = NULL;
+ }
+ if (btc_sbc_decoder_context_data) {
+ osi_free(btc_sbc_decoder_context_data);
+ btc_sbc_decoder_context_data = NULL;
+ }
+ if (btc_sbc_pcm_data) {
+ osi_free(btc_sbc_pcm_data);
+ btc_sbc_pcm_data = NULL;
+ }
+#endif /* BTC_SBC_DEC_DYNAMIC_MEMORY == TRUE */
+
return false;
}
vQueueDelete(btc_aa_snk_queue_set);
btc_aa_snk_queue_set = NULL;
+
+#if (BTC_SBC_DEC_DYNAMIC_MEMORY == TRUE)
+ osi_free(btc_sbc_decoder_context_ptr);
+ btc_sbc_decoder_context_ptr = NULL;
+
+ osi_free(btc_sbc_decoder_context_data);
+ btc_sbc_decoder_context_data = NULL;
+
+ osi_free(btc_sbc_pcm_data);
+ btc_sbc_pcm_data = NULL;
+#endif /* BTC_SBC_DEC_DYNAMIC_MEMORY == TRUE */
}
/*****************************************************************************
btc_aa_snk_cb.rx_flush = FALSE;
APPL_TRACE_EVENT("Reset to sink role");
- status = OI_CODEC_SBC_DecoderReset(&context, contextData, sizeof(contextData), 2, 2, FALSE);
+ status = OI_CODEC_SBC_DecoderReset(&btc_sbc_decoder_context, btc_sbc_decoder_context_data,
+ BTC_SBC_DEC_CONTEXT_DATA_LEN * sizeof(OI_UINT32), 2, 2, FALSE);
if (!OI_SUCCESS(status)) {
APPL_TRACE_ERROR("OI_CODEC_SBC_DecoderReset failed with error code %d\n", status);
}
UINT8 *sbc_start_frame = ((UINT8 *)(p_msg + 1) + p_msg->offset + 1);
int count;
UINT32 pcmBytes, availPcmBytes;
- OI_INT16 *pcmDataPointer = pcmData; /*Will be overwritten on next packet receipt*/
+ OI_INT16 *pcmDataPointer = btc_sbc_pcm_data; /*Will be overwritten on next packet receipt*/
OI_STATUS status;
int num_sbc_frames = p_msg->num_frames_to_be_processed;
UINT32 sbc_frame_len = p_msg->len - 1;
- availPcmBytes = sizeof(pcmData);
+ availPcmBytes = BTC_SBC_DEC_PCM_DATA_LEN * sizeof(OI_INT16);
/* XXX: Check if the below check is correct, we are checking for peer to be sink when we are sink */
if (btc_av_get_peer_sep() == AVDT_TSEP_SNK || (btc_aa_snk_cb.rx_flush)) {
for (count = 0; count < num_sbc_frames && sbc_frame_len != 0; count ++) {
pcmBytes = availPcmBytes;
- status = OI_CODEC_SBC_DecodeFrame(&context, (const OI_BYTE **)&sbc_start_frame,
+ status = OI_CODEC_SBC_DecodeFrame(&btc_sbc_decoder_context, (const OI_BYTE **)&sbc_start_frame,
(OI_UINT32 *)&sbc_frame_len,
(OI_INT16 *)pcmDataPointer,
(OI_UINT32 *)&pcmBytes);
p_msg->len = sbc_frame_len + 1;
}
- btc_a2d_data_cb_to_app((uint8_t *)pcmData, (sizeof(pcmData) - availPcmBytes));
+ btc_a2d_data_cb_to_app((uint8_t *)btc_sbc_pcm_data, (BTC_SBC_DEC_PCM_DATA_LEN * sizeof(OI_INT16) - availPcmBytes));
}
/*******************************************************************************
tBTC_AV_FEEDING_MODE feeding_mode;
tBTC_AV_MEDIA_FEEDINGS_STATE media_feeding_state;
tBTC_AV_MEDIA_FEEDINGS media_feeding;
- SBC_ENC_PARAMS encoder;
osi_alarm_t *media_alarm;
} tBTC_A2DP_SOURCE_CB;
static esp_a2d_source_data_cb_t btc_aa_src_data_cb = NULL;
static UINT64 last_frame_us = 0;
+#if BTC_SBC_ENC_DYNAMIC_MEMORY == FALSE
+static SBC_ENC_PARAMS btc_sbc_encoder;
+#else
+static SBC_ENC_PARAMS *btc_sbc_encoder_ptr;
+#define btc_sbc_encoder (*btc_sbc_encoder_ptr)
+#endif /* BTC_SBC_ENC_DYNAMIC_MEMORY == FALSE */
+
void btc_a2dp_src_reg_data_cb(esp_a2d_source_data_cb_t callback)
{
// todo: critical section protection
APPL_TRACE_EVENT("## A2DP SOURCE START MEDIA THREAD ##");
+#if BTC_SBC_ENC_DYNAMIC_MEMORY == TRUE
+ btc_sbc_encoder_ptr = osi_calloc(sizeof(SBC_ENC_PARAMS));
+ if (!btc_sbc_encoder_ptr) {
+ APPL_TRACE_ERROR("failed to allocate SBC encoder");
+ goto error_exit;
+ }
+#endif /* #if BTC_SBC_ENC_DYNAMIC_MEMORY == TRUE */
+
btc_aa_src_queue_set = xQueueCreateSet(BTC_A2DP_SOURCE_TASK_QUEUE_SET_LEN);
configASSERT(btc_aa_src_queue_set);
btc_aa_src_data_queue = xQueueCreate(BTC_A2DP_SOURCE_DATA_QUEUE_LEN, sizeof(void *));
vQueueDelete(btc_aa_src_queue_set);
btc_aa_src_queue_set = NULL;
}
+#if (BTC_SBC_ENC_DYNAMIC_MEMORY == TRUE)
+ if (btc_sbc_encoder_ptr) {
+ osi_free(btc_sbc_encoder_ptr);
+ btc_sbc_encoder_ptr = NULL;
+ }
+#endif /* #if BTC_SBC_ENC_DYNAMIC_MEMORY == TRUE */
return false;
}
vQueueDelete(btc_aa_src_queue_set);
btc_aa_src_queue_set = NULL;
+
+#if (BTC_SBC_ENC_DYNAMIC_MEMORY == TRUE)
+ osi_free(btc_sbc_encoder_ptr);
+ btc_sbc_encoder_ptr = NULL;
+#endif /* #if BTC_SBC_ENC_DYNAMIC_MEMORY == TRUE */
}
/*****************************************************************************
btc_aa_src_cb.timestamp = 0;
/* SBC encoder config (enforced even if not used) */
- btc_aa_src_cb.encoder.s16ChannelMode = pInitAudio->ChannelMode;
- btc_aa_src_cb.encoder.s16NumOfSubBands = pInitAudio->NumOfSubBands;
- btc_aa_src_cb.encoder.s16NumOfBlocks = pInitAudio->NumOfBlocks;
- btc_aa_src_cb.encoder.s16AllocationMethod = pInitAudio->AllocationMethod;
- btc_aa_src_cb.encoder.s16SamplingFreq = pInitAudio->SamplingFreq;
- btc_aa_src_cb.encoder.u16BitRate = btc_a2dp_source_get_sbc_rate();
+ btc_sbc_encoder.s16ChannelMode = pInitAudio->ChannelMode;
+ btc_sbc_encoder.s16NumOfSubBands = pInitAudio->NumOfSubBands;
+ btc_sbc_encoder.s16NumOfBlocks = pInitAudio->NumOfBlocks;
+ btc_sbc_encoder.s16AllocationMethod = pInitAudio->AllocationMethod;
+ btc_sbc_encoder.s16SamplingFreq = pInitAudio->SamplingFreq;
+
+ btc_sbc_encoder.u16BitRate = btc_a2dp_source_get_sbc_rate();
/* Default transcoding is PCM to SBC, modified by feeding configuration */
btc_aa_src_cb.TxTranscoding = BTC_MEDIA_TRSCD_PCM_2_SBC;
APPL_TRACE_EVENT("btc_a2dp_source_enc_init mtu %d, peer mtu %d",
btc_aa_src_cb.TxAaMtuSize, pInitAudio->MtuSize);
APPL_TRACE_EVENT(" ch mode %d, subnd %d, nb blk %d, alloc %d, rate %d, freq %d",
- btc_aa_src_cb.encoder.s16ChannelMode, btc_aa_src_cb.encoder.s16NumOfSubBands,
- btc_aa_src_cb.encoder.s16NumOfBlocks,
- btc_aa_src_cb.encoder.s16AllocationMethod, btc_aa_src_cb.encoder.u16BitRate,
- btc_aa_src_cb.encoder.s16SamplingFreq);
+ btc_sbc_encoder.s16ChannelMode, btc_sbc_encoder.s16NumOfSubBands,
+ btc_sbc_encoder.s16NumOfBlocks,
+ btc_sbc_encoder.s16AllocationMethod, btc_sbc_encoder.u16BitRate,
+ btc_sbc_encoder.s16SamplingFreq);
/* Reset entirely the SBC encoder */
- SBC_Encoder_Init(&(btc_aa_src_cb.encoder));
- APPL_TRACE_DEBUG("btc_a2dp_source_enc_init bit pool %d", btc_aa_src_cb.encoder.s16BitPool);
+ SBC_Encoder_Init(&(btc_sbc_encoder));
+ APPL_TRACE_DEBUG("btc_a2dp_source_enc_init bit pool %d", btc_sbc_encoder.s16BitPool);
}
static void btc_a2dp_source_enc_update(BT_HDR *p_msg)
{
tBTC_MEDIA_UPDATE_AUDIO *pUpdateAudio = (tBTC_MEDIA_UPDATE_AUDIO *) p_msg;
- SBC_ENC_PARAMS *pstrEncParams = &btc_aa_src_cb.encoder;
+ SBC_ENC_PARAMS *pstrEncParams = &btc_sbc_encoder;
UINT16 s16SamplingFreq;
SINT16 s16BitPool = 0;
SINT16 s16BitRate;
if (s16BitPool > pUpdateAudio->MaxBitPool) {
APPL_TRACE_DEBUG("%s computed bitpool too large (%d)", __FUNCTION__, s16BitPool);
/* Decrease bitrate */
- btc_aa_src_cb.encoder.u16BitRate -= BTC_MEDIA_BITRATE_STEP;
+ btc_sbc_encoder.u16BitRate -= BTC_MEDIA_BITRATE_STEP;
/* Record that we have decreased the bitrate */
protect |= 1;
} else if (s16BitPool < pUpdateAudio->MinBitPool) {
APPL_TRACE_WARNING("%s computed bitpool too small (%d)", __FUNCTION__, s16BitPool);
/* Increase bitrate */
- UINT16 previous_u16BitRate = btc_aa_src_cb.encoder.u16BitRate;
- btc_aa_src_cb.encoder.u16BitRate += BTC_MEDIA_BITRATE_STEP;
+ UINT16 previous_u16BitRate = btc_sbc_encoder.u16BitRate;
+ btc_sbc_encoder.u16BitRate += BTC_MEDIA_BITRATE_STEP;
/* Record that we have increased the bitrate */
protect |= 2;
/* Check over-flow */
- if (btc_aa_src_cb.encoder.u16BitRate < previous_u16BitRate) {
+ if (btc_sbc_encoder.u16BitRate < previous_u16BitRate) {
protect |= 3;
}
} else {
pstrEncParams->s16BitPool = s16BitPool;
APPL_TRACE_DEBUG("%s final bit rate %d, final bit pool %d", __FUNCTION__,
- btc_aa_src_cb.encoder.u16BitRate, btc_aa_src_cb.encoder.s16BitPool);
+ btc_sbc_encoder.u16BitRate, btc_sbc_encoder.s16BitPool);
/* make sure we reinitialize encoder with new settings */
- SBC_Encoder_Init(&(btc_aa_src_cb.encoder));
+ SBC_Encoder_Init(&(btc_sbc_encoder));
}
}
case 32000:
case 48000:
/* For these sampling_freq the AV connection must be 48000 */
- if (btc_aa_src_cb.encoder.s16SamplingFreq != SBC_sf48000) {
+ if (btc_sbc_encoder.s16SamplingFreq != SBC_sf48000) {
/* Reconfiguration needed at 48000 */
APPL_TRACE_DEBUG("SBC Reconfiguration needed at 48000");
- btc_aa_src_cb.encoder.s16SamplingFreq = SBC_sf48000;
+ btc_sbc_encoder.s16SamplingFreq = SBC_sf48000;
reconfig_needed = TRUE;
}
break;
case 22050:
case 44100:
/* For these sampling_freq the AV connection must be 44100 */
- if (btc_aa_src_cb.encoder.s16SamplingFreq != SBC_sf44100) {
+ if (btc_sbc_encoder.s16SamplingFreq != SBC_sf44100) {
/* Reconfiguration needed at 44100 */
APPL_TRACE_DEBUG("SBC Reconfiguration needed at 44100");
- btc_aa_src_cb.encoder.s16SamplingFreq = SBC_sf44100;
+ btc_sbc_encoder.s16SamplingFreq = SBC_sf44100;
reconfig_needed = TRUE;
}
break;
}
/* Some AV Headsets do not support Mono => always ask for Stereo */
- if (btc_aa_src_cb.encoder.s16ChannelMode == SBC_MONO) {
+ if (btc_sbc_encoder.s16ChannelMode == SBC_MONO) {
APPL_TRACE_DEBUG("SBC Reconfiguration needed in Stereo");
- btc_aa_src_cb.encoder.s16ChannelMode = SBC_JOINT_STEREO;
+ btc_sbc_encoder.s16ChannelMode = SBC_JOINT_STEREO;
reconfig_needed = TRUE;
}
if (reconfig_needed != FALSE) {
APPL_TRACE_DEBUG("%s :: mtu %d", __FUNCTION__, btc_aa_src_cb.TxAaMtuSize);
APPL_TRACE_DEBUG("ch mode %d, nbsubd %d, nb %d, alloc %d, rate %d, freq %d",
- btc_aa_src_cb.encoder.s16ChannelMode,
- btc_aa_src_cb.encoder.s16NumOfSubBands, btc_aa_src_cb.encoder.s16NumOfBlocks,
- btc_aa_src_cb.encoder.s16AllocationMethod, btc_aa_src_cb.encoder.u16BitRate,
- btc_aa_src_cb.encoder.s16SamplingFreq);
+ btc_sbc_encoder.s16ChannelMode,
+ btc_sbc_encoder.s16NumOfSubBands, btc_sbc_encoder.s16NumOfBlocks,
+ btc_sbc_encoder.s16AllocationMethod, btc_sbc_encoder.u16BitRate,
+ btc_sbc_encoder.s16SamplingFreq);
- SBC_Encoder_Init(&(btc_aa_src_cb.encoder));
+ SBC_Encoder_Init(&(btc_sbc_encoder));
} else {
APPL_TRACE_DEBUG("%s no SBC reconfig needed", __FUNCTION__);
}
switch (btc_aa_src_cb.TxTranscoding) {
case BTC_MEDIA_TRSCD_PCM_2_SBC: {
- UINT32 pcm_bytes_per_frame = btc_aa_src_cb.encoder.s16NumOfSubBands *
- btc_aa_src_cb.encoder.s16NumOfBlocks *
+ UINT32 pcm_bytes_per_frame = btc_sbc_encoder.s16NumOfSubBands *
+ btc_sbc_encoder.s16NumOfBlocks *
btc_aa_src_cb.media_feeding.cfg.pcm.num_channel *
btc_aa_src_cb.media_feeding.cfg.pcm.bit_per_sample / 8;
BOOLEAN btc_media_aa_read_feeding(void)
{
- UINT16 blocm_x_subband = btc_aa_src_cb.encoder.s16NumOfSubBands * \
- btc_aa_src_cb.encoder.s16NumOfBlocks;
+ UINT16 blocm_x_subband = btc_sbc_encoder.s16NumOfSubBands * \
+ btc_sbc_encoder.s16NumOfBlocks;
UINT32 read_size;
UINT16 sbc_sampling = 48000;
UINT32 src_samples;
- UINT16 bytes_needed = blocm_x_subband * btc_aa_src_cb.encoder.s16NumOfChannels * \
+ UINT16 bytes_needed = blocm_x_subband * btc_sbc_encoder.s16NumOfChannels * \
btc_aa_src_cb.media_feeding.cfg.pcm.bit_per_sample / 8;
static UINT16 up_sampled_buffer[SBC_MAX_NUM_FRAME * SBC_MAX_NUM_OF_BLOCKS
* SBC_MAX_NUM_OF_CHANNELS * SBC_MAX_NUM_OF_SUBBANDS * 2];
UINT32 nb_byte_read = 0;
/* Get the SBC sampling rate */
- switch (btc_aa_src_cb.encoder.s16SamplingFreq) {
+ switch (btc_sbc_encoder.s16SamplingFreq) {
case SBC_sf48000:
sbc_sampling = 48000;
break;
if (sbc_sampling == btc_aa_src_cb.media_feeding.cfg.pcm.sampling_freq) {
read_size = bytes_needed - btc_aa_src_cb.media_feeding_state.pcm.aa_feed_residue;
nb_byte_read = btc_aa_src_data_read(
- ((uint8_t *)btc_aa_src_cb.encoder.as16PcmBuffer) +
+ ((uint8_t *)btc_sbc_encoder.as16PcmBuffer) +
btc_aa_src_cb.media_feeding_state.pcm.aa_feed_residue,
read_size);
if (nb_byte_read == read_size) {
/* only copy the pcm sample when we have up-sampled enough PCM */
if (btc_aa_src_cb.media_feeding_state.pcm.aa_feed_residue >= bytes_needed) {
/* Copy the output pcm samples in SBC encoding buffer */
- memcpy((UINT8 *)btc_aa_src_cb.encoder.as16PcmBuffer,
+ memcpy((UINT8 *)btc_sbc_encoder.as16PcmBuffer,
(UINT8 *)up_sampled_buffer,
bytes_needed);
/* update the residue */
static void btc_media_aa_prep_sbc_2_send(UINT8 nb_frame)
{
BT_HDR *p_buf;
- UINT16 blocm_x_subband = btc_aa_src_cb.encoder.s16NumOfSubBands *
- btc_aa_src_cb.encoder.s16NumOfBlocks;
+ UINT16 blocm_x_subband = btc_sbc_encoder.s16NumOfSubBands *
+ btc_sbc_encoder.s16NumOfBlocks;
while (nb_frame) {
if (NULL == (p_buf = osi_malloc(BTC_MEDIA_AA_BUF_SIZE))) {
do {
/* Write @ of allocated buffer in encoder.pu8Packet */
- btc_aa_src_cb.encoder.pu8Packet = (UINT8 *) (p_buf + 1) + p_buf->offset + p_buf->len;
+ btc_sbc_encoder.pu8Packet = (UINT8 *) (p_buf + 1) + p_buf->offset + p_buf->len;
/* Fill allocated buffer with 0 */
- memset(btc_aa_src_cb.encoder.as16PcmBuffer, 0, blocm_x_subband
- * btc_aa_src_cb.encoder.s16NumOfChannels);
+ memset(btc_sbc_encoder.as16PcmBuffer, 0, blocm_x_subband
+ * btc_sbc_encoder.s16NumOfChannels);
/* Read PCM data and upsample them if needed */
if (btc_media_aa_read_feeding()) {
/* SBC encode and descramble frame */
- SBC_Encoder(&(btc_aa_src_cb.encoder));
- A2D_SbcChkFrInit(btc_aa_src_cb.encoder.pu8Packet);
- A2D_SbcDescramble(btc_aa_src_cb.encoder.pu8Packet, btc_aa_src_cb.encoder.u16PacketLength);
+ SBC_Encoder(&(btc_sbc_encoder));
+ A2D_SbcChkFrInit(btc_sbc_encoder.pu8Packet);
+ A2D_SbcDescramble(btc_sbc_encoder.pu8Packet, btc_sbc_encoder.u16PacketLength);
/* Update SBC frame length */
- p_buf->len += btc_aa_src_cb.encoder.u16PacketLength;
+ p_buf->len += btc_sbc_encoder.u16PacketLength;
nb_frame--;
p_buf->layer_specific++;
} else {
APPL_TRACE_WARNING("btc_media_aa_prep_sbc_2_send underflow %d, %d",
nb_frame, btc_aa_src_cb.media_feeding_state.pcm.aa_feed_residue);
btc_aa_src_cb.media_feeding_state.pcm.counter += nb_frame *
- btc_aa_src_cb.encoder.s16NumOfSubBands *
- btc_aa_src_cb.encoder.s16NumOfBlocks *
+ btc_sbc_encoder.s16NumOfSubBands *
+ btc_sbc_encoder.s16NumOfBlocks *
btc_aa_src_cb.media_feeding.cfg.pcm.num_channel *
btc_aa_src_cb.media_feeding.cfg.pcm.bit_per_sample / 8;
/* no more pcm to read */
}
}
- } while (((p_buf->len + btc_aa_src_cb.encoder.u16PacketLength) < btc_aa_src_cb.TxAaMtuSize)
+ } while (((p_buf->len + btc_sbc_encoder.u16PacketLength) < btc_aa_src_cb.TxAaMtuSize)
&& (p_buf->layer_specific < 0x0F) && nb_frame);
if (p_buf->len) {