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