but due to link flow control or thread preemption in lower
layers we might need to temporarily buffer up data */
-/* 24 frames is equivalent to 6.89*24*2.9 ~= 480 ms @ 44.1 khz, 20 ms mediatick */
-#define MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ 24
+/* 18 frames is equivalent to 6.89*18*2.9 ~= 360 ms @ 44.1 khz, 20 ms mediatick */
+#define MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ 18
+#define A2DP_PACKET_COUNT_LOW_WATERMARK 5
+#define MAX_PCM_FRAME_NUM_PER_TICK 40
+#define RESET_RATE_COUNTER_THRESHOLD_MS 2000
//#define BTIF_MEDIA_VERBOSE_ENABLED
INT32 aa_feed_residue;
UINT32 counter;
UINT32 bytes_per_tick; /* pcm bytes read each media task tick */
+ UINT32 max_counter_exit;
+ UINT32 max_counter_enter;
+ UINT32 overflow_count;
+ BOOLEAN overflow;
} tBTIF_AV_MEDIA_FEEDINGS_PCM_STATE;
*******************************************************************************/
static void btif_media_task_feeding_state_reset(void)
{
+ APPL_TRACE_WARNING3("overflow %d, enter %d, exit %d",
+ btif_media_cb.media_feeding_state.pcm.overflow_count,
+ btif_media_cb.media_feeding_state.pcm.max_counter_enter,
+ btif_media_cb.media_feeding_state.pcm.max_counter_exit);
+
/* By default, just clear the entire state */
memset(&btif_media_cb.media_feeding_state, 0, sizeof(btif_media_cb.media_feeding_state));
*******************************************************************************/
static UINT8 btif_get_num_aa_frame(void)
{
- UINT8 result=0;
+ UINT32 result=0;
switch (btif_media_cb.TxTranscoding)
{
btif_media_cb.media_feeding_state.pcm.counter +=
btif_media_cb.media_feeding_state.pcm.bytes_per_tick;
-
- /* calculate nbr of frames pending for this media tick */
- result = btif_media_cb.media_feeding_state.pcm.counter/pcm_bytes_per_frame;
- btif_media_cb.media_feeding_state.pcm.counter -= result*pcm_bytes_per_frame;
-
+ if ((!btif_media_cb.media_feeding_state.pcm.overflow) ||
+ (btif_media_cb.TxAaQ.count < A2DP_PACKET_COUNT_LOW_WATERMARK)) {
+ if (btif_media_cb.media_feeding_state.pcm.overflow) {
+ btif_media_cb.media_feeding_state.pcm.overflow = FALSE;
+
+ if (btif_media_cb.media_feeding_state.pcm.counter >
+ btif_media_cb.media_feeding_state.pcm.max_counter_exit) {
+ btif_media_cb.media_feeding_state.pcm.max_counter_exit =
+ btif_media_cb.media_feeding_state.pcm.counter;
+ }
+ }
+ /* calculate nbr of frames pending for this media tick */
+ result = btif_media_cb.media_feeding_state.pcm.counter/pcm_bytes_per_frame;
+ if (result > MAX_PCM_FRAME_NUM_PER_TICK) result = MAX_PCM_FRAME_NUM_PER_TICK;
+ btif_media_cb.media_feeding_state.pcm.counter -= result*pcm_bytes_per_frame;
+ } else {
+ result = 0;
+ }
VERBOSE("WRITE %d FRAMES", result);
}
break;
APPL_TRACE_DEBUG1("btif_get_num_aa_frame returns %d", result);
#endif
- return result;
+ return (UINT8)result;
}
/*******************************************************************************
{
GKI_freebuf(p_buf);
}
+
+ if (btif_media_cb.TxAaQ.count >= MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ) {
+ UINT32 reset_rate_bytes = btif_media_cb.media_feeding_state.pcm.bytes_per_tick *
+ (RESET_RATE_COUNTER_THRESHOLD_MS / BTIF_MEDIA_TIME_TICK);
+ btif_media_cb.media_feeding_state.pcm.overflow = TRUE;
+ btif_media_cb.media_feeding_state.pcm.counter += nb_frame *
+ btif_media_cb.encoder.s16NumOfSubBands *
+ btif_media_cb.encoder.s16NumOfBlocks *
+ btif_media_cb.media_feeding.cfg.pcm.num_channel *
+ btif_media_cb.media_feeding.cfg.pcm.bit_per_sample / 8;
+
+ btif_media_cb.media_feeding_state.pcm.overflow_count++;
+ if (btif_media_cb.media_feeding_state.pcm.counter >
+ btif_media_cb.media_feeding_state.pcm.max_counter_enter) {
+ btif_media_cb.media_feeding_state.pcm.max_counter_enter =
+ btif_media_cb.media_feeding_state.pcm.counter;
+ }
+
+ if (btif_media_cb.media_feeding_state.pcm.counter > reset_rate_bytes) {
+ btif_media_cb.media_feeding_state.pcm.counter = 0;
+ APPL_TRACE_WARNING0("btif_media_aa_prep_sbc_2_send:reset rate counter");
+ }
+
+ /* no more pcm to read */
+ nb_frame = 0;
+ }
}
}
VERBOSE("btif_media_aa_prep_2_send : %d frames (queue %d)", nb_frame,
btif_media_cb.TxAaQ.count);
- while (btif_media_cb.TxAaQ.count >= MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ)
- {
- APPL_TRACE_WARNING1("btif_media_aa_prep_2_send congestion buf count %d",
- btif_media_cb.TxAaQ.count);
- GKI_freebuf(GKI_dequeue(&(btif_media_cb.TxAaQ)));
- }
-
switch (btif_media_cb.TxTranscoding)
{
case BTIF_MEDIA_TRSCD_PCM_2_SBC:
/* get the number of frame to send */
nb_frame_2_send = btif_get_num_aa_frame();
- /* format and Q buffer to send */
- btif_media_aa_prep_2_send(nb_frame_2_send);
+ if (nb_frame_2_send != 0) {
+ /* format and Q buffer to send */
+ btif_media_aa_prep_2_send(nb_frame_2_send);
+ }
/* send it */
VERBOSE("btif_media_send_aa_frame : send %d frames", nb_frame_2_send);