1 /*
2  * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /******************************************************************************
8  **
9  **  Name:          btc_a2dp_sink.c
10  **
11  ******************************************************************************/
12 #include "common/bt_target.h"
13 #include "common/bt_trace.h"
14 #include <string.h>
15 #include <stdint.h>
16 #include "common/bt_defs.h"
17 #include "osi/allocator.h"
18 #include "osi/mutex.h"
19 #include "osi/thread.h"
20 #include "osi/fixed_queue.h"
21 #include "stack/a2d_api.h"
22 #include "stack/a2d_sbc.h"
23 #include "bta/bta_av_api.h"
24 #include "bta/bta_av_ci.h"
25 #include "btc_av_co.h"
26 #include "btc_a2dp.h"
27 #include "btc_a2dp_control.h"
28 #include "btc_a2dp_sink.h"
29 #include "btc/btc_manage.h"
30 #include "btc_av.h"
31 #include "btc/btc_util.h"
32 #include "esp_a2dp_api.h"
33 #include "oi_codec_sbc.h"
34 #include "oi_status.h"
35 #include "osi/future.h"
36 #include <assert.h>
37 
38 #if (BTC_AV_SINK_INCLUDED == TRUE)
39 
40 /*****************************************************************************
41  **  Constants
42  *****************************************************************************/
43 
44 /* BTC media cmd event definition : BTC_MEDIA_TASK_CMD */
45 enum {
46     BTC_MEDIA_TASK_SINK_INIT,
47     BTC_MEDIA_TASK_SINK_CLEAN_UP,
48     BTC_MEDIA_FLUSH_AA_RX,
49     BTC_MEDIA_AUDIO_SINK_CFG_UPDATE,
50     BTC_MEDIA_AUDIO_SINK_CLEAR_TRACK,
51 };
52 
53 enum {
54     BTC_A2DP_SINK_STATE_OFF = 0,
55     BTC_A2DP_SINK_STATE_ON = 1,
56     BTC_A2DP_SINK_STATE_SHUTTING_DOWN = 2
57 };
58 
59 /*
60  * CONGESTION COMPENSATION CTRL ::
61  *
62  * Thus setting controls how many buffers we will hold in media task
63  * during temp link congestion. Together with the stack buffer queues
64  * it controls much temporary a2dp link congestion we can
65  * compensate for. It however also depends on the default run level of sinks
66  * jitterbuffers. Depending on type of sink this would vary.
67  * Ideally the (SRC) max tx buffer capacity should equal the sinks
68  * jitterbuffer runlevel including any intermediate buffers on the way
69  * towards the sinks codec.
70  */
71 
72 /* fixme -- define this in pcm time instead of buffer count */
73 
74 /* The typical runlevel of the tx queue size is ~1 buffer
75    but due to link flow control or thread preemption in lower
76    layers we might need to temporarily buffer up data */
77 
78 /* 18 frames is equivalent to 6.89*18*2.9 ~= 360 ms @ 44.1 khz, 20 ms mediatick */
79 #define MAX_OUTPUT_A2DP_SNK_FRAME_QUEUE_SZ     (25)
80 
81 #define BTC_A2DP_SNK_DATA_QUEUE_IDX            (1)
82 
83 typedef struct {
84     uint32_t sig;
85     void *param;
86 } a2dp_sink_task_evt_t;
87 
88 typedef struct {
89     UINT16 num_frames_to_be_processed;
90     UINT16 len;
91     UINT16 offset;
92     UINT16 layer_specific;
93 } tBT_SBC_HDR;
94 
95 typedef struct {
96     BOOLEAN rx_flush; /* discards any incoming data when true */
97     UINT8   channel_count;
98     struct osi_event *data_ready_event;
99     fixed_queue_t *RxSbcQ;
100     UINT32  sample_rate;
101 } tBTC_A2DP_SINK_CB;
102 
103 typedef struct {
104     uint16_t expected_seq_num;
105     bool seq_num_recount;
106 } a2dp_sink_media_pkt_seq_num_t;
107 
108 typedef struct {
109     tBTC_A2DP_SINK_CB   btc_aa_snk_cb;
110     osi_thread_t        *btc_aa_snk_task_hdl;
111     OI_CODEC_SBC_DECODER_CONTEXT    context;
112     OI_UINT32           contextData[CODEC_DATA_WORDS(2, SBC_CODEC_FAST_FILTER_BUFFERS)];
113     OI_INT16            pcmData[15 * SBC_MAX_SAMPLES_PER_FRAME * SBC_MAX_CHANNELS];
114     a2dp_sink_media_pkt_seq_num_t   media_pkt_seq_num;
115 } a2dp_sink_local_param_t;
116 
117 static void btc_a2dp_sink_thread_init(UNUSED_ATTR void *context);
118 static void btc_a2dp_sink_thread_cleanup(UNUSED_ATTR void *context);
119 static void btc_a2dp_sink_flush_q(fixed_queue_t *p_q);
120 static void btc_a2dp_sink_rx_flush(void);
121 static int btc_a2dp_sink_get_track_frequency(UINT8 frequency);
122 static int btc_a2dp_sink_get_track_channel_count(UINT8 channeltype);
123 /* Handle incoming media packets A2DP SINK streaming*/
124 static void btc_a2dp_sink_handle_inc_media(tBT_SBC_HDR *p_msg);
125 static void btc_a2dp_sink_handle_decoder_reset(tBTC_MEDIA_SINK_CFG_UPDATE *p_msg);
126 static void btc_a2dp_sink_handle_clear_track(void);
127 static BOOLEAN btc_a2dp_sink_clear_track(void);
128 
129 static void btc_a2dp_sink_data_ready(void *context);
130 
131 static int btc_a2dp_sink_state = BTC_A2DP_SINK_STATE_OFF;
132 static esp_a2d_sink_data_cb_t bt_aa_snk_data_cb = NULL;
133 #if A2D_DYNAMIC_MEMORY == FALSE
134 static a2dp_sink_local_param_t a2dp_sink_local_param;
135 #else
136 static a2dp_sink_local_param_t *a2dp_sink_local_param_ptr;
137 #define a2dp_sink_local_param (*a2dp_sink_local_param_ptr)
138 #endif ///A2D_DYNAMIC_MEMORY == FALSE
139 
btc_a2dp_sink_reg_data_cb(esp_a2d_sink_data_cb_t callback)140 void btc_a2dp_sink_reg_data_cb(esp_a2d_sink_data_cb_t callback)
141 {
142     // todo: critical section protection
143     bt_aa_snk_data_cb = callback;
144 }
145 
btc_a2d_data_cb_to_app(const uint8_t * data,uint32_t len)146 static inline void btc_a2d_data_cb_to_app(const uint8_t *data, uint32_t len)
147 {
148     // todo: critical section protection
149     if (bt_aa_snk_data_cb) {
150         bt_aa_snk_data_cb(data, len);
151     }
152 }
153 
154 /*****************************************************************************
155  **  Misc helper functions
156  *****************************************************************************/
btc_a2d_cb_to_app(esp_a2d_cb_event_t event,esp_a2d_cb_param_t * param)157 static inline void btc_a2d_cb_to_app(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param)
158 {
159     esp_a2d_cb_t btc_aa_cb = (esp_a2d_cb_t)btc_profile_cb_get(BTC_PID_A2DP);
160     if (btc_aa_cb) {
161         btc_aa_cb(event, param);
162     }
163 }
164 
165 /*****************************************************************************
166  **  BTC ADAPTATION
167  *****************************************************************************/
168 
btc_a2dp_sink_ctrl(uint32_t sig,void * param)169 static bool btc_a2dp_sink_ctrl(uint32_t sig, void *param)
170 {
171     switch (sig) {
172     case BTC_MEDIA_TASK_SINK_INIT:
173         btc_a2dp_sink_thread_init(NULL);
174         break;
175     case BTC_MEDIA_TASK_SINK_CLEAN_UP:
176         btc_a2dp_sink_thread_cleanup(NULL);
177         break;
178     case BTC_MEDIA_AUDIO_SINK_CFG_UPDATE:
179         btc_a2dp_sink_handle_decoder_reset(param);
180         break;
181     case BTC_MEDIA_AUDIO_SINK_CLEAR_TRACK:
182         btc_a2dp_sink_handle_clear_track();
183         break;
184     case BTC_MEDIA_FLUSH_AA_RX:
185         btc_a2dp_sink_rx_flush();
186         break;
187     default:
188         APPL_TRACE_WARNING("media task unhandled evt: 0x%x\n", sig);
189     }
190 
191     if (param != NULL) {
192         osi_free(param);
193     }
194 
195     return true;
196 }
197 
btc_a2dp_sink_startup(void)198 bool btc_a2dp_sink_startup(void)
199 {
200     if (btc_a2dp_sink_state != BTC_A2DP_SINK_STATE_OFF) {
201         APPL_TRACE_ERROR("warning : media task already running");
202         return false;
203     }
204 
205 #if A2D_DYNAMIC_MEMORY == TRUE
206     if ((a2dp_sink_local_param_ptr = (a2dp_sink_local_param_t *)osi_malloc(sizeof(a2dp_sink_local_param_t))) == NULL) {
207         APPL_TRACE_ERROR("%s malloc failed!", __func__);
208         return false;
209     }
210     memset((void *)a2dp_sink_local_param_ptr, 0, sizeof(a2dp_sink_local_param_t));
211 #endif
212 
213     APPL_TRACE_EVENT("## A2DP SINK START MEDIA THREAD ##");
214 
215     a2dp_sink_local_param.btc_aa_snk_task_hdl = btc_get_current_thread();
216 
217     if (btc_a2dp_sink_ctrl(BTC_MEDIA_TASK_SINK_INIT, NULL) == false) {
218         goto error_exit;
219     }
220 
221     APPL_TRACE_EVENT("## A2DP SINK MEDIA THREAD STARTED ##\n");
222 
223     return true;
224 
225 error_exit:;
226     APPL_TRACE_ERROR("%s unable to start up media thread\n", __func__);
227     a2dp_sink_local_param.btc_aa_snk_task_hdl = NULL;
228 
229 #if A2D_DYNAMIC_MEMORY == TRUE
230     osi_free(a2dp_sink_local_param_ptr);
231     a2dp_sink_local_param_ptr = NULL;
232 #endif
233 
234     return false;
235 }
236 
btc_a2dp_sink_shutdown(void)237 void btc_a2dp_sink_shutdown(void)
238 {
239     APPL_TRACE_EVENT("## A2DP SINK STOP MEDIA THREAD ##\n");
240 
241     // Exit thread
242     btc_a2dp_sink_state = BTC_A2DP_SINK_STATE_SHUTTING_DOWN;
243 
244     btc_a2dp_sink_ctrl(BTC_MEDIA_TASK_SINK_CLEAN_UP, NULL);
245 
246     a2dp_sink_local_param.btc_aa_snk_task_hdl = NULL;
247 
248 #if A2D_DYNAMIC_MEMORY == TRUE
249     osi_free(a2dp_sink_local_param_ptr);
250     a2dp_sink_local_param_ptr = NULL;
251 #endif
252 }
253 
254 /*****************************************************************************
255 **
256 ** Function        btc_a2dp_sink_on_idle
257 **
258 *******************************************************************************/
259 
btc_a2dp_sink_on_idle(void)260 void btc_a2dp_sink_on_idle(void)
261 {
262     a2dp_sink_local_param.btc_aa_snk_cb.rx_flush = TRUE;
263     btc_a2dp_sink_rx_flush_req();
264     btc_a2dp_sink_clear_track();
265 
266     APPL_TRACE_DEBUG("Stopped BT track");
267 }
268 
269 /*****************************************************************************
270 **
271 ** Function        btc_a2dp_sink_on_stopped
272 **
273 *******************************************************************************/
274 
btc_a2dp_sink_on_stopped(tBTA_AV_SUSPEND * p_av)275 void btc_a2dp_sink_on_stopped(tBTA_AV_SUSPEND *p_av)
276 {
277     a2dp_sink_local_param.btc_aa_snk_cb.rx_flush = TRUE;
278     btc_a2dp_sink_rx_flush_req();
279     btc_a2dp_control_set_datachnl_stat(FALSE);
280 }
281 
282 /*****************************************************************************
283 **
284 ** Function        btc_a2dp_on_suspended
285 **
286 *******************************************************************************/
287 
btc_a2dp_sink_on_suspended(tBTA_AV_SUSPEND * p_av)288 void btc_a2dp_sink_on_suspended(tBTA_AV_SUSPEND *p_av)
289 {
290     a2dp_sink_local_param.btc_aa_snk_cb.rx_flush = TRUE;
291     btc_a2dp_sink_rx_flush_req();
292     return;
293 }
294 
295 /*******************************************************************************
296  **
297  ** Function         btc_a2dp_sink_clear_track
298  **
299  ** Description
300  **
301  ** Returns          TRUE is success
302  **
303  *******************************************************************************/
btc_a2dp_sink_clear_track(void)304 static BOOLEAN btc_a2dp_sink_clear_track(void)
305 {
306     return btc_a2dp_sink_ctrl(BTC_MEDIA_AUDIO_SINK_CLEAR_TRACK, NULL);
307 }
308 
309 /* when true media task discards any rx frames */
btc_a2dp_sink_set_rx_flush(BOOLEAN enable)310 void btc_a2dp_sink_set_rx_flush(BOOLEAN enable)
311 {
312     APPL_TRACE_EVENT("## DROP RX %d ##\n", enable);
313     if (enable == FALSE) {
314         a2dp_sink_local_param.media_pkt_seq_num.expected_seq_num = 0x1;
315         a2dp_sink_local_param.media_pkt_seq_num.seq_num_recount = true;
316     }
317     a2dp_sink_local_param.btc_aa_snk_cb.rx_flush = enable;
318 }
319 
320 /*****************************************************************************
321 **
322 ** Function        btc_a2dp_sink_reset_decoder
323 **
324 ** Description
325 **
326 ** Returns
327 **
328 *******************************************************************************/
329 
btc_a2dp_sink_reset_decoder(UINT8 * p_av)330 void btc_a2dp_sink_reset_decoder(UINT8 *p_av)
331 {
332     APPL_TRACE_EVENT("btc reset decoder");
333     APPL_TRACE_DEBUG("btc reset decoder p_codec_info[%x:%x:%x:%x:%x:%x]\n",
334                      p_av[1], p_av[2], p_av[3],
335                      p_av[4], p_av[5], p_av[6]);
336 
337     tBTC_MEDIA_SINK_CFG_UPDATE *p_buf;
338     if (NULL == (p_buf = osi_malloc(sizeof(tBTC_MEDIA_SINK_CFG_UPDATE)))) {
339         APPL_TRACE_ERROR("btc reset decoder No Buffer ");
340         return;
341     }
342 
343     memcpy(p_buf->codec_info, p_av, AVDT_CODEC_SIZE);
344     btc_a2dp_sink_ctrl(BTC_MEDIA_AUDIO_SINK_CFG_UPDATE, p_buf);
345 }
346 
btc_a2dp_sink_data_ready(UNUSED_ATTR void * context)347 static void btc_a2dp_sink_data_ready(UNUSED_ATTR void *context)
348 {
349     tBT_SBC_HDR *p_msg;
350     int nb_of_msgs_to_process = 0;
351 
352     if (fixed_queue_is_empty(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ)) {
353         APPL_TRACE_DEBUG("  QUE  EMPTY ");
354     } else {
355         if (a2dp_sink_local_param.btc_aa_snk_cb.rx_flush == TRUE) {
356             btc_a2dp_sink_flush_q(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ);
357             return;
358         }
359         nb_of_msgs_to_process = fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ);
360         APPL_TRACE_DEBUG("nb:%d", nb_of_msgs_to_process);
361         while (nb_of_msgs_to_process > 0) {
362             if (btc_a2dp_sink_state != BTC_A2DP_SINK_STATE_ON){
363                 return;
364             }
365             p_msg = (tBT_SBC_HDR *)fixed_queue_dequeue(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ, 0);
366             if ( p_msg == NULL ) {
367                 APPL_TRACE_ERROR("Insufficient data in que ");
368                 break;
369             }
370             btc_a2dp_sink_handle_inc_media(p_msg);
371             osi_free(p_msg);
372             nb_of_msgs_to_process--;
373         }
374         APPL_TRACE_DEBUG(" Process Frames - ");
375 
376         if (!fixed_queue_is_empty(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ)) {
377             osi_thread_post_event(a2dp_sink_local_param.btc_aa_snk_cb.data_ready_event, OSI_THREAD_MAX_TIMEOUT);
378         }
379     }
380 }
381 
382 /*******************************************************************************
383  **
384  ** Function         btc_a2dp_sink_handle_decoder_reset
385  **
386  ** Description
387  **
388  ** Returns          void
389  **
390  *******************************************************************************/
btc_a2dp_sink_handle_decoder_reset(tBTC_MEDIA_SINK_CFG_UPDATE * p_msg)391 static void btc_a2dp_sink_handle_decoder_reset(tBTC_MEDIA_SINK_CFG_UPDATE *p_msg)
392 {
393     tBTC_MEDIA_SINK_CFG_UPDATE *p_buf = p_msg;
394     tA2D_STATUS a2d_status;
395     tA2D_SBC_CIE sbc_cie;
396     OI_STATUS       status;
397     UINT32          freq_multiple = 48 * 20; /* frequency multiple for 20ms of data , initialize with 48K*/
398     UINT32          num_blocks = 16;
399     UINT32          num_subbands = 8;
400 
401     APPL_TRACE_EVENT("%s p_codec_info[%x:%x:%x:%x:%x:%x]\n", __FUNCTION__,
402                      p_buf->codec_info[1], p_buf->codec_info[2], p_buf->codec_info[3],
403                      p_buf->codec_info[4], p_buf->codec_info[5], p_buf->codec_info[6]);
404 
405     a2d_status = A2D_ParsSbcInfo(&sbc_cie, p_buf->codec_info, FALSE);
406     if (a2d_status != A2D_SUCCESS) {
407         APPL_TRACE_ERROR("ERROR dump_codec_info A2D_ParsSbcInfo fail:%d\n", a2d_status);
408         return;
409     }
410 
411     a2dp_sink_local_param.btc_aa_snk_cb.sample_rate = btc_a2dp_sink_get_track_frequency(sbc_cie.samp_freq);
412     a2dp_sink_local_param.btc_aa_snk_cb.channel_count = btc_a2dp_sink_get_track_channel_count(sbc_cie.ch_mode);
413 
414     a2dp_sink_local_param.btc_aa_snk_cb.rx_flush = FALSE;
415     APPL_TRACE_EVENT("Reset to sink role");
416     status = OI_CODEC_SBC_DecoderReset(&a2dp_sink_local_param.context, a2dp_sink_local_param.contextData,
417                                         sizeof(a2dp_sink_local_param.contextData), a2dp_sink_local_param.btc_aa_snk_cb.channel_count,
418                                         a2dp_sink_local_param.btc_aa_snk_cb.channel_count, FALSE, FALSE);
419     if (!OI_SUCCESS(status)) {
420         APPL_TRACE_ERROR("OI_CODEC_SBC_DecoderReset failed with error code %d\n", status);
421     }
422 
423     btc_a2dp_control_set_datachnl_stat(TRUE);
424 
425     switch (sbc_cie.samp_freq) {
426     case A2D_SBC_IE_SAMP_FREQ_16:
427         APPL_TRACE_DEBUG("\tsamp_freq:%d (16000)\n", sbc_cie.samp_freq);
428         freq_multiple = 16 * 20;
429         break;
430     case A2D_SBC_IE_SAMP_FREQ_32:
431         APPL_TRACE_DEBUG("\tsamp_freq:%d (32000)\n", sbc_cie.samp_freq);
432         freq_multiple = 32 * 20;
433         break;
434     case A2D_SBC_IE_SAMP_FREQ_44:
435         APPL_TRACE_DEBUG("\tsamp_freq:%d (44100)\n", sbc_cie.samp_freq);
436         freq_multiple = 441 * 2;
437         break;
438     case A2D_SBC_IE_SAMP_FREQ_48:
439         APPL_TRACE_DEBUG("\tsamp_freq:%d (48000)\n", sbc_cie.samp_freq);
440         freq_multiple = 48 * 20;
441         break;
442     default:
443         APPL_TRACE_DEBUG(" Unknown Frequency ");
444         break;
445     }
446 
447     switch (sbc_cie.ch_mode) {
448     case A2D_SBC_IE_CH_MD_MONO:
449         APPL_TRACE_DEBUG("\tch_mode:%d (Mono)\n", sbc_cie.ch_mode);
450         break;
451     case A2D_SBC_IE_CH_MD_DUAL:
452         APPL_TRACE_DEBUG("\tch_mode:%d (DUAL)\n", sbc_cie.ch_mode);
453         break;
454     case A2D_SBC_IE_CH_MD_STEREO:
455         APPL_TRACE_DEBUG("\tch_mode:%d (STEREO)\n", sbc_cie.ch_mode);
456         break;
457     case A2D_SBC_IE_CH_MD_JOINT:
458         APPL_TRACE_DEBUG("\tch_mode:%d (JOINT)\n", sbc_cie.ch_mode);
459         break;
460     default:
461         APPL_TRACE_DEBUG(" Unknown Mode ");
462         break;
463     }
464 
465     switch (sbc_cie.block_len) {
466     case A2D_SBC_IE_BLOCKS_4:
467         APPL_TRACE_DEBUG("\tblock_len:%d (4)\n", sbc_cie.block_len);
468         num_blocks = 4;
469         break;
470     case A2D_SBC_IE_BLOCKS_8:
471         APPL_TRACE_DEBUG("\tblock_len:%d (8)\n", sbc_cie.block_len);
472         num_blocks = 8;
473         break;
474     case A2D_SBC_IE_BLOCKS_12:
475         APPL_TRACE_DEBUG("\tblock_len:%d (12)\n", sbc_cie.block_len);
476         num_blocks = 12;
477         break;
478     case A2D_SBC_IE_BLOCKS_16:
479         APPL_TRACE_DEBUG("\tblock_len:%d (16)\n", sbc_cie.block_len);
480         num_blocks = 16;
481         break;
482     default:
483         APPL_TRACE_DEBUG(" Unknown BlockLen ");
484         break;
485     }
486 
487     switch (sbc_cie.num_subbands) {
488     case A2D_SBC_IE_SUBBAND_4:
489         APPL_TRACE_DEBUG("\tnum_subbands:%d (4)\n", sbc_cie.num_subbands);
490         num_subbands = 4;
491         break;
492     case A2D_SBC_IE_SUBBAND_8:
493         APPL_TRACE_DEBUG("\tnum_subbands:%d (8)\n", sbc_cie.num_subbands);
494         num_subbands = 8;
495         break;
496     default:
497         APPL_TRACE_DEBUG(" Unknown SubBands ");
498         break;
499     }
500 
501     switch (sbc_cie.alloc_mthd) {
502     case A2D_SBC_IE_ALLOC_MD_S:
503         APPL_TRACE_DEBUG("\talloc_mthd:%d (SNR)\n", sbc_cie.alloc_mthd);
504         break;
505     case A2D_SBC_IE_ALLOC_MD_L:
506         APPL_TRACE_DEBUG("\talloc_mthd:%d (Loudness)\n", sbc_cie.alloc_mthd);
507         break;
508     default:
509         APPL_TRACE_DEBUG(" Unknown Allocation Method");
510         break;
511     }
512 
513     APPL_TRACE_EVENT("\tBit pool Min:%d Max:%d\n", sbc_cie.min_bitpool, sbc_cie.max_bitpool);
514 
515     int frames_to_process = ((freq_multiple) / (num_blocks * num_subbands)) + 1;
516     APPL_TRACE_EVENT(" Frames to be processed in 20 ms %d\n", frames_to_process);
517     UNUSED(frames_to_process);
518 }
519 
520 /*******************************************************************************
521  **
522  ** Function         btc_a2dp_sink_handle_inc_media
523  **
524  ** Description
525  **
526  ** Returns          void
527  **
528  *******************************************************************************/
btc_a2dp_sink_handle_inc_media(tBT_SBC_HDR * p_msg)529 static void btc_a2dp_sink_handle_inc_media(tBT_SBC_HDR *p_msg)
530 {
531     UINT8 *sbc_start_frame = ((UINT8 *)(p_msg + 1) + p_msg->offset + 1);
532     int count;
533     UINT32 pcmBytes, availPcmBytes;
534     OI_INT16 *pcmDataPointer = a2dp_sink_local_param.pcmData; /*Will be overwritten on next packet receipt*/
535     OI_STATUS status;
536     int num_sbc_frames = p_msg->num_frames_to_be_processed;
537     UINT32 sbc_frame_len = p_msg->len - 1;
538     availPcmBytes = sizeof(a2dp_sink_local_param.pcmData);
539 
540     /* XXX: Check if the below check is correct, we are checking for peer to be sink when we are sink */
541     if (btc_av_get_peer_sep() == AVDT_TSEP_SNK || (a2dp_sink_local_param.btc_aa_snk_cb.rx_flush)) {
542         APPL_TRACE_DEBUG(" State Changed happened in this tick ");
543         return;
544     }
545 
546     // ignore data if no one is listening
547     if (!btc_a2dp_control_get_datachnl_stat()) {
548         return;
549     }
550 
551     if (p_msg->layer_specific != a2dp_sink_local_param.media_pkt_seq_num.expected_seq_num) {
552         /* Because the sequence number of some devices is not recounted */
553         if (!a2dp_sink_local_param.media_pkt_seq_num.seq_num_recount ||
554                 a2dp_sink_local_param.media_pkt_seq_num.expected_seq_num != 0x1) {
555             APPL_TRACE_WARNING("Sequence numbers error, recv:0x%x, expect:0x%x, recount:0x%x",
556                                 p_msg->layer_specific, a2dp_sink_local_param.media_pkt_seq_num.expected_seq_num,
557                                 a2dp_sink_local_param.media_pkt_seq_num.seq_num_recount);
558         }
559     }
560     a2dp_sink_local_param.media_pkt_seq_num.expected_seq_num  = p_msg->layer_specific + 1;
561     a2dp_sink_local_param.media_pkt_seq_num.seq_num_recount = false;
562 
563     APPL_TRACE_DEBUG("Number of sbc frames %d, frame_len %d\n", num_sbc_frames, sbc_frame_len);
564 
565     for (count = 0; count < num_sbc_frames && sbc_frame_len != 0; count ++) {
566         pcmBytes = availPcmBytes;
567         status = OI_CODEC_SBC_DecodeFrame(&a2dp_sink_local_param.context, (const OI_BYTE **)&sbc_start_frame,
568                                           (OI_UINT32 *)&sbc_frame_len,
569                                           (OI_INT16 *)pcmDataPointer,
570                                           (OI_UINT32 *)&pcmBytes);
571         if (!OI_SUCCESS(status)) {
572             APPL_TRACE_ERROR("Decoding failure: %d\n", status);
573             break;
574         }
575         availPcmBytes -= pcmBytes;
576         pcmDataPointer += pcmBytes / 2;
577         p_msg->offset += (p_msg->len - 1) - sbc_frame_len;
578         p_msg->len = sbc_frame_len + 1;
579     }
580 
581     btc_a2d_data_cb_to_app((uint8_t *)a2dp_sink_local_param.pcmData, (sizeof(a2dp_sink_local_param.pcmData) - availPcmBytes));
582 }
583 
584 /*******************************************************************************
585  **
586  ** Function         btc_a2dp_sink_rx_flush_req
587  **
588  ** Description
589  **
590  ** Returns          TRUE is success
591  **
592  *******************************************************************************/
btc_a2dp_sink_rx_flush_req(void)593 BOOLEAN btc_a2dp_sink_rx_flush_req(void)
594 {
595     if (fixed_queue_is_empty(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ) == TRUE) { /*  Que is already empty */
596         return TRUE;
597     }
598 
599     return btc_a2dp_sink_ctrl(BTC_MEDIA_FLUSH_AA_RX, NULL);
600 }
601 
602 /*******************************************************************************
603  **
604  ** Function         btc_a2dp_sink_rx_flush
605  **
606  ** Description
607  **
608  ** Returns          void
609  **
610  *******************************************************************************/
btc_a2dp_sink_rx_flush(void)611 static void btc_a2dp_sink_rx_flush(void)
612 {
613     /* Flush all enqueued SBC  buffers (encoded) */
614     APPL_TRACE_DEBUG("btc_a2dp_sink_rx_flush");
615 
616     btc_a2dp_sink_flush_q(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ);
617 }
618 
btc_a2dp_sink_get_track_frequency(UINT8 frequency)619 static int btc_a2dp_sink_get_track_frequency(UINT8 frequency)
620 {
621     int freq = 48000;
622     switch (frequency) {
623     case A2D_SBC_IE_SAMP_FREQ_16:
624         freq = 16000;
625         break;
626     case A2D_SBC_IE_SAMP_FREQ_32:
627         freq = 32000;
628         break;
629     case A2D_SBC_IE_SAMP_FREQ_44:
630         freq = 44100;
631         break;
632     case A2D_SBC_IE_SAMP_FREQ_48:
633         freq = 48000;
634         break;
635     }
636     return freq;
637 }
638 
btc_a2dp_sink_get_track_channel_count(UINT8 channeltype)639 static int btc_a2dp_sink_get_track_channel_count(UINT8 channeltype)
640 {
641     int count = 1;
642     switch (channeltype) {
643     case A2D_SBC_IE_CH_MD_MONO:
644         count = 1;
645         break;
646     case A2D_SBC_IE_CH_MD_DUAL:
647     case A2D_SBC_IE_CH_MD_STEREO:
648     case A2D_SBC_IE_CH_MD_JOINT:
649         count = 2;
650         break;
651     }
652     return count;
653 }
654 
655 /*******************************************************************************
656  **
657  ** Function         btc_a2dp_sink_enque_buf
658  **
659  ** Description      This function is called by the av_co to fill A2DP Sink Queue
660  **
661  **
662  ** Returns          size of the queue
663  *******************************************************************************/
btc_a2dp_sink_enque_buf(BT_HDR * p_pkt)664 UINT8 btc_a2dp_sink_enque_buf(BT_HDR *p_pkt)
665 {
666     tBT_SBC_HDR *p_msg;
667 
668     if (btc_a2dp_sink_state != BTC_A2DP_SINK_STATE_ON){
669         return 0;
670     }
671 
672     if (a2dp_sink_local_param.btc_aa_snk_cb.rx_flush == TRUE) { /* Flush enabled, do not enque*/
673         return fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ);
674     }
675 
676     if (fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ) >= MAX_OUTPUT_A2DP_SNK_FRAME_QUEUE_SZ) {
677         APPL_TRACE_WARNING("Pkt dropped\n");
678         return fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ);
679     }
680 
681     APPL_TRACE_DEBUG("btc_a2dp_sink_enque_buf + ");
682 
683     /* allocate and Queue this buffer */
684     if ((p_msg = (tBT_SBC_HDR *) osi_malloc(sizeof(tBT_SBC_HDR) +
685                                             p_pkt->offset + p_pkt->len)) != NULL) {
686         memcpy(p_msg, p_pkt, (sizeof(BT_HDR) + p_pkt->offset + p_pkt->len));
687         p_msg->num_frames_to_be_processed = (*((UINT8 *)(p_msg + 1) + p_msg->offset)) & 0x0f;
688         APPL_TRACE_VERBOSE("btc_a2dp_sink_enque_buf %d + \n", p_msg->num_frames_to_be_processed);
689         fixed_queue_enqueue(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ, p_msg, FIXED_QUEUE_MAX_TIMEOUT);
690         osi_thread_post_event(a2dp_sink_local_param.btc_aa_snk_cb.data_ready_event, OSI_THREAD_MAX_TIMEOUT);
691     } else {
692         /* let caller deal with a failed allocation */
693         APPL_TRACE_WARNING("btc_a2dp_sink_enque_buf No Buffer left - ");
694     }
695     return fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ);
696 }
697 
btc_a2dp_sink_handle_clear_track(void)698 static void btc_a2dp_sink_handle_clear_track (void)
699 {
700     APPL_TRACE_DEBUG("%s", __FUNCTION__);
701 }
702 
703 /*******************************************************************************
704  **
705  ** Function         btc_a2dp_sink_flush_q
706  **
707  ** Description
708  **
709  ** Returns          void
710  **
711  *******************************************************************************/
btc_a2dp_sink_flush_q(fixed_queue_t * p_q)712 static void btc_a2dp_sink_flush_q(fixed_queue_t *p_q)
713 {
714     while (! fixed_queue_is_empty(p_q)) {
715         osi_free(fixed_queue_dequeue(p_q, 0));
716     }
717 }
718 
btc_a2dp_sink_thread_init(UNUSED_ATTR void * context)719 static void btc_a2dp_sink_thread_init(UNUSED_ATTR void *context)
720 {
721     APPL_TRACE_EVENT("%s\n", __func__);
722     memset(&a2dp_sink_local_param.btc_aa_snk_cb, 0, sizeof(a2dp_sink_local_param.btc_aa_snk_cb));
723 
724     btc_a2dp_sink_state = BTC_A2DP_SINK_STATE_ON;
725 
726     struct osi_event *data_event = osi_event_create(btc_a2dp_sink_data_ready, NULL);
727     assert (data_event != NULL);
728     osi_event_bind(data_event, a2dp_sink_local_param.btc_aa_snk_task_hdl, BTC_A2DP_SNK_DATA_QUEUE_IDX);
729     a2dp_sink_local_param.btc_aa_snk_cb.data_ready_event = data_event;
730 
731     a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ = fixed_queue_new(QUEUE_SIZE_MAX);
732 
733     btc_a2dp_control_init();
734 }
735 
btc_a2dp_sink_thread_cleanup(UNUSED_ATTR void * context)736 static void btc_a2dp_sink_thread_cleanup(UNUSED_ATTR void *context)
737 {
738     btc_a2dp_control_set_datachnl_stat(FALSE);
739     /* Clear task flag */
740     btc_a2dp_sink_state = BTC_A2DP_SINK_STATE_OFF;
741 
742     btc_a2dp_control_cleanup();
743 
744     fixed_queue_free(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ, osi_free_func);
745 
746     a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ = NULL;
747 
748     osi_event_delete(a2dp_sink_local_param.btc_aa_snk_cb.data_ready_event);
749     a2dp_sink_local_param.btc_aa_snk_cb.data_ready_event = NULL;
750 }
751 
752 #endif /* BTC_AV_SINK_INCLUDED */
753