hal: AV sync latency correction for split A2dp
Audio lagging video for split A2DP. Encoder latencies were not
considered for SBC/APTX/APTXHD/AAC formats taking deep buffer,
PCM offload, low latency paths. A latency of 200-300ms observed
across formats. Our current solution changes the out_get_latency()
function in primary HAL to update latency based on BT codec formats.
CRs-Fixed: 2004199
Change-Id: I8f19018054e3945d618ba6bcfef5d28e4fbab716
diff --git a/hal/audio_extn/a2dp.c b/hal/audio_extn/a2dp.c
index cc4b283..3dc00fb 100644
--- a/hal/audio_extn/a2dp.c
+++ b/hal/audio_extn/a2dp.c
@@ -824,4 +824,51 @@
a2dp.is_handoff_in_progress = false;
update_offload_codec_capabilities();
}
+
+uint32_t audio_extn_a2dp_get_encoder_latency()
+{
+ void *codec_info = NULL;
+ uint8_t multi_cast = 0, num_dev = 1;
+ audio_format_t codec_type = AUDIO_FORMAT_INVALID;
+ uint32_t latency = 0;
+ int avsync_runtime_prop = 0;
+ int sbc_offset = 0, aptx_offset = 0, aptxhd_offset = 0, aac_offset = 0;
+ char value[PROPERTY_VALUE_MAX];
+
+ if (!a2dp.audio_get_codec_config) {
+ ALOGE(" a2dp handle is not identified");
+ return latency;
+ }
+ codec_info = a2dp.audio_get_codec_config(&multi_cast, &num_dev,
+ &codec_type);
+
+ memset(value, '\0', sizeof(char)*PROPERTY_VALUE_MAX);
+ avsync_runtime_prop = property_get("audio.a2dp.codec.latency", value, NULL);
+ if (avsync_runtime_prop > 0) {
+ if (sscanf(value, "%d/%d/%d/%d",
+ &sbc_offset, &aptx_offset, &aptxhd_offset, &aac_offset) != 4) {
+ ALOGI("Failed to parse avsync offset params from '%s'.", value);
+ avsync_runtime_prop = 0;
+ }
+ }
+
+ switch(codec_type) {
+ case AUDIO_FORMAT_SBC:
+ latency = (avsync_runtime_prop > 0) ? sbc_offset : 150;
+ break;
+ case AUDIO_FORMAT_APTX:
+ latency = (avsync_runtime_prop > 0) ? aptx_offset : 200;
+ break;
+ case AUDIO_FORMAT_APTX_HD:
+ latency = (avsync_runtime_prop > 0) ? aptxhd_offset : 200;
+ break;
+ case AUDIO_FORMAT_AAC:
+ latency = (avsync_runtime_prop > 0) ? aac_offset : 250;
+ break;
+ default:
+ latency = 200;
+ break;
+ }
+ return latency;
+}
#endif // SPLIT_A2DP_ENABLED
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 8d58d09..c114d2d 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -205,6 +205,7 @@
#define audio_extn_a2dp_is_force_device_switch() (0)
#define audio_extn_a2dp_set_handoff_mode(is_on) (0)
#define audio_extn_a2dp_get_apptype_params(sample_rate,bit_width) (0)
+#define audio_extn_a2dp_get_encoder_latency() (0)
#else
void audio_extn_a2dp_init(void *adev);
@@ -215,6 +216,7 @@
void audio_extn_a2dp_set_handoff_mode(bool is_on);
void audio_extn_a2dp_get_apptype_params(uint32_t *sample_rate,
uint32_t *bit_width);
+uint32_t audio_extn_a2dp_get_encoder_latency();
#endif
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 6f33acf..262fec5 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -2895,6 +2895,10 @@
(out->config.rate);
}
+ if ((AUDIO_DEVICE_OUT_BLUETOOTH_A2DP == out->devices) &&
+ !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
+ latency += audio_extn_a2dp_get_encoder_latency();
+
ALOGV("%s: Latency %d", __func__, latency);
return latency;
}