1 /*
2  * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /******************************************************************************
8  **
9  **  Name:          btc_a2dp_source.c
10  **
11  ******************************************************************************/
12 #include "common/bt_target.h"
13 #include "common/bt_trace.h"
14 #include <string.h>
15 #include <stdio.h>
16 #include <stdint.h>
17 #include <unistd.h>
18 #include <time.h>
19 #include <sys/time.h>
20 #include "osi/allocator.h"
21 #include "osi/alarm.h"
22 #include "osi/thread.h"
23 #include "osi/mutex.h"
24 #include "osi/fixed_queue.h"
25 #include "stack/a2d_api.h"
26 #include "stack/a2d_sbc.h"
27 #include "bta/bta_av_api.h"
28 #include "bta/bta_av_sbc.h"
29 #include "bta/bta_av_ci.h"
30 #include "btc/btc_manage.h"
31 #include "btc/btc_common.h"
32 #include "btc_av_co.h"
33 #include "btc_a2dp.h"
34 #include "btc_a2dp_control.h"
35 #include "btc_a2dp_source.h"
36 #include "btc_av.h"
37 #include "btc/btc_util.h"
38 #include "esp_a2dp_api.h"
39 #include "sbc_encoder.h"
40 #include "osi/future.h"
41 #include <assert.h>
42 
43 #if BTC_AV_SRC_INCLUDED
44 
45 /*****************************************************************************
46  **  BQB global variables
47  *****************************************************************************/
48 #if A2D_SRC_BQB_INCLUDED
49 bool a2dp_src_bqb_set_sbc_encoder_flag = FALSE;
50 #endif /* A2D_SRC_BQB_INCLUDED */
51 
52 /*****************************************************************************
53  **  Constants
54  *****************************************************************************/
55 
56 /* BTC source command event definition */
57 enum {
58     BTC_MEDIA_TASK_INIT,
59     BTC_MEDIA_TASK_CLEAN_UP,
60     BTC_MEDIA_START_AA_TX,
61     BTC_MEDIA_STOP_AA_TX,
62     BTC_MEDIA_SBC_ENC_INIT,
63     BTC_MEDIA_SBC_ENC_UPDATE,
64     BTC_MEDIA_FLUSH_AA_TX,
65     BTC_MEDIA_AUDIO_FEEDING_INIT,
66 };
67 
68 enum {
69     BTC_A2DP_SOURCE_STATE_OFF = 0,
70     BTC_A2DP_SOURCE_STATE_ON = 1,
71     BTC_A2DP_SOURCE_STATE_SHUTTING_DOWN = 2
72 };
73 
74 
75 /* Media task tick in milliseconds, must be set to multiple of
76    (1000/TICKS_PER_SEC) */
77 #define BTC_MEDIA_TIME_TICK_MS                 (30)
78 #define A2DP_DATA_READ_POLL_MS                 (BTC_MEDIA_TIME_TICK_MS / 2)
79 
80 #ifndef MAX_PCM_FRAME_NUM_PER_TICK
81 #define MAX_PCM_FRAME_NUM_PER_TICK             21 // 14 for 20ms
82 #endif
83 
84 #define BTC_MEDIA_AA_BUF_SIZE                  (4096+16)
85 
86 #if (BTA_AV_CO_CP_SCMS_T == TRUE)
87 #define BTC_MEDIA_AA_SBC_OFFSET (AVDT_MEDIA_OFFSET + BTA_AV_SBC_HDR_SIZE + 1)
88 #else
89 #define BTC_MEDIA_AA_SBC_OFFSET (AVDT_MEDIA_OFFSET + BTA_AV_SBC_HDR_SIZE)
90 #endif
91 
92 #ifndef BTC_MEDIA_BITRATE_STEP
93 #define BTC_MEDIA_BITRATE_STEP                 5
94 #endif
95 
96 #ifndef BTC_A2DP_NON_EDR_MAX_RATE
97 #define BTC_A2DP_NON_EDR_MAX_RATE              229
98 #endif
99 
100 /* Middle quality quality setting @ 44.1 khz */
101 #define DEFAULT_SBC_BITRATE                    328
102 
103 /*
104  * CONGESTION COMPENSATION CTRL ::
105  *
106  * Thus setting controls how many buffers we will hold in media task
107  * during temp link congestion. Together with the stack buffer queues
108  * it controls much temporary a2dp link congestion we can
109  * compensate for. It however also depends on the default run level of sinks
110  * jitterbuffers. Depending on type of sink this would vary.
111  * Ideally the (SRC) max tx buffer capacity should equal the sinks
112  * jitterbuffer runlevel including any intermediate buffers on the way
113  * towards the sinks codec.
114  */
115 
116 /* fixme -- define this in pcm time instead of buffer count */
117 
118 /* The typical runlevel of the tx queue size is ~1 buffer
119    but due to link flow control or thread preemption in lower
120    layers we might need to temporarily buffer up data */
121 
122 /* 5 frames is equivalent to 6.89*5*2.9 ~= 100 ms @ 44.1 khz, 20 ms mediatick */
123 #define MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ         (5)
124 #define MAX_OUTPUT_A2DP_SRC_FRAME_QUEUE_SZ     (27) // 18 for 20ms tick
125 
126 #define BTC_A2DP_SRC_DATA_QUEUE_IDX            (1)
127 
128 typedef struct {
129     uint32_t sig;
130     void *param;
131 } a2dp_src_task_evt_t;
132 
133 typedef struct {
134     UINT16 num_frames_to_be_processed;
135     UINT16 len;
136     UINT16 offset;
137     UINT16 layer_specific;
138 } tBT_SBC_HDR;
139 
140 typedef struct {
141     UINT32 aa_frame_counter;
142     INT32  aa_feed_counter;
143     INT32  aa_feed_residue;
144     UINT32 counter;
145     UINT32 bytes_per_tick;  /* pcm bytes read each media task tick */
146 } tBTC_AV_MEDIA_FEEDINGS_PCM_STATE;
147 
148 typedef union {
149     tBTC_AV_MEDIA_FEEDINGS_PCM_STATE pcm;
150 } tBTC_AV_MEDIA_FEEDINGS_STATE;
151 
152 typedef struct {
153     UINT8 TxTranscoding;
154     BOOLEAN tx_flush; /* discards any outgoing data when true */
155     BOOLEAN is_tx_timer;
156     UINT16 TxAaMtuSize;
157     UINT32 timestamp;
158     fixed_queue_t *TxAaQ;
159     tBTC_AV_FEEDING_MODE feeding_mode;
160     tBTC_AV_MEDIA_FEEDINGS_STATE media_feeding_state;
161     tBTC_AV_MEDIA_FEEDINGS media_feeding;
162     SBC_ENC_PARAMS encoder;
163     osi_alarm_t *media_alarm;
164     struct osi_event *poll_data;
165 } tBTC_A2DP_SOURCE_CB;
166 
167 typedef struct {
168     tBTC_A2DP_SOURCE_CB         btc_aa_src_cb;
169     osi_thread_t                *btc_aa_src_task_hdl;
170     UINT64                      last_frame_us;
171 } a2dp_source_local_param_t;
172 
173 static void btc_a2dp_source_thread_init(UNUSED_ATTR void *context);
174 static void btc_a2dp_source_thread_cleanup(UNUSED_ATTR void *context);
175 static void btc_a2dp_source_flush_q(fixed_queue_t *p_q);
176 
177 static void btc_a2dp_source_feeding_state_reset(void);
178 static void btc_a2dp_source_send_aa_frame(void);
179 static void btc_a2dp_source_aa_start_tx(void);
180 static void btc_a2dp_source_aa_stop_tx(void);
181 static void btc_a2dp_source_enc_init(BT_HDR *p_msg);
182 static void btc_a2dp_source_enc_update(BT_HDR *p_msg);
183 static void btc_a2dp_source_audio_feeding_init(BT_HDR *p_msg);
184 static void btc_a2dp_source_aa_tx_flush(void);
185 static void btc_a2dp_source_prep_2_send(UINT8 nb_frame);
186 static void btc_a2dp_source_handle_timer(UNUSED_ATTR void *context);
187 static void btc_a2dp_source_encoder_init(void);
188 
189 static int btc_a2dp_source_state = BTC_A2DP_SOURCE_STATE_OFF;
190 static esp_a2d_source_data_cb_t btc_aa_src_data_cb = NULL;
191 #if A2D_DYNAMIC_MEMORY == FALSE
192 static a2dp_source_local_param_t a2dp_source_local_param;
193 #else
194 static a2dp_source_local_param_t *a2dp_source_local_param_ptr;
195 #define a2dp_source_local_param (*a2dp_source_local_param_ptr)
196 #endif ///A2D_DYNAMIC_MEMORY == FALSE
197 
btc_a2dp_src_reg_data_cb(esp_a2d_source_data_cb_t callback)198 void btc_a2dp_src_reg_data_cb(esp_a2d_source_data_cb_t callback)
199 {
200     // todo: critical section protection
201     btc_aa_src_data_cb = callback;
202 }
203 
btc_aa_src_data_read(uint8_t * data,int32_t len)204 static inline uint32_t btc_aa_src_data_read(uint8_t *data, int32_t len)
205 {
206     // todo: critical section protection
207     if (btc_aa_src_data_cb) {
208         return btc_aa_src_data_cb(data, len);
209     } else {
210         return 0;
211     }
212 }
213 
214 /*****************************************************************************
215  **  Misc helper functions
216  *****************************************************************************/
btc_aa_cb_to_app(esp_a2d_cb_event_t event,esp_a2d_cb_param_t * param)217 static inline void btc_aa_cb_to_app(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param)
218 {
219     esp_a2d_cb_t btc_aa_cb = (esp_a2d_cb_t)btc_profile_cb_get(BTC_PID_A2DP);
220     if (btc_aa_cb) {
221         btc_aa_cb(event, param);
222     }
223 }
224 
225 /*****************************************************************************
226  **  BTC ADAPTATION
227  *****************************************************************************/
228 
btc_a2dp_source_is_streaming(void)229 bool btc_a2dp_source_is_streaming(void)
230 {
231     return a2dp_source_local_param.btc_aa_src_cb.is_tx_timer == TRUE;
232 }
233 
btc_a2dp_source_is_task_shutting_down(void)234 bool btc_a2dp_source_is_task_shutting_down(void)
235 {
236     return btc_a2dp_source_state == BTC_A2DP_SOURCE_STATE_SHUTTING_DOWN;
237 }
238 
btc_a2dp_source_ctrl(uint32_t sig,void * param)239 static bool btc_a2dp_source_ctrl(uint32_t sig, void *param)
240 {
241     switch (sig) {
242     case BTC_MEDIA_TASK_INIT:
243         btc_a2dp_source_thread_init(NULL);
244         break;
245     case BTC_MEDIA_TASK_CLEAN_UP:
246         btc_a2dp_source_thread_cleanup(NULL);
247         break;
248     case BTC_MEDIA_START_AA_TX:
249         btc_a2dp_source_aa_start_tx();
250         break;
251     case BTC_MEDIA_STOP_AA_TX:
252         btc_a2dp_source_aa_stop_tx();
253         break;
254     case BTC_MEDIA_SBC_ENC_INIT:
255         btc_a2dp_source_enc_init(param);
256         break;
257     case BTC_MEDIA_SBC_ENC_UPDATE:
258         btc_a2dp_source_enc_update(param);
259         break;
260     case BTC_MEDIA_AUDIO_FEEDING_INIT:
261         btc_a2dp_source_audio_feeding_init(param);
262         break;
263     case BTC_MEDIA_FLUSH_AA_TX:
264         btc_a2dp_source_aa_tx_flush();
265         break;
266     default:
267         APPL_TRACE_WARNING("media task unhandled evt: 0x%x\n", sig);
268     }
269 
270     if (param != NULL) {
271         osi_free(param);
272     }
273 
274     return true;
275 }
276 
btc_a2dp_source_startup(void)277 bool btc_a2dp_source_startup(void)
278 {
279     if (btc_a2dp_source_state != BTC_A2DP_SOURCE_STATE_OFF) {
280         APPL_TRACE_ERROR("warning : media task already running");
281         return false;
282     }
283 
284 #if A2D_DYNAMIC_MEMORY == TRUE
285     if ((a2dp_source_local_param_ptr = (a2dp_source_local_param_t *)osi_malloc(sizeof(a2dp_source_local_param_t))) == NULL) {
286         APPL_TRACE_ERROR("%s malloc failed!", __func__);
287         return false;
288     }
289     memset((void *)a2dp_source_local_param_ptr, 0, sizeof(a2dp_source_local_param_t));
290 #endif
291 
292     APPL_TRACE_EVENT("## A2DP SOURCE START MEDIA THREAD ##");
293 
294     a2dp_source_local_param.btc_aa_src_task_hdl = btc_get_current_thread();
295 
296     if (btc_a2dp_source_ctrl(BTC_MEDIA_TASK_INIT, NULL) == false) {
297         goto error_exit;
298     }
299 
300     APPL_TRACE_EVENT("## A2DP SOURCE MEDIA THREAD STARTED ##\n");
301 
302     return true;
303 
304 error_exit:;
305     APPL_TRACE_ERROR("%s unable to start up media thread\n", __func__);
306     a2dp_source_local_param.btc_aa_src_task_hdl = NULL;
307 
308 #if A2D_DYNAMIC_MEMORY == TRUE
309     osi_free(a2dp_source_local_param_ptr);
310     a2dp_source_local_param_ptr = NULL;
311 #endif
312 
313     return false;
314 }
315 
btc_a2dp_source_shutdown(void)316 void btc_a2dp_source_shutdown(void)
317 {
318     APPL_TRACE_EVENT("## A2DP SOURCE STOP MEDIA THREAD ##\n");
319 
320     // Exit thread
321     btc_a2dp_source_state = BTC_A2DP_SOURCE_STATE_SHUTTING_DOWN;
322     btc_a2dp_source_ctrl(BTC_MEDIA_TASK_CLEAN_UP, NULL);
323 
324     a2dp_source_local_param.btc_aa_src_task_hdl = NULL;
325 
326 #if A2D_DYNAMIC_MEMORY == TRUE
327     osi_free(a2dp_source_local_param_ptr);
328     a2dp_source_local_param_ptr = NULL;
329 #endif
330 }
331 
332 /*****************************************************************************
333 **
334 ** Function        btc_a2dp_source_on_idle
335 **
336 *******************************************************************************/
btc_a2dp_source_on_idle(void)337 void btc_a2dp_source_on_idle(void)
338 {
339     /* Make sure media task is stopped */
340     btc_a2dp_source_stop_audio_req();
341 }
342 
343 /*****************************************************************************
344 **
345 ** Function        btc_a2dp_source_on_stopped
346 **
347 *******************************************************************************/
btc_a2dp_source_on_stopped(tBTA_AV_SUSPEND * p_av)348 void btc_a2dp_source_on_stopped(tBTA_AV_SUSPEND *p_av)
349 {
350     /* allow using this api for other than suspend */
351     if (p_av != NULL) {
352         if (p_av->status != BTA_AV_SUCCESS) {
353             APPL_TRACE_EVENT("AV STOP FAILED (%d)", p_av->status);
354             if (p_av->initiator) {
355                 btc_a2dp_control_command_ack(ESP_A2D_MEDIA_CTRL_ACK_FAILURE);
356             }
357             return;
358         }
359     }
360 
361     /* ensure tx frames are immediately suspended */
362     a2dp_source_local_param.btc_aa_src_cb.tx_flush = 1;
363 
364     /* request to stop media task  */
365     btc_a2dp_source_tx_flush_req();
366     btc_a2dp_source_stop_audio_req();
367 
368     /* once stream is fully stopped we will ack back */
369 }
370 
371 /*****************************************************************************
372 **
373 ** Function        btc_a2dp_source_on_suspended
374 **
375 **
376 *******************************************************************************/
377 
btc_a2dp_source_on_suspended(tBTA_AV_SUSPEND * p_av)378 void btc_a2dp_source_on_suspended(tBTA_AV_SUSPEND *p_av)
379 {
380     /* check for status failures */
381     if (p_av->status != BTA_AV_SUCCESS) {
382         if (p_av->initiator == TRUE) {
383             btc_a2dp_control_command_ack(ESP_A2D_MEDIA_CTRL_ACK_FAILURE);
384         }
385     }
386 
387     /* once stream is fully stopped we will ack back */
388 
389     /* ensure tx frames are immediately flushed */
390     a2dp_source_local_param.btc_aa_src_cb.tx_flush = 1;
391 
392     /* stop timer tick */
393     btc_a2dp_source_stop_audio_req();
394 }
395 
time_now_us(void)396 static UINT64 time_now_us(void)
397 {
398 #if _POSIX_TIMERS
399     struct timespec ts_now;
400     clock_gettime(CLOCK_MONOTONIC, &ts_now);
401     return ((UINT64)ts_now.tv_sec * 1000000L) + ((UINT64)ts_now.tv_nsec / 1000);
402 #else
403     struct timeval ts_now;
404     gettimeofday(&ts_now, NULL);
405     return ((UINT64)ts_now.tv_sec * 1000000L) + ((UINT64)ts_now.tv_usec);
406 #endif
407 }
408 
log_tstamps_us(char * comment)409 static void log_tstamps_us(char *comment)
410 {
411     static UINT64 prev_us = 0;
412     UINT64 now_us = time_now_us();
413     APPL_TRACE_DEBUG("[%s] ts %08llu, diff : %08llu, queue sz %d", comment, now_us, now_us - prev_us,
414                      fixed_queue_length(a2dp_source_local_param.btc_aa_src_cb.TxAaQ));
415     prev_us = now_us;
416     UNUSED(prev_us);
417 }
418 
419 /* when true media task discards any tx frames */
btc_a2dp_source_set_tx_flush(BOOLEAN enable)420 void btc_a2dp_source_set_tx_flush(BOOLEAN enable)
421 {
422     APPL_TRACE_EVENT("## DROP TX %d ##", enable);
423     a2dp_source_local_param.btc_aa_src_cb.tx_flush = enable;
424 }
425 
426 /*****************************************************************************
427 **
428 ** Function        btc_a2dp_source_setup_codec
429 **
430 ** Description
431 **
432 ** Returns
433 **
434 *******************************************************************************/
btc_a2dp_source_setup_codec(void)435 void btc_a2dp_source_setup_codec(void)
436 {
437     tBTC_AV_MEDIA_FEEDINGS media_feeding;
438     tBTC_AV_STATUS status;
439 
440     APPL_TRACE_EVENT("## A2DP SETUP CODEC ##\n");
441 
442     osi_mutex_global_lock();
443 
444     /* for now hardcode 44.1 khz 16 bit stereo PCM format */
445     media_feeding.cfg.pcm.sampling_freq = 44100;
446     media_feeding.cfg.pcm.bit_per_sample = 16;
447     media_feeding.cfg.pcm.num_channel = 2;
448     media_feeding.format = BTC_AV_CODEC_PCM;
449 
450     if (bta_av_co_audio_set_codec(&media_feeding, &status)) {
451         tBTC_MEDIA_INIT_AUDIO_FEEDING mfeed;
452 
453         /* Init the encoding task */
454         btc_a2dp_source_encoder_init();
455 
456         /* Build the media task configuration */
457         mfeed.feeding = media_feeding;
458         mfeed.feeding_mode = BTC_AV_FEEDING_ASYNCHRONOUS;
459         /* Send message to Media task to configure transcoding */
460         btc_a2dp_source_audio_feeding_init_req(&mfeed);
461     }
462 
463     osi_mutex_global_unlock();
464 }
465 
466 
467 /*******************************************************************************
468  **
469  ** Function         btc_a2dp_source_audio_readbuf
470  **
471  ** Description      This function is called by the av_co to get the next buffer to send
472  **
473  **
474  ** Returns          void
475  *******************************************************************************/
btc_a2dp_source_audio_readbuf(void)476 BT_HDR *btc_a2dp_source_audio_readbuf(void)
477 {
478     if (btc_a2dp_source_state != BTC_A2DP_SOURCE_STATE_ON){
479         return NULL;
480     }
481     return fixed_queue_dequeue(a2dp_source_local_param.btc_aa_src_cb.TxAaQ, 0);
482 }
483 
484 /*******************************************************************************
485  **
486  ** Function         btc_a2dp_source_start_audio_req
487  **
488  ** Description
489  **
490  ** Returns          TRUE is success
491  **
492  *******************************************************************************/
btc_a2dp_source_start_audio_req(void)493 BOOLEAN btc_a2dp_source_start_audio_req(void)
494 {
495     btc_a2dp_source_ctrl(BTC_MEDIA_START_AA_TX, NULL);
496     return TRUE;
497 }
498 
499 /*******************************************************************************
500  **
501  ** Function         btc_a2dp_source_stop_audio_req
502  **
503  ** Description
504  **
505  ** Returns          TRUE is success
506  **
507  *******************************************************************************/
btc_a2dp_source_stop_audio_req(void)508 BOOLEAN btc_a2dp_source_stop_audio_req(void)
509 {
510     /*
511      * Explicitly check whether the btc_aa_src_ctrl_queue is not NULL to
512      * avoid a race condition during shutdown of the Bluetooth stack.
513      * This race condition is triggered when A2DP audio is streaming on
514      * shutdown:
515      * "btc_a2dp_on_stopped() -> btc_a2dp_source_stop_audio_req()" is called
516      * to stop the particular audio stream, and this happens right after
517      * the "cleanup() -> btc_a2dp_stop_media_task()" processing during
518      * the shutdown of the Bluetooth stack.
519      */
520 #if 0
521     if (btc_aa_src_ctrl_queue != NULL) {
522 #endif
523         btc_a2dp_source_ctrl(BTC_MEDIA_STOP_AA_TX, NULL);
524 #if 0
525     }
526 #endif
527     return TRUE;
528 }
529 
530 /*******************************************************************************
531  **
532  ** Function         btc_a2dp_source_enc_init_req
533  **
534  ** Description
535  **
536  ** Returns          TRUE is success
537  **
538  *******************************************************************************/
btc_a2dp_source_enc_init_req(tBTC_MEDIA_INIT_AUDIO * p_msg)539 BOOLEAN btc_a2dp_source_enc_init_req(tBTC_MEDIA_INIT_AUDIO *p_msg)
540 {
541     tBTC_MEDIA_INIT_AUDIO *p_buf;
542     if (NULL == (p_buf = osi_malloc(sizeof(tBTC_MEDIA_INIT_AUDIO)))) {
543         return FALSE;
544     }
545 
546     memcpy(p_buf, p_msg, sizeof(tBTC_MEDIA_INIT_AUDIO));
547 
548     btc_a2dp_source_ctrl(BTC_MEDIA_SBC_ENC_INIT, p_buf);
549 
550     return TRUE;
551 }
552 
553 /*******************************************************************************
554  **
555  ** Function         btc_a2dp_source_enc_update_req
556  **
557  ** Description
558  **
559  ** Returns          TRUE is success
560  **
561  *******************************************************************************/
btc_a2dp_source_enc_update_req(tBTC_MEDIA_UPDATE_AUDIO * p_msg)562 BOOLEAN btc_a2dp_source_enc_update_req(tBTC_MEDIA_UPDATE_AUDIO *p_msg)
563 {
564     tBTC_MEDIA_UPDATE_AUDIO *p_buf;
565     if (NULL == (p_buf = osi_malloc(sizeof(tBTC_MEDIA_UPDATE_AUDIO)))) {
566         return FALSE;
567     }
568 
569     memcpy(p_buf, p_msg, sizeof(tBTC_MEDIA_UPDATE_AUDIO));
570     btc_a2dp_source_ctrl(BTC_MEDIA_SBC_ENC_UPDATE, p_buf);
571     return TRUE;
572 }
573 
574 /*******************************************************************************
575  **
576  ** Function         btc_a2dp_source_audio_feeding_init_req
577  **
578  ** Description
579  **
580  ** Returns          TRUE is success
581  **
582  *******************************************************************************/
btc_a2dp_source_audio_feeding_init_req(tBTC_MEDIA_INIT_AUDIO_FEEDING * p_msg)583 BOOLEAN btc_a2dp_source_audio_feeding_init_req(tBTC_MEDIA_INIT_AUDIO_FEEDING *p_msg)
584 {
585     tBTC_MEDIA_INIT_AUDIO_FEEDING *p_buf;
586     if (NULL == (p_buf = osi_malloc(sizeof(tBTC_MEDIA_INIT_AUDIO_FEEDING)))) {
587         return FALSE;
588     }
589 
590     memcpy(p_buf, p_msg, sizeof(tBTC_MEDIA_INIT_AUDIO_FEEDING));
591     btc_a2dp_source_ctrl(BTC_MEDIA_AUDIO_FEEDING_INIT, p_buf);
592     return TRUE;
593 }
594 
595 /*******************************************************************************
596  **
597  ** Function         btc_a2dp_source_tx_flush_req
598  **
599  ** Description
600  **
601  ** Returns          TRUE is success
602  **
603  *******************************************************************************/
btc_a2dp_source_tx_flush_req(void)604 BOOLEAN btc_a2dp_source_tx_flush_req(void)
605 {
606     /*
607      * Explicitly check whether the btc_aa_src_ctrl_queue is not NULL to
608      * avoid a race condition during shutdown of the Bluetooth stack.
609      * This race condition is triggered when A2DP audio is streaming on
610      * shutdown:
611      * "btc_a2dp_on_stopped() -> btc_a2dp_source_tx_flush_req()" is called
612      * to stop the particular audio stream, and this happens right after
613      * the "cleanup() -> btc_a2dp_stop_media_task()" processing during
614      * the shutdown of the Bluetooth stack.
615      */
616 #if 0
617     if (btc_aa_src_ctrl_queue != NULL) {
618 #endif
619         btc_a2dp_source_ctrl(BTC_MEDIA_FLUSH_AA_TX, NULL);
620 #if 0
621     }
622 #endif
623 
624     return TRUE;
625 }
626 
627 /*****************************************************************************
628 **
629 ** Function        btc_source_report_delay_value
630 **
631 ** Description
632 **
633 ** Returns
634 **
635 *******************************************************************************/
btc_source_report_delay_value(UINT16 delay_value)636 void btc_source_report_delay_value(UINT16 delay_value)
637 {
638     esp_a2d_cb_param_t param;
639 
640 #if A2D_DYNAMIC_MEMORY == TRUE
641     if (a2dp_source_local_param_ptr == NULL) {
642         return;
643     }
644 #endif
645 
646     param.a2d_report_delay_value_stat.delay_value = delay_value;
647 
648     btc_aa_cb_to_app(ESP_A2D_REPORT_SNK_DELAY_VALUE_EVT, &param);
649 }
650 
651 /*****************************************************************************
652  **  BTC ADAPTATION
653  *****************************************************************************/
btc_a2dp_source_get_sbc_rate(void)654 static UINT16 btc_a2dp_source_get_sbc_rate(void)
655 {
656     UINT16 rate = DEFAULT_SBC_BITRATE;
657 
658     /* restrict bitrate if a2dp link is non-edr */
659     if (!btc_av_is_peer_edr()) {
660         rate = BTC_A2DP_NON_EDR_MAX_RATE;
661         APPL_TRACE_DEBUG("non-edr a2dp sink detected, restrict rate to %d", rate);
662     }
663     return rate;
664 }
665 
btc_a2dp_source_encoder_init(void)666 static void btc_a2dp_source_encoder_init(void)
667 {
668     UINT16 minmtu;
669     tBTC_MEDIA_INIT_AUDIO msg;
670     tA2D_SBC_CIE sbc_config;
671 
672     /* lookup table for converting channel mode */
673     UINT16 codec_mode_tbl[5] = { SBC_JOINT_STEREO, SBC_STEREO, SBC_DUAL, 0, SBC_MONO };
674 
675     /* lookup table for converting number of blocks */
676     UINT16 codec_block_tbl[5] = { 16, 12, 8, 0, 4 };
677 
678     /* lookup table to convert freq */
679     UINT16 freq_block_tbl[5] = { SBC_sf48000, SBC_sf44100, SBC_sf32000, 0, SBC_sf16000 };
680 
681     APPL_TRACE_DEBUG("%s", __FUNCTION__);
682 
683     /* Retrieve the current SBC configuration (default if currently not used) */
684     bta_av_co_audio_get_sbc_config(&sbc_config, &minmtu);
685     msg.NumOfSubBands = (sbc_config.num_subbands == A2D_SBC_IE_SUBBAND_4) ? 4 : 8;
686     msg.NumOfBlocks = codec_block_tbl[sbc_config.block_len >> 5];
687     msg.AllocationMethod = (sbc_config.alloc_mthd == A2D_SBC_IE_ALLOC_MD_L) ? SBC_LOUDNESS : SBC_SNR;
688     msg.ChannelMode = codec_mode_tbl[sbc_config.ch_mode >> 1];
689     msg.SamplingFreq = freq_block_tbl[sbc_config.samp_freq >> 5];
690     msg.MtuSize = minmtu;
691 
692     APPL_TRACE_EVENT("msg.ChannelMode %x", msg.ChannelMode);
693 
694     /* Init the media task to encode SBC properly */
695     btc_a2dp_source_enc_init_req(&msg);
696 }
697 
btc_a2dp_source_encoder_update(void)698 void btc_a2dp_source_encoder_update(void)
699 {
700     UINT16 minmtu;
701     tA2D_SBC_CIE sbc_config;
702     tBTC_MEDIA_UPDATE_AUDIO msg;
703     UINT8 pref_min;
704     UINT8 pref_max;
705 
706     APPL_TRACE_DEBUG("%s", __FUNCTION__);
707 
708     /* Retrieve the current SBC configuration (default if currently not used) */
709     bta_av_co_audio_get_sbc_config(&sbc_config, &minmtu);
710 
711     APPL_TRACE_DEBUG("%s: Common min_bitpool:%d(0x%x) max_bitpool:%d(0x%x)", __FUNCTION__,
712                      sbc_config.min_bitpool, sbc_config.min_bitpool,
713                      sbc_config.max_bitpool, sbc_config.max_bitpool);
714 
715     if (sbc_config.min_bitpool > sbc_config.max_bitpool) {
716         APPL_TRACE_ERROR("%s: ERROR min_bitpool > max_bitpool", __FUNCTION__);
717     }
718 
719     /* check if remote sink has a preferred bitpool range */
720     if (bta_av_co_get_remote_bitpool_pref(&pref_min, &pref_max) == TRUE) {
721         /* adjust our preferred bitpool with the remote preference if within
722            our capable range */
723 
724         if (pref_min < sbc_config.min_bitpool) {
725             pref_min = sbc_config.min_bitpool;
726         }
727 
728         if (pref_max > sbc_config.max_bitpool) {
729             pref_max = sbc_config.max_bitpool;
730         }
731 
732         msg.MinBitPool = pref_min;
733         msg.MaxBitPool = pref_max;
734 
735         if ((pref_min != sbc_config.min_bitpool) || (pref_max != sbc_config.max_bitpool)) {
736             APPL_TRACE_EVENT("## adjusted our bitpool range to peer pref [%d:%d] ##",
737                              pref_min, pref_max);
738         }
739     } else {
740         msg.MinBitPool = sbc_config.min_bitpool;
741         msg.MaxBitPool = sbc_config.max_bitpool;
742     }
743 
744     msg.MinMtuSize = minmtu;
745 
746     /* Update the media task to encode SBC properly */
747     btc_a2dp_source_enc_update_req(&msg);
748 }
749 
750 /*******************************************************************************
751  **
752  ** Function       btc_a2dp_source_enc_init
753  **
754  ** Description    Initialize encoding task
755  **
756  ** Returns        void
757  **
758  *******************************************************************************/
btc_a2dp_source_enc_init(BT_HDR * p_msg)759 static void btc_a2dp_source_enc_init(BT_HDR *p_msg)
760 {
761     tBTC_MEDIA_INIT_AUDIO *pInitAudio = (tBTC_MEDIA_INIT_AUDIO *) p_msg;
762 
763     APPL_TRACE_DEBUG("btc_a2dp_source_enc_init");
764 
765     a2dp_source_local_param.btc_aa_src_cb.timestamp = 0;
766 
767     /* SBC encoder config (enforced even if not used) */
768     a2dp_source_local_param.btc_aa_src_cb.encoder.sbc_mode = SBC_MODE_STD;
769     a2dp_source_local_param.btc_aa_src_cb.encoder.s16ChannelMode = pInitAudio->ChannelMode;
770     a2dp_source_local_param.btc_aa_src_cb.encoder.s16NumOfSubBands = pInitAudio->NumOfSubBands;
771     a2dp_source_local_param.btc_aa_src_cb.encoder.s16NumOfBlocks = pInitAudio->NumOfBlocks;
772     a2dp_source_local_param.btc_aa_src_cb.encoder.s16AllocationMethod = pInitAudio->AllocationMethod;
773     a2dp_source_local_param.btc_aa_src_cb.encoder.s16SamplingFreq = pInitAudio->SamplingFreq;
774 
775     a2dp_source_local_param.btc_aa_src_cb.encoder.u16BitRate = btc_a2dp_source_get_sbc_rate();
776 
777     /* Default transcoding is PCM to SBC, modified by feeding configuration */
778     a2dp_source_local_param.btc_aa_src_cb.TxTranscoding = BTC_MEDIA_TRSCD_PCM_2_SBC;
779     a2dp_source_local_param.btc_aa_src_cb.TxAaMtuSize = ((BTC_MEDIA_AA_BUF_SIZE - BTC_MEDIA_AA_SBC_OFFSET - sizeof(BT_HDR))
780                                  < pInitAudio->MtuSize) ? (BTC_MEDIA_AA_BUF_SIZE - BTC_MEDIA_AA_SBC_OFFSET
781                                          - sizeof(BT_HDR)) : pInitAudio->MtuSize;
782 
783     APPL_TRACE_EVENT("btc_a2dp_source_enc_init mtu %d, peer mtu %d",
784                      a2dp_source_local_param.btc_aa_src_cb.TxAaMtuSize, pInitAudio->MtuSize);
785     APPL_TRACE_EVENT("      ch mode %d, subnd %d, nb blk %d, alloc %d, rate %d, freq %d",
786                      a2dp_source_local_param.btc_aa_src_cb.encoder.s16ChannelMode, a2dp_source_local_param.btc_aa_src_cb.encoder.s16NumOfSubBands,
787                      a2dp_source_local_param.btc_aa_src_cb.encoder.s16NumOfBlocks,
788                      a2dp_source_local_param.btc_aa_src_cb.encoder.s16AllocationMethod, a2dp_source_local_param.btc_aa_src_cb.encoder.u16BitRate,
789                      a2dp_source_local_param.btc_aa_src_cb.encoder.s16SamplingFreq);
790 
791     /* Reset entirely the SBC encoder */
792     SBC_Encoder_Init(&(a2dp_source_local_param.btc_aa_src_cb.encoder));
793     APPL_TRACE_DEBUG("btc_a2dp_source_enc_init bit pool %d", a2dp_source_local_param.btc_aa_src_cb.encoder.s16BitPool);
794 }
795 
796 
797 /*******************************************************************************
798  **
799  ** Function       btc_a2dp_source_enc_update
800  **
801  ** Description    Update encoding task
802  **
803  ** Returns        void
804  **
805  *******************************************************************************/
806 
btc_a2dp_source_enc_update(BT_HDR * p_msg)807 static void btc_a2dp_source_enc_update(BT_HDR *p_msg)
808 {
809     tBTC_MEDIA_UPDATE_AUDIO *pUpdateAudio = (tBTC_MEDIA_UPDATE_AUDIO *) p_msg;
810     SBC_ENC_PARAMS *pstrEncParams = &a2dp_source_local_param.btc_aa_src_cb.encoder;
811     UINT16 s16SamplingFreq;
812     SINT16 s16BitPool = 0;
813     SINT16 s16BitRate;
814     SINT16 s16FrameLen;
815     UINT8 protect = 0;
816 
817     APPL_TRACE_DEBUG("%s : minmtu %d, maxbp %d minbp %d", __FUNCTION__,
818                      pUpdateAudio->MinMtuSize, pUpdateAudio->MaxBitPool, pUpdateAudio->MinBitPool);
819 
820     /* Only update the bitrate and MTU size while timer is running to make sure it has been initialized */
821     //if (a2dp_source_local_param.btc_aa_src_cb.is_tx_timer)
822     {
823         a2dp_source_local_param.btc_aa_src_cb.TxAaMtuSize = ((BTC_MEDIA_AA_BUF_SIZE -
824                                       BTC_MEDIA_AA_SBC_OFFSET - sizeof(BT_HDR))
825                                      < pUpdateAudio->MinMtuSize) ? (BTC_MEDIA_AA_BUF_SIZE - BTC_MEDIA_AA_SBC_OFFSET
826                                              - sizeof(BT_HDR)) : pUpdateAudio->MinMtuSize;
827         /* Set the initial target bit rate */
828         pstrEncParams->u16BitRate = btc_a2dp_source_get_sbc_rate();
829 
830         if (pstrEncParams->s16SamplingFreq == SBC_sf16000) {
831             s16SamplingFreq = 16000;
832         } else if (pstrEncParams->s16SamplingFreq == SBC_sf32000) {
833             s16SamplingFreq = 32000;
834         } else if (pstrEncParams->s16SamplingFreq == SBC_sf44100) {
835             s16SamplingFreq = 44100;
836         } else {
837             s16SamplingFreq = 48000;
838         }
839 
840         do {
841             if (pstrEncParams->s16NumOfBlocks == 0 || pstrEncParams->s16NumOfSubBands == 0
842                     || pstrEncParams->s16NumOfChannels == 0) {
843                 APPL_TRACE_ERROR("%s - Avoiding division by zero...", __FUNCTION__);
844                 APPL_TRACE_ERROR("%s - block=%d, subBands=%d, channels=%d", __FUNCTION__,
845                                  pstrEncParams->s16NumOfBlocks, pstrEncParams->s16NumOfSubBands,
846                                  pstrEncParams->s16NumOfChannels);
847                 break;
848             }
849 
850             if ((pstrEncParams->s16ChannelMode == SBC_JOINT_STEREO) ||
851                     (pstrEncParams->s16ChannelMode == SBC_STEREO) ) {
852                 s16BitPool = (SINT16)( (pstrEncParams->u16BitRate *
853                                         pstrEncParams->s16NumOfSubBands * 1000 / s16SamplingFreq)
854                                        - ( (32 + (4 * pstrEncParams->s16NumOfSubBands *
855                                                   pstrEncParams->s16NumOfChannels)
856                                             + ( (pstrEncParams->s16ChannelMode - 2) *
857                                                 pstrEncParams->s16NumOfSubBands )   )
858                                            / pstrEncParams->s16NumOfBlocks) );
859 
860                 s16FrameLen = 4 + (4 * pstrEncParams->s16NumOfSubBands *
861                                    pstrEncParams->s16NumOfChannels) / 8
862                               + ( ((pstrEncParams->s16ChannelMode - 2) *
863                                    pstrEncParams->s16NumOfSubBands)
864                                   + (pstrEncParams->s16NumOfBlocks * s16BitPool) ) / 8;
865 
866                 s16BitRate = (8 * s16FrameLen * s16SamplingFreq)
867                              / (pstrEncParams->s16NumOfSubBands *
868                                 pstrEncParams->s16NumOfBlocks * 1000);
869 
870                 if (s16BitRate > pstrEncParams->u16BitRate) {
871                     s16BitPool--;
872                 }
873 
874                 if (pstrEncParams->s16NumOfSubBands == 8) {
875                     s16BitPool = (s16BitPool > 255) ? 255 : s16BitPool;
876                 } else {
877                     s16BitPool = (s16BitPool > 128) ? 128 : s16BitPool;
878                 }
879             } else {
880                 s16BitPool = (SINT16)( ((pstrEncParams->s16NumOfSubBands *
881                                          pstrEncParams->u16BitRate * 1000)
882                                         / (s16SamplingFreq * pstrEncParams->s16NumOfChannels))
883                                        - ( ( (32 / pstrEncParams->s16NumOfChannels) +
884                                              (4 * pstrEncParams->s16NumOfSubBands) )
885                                            /   pstrEncParams->s16NumOfBlocks ) );
886 
887                 pstrEncParams->s16BitPool = (s16BitPool >
888                                              (16 * pstrEncParams->s16NumOfSubBands))
889                                             ? (16 * pstrEncParams->s16NumOfSubBands) : s16BitPool;
890             }
891 
892             if (s16BitPool < 0) {
893                 s16BitPool = 0;
894             }
895 
896             APPL_TRACE_EVENT("bitpool candidate : %d (%d kbps)",
897                              s16BitPool, pstrEncParams->u16BitRate);
898 
899             if (s16BitPool > pUpdateAudio->MaxBitPool) {
900                 APPL_TRACE_DEBUG("%s computed bitpool too large (%d)",  __FUNCTION__, s16BitPool);
901                 /* Decrease bitrate */
902                 a2dp_source_local_param.btc_aa_src_cb.encoder.u16BitRate -= BTC_MEDIA_BITRATE_STEP;
903                 /* Record that we have decreased the bitrate */
904                 protect |= 1;
905             } else if (s16BitPool < pUpdateAudio->MinBitPool) {
906                 APPL_TRACE_WARNING("%s computed bitpool too small (%d)", __FUNCTION__, s16BitPool);
907 
908                 /* Increase bitrate */
909                 UINT16 previous_u16BitRate = a2dp_source_local_param.btc_aa_src_cb.encoder.u16BitRate;
910                 a2dp_source_local_param.btc_aa_src_cb.encoder.u16BitRate += BTC_MEDIA_BITRATE_STEP;
911                 /* Record that we have increased the bitrate */
912                 protect |= 2;
913                 /* Check over-flow */
914                 if (a2dp_source_local_param.btc_aa_src_cb.encoder.u16BitRate < previous_u16BitRate) {
915                     protect |= 3;
916                 }
917             } else {
918                 break;
919             }
920             /* In case we have already increased and decreased the bitrate, just stop */
921             if (protect == 3) {
922                 APPL_TRACE_ERROR("%s could not find bitpool in range", __FUNCTION__);
923                 break;
924             }
925         } while (1);
926 
927         /* Finally update the bitpool in the encoder structure */
928         pstrEncParams->s16BitPool = s16BitPool;
929 
930         APPL_TRACE_DEBUG("%s final bit rate %d, final bit pool %d", __FUNCTION__,
931                          a2dp_source_local_param.btc_aa_src_cb.encoder.u16BitRate, a2dp_source_local_param.btc_aa_src_cb.encoder.s16BitPool);
932 
933         /* make sure we reinitialize encoder with new settings */
934         SBC_Encoder_Init(&(a2dp_source_local_param.btc_aa_src_cb.encoder));
935     }
936 }
937 
938 #if A2D_SRC_BQB_INCLUDED
939 /*******************************************************************************
940  **
941  ** Function         btc_a2dp_source_bqb_sbc_encoder_set
942  **
943  ** Description      Set SBC encoder for bqb test cases A2DP/SRC/SET/BV-04-I and A2DP/SRC/SET/BV-06-I
944  **
945  ** Returns          void
946  **
947  *******************************************************************************/
btc_a2dp_source_bqb_sbc_encoder_set(void)948 void btc_a2dp_source_bqb_sbc_encoder_set(void)
949 {
950     a2dp_source_local_param.btc_aa_src_cb.encoder.s16NumOfSubBands = 8;
951     a2dp_source_local_param.btc_aa_src_cb.encoder.s16NumOfBlocks = 8;
952     a2dp_source_local_param.btc_aa_src_cb.encoder.s16AllocationMethod = SBC_LOUDNESS;
953     a2dp_source_local_param.btc_aa_src_cb.encoder.s16ChannelMode = SBC_MONO;
954     a2dp_source_local_param.btc_aa_src_cb.encoder.s16SamplingFreq = SBC_sf44100;
955     SBC_Encoder_Init(&(a2dp_source_local_param.btc_aa_src_cb.encoder));
956 }
957 #endif /* A2D_SRC_BQB_INCLUDED */
958 
959 /*******************************************************************************
960  **
961  ** Function         btc_a2dp_source_pcm2sbc_init
962  **
963  ** Description      Init encoding task for PCM to SBC according to feeding
964  **
965  ** Returns          void
966  **
967  *******************************************************************************/
btc_a2dp_source_pcm2sbc_init(tBTC_MEDIA_INIT_AUDIO_FEEDING * p_feeding)968 static void btc_a2dp_source_pcm2sbc_init(tBTC_MEDIA_INIT_AUDIO_FEEDING *p_feeding)
969 {
970     BOOLEAN reconfig_needed = FALSE;
971 
972     APPL_TRACE_DEBUG("PCM feeding:");
973     APPL_TRACE_DEBUG("sampling_freq:%d", p_feeding->feeding.cfg.pcm.sampling_freq);
974     APPL_TRACE_DEBUG("num_channel:%d", p_feeding->feeding.cfg.pcm.num_channel);
975     APPL_TRACE_DEBUG("bit_per_sample:%d", p_feeding->feeding.cfg.pcm.bit_per_sample);
976 
977     /* Check the PCM feeding sampling_freq */
978     switch (p_feeding->feeding.cfg.pcm.sampling_freq) {
979     case  8000:
980     case 12000:
981     case 16000:
982     case 24000:
983     case 32000:
984     case 48000:
985         /* For these sampling_freq the AV connection must be 48000 */
986         if (a2dp_source_local_param.btc_aa_src_cb.encoder.s16SamplingFreq != SBC_sf48000) {
987             /* Reconfiguration needed at 48000 */
988             APPL_TRACE_DEBUG("SBC Reconfiguration needed at 48000");
989             a2dp_source_local_param.btc_aa_src_cb.encoder.s16SamplingFreq = SBC_sf48000;
990             reconfig_needed = TRUE;
991         }
992         break;
993 
994     case 11025:
995     case 22050:
996     case 44100:
997         /* For these sampling_freq the AV connection must be 44100 */
998         if (a2dp_source_local_param.btc_aa_src_cb.encoder.s16SamplingFreq != SBC_sf44100) {
999             /* Reconfiguration needed at 44100 */
1000             APPL_TRACE_DEBUG("SBC Reconfiguration needed at 44100");
1001             a2dp_source_local_param.btc_aa_src_cb.encoder.s16SamplingFreq = SBC_sf44100;
1002             reconfig_needed = TRUE;
1003         }
1004         break;
1005     default:
1006         APPL_TRACE_DEBUG("Feeding PCM sampling_freq unsupported");
1007         break;
1008     }
1009 
1010     /* Some AV Headsets do not support Mono => always ask for Stereo */
1011     if (a2dp_source_local_param.btc_aa_src_cb.encoder.s16ChannelMode == SBC_MONO) {
1012         APPL_TRACE_DEBUG("SBC Reconfiguration needed in Stereo");
1013         a2dp_source_local_param.btc_aa_src_cb.encoder.s16ChannelMode = SBC_JOINT_STEREO;
1014         reconfig_needed = TRUE;
1015     }
1016 
1017     if (reconfig_needed != FALSE) {
1018         APPL_TRACE_DEBUG("%s :: mtu %d", __FUNCTION__, a2dp_source_local_param.btc_aa_src_cb.TxAaMtuSize);
1019         APPL_TRACE_DEBUG("ch mode %d, nbsubd %d, nb %d, alloc %d, rate %d, freq %d",
1020                          a2dp_source_local_param.btc_aa_src_cb.encoder.s16ChannelMode,
1021                          a2dp_source_local_param.btc_aa_src_cb.encoder.s16NumOfSubBands, a2dp_source_local_param.btc_aa_src_cb.encoder.s16NumOfBlocks,
1022                          a2dp_source_local_param.btc_aa_src_cb.encoder.s16AllocationMethod, a2dp_source_local_param.btc_aa_src_cb.encoder.u16BitRate,
1023                          a2dp_source_local_param.btc_aa_src_cb.encoder.s16SamplingFreq);
1024 
1025         SBC_Encoder_Init(&(a2dp_source_local_param.btc_aa_src_cb.encoder));
1026     } else {
1027         APPL_TRACE_DEBUG("%s no SBC reconfig needed", __FUNCTION__);
1028     }
1029 
1030 #if A2D_SRC_BQB_INCLUDED
1031     if (a2dp_src_bqb_set_sbc_encoder_flag) {
1032         btc_a2dp_source_bqb_sbc_encoder_set();
1033     }
1034 #endif /* A2D_SRC_BQB_INCLUDED */
1035 }
1036 
1037 /*******************************************************************************
1038  **
1039  ** Function         btc_a2dp_source_audio_feeding_init
1040  **
1041  ** Description      Initialize the audio path according to the feeding format
1042  **
1043  ** Returns          void
1044  **
1045  *******************************************************************************/
btc_a2dp_source_audio_feeding_init(BT_HDR * p_msg)1046 static void btc_a2dp_source_audio_feeding_init(BT_HDR *p_msg)
1047 {
1048     tBTC_MEDIA_INIT_AUDIO_FEEDING *p_feeding = (tBTC_MEDIA_INIT_AUDIO_FEEDING *) p_msg;
1049 
1050     APPL_TRACE_DEBUG("%s format:%d", __FUNCTION__, p_feeding->feeding.format);
1051 
1052     /* Save Media Feeding information */
1053     a2dp_source_local_param.btc_aa_src_cb.feeding_mode = p_feeding->feeding_mode;
1054     a2dp_source_local_param.btc_aa_src_cb.media_feeding = p_feeding->feeding;
1055 
1056     /* Handle different feeding formats */
1057     switch (p_feeding->feeding.format) {
1058     case BTC_AV_CODEC_PCM:
1059         a2dp_source_local_param.btc_aa_src_cb.TxTranscoding = BTC_MEDIA_TRSCD_PCM_2_SBC;
1060         btc_a2dp_source_pcm2sbc_init(p_feeding);
1061         break;
1062 
1063     default :
1064         APPL_TRACE_ERROR("unknown feeding format %d", p_feeding->feeding.format);
1065         break;
1066     }
1067 }
1068 
1069 /*******************************************************************************
1070  **
1071  ** Function         btc_a2dp_source_aa_tx_flush
1072  **
1073  ** Description
1074  **
1075  ** Returns          void
1076  **
1077  *******************************************************************************/
btc_a2dp_source_aa_tx_flush(void)1078 static void btc_a2dp_source_aa_tx_flush(void)
1079 {
1080     /* Flush all enqueued music buffers (encoded) */
1081     APPL_TRACE_DEBUG("%s", __FUNCTION__);
1082 
1083     a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.counter = 0;
1084     a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.aa_feed_residue = 0;
1085 
1086     btc_a2dp_source_flush_q(a2dp_source_local_param.btc_aa_src_cb.TxAaQ);
1087 
1088     btc_aa_src_data_read(NULL, -1);
1089 }
1090 
1091 /*******************************************************************************
1092  **
1093  ** Function         btc_get_num_aa_frame
1094  **
1095  ** Description
1096  **
1097  ** Returns          The number of media frames in this time slice
1098  **
1099  *******************************************************************************/
btc_get_num_aa_frame(void)1100 static UINT8 btc_get_num_aa_frame(void)
1101 {
1102     UINT8 result = 0;
1103 
1104     switch (a2dp_source_local_param.btc_aa_src_cb.TxTranscoding) {
1105     case BTC_MEDIA_TRSCD_PCM_2_SBC: {
1106         UINT32 pcm_bytes_per_frame = a2dp_source_local_param.btc_aa_src_cb.encoder.s16NumOfSubBands *
1107                                      a2dp_source_local_param.btc_aa_src_cb.encoder.s16NumOfBlocks *
1108                                      a2dp_source_local_param.btc_aa_src_cb.media_feeding.cfg.pcm.num_channel *
1109                                      a2dp_source_local_param.btc_aa_src_cb.media_feeding.cfg.pcm.bit_per_sample / 8;
1110 
1111         UINT32 us_this_tick = BTC_MEDIA_TIME_TICK_MS * 1000;
1112         UINT64 now_us = time_now_us();
1113         if (a2dp_source_local_param.last_frame_us != 0) {
1114 #if _POSIX_TIMERS
1115             us_this_tick = (now_us - a2dp_source_local_param.last_frame_us);
1116 #else
1117             // consider the case that the number of day increases and timeofday wraps around
1118             us_this_tick = (now_us > a2dp_source_local_param.last_frame_us) ? (now_us - a2dp_source_local_param.last_frame_us) :
1119                            (now_us + 86400000000ull - a2dp_source_local_param.last_frame_us);
1120 #endif
1121         }
1122         a2dp_source_local_param.last_frame_us = now_us;
1123 
1124         a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.counter +=
1125             a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.bytes_per_tick *
1126             us_this_tick / (BTC_MEDIA_TIME_TICK_MS * 1000);
1127 
1128         /* calculate nbr of frames pending for this media tick */
1129         result = a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.counter / pcm_bytes_per_frame;
1130 
1131         /* limit the frames to be sent */
1132         UINT32 frm_nb_threshold = MAX_OUTPUT_A2DP_SRC_FRAME_QUEUE_SZ - fixed_queue_length(a2dp_source_local_param.btc_aa_src_cb.TxAaQ);
1133         if (frm_nb_threshold > MAX_PCM_FRAME_NUM_PER_TICK) {
1134             frm_nb_threshold = MAX_PCM_FRAME_NUM_PER_TICK;
1135         }
1136 
1137         if (result > frm_nb_threshold) {
1138             APPL_TRACE_EVENT("Limit frms to send from %d to %d", result, frm_nb_threshold);
1139             result = frm_nb_threshold;
1140         }
1141         a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.counter -= result * pcm_bytes_per_frame;
1142 
1143         BTC_TRACE_VERBOSE("WRITE %d FRAMES", result);
1144     }
1145     break;
1146 
1147     default:
1148         APPL_TRACE_ERROR("ERROR btc_get_num_aa_frame Unsupported transcoding format 0x%x",
1149                          a2dp_source_local_param.btc_aa_src_cb.TxTranscoding);
1150         result = 0;
1151         break;
1152     }
1153 
1154     return (UINT8)result;
1155 }
1156 
1157 /*******************************************************************************
1158  **
1159  ** Function         btc_media_aa_read_feeding
1160  **
1161  ** Description
1162  **
1163  ** Returns          void
1164  **
1165  *******************************************************************************/
1166 
btc_media_aa_read_feeding(void)1167 BOOLEAN btc_media_aa_read_feeding(void)
1168 {
1169     UINT16 blocm_x_subband = a2dp_source_local_param.btc_aa_src_cb.encoder.s16NumOfSubBands * \
1170                              a2dp_source_local_param.btc_aa_src_cb.encoder.s16NumOfBlocks;
1171     UINT32 read_size;
1172     UINT16 sbc_sampling = 48000;
1173     UINT32 src_samples;
1174     UINT16 bytes_needed = blocm_x_subband * a2dp_source_local_param.btc_aa_src_cb.encoder.s16NumOfChannels * \
1175                           a2dp_source_local_param.btc_aa_src_cb.media_feeding.cfg.pcm.bit_per_sample / 8;
1176     static UINT16 up_sampled_buffer[SBC_MAX_NUM_FRAME * SBC_MAX_NUM_OF_BLOCKS
1177                                     * SBC_MAX_NUM_OF_CHANNELS * SBC_MAX_NUM_OF_SUBBANDS * 2];
1178     static UINT16 read_buffer[SBC_MAX_NUM_FRAME * SBC_MAX_NUM_OF_BLOCKS
1179                               * SBC_MAX_NUM_OF_CHANNELS * SBC_MAX_NUM_OF_SUBBANDS];
1180     UINT32 src_size_used;
1181     UINT32 dst_size_used;
1182     BOOLEAN fract_needed;
1183     INT32   fract_max;
1184     INT32   fract_threshold;
1185     UINT32  nb_byte_read = 0;
1186 
1187     /* Get the SBC sampling rate */
1188     switch (a2dp_source_local_param.btc_aa_src_cb.encoder.s16SamplingFreq) {
1189     case SBC_sf48000:
1190         sbc_sampling = 48000;
1191         break;
1192     case SBC_sf44100:
1193         sbc_sampling = 44100;
1194         break;
1195     case SBC_sf32000:
1196         sbc_sampling = 32000;
1197         break;
1198     case SBC_sf16000:
1199         sbc_sampling = 16000;
1200         break;
1201     }
1202 
1203     if (sbc_sampling == a2dp_source_local_param.btc_aa_src_cb.media_feeding.cfg.pcm.sampling_freq) {
1204         read_size = bytes_needed - a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.aa_feed_residue;
1205         nb_byte_read = btc_aa_src_data_read(
1206                            ((uint8_t *)a2dp_source_local_param.btc_aa_src_cb.encoder.as16PcmBuffer) +
1207                            a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.aa_feed_residue,
1208                            read_size);
1209         if (nb_byte_read == read_size) {
1210             a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.aa_feed_residue = 0;
1211             return TRUE;
1212         } else {
1213             APPL_TRACE_WARNING("### UNDERFLOW :: ONLY READ %d BYTES OUT OF %d ###",
1214                                nb_byte_read, read_size);
1215             a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.aa_feed_residue += nb_byte_read;
1216             return FALSE;
1217         }
1218     }
1219 
1220     /* Some Feeding PCM frequencies require to split the number of sample */
1221     /* to read. */
1222     /* E.g 128/6=21.3333 => read 22 and 21 and 21 => max = 2; threshold = 0*/
1223     fract_needed = FALSE;   /* Default */
1224     switch (a2dp_source_local_param.btc_aa_src_cb.media_feeding.cfg.pcm.sampling_freq) {
1225     case 32000:
1226     case 8000:
1227         fract_needed = TRUE;
1228         fract_max = 2;          /* 0, 1 and 2 */
1229         fract_threshold = 0;    /* Add one for the first */
1230         break;
1231     case 16000:
1232         fract_needed = TRUE;
1233         fract_max = 2;          /* 0, 1 and 2 */
1234         fract_threshold = 1;    /* Add one for the first two frames*/
1235         break;
1236     }
1237 
1238     /* Compute number of sample to read from source */
1239     src_samples = blocm_x_subband;
1240     src_samples *= a2dp_source_local_param.btc_aa_src_cb.media_feeding.cfg.pcm.sampling_freq;
1241     src_samples /= sbc_sampling;
1242 
1243     /* The previous division may have a remainder not null */
1244     if (fract_needed) {
1245         if (a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.aa_feed_counter <= fract_threshold) {
1246             src_samples++; /* for every read before threshold add one sample */
1247         }
1248 
1249         /* do nothing if counter >= threshold */
1250         a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.aa_feed_counter++; /* one more read */
1251         if (a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.aa_feed_counter > fract_max) {
1252             a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.aa_feed_counter = 0;
1253         }
1254     }
1255 
1256     /* Compute number of bytes to read from source */
1257     read_size = src_samples;
1258     read_size *= a2dp_source_local_param.btc_aa_src_cb.media_feeding.cfg.pcm.num_channel;
1259     read_size *= (a2dp_source_local_param.btc_aa_src_cb.media_feeding.cfg.pcm.bit_per_sample / 8);
1260 
1261     /* Read Data from data channel */
1262     nb_byte_read = btc_aa_src_data_read((uint8_t *)read_buffer, read_size);
1263 
1264     if (nb_byte_read < read_size) {
1265         APPL_TRACE_WARNING("### UNDERRUN :: ONLY READ %d BYTES OUT OF %d ###",
1266                            nb_byte_read, read_size);
1267 
1268         if (nb_byte_read == 0) {
1269             return FALSE;
1270         }
1271 
1272         if (a2dp_source_local_param.btc_aa_src_cb.feeding_mode == BTC_AV_FEEDING_ASYNCHRONOUS) {
1273             /* Fill the unfilled part of the read buffer with silence (0) */
1274             memset(((UINT8 *)read_buffer) + nb_byte_read, 0, read_size - nb_byte_read);
1275             nb_byte_read = read_size;
1276         }
1277     }
1278 
1279     /* Initialize PCM up-sampling engine */
1280     bta_av_sbc_init_up_sample(a2dp_source_local_param.btc_aa_src_cb.media_feeding.cfg.pcm.sampling_freq,
1281                               sbc_sampling, a2dp_source_local_param.btc_aa_src_cb.media_feeding.cfg.pcm.bit_per_sample,
1282                               a2dp_source_local_param.btc_aa_src_cb.media_feeding.cfg.pcm.num_channel);
1283 
1284     /* re-sample read buffer */
1285     /* The output PCM buffer will be stereo, 16 bit per sample */
1286     dst_size_used = bta_av_sbc_up_sample((UINT8 *)read_buffer,
1287                                          (UINT8 *)up_sampled_buffer + a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.aa_feed_residue,
1288                                          nb_byte_read,
1289                                          sizeof(up_sampled_buffer) - a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.aa_feed_residue,
1290                                          &src_size_used);
1291 
1292     /* update the residue */
1293     a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.aa_feed_residue += dst_size_used;
1294 
1295     /* only copy the pcm sample when we have up-sampled enough PCM */
1296     if (a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.aa_feed_residue >= bytes_needed) {
1297         /* Copy the output pcm samples in SBC encoding buffer */
1298         memcpy((UINT8 *)a2dp_source_local_param.btc_aa_src_cb.encoder.as16PcmBuffer,
1299                (UINT8 *)up_sampled_buffer,
1300                bytes_needed);
1301         /* update the residue */
1302         a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.aa_feed_residue -= bytes_needed;
1303 
1304         if (a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.aa_feed_residue != 0) {
1305             memcpy((UINT8 *)up_sampled_buffer,
1306                    (UINT8 *)up_sampled_buffer + bytes_needed,
1307                    a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.aa_feed_residue);
1308         }
1309         return TRUE;
1310     }
1311 
1312     return FALSE;
1313 }
1314 
1315 /*******************************************************************************
1316  **
1317  ** Function         btc_media_aa_prep_sbc_2_send
1318  **
1319  ** Description
1320  **
1321  ** Returns          void
1322  **
1323  *******************************************************************************/
btc_media_aa_prep_sbc_2_send(UINT8 nb_frame)1324 static void btc_media_aa_prep_sbc_2_send(UINT8 nb_frame)
1325 {
1326     BT_HDR *p_buf;
1327     UINT16 blocm_x_subband = a2dp_source_local_param.btc_aa_src_cb.encoder.s16NumOfSubBands *
1328                              a2dp_source_local_param.btc_aa_src_cb.encoder.s16NumOfBlocks;
1329 
1330     while (nb_frame) {
1331         if (NULL == (p_buf = osi_malloc(BTC_MEDIA_AA_BUF_SIZE))) {
1332             APPL_TRACE_ERROR ("ERROR btc_media_aa_prep_sbc_2_send no buffer TxCnt %d ",
1333                               fixed_queue_length(a2dp_source_local_param.btc_aa_src_cb.TxAaQ));
1334             return;
1335         }
1336 
1337         /* Init buffer */
1338         p_buf->offset = BTC_MEDIA_AA_SBC_OFFSET;
1339         p_buf->len = 0;
1340         p_buf->layer_specific = 0;
1341 
1342         do {
1343             /* Write @ of allocated buffer in encoder.pu8Packet */
1344             a2dp_source_local_param.btc_aa_src_cb.encoder.pu8Packet = (UINT8 *) (p_buf + 1) + p_buf->offset + p_buf->len;
1345             /* Fill allocated buffer with 0 */
1346             memset(a2dp_source_local_param.btc_aa_src_cb.encoder.as16PcmBuffer, 0, blocm_x_subband
1347                    * a2dp_source_local_param.btc_aa_src_cb.encoder.s16NumOfChannels);
1348 
1349             /* Read PCM data and upsample them if needed */
1350             if (btc_media_aa_read_feeding()) {
1351                 /* SBC encode and descramble frame */
1352                 SBC_Encoder(&(a2dp_source_local_param.btc_aa_src_cb.encoder));
1353 
1354                 /* Update SBC frame length */
1355                 p_buf->len += a2dp_source_local_param.btc_aa_src_cb.encoder.u16PacketLength;
1356                 nb_frame--;
1357                 p_buf->layer_specific++;
1358             } else {
1359                 APPL_TRACE_WARNING("btc_media_aa_prep_sbc_2_send underflow %d, %d",
1360                                    nb_frame, a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.aa_feed_residue);
1361                 a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.counter += nb_frame *
1362                         a2dp_source_local_param.btc_aa_src_cb.encoder.s16NumOfSubBands *
1363                         a2dp_source_local_param.btc_aa_src_cb.encoder.s16NumOfBlocks *
1364                         a2dp_source_local_param.btc_aa_src_cb.media_feeding.cfg.pcm.num_channel *
1365                         a2dp_source_local_param.btc_aa_src_cb.media_feeding.cfg.pcm.bit_per_sample / 8;
1366                 /* no more pcm to read */
1367                 nb_frame = 0;
1368 
1369                 /* break read loop if timer was stopped (media task stopped) */
1370                 if ( a2dp_source_local_param.btc_aa_src_cb.is_tx_timer == FALSE ) {
1371                     osi_free(p_buf);
1372                     return;
1373                 }
1374             }
1375 
1376         } while (((p_buf->len + a2dp_source_local_param.btc_aa_src_cb.encoder.u16PacketLength) < a2dp_source_local_param.btc_aa_src_cb.TxAaMtuSize)
1377                  && (p_buf->layer_specific < 0x0F) && nb_frame);
1378 
1379         if (p_buf->len) {
1380             /* timestamp of the media packet header represent the TS of the first SBC frame
1381                i.e the timestamp before including this frame */
1382             *((UINT32 *) (p_buf + 1)) = a2dp_source_local_param.btc_aa_src_cb.timestamp;
1383 
1384             a2dp_source_local_param.btc_aa_src_cb.timestamp += p_buf->layer_specific * blocm_x_subband;
1385 
1386             if (a2dp_source_local_param.btc_aa_src_cb.tx_flush) {
1387                 APPL_TRACE_DEBUG("### tx suspended, discarded frame ###");
1388 
1389                 if (fixed_queue_length(a2dp_source_local_param.btc_aa_src_cb.TxAaQ) > 0) {
1390                     btc_a2dp_source_flush_q(a2dp_source_local_param.btc_aa_src_cb.TxAaQ);
1391                 }
1392 
1393                 osi_free(p_buf);
1394                 return;
1395             }
1396 
1397             /* Enqueue the encoded SBC frame in AA Tx Queue */
1398             fixed_queue_enqueue(a2dp_source_local_param.btc_aa_src_cb.TxAaQ, p_buf, FIXED_QUEUE_MAX_TIMEOUT);
1399         } else {
1400             osi_free(p_buf);
1401         }
1402     }
1403 }
1404 
1405 /*******************************************************************************
1406  **
1407  ** Function         btc_a2dp_source_prep_2_send
1408  **
1409  ** Description
1410  **
1411  ** Returns          void
1412  **
1413  *******************************************************************************/
btc_a2dp_source_prep_2_send(UINT8 nb_frame)1414 static void btc_a2dp_source_prep_2_send(UINT8 nb_frame)
1415 {
1416     // Check for TX queue overflow
1417     if (nb_frame > MAX_OUTPUT_A2DP_SRC_FRAME_QUEUE_SZ) {
1418         nb_frame = MAX_OUTPUT_A2DP_SRC_FRAME_QUEUE_SZ;
1419     }
1420 
1421     if (fixed_queue_length(a2dp_source_local_param.btc_aa_src_cb.TxAaQ) > (MAX_OUTPUT_A2DP_SRC_FRAME_QUEUE_SZ - nb_frame)) {
1422         APPL_TRACE_WARNING("TX Q overflow: %d/%d",
1423                            fixed_queue_length(a2dp_source_local_param.btc_aa_src_cb.TxAaQ), MAX_OUTPUT_A2DP_SRC_FRAME_QUEUE_SZ - nb_frame);
1424     }
1425 
1426     while (fixed_queue_length(a2dp_source_local_param.btc_aa_src_cb.TxAaQ) > (MAX_OUTPUT_A2DP_SRC_FRAME_QUEUE_SZ - nb_frame)) {
1427         osi_free(fixed_queue_dequeue(a2dp_source_local_param.btc_aa_src_cb.TxAaQ, 0));
1428     }
1429 
1430     // Transcode frame
1431 
1432     switch (a2dp_source_local_param.btc_aa_src_cb.TxTranscoding) {
1433     case BTC_MEDIA_TRSCD_PCM_2_SBC:
1434         btc_media_aa_prep_sbc_2_send(nb_frame);
1435         break;
1436 
1437     default:
1438         APPL_TRACE_ERROR("%s unsupported transcoding format 0x%x", __func__, a2dp_source_local_param.btc_aa_src_cb.TxTranscoding);
1439         break;
1440     }
1441 }
1442 
1443 /*******************************************************************************
1444  **
1445  ** Function         btc_a2dp_source_send_aa_frame
1446  **
1447  ** Description
1448  **
1449  ** Returns          void
1450  **
1451  *******************************************************************************/
btc_a2dp_source_send_aa_frame(void)1452 static void btc_a2dp_source_send_aa_frame(void)
1453 {
1454     UINT8 nb_frame_2_send;
1455 
1456     /* get the number of frame to send */
1457     nb_frame_2_send = btc_get_num_aa_frame();
1458 
1459     if (nb_frame_2_send != 0) {
1460         /* format and Q buffer to send */
1461         btc_a2dp_source_prep_2_send(nb_frame_2_send);
1462     }
1463 
1464     /* send it */
1465     BTC_TRACE_VERBOSE("%s: send %d frames", __FUNCTION__, nb_frame_2_send);
1466     bta_av_ci_src_data_ready(BTA_AV_CHNL_AUDIO);
1467 }
1468 
btc_a2dp_source_handle_timer(UNUSED_ATTR void * context)1469 static void btc_a2dp_source_handle_timer(UNUSED_ATTR void *context)
1470 {
1471     log_tstamps_us("media task tx timer");
1472 
1473 #if (BTA_AV_INCLUDED == TRUE)
1474     if (btc_a2dp_source_state != BTC_A2DP_SOURCE_STATE_ON || g_a2dp_source_ongoing_deinit){
1475         return;
1476     }
1477 
1478     if (a2dp_source_local_param.btc_aa_src_cb.is_tx_timer == TRUE) {
1479         btc_a2dp_source_send_aa_frame();
1480     } else {
1481         APPL_TRACE_WARNING("Media task Scheduled after Suspend");
1482     }
1483 #endif
1484 }
1485 
1486 /*******************************************************************************
1487  **
1488  ** Function         btc_a2dp_source_feeding_state_reset
1489  **
1490  ** Description      Reset the media feeding state
1491  **
1492  ** Returns          void
1493  **
1494  *******************************************************************************/
btc_a2dp_source_feeding_state_reset(void)1495 static void btc_a2dp_source_feeding_state_reset(void)
1496 {
1497     /* By default, just clear the entire state */
1498     memset(&a2dp_source_local_param.btc_aa_src_cb.media_feeding_state, 0, sizeof(a2dp_source_local_param.btc_aa_src_cb.media_feeding_state));
1499 
1500     if (a2dp_source_local_param.btc_aa_src_cb.TxTranscoding == BTC_MEDIA_TRSCD_PCM_2_SBC) {
1501         a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.bytes_per_tick =
1502             (a2dp_source_local_param.btc_aa_src_cb.media_feeding.cfg.pcm.sampling_freq *
1503              a2dp_source_local_param.btc_aa_src_cb.media_feeding.cfg.pcm.bit_per_sample / 8 *
1504              a2dp_source_local_param.btc_aa_src_cb.media_feeding.cfg.pcm.num_channel *
1505              BTC_MEDIA_TIME_TICK_MS) / 1000;
1506 
1507         APPL_TRACE_EVENT("pcm bytes per tick %d",
1508                            (int)a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.bytes_per_tick);
1509     }
1510 }
1511 
1512 /*******************************************************************************
1513  **
1514  ** Function         btc_a2dp_source_aa_stop_tx
1515  **
1516  ** Description      Stop media task encoding
1517  **
1518  ** Returns          void
1519  **
1520  *******************************************************************************/
btc_a2dp_source_aa_stop_tx(void)1521 static void btc_a2dp_source_aa_stop_tx(void)
1522 {
1523     APPL_TRACE_DEBUG("%s is_tx_timer: %d", __func__, a2dp_source_local_param.btc_aa_src_cb.is_tx_timer);
1524 
1525     const bool send_ack = (a2dp_source_local_param.btc_aa_src_cb.is_tx_timer != FALSE);
1526 
1527     /* Stop the timer first */
1528     if (a2dp_source_local_param.btc_aa_src_cb.media_alarm) {
1529         osi_alarm_cancel(a2dp_source_local_param.btc_aa_src_cb.media_alarm);
1530         osi_alarm_free(a2dp_source_local_param.btc_aa_src_cb.media_alarm);
1531     }
1532     a2dp_source_local_param.btc_aa_src_cb.media_alarm = NULL;
1533     a2dp_source_local_param.btc_aa_src_cb.is_tx_timer = FALSE;
1534 
1535     /* Try to send acknowldegment once the media stream is
1536        stopped. This will make sure that the A2DP HAL layer is
1537        un-blocked on wait for acknowledgment for the sent command.
1538        This resolves a corner cases AVDTP SUSPEND collision
1539        when the DUT and the remote device issue SUSPEND simultaneously
1540        and due to the processing of the SUSPEND request from the remote,
1541        the media path is torn down. If the A2DP HAL happens to wait
1542        for ACK for the initiated SUSPEND, it would never receive it casuing
1543        a block/wait. Due to this acknowledgement, the A2DP HAL is guranteed
1544        to get the ACK for any pending command in such cases. */
1545 
1546     if (send_ack) {
1547         btc_a2dp_control_command_ack(ESP_A2D_MEDIA_CTRL_ACK_SUCCESS);
1548     }
1549 
1550     /* audio engine stopped, reset tx suspended flag */
1551     a2dp_source_local_param.btc_aa_src_cb.tx_flush = 0;
1552     a2dp_source_local_param.last_frame_us = 0;
1553 
1554     /* Reset the feeding state */
1555     btc_a2dp_source_feeding_state_reset();
1556 }
1557 
1558 /*******************************************************************************
1559  **
1560  ** Function         btc_a2dp_source_aa_start_tx
1561  **
1562  ** Description      Start media task encoding
1563  **
1564  ** Returns          void
1565  **
1566  *******************************************************************************/
btc_a2dp_source_alarm_cb(UNUSED_ATTR void * context)1567 static void btc_a2dp_source_alarm_cb(UNUSED_ATTR void *context)
1568 {
1569     if (a2dp_source_local_param.btc_aa_src_task_hdl) {
1570         osi_thread_post_event(a2dp_source_local_param.btc_aa_src_cb.poll_data, OSI_THREAD_MAX_TIMEOUT);
1571     } else {
1572         APPL_TRACE_DEBUG("[%s] A2DP ALREADY FREED", __func__);
1573         btc_a2dp_source_aa_stop_tx();
1574     }
1575 }
1576 
btc_a2dp_source_aa_start_tx(void)1577 static void btc_a2dp_source_aa_start_tx(void)
1578 {
1579     APPL_TRACE_DEBUG("btc_a2dp_source_aa_start_tx is timer %d, feeding mode %d",
1580                      a2dp_source_local_param.btc_aa_src_cb.is_tx_timer, a2dp_source_local_param.btc_aa_src_cb.feeding_mode);
1581 
1582     a2dp_source_local_param.btc_aa_src_cb.is_tx_timer = TRUE;
1583     a2dp_source_local_param.last_frame_us = 0;
1584 
1585     /* Reset the media feeding state */
1586     btc_a2dp_source_feeding_state_reset();
1587 
1588     APPL_TRACE_EVENT("starting timer %dms", BTC_MEDIA_TIME_TICK_MS);
1589 
1590     assert(a2dp_source_local_param.btc_aa_src_cb.media_alarm == NULL);
1591 
1592     a2dp_source_local_param.btc_aa_src_cb.media_alarm = osi_alarm_new("aaTx", btc_a2dp_source_alarm_cb, NULL, BTC_MEDIA_TIME_TICK_MS);
1593 
1594     if (!a2dp_source_local_param.btc_aa_src_cb.media_alarm) {
1595         BTC_TRACE_ERROR("%s unable to allocate media alarm.", __func__);
1596         return;
1597     }
1598 
1599     osi_alarm_set_periodic(a2dp_source_local_param.btc_aa_src_cb.media_alarm, BTC_MEDIA_TIME_TICK_MS);
1600 }
1601 
1602 /*******************************************************************************
1603  **
1604  ** Function         btc_a2dp_source_flush_q
1605  **
1606  ** Description
1607  **
1608  ** Returns          void
1609  **
1610  *******************************************************************************/
btc_a2dp_source_flush_q(fixed_queue_t * p_q)1611 static void btc_a2dp_source_flush_q(fixed_queue_t *p_q)
1612 {
1613     while (! fixed_queue_is_empty(p_q)) {
1614         osi_free(fixed_queue_dequeue(p_q, 0));
1615     }
1616 }
1617 
btc_a2dp_source_thread_init(UNUSED_ATTR void * context)1618 static void btc_a2dp_source_thread_init(UNUSED_ATTR void *context)
1619 {
1620     APPL_TRACE_EVENT("%s\n", __func__);
1621     memset(&a2dp_source_local_param.btc_aa_src_cb, 0, sizeof(a2dp_source_local_param.btc_aa_src_cb));
1622 
1623     btc_a2dp_source_state = BTC_A2DP_SOURCE_STATE_ON;
1624 
1625     struct osi_event *poll_data = osi_event_create(btc_a2dp_source_handle_timer, NULL);
1626     assert(poll_data != NULL);
1627     osi_event_bind(poll_data, a2dp_source_local_param.btc_aa_src_task_hdl, BTC_A2DP_SRC_DATA_QUEUE_IDX);
1628     a2dp_source_local_param.btc_aa_src_cb.poll_data = poll_data;
1629 
1630     a2dp_source_local_param.btc_aa_src_cb.TxAaQ = fixed_queue_new(QUEUE_SIZE_MAX);
1631 
1632     btc_a2dp_control_init();
1633 }
1634 
btc_a2dp_source_thread_cleanup(UNUSED_ATTR void * context)1635 static void btc_a2dp_source_thread_cleanup(UNUSED_ATTR void *context)
1636 {
1637     /* Clear media task flag */
1638     btc_a2dp_source_state = BTC_A2DP_SOURCE_STATE_OFF;
1639 
1640     btc_a2dp_control_cleanup();
1641 
1642     fixed_queue_free(a2dp_source_local_param.btc_aa_src_cb.TxAaQ, osi_free_func);
1643 
1644     a2dp_source_local_param.btc_aa_src_cb.TxAaQ = NULL;
1645 
1646     osi_event_delete(a2dp_source_local_param.btc_aa_src_cb.poll_data);
1647     a2dp_source_local_param.btc_aa_src_cb.poll_data = NULL;
1648 }
1649 
1650 #endif /* BTC_AV_INCLUDED */
1651