summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormillerliang <millerliang@google.com>2020-05-04 06:07:45 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2020-05-04 06:07:45 +0000
commit9ebc9fcbfca6925f9bacdecae4ec914a4f21726a (patch)
tree34b1dfec3e6125bdb671056f91b96f6fad28ca87
parent129fa9a43d0f51af0caa563aea00ce3735a4be29 (diff)
parent680f560798af7c170e29cd30b37c585117cdc26e (diff)
downloadaudio-9ebc9fcbfca6925f9bacdecae4ec914a4f21726a.tar.gz
hal: Fix AudioRecord and AudioTrack timestamps incorrect am: 680f560798
Change-Id: I1d8e8c53bfa0653457062f19bbe7f28f2442db33
-rw-r--r--hal/audio_hw.c7
-rw-r--r--hal/msm8916/platform.c101
-rw-r--r--hal/msm8960/platform.c101
-rw-r--r--hal/msm8974/platform.c107
-rw-r--r--hal/platform_api.h9
-rw-r--r--hal/platform_info.c71
6 files changed, 375 insertions, 21 deletions
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 1e3bb91..035b14e 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -3286,7 +3286,7 @@ static uint32_t out_get_latency(const struct audio_stream_out *stream)
// return a smaller number
period_ms = (out->af_period_multiplier * out->config.period_size *
1000) / (out->config.rate);
- hw_delay = platform_render_latency(out->usecase)/1000;
+ hw_delay = platform_render_latency(out)/1000;
return period_ms + hw_delay;
}
@@ -3770,7 +3770,7 @@ 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.
signed_frames -=
- (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
+ (platform_render_latency(out) * out->sample_rate / 1000000LL);
// Adjustment accounts for A2DP encoder latency with non-offload usecases
// Note: Encoder latency is returned in ms, while platform_render_latency in us.
@@ -4490,7 +4490,8 @@ static int in_get_capture_position(const struct audio_stream_in *stream,
unsigned int avail;
if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
*frames = in->frames_read + avail;
- *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
+ *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
+ - platform_capture_latency(in) * 1000LL;
ret = 0;
}
}
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 8600b7d..1a62ac3 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -554,6 +554,24 @@ static struct name_to_index usecase_name_index[AUDIO_USECASE_MAX] = {
#define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL)
#define LOW_LATENCY_PLATFORM_DELAY (13*1000LL)
+static int audio_usecase_delay_ms[AUDIO_USECASE_MAX] = {0};
+
+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 void query_platform(const char *snd_card_name,
char *mixer_xml_path)
{
@@ -1453,6 +1471,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)
@@ -2559,17 +2582,85 @@ done:
return ret;
}
+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];
+}
+
+void platform_set_audio_usecase_delay(audio_usecase_t usecase, int delay_ms)
+{
+ if ((usecase <= USECASE_INVALID) || (usecase >= AUDIO_USECASE_MAX)) {
+ ALOGE("%s: invalid usecase case idx %d", __func__, usecase);
+ return;
+ }
+
+ audio_usecase_delay_ms[usecase] = delay_ms;
+}
+
+/* Delay in Us */
+int64_t platform_get_audio_usecase_delay(audio_usecase_t usecase)
+{
+ if ((usecase <= USECASE_INVALID) || (usecase >= AUDIO_USECASE_MAX)) {
+ ALOGE("%s: invalid usecase case idx %d", __func__, usecase);
+ return 0;
+ }
+
+ return 1000LL * audio_usecase_delay_ms[usecase] ;
+}
+
/* Delay in Us */
-int64_t platform_render_latency(audio_usecase_t usecase)
+int64_t platform_render_latency(struct stream_out *out)
{
- switch (usecase) {
+ int64_t delay = 0LL;
+
+ if (!out)
+ return delay;
+
+ switch (out->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;
default:
- return 0;
+ break;
}
+
+/* out->usecase could be used to add delay time if it's necessary */
+ delay += platform_get_audio_usecase_delay(out->usecase);
+ 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_set_snd_device_backend(snd_device_t device, const char *backend, const char * hw_interface)
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index ae65ef2..6cc5411 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -226,6 +226,24 @@ static const int acdb_device_table[SND_DEVICE_MAX] = {
#define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL)
#define LOW_LATENCY_PLATFORM_DELAY (13*1000LL)
+static int audio_usecase_delay_ms[AUDIO_USECASE_MAX] = {0};
+
+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 pthread_once_t check_op_once_ctl = PTHREAD_ONCE_INIT;
static bool is_tmus = false;
@@ -1026,17 +1044,85 @@ int platform_set_parameters(void *platform __unused,
return -ENOSYS;
}
+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_render_latency(audio_usecase_t usecase)
+int64_t platform_get_audio_source_delay(audio_source_t audio_source)
{
- switch (usecase) {
+ 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];
+}
+
+void platform_set_audio_usecase_delay(audio_usecase_t usecase, int delay_ms)
+{
+ if ((usecase <= USECASE_INVALID) || (usecase >= AUDIO_USECASE_MAX)) {
+ ALOGE("%s: invalid usecase case idx %d", __func__, usecase);
+ return;
+ }
+
+ audio_usecase_delay_ms[usecase] = delay_ms;
+}
+
+/* Delay in Us */
+int64_t platform_get_audio_usecase_delay(audio_usecase_t usecase)
+{
+ if ((usecase <= USECASE_INVALID) || (usecase >= AUDIO_USECASE_MAX)) {
+ ALOGE("%s: invalid usecase case idx %d", __func__, usecase);
+ return 0;
+ }
+
+ return 1000LL * audio_usecase_delay_ms[usecase] ;
+}
+
+/* Delay in Us */
+int64_t platform_render_latency(struct stream_out *out)
+{
+ int64_t delay = 0LL;
+
+ if (!out)
+ return delay;
+
+ switch (out->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;
default:
- return 0;
+ break;
}
+
+/* out->usecase could be used to add delay time if it's necessary */
+ delay += platform_get_audio_usecase_delay(out->usecase);
+ 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_switch_voice_call_enable_device_config(void *platform __unused,
@@ -1063,6 +1149,11 @@ int platform_get_usecase_index(const char * usecase __unused)
return -ENOSYS;
}
+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_set_usecase_pcm_id(audio_usecase_t usecase __unused, int32_t type __unused,
int32_t pcm_id __unused)
{
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index d8ec06a..8fa9826 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -741,6 +741,24 @@ static struct listnode app_type_entry_list;
#define ULL_PLATFORM_DELAY (3*1000LL)
#define MMAP_PLATFORM_DELAY (3*1000LL)
+static int audio_usecase_delay_ms[AUDIO_USECASE_MAX] = {0};
+
+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 pthread_once_t check_op_once_ctl = PTHREAD_ONCE_INIT;
static bool is_tmus = false;
@@ -2254,6 +2272,11 @@ done:
return ret;
}
+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,
@@ -3828,22 +3851,92 @@ done:
return ret;
}
+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_render_latency(audio_usecase_t usecase)
+int64_t platform_get_audio_source_delay(audio_source_t audio_source)
{
- switch (usecase) {
+ 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];
+}
+
+void platform_set_audio_usecase_delay(audio_usecase_t usecase, int delay_ms)
+{
+ if ((usecase <= USECASE_INVALID) || (usecase >= AUDIO_USECASE_MAX)) {
+ ALOGE("%s: invalid usecase case idx %d", __func__, usecase);
+ return;
+ }
+
+ audio_usecase_delay_ms[usecase] = delay_ms;
+}
+
+/* Delay in Us */
+int64_t platform_get_audio_usecase_delay(audio_usecase_t usecase)
+{
+ if ((usecase <= USECASE_INVALID) || (usecase >= AUDIO_USECASE_MAX)) {
+ ALOGE("%s: invalid usecase case idx %d", __func__, usecase);
+ return 0;
+ }
+
+ return 1000LL * audio_usecase_delay_ms[usecase] ;
+}
+
+/* Delay in Us */
+int64_t platform_render_latency(struct stream_out *out)
+{
+ int64_t delay = 0LL;
+
+ if (!out)
+ return delay;
+
+ switch (out->usecase) {
case USECASE_AUDIO_PLAYBACK_DEEP_BUFFER:
- return DEEP_BUFFER_PLATFORM_DELAY;
+ delay = DEEP_BUFFER_PLATFORM_DELAY;
+ break;
case USECASE_AUDIO_PLAYBACK_LOW_LATENCY:
case USECASE_AUDIO_PLAYBACK_WITH_HAPTICS:
- return LOW_LATENCY_PLATFORM_DELAY;
+ delay = LOW_LATENCY_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->usecase could be used to add delay time if it's necessary */
+ delay += platform_get_audio_usecase_delay(out->usecase);
+ 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_set_snd_device_backend(snd_device_t device, const char *backend_tag,
diff --git a/hal/platform_api.h b/hal/platform_api.h
index 1d46c31..008e9a6 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -127,7 +127,8 @@ int platform_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
int table_size);
/* returns the latency for a usecase in Us */
-int64_t platform_render_latency(audio_usecase_t usecase);
+int64_t platform_render_latency(struct stream_out *out);
+int64_t platform_capture_latency(struct stream_in *in);
int platform_set_incall_recording_session_id(void *platform,
uint32_t session_id, int rec_mode);
@@ -209,6 +210,12 @@ int platform_get_usb_service_interval(void *platform,
unsigned long *service_interval);
int platform_get_haptics_pcm_device_id();
+void platform_set_audio_source_delay(audio_source_t audio_source, int delay_ms);
+
+int platform_get_audio_source_index(const char *audio_source_name);
+
+void platform_set_audio_usecase_delay(audio_usecase_t usecase, int delay_ms);
+
/* callback functions from platform to common audio HAL */
struct stream_in *adev_get_active_input(const struct audio_device *adev);
diff --git a/hal/platform_info.c b/hal/platform_info.c
index 5159d6d..fd8f745 100644
--- a/hal/platform_info.c
+++ b/hal/platform_info.c
@@ -55,6 +55,8 @@ typedef enum {
MIC_INFO,
ACDB_METAINFO_KEY,
EXTERNAL_DEVICE_SPECIFIC,
+ AUDIO_SOURCE_DELAY,
+ AUDIO_OUTPUT_USECASE_DELAY,
} section_t;
typedef void (* section_process_fn)(const XML_Char **attr);
@@ -75,6 +77,8 @@ static void process_snd_dev(const XML_Char **attr);
static void process_mic_info(const XML_Char **attr);
static void process_acdb_metainfo_key(const XML_Char **attr);
static void process_external_dev(const XML_Char **attr);
+static void process_audio_source_delay(const XML_Char **attr);
+static void process_audio_usecase_delay(const XML_Char **attr);
static section_process_fn section_table[] = {
[ROOT] = process_root,
@@ -92,6 +96,8 @@ static section_process_fn section_table[] = {
[MIC_INFO] = process_mic_info,
[ACDB_METAINFO_KEY] = process_acdb_metainfo_key,
[EXTERNAL_DEVICE_SPECIFIC] = process_external_dev,
+ [AUDIO_SOURCE_DELAY] = process_audio_source_delay,
+ [AUDIO_OUTPUT_USECASE_DELAY] = process_audio_usecase_delay,
};
static section_t section;
@@ -523,6 +529,61 @@ done:
return;
}
+static void process_audio_source_delay(const XML_Char **attr)
+{
+ audio_source_t audio_source = -1;
+
+ if (strcmp(attr[0], "name") != 0) {
+ ALOGE("%s: 'name' not found", __func__);
+ goto done;
+ }
+
+ audio_source = platform_get_audio_source_index((const char *)attr[1]);
+
+ if (audio_source < 0) {
+ ALOGE("%s: audio_source %s is not defined",
+ __func__, (char *)attr[1]);
+ goto done;
+ }
+
+ if (strcmp(attr[2], "delay") != 0) {
+ ALOGE("%s: 'delay' not found", __func__);
+ goto done;
+ }
+
+ platform_set_audio_source_delay(audio_source, atoi((char *)attr[3]));
+
+done:
+ return;
+}
+
+static void process_audio_usecase_delay(const XML_Char **attr)
+{
+ int index;
+
+ if (strcmp(attr[0], "name") != 0) {
+ ALOGE("%s: 'name' not found", __func__);
+ goto done;
+ }
+
+ index = platform_get_usecase_index((char *)attr[1]);
+ if (index < 0) {
+ ALOGE("%s: usecase %s in %s not found!",
+ __func__, attr[1], PLATFORM_INFO_XML_PATH);
+ goto done;
+ }
+
+ if (strcmp(attr[2], "delay") != 0) {
+ ALOGE("%s: 'delay' not found", __func__);
+ goto done;
+ }
+
+ platform_set_audio_usecase_delay(index, atoi((char *)attr[3]));
+
+done:
+ return;
+}
+
/* platform specific configuration key-value pairs */
static void process_config_params(const XML_Char **attr)
{
@@ -954,6 +1015,16 @@ static void start_tag(void *userdata __unused, const XML_Char *tag_name,
return;
}
section = NS;
+ } else if (strcmp(tag_name, "audio_input_source_delay") == 0) {
+ section = AUDIO_SOURCE_DELAY;
+ } else if (strcmp(tag_name, "audio_source_delay") == 0) {
+ section_process_fn fn = section_table[section];
+ fn(attr);
+ } else if (strcmp(tag_name, "audio_output_usecase_delay") == 0) {
+ section = AUDIO_OUTPUT_USECASE_DELAY;
+ } else if (strcmp(tag_name, "audio_usecase_delay") == 0) {
+ section_process_fn fn = section_table[section];
+ fn(attr);
}
} else {
if(strcmp(tag_name, "config_params") == 0) {