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

Commit 084ff19c authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "hal: Add support for PCM in offload path"

parents 5e882449 c6a3a9e6
Loading
Loading
Loading
Loading
+25 −37
Original line number Diff line number Diff line
@@ -53,16 +53,14 @@
#include "voice_extn.h"

#include "sound/compress_params.h"
#include "sound/asound.h"

#define MAX_COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
#define MIN_COMPRESS_OFFLOAD_FRAGMENT_SIZE (2 * 1024)
#define COMPRESS_OFFLOAD_FRAGMENT_SIZE_FOR_AV_STREAMING (2 * 1024)
#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (32 * 1024)
#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
/* ToDo: Check and update a proper value in msec */
#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000


#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER

struct pcm_config pcm_config_deep_buffer = {
@@ -155,35 +153,6 @@ static unsigned int audio_device_ref_count;

static int set_voice_volume_l(struct audio_device *adev, float volume);

/* Read  offload buffer size from a property.
 * If value is not power of 2  round it to
 * power of 2.
 */
static uint32_t get_offload_buffer_size(audio_offload_info_t* info)
{
    char value[PROPERTY_VALUE_MAX] = {0};
    uint32_t fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
    if((property_get("audio.offload.buffer.size.kb", value, "")) &&
            atoi(value)) {
        fragment_size =  atoi(value) * 1024;
        //ring buffer size needs to be 4k aligned.
        CHECK(!(fragment_size * COMPRESS_OFFLOAD_NUM_FRAGMENTS % 4096));
    }

    if (info != NULL && info->has_video && info->is_streaming) {
        fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE_FOR_AV_STREAMING;
        ALOGV("%s: offload fragment size reduced for AV streaming to %d",
               __func__, out->compr_config.fragment_size);
    }

    if(fragment_size < MIN_COMPRESS_OFFLOAD_FRAGMENT_SIZE)
        fragment_size = MIN_COMPRESS_OFFLOAD_FRAGMENT_SIZE;
    else if(fragment_size > MAX_COMPRESS_OFFLOAD_FRAGMENT_SIZE)
        fragment_size = MAX_COMPRESS_OFFLOAD_FRAGMENT_SIZE;
    ALOGVV("%s: fragment_size %d", __func__, fragment_size);
    return fragment_size;
}

static int check_and_set_gapless_mode(struct audio_device *adev) {


@@ -214,7 +183,9 @@ static int check_and_set_gapless_mode(struct audio_device *adev) {
static bool is_supported_format(audio_format_t format)
{
    if (format == AUDIO_FORMAT_MP3 ||
            format == AUDIO_FORMAT_AAC)
        format == AUDIO_FORMAT_AAC ||
        format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
        format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
           return true;

    return false;
@@ -231,6 +202,10 @@ static int get_snd_codec_id(audio_format_t format)
    case AUDIO_FORMAT_AAC:
        id = SND_AUDIOCODEC_AAC;
        break;
    case AUDIO_FORMAT_PCM_16_BIT_OFFLOAD:
    case AUDIO_FORMAT_PCM_24_BIT_OFFLOAD:
        id = SND_AUDIOCODEC_PCM;
        break;
    default:
        ALOGE("%s: Unsupported audio format :%x", __func__, format);
    }
@@ -2169,8 +2144,10 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
        out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
        if (config->offload_info.channel_mask)
            out->channel_mask = config->offload_info.channel_mask;
        else if (config->channel_mask)
        else if (config->channel_mask) {
            out->channel_mask = config->channel_mask;
            config->offload_info.channel_mask = config->channel_mask;
        }
        out->format = config->offload_info.format;
        out->sample_rate = config->offload_info.sample_rate;

@@ -2187,7 +2164,13 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
        else
            out->compr_config.codec->id =
                get_snd_codec_id(config->offload_info.format);
        out->compr_config.fragment_size = get_offload_buffer_size(&config->offload_info);
        if (audio_is_offload_pcm(config->offload_info.format)) {
            out->compr_config.fragment_size =
                       platform_get_pcm_offload_buffer_size(&config->offload_info);
        } else {
            out->compr_config.fragment_size =
                       platform_get_compress_offload_buffer_size(&config->offload_info);
        }
        out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
        out->compr_config.codec->sample_rate =
                    compress_get_alsa_rate(config->offload_info.sample_rate);
@@ -2198,6 +2181,11 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
        out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
        out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;

        if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
            out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
        else if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
            out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;

        if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
            out->non_blocking = 1;

+84 −0
Original line number Diff line number Diff line
@@ -31,12 +31,30 @@
#include "platform.h"
#include "audio_extn.h"
#include "voice_extn.h"
#include "sound/compress_params.h"

#define MIXER_XML_PATH "/system/etc/mixer_paths.xml"
#define MIXER_XML_PATH_AUXPCM "/system/etc/mixer_paths_auxpcm.xml"
#define LIB_ACDB_LOADER "libacdbloader.so"
#define AUDIO_DATA_BLOCK_MIXER_CTL "HDMI EDID"

#define MAX_COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
#define MIN_COMPRESS_OFFLOAD_FRAGMENT_SIZE (2 * 1024)
#define COMPRESS_OFFLOAD_FRAGMENT_SIZE_FOR_AV_STREAMING (2 * 1024)
#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (32 * 1024)

/* Used in calculating fragment size for pcm offload */
#define PCM_OFFLOAD_BUFFER_DURATION_FOR_AV 2000 /* 2 secs */
#define PCM_OFFLOAD_BUFFER_DURATION_FOR_AV_STREAMING 100 /* 100 millisecs */

/* MAX PCM fragment size cannot be increased  further due
 * to flinger's cblk size of 1mb,and it has to be a multiple of
 * 24 - lcm of channels supported by DSP
 */
#define MAX_PCM_OFFLOAD_FRAGMENT_SIZE (240 * 1024)
#define MIN_PCM_OFFLOAD_FRAGMENT_SIZE (32 * 1024)

#define ALIGN( num, to ) (((num) + (to-1)) & (~(to-1)))
/*
 * This file will have a maximum of 38 bytes:
 *
@@ -1733,3 +1751,69 @@ bool platform_listen_update_status(snd_device_t snd_device)
    else
        return false;
}

/* Read  offload buffer size from a property.
 * If value is not power of 2  round it to
 * power of 2.
 */
uint32_t platform_get_compress_offload_buffer_size(audio_offload_info_t* info)
{
    char value[PROPERTY_VALUE_MAX] = {0};
    uint32_t fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
    if((property_get("audio.offload.buffer.size.kb", value, "")) &&
            atoi(value)) {
        fragment_size =  atoi(value) * 1024;
    }

    if (info != NULL && info->has_video && info->is_streaming) {
        fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE_FOR_AV_STREAMING;
        ALOGV("%s: offload fragment size reduced for AV streaming to %d",
               __func__, out->compr_config.fragment_size);
    }

    fragment_size = ALIGN( fragment_size, 1024);

    if(fragment_size < MIN_COMPRESS_OFFLOAD_FRAGMENT_SIZE)
        fragment_size = MIN_COMPRESS_OFFLOAD_FRAGMENT_SIZE;
    else if(fragment_size > MAX_COMPRESS_OFFLOAD_FRAGMENT_SIZE)
        fragment_size = MAX_COMPRESS_OFFLOAD_FRAGMENT_SIZE;
    ALOGV("%s: fragment_size %d", __func__, fragment_size);
    return fragment_size;
}

uint32_t platform_get_pcm_offload_buffer_size(audio_offload_info_t* info)
{
    uint32_t fragment_size = MIN_PCM_OFFLOAD_FRAGMENT_SIZE;
    uint32_t bits_per_sample = 16;

    if (info->format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD) {
        bits_per_sample = 32;
    }

    if (!info->has_video) {
        fragment_size = MAX_PCM_OFFLOAD_FRAGMENT_SIZE;

    } else if (info->has_video && info->is_streaming) {
        fragment_size = (PCM_OFFLOAD_BUFFER_DURATION_FOR_AV_STREAMING
                                     * info->sample_rate
                                     * bits_per_sample
                                     * popcount(info->channel_mask))/1000;

    } else if (info->has_video) {
        fragment_size = (PCM_OFFLOAD_BUFFER_DURATION_FOR_AV
                                     * info->sample_rate
                                     * bits_per_sample
                                     * popcount(info->channel_mask))/1000;
    }

    fragment_size = ALIGN( fragment_size, 1024);

    if(fragment_size < MIN_PCM_OFFLOAD_FRAGMENT_SIZE)
        fragment_size = MIN_PCM_OFFLOAD_FRAGMENT_SIZE;
    else if(fragment_size > MAX_PCM_OFFLOAD_FRAGMENT_SIZE)
        fragment_size = MAX_PCM_OFFLOAD_FRAGMENT_SIZE;

    ALOGV("%s: fragment_size %d", __func__, fragment_size);
    return fragment_size;
}
+4 −0
Original line number Diff line number Diff line
@@ -65,4 +65,8 @@ bool platform_listen_update_status(snd_device_t snd_device);
/* From platform_info_parser.c */
int platform_info_init(void);

struct audio_offload_info_t;
uint32_t platform_get_compress_offload_buffer_size(audio_offload_info_t* info);
uint32_t platform_get_pcm_offload_buffer_size(audio_offload_info_t* info);

#endif // AUDIO_PLATFORM_API_H
+55 −26
Original line number Diff line number Diff line
@@ -1116,9 +1116,31 @@ bool AudioPolicyManager::isOffloadSupported(const audio_offload_info_t& offloadI
        return false;
    }
#endif
    // Check if stream type is music, then only allow offload as of now.
    if (offloadInfo.stream_type != AUDIO_STREAM_MUSIC)
    {
        ALOGV("isOffloadSupported: stream_type != MUSIC, returning false");
        return false;
    }

    // Check if offload has been disabled
    char propValue[PROPERTY_VALUE_MAX];
    bool pcmOffload = false;
    if (audio_is_offload_pcm(offloadInfo.format)) {
        if(property_get("audio.offload.pcm.enable", propValue, NULL)) {
            bool prop_enabled = atoi(propValue) || !strncmp("true", propValue, 4);
            if (prop_enabled) {
                ALOGW("PCM offload property is enabled");
                pcmOffload = true;
            }
        }
        if (!pcmOffload) {
            ALOGV("PCM offload disabled by property audio.offload.pcm.enable");
            return false;
        }
    }

    if (!pcmOffload) {
        // Check if offload has been disabled
        if (property_get("audio.offload.disable", propValue, "0")) {
            if (atoi(propValue) != 0) {
                ALOGV("offload disabled by audio.offload.disable=%s", propValue );
@@ -1126,14 +1148,13 @@ bool AudioPolicyManager::isOffloadSupported(const audio_offload_info_t& offloadI
            }
        }

    // Check if stream type is music, then only allow offload as of now.
    if (offloadInfo.stream_type != AUDIO_STREAM_MUSIC)
    {
        ALOGV("isOffloadSupported: stream_type != MUSIC, returning false");
        //check if it's multi-channel AAC format
        if (AudioSystem::popCount(offloadInfo.channel_mask) > 2
              && offloadInfo.format == AUDIO_FORMAT_AAC) {
            ALOGV("offload disabled for multi-channel AAC format");
            return false;
        }

    //TODO: enable audio offloading with video when ready
        if (offloadInfo.has_video)
        {
            if(property_get("av.offload.enable", propValue, NULL)) {
@@ -1142,18 +1163,26 @@ bool AudioPolicyManager::isOffloadSupported(const audio_offload_info_t& offloadI
                    ALOGW("offload disabled by av.offload.enable = %s ", propValue );
                    return false;
                }
            } else {
                return false;
            }
        if(offloadInfo.is_streaming &&
           property_get("av.streaming.offload.enable", propValue, NULL)) {

            if(offloadInfo.is_streaming) {
                if (property_get("av.streaming.offload.enable", propValue, NULL)) {
                    bool prop_enabled = atoi(propValue) || !strncmp("true", propValue, 4);
                    if (!prop_enabled) {
                       ALOGW("offload disabled by av.streaming.offload.enable = %s ", propValue );
                       return false;
                    }
                } else {
                    //Do not offload AV streamnig if the property is not defined
                    return false;
                }
            }
            ALOGV("isOffloadSupported: has_video == true, property\
                    set to enable offload");
        }
    }

    //If duration is less than minimum value defined in property, return false
    if (property_get("audio.offload.min.duration.secs", propValue, NULL)) {
@@ -1165,7 +1194,7 @@ bool AudioPolicyManager::isOffloadSupported(const audio_offload_info_t& offloadI
        ALOGV("Offload denied by duration < default min(=%u)", OFFLOAD_DEFAULT_MIN_DURATION_SECS);
        //duration checks only valid for MP3/AAC formats,
        //do not check duration for other audio formats, e.g. dolby AAC/AC3 and amrwb+ formats
        if (offloadInfo.format == AUDIO_FORMAT_MP3 || offloadInfo.format == AUDIO_FORMAT_AAC)
        if (offloadInfo.format == AUDIO_FORMAT_MP3 || offloadInfo.format == AUDIO_FORMAT_AAC || pcmOffload)
            return false;
    }