From 11ee3ea7d80c541bfeb9f7fe71d41e5bde507001 Mon Sep 17 00:00:00 2001 From: SungHwan Yu Date: Thu, 4 Jan 2024 10:54:55 +0900 Subject: [PATCH] audio: add data handle process when pcm unstandby PD#OTT-52950 Problem: AUDIO-MEDIAVOL-HEAAC-TC3 wavform is not perfect Solution: add data handle process when pcm unstandby Verify: S905X2 Change-Id: I52e44f7e5bb7020c238a68151534e89602526414 Signed-off-by: zeming.huang --- audio/audio_hal/audio_hw.c | 14 +++ audio/audio_hal/audio_hw.h | 17 ++++ audio/audio_hal/audio_hw_utils.c | 140 +++++++++++++++++++++++++++ audio/audio_hal/audio_hw_utils.h | 2 + audio/audio_hal/sub_mixing_factory.c | 7 ++ 5 files changed, 180 insertions(+) diff --git a/audio/audio_hal/audio_hw.c b/audio/audio_hal/audio_hw.c index 649bc46..f31b268 100755 --- a/audio/audio_hal/audio_hw.c +++ b/audio/audio_hal/audio_hw.c @@ -10272,6 +10272,13 @@ int adev_open_output_stream_new(struct audio_hw_device *dev, adev->active_outputs[aml_out->usecase] = aml_out; pthread_mutex_unlock(&adev->lock); + /* init ease for stream */ + if (aml_audio_ease_init(&aml_out->audio_stream_ease) < 0) { + ALOGE("%s aml_audio_ease_init failed\n", __func__); + ret = -EINVAL; + goto AUDIO_EASE_INIT_FAIL; + } + if (aml_getprop_bool("vendor.media.audio.hal.debug")) { aml_out->debug_stream = 1; } @@ -10279,6 +10286,10 @@ int adev_open_output_stream_new(struct audio_hw_device *dev, aml_out, usecase2Str(aml_out->usecase), aml_out->card, aml_out->device); return 0; + +AUDIO_EASE_INIT_FAIL: + adev_close_output_stream(dev, *stream_out); + return ret; } void adev_close_output_stream_new(struct audio_hw_device *dev, @@ -10291,6 +10302,9 @@ void adev_close_output_stream_new(struct audio_hw_device *dev, /* call legacy close to reuse codes */ adev->active_outputs[aml_out->usecase] = NULL; + /* free stream ease resource */ + aml_audio_ease_close(aml_out->audio_stream_ease); + if (adev->useSubMix) { if (aml_out->is_normal_pcm || aml_out->usecase == STREAM_PCM_HWSYNC || diff --git a/audio/audio_hal/audio_hw.h b/audio/audio_hal/audio_hw.h index b7be540..dcb882d 100755 --- a/audio/audio_hal/audio_hw.h +++ b/audio/audio_hal/audio_hw.h @@ -581,6 +581,19 @@ typedef union output_info { } output_info_t; +typedef enum audio_data_handle_state { + AUDIO_DATA_HANDLE_NONE = 0, + AUDIO_DATA_HANDLE_START, + AUDIO_DATA_HANDLE_DETECT, + AUDIO_DATA_HANDLE_DETECTED, + AUDIO_DATA_HANDLE_EASE_CONFIG, + AUDIO_DATA_HANDLE_EASING, + AUDIO_DATA_HANDLE_FINISHED, + + AUDIO_DATA_HANDLE_MAX +} audio_data_handle_state_t; + + struct aml_stream_out { struct audio_stream_out stream; /* see note below on mutex acquisition order */ @@ -711,6 +724,10 @@ struct aml_stream_out { int dtvsync_enable; bool is_ms12_main_decoder; pthread_mutex_t apts_update_lock; /*SWPL-88828: Make sure audio timestamps and frame positions are updated synchronously.*/ + + aml_audio_ease_t *audio_stream_ease; + audio_data_handle_state_t audio_data_handle_state; + uint16_t easing_time; }; typedef ssize_t (*write_func)(struct audio_stream_out *stream, const void *buffer, size_t bytes); diff --git a/audio/audio_hal/audio_hw_utils.c b/audio/audio_hal/audio_hw_utils.c index ab66578..718fe1c 100755 --- a/audio/audio_hal/audio_hw_utils.c +++ b/audio/audio_hal/audio_hw_utils.c @@ -48,6 +48,7 @@ #include "a2dp_hal.h" #include "aml_audio_avsync_table.h" #include "dolby_lib_api.h" +#include #ifdef LOG_NDEBUG_FUNCTION #define LOGFUNC(...) ((void)0) @@ -1458,3 +1459,142 @@ void UpdateDecodeInfo_ChannelConfiguration(char *sysfs_buf, int ch_num) { } } +/***************************************************************************** +* Function Name: aml_audio_data_detect +* Description: accumulate buf in bytes, then compare with detect_value. +* the purpose is to detect value of buf that is zero or not. +* Parameters: int16_t *: the audio data buffer. +* size_t bytes: the buffer length. +* int: for compared value. +* Return value: true if buf value is zero, or false. +******************************************************************************/ +bool aml_audio_data_detect(int16_t *buf, size_t bytes, int detect_value) +{ + int ret = false; + uint64_t buf_value = 0; + uint32_t i = 0; + int8_t *temp_buf = (int8_t *)buf; + + while (i < bytes) { + buf_value += abs(temp_buf[i++]); + }; + + ALOGV("%s bytes:%zu i:%u buf_value:%" PRIu64 " sizeof(uint64_t):%zu sizeof(size_t):%zu", __func__, + bytes, i, buf_value, sizeof(uint64_t), sizeof(size_t)); + if (buf_value <= detect_value) { + ret = true; + } else { + ret = false; + } + + return ret; +} + +static int mixer_aux_start_ease_in(struct aml_stream_out *aml_out) { + /*start ease in the audio*/ + ease_setting_t ease_setting; + aml_out->audio_stream_ease->data_format.format = aml_out->hal_format; + aml_out->audio_stream_ease->data_format.ch = aml_out->hal_ch; + aml_out->audio_stream_ease->data_format.sr = aml_out->hal_rate; + aml_out->audio_stream_ease->ease_type = EaseLinear; + ease_setting.duration = 40; + ease_setting.start_volume = 0.0; + ease_setting.target_volume = 1.0; + aml_audio_ease_config(aml_out->audio_stream_ease, &ease_setting); + + ALOGV("%s ", __func__); + return 0; +} + +/***************************************************************************** +* Function Name: aml_audio_data_handle +* Description: handle audio data before send to driver or decoder. +* the purpose is to detect and fade in. +* Parameters: struct audio_stream_out: audio output stream pointer. +* const void *: the buffer pointer. +* size_t: the buffer length. +* Return value: true if buf value is zero, or false. +******************************************************************************/ +int aml_audio_data_handle(struct audio_stream_out *stream, const void* buffer, size_t bytes) +{ +// 8ms audio data +#define DETECT_AUDIO_TIME_UNIT (8) +#define DETECT_AUDIO_DATA_UNIT (DETECT_AUDIO_TIME_UNIT * out->hal_frame_size * out->hal_rate / 1000) +/* value 2000 for filter noise data, +** this value is confirmed according logs. +*/ +#define AML_DETECT_VALUE (2000) + + struct aml_stream_out *out = (struct aml_stream_out *)stream; + struct aml_audio_device *adev = out->dev; + bool ret = false; + int unit_size = 0; + int detected_size = 0; + size_t remaining_size = bytes; + audio_data_handle_state_t data_handle_state = out->audio_data_handle_state; + + AM_LOGV("out_stream usecase:%d-->%s, hal_format:%#x hal_ch:%u --> hal_frame_size:%u, hal_rate:%u, DETECT_AUDIO_DATA_UNIT:%u, bytes:%zu", + out->usecase, usecase2Str(out->usecase), out->hal_format, out->hal_ch, out->hal_frame_size, out->hal_rate, DETECT_AUDIO_DATA_UNIT, bytes); + if ((data_handle_state == AUDIO_DATA_HANDLE_NONE) || (data_handle_state == AUDIO_DATA_HANDLE_MAX)) { + AM_LOGE("invalid audio_data_handle_state %d", data_handle_state); + return -1; + } + + while (out->audio_data_handle_state < AUDIO_DATA_HANDLE_FINISHED && remaining_size) { + AM_LOGD("remaining_size:%zu, out->audio_data_handle_status:%u", remaining_size, out->audio_data_handle_state); + switch (out->audio_data_handle_state) { + case AUDIO_DATA_HANDLE_START: + FALLTHROUGH_INTENDED; /* [[fallthrough]] */ + case AUDIO_DATA_HANDLE_DETECT: + out->audio_data_handle_state = AUDIO_DATA_HANDLE_DETECT; + while (remaining_size > 0) { + if (remaining_size > DETECT_AUDIO_DATA_UNIT) { + unit_size = DETECT_AUDIO_DATA_UNIT; + } else { + unit_size = remaining_size; + } + + ret = aml_audio_data_detect((int16_t *)((int8_t *)buffer + detected_size), unit_size , AML_DETECT_VALUE); + if (false == ret) { + out->audio_data_handle_state = AUDIO_DATA_HANDLE_DETECTED; + AM_LOGD("detected the nonzero data, remaining_size:%zu detected_size:%u", remaining_size, detected_size); + break; + } else { + // when ease_setting.duration = 0, aml_audio_ease_process will not do easing. + memset((int8_t *)buffer + detected_size, 0, unit_size); + } + + remaining_size -= unit_size; + detected_size += unit_size; + } + break; + // detect finished, then do fade in. + case AUDIO_DATA_HANDLE_DETECTED: + out->audio_data_handle_state = AUDIO_DATA_HANDLE_EASE_CONFIG; + break; + case AUDIO_DATA_HANDLE_EASE_CONFIG: + mixer_aux_start_ease_in(out); + out->easing_time = 0; + out->audio_data_handle_state = AUDIO_DATA_HANDLE_EASING; + break; + case AUDIO_DATA_HANDLE_EASING: + aml_audio_ease_process(out->audio_stream_ease, (void *)((uint8_t *)buffer + detected_size), remaining_size); + out->easing_time += remaining_size/(out->hal_frame_size * out->hal_rate / 1000); + AM_LOGD("easing_time:%u, audio_stream_ease->ease_time:%u", out->easing_time, out->audio_stream_ease->ease_time); + remaining_size = 0; + if (out->easing_time >= out->audio_stream_ease->ease_time) { + out->audio_data_handle_state = AUDIO_DATA_HANDLE_FINISHED; + } + break; + case AUDIO_DATA_HANDLE_FINISHED: + out->audio_data_handle_state = AUDIO_DATA_HANDLE_FINISHED; + AM_LOGD("handle finished"); + break; + default : + break; + }; + } + + return 0; +} + diff --git a/audio/audio_hal/audio_hw_utils.h b/audio/audio_hal/audio_hw_utils.h index ffe88ed..01939ab 100755 --- a/audio/audio_hal/audio_hw_utils.h +++ b/audio/audio_hal/audio_hw_utils.h @@ -156,4 +156,6 @@ void UpdateDecodedInfo_SampleRate_ChannelNum_ChannelConfiguration(int samplerate void UpdateDecodeInfo_ChannelConfiguration(char *sysfs_buf, int ch_num); +int aml_audio_data_handle(struct audio_stream_out *stream, const void* buffer, size_t bytes); + #endif diff --git a/audio/audio_hal/sub_mixing_factory.c b/audio/audio_hal/sub_mixing_factory.c index f998586..6c55e9e 100755 --- a/audio/audio_hal/sub_mixing_factory.c +++ b/audio/audio_hal/sub_mixing_factory.c @@ -150,6 +150,10 @@ static ssize_t aml_out_write_to_mixer(struct audio_stream_out *stream, const voi uint32_t latency_frames = 0; struct timespec ts; + if (adev->is_netflix && (STREAM_PCM_NORMAL == out->usecase || STREAM_PCM_HWSYNC == out->usecase)) { + aml_audio_data_handle(stream, buffer, bytes); + } + do { ssize_t written = 0; ALOGV("%s(), stream usecase: %s, written_total %d, bytes %d", @@ -391,6 +395,7 @@ static ssize_t out_write_hwsync_lpcm(struct audio_stream_out *stream, const void get_input_port_type(&out->audioCfg, out->flags)); out->standby = false; mixer_set_continuous_output(sm->mixerData, false); + out->audio_data_handle_state = AUDIO_DATA_HANDLE_START; /*wait video ready*/ { int vframe_ready_cnt = 0; @@ -564,6 +569,7 @@ static ssize_t out_write_direct_pcm(struct audio_stream_out *stream, const void ALOGI("[%s:%d] direct port:%s", __func__, __LINE__, inportType2Str(get_input_port_type(&out->audioCfg, out->flags))); out->standby = false; + out->audio_data_handle_state = AUDIO_DATA_HANDLE_START; } clock_gettime(CLOCK_MONOTONIC, &tval); @@ -1195,6 +1201,7 @@ ssize_t mixer_aux_buffer_write_sm(struct audio_stream_out *stream, const void *b if (aml_out->out_device & AUDIO_DEVICE_OUT_ALL_A2DP) padding_bytes = 0; + aml_out->audio_data_handle_state = AUDIO_DATA_HANDLE_START; //set_thread_affinity(); init_mixer_input_port(sm->mixerData, &aml_out->audioCfg, aml_out->flags, on_notify_cbk, aml_out, on_input_avail_cbk, aml_out, -- 2.17.1