audio: hal: update backend configuration for DTS passthrough
-For DTS passthrough usecase derive IEC61937 transmissing rate and
channels from DTS frame parser as backend needs to be configured as
per transmission rate and not based on stream sample rate and channels.
CRs-Fixed: 2049605
Change-Id: I9d5703d4b4d3485df629b9f169487e8be852ad7a
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 67a8e26..8772302 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -480,7 +480,7 @@
#define HDMI_PASSTHROUGH_MAX_SAMPLE_RATE 192000
#ifndef HDMI_PASSTHROUGH_ENABLED
-#define audio_extn_passthru_update_stream_configuration(adev, out) (0)
+#define audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes) (0)
#define audio_extn_passthru_is_convert_supported(adev, out) (0)
#define audio_extn_passthru_is_passt_supported(adev, out) (0)
#define audio_extn_passthru_is_passthrough_stream(out) (0)
@@ -497,13 +497,15 @@
#define audio_extn_passthru_set_parameters(a, p) (-ENOSYS)
#define audio_extn_passthru_init(a) do {} while(0)
#define audio_extn_passthru_should_standby(o) (1)
+#define audio_extn_passthru_get_channel_count(out) (0)
#else
bool audio_extn_passthru_is_convert_supported(struct audio_device *adev,
struct stream_out *out);
bool audio_extn_passthru_is_passt_supported(struct audio_device *adev,
struct stream_out *out);
-void audio_extn_passthru_update_stream_configuration(struct audio_device *adev,
- struct stream_out *out);
+void audio_extn_passthru_update_stream_configuration(
+ struct audio_device *adev, struct stream_out *out,
+ const void *buffer, size_t bytes);
bool audio_extn_passthru_is_passthrough_stream(struct stream_out *out);
int audio_extn_passthru_get_buffer_size(audio_offload_info_t* info);
int audio_extn_passthru_set_volume(struct stream_out *out, int mute);
@@ -519,6 +521,7 @@
bool audio_extn_passthru_is_active();
void audio_extn_passthru_init(struct audio_device *adev);
bool audio_extn_passthru_should_standby(struct stream_out *out);
+int audio_extn_passthru_get_channel_count(struct stream_out *out);
#endif
#ifndef HFP_ENABLED
diff --git a/hal/audio_extn/passthru.c b/hal/audio_extn/passthru.c
index 7011c40..31c94f6 100644
--- a/hal/audio_extn/passthru.c
+++ b/hal/audio_extn/passthru.c
@@ -40,11 +40,34 @@
#include <cutils/properties.h>
#include "sound/compress_params.h"
+
#ifdef DYNAMIC_LOG_ENABLED
#include <log_xml_parser.h>
#define LOG_MASK HAL_MOD_FILE_PASSTH
#include <log_utils.h>
#endif
+/*
+ * Offload buffer size for compress passthrough
+ */
+
+#ifdef DTSHD_PARSER_ENABLED
+#include "audio_parsers.h"
+
+/* list of all supported DTS transmission sample rates */
+static const int dts_transmission_sample_rates[] = {
+ 44100, 48000, 88200, 96000, 176400, 192000
+};
+
+ /*
+ * for DTSHD stream one frame size can be upto 36kb and to extract iec61937
+ * info for parsing usecase minimum one frame needs to be sent to dts parser
+ */
+#define MAX_COMPRESS_PASSTHROUGH_FRAGMENT_SIZE (36 * 1024)
+#else
+#define MAX_COMPRESS_PASSTHROUGH_FRAGMENT_SIZE (8 * 1024)
+#endif
+
+#define MIN_COMPRESS_PASSTHROUGH_FRAGMENT_SIZE (2 * 1024)
static const audio_format_t audio_passthru_formats[] = {
AUDIO_FORMAT_AC3,
@@ -66,6 +89,108 @@
*/
static volatile int32_t compress_passthru_active;
+#ifdef DTSHD_PARSER_ENABLED
+static void passthru_update_stream_configuration_from_dts_parser( struct stream_out *out,
+ const void *buffer, size_t bytes)
+{
+ struct audio_parser_codec_info codec_info;
+ struct dtshd_iec61937_info dtshd_tr_info;
+ int i;
+ int ret;
+ bool is_valid_transmission_rate = false;
+ bool is_valid_transmission_channels = false;
+
+ /* codec format is AUDIO_PARSER_CODEC_DTSHD for both DTS and DTSHD as
+ * DTSHD parser can support both DTS and DTSHD
+ */
+ memset(&codec_info, 0, sizeof(struct audio_parser_codec_info));
+ memset(&dtshd_tr_info, 0, sizeof(struct dtshd_iec61937_info));
+
+ init_audio_parser((unsigned char *)buffer, bytes, AUDIO_PARSER_CODEC_DTSHD);
+ codec_info.codec_type = AUDIO_PARSER_CODEC_DTSHD;
+ if (!(ret = get_iec61937_info(&codec_info))) {
+ dtshd_tr_info = codec_info.codec_config.dtshd_tr_info;
+ ALOGD("dts new sample rate %d and channels %d\n",
+ dtshd_tr_info.sample_rate,
+ dtshd_tr_info.num_channels);
+ for (i = 0; i < sizeof(dts_transmission_sample_rates); i++) {
+ if (dts_transmission_sample_rates[i] ==
+ dtshd_tr_info.sample_rate) {
+ out->sample_rate = dtshd_tr_info.sample_rate;
+ out->compr_config.codec->sample_rate = out->sample_rate;
+ is_valid_transmission_rate = true;
+ break;
+ }
+ }
+ /* DTS transmission channels should be 2 or 8*/
+ if ((dtshd_tr_info.num_channels == 2) ||
+ (dtshd_tr_info.num_channels == 8)) {
+ out->compr_config.codec->ch_in = dtshd_tr_info.num_channels;
+ out->channel_mask = audio_channel_out_mask_from_count
+ (dtshd_tr_info.num_channels);
+ is_valid_transmission_channels = true;
+ }
+ } else {
+ ALOGE("%s:: get_iec61937_info failed %d", __func__, ret);
+ }
+
+ if (!is_valid_transmission_rate) {
+ ALOGE("%s:: Invalid dts transmission rate %d\n using default sample rate 192000",
+ dtshd_tr_info.sample_rate);
+ out->sample_rate = 192000;
+ out->compr_config.codec->sample_rate = out->sample_rate;
+ }
+
+ if (!is_valid_transmission_channels) {
+ ALOGE("%s:: Invalid transmission channels %d using default transmission"
+ " channels as 2", __func__, dtshd_tr_info.num_channels);
+ out->compr_config.codec->ch_in = 2;
+ out->channel_mask = audio_channel_out_mask_from_count(2);
+ }
+}
+#else
+static void passthru_update_stream_configuration_from_dts_parser(
+ struct stream_out *out __unused,
+ const void *buffer __unused,
+ size_t bytes __unused)
+{
+ return;
+}
+#endif
+
+int audio_extn_passthru_get_channel_count(struct stream_out *out)
+{
+ int channel_count = DEFAULT_HDMI_OUT_CHANNELS;
+
+ if (!out) {
+ ALOGE("%s:: Invalid param out %p", __func__, out);
+ return -EINVAL;
+ }
+
+ if (!audio_extn_passthru_is_supported_format(out->format)) {
+ ALOGE("%s:: not a passthrough format %d", __func__, out->format);
+ return -EINVAL;
+ }
+
+ switch(out->format) {
+ case AUDIO_FORMAT_DOLBY_TRUEHD:
+ channel_count = 8;
+ break;
+ case AUDIO_FORMAT_DTS:
+ case AUDIO_FORMAT_DTS_HD:
+#ifdef DTSHD_PARSER_ENABLED
+ /* taken channel count from parser*/
+ channel_count = audio_channel_count_from_out_mask(out->channel_mask);
+#endif
+ break;
+ default:
+ break;
+ }
+
+ ALOGE("%s: pass through channel count %d\n", __func__, channel_count);
+ return channel_count;
+}
+
bool audio_extn_passthru_is_supported_format(audio_format_t format)
{
int32_t num_passthru_formats = sizeof(audio_passthru_formats) /
@@ -265,7 +390,8 @@
}
void audio_extn_passthru_update_stream_configuration(
- struct audio_device *adev, struct stream_out *out)
+ struct audio_device *adev, struct stream_out *out,
+ const void *buffer, size_t bytes)
{
if (audio_extn_passthru_is_passt_supported(adev, out)) {
ALOGV("%s:PASSTHROUGH", __func__);
@@ -280,6 +406,15 @@
ALOGV("%s:NO PASSTHROUGH", __func__);
out->compr_config.codec->compr_passthr = LEGACY_PCM;
}
+
+ /*
+ * for DTS passthrough, need to get sample rate from bitstream,
+ * based on this sample rate hdmi backend will be configured
+ */
+ if ((out->format == AUDIO_FORMAT_DTS) ||
+ (out->format == AUDIO_FORMAT_DTS_HD))
+ passthru_update_stream_configuration_from_dts_parser(out, buffer, bytes);
+
}
bool audio_extn_passthru_is_passthrough_stream(struct stream_out *out)
@@ -318,7 +453,24 @@
int audio_extn_passthru_get_buffer_size(audio_offload_info_t* info)
{
- return platform_get_compress_passthrough_buffer_size(info);
+ uint32_t fragment_size = MIN_COMPRESS_PASSTHROUGH_FRAGMENT_SIZE;
+ char value[PROPERTY_VALUE_MAX] = {0};
+
+ if (((info->format == AUDIO_FORMAT_DOLBY_TRUEHD) ||
+ (info->format == AUDIO_FORMAT_IEC61937)) &&
+ property_get("audio.truehd.buffer.size.kb", value, "") &&
+ atoi(value)) {
+ fragment_size = atoi(value) * 1024;
+ goto done;
+ } else if ((info->format == AUDIO_FORMAT_DTS) ||
+ (info->format == AUDIO_FORMAT_DTS_HD)) {
+ fragment_size = MAX_COMPRESS_PASSTHROUGH_FRAGMENT_SIZE;
+ goto done;
+ }
+
+done:
+ return fragment_size;
+
}
int audio_extn_passthru_set_volume(struct stream_out *out, int mute)
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index eeaec21..9bee430 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -2407,7 +2407,6 @@
if (audio_extn_passthru_is_enabled() &&
audio_extn_passthru_is_passthrough_stream(out)) {
audio_extn_passthru_on_start(out);
- audio_extn_passthru_update_stream_configuration(adev, out);
}
}
@@ -3350,6 +3349,15 @@
goto exit;
}
+ if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
+ /*ADD audio_extn_passthru_is_passthrough_stream(out) check*/
+ if ((audio_extn_passthru_is_enabled()) &&
+ (!out->is_iec61937_info_available)) {
+ audio_extn_passthru_update_stream_configuration(adev, out,
+ buffer, bytes);
+ out->is_iec61937_info_available = true;
+ }
+ }
if (out->standby) {
out->standby = false;
pthread_mutex_lock(&adev->lock);
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 80b11b8..9c13d99 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -297,6 +297,8 @@
audio_offload_info_t info;
int started;
qahwi_stream_out_t qahwi_out;
+
+ bool is_iec61937_info_available;
};
struct stream_in {
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 3fd13b3..2836974 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -113,12 +113,6 @@
#define DEFAULT_RX_BACKEND "SLIMBUS_0_RX"
/*
- * Offload buffer size for compress passthrough
- */
-#define MIN_COMPRESS_PASSTHROUGH_FRAGMENT_SIZE (2 * 1024)
-#define MAX_COMPRESS_PASSTHROUGH_FRAGMENT_SIZE (8 * 1024)
-
-/*
* This file will have a maximum of 38 bytes:
*
* 4 bytes: number of audio blocks
@@ -5448,7 +5442,7 @@
{
unsigned int bit_width;
unsigned int sample_rate;
- unsigned int channels, max_supported_channels = 0;
+ int channels, max_supported_channels = 0;
struct platform_data *my_data = (struct platform_data *)adev->platform;
edid_audio_info *edid_info = (edid_audio_info *)my_data->edid_info;
bool passthrough_enabled = false;
@@ -5494,17 +5488,18 @@
channels = max_supported_channels;
} else {
- /*During pass through set default bit width */
- if (usecase->stream.out->format == AUDIO_FORMAT_DOLBY_TRUEHD)
- channels = 8;
- else
+ channels = audio_extn_passthru_get_channel_count(usecase->stream.out);
+ if (channels <= 0) {
+ ALOGE("%s: becf: afe: HDMI backend using defalut channel %u",
+ __func__, DEFAULT_HDMI_OUT_CHANNELS);
channels = DEFAULT_HDMI_OUT_CHANNELS;
+ }
if ((usecase->stream.out->format == AUDIO_FORMAT_E_AC3) ||
(usecase->stream.out->format == AUDIO_FORMAT_E_AC3_JOC) ||
(usecase->stream.out->format == AUDIO_FORMAT_DOLBY_TRUEHD)) {
+ sample_rate = sample_rate * 4 ;
- sample_rate = sample_rate * 4;
if (sample_rate > HDMI_PASSTHROUGH_MAX_SAMPLE_RATE)
sample_rate = HDMI_PASSTHROUGH_MAX_SAMPLE_RATE;
}
@@ -6421,25 +6416,6 @@
return format;
}
-uint32_t platform_get_compress_passthrough_buffer_size(
- audio_offload_info_t* info)
-{
- uint32_t fragment_size = MIN_COMPRESS_PASSTHROUGH_FRAGMENT_SIZE;
- char value[PROPERTY_VALUE_MAX] = {0};
-
- if (((info->format == AUDIO_FORMAT_DOLBY_TRUEHD) ||
- (info->format == AUDIO_FORMAT_IEC61937)) &&
- property_get("vendor.audio.truehd.buffer.size.kb", value, "") &&
- atoi(value)) {
- fragment_size = atoi(value) * 1024;
- goto done;
- }
- if (!info->has_video)
- fragment_size = MIN_COMPRESS_PASSTHROUGH_FRAGMENT_SIZE;
-done:
- return fragment_size;
-}
-
void platform_reset_edid_info(void *platform) {
ALOGV("%s:", __func__);
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 36a1d3a..d423919 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -87,12 +87,6 @@
/*
- * Offload buffer size for compress passthrough
- */
-#define MIN_COMPRESS_PASSTHROUGH_FRAGMENT_SIZE (2 * 1024)
-#define MAX_COMPRESS_PASSTHROUGH_FRAGMENT_SIZE (8 * 1024)
-
-/*
* This file will have a maximum of 38 bytes:
*
* 4 bytes: number of audio blocks
@@ -5323,7 +5317,7 @@
{
unsigned int bit_width;
unsigned int sample_rate;
- unsigned int channels, max_supported_channels = 0;
+ int channels, max_supported_channels = 0;
struct platform_data *my_data = (struct platform_data *)adev->platform;
edid_audio_info *edid_info = (edid_audio_info *)my_data->edid_info;
bool passthrough_enabled = false;
@@ -5369,12 +5363,12 @@
channels = max_supported_channels;
} else {
- /*During pass through set default bit width */
- if (usecase->stream.out->format == AUDIO_FORMAT_DOLBY_TRUEHD)
- channels = 8;
- else
+ channels = audio_extn_passthru_get_channel_count(usecase->stream.out);
+ if (channels <= 0) {
+ ALOGE("%s: becf: afe: HDMI backend using defalut channel %u",
+ __func__, DEFAULT_HDMI_OUT_CHANNELS);
channels = DEFAULT_HDMI_OUT_CHANNELS;
-
+ }
if ((usecase->stream.out->format == AUDIO_FORMAT_E_AC3) ||
(usecase->stream.out->format == AUDIO_FORMAT_E_AC3_JOC) ||
(usecase->stream.out->format == AUDIO_FORMAT_DOLBY_TRUEHD)) {
@@ -6248,25 +6242,6 @@
return format;
}
-uint32_t platform_get_compress_passthrough_buffer_size(
- audio_offload_info_t* info)
-{
- uint32_t fragment_size = MIN_COMPRESS_PASSTHROUGH_FRAGMENT_SIZE;
- char value[PROPERTY_VALUE_MAX] = {0};
-
- if (((info->format == AUDIO_FORMAT_DOLBY_TRUEHD) ||
- (info->format == AUDIO_FORMAT_IEC61937)) &&
- property_get("vendor.audio.truehd.buffer.size.kb", value, "") &&
- atoi(value)) {
- fragment_size = atoi(value) * 1024;
- goto done;
- }
- if (!info->has_video)
- fragment_size = MIN_COMPRESS_PASSTHROUGH_FRAGMENT_SIZE;
-done:
- return fragment_size;
-}
-
void platform_check_and_update_copp_sample_rate(void* platform, snd_device_t snd_device,
unsigned int stream_sr, int* sample_rate)
{
diff --git a/hal/platform_api.h b/hal/platform_api.h
index b31ed94..56e56d0 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -153,7 +153,6 @@
struct audio_offload_info_t;
uint32_t platform_get_compress_offload_buffer_size(audio_offload_info_t* info);
-uint32_t platform_get_compress_passthrough_buffer_size(audio_offload_info_t* info);
bool platform_check_and_set_codec_backend_cfg(struct audio_device* adev,
struct audio_usecase *usecase, snd_device_t snd_device);