hal: Add support for acquiring inital sink latency
Split a2dp get initial sink latency from BT host ipc.
Change-Id: Ia97f4379f6bd8ae925bc79f7e458383eaabc2bd2
diff --git a/hal/audio_extn/a2dp.c b/hal/audio_extn/a2dp.c
index 0c51ec0..5239a30 100644
--- a/hal/audio_extn/a2dp.c
+++ b/hal/audio_extn/a2dp.c
@@ -74,6 +74,14 @@
#define MIXER_ENC_FMT_APTX "APTX"
#define MIXER_ENC_FMT_APTXHD "APTXHD"
#define MIXER_ENC_FMT_NONE "NONE"
+#define ENCODER_LATENCY_SBC 10
+#define ENCODER_LATENCY_APTX 40
+#define ENCODER_LATENCY_APTX_HD 20
+#define ENCODER_LATENCY_AAC 70
+#define DEFAULT_SINK_LATENCY_SBC 140
+#define DEFAULT_SINK_LATENCY_APTX 160
+#define DEFAULT_SINK_LATENCY_APTX_HD 180
+#define DEFAULT_SINK_LATENCY_AAC 180
typedef int (*audio_stream_open_t)(void);
typedef int (*audio_stream_close_t)(void);
@@ -85,6 +93,7 @@
typedef void * (*audio_get_codec_config_t)(uint8_t *multicast_status,uint8_t *num_dev,
audio_format_t *codec_type);
typedef int (*audio_check_a2dp_ready_t)(void);
+typedef uint16_t (*audio_get_a2dp_sink_latency_t)(void);
enum A2DP_STATE {
A2DP_STATE_CONNECTED,
@@ -109,6 +118,7 @@
clear_a2dpsuspend_flag_t clear_a2dpsuspend_flag;
audio_get_codec_config_t audio_get_codec_config;
audio_check_a2dp_ready_t audio_check_a2dp_ready;
+ audio_get_a2dp_sink_latency_t audio_get_a2dp_sink_latency;
enum A2DP_STATE bt_state;
audio_format_t bt_encoder_format;
uint32_t enc_sampling_rate;
@@ -293,6 +303,8 @@
dlsym(a2dp.bt_lib_handle, "audio_stream_close");
a2dp.audio_check_a2dp_ready = (audio_check_a2dp_ready_t)
dlsym(a2dp.bt_lib_handle,"audio_check_a2dp_ready");
+ a2dp.audio_get_a2dp_sink_latency = (audio_get_a2dp_sink_latency_t)
+ dlsym(a2dp.bt_lib_handle,"audio_get_a2dp_sink_latency");
}
}
@@ -901,18 +913,27 @@
}
}
+ uint32_t slatency = 0;
+ if (a2dp.audio_get_a2dp_sink_latency && a2dp.bt_state != A2DP_STATE_DISCONNECTED) {
+ slatency = a2dp.audio_get_a2dp_sink_latency();
+ }
+
switch(a2dp.bt_encoder_format) {
case AUDIO_FORMAT_SBC:
- latency = (avsync_runtime_prop > 0) ? sbc_offset : 150;
+ latency = (avsync_runtime_prop > 0) ? sbc_offset : ENCODER_LATENCY_SBC;
+ latency += (slatency <= 0) ? DEFAULT_SINK_LATENCY_SBC : slatency;
break;
case AUDIO_FORMAT_APTX:
- latency = (avsync_runtime_prop > 0) ? aptx_offset : 200;
+ latency = (avsync_runtime_prop > 0) ? aptx_offset : ENCODER_LATENCY_APTX;
+ latency += (slatency <= 0) ? DEFAULT_SINK_LATENCY_APTX : slatency;
break;
case AUDIO_FORMAT_APTX_HD:
- latency = (avsync_runtime_prop > 0) ? aptxhd_offset : 200;
+ latency = (avsync_runtime_prop > 0) ? aptxhd_offset : ENCODER_LATENCY_APTX_HD;
+ latency += (slatency <= 0) ? DEFAULT_SINK_LATENCY_APTX_HD : slatency;
break;
case AUDIO_FORMAT_AAC:
- latency = (avsync_runtime_prop > 0) ? aac_offset : 250;
+ latency = (avsync_runtime_prop > 0) ? aac_offset : ENCODER_LATENCY_AAC;
+ latency += (slatency <= 0) ? DEFAULT_SINK_LATENCY_AAC : slatency;
break;
default:
latency = 200;
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 868b562..2531b85 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -3269,8 +3269,7 @@
(out->config.rate);
}
- if ((AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) &&
- !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
+ if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
latency += audio_extn_a2dp_get_encoder_latency();
ALOGV("%s: Latency %d", __func__, latency);
@@ -3708,6 +3707,13 @@
if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
ret = compress_get_tstamp(out->compr, &dsp_frames,
&out->sample_rate);
+ // Adjustment accounts for A2dp encoder latency with offload usecases
+ // Note: Encoder latency is returned in ms.
+ if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
+ unsigned long offset =
+ (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
+ dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
+ }
ALOGVV("%s rendered frames %ld sample_rate %d",
__func__, dsp_frames, out->sample_rate);
*frames = dsp_frames;