diff options
author | Matthew Xie <mattx@google.com> | 2012-10-25 22:27:47 -0700 |
---|---|---|
committer | Matthew Xie <mattx@google.com> | 2012-10-25 22:27:47 -0700 |
commit | b930299a8ad32a8227b00e0d9016b62682b577f3 (patch) | |
tree | 50e275d8d85741eaaeb304416bd5f8be3b3382db | |
parent | 9ab1946281916b06df6cb2e5eb37ad12cd4dce4a (diff) | |
download | external_bluetooth_bluedroid-b930299a8ad32a8227b00e0d9016b62682b577f3.zip external_bluetooth_bluedroid-b930299a8ad32a8227b00e0d9016b62682b577f3.tar.gz external_bluetooth_bluedroid-b930299a8ad32a8227b00e0d9016b62682b577f3.tar.bz2 |
Manage a2dp frame distribution when rate doesn't scale with media tick
Added back original frame rate calculation used to manage sending
6.89 frames every 20 ms tick. Removed unused rate adjustment logic
Blacklist Porsche carkit out of this change, ie keep old behavior.
Originally by Mattias Ganesh
bug 7302257 7394193 7267756
Change-Id: Id40fee2d52098a011d13ad3b70301003da675c72
-rw-r--r-- | btif/include/btif_media.h | 2 | ||||
-rwxr-xr-x | btif/src/btif_av.c | 1 | ||||
-rwxr-xr-x | btif/src/btif_media_task.c | 246 |
3 files changed, 74 insertions, 175 deletions
diff --git a/btif/include/btif_media.h b/btif/include/btif_media.h index ce7c0a1..eb4c2b4 100644 --- a/btif/include/btif_media.h +++ b/btif/include/btif_media.h @@ -243,4 +243,6 @@ void btif_a2dp_on_suspend(void); void btif_a2dp_on_suspended(tBTA_AV_SUSPEND *p_av); void btif_a2dp_set_tx_flush(BOOLEAN enable); +void btif_media_check_iop_exceptions(char *peer_bda); + #endif diff --git a/btif/src/btif_av.c b/btif/src/btif_av.c index d25fb61..af4830f 100755 --- a/btif/src/btif_av.c +++ b/btif/src/btif_av.c @@ -463,6 +463,7 @@ static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *p_data) switch (event) { case BTIF_SM_ENTER_EVT: + btif_media_check_iop_exceptions((char *)btif_av_cb.peer_bda.address); break; case BTIF_SM_EXIT_EVT: diff --git a/btif/src/btif_media_task.c b/btif/src/btif_media_task.c index 6975154..0e9dff3 100755 --- a/btif/src/btif_media_task.c +++ b/btif/src/btif_media_task.c @@ -119,14 +119,20 @@ enum { /* Media task tick in milliseconds */ #define BTIF_MEDIA_TIME_TICK (20 * BTIF_MEDIA_NUM_TICK) -/* Number of frames per media task tick */ -/* 7.5 frames/tick @ 20 ms tick */ -#define BTIF_MEDIA_FR_PER_TICKS_48 (7 * BTIF_MEDIA_NUM_TICK) -/* 6.89 frames/tick @ 20 ms tick */ +/* Number of frames per media task tick. + Configure value rounded up to closest integer and + adjust any deltas in btif_get_num_aa_frame */ + +/* 7.5 frames/tick @ 20 ms tick (every 2nd frame send one less) */ +#define BTIF_MEDIA_FR_PER_TICKS_48 (8 * BTIF_MEDIA_NUM_TICK) + +/* 6.89 frames/tick @ 20 ms tick (7 out of 64 frames send one less */ #define BTIF_MEDIA_FR_PER_TICKS_44_1 (7 * BTIF_MEDIA_NUM_TICK) + /* 5.0 frames/tick @ 20 ms tick */ #define BTIF_MEDIA_FR_PER_TICKS_32 (5 * BTIF_MEDIA_NUM_TICK) -/* 2.5 frames/tick @ 20 ms tick */ + +/* 2.5 frames/tick @ 20 ms tick (every 2nd frame send one less) */ #define BTIF_MEDIA_FR_PER_TICKS_16 (3 * BTIF_MEDIA_NUM_TICK) @@ -178,9 +184,6 @@ static UINT32 a2dp_media_task_stack[(A2DP_MEDIA_TASK_STACK_SIZE + 3) / 4]; /* fixme -- tune optimal value. For now set a large buffer capacity */ #define MAX_OUTPUT_BUFFER_QUEUE_SZ 12 -/* trigger rate adjustment if deviation is more than threshold */ -#define BTIF_RA_OFFSET_TRIGGER_US 3000 - //#define BTIF_MEDIA_VERBOSE_ENABLED #ifdef BTIF_MEDIA_VERBOSE_ENABLED @@ -208,19 +211,6 @@ typedef union tBTIF_AV_MEDIA_FEEDINGS_PCM_STATE pcm; } tBTIF_AV_MEDIA_FEEDINGS_STATE; - -/* pcm rate adjustment */ -typedef struct { - struct timespec time_start; /* offset used to calculate time elapsed */ - unsigned long long tx_pcmtime_us; /* track pcm time transmitted since stream start */ - - /* stats */ - int ra_adjust_cnt; /* tracks nbr of frame intervals adjusted */ - int ra_adjust_pcmtime; /* pcmtime adjusted each stats interval */ - - /* add latency tracker */ -} tBTIF_MEDIA_RA; - typedef struct { #if (BTA_AV_INCLUDED == TRUE) @@ -237,7 +227,7 @@ typedef struct void* av_sm_hdl; UINT8 a2dp_cmd_pending; /* we can have max one command pending */ BOOLEAN tx_flush; /* discards any outgoing data when true */ - tBTIF_MEDIA_RA ra; /* tx rate adjustment logic */ + BOOLEAN scaling_disabled; #endif } tBTIF_MEDIA_CB; @@ -985,132 +975,6 @@ static int btif_calc_pcmtime(UINT32 bytes_processed) return pcm_time_us; } -/***************************************************************************** -** -** Function ra_reset -** -** Description Media task tx rate adjustment -** -** Returns void -** -*******************************************************************************/ - -static void ra_reset(void) -{ - /* initialize start time of test interval */ - btif_media_cb.ra.time_start.tv_nsec = 0; - btif_media_cb.ra.time_start.tv_sec = 0; - btif_media_cb.ra.tx_pcmtime_us= 0; - btif_media_cb.ra.ra_adjust_cnt = 0; - btif_media_cb.ra.ra_adjust_pcmtime = 0; -} - -/***************************************************************************** -** -** Function ra_update -** -** Description Updates RA with amount of UIPC channel data processed -** -** Returns void -** -*******************************************************************************/ - -static void ra_update(UINT32 bytes_processed) -{ -#define RA_STATS_INTERVAL 3 - static unsigned long ra_stats_update = 0; - int pcmtime_equivalent; - - /* if this is the first frame we will initialize tx start time */ - if ( (btif_media_cb.ra.time_start.tv_sec == 0) && (btif_media_cb.ra.time_start.tv_nsec == 0) ) - clock_gettime(CLOCK_MONOTONIC, &btif_media_cb.ra.time_start); - - pcmtime_equivalent = btif_calc_pcmtime(bytes_processed); - btif_media_cb.ra.tx_pcmtime_us += pcmtime_equivalent; - - ra_stats_update += pcmtime_equivalent; - - /* converts adjusted frame count to adjusted pcmtime equivalent */ - btif_media_cb.ra.ra_adjust_pcmtime += (btif_media_cb.ra.ra_adjust_cnt)*pcmtime_equivalent; - - //VERBOSE("ra update %d %d %d", btif_media_cb.ra.ra_adjust_cnt, - // btif_media_cb.ra.ra_adjust_pcmtime, ra_stats_update); - - /* check pcmtime adjustments every stats interval */ - if (ra_stats_update > (RA_STATS_INTERVAL*1000000L)) - { - APPL_TRACE_DEBUG3("ra estimate : %d us for %d secs (%d ppm)", - btif_media_cb.ra.ra_adjust_pcmtime, RA_STATS_INTERVAL, - btif_media_cb.ra.ra_adjust_pcmtime/RA_STATS_INTERVAL); - btif_media_cb.ra.ra_adjust_pcmtime = 0; - ra_stats_update = 0; - - } - - /* reset count for next conversion */ - btif_media_cb.ra.ra_adjust_cnt = 0; -} - -/***************************************************************************** -** -** Function ra_adjust -** -** Description Calculates deviation between PCM time processed across -** UIPC audio channel and PCM time transmitted across the -** A2DP stream. Is checked every time slice (media timer -** tick). -** -** Returns Returns a frame count offset used to compensate for -** any drift versus the ideal clockrate -** -*******************************************************************************/ - -static int ra_adjust(void) -{ - unsigned long long time_elapsed_us; - struct timespec now; - int adjust = 0; - - /* don't start adjusting until we have read any pcm data */ - if (btif_media_cb.ra.tx_pcmtime_us == 0) - return 0; - - clock_gettime(CLOCK_MONOTONIC, &now); - - time_elapsed_us = ((unsigned long long)(now.tv_sec - btif_media_cb.ra.time_start.tv_sec))\ - * USEC_PER_SEC + (now.tv_nsec - btif_media_cb.ra.time_start.tv_nsec)/1000; - - /* compare elapsed time vs read pcm time */ - if (btif_media_cb.ra.tx_pcmtime_us > time_elapsed_us) - { - //VERBOSE("TOO FAST : %06d us", btif_media_cb.ra.tx_pcmtime_us - time_elapsed_us); - - if ((btif_media_cb.ra.tx_pcmtime_us - time_elapsed_us) > BTIF_RA_OFFSET_TRIGGER_US) - { - VERBOSE("RA : -1 FRAME (%06d us)", btif_media_cb.ra.tx_pcmtime_us - time_elapsed_us); - - /* adjust by sending one frame less this time slice */ - adjust--; - btif_media_cb.ra.ra_adjust_cnt--; - } - } - else if (btif_media_cb.ra.tx_pcmtime_us < time_elapsed_us) - { - //VERBOSE("TOO SLOW : %06d us", time_elapsed_us - btif_media_cb.ra.tx_pcmtime_us); - - if ((time_elapsed_us - btif_media_cb.ra.tx_pcmtime_us) > BTIF_RA_OFFSET_TRIGGER_US) - { - VERBOSE("RA : +1 FRAME (%06d us)", time_elapsed_us - btif_media_cb.ra.tx_pcmtime_us); - - /* adjust by sending one frame more this time slice */ - adjust++; - btif_media_cb.ra.ra_adjust_cnt++; - } - } - - return adjust; -} - /******************************************************************************* ** @@ -1860,11 +1724,6 @@ static void btif_media_task_feeding_state_reset(void) { /* By default, just clear the entire state */ memset(&btif_media_cb.media_feeding_state, 0, sizeof(btif_media_cb.media_feeding_state)); - - /* reset pcm time tracker */ - ra_reset(); - - } /******************************************************************************* ** @@ -1928,6 +1787,8 @@ static void btif_media_task_aa_stop_tx(void) ** Returns The number of media frames in this time slice ** *******************************************************************************/ + + static UINT8 btif_get_num_aa_frame(void) { UINT8 result=0; @@ -1938,35 +1799,46 @@ static UINT8 btif_get_num_aa_frame(void) switch (btif_media_cb.encoder.s16SamplingFreq) { case SBC_sf16000: - result = BTIF_MEDIA_FR_PER_TICKS_16; + if (!btif_media_cb.scaling_disabled && + (btif_media_cb.media_feeding_state.pcm.aa_frame_counter++ % 2) == 0) + { + result = BTIF_MEDIA_FR_PER_TICKS_16-1; + } + else + { + result = BTIF_MEDIA_FR_PER_TICKS_16; + } break; + case SBC_sf32000: result = BTIF_MEDIA_FR_PER_TICKS_32; break; + case SBC_sf48000: - result = BTIF_MEDIA_FR_PER_TICKS_48; + if (!btif_media_cb.scaling_disabled && + (btif_media_cb.media_feeding_state.pcm.aa_frame_counter++ % 2) == 0) + { + result = BTIF_MEDIA_FR_PER_TICKS_48-1; + } + else + { + result = BTIF_MEDIA_FR_PER_TICKS_48; + } break; + case SBC_sf44100: - result = BTIF_MEDIA_FR_PER_TICKS_44_1; + if (!btif_media_cb.scaling_disabled && + (btif_media_cb.media_feeding_state.pcm.aa_frame_counter++ % 64) < 7) + { + result = BTIF_MEDIA_FR_PER_TICKS_44_1-1; + } + else + { + result = BTIF_MEDIA_FR_PER_TICKS_44_1; + } break; } - /* Frames per tick should be selected to come as close as possible - to the ideal framecount. Any residue compared to ideal framecount - is compensated here. - - Although we can estimate the frames per tick using modula - counters using the rate adapter logic smoothes out the compensation - over time and tracks transmitted time vs elapsed time counted from the first - frame sent out. Hence regardless of the reason for the drift (gki timer - inaccuracies or media tick frame residues) the rate - adaptor will compensate as soon as we drift outside the configued - threshold - */ - - // TODO(BT) ra_adjust causes problem, need correction - // result += ra_adjust(); - VERBOSE("WRITE %d FRAMES", result); break; @@ -2093,9 +1965,6 @@ BOOLEAN btif_media_aa_read_feeding(tUIPC_CH_ID channel_id) /* Read Data from UIPC channel */ nb_byte_read = UIPC_Read(channel_id, &event, (UINT8 *)read_buffer, read_size); - /* update read 'pcmtime' */ - ra_update(nb_byte_read); - //tput_mon(TRUE, nb_byte_read, FALSE); if (nb_byte_read < read_size) @@ -2310,6 +2179,33 @@ static void btif_media_send_aa_frame(void) bta_av_ci_src_data_ready(BTA_AV_CHNL_AUDIO); } +/******************************************************************************* + ** + ** Function btif_media_check_iop_exceptions + ** + ** Description Perform any device specific iop changes + ** + ** Returns void + ** + *******************************************************************************/ + +void btif_media_check_iop_exceptions(char *peer_bda) +{ + /* disable rate scaling for pcm carkit */ + if ((peer_bda[0] == 0x00) && + (peer_bda[1] == 0x0E) && + (peer_bda[2] == 0x9F)) + { + BTIF_TRACE_WARNING0("detected pcm carkit, disable rate scaling"); + btif_media_cb.scaling_disabled = TRUE; + } + else + { + btif_media_cb.scaling_disabled = FALSE; + } +} + + #endif /* BTA_AV_INCLUDED == TRUE */ /******************************************************************************* |