Loading hal/audio_extn/qaf.c +2 −2 Original line number Diff line number Diff line Loading @@ -952,10 +952,10 @@ static int qaf_get_rendered_frames(struct stream_out *out, uint64_t *frames) if (qaf_mod->stream_out[QAF_OUT_OFFLOAD]) platform_latency = platform_render_latency(qaf_mod->stream_out[QAF_OUT_OFFLOAD]->usecase); platform_render_latency(qaf_mod->stream_out[QAF_OUT_OFFLOAD]); else platform_latency = platform_render_latency(qaf_mod->stream_out[QAF_OUT_OFFLOAD_MCH]->usecase); platform_render_latency(qaf_mod->stream_out[QAF_OUT_OFFLOAD_MCH]); dsp_latency = (platform_latency * sample_rate) / 1000000LL; } else if (qaf_mod->stream_out[QAF_OUT_TRANSCODE_PASSTHROUGH] != NULL) { Loading hal/audio_extn/soundtrigger.c +29 −13 Original line number Diff line number Diff line Loading @@ -186,6 +186,8 @@ do {\ #define SVA_PARAM_CHANNEL_INDEX "st_channel_index" #define MAX_STR_LENGTH_FFV_PARAMS 30 #define MAX_FFV_SESSION_ID 100 #define ST_DEVICE SND_DEVICE_IN_HANDSET_MIC /* * Current proprietary API version used by AHAL. Queried by STHAL * for compatibility check with AHAL Loading Loading @@ -254,7 +256,8 @@ static int populate_usecase(struct audio_hal_usecase *usecase, break; case PCM_CAPTURE: if (uc_info->id == USECASE_AUDIO_RECORD_VOIP) if (uc_info->stream.in != NULL && uc_info->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) usecase->type = USECASE_TYPE_VOIP_CALL; else usecase->type = USECASE_TYPE_PCM_CAPTURE; Loading Loading @@ -474,14 +477,7 @@ void audio_extn_sound_trigger_check_and_get_session(struct stream_in *in) bool is_same_as_st_device(snd_device_t snd_device) { if (snd_device == SND_DEVICE_IN_HANDSET_MIC_AEC || snd_device == SND_DEVICE_IN_HANDSET_MIC || snd_device == SND_DEVICE_IN_HANDSET_MIC_AEC_NS || snd_device == SND_DEVICE_IN_SPEAKER_MIC || snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC || snd_device == SND_DEVICE_IN_SPEAKER_MIC_AEC || snd_device == SND_DEVICE_IN_SPEAKER_MIC_AEC_NS || snd_device == SND_DEVICE_IN_SPEAKER_MIC_NS) { if (platform_check_all_backends_match(ST_DEVICE, snd_device)) { ALOGD("audio HAL using same device %d as ST", snd_device); return true; } Loading Loading @@ -529,32 +525,52 @@ void audio_extn_sound_trigger_update_device_status(snd_device_t snd_device, { bool raise_event = false; int device_type = -1; struct audio_event_info ev_info; ev_info.u.usecase.type = -1; if (!st_dev) return; list_init(&ev_info.device_info.devices); if (snd_device >= SND_DEVICE_OUT_BEGIN && snd_device < SND_DEVICE_OUT_END) device_type = PCM_PLAYBACK; else if (snd_device >= SND_DEVICE_IN_BEGIN && snd_device < SND_DEVICE_IN_END) snd_device < SND_DEVICE_IN_END) { device_type = PCM_CAPTURE; else { if (is_same_as_st_device(snd_device)) update_device_list(&ev_info.device_info.devices, ST_DEVICE_HANDSET_MIC, "", true); } else { ALOGE("%s: invalid device 0x%x, for event %d", __func__, snd_device, event); return; } struct stream_in *active_input = adev_get_active_input(st_dev->adev); audio_source_t source = (active_input == NULL) ? AUDIO_SOURCE_DEFAULT : active_input->source; if (st_dev->adev->mode == AUDIO_MODE_IN_CALL) { ev_info.u.usecase.type = USECASE_TYPE_VOICE_CALL; } else if ((st_dev->adev->mode == AUDIO_MODE_IN_COMMUNICATION || source == AUDIO_SOURCE_VOICE_COMMUNICATION) && active_input) { ev_info.u.usecase.type = USECASE_TYPE_VOIP_CALL; } else if (device_type == PCM_CAPTURE) { ev_info.u.usecase.type = USECASE_TYPE_PCM_CAPTURE; } raise_event = platform_sound_trigger_device_needs_event(snd_device); ALOGI("%s: device 0x%x of type %d for Event %d, with Raise=%d", __func__, snd_device, device_type, event, raise_event); if (raise_event && (device_type == PCM_CAPTURE)) { switch(event) { case ST_EVENT_SND_DEVICE_FREE: st_dev->st_callback(AUDIO_EVENT_CAPTURE_DEVICE_INACTIVE, NULL); st_dev->st_callback(AUDIO_EVENT_CAPTURE_DEVICE_INACTIVE, &ev_info); break; case ST_EVENT_SND_DEVICE_BUSY: st_dev->st_callback(AUDIO_EVENT_CAPTURE_DEVICE_ACTIVE, NULL); st_dev->st_callback(AUDIO_EVENT_CAPTURE_DEVICE_ACTIVE, &ev_info); break; default: ALOGW("%s:invalid event %d for device 0x%x", Loading hal/audio_hw.c +14 −4 Original line number Diff line number Diff line Loading @@ -4297,8 +4297,10 @@ static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct ti /* This adjustment accounts for buffering after app processor. * It is based on estimated DSP latency per use case, rather than exact. */ int64_t platform_latency = platform_render_latency(out->usecase) * pthread_mutex_lock(&adev->lock); int64_t platform_latency = platform_render_latency(out->dev, out->usecase) * out->sample_rate / 1000000LL; pthread_mutex_unlock(&adev->lock); pthread_mutex_lock(&out->position_query_lock); /* not querying actual state of buffering in kernel as it would involve an ioctl call Loading Loading @@ -5250,7 +5252,9 @@ static uint32_t out_get_latency(const struct audio_stream_out *stream) 1000) / (out->config.rate); else period_ms = 0; latency = period_ms + platform_render_latency(out->usecase)/1000; pthread_mutex_lock(&adev->lock); latency = period_ms + platform_render_latency(out->dev, out->usecase)/1000; pthread_mutex_unlock(&adev->lock); } else { latency = (out->config.period_count * out->config.period_size * 1000) / (out->config.rate); Loading Loading @@ -6184,7 +6188,10 @@ static int out_get_presentation_position(const struct audio_stream_out *stream, // This adjustment accounts for buffering after app processor. // It is based on estimated DSP latency per use case, rather than exact. frames_temp = platform_render_latency(out->usecase) * out->sample_rate / 1000000LL; pthread_mutex_lock(&adev->lock); frames_temp = platform_render_latency(out->dev, out->usecase) * out->sample_rate / 1000000LL; pthread_mutex_unlock(&adev->lock); if (signed_frames >= frames_temp) signed_frames -= frames_temp; Loading Loading @@ -7081,7 +7088,10 @@ static int in_get_capture_position(const struct audio_stream_in *stream, unsigned int avail; if (pcm_get_htimestamp(in->pcm, &avail, ×tamp) == 0) { *frames = in->frames_read + avail; *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec; pthread_mutex_lock(&adev->lock); *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec - platform_capture_latency(in->dev, in->usecase) * 1000LL; pthread_mutex_unlock(&adev->lock); ret = 0; } } Loading hal/msm8916/platform.c +84 −7 Original line number Diff line number Diff line Loading @@ -1034,6 +1034,22 @@ static int msm_device_to_be_id_external_codec [][NO_COLS] = { #define ULL_PLATFORM_DELAY (6*1000LL) #define MMAP_PLATFORM_DELAY (3*1000LL) static int audio_source_delay_ms[AUDIO_SOURCE_CNT] = {0}; static struct name_to_index audio_source_index[AUDIO_SOURCE_CNT] = { {TO_NAME_INDEX(AUDIO_SOURCE_DEFAULT)}, {TO_NAME_INDEX(AUDIO_SOURCE_MIC)}, {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_UPLINK)}, {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_DOWNLINK)}, {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_CALL)}, {TO_NAME_INDEX(AUDIO_SOURCE_CAMCORDER)}, {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_RECOGNITION)}, {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_COMMUNICATION)}, {TO_NAME_INDEX(AUDIO_SOURCE_REMOTE_SUBMIX)}, {TO_NAME_INDEX(AUDIO_SOURCE_UNPROCESSED)}, {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_PERFORMANCE)}, }; static const char *platform_get_mixer_control(struct mixer_ctl *); static void update_interface(const char *snd_card_name) { Loading Loading @@ -3215,6 +3231,11 @@ int platform_get_usecase_index(const char *usecase_name) return find_index(usecase_name_index, AUDIO_USECASE_MAX, usecase_name); } int platform_get_audio_source_index(const char *audio_source_name) { return find_index(audio_source_index, AUDIO_SOURCE_CNT, audio_source_name); } int platform_get_effect_config_data(snd_device_t snd_device, struct audio_effect_config *effect_config, effect_type_t effect_type) Loading Loading @@ -5767,24 +5788,80 @@ unsigned char* platform_get_license(void *platform __unused, int *size __unused) } void platform_set_snd_device_delay(snd_device_t snd_device __unused, int delay_ms __unused) { } void platform_set_audio_source_delay(audio_source_t audio_source, int delay_ms) { if ((audio_source < AUDIO_SOURCE_DEFAULT) || (audio_source > AUDIO_SOURCE_MAX)) { ALOGE("%s: Invalid audio_source = %d", __func__, audio_source); return; } audio_source_delay_ms[audio_source] = delay_ms; } /* Delay in Us */ int64_t platform_get_audio_source_delay(audio_source_t audio_source) { if ((audio_source < AUDIO_SOURCE_DEFAULT) || (audio_source > AUDIO_SOURCE_MAX)) { ALOGE("%s: Invalid audio_source = %d", __func__, audio_source); return 0; } return 1000LL * audio_source_delay_ms[audio_source]; } int64_t platform_capture_latency(struct audio_device *adev __unused, audio_usecase_t usecase) { } /* Delay in Us, only to be used for PCM formats */ int64_t platform_render_latency(audio_usecase_t usecase) int64_t platform_render_latency(struct audio_device *adev __unused, audio_usecase_t usecase) { int64_t delay = 0LL; switch (usecase) { case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER: return DEEP_BUFFER_PLATFORM_DELAY; delay = DEEP_BUFFER_PLATFORM_DELAY; break; case USECASE_AUDIO_PLAYBACK_LOW_LATENCY: return LOW_LATENCY_PLATFORM_DELAY; delay = LOW_LATENCY_PLATFORM_DELAY; break; case USECASE_AUDIO_PLAYBACK_OFFLOAD: case USECASE_AUDIO_PLAYBACK_OFFLOAD2: return PCM_OFFLOAD_PLATFORM_DELAY; delay = PCM_OFFLOAD_PLATFORM_DELAY; break; case USECASE_AUDIO_PLAYBACK_ULL: return ULL_PLATFORM_DELAY; delay = ULL_PLATFORM_DELAY; break; case USECASE_AUDIO_PLAYBACK_MMAP: return MMAP_PLATFORM_DELAY; delay = MMAP_PLATFORM_DELAY; break; default: return 0; break; } /* out->device could be used to add delay time if it's necessary */ return delay; } int64_t platform_capture_latency(struct stream_in *in) { int64_t delay = 0LL; if (!in) return delay; delay = platform_get_audio_source_delay(in->source); /* in->device could be used to add delay time if it's necessary */ return delay; } int platform_update_usecase_from_source(int source, int usecase) Loading hal/msm8974/platform.c +110 −7 Original line number Diff line number Diff line Loading @@ -1520,12 +1520,30 @@ static int msm_be_id_array_len = sizeof(msm_device_to_be_id) / sizeof(msm_device_to_be_id[0]); #endif static int snd_device_delay_ms[SND_DEVICE_MAX] = {0}; #define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL) #define PCM_OFFLOAD_PLATFORM_DELAY (30*1000LL) #define LOW_LATENCY_PLATFORM_DELAY (13*1000LL) #define ULL_PLATFORM_DELAY (3*1000LL) #define MMAP_PLATFORM_DELAY (3*1000LL) static int audio_source_delay_ms[AUDIO_SOURCE_CNT] = {0}; static struct name_to_index audio_source_index[AUDIO_SOURCE_CNT] = { {TO_NAME_INDEX(AUDIO_SOURCE_DEFAULT)}, {TO_NAME_INDEX(AUDIO_SOURCE_MIC)}, {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_UPLINK)}, {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_DOWNLINK)}, {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_CALL)}, {TO_NAME_INDEX(AUDIO_SOURCE_CAMCORDER)}, {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_RECOGNITION)}, {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_COMMUNICATION)}, {TO_NAME_INDEX(AUDIO_SOURCE_REMOTE_SUBMIX)}, {TO_NAME_INDEX(AUDIO_SOURCE_UNPROCESSED)}, {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_PERFORMANCE)}, }; static bool is_usb_snd_dev(snd_device_t snd_device) { if (snd_device < SND_DEVICE_IN_BEGIN) { Loading Loading @@ -2154,6 +2172,7 @@ static void set_platform_defaults(struct platform_data * my_data) hw_interface_table[dev] = NULL; operator_specific_device_table[dev] = NULL; external_specific_device_table[dev] = NULL; snd_device_delay_ms[dev] = 0; } for (dev = 0; dev < SND_DEVICE_MAX; dev++) { backend_bit_width_table[dev] = CODEC_BACKEND_DEFAULT_BIT_WIDTH; Loading Loading @@ -4647,6 +4666,11 @@ int platform_get_usecase_index(const char *usecase_name) return find_index(usecase_name_index, AUDIO_USECASE_MAX, usecase_name); } int platform_get_audio_source_index(const char *audio_source_name) { return find_index(audio_source_index, AUDIO_SOURCE_CNT, audio_source_name); } void platform_add_operator_specific_device(snd_device_t snd_device, const char *operator, const char *mixer_path, Loading Loading @@ -8602,31 +8626,110 @@ done: return NULL; } void platform_set_snd_device_delay(snd_device_t snd_device, int delay_ms) { if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) { ALOGE("%s: Invalid snd_device = %d", __func__, snd_device); return; } snd_device_delay_ms[snd_device] = delay_ms; } /* return delay in Us */ int64_t platform_get_snd_device_delay(snd_device_t snd_device) { if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) { ALOGE("%s: Invalid snd_device = %d", __func__, snd_device); return 0; } return 1000LL * (int64_t)snd_device_delay_ms[snd_device]; } void platform_set_audio_source_delay(audio_source_t audio_source, int delay_ms) { if ((audio_source < AUDIO_SOURCE_DEFAULT) || (audio_source > AUDIO_SOURCE_MAX)) { ALOGE("%s: Invalid audio_source = %d", __func__, audio_source); return; } audio_source_delay_ms[audio_source] = delay_ms; } /* Delay in Us */ int64_t platform_get_audio_source_delay(audio_source_t audio_source) { if ((audio_source < AUDIO_SOURCE_DEFAULT) || (audio_source > AUDIO_SOURCE_MAX)) { ALOGE("%s: Invalid audio_source = %d", __func__, audio_source); return 0; } return 1000LL * audio_source_delay_ms[audio_source]; } /* Delay in Us */ /* Delay in Us, only to be used for PCM formats */ int64_t platform_render_latency(audio_usecase_t usecase) int64_t platform_render_latency(struct audio_device *adev, audio_usecase_t usecase) { int64_t delay = 0LL; struct audio_usecase *uc_info; switch (usecase) { case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER: case USECASE_AUDIO_PLAYBACK_MEDIA: case USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE: case USECASE_AUDIO_PLAYBACK_REAR_SEAT: return DEEP_BUFFER_PLATFORM_DELAY; delay = DEEP_BUFFER_PLATFORM_DELAY; break; case USECASE_AUDIO_PLAYBACK_LOW_LATENCY: case USECASE_AUDIO_PLAYBACK_WITH_HAPTICS: case USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION: case USECASE_AUDIO_PLAYBACK_PHONE: return LOW_LATENCY_PLATFORM_DELAY; delay = LOW_LATENCY_PLATFORM_DELAY; break; case USECASE_AUDIO_PLAYBACK_OFFLOAD: case USECASE_AUDIO_PLAYBACK_OFFLOAD2: return PCM_OFFLOAD_PLATFORM_DELAY; delay = PCM_OFFLOAD_PLATFORM_DELAY; break; case USECASE_AUDIO_PLAYBACK_ULL: return ULL_PLATFORM_DELAY; delay = ULL_PLATFORM_DELAY; break; case USECASE_AUDIO_PLAYBACK_MMAP: return MMAP_PLATFORM_DELAY; delay = MMAP_PLATFORM_DELAY; break; default: return 0; break; } uc_info = get_usecase_from_list(adev, usecase); if (uc_info != NULL) { if (uc_info->type == PCM_PLAYBACK) delay += platform_get_snd_device_delay(uc_info->out_snd_device); else ALOGE("%s: Invalid uc_info->type %d", __func__, uc_info->type); } return delay; } int64_t platform_capture_latency(struct audio_device *adev, audio_usecase_t usecase) { int64_t delay = 0LL; struct audio_usecase *uc_info; uc_info = get_usecase_from_list(adev, usecase); if (uc_info != NULL) { if (uc_info->type == PCM_CAPTURE) delay += platform_get_snd_device_delay(uc_info->in_snd_device); else ALOGE("%s: Invalid uc_info->type %d", __func__, uc_info->type); } return delay; } int platform_update_usecase_from_source(int source, int usecase) Loading Loading
hal/audio_extn/qaf.c +2 −2 Original line number Diff line number Diff line Loading @@ -952,10 +952,10 @@ static int qaf_get_rendered_frames(struct stream_out *out, uint64_t *frames) if (qaf_mod->stream_out[QAF_OUT_OFFLOAD]) platform_latency = platform_render_latency(qaf_mod->stream_out[QAF_OUT_OFFLOAD]->usecase); platform_render_latency(qaf_mod->stream_out[QAF_OUT_OFFLOAD]); else platform_latency = platform_render_latency(qaf_mod->stream_out[QAF_OUT_OFFLOAD_MCH]->usecase); platform_render_latency(qaf_mod->stream_out[QAF_OUT_OFFLOAD_MCH]); dsp_latency = (platform_latency * sample_rate) / 1000000LL; } else if (qaf_mod->stream_out[QAF_OUT_TRANSCODE_PASSTHROUGH] != NULL) { Loading
hal/audio_extn/soundtrigger.c +29 −13 Original line number Diff line number Diff line Loading @@ -186,6 +186,8 @@ do {\ #define SVA_PARAM_CHANNEL_INDEX "st_channel_index" #define MAX_STR_LENGTH_FFV_PARAMS 30 #define MAX_FFV_SESSION_ID 100 #define ST_DEVICE SND_DEVICE_IN_HANDSET_MIC /* * Current proprietary API version used by AHAL. Queried by STHAL * for compatibility check with AHAL Loading Loading @@ -254,7 +256,8 @@ static int populate_usecase(struct audio_hal_usecase *usecase, break; case PCM_CAPTURE: if (uc_info->id == USECASE_AUDIO_RECORD_VOIP) if (uc_info->stream.in != NULL && uc_info->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) usecase->type = USECASE_TYPE_VOIP_CALL; else usecase->type = USECASE_TYPE_PCM_CAPTURE; Loading Loading @@ -474,14 +477,7 @@ void audio_extn_sound_trigger_check_and_get_session(struct stream_in *in) bool is_same_as_st_device(snd_device_t snd_device) { if (snd_device == SND_DEVICE_IN_HANDSET_MIC_AEC || snd_device == SND_DEVICE_IN_HANDSET_MIC || snd_device == SND_DEVICE_IN_HANDSET_MIC_AEC_NS || snd_device == SND_DEVICE_IN_SPEAKER_MIC || snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC || snd_device == SND_DEVICE_IN_SPEAKER_MIC_AEC || snd_device == SND_DEVICE_IN_SPEAKER_MIC_AEC_NS || snd_device == SND_DEVICE_IN_SPEAKER_MIC_NS) { if (platform_check_all_backends_match(ST_DEVICE, snd_device)) { ALOGD("audio HAL using same device %d as ST", snd_device); return true; } Loading Loading @@ -529,32 +525,52 @@ void audio_extn_sound_trigger_update_device_status(snd_device_t snd_device, { bool raise_event = false; int device_type = -1; struct audio_event_info ev_info; ev_info.u.usecase.type = -1; if (!st_dev) return; list_init(&ev_info.device_info.devices); if (snd_device >= SND_DEVICE_OUT_BEGIN && snd_device < SND_DEVICE_OUT_END) device_type = PCM_PLAYBACK; else if (snd_device >= SND_DEVICE_IN_BEGIN && snd_device < SND_DEVICE_IN_END) snd_device < SND_DEVICE_IN_END) { device_type = PCM_CAPTURE; else { if (is_same_as_st_device(snd_device)) update_device_list(&ev_info.device_info.devices, ST_DEVICE_HANDSET_MIC, "", true); } else { ALOGE("%s: invalid device 0x%x, for event %d", __func__, snd_device, event); return; } struct stream_in *active_input = adev_get_active_input(st_dev->adev); audio_source_t source = (active_input == NULL) ? AUDIO_SOURCE_DEFAULT : active_input->source; if (st_dev->adev->mode == AUDIO_MODE_IN_CALL) { ev_info.u.usecase.type = USECASE_TYPE_VOICE_CALL; } else if ((st_dev->adev->mode == AUDIO_MODE_IN_COMMUNICATION || source == AUDIO_SOURCE_VOICE_COMMUNICATION) && active_input) { ev_info.u.usecase.type = USECASE_TYPE_VOIP_CALL; } else if (device_type == PCM_CAPTURE) { ev_info.u.usecase.type = USECASE_TYPE_PCM_CAPTURE; } raise_event = platform_sound_trigger_device_needs_event(snd_device); ALOGI("%s: device 0x%x of type %d for Event %d, with Raise=%d", __func__, snd_device, device_type, event, raise_event); if (raise_event && (device_type == PCM_CAPTURE)) { switch(event) { case ST_EVENT_SND_DEVICE_FREE: st_dev->st_callback(AUDIO_EVENT_CAPTURE_DEVICE_INACTIVE, NULL); st_dev->st_callback(AUDIO_EVENT_CAPTURE_DEVICE_INACTIVE, &ev_info); break; case ST_EVENT_SND_DEVICE_BUSY: st_dev->st_callback(AUDIO_EVENT_CAPTURE_DEVICE_ACTIVE, NULL); st_dev->st_callback(AUDIO_EVENT_CAPTURE_DEVICE_ACTIVE, &ev_info); break; default: ALOGW("%s:invalid event %d for device 0x%x", Loading
hal/audio_hw.c +14 −4 Original line number Diff line number Diff line Loading @@ -4297,8 +4297,10 @@ static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct ti /* This adjustment accounts for buffering after app processor. * It is based on estimated DSP latency per use case, rather than exact. */ int64_t platform_latency = platform_render_latency(out->usecase) * pthread_mutex_lock(&adev->lock); int64_t platform_latency = platform_render_latency(out->dev, out->usecase) * out->sample_rate / 1000000LL; pthread_mutex_unlock(&adev->lock); pthread_mutex_lock(&out->position_query_lock); /* not querying actual state of buffering in kernel as it would involve an ioctl call Loading Loading @@ -5250,7 +5252,9 @@ static uint32_t out_get_latency(const struct audio_stream_out *stream) 1000) / (out->config.rate); else period_ms = 0; latency = period_ms + platform_render_latency(out->usecase)/1000; pthread_mutex_lock(&adev->lock); latency = period_ms + platform_render_latency(out->dev, out->usecase)/1000; pthread_mutex_unlock(&adev->lock); } else { latency = (out->config.period_count * out->config.period_size * 1000) / (out->config.rate); Loading Loading @@ -6184,7 +6188,10 @@ static int out_get_presentation_position(const struct audio_stream_out *stream, // This adjustment accounts for buffering after app processor. // It is based on estimated DSP latency per use case, rather than exact. frames_temp = platform_render_latency(out->usecase) * out->sample_rate / 1000000LL; pthread_mutex_lock(&adev->lock); frames_temp = platform_render_latency(out->dev, out->usecase) * out->sample_rate / 1000000LL; pthread_mutex_unlock(&adev->lock); if (signed_frames >= frames_temp) signed_frames -= frames_temp; Loading Loading @@ -7081,7 +7088,10 @@ static int in_get_capture_position(const struct audio_stream_in *stream, unsigned int avail; if (pcm_get_htimestamp(in->pcm, &avail, ×tamp) == 0) { *frames = in->frames_read + avail; *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec; pthread_mutex_lock(&adev->lock); *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec - platform_capture_latency(in->dev, in->usecase) * 1000LL; pthread_mutex_unlock(&adev->lock); ret = 0; } } Loading
hal/msm8916/platform.c +84 −7 Original line number Diff line number Diff line Loading @@ -1034,6 +1034,22 @@ static int msm_device_to_be_id_external_codec [][NO_COLS] = { #define ULL_PLATFORM_DELAY (6*1000LL) #define MMAP_PLATFORM_DELAY (3*1000LL) static int audio_source_delay_ms[AUDIO_SOURCE_CNT] = {0}; static struct name_to_index audio_source_index[AUDIO_SOURCE_CNT] = { {TO_NAME_INDEX(AUDIO_SOURCE_DEFAULT)}, {TO_NAME_INDEX(AUDIO_SOURCE_MIC)}, {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_UPLINK)}, {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_DOWNLINK)}, {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_CALL)}, {TO_NAME_INDEX(AUDIO_SOURCE_CAMCORDER)}, {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_RECOGNITION)}, {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_COMMUNICATION)}, {TO_NAME_INDEX(AUDIO_SOURCE_REMOTE_SUBMIX)}, {TO_NAME_INDEX(AUDIO_SOURCE_UNPROCESSED)}, {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_PERFORMANCE)}, }; static const char *platform_get_mixer_control(struct mixer_ctl *); static void update_interface(const char *snd_card_name) { Loading Loading @@ -3215,6 +3231,11 @@ int platform_get_usecase_index(const char *usecase_name) return find_index(usecase_name_index, AUDIO_USECASE_MAX, usecase_name); } int platform_get_audio_source_index(const char *audio_source_name) { return find_index(audio_source_index, AUDIO_SOURCE_CNT, audio_source_name); } int platform_get_effect_config_data(snd_device_t snd_device, struct audio_effect_config *effect_config, effect_type_t effect_type) Loading Loading @@ -5767,24 +5788,80 @@ unsigned char* platform_get_license(void *platform __unused, int *size __unused) } void platform_set_snd_device_delay(snd_device_t snd_device __unused, int delay_ms __unused) { } void platform_set_audio_source_delay(audio_source_t audio_source, int delay_ms) { if ((audio_source < AUDIO_SOURCE_DEFAULT) || (audio_source > AUDIO_SOURCE_MAX)) { ALOGE("%s: Invalid audio_source = %d", __func__, audio_source); return; } audio_source_delay_ms[audio_source] = delay_ms; } /* Delay in Us */ int64_t platform_get_audio_source_delay(audio_source_t audio_source) { if ((audio_source < AUDIO_SOURCE_DEFAULT) || (audio_source > AUDIO_SOURCE_MAX)) { ALOGE("%s: Invalid audio_source = %d", __func__, audio_source); return 0; } return 1000LL * audio_source_delay_ms[audio_source]; } int64_t platform_capture_latency(struct audio_device *adev __unused, audio_usecase_t usecase) { } /* Delay in Us, only to be used for PCM formats */ int64_t platform_render_latency(audio_usecase_t usecase) int64_t platform_render_latency(struct audio_device *adev __unused, audio_usecase_t usecase) { int64_t delay = 0LL; switch (usecase) { case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER: return DEEP_BUFFER_PLATFORM_DELAY; delay = DEEP_BUFFER_PLATFORM_DELAY; break; case USECASE_AUDIO_PLAYBACK_LOW_LATENCY: return LOW_LATENCY_PLATFORM_DELAY; delay = LOW_LATENCY_PLATFORM_DELAY; break; case USECASE_AUDIO_PLAYBACK_OFFLOAD: case USECASE_AUDIO_PLAYBACK_OFFLOAD2: return PCM_OFFLOAD_PLATFORM_DELAY; delay = PCM_OFFLOAD_PLATFORM_DELAY; break; case USECASE_AUDIO_PLAYBACK_ULL: return ULL_PLATFORM_DELAY; delay = ULL_PLATFORM_DELAY; break; case USECASE_AUDIO_PLAYBACK_MMAP: return MMAP_PLATFORM_DELAY; delay = MMAP_PLATFORM_DELAY; break; default: return 0; break; } /* out->device could be used to add delay time if it's necessary */ return delay; } int64_t platform_capture_latency(struct stream_in *in) { int64_t delay = 0LL; if (!in) return delay; delay = platform_get_audio_source_delay(in->source); /* in->device could be used to add delay time if it's necessary */ return delay; } int platform_update_usecase_from_source(int source, int usecase) Loading
hal/msm8974/platform.c +110 −7 Original line number Diff line number Diff line Loading @@ -1520,12 +1520,30 @@ static int msm_be_id_array_len = sizeof(msm_device_to_be_id) / sizeof(msm_device_to_be_id[0]); #endif static int snd_device_delay_ms[SND_DEVICE_MAX] = {0}; #define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL) #define PCM_OFFLOAD_PLATFORM_DELAY (30*1000LL) #define LOW_LATENCY_PLATFORM_DELAY (13*1000LL) #define ULL_PLATFORM_DELAY (3*1000LL) #define MMAP_PLATFORM_DELAY (3*1000LL) static int audio_source_delay_ms[AUDIO_SOURCE_CNT] = {0}; static struct name_to_index audio_source_index[AUDIO_SOURCE_CNT] = { {TO_NAME_INDEX(AUDIO_SOURCE_DEFAULT)}, {TO_NAME_INDEX(AUDIO_SOURCE_MIC)}, {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_UPLINK)}, {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_DOWNLINK)}, {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_CALL)}, {TO_NAME_INDEX(AUDIO_SOURCE_CAMCORDER)}, {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_RECOGNITION)}, {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_COMMUNICATION)}, {TO_NAME_INDEX(AUDIO_SOURCE_REMOTE_SUBMIX)}, {TO_NAME_INDEX(AUDIO_SOURCE_UNPROCESSED)}, {TO_NAME_INDEX(AUDIO_SOURCE_VOICE_PERFORMANCE)}, }; static bool is_usb_snd_dev(snd_device_t snd_device) { if (snd_device < SND_DEVICE_IN_BEGIN) { Loading Loading @@ -2154,6 +2172,7 @@ static void set_platform_defaults(struct platform_data * my_data) hw_interface_table[dev] = NULL; operator_specific_device_table[dev] = NULL; external_specific_device_table[dev] = NULL; snd_device_delay_ms[dev] = 0; } for (dev = 0; dev < SND_DEVICE_MAX; dev++) { backend_bit_width_table[dev] = CODEC_BACKEND_DEFAULT_BIT_WIDTH; Loading Loading @@ -4647,6 +4666,11 @@ int platform_get_usecase_index(const char *usecase_name) return find_index(usecase_name_index, AUDIO_USECASE_MAX, usecase_name); } int platform_get_audio_source_index(const char *audio_source_name) { return find_index(audio_source_index, AUDIO_SOURCE_CNT, audio_source_name); } void platform_add_operator_specific_device(snd_device_t snd_device, const char *operator, const char *mixer_path, Loading Loading @@ -8602,31 +8626,110 @@ done: return NULL; } void platform_set_snd_device_delay(snd_device_t snd_device, int delay_ms) { if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) { ALOGE("%s: Invalid snd_device = %d", __func__, snd_device); return; } snd_device_delay_ms[snd_device] = delay_ms; } /* return delay in Us */ int64_t platform_get_snd_device_delay(snd_device_t snd_device) { if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) { ALOGE("%s: Invalid snd_device = %d", __func__, snd_device); return 0; } return 1000LL * (int64_t)snd_device_delay_ms[snd_device]; } void platform_set_audio_source_delay(audio_source_t audio_source, int delay_ms) { if ((audio_source < AUDIO_SOURCE_DEFAULT) || (audio_source > AUDIO_SOURCE_MAX)) { ALOGE("%s: Invalid audio_source = %d", __func__, audio_source); return; } audio_source_delay_ms[audio_source] = delay_ms; } /* Delay in Us */ int64_t platform_get_audio_source_delay(audio_source_t audio_source) { if ((audio_source < AUDIO_SOURCE_DEFAULT) || (audio_source > AUDIO_SOURCE_MAX)) { ALOGE("%s: Invalid audio_source = %d", __func__, audio_source); return 0; } return 1000LL * audio_source_delay_ms[audio_source]; } /* Delay in Us */ /* Delay in Us, only to be used for PCM formats */ int64_t platform_render_latency(audio_usecase_t usecase) int64_t platform_render_latency(struct audio_device *adev, audio_usecase_t usecase) { int64_t delay = 0LL; struct audio_usecase *uc_info; switch (usecase) { case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER: case USECASE_AUDIO_PLAYBACK_MEDIA: case USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE: case USECASE_AUDIO_PLAYBACK_REAR_SEAT: return DEEP_BUFFER_PLATFORM_DELAY; delay = DEEP_BUFFER_PLATFORM_DELAY; break; case USECASE_AUDIO_PLAYBACK_LOW_LATENCY: case USECASE_AUDIO_PLAYBACK_WITH_HAPTICS: case USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION: case USECASE_AUDIO_PLAYBACK_PHONE: return LOW_LATENCY_PLATFORM_DELAY; delay = LOW_LATENCY_PLATFORM_DELAY; break; case USECASE_AUDIO_PLAYBACK_OFFLOAD: case USECASE_AUDIO_PLAYBACK_OFFLOAD2: return PCM_OFFLOAD_PLATFORM_DELAY; delay = PCM_OFFLOAD_PLATFORM_DELAY; break; case USECASE_AUDIO_PLAYBACK_ULL: return ULL_PLATFORM_DELAY; delay = ULL_PLATFORM_DELAY; break; case USECASE_AUDIO_PLAYBACK_MMAP: return MMAP_PLATFORM_DELAY; delay = MMAP_PLATFORM_DELAY; break; default: return 0; break; } uc_info = get_usecase_from_list(adev, usecase); if (uc_info != NULL) { if (uc_info->type == PCM_PLAYBACK) delay += platform_get_snd_device_delay(uc_info->out_snd_device); else ALOGE("%s: Invalid uc_info->type %d", __func__, uc_info->type); } return delay; } int64_t platform_capture_latency(struct audio_device *adev, audio_usecase_t usecase) { int64_t delay = 0LL; struct audio_usecase *uc_info; uc_info = get_usecase_from_list(adev, usecase); if (uc_info != NULL) { if (uc_info->type == PCM_CAPTURE) delay += platform_get_snd_device_delay(uc_info->in_snd_device); else ALOGE("%s: Invalid uc_info->type %d", __func__, uc_info->type); } return delay; } int platform_update_usecase_from_source(int source, int usecase) Loading