hal: Add support for PCM in offload path
- Translate PCM Offload format to pcm codec id - Set 16/24 sub format id in compress params format - Calculate offload fragment size for pcm - Move offload calculation functions to platform file - Update audio policy manager isOffloadSupported for pcm offload profile. Use audio.offload.pcm.enable Change-Id: I2064d646b66e8283fce2cc736e96fb93cba0a552
This commit is contained in:
parent
c4ad7c0214
commit
c6a3a9e6ed
|
@ -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,8 +183,10 @@ 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)
|
||||
return true;
|
||||
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);
|
||||
}
|
||||
|
@ -2161,8 +2136,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;
|
||||
|
||||
|
@ -2179,7 +2156,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);
|
||||
|
@ -2190,6 +2173,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;
|
||||
|
||||
|
|
|
@ -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:
|
||||
*
|
||||
|
@ -1694,3 +1712,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;
|
||||
}
|
||||
|
||||
|
|
|
@ -62,4 +62,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
|
||||
|
|
|
@ -1116,16 +1116,6 @@ bool AudioPolicyManager::isOffloadSupported(const audio_offload_info_t& offloadI
|
|||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check if offload has been disabled
|
||||
char propValue[PROPERTY_VALUE_MAX];
|
||||
if (property_get("audio.offload.disable", propValue, "0")) {
|
||||
if (atoi(propValue) != 0) {
|
||||
ALOGV("offload disabled by audio.offload.disable=%s", propValue );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if stream type is music, then only allow offload as of now.
|
||||
if (offloadInfo.stream_type != AUDIO_STREAM_MUSIC)
|
||||
{
|
||||
|
@ -1133,26 +1123,65 @@ bool AudioPolicyManager::isOffloadSupported(const audio_offload_info_t& offloadI
|
|||
return false;
|
||||
}
|
||||
|
||||
//TODO: enable audio offloading with video when ready
|
||||
if (offloadInfo.has_video)
|
||||
{
|
||||
if(property_get("av.offload.enable", propValue, NULL)) {
|
||||
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("offload disabled by av.offload.enable = %s ", propValue );
|
||||
return false;
|
||||
if (prop_enabled) {
|
||||
ALOGW("PCM offload property is enabled");
|
||||
pcmOffload = true;
|
||||
}
|
||||
}
|
||||
if(offloadInfo.is_streaming &&
|
||||
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;
|
||||
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 );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ALOGV("isOffloadSupported: has_video == true, property\
|
||||
set to enable offload");
|
||||
|
||||
//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;
|
||||
}
|
||||
|
||||
if (offloadInfo.has_video)
|
||||
{
|
||||
if(property_get("av.offload.enable", propValue, NULL)) {
|
||||
bool prop_enabled = atoi(propValue) || !strncmp("true", propValue, 4);
|
||||
if (!prop_enabled) {
|
||||
ALOGW("offload disabled by av.offload.enable = %s ", propValue );
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue