diff options
-rw-r--r-- | audio_a2dp_hw/audio_a2dp_hw.c | 12 | ||||
-rwxr-xr-x[-rw-r--r--] | btif/src/btif_core.c | 31 | ||||
-rwxr-xr-x[-rw-r--r--] | btif/src/btif_media_task.c | 95 | ||||
-rwxr-xr-x[-rw-r--r--] | gki/ulinux/gki_ulinux.c | 101 |
4 files changed, 161 insertions, 78 deletions
diff --git a/audio_a2dp_hw/audio_a2dp_hw.c b/audio_a2dp_hw/audio_a2dp_hw.c index 9f4b238..42e416e 100644 --- a/audio_a2dp_hw/audio_a2dp_hw.c +++ b/audio_a2dp_hw/audio_a2dp_hw.c @@ -494,7 +494,7 @@ static uint32_t out_get_sample_rate(const struct audio_stream *stream) { struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; - INFO("rate %d", out->cfg.rate); + DEBUG("rate %d", out->cfg.rate); return out->cfg.rate; } @@ -503,7 +503,7 @@ static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate) { struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; - INFO("out_set_sample_rate : %d", rate); + DEBUG("out_set_sample_rate : %d", rate); if (rate != AUDIO_STREAM_DEFAULT_RATE) { @@ -520,7 +520,7 @@ static size_t out_get_buffer_size(const struct audio_stream *stream) { struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; - INFO("buffer_size : %d", out->buffer_sz); + DEBUG("buffer_size : %d", out->buffer_sz); return out->buffer_sz; } @@ -529,7 +529,7 @@ static uint32_t out_get_channels(const struct audio_stream *stream) { struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; - INFO("channels 0x%x", out->cfg.channel_flags); + DEBUG("channels 0x%x", out->cfg.channel_flags); return out->cfg.channel_flags; } @@ -537,14 +537,14 @@ static uint32_t out_get_channels(const struct audio_stream *stream) static audio_format_t out_get_format(const struct audio_stream *stream) { struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; - INFO("format 0x%x", out->cfg.format); + DEBUG("format 0x%x", out->cfg.format); return out->cfg.format; } static int out_set_format(struct audio_stream *stream, audio_format_t format) { struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; - ALOGW("setting format not yet supported (0x%x)", format); + DEBUG("setting format not yet supported (0x%x)", format); return -ENOSYS; } diff --git a/btif/src/btif_core.c b/btif/src/btif_core.c index 29e493d..3440685 100644..100755 --- a/btif/src/btif_core.c +++ b/btif/src/btif_core.c @@ -342,17 +342,9 @@ static void btif_fetch_local_bdaddr(bt_bdaddr_t *local_addr) { char val[256]; uint8_t valid_bda = FALSE; + int val_size = 0; const uint8_t null_bdaddr[BD_ADDR_LEN] = {0,0,0,0,0,0}; - BTIF_TRACE_DEBUG1("Look for bdaddr storage path in prop %s", PROPERTY_BT_BDADDR_PATH); - int val_size = sizeof(val); - if(btif_config_get_str("Local", "Adapter", "Address", val, &val_size)) - { - str2bd(val, local_addr); - BTIF_TRACE_DEBUG1("local bdaddr from bt_config.xml is %s", val); - return; - } - /* Get local bdaddr storage path from property */ if (property_get(PROPERTY_BT_BDADDR_PATH, val, NULL)) { @@ -378,6 +370,18 @@ static void btif_fetch_local_bdaddr(bt_bdaddr_t *local_addr) } } + if(!valid_bda) + { + val_size = sizeof(val); + BTIF_TRACE_DEBUG1("Look for bdaddr storage path in prop %s", PROPERTY_BT_BDADDR_PATH); + if(btif_config_get_str("Local", "Adapter", "Address", val, &val_size)) + { + str2bd(val, local_addr); + BTIF_TRACE_DEBUG1("local bdaddr from bt_config.xml is %s", val); + return; + } + } + /* No factory BDADDR found. Look for previously generated random BDA */ if ((!valid_bda) && \ (property_get(PERSIST_BDADDR_PROPERTY, val, NULL))) @@ -416,6 +420,15 @@ static void btif_fetch_local_bdaddr(bt_bdaddr_t *local_addr) //save the bd address to config file bdstr_t bdstr; bd2str(local_addr, &bdstr); + val_size = sizeof(val); + if (btif_config_get_str("Local", "Adapter", "Address", val, &val_size)) + { + if (strcmp(bdstr, val) ==0) + { + // BDA is already present in the config file. + return; + } + } btif_config_set_str("Local", "Adapter", "Address", bdstr); btif_config_save(); } diff --git a/btif/src/btif_media_task.c b/btif/src/btif_media_task.c index 1b39137..6847696 100644..100755 --- a/btif/src/btif_media_task.c +++ b/btif/src/btif_media_task.c @@ -117,14 +117,17 @@ enum { #endif /* Media task tick in milliseconds */ -#define BTIF_MEDIA_TIME_TICK (40 * BTIF_MEDIA_NUM_TICK) +#define BTIF_MEDIA_TIME_TICK (20 * BTIF_MEDIA_NUM_TICK) /* Number of frames per media task tick */ -#define BTIF_MEDIA_FR_PER_TICKS_48 (15 * BTIF_MEDIA_NUM_TICK) -#define BTIF_MEDIA_FR_PER_TICKS_44_1_H (14 * BTIF_MEDIA_NUM_TICK) -#define BTIF_MEDIA_FR_PER_TICKS_44_1_L (13 * BTIF_MEDIA_NUM_TICK) -#define BTIF_MEDIA_FR_PER_TICKS_32 (10 * BTIF_MEDIA_NUM_TICK) -#define BTIF_MEDIA_FR_PER_TICKS_16 ( 5 * BTIF_MEDIA_NUM_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 */ +#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 */ +#define BTIF_MEDIA_FR_PER_TICKS_16 (3 * BTIF_MEDIA_NUM_TICK) /* buffer pool */ @@ -143,7 +146,8 @@ enum { #define BTIF_MEDIA_BITRATE_STEP 5 #endif -#define DEFAULT_SBC_BITRATE 220 +/* Middle quality quality setting @ 44.1 khz */ +#define DEFAULT_SBC_BITRATE 229 #ifndef A2DP_MEDIA_TASK_STACK_SIZE #define A2DP_MEDIA_TASK_STACK_SIZE 0x2000 /* In bytes */ @@ -234,11 +238,6 @@ typedef struct 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 */ - -#if ((defined(BTIF_MEDIA_OVERFEED_INCLUDED) && (BTIF_MEDIA_OVERFEED_INCLUDED == TRUE)) || \ - (defined(BTIF_MEDIA_UNDERFEED_INCLUDED) && (BTIF_MEDIA_UNDERFEED_INCLUDED == TRUE))) - UINT8 tx_counter; -#endif #endif } tBTIF_MEDIA_CB; @@ -1034,13 +1033,15 @@ static void ra_update(UINT32 bytes_processed) /* 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 adjust %d %d", btif_media_cb.ra.ra_adjust_cnt, btif_media_cb.ra.ra_adjust_pcmtime); + //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_EVENT2("ra estimate : %d us (%d ppm)", btif_media_cb.ra.ra_adjust_pcmtime, - btif_media_cb.ra.ra_adjust_pcmtime/RA_STATS_INTERVAL); + 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; @@ -1076,11 +1077,8 @@ static int ra_adjust(void) 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; - - VERBOSE("tx_pcmtime_us : %llu us, elapsed : %llu us", btif_media_cb.ra.tx_pcmtime_us, - time_elapsed_us); + 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) @@ -1250,7 +1248,7 @@ int btif_media_task(void *p) /* make sure no channels are restarted while shutting down */ media_task_running = MEDIA_TASK_STATE_SHUTTING_DOWN; - /* this calls blocks until uipc is fully closed */ + /* this calls blocks until uipc is fully closed */ UIPC_Close(UIPC_CH_ID_ALL); break; } @@ -1559,14 +1557,17 @@ static void btif_media_task_enc_init(BT_HDR *p_msg) btif_media_cb.encoder.u16BitRate = DEFAULT_SBC_BITRATE; /* Default transcoding is PCM to SBC, modified by feeding configuration */ btif_media_cb.TxTranscoding = BTIF_MEDIA_TRSCD_PCM_2_SBC; - btif_media_cb.TxAaMtuSize = ((BTIF_MEDIA_AA_BUF_SIZE - BTIF_MEDIA_AA_SBC_OFFSET - sizeof(BT_HDR)) + btif_media_cb.TxAaMtuSize = ((BTIF_MEDIA_AA_BUF_SIZE-BTIF_MEDIA_AA_SBC_OFFSET-sizeof(BT_HDR)) < pInitAudio->MtuSize) ? (BTIF_MEDIA_AA_BUF_SIZE - BTIF_MEDIA_AA_SBC_OFFSET - sizeof(BT_HDR)) : pInitAudio->MtuSize; - APPL_TRACE_DEBUG3("btif_media_task_enc_init busy %d, mtu %d, peer mtu %d", btif_media_cb.busy_level, btif_media_cb.TxAaMtuSize, pInitAudio->MtuSize); - APPL_TRACE_DEBUG6("btif_media_task_enc_init ch mode %d, nbsubd %d, nb blk %d, alloc method %d, bit rate %d, Smp freq %d", - btif_media_cb.encoder.s16ChannelMode, btif_media_cb.encoder.s16NumOfSubBands, btif_media_cb.encoder.s16NumOfBlocks, - btif_media_cb.encoder.s16AllocationMethod, btif_media_cb.encoder.u16BitRate, btif_media_cb.encoder.s16SamplingFreq); + APPL_TRACE_EVENT3("btif_media_task_enc_init busy %d, mtu %d, peer mtu %d", + btif_media_cb.busy_level, btif_media_cb.TxAaMtuSize, pInitAudio->MtuSize); + APPL_TRACE_EVENT6(" ch mode %d, subnd %d, nb blk %d, alloc %d, rate %d, freq %d", + btif_media_cb.encoder.s16ChannelMode, btif_media_cb.encoder.s16NumOfSubBands, + btif_media_cb.encoder.s16NumOfBlocks, + btif_media_cb.encoder.s16AllocationMethod, btif_media_cb.encoder.u16BitRate, + btif_media_cb.encoder.s16SamplingFreq); /* Reset entirely the SBC encoder */ SBC_Encoder_Init(&(btif_media_cb.encoder)); @@ -1885,11 +1886,6 @@ static void btif_media_task_aa_start_tx(void) btif_media_cb.is_tx_timer = TRUE; -#if ((defined(BTIF_MEDIA_OVERFEED_INCLUDED) && (BTIF_MEDIA_OVERFEED_INCLUDED == TRUE)) || \ - (defined(BTIF_MEDIA_UNDERFEED_INCLUDED) && (BTIF_MEDIA_UNDERFEED_INCLUDED == TRUE))) - btif_media_cb.tx_counter = 0; -#endif - /* Reset the media feeding state */ btif_media_task_feeding_state_reset(); @@ -1951,35 +1947,26 @@ static UINT8 btif_get_num_aa_frame(void) result = BTIF_MEDIA_FR_PER_TICKS_48; break; case SBC_sf44100: - if ((btif_media_cb.media_feeding_state.pcm.aa_frame_counter++ % 32) < 7) - { - result = BTIF_MEDIA_FR_PER_TICKS_44_1_L; - } - else - { - result = BTIF_MEDIA_FR_PER_TICKS_44_1_H; - } + 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 + */ + result += ra_adjust(); VERBOSE("WRITE %d FRAMES", result); - -#if ((defined(BTIF_MEDIA_OVERFEED_INCLUDED) && (BTIF_MEDIA_OVERFEED_INCLUDED == TRUE)) || \ - (defined(BTIF_MEDIA_UNDERFEED_INCLUDED) && (BTIF_MEDIA_UNDERFEED_INCLUDED == TRUE))) - btif_media_cb.tx_counter++; - if (btif_media_cb.tx_counter == 10) - { - btif_media_cb.tx_counter = 0; -#if defined(BTIF_MEDIA_OVERFEED_INCLUDED) && (BTIF_MEDIA_OVERFEED_INCLUDED == TRUE) - result++; -#endif -#if defined(BTIF_MEDIA_UNDERFEED_INCLUDED) && (BTIF_MEDIA_UNDERFEED_INCLUDED == TRUE) - result--; -#endif - } -#endif break; default: diff --git a/gki/ulinux/gki_ulinux.c b/gki/ulinux/gki_ulinux.c index fabaea1..e4e0323 100644..100755 --- a/gki/ulinux/gki_ulinux.c +++ b/gki/ulinux/gki_ulinux.c @@ -89,6 +89,9 @@ static int shutdown_timer = 0; #define GKI_SHUTDOWN_EVT APPL_EVT_7 #endif +#define __likely(cond) __builtin_expect(!!(cond), 1) +#define __unlikely(cond) __builtin_expect(!!(cond), 0) + /***************************************************************************** ** Local type definitions ******************************************************************************/ @@ -538,7 +541,7 @@ void GKI_shutdown(void) void gki_system_tick_start_stop_cback(BOOLEAN start) { tGKI_OS *p_os = &gki_cb.os; - volatile int *p_run_cond = &p_os->no_timer_suspend; + int *p_run_cond = &p_os->no_timer_suspend; static int wake_lock_count; if ( FALSE == start ) { @@ -584,24 +587,104 @@ void gki_system_tick_start_stop_cback(BOOLEAN start) ** one step, If your OS does it in one step, this function ** should be empty. *********************************************************************************/ - #ifdef NO_GKI_RUN_RETURN void* timer_thread(void *arg) { - struct timespec delay; + int timeout_ns=0; + struct timespec timeout; + struct timespec previous = {0,0}; + struct timespec current; int err; + int delta_ns; + int restart; + tGKI_OS *p_os = &gki_cb.os; + int *p_run_cond = &p_os->no_timer_suspend; + + /* Indicate that tick is just starting */ + restart = 1; while(!shutdown_timer) { - delay.tv_sec = LINUX_SEC / 1000; - delay.tv_nsec = 1000 * 1000 * (LINUX_SEC%1000); + /* If the timer has been stopped (no SW timer running) */ + if (*p_run_cond == GKI_TIMER_TICK_STOP_COND) + { + /* + * We will lock/wait on GKI_timer_mutex. + * This mutex will be unlocked when timer is re-started + */ + GKI_TRACE("GKI_run lock mutex"); + pthread_mutex_lock(&p_os->gki_timer_mutex); + + /* We are here because the mutex has been released by timer cback */ + /* Let's release it for future use */ + GKI_TRACE("GKI_run unlock mutex"); + pthread_mutex_unlock(&p_os->gki_timer_mutex); - /* [u]sleep can't be used because it uses SIGALRM */ + /* Indicate that tick is just starting */ + restart = 1; + } + + /* Get time */ + clock_gettime(CLOCK_MONOTONIC, ¤t); + + /* Check if tick was just restarted, indicating to the compiler that this is + * unlikely to happen (to help branch prediction) */ + if (__unlikely(restart)) + { + /* Clear the restart indication */ + restart = 0; - do { - err = nanosleep(&delay, &delay); - } while (err < 0 && errno ==EINTR); + timeout_ns = (GKI_TICKS_TO_MS(1) * 1000000); + } + else + { + /* Compute time elapsed since last sleep start */ + delta_ns = current.tv_nsec - previous.tv_nsec; + delta_ns += (current.tv_sec - previous.tv_sec) * 1000000000; + + /* Compute next timeout: + * timeout = (next theoretical expiration) - current time + * timeout = (previous time + timeout + delay) - current time + * timeout = timeout + delay - (current time - previous time) + * timeout += delay - delta */ + timeout_ns += (GKI_TICKS_TO_MS(1) * 1000000) - delta_ns; + } + /* Save the current time for next iteration */ + previous = current; + + timeout.tv_sec = 0; + + /* Sleep until next theoretical tick time. In case of excessive + elapsed time since last theoretical tick expiration, it is + possible that the timeout value is negative. To protect + against this error, we set minimum sleep time to 10% of the + tick period. We indicate to compiler that this is unlikely to + happen (to help branch prediction) */ + + if (__unlikely(timeout_ns < ((GKI_TICKS_TO_MS(1) * 1000000) * 0.1))) + { + timeout.tv_nsec = (GKI_TICKS_TO_MS(1) * 1000000) * 0.1; + + /* Print error message if tick really got delayed + (more than 5 ticks) */ + if (timeout_ns < GKI_TICKS_TO_MS(-5) * 1000000) + { + GKI_ERROR_LOG("tick delayed > 5 slots (%d,%d) -- cpu overload ? ", + timeout_ns, GKI_TICKS_TO_MS(-5) * 1000000); + } + } + else + { + timeout.tv_nsec = timeout_ns; + } + + do + { + /* [u]sleep can't be used because it uses SIGALRM */ + err = nanosleep(&timeout, &timeout); + } while (err < 0 && errno == EINTR); + /* Increment the GKI time value by one tick and update internal timers */ GKI_timer_update(1); } GKI_TRACE("gki_ulinux: Exiting timer_thread"); |