diff --git a/hal/audio_hw.c b/hal/audio_hw.c index e63f12de..26088eb8 100644 --- a/hal/audio_hw.c +++ b/hal/audio_hw.c @@ -1980,12 +1980,23 @@ static char* out_get_parameters(const struct audio_stream *stream, const char *k static uint32_t out_get_latency(const struct audio_stream_out *stream) { struct stream_out *out = (struct stream_out *)stream; + uint32_t latency = 0; - if (is_offload_usecase(out->usecase)) - return COMPRESS_OFFLOAD_PLAYBACK_LATENCY; - - return (out->config.period_count * out->config.period_size * 1000) / + if (is_offload_usecase(out->usecase)) { + if (out->use_small_bufs == true) + latency = ((out->compr_config.fragments * + out->compr_config.fragment_size * 1000) / + (out->sample_rate * out->compr_config.codec->ch_in * + audio_bytes_per_sample(out->format))); + else + latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY; + } else { + latency = (out->config.period_count * out->config.period_size * 1000) / (out->config.rate); + } + + ALOGV("%s: Latency %d", latency); + return latency; } static int out_set_volume(struct audio_stream_out *stream, float left, @@ -2692,6 +2703,8 @@ static int adev_open_output_stream(struct audio_hw_device *dev, out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO; out->handle = handle; out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH; + out->non_blocking = 0; + out->use_small_bufs = false; /* Init use case and pcm_config */ if ((out->flags == AUDIO_OUTPUT_FLAG_DIRECT) && @@ -2826,6 +2839,15 @@ static int adev_open_output_stream(struct audio_hw_device *dev, if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING) out->non_blocking = 1; + if (config->offload_info.use_small_bufs) { + //this flag is set from framework only if its for PCM formats + //no need to check for PCM format again + out->non_blocking = 0; + out->use_small_bufs = true; + ALOGI("Keep write blocking for small buff: non_blockling %d", + out->non_blocking); + } + out->send_new_metadata = 1; out->offload_state = OFFLOAD_STATE_IDLE; out->playback_started = 0; diff --git a/hal/audio_hw.h b/hal/audio_hw.h index 7fc10172..ba24b6b7 100644 --- a/hal/audio_hw.h +++ b/hal/audio_hw.h @@ -199,6 +199,7 @@ struct stream_out { struct stream_app_type_cfg app_type_cfg; int non_blocking; + bool use_small_bufs; int playback_started; int offload_state; pthread_cond_t offload_cond; diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c index 675a3061..1c19a614 100644 --- a/hal/msm8974/platform.c +++ b/hal/msm8974/platform.c @@ -63,6 +63,8 @@ /* Used in calculating fragment size for pcm offload */ #define PCM_OFFLOAD_BUFFER_DURATION_FOR_AV 1000 /* 1 sec */ #define PCM_OFFLOAD_BUFFER_DURATION_FOR_AV_STREAMING 80 /* 80 millisecs */ +#define PCM_OFFLOAD_BUFFER_DURATION_FOR_SMALL_BUFFERS 20 /* 20 millisecs */ +#define PCM_OFFLOAD_BUFFER_DURATION_MAX 1200 /* 1200 millisecs */ /* MAX PCM fragment size cannot be increased further due * to flinger's cblk size of 1mb,and it has to be a multiple of @@ -2898,44 +2900,42 @@ uint32_t platform_get_compress_offload_buffer_size(audio_offload_info_t* info) uint32_t platform_get_pcm_offload_buffer_size(audio_offload_info_t* info) { - uint32_t fragment_size = MIN_PCM_OFFLOAD_FRAGMENT_SIZE; + uint32_t fragment_size = 0; uint32_t bits_per_sample = 16; + uint32_t pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION_FOR_SMALL_BUFFERS; if (info->format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD) { bits_per_sample = 32; } - if (!info->has_video) { - fragment_size = MAX_PCM_OFFLOAD_FRAGMENT_SIZE; - - } else if (info->has_video && info->is_streaming) { - fragment_size = (PCM_OFFLOAD_BUFFER_DURATION_FOR_AV_STREAMING - * info->sample_rate - * (bits_per_sample >> 3) - * popcount(info->channel_mask))/1000; - - } else if (info->has_video) { - fragment_size = (PCM_OFFLOAD_BUFFER_DURATION_FOR_AV - * info->sample_rate - * (bits_per_sample >> 3) - * popcount(info->channel_mask))/1000; + if (info->use_small_bufs) { + pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION_FOR_SMALL_BUFFERS; + } else { + if (!info->has_video) { + pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION_MAX; + } else if (info->has_video && info->is_streaming) { + pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION_FOR_AV_STREAMING; + } else if (info->has_video) { + pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION_FOR_AV; + } } - char value[PROPERTY_VALUE_MAX] = {0}; - if((property_get("audio.offload.pcm.buffer.size", value, "")) && - atoi(value)) { - fragment_size = atoi(value) * 1024; - ALOGV("Using buffer size from sys prop %d", fragment_size); - } + //duration is set to 20 ms worth of stereo data at 48Khz + //with 16 bit per sample, modify this when the channel + //configuration is different + fragment_size = (pcm_offload_time + * info->sample_rate + * (bits_per_sample >> 3) + * popcount(info->channel_mask))/1000; - fragment_size = ALIGN( fragment_size, 1024); + fragment_size = ALIGN (fragment_size, 1024); if(fragment_size < MIN_PCM_OFFLOAD_FRAGMENT_SIZE) fragment_size = MIN_PCM_OFFLOAD_FRAGMENT_SIZE; else if(fragment_size > MAX_PCM_OFFLOAD_FRAGMENT_SIZE) fragment_size = MAX_PCM_OFFLOAD_FRAGMENT_SIZE; - ALOGV("%s: fragment_size %d", __func__, fragment_size); + ALOGI("PCM offload Fragment size to %d bytes", fragment_size); return fragment_size; }