Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 37864bc1 authored by Manish Dewangan's avatar Manish Dewangan Committed by Shiv Maliyappanahalli
Browse files

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
parent e64c61e8
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -480,7 +480,7 @@ enum {
#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 @@ enum {
#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_enabled();
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
+154 −2
Original line number Diff line number Diff line
@@ -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 const audio_format_t audio_passthru_formats[] = {
 */
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 @@ bool audio_extn_passthru_is_passt_supported(struct audio_device *adev,
}

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 @@ void audio_extn_passthru_update_stream_configuration(
        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 @@ bool audio_extn_passthru_is_passthrough_stream(struct stream_out *out)

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)
+9 −1
Original line number Diff line number Diff line
@@ -2407,7 +2407,6 @@ int start_output_stream(struct stream_out *out)
        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 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
        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);
+2 −0
Original line number Diff line number Diff line
@@ -297,6 +297,8 @@ struct stream_out {
    audio_offload_info_t info;
    int started;
    qahwi_stream_out_t qahwi_out;

    bool is_iec61937_info_available;
};

struct stream_in {
+7 −31
Original line number Diff line number Diff line
@@ -112,12 +112,6 @@
#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (32 * 1024)
#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:
 *
@@ -5448,7 +5442,7 @@ static void platform_check_hdmi_backend_cfg(struct audio_device* adev,
{
    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 @@ static void platform_check_hdmi_backend_cfg(struct audio_device* adev,
            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 ;

            if (sample_rate > HDMI_PASSTHROUGH_MAX_SAMPLE_RATE)
                sample_rate = HDMI_PASSTHROUGH_MAX_SAMPLE_RATE;
        }
@@ -6421,25 +6416,6 @@ unsigned char platform_map_to_edid_format(int audio_format)
    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__);
Loading