From 936572fa132ffa0a150d826846bbd17fc53798fd Mon Sep 17 00:00:00 2001 From: liqigan Date: Mon, 21 Jun 2021 19:23:50 +0800 Subject: [PATCH] fix a2dp sink RxSbcQ bugs Closes https://github.com/espressif/esp-idf/issues/6712 Closes https://github.com/espressif/esp-idf/issues/7100 --- .../btc/profile/std/a2dp/btc_a2dp_sink.c | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c b/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c index e24b761e48..1316bbfb49 100644 --- a/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c +++ b/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c @@ -24,6 +24,7 @@ #include "common/bt_defs.h" #include "osi/allocator.h" #include "osi/mutex.h" +#include "osi/semaphore.h" #include "osi/thread.h" #include "osi/fixed_queue.h" #include "stack/a2d_api.h" @@ -86,8 +87,8 @@ enum { layers we might need to temporarily buffer up data */ /* 18 frames is equivalent to 6.89*18*2.9 ~= 360 ms @ 44.1 khz, 20 ms mediatick */ -#define JITTER_BUFFER_WATER_LEVEL (15) -#define MAX_OUTPUT_A2DP_SNK_FRAME_QUEUE_SZ (18 + JITTER_BUFFER_WATER_LEVEL) +#define MAX_OUTPUT_A2DP_SNK_FRAME_QUEUE_SZ (25) +#define JITTER_BUFFER_WATER_LEVEL (5) typedef struct { uint32_t sig; @@ -104,6 +105,7 @@ typedef struct { typedef struct { BOOLEAN rx_flush; /* discards any incoming data when true */ UINT8 channel_count; + osi_sem_t post_sem; fixed_queue_t *RxSbcQ; UINT32 sample_rate; } tBTC_A2DP_SINK_CB; @@ -153,7 +155,6 @@ static inline void btc_a2d_data_cb_to_app(const uint8_t *data, uint32_t len) } } - /***************************************************************************** ** Misc helper functions *****************************************************************************/ @@ -351,7 +352,9 @@ void btc_a2dp_sink_reset_decoder(UINT8 *p_av) static void btc_a2dp_sink_data_ready(UNUSED_ATTR void *context) { tBT_SBC_HDR *p_msg; + int nb_of_msgs_to_process = 0; + osi_sem_give(&a2dp_sink_local_param.btc_aa_snk_cb.post_sem); if (fixed_queue_is_empty(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ)) { APPL_TRACE_DEBUG(" QUE EMPTY "); } else { @@ -359,18 +362,20 @@ static void btc_a2dp_sink_data_ready(UNUSED_ATTR void *context) btc_a2dp_sink_flush_q(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ); return; } - - while ((p_msg = (tBT_SBC_HDR *)fixed_queue_try_peek_first(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ)) != NULL ) { + nb_of_msgs_to_process = fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ); + APPL_TRACE_DEBUG("nb:%d", nb_of_msgs_to_process); + while (nb_of_msgs_to_process > 0) { if (btc_a2dp_sink_state != BTC_A2DP_SINK_STATE_ON){ return; } - btc_a2dp_sink_handle_inc_media(p_msg); p_msg = (tBT_SBC_HDR *)fixed_queue_dequeue(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ, 0); if ( p_msg == NULL ) { APPL_TRACE_ERROR("Insufficient data in que "); break; } + btc_a2dp_sink_handle_inc_media(p_msg); osi_free(p_msg); + nb_of_msgs_to_process--; } APPL_TRACE_DEBUG(" Process Frames - "); } @@ -671,12 +676,11 @@ UINT8 btc_a2dp_sink_enque_buf(BT_HDR *p_pkt) p_msg->num_frames_to_be_processed = (*((UINT8 *)(p_msg + 1) + p_msg->offset)) & 0x0f; APPL_TRACE_VERBOSE("btc_a2dp_sink_enque_buf %d + \n", p_msg->num_frames_to_be_processed); fixed_queue_enqueue(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ, p_msg, FIXED_QUEUE_MAX_TIMEOUT); - - if (fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ) < JITTER_BUFFER_WATER_LEVEL) { - return fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ); + if (fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ) >= JITTER_BUFFER_WATER_LEVEL) { + if (osi_sem_take(&a2dp_sink_local_param.btc_aa_snk_cb.post_sem, 0) == 0) { + btc_a2dp_sink_data_post(); + } } - - btc_a2dp_sink_data_post(); } else { /* let caller deal with a failed allocation */ APPL_TRACE_WARNING("btc_a2dp_sink_enque_buf No Buffer left - "); @@ -711,7 +715,9 @@ static void btc_a2dp_sink_thread_init(UNUSED_ATTR void *context) memset(&a2dp_sink_local_param.btc_aa_snk_cb, 0, sizeof(a2dp_sink_local_param.btc_aa_snk_cb)); btc_a2dp_sink_state = BTC_A2DP_SINK_STATE_ON; - + if (!a2dp_sink_local_param.btc_aa_snk_cb.post_sem) { + osi_sem_new(&a2dp_sink_local_param.btc_aa_snk_cb.post_sem, 1, 1); + } a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ = fixed_queue_new(QUEUE_SIZE_MAX); btc_a2dp_control_init(); @@ -728,6 +734,11 @@ static void btc_a2dp_sink_thread_cleanup(UNUSED_ATTR void *context) fixed_queue_free(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ, osi_free_func); a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ = NULL; + + if (a2dp_sink_local_param.btc_aa_snk_cb.post_sem) { + osi_sem_free(&a2dp_sink_local_param.btc_aa_snk_cb.post_sem); + a2dp_sink_local_param.btc_aa_snk_cb.post_sem = NULL; + } } #endif /* BTC_AV_SINK_INCLUDED */