summaryrefslogtreecommitdiffstats
path: root/services/audioflinger/AudioMixer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'services/audioflinger/AudioMixer.cpp')
-rw-r--r--services/audioflinger/AudioMixer.cpp321
1 files changed, 1 insertions, 320 deletions
diff --git a/services/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp
index dddca02..cb90ece 100644
--- a/services/audioflinger/AudioMixer.cpp
+++ b/services/audioflinger/AudioMixer.cpp
@@ -38,9 +38,7 @@
#include <audio_utils/format.h>
#include <common_time/local_clock.h>
#include <common_time/cc_helper.h>
-
-#include <media/EffectsFactoryApi.h>
-#include <audio_effects/effect_downmix.h>
+#include <media/AudioResamplerPublic.h>
#include "AudioMixerOps.h"
#include "AudioMixer.h"
@@ -91,323 +89,6 @@ T min(const T& a, const T& b)
return a < b ? a : b;
}
-AudioMixer::CopyBufferProvider::CopyBufferProvider(size_t inputFrameSize,
- size_t outputFrameSize, size_t bufferFrameCount) :
- mInputFrameSize(inputFrameSize),
- mOutputFrameSize(outputFrameSize),
- mLocalBufferFrameCount(bufferFrameCount),
- mLocalBufferData(NULL),
- mConsumed(0)
-{
- ALOGV("CopyBufferProvider(%p)(%zu, %zu, %zu)", this,
- inputFrameSize, outputFrameSize, bufferFrameCount);
- LOG_ALWAYS_FATAL_IF(inputFrameSize < outputFrameSize && bufferFrameCount == 0,
- "Requires local buffer if inputFrameSize(%zu) < outputFrameSize(%zu)",
- inputFrameSize, outputFrameSize);
- if (mLocalBufferFrameCount) {
- (void)posix_memalign(&mLocalBufferData, 32, mLocalBufferFrameCount * mOutputFrameSize);
- }
- mBuffer.frameCount = 0;
-}
-
-AudioMixer::CopyBufferProvider::~CopyBufferProvider()
-{
- ALOGV("~CopyBufferProvider(%p)", this);
- if (mBuffer.frameCount != 0) {
- mTrackBufferProvider->releaseBuffer(&mBuffer);
- }
- free(mLocalBufferData);
-}
-
-status_t AudioMixer::CopyBufferProvider::getNextBuffer(AudioBufferProvider::Buffer *pBuffer,
- int64_t pts)
-{
- //ALOGV("CopyBufferProvider(%p)::getNextBuffer(%p (%zu), %lld)",
- // this, pBuffer, pBuffer->frameCount, pts);
- if (mLocalBufferFrameCount == 0) {
- status_t res = mTrackBufferProvider->getNextBuffer(pBuffer, pts);
- if (res == OK) {
- copyFrames(pBuffer->raw, pBuffer->raw, pBuffer->frameCount);
- }
- return res;
- }
- if (mBuffer.frameCount == 0) {
- mBuffer.frameCount = pBuffer->frameCount;
- status_t res = mTrackBufferProvider->getNextBuffer(&mBuffer, pts);
- // At one time an upstream buffer provider had
- // res == OK and mBuffer.frameCount == 0, doesn't seem to happen now 7/18/2014.
- //
- // By API spec, if res != OK, then mBuffer.frameCount == 0.
- // but there may be improper implementations.
- ALOG_ASSERT(res == OK || mBuffer.frameCount == 0);
- if (res != OK || mBuffer.frameCount == 0) { // not needed by API spec, but to be safe.
- pBuffer->raw = NULL;
- pBuffer->frameCount = 0;
- return res;
- }
- mConsumed = 0;
- }
- ALOG_ASSERT(mConsumed < mBuffer.frameCount);
- size_t count = min(mLocalBufferFrameCount, mBuffer.frameCount - mConsumed);
- count = min(count, pBuffer->frameCount);
- pBuffer->raw = mLocalBufferData;
- pBuffer->frameCount = count;
- copyFrames(pBuffer->raw, (uint8_t*)mBuffer.raw + mConsumed * mInputFrameSize,
- pBuffer->frameCount);
- return OK;
-}
-
-void AudioMixer::CopyBufferProvider::releaseBuffer(AudioBufferProvider::Buffer *pBuffer)
-{
- //ALOGV("CopyBufferProvider(%p)::releaseBuffer(%p(%zu))",
- // this, pBuffer, pBuffer->frameCount);
- if (mLocalBufferFrameCount == 0) {
- mTrackBufferProvider->releaseBuffer(pBuffer);
- return;
- }
- // LOG_ALWAYS_FATAL_IF(pBuffer->frameCount == 0, "Invalid framecount");
- mConsumed += pBuffer->frameCount; // TODO: update for efficiency to reuse existing content
- if (mConsumed != 0 && mConsumed >= mBuffer.frameCount) {
- mTrackBufferProvider->releaseBuffer(&mBuffer);
- ALOG_ASSERT(mBuffer.frameCount == 0);
- }
- pBuffer->raw = NULL;
- pBuffer->frameCount = 0;
-}
-
-void AudioMixer::CopyBufferProvider::reset()
-{
- if (mBuffer.frameCount != 0) {
- mTrackBufferProvider->releaseBuffer(&mBuffer);
- }
- mConsumed = 0;
-}
-
-AudioMixer::DownmixerBufferProvider::DownmixerBufferProvider(
- audio_channel_mask_t inputChannelMask,
- audio_channel_mask_t outputChannelMask, audio_format_t format,
- uint32_t sampleRate, int32_t sessionId, size_t bufferFrameCount) :
- CopyBufferProvider(
- audio_bytes_per_sample(format) * audio_channel_count_from_out_mask(inputChannelMask),
- audio_bytes_per_sample(format) * audio_channel_count_from_out_mask(outputChannelMask),
- bufferFrameCount) // set bufferFrameCount to 0 to do in-place
-{
- ALOGV("DownmixerBufferProvider(%p)(%#x, %#x, %#x %u %d)",
- this, inputChannelMask, outputChannelMask, format,
- sampleRate, sessionId);
- if (!sIsMultichannelCapable
- || EffectCreate(&sDwnmFxDesc.uuid,
- sessionId,
- SESSION_ID_INVALID_AND_IGNORED,
- &mDownmixHandle) != 0) {
- ALOGE("DownmixerBufferProvider() error creating downmixer effect");
- mDownmixHandle = NULL;
- return;
- }
- // channel input configuration will be overridden per-track
- mDownmixConfig.inputCfg.channels = inputChannelMask; // FIXME: Should be bits
- mDownmixConfig.outputCfg.channels = outputChannelMask; // FIXME: should be bits
- mDownmixConfig.inputCfg.format = format;
- mDownmixConfig.outputCfg.format = format;
- mDownmixConfig.inputCfg.samplingRate = sampleRate;
- mDownmixConfig.outputCfg.samplingRate = sampleRate;
- mDownmixConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
- mDownmixConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
- // input and output buffer provider, and frame count will not be used as the downmix effect
- // process() function is called directly (see DownmixerBufferProvider::getNextBuffer())
- mDownmixConfig.inputCfg.mask = EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS |
- EFFECT_CONFIG_FORMAT | EFFECT_CONFIG_ACC_MODE;
- mDownmixConfig.outputCfg.mask = mDownmixConfig.inputCfg.mask;
-
- int cmdStatus;
- uint32_t replySize = sizeof(int);
-
- // Configure downmixer
- status_t status = (*mDownmixHandle)->command(mDownmixHandle,
- EFFECT_CMD_SET_CONFIG /*cmdCode*/, sizeof(effect_config_t) /*cmdSize*/,
- &mDownmixConfig /*pCmdData*/,
- &replySize, &cmdStatus /*pReplyData*/);
- if (status != 0 || cmdStatus != 0) {
- ALOGE("DownmixerBufferProvider() error %d cmdStatus %d while configuring downmixer",
- status, cmdStatus);
- EffectRelease(mDownmixHandle);
- mDownmixHandle = NULL;
- return;
- }
-
- // Enable downmixer
- replySize = sizeof(int);
- status = (*mDownmixHandle)->command(mDownmixHandle,
- EFFECT_CMD_ENABLE /*cmdCode*/, 0 /*cmdSize*/, NULL /*pCmdData*/,
- &replySize, &cmdStatus /*pReplyData*/);
- if (status != 0 || cmdStatus != 0) {
- ALOGE("DownmixerBufferProvider() error %d cmdStatus %d while enabling downmixer",
- status, cmdStatus);
- EffectRelease(mDownmixHandle);
- mDownmixHandle = NULL;
- return;
- }
-
- // Set downmix type
- // parameter size rounded for padding on 32bit boundary
- const int psizePadded = ((sizeof(downmix_params_t) - 1)/sizeof(int) + 1) * sizeof(int);
- const int downmixParamSize =
- sizeof(effect_param_t) + psizePadded + sizeof(downmix_type_t);
- effect_param_t * const param = (effect_param_t *) malloc(downmixParamSize);
- param->psize = sizeof(downmix_params_t);
- const downmix_params_t downmixParam = DOWNMIX_PARAM_TYPE;
- memcpy(param->data, &downmixParam, param->psize);
- const downmix_type_t downmixType = DOWNMIX_TYPE_FOLD;
- param->vsize = sizeof(downmix_type_t);
- memcpy(param->data + psizePadded, &downmixType, param->vsize);
- replySize = sizeof(int);
- status = (*mDownmixHandle)->command(mDownmixHandle,
- EFFECT_CMD_SET_PARAM /* cmdCode */, downmixParamSize /* cmdSize */,
- param /*pCmdData*/, &replySize, &cmdStatus /*pReplyData*/);
- free(param);
- if (status != 0 || cmdStatus != 0) {
- ALOGE("DownmixerBufferProvider() error %d cmdStatus %d while setting downmix type",
- status, cmdStatus);
- EffectRelease(mDownmixHandle);
- mDownmixHandle = NULL;
- return;
- }
- ALOGV("DownmixerBufferProvider() downmix type set to %d", (int) downmixType);
-}
-
-AudioMixer::DownmixerBufferProvider::~DownmixerBufferProvider()
-{
- ALOGV("~DownmixerBufferProvider (%p)", this);
- EffectRelease(mDownmixHandle);
- mDownmixHandle = NULL;
-}
-
-void AudioMixer::DownmixerBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
-{
- mDownmixConfig.inputCfg.buffer.frameCount = frames;
- mDownmixConfig.inputCfg.buffer.raw = const_cast<void *>(src);
- mDownmixConfig.outputCfg.buffer.frameCount = frames;
- mDownmixConfig.outputCfg.buffer.raw = dst;
- // may be in-place if src == dst.
- status_t res = (*mDownmixHandle)->process(mDownmixHandle,
- &mDownmixConfig.inputCfg.buffer, &mDownmixConfig.outputCfg.buffer);
- ALOGE_IF(res != OK, "DownmixBufferProvider error %d", res);
-}
-
-/* call once in a pthread_once handler. */
-/*static*/ status_t AudioMixer::DownmixerBufferProvider::init()
-{
- // find multichannel downmix effect if we have to play multichannel content
- uint32_t numEffects = 0;
- int ret = EffectQueryNumberEffects(&numEffects);
- if (ret != 0) {
- ALOGE("AudioMixer() error %d querying number of effects", ret);
- return NO_INIT;
- }
- ALOGV("EffectQueryNumberEffects() numEffects=%d", numEffects);
-
- for (uint32_t i = 0 ; i < numEffects ; i++) {
- if (EffectQueryEffect(i, &sDwnmFxDesc) == 0) {
- ALOGV("effect %d is called %s", i, sDwnmFxDesc.name);
- if (memcmp(&sDwnmFxDesc.type, EFFECT_UIID_DOWNMIX, sizeof(effect_uuid_t)) == 0) {
- ALOGI("found effect \"%s\" from %s",
- sDwnmFxDesc.name, sDwnmFxDesc.implementor);
- sIsMultichannelCapable = true;
- break;
- }
- }
- }
- ALOGW_IF(!sIsMultichannelCapable, "unable to find downmix effect");
- return NO_INIT;
-}
-
-/*static*/ bool AudioMixer::DownmixerBufferProvider::sIsMultichannelCapable = false;
-/*static*/ effect_descriptor_t AudioMixer::DownmixerBufferProvider::sDwnmFxDesc;
-
-AudioMixer::RemixBufferProvider::RemixBufferProvider(audio_channel_mask_t inputChannelMask,
- audio_channel_mask_t outputChannelMask, audio_format_t format,
- size_t bufferFrameCount) :
- CopyBufferProvider(
- audio_bytes_per_sample(format)
- * audio_channel_count_from_out_mask(inputChannelMask),
- audio_bytes_per_sample(format)
- * audio_channel_count_from_out_mask(outputChannelMask),
- bufferFrameCount),
- mFormat(format),
- mSampleSize(audio_bytes_per_sample(format)),
- mInputChannels(audio_channel_count_from_out_mask(inputChannelMask)),
- mOutputChannels(audio_channel_count_from_out_mask(outputChannelMask))
-{
- ALOGV("RemixBufferProvider(%p)(%#x, %#x, %#x) %zu %zu",
- this, format, inputChannelMask, outputChannelMask,
- mInputChannels, mOutputChannels);
-
- const audio_channel_representation_t inputRepresentation =
- audio_channel_mask_get_representation(inputChannelMask);
- const audio_channel_representation_t outputRepresentation =
- audio_channel_mask_get_representation(outputChannelMask);
- const uint32_t inputBits = audio_channel_mask_get_bits(inputChannelMask);
- const uint32_t outputBits = audio_channel_mask_get_bits(outputChannelMask);
-
- switch (inputRepresentation) {
- case AUDIO_CHANNEL_REPRESENTATION_POSITION:
- switch (outputRepresentation) {
- case AUDIO_CHANNEL_REPRESENTATION_POSITION:
- memcpy_by_index_array_initialization(mIdxAry, ARRAY_SIZE(mIdxAry),
- outputBits, inputBits);
- return;
- case AUDIO_CHANNEL_REPRESENTATION_INDEX:
- // TODO: output channel index mask not currently allowed
- // fall through
- default:
- break;
- }
- break;
- case AUDIO_CHANNEL_REPRESENTATION_INDEX:
- switch (outputRepresentation) {
- case AUDIO_CHANNEL_REPRESENTATION_POSITION:
- memcpy_by_index_array_initialization_src_index(mIdxAry, ARRAY_SIZE(mIdxAry),
- outputBits, inputBits);
- return;
- case AUDIO_CHANNEL_REPRESENTATION_INDEX:
- // TODO: output channel index mask not currently allowed
- // fall through
- default:
- break;
- }
- break;
- default:
- break;
- }
- LOG_ALWAYS_FATAL("invalid channel mask conversion from %#x to %#x",
- inputChannelMask, outputChannelMask);
-}
-
-void AudioMixer::RemixBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
-{
- memcpy_by_index_array(dst, mOutputChannels,
- src, mInputChannels, mIdxAry, mSampleSize, frames);
-}
-
-AudioMixer::ReformatBufferProvider::ReformatBufferProvider(int32_t channels,
- audio_format_t inputFormat, audio_format_t outputFormat,
- size_t bufferFrameCount) :
- CopyBufferProvider(
- channels * audio_bytes_per_sample(inputFormat),
- channels * audio_bytes_per_sample(outputFormat),
- bufferFrameCount),
- mChannels(channels),
- mInputFormat(inputFormat),
- mOutputFormat(outputFormat)
-{
- ALOGV("ReformatBufferProvider(%p)(%d, %#x, %#x)", this, channels, inputFormat, outputFormat);
-}
-
-void AudioMixer::ReformatBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
-{
- memcpy_by_audio_format(dst, mOutputFormat, src, mInputFormat, frames * mChannels);
-}
-
// ----------------------------------------------------------------------------
// Ensure mConfiguredNames bitmask is initialized properly on all architectures.