summaryrefslogtreecommitdiffstats
path: root/services/audioflinger
diff options
context:
space:
mode:
Diffstat (limited to 'services/audioflinger')
-rw-r--r--services/audioflinger/Android.mk22
-rw-r--r--services/audioflinger/AudioFlinger.cpp34
-rw-r--r--services/audioflinger/AudioMixer.cpp13
-rw-r--r--services/audioflinger/AudioMixer.h1
-rw-r--r--services/audioflinger/AudioResampler.cpp25
-rw-r--r--services/audioflinger/AudioResampler.h3
-rw-r--r--services/audioflinger/AudioResamplerQTI.cpp168
-rw-r--r--services/audioflinger/AudioResamplerQTI.h52
-rw-r--r--services/audioflinger/BufferProviders.cpp2
-rw-r--r--services/audioflinger/Effects.cpp21
-rw-r--r--services/audioflinger/FastCapture.cpp2
-rw-r--r--services/audioflinger/Threads.cpp44
-rw-r--r--services/audioflinger/Threads.h1
-rw-r--r--services/audioflinger/Tracks.cpp14
14 files changed, 376 insertions, 26 deletions
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 9b4ba79..474fb46 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -60,6 +60,14 @@ LOCAL_STATIC_LIBRARIES := \
libcpustats \
libmedia_helper
+#QTI Resampler
+ifeq ($(call is-vendor-board-platform,QCOM), true)
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXTN_RESAMPLER)), true)
+LOCAL_CFLAGS += -DQTI_RESAMPLER
+endif
+endif
+#QTI Resampler
+
LOCAL_MODULE:= libaudioflinger
LOCAL_32_BIT_ONLY := true
@@ -123,7 +131,19 @@ LOCAL_C_INCLUDES := \
LOCAL_SHARED_LIBRARIES := \
libcutils \
libdl \
- liblog
+ liblog \
+ libaudioutils
+
+#QTI Resampler
+ifeq ($(call is-vendor-board-platform,QCOM), true)
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXTN_RESAMPLER)), true)
+LOCAL_SRC_FILES_$(TARGET_2ND_ARCH) += AudioResamplerQTI.cpp.arm
+LOCAL_C_INCLUDES_$(TARGET_2ND_ARCH) += $(TARGET_OUT_HEADERS)/mm-audio/audio-src
+LOCAL_SHARED_LIBRARIES_$(TARGET_2ND_ARCH) += libqct_resampler
+LOCAL_CFLAGS_$(TARGET_2ND_ARCH) += -DQTI_RESAMPLER
+endif
+endif
+#QTI Resampler
LOCAL_MODULE := libaudioresampler
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index fab1ef5..1acfaad 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -131,6 +131,14 @@ const char *formatToString(audio_format_t format) {
case AUDIO_FORMAT_OPUS: return "opus";
case AUDIO_FORMAT_AC3: return "ac-3";
case AUDIO_FORMAT_E_AC3: return "e-ac-3";
+ case AUDIO_FORMAT_PCM_OFFLOAD:
+ switch (format) {
+ case AUDIO_FORMAT_PCM_16_BIT_OFFLOAD: return "pcm-16bit-offload";
+ case AUDIO_FORMAT_PCM_24_BIT_OFFLOAD: return "pcm-24bit-offload";
+ default:
+ break;
+ }
+ break;
default:
break;
}
@@ -1053,9 +1061,24 @@ status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8&
}
mHardwareStatus = AUDIO_HW_IDLE;
}
- // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
+
AudioParameter param = AudioParameter(keyValuePairs);
- String8 value;
+ String8 value, key;
+ key = String8("SND_CARD_STATUS");
+ if (param.get(key, value) == NO_ERROR) {
+ ALOGV("Set keySoundCardStatus:%s", value.string());
+ if ((value.find("OFFLINE", 0) != -1) ) {
+ ALOGV("OFFLINE detected - call InvalidateTracks()");
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+ PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
+ if( thread->getOutput()->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ){
+ thread->invalidateTracks(AUDIO_STREAM_MUSIC);
+ }
+ }
+ }
+ }
+
+ // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
if (param.get(String8(AUDIO_PARAMETER_KEY_BT_NREC), value) == NO_ERROR) {
bool btNrecIsOff = (value == AUDIO_PARAMETER_VALUE_OFF);
if (mBtNrecIsOff != btNrecIsOff) {
@@ -1822,7 +1845,11 @@ sp<AudioFlinger::PlaybackThread> AudioFlinger::openOutput_l(audio_module_handle_
|| !isValidPcmSinkFormat(config->format)
|| !isValidPcmSinkChannelMask(config->channel_mask)) {
thread = new DirectOutputThread(this, outputStream, *output, devices, mSystemReady);
- ALOGV("openOutput_l() created direct output: ID %d thread %p", *output, thread);
+ ALOGV("openOutput_l() created direct output: ID %d thread %p ", *output, thread);
+ //Check if this is DirectPCM, if so
+ if (flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
+ thread->mIsDirectPcm = true;
+ }
} else {
thread = new MixerThread(this, outputStream, *output, devices, mSystemReady);
ALOGV("openOutput_l() created mixer output: ID %d thread %p", *output, thread);
@@ -2964,6 +2991,7 @@ void AudioFlinger::dumpTee(int fd, const sp<NBAIO_Source>& source, audio_io_hand
bool firstRead = true;
#define TEE_SINK_READ 1024 // frames per I/O operation
void *buffer = malloc(TEE_SINK_READ * frameSize);
+ CHECK (buffer != NULL);
for (;;) {
size_t count = TEE_SINK_READ;
ssize_t actual = teeSource->read(buffer, count,
diff --git a/services/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp
index 8a9a837..27a2f65 100644
--- a/services/audioflinger/AudioMixer.cpp
+++ b/services/audioflinger/AudioMixer.cpp
@@ -85,6 +85,9 @@ static const bool kUseFloat = true;
// Set to default copy buffer size in frames for input processing.
static const size_t kCopyBufferFrameCount = 256;
+#ifdef QTI_RESAMPLER
+#define QTI_RESAMPLER_MAX_SAMPLERATE 192000
+#endif
namespace android {
// ----------------------------------------------------------------------------
@@ -779,6 +782,13 @@ bool AudioMixer::track_t::setResampler(uint32_t trackSampleRate, uint32_t devSam
// but if none exists, it is the channel count (1 for mono).
const int resamplerChannelCount = downmixerBufferProvider != NULL
? mMixerChannelCount : channelCount;
+#ifdef QTI_RESAMPLER
+ if ((trackSampleRate <= QTI_RESAMPLER_MAX_SAMPLERATE) &&
+ (trackSampleRate > devSampleRate * 2) &&
+ ((devSampleRate == 48000)||(devSampleRate == 44100))) {
+ quality = AudioResampler::QTI_QUALITY;
+ }
+#endif
ALOGVV("Creating resampler:"
" format(%#x) channels(%d) devSampleRate(%u) quality(%d)\n",
mMixerInFormat, resamplerChannelCount, devSampleRate, quality);
@@ -1644,6 +1654,9 @@ void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state,
// Note: In case of later int16_t sink output,
// conversion and clamping is done by memcpy_to_i16_from_float().
} while (--outFrames);
+ //assign fout to out, when no more frames are available, so that 0s
+ //can be filled at the right place
+ out = (int32_t *)fout;
break;
case AUDIO_FORMAT_PCM_16_BIT:
if (CC_UNLIKELY(uint32_t(vl) > UNITY_GAIN_INT || uint32_t(vr) > UNITY_GAIN_INT)) {
diff --git a/services/audioflinger/AudioMixer.h b/services/audioflinger/AudioMixer.h
index 7165c6c..f0ae4ec 100644
--- a/services/audioflinger/AudioMixer.h
+++ b/services/audioflinger/AudioMixer.h
@@ -137,6 +137,7 @@ public:
case AUDIO_FORMAT_PCM_8_BIT:
case AUDIO_FORMAT_PCM_16_BIT:
case AUDIO_FORMAT_PCM_24_BIT_PACKED:
+ case AUDIO_FORMAT_PCM_8_24_BIT:
case AUDIO_FORMAT_PCM_32_BIT:
case AUDIO_FORMAT_PCM_FLOAT:
return true;
diff --git a/services/audioflinger/AudioResampler.cpp b/services/audioflinger/AudioResampler.cpp
index e49b7b1..ab3294a 100644
--- a/services/audioflinger/AudioResampler.cpp
+++ b/services/audioflinger/AudioResampler.cpp
@@ -28,6 +28,10 @@
#include "AudioResamplerCubic.h"
#include "AudioResamplerDyn.h"
+#ifdef QTI_RESAMPLER
+#include "AudioResamplerQTI.h"
+#endif
+
#ifdef __arm__
#define ASM_ARM_RESAMP1 // enable asm optimisation for ResamplerOrder1
#endif
@@ -90,6 +94,9 @@ bool AudioResampler::qualityIsSupported(src_quality quality)
case DYN_LOW_QUALITY:
case DYN_MED_QUALITY:
case DYN_HIGH_QUALITY:
+#ifdef QTI_RESAMPLER
+ case QTI_QUALITY:
+#endif
return true;
default:
return false;
@@ -110,7 +117,11 @@ void AudioResampler::init_routine()
if (*endptr == '\0') {
defaultQuality = (src_quality) l;
ALOGD("forcing AudioResampler quality to %d", defaultQuality);
+#ifdef QTI_RESAMPLER
+ if (defaultQuality < DEFAULT_QUALITY || defaultQuality > QTI_QUALITY) {
+#else
if (defaultQuality < DEFAULT_QUALITY || defaultQuality > DYN_HIGH_QUALITY) {
+#endif
defaultQuality = DEFAULT_QUALITY;
}
}
@@ -129,6 +140,9 @@ uint32_t AudioResampler::qualityMHz(src_quality quality)
case HIGH_QUALITY:
return 20;
case VERY_HIGH_QUALITY:
+#ifdef QTI_RESAMPLER
+ case QTI_QUALITY: //for QTI_QUALITY, currently assuming same as VHQ
+#endif
return 34;
case DYN_LOW_QUALITY:
return 4;
@@ -204,6 +218,11 @@ AudioResampler* AudioResampler::create(audio_format_t format, int inChannelCount
case DYN_HIGH_QUALITY:
quality = DYN_MED_QUALITY;
break;
+#ifdef QTI_RESAMPLER
+ case QTI_QUALITY:
+ quality = DYN_HIGH_QUALITY;
+ break;
+#endif
}
}
pthread_mutex_unlock(&mutex);
@@ -250,6 +269,12 @@ AudioResampler* AudioResampler::create(audio_format_t format, int inChannelCount
}
}
break;
+#ifdef QTI_RESAMPLER
+ case QTI_QUALITY:
+ ALOGV("Create QTI_QUALITY Resampler = %d",quality);
+ resampler = new AudioResamplerQTI(format, inChannelCount, sampleRate);
+ break;
+#endif
}
// initialize resampler
diff --git a/services/audioflinger/AudioResampler.h b/services/audioflinger/AudioResampler.h
index a8e3e6f..6669a85 100644
--- a/services/audioflinger/AudioResampler.h
+++ b/services/audioflinger/AudioResampler.h
@@ -47,6 +47,9 @@ public:
DYN_LOW_QUALITY=5,
DYN_MED_QUALITY=6,
DYN_HIGH_QUALITY=7,
+#ifdef QTI_RESAMPLER
+ QTI_QUALITY=8,
+#endif
};
static const CONSTEXPR float UNITY_GAIN_FLOAT = 1.0f;
diff --git a/services/audioflinger/AudioResamplerQTI.cpp b/services/audioflinger/AudioResamplerQTI.cpp
new file mode 100644
index 0000000..44b741e
--- /dev/null
+++ b/services/audioflinger/AudioResamplerQTI.cpp
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2014, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "AudioResamplerQTI.h"
+#include "QCT_Resampler.h"
+#include <sys/time.h>
+#include <audio_utils/primitives.h>
+
+namespace android {
+AudioResamplerQTI::AudioResamplerQTI(int format,
+ int inChannelCount, int32_t sampleRate)
+ :AudioResampler(inChannelCount, sampleRate, QTI_QUALITY),
+ mOutFrameCount(0), mTmpBuf(0), mResamplerOutBuf(0), mFrameIndex(0)
+{
+ stateSize = QCT_Resampler::MemAlloc(format, inChannelCount, sampleRate, sampleRate);
+ mState = new int16_t[stateSize];
+ mVolume[0] = mVolume[1] = 0;
+ mBuffer.frameCount = 0;
+}
+
+AudioResamplerQTI::~AudioResamplerQTI()
+{
+ if (mState) {
+ delete [] mState;
+ }
+ if (mTmpBuf) {
+ delete [] mTmpBuf;
+ }
+ if(mResamplerOutBuf) {
+ delete [] mResamplerOutBuf;
+ }
+}
+
+size_t AudioResamplerQTI::resample(int32_t* out, size_t outFrameCount,
+ AudioBufferProvider* provider)
+{
+ int16_t vl = mVolume[0];
+ int16_t vr = mVolume[1];
+ int16_t *pBuf;
+
+ size_t inFrameRequest;
+ size_t inFrameCount = getNumInSample(outFrameCount);
+ size_t index = 0;
+ size_t frameIndex = mFrameIndex;
+ size_t out_count = outFrameCount * 2;
+ float *fout = reinterpret_cast<float *>(out);
+
+ if (mChannelCount == 1) {
+ inFrameRequest = inFrameCount;
+ } else {
+ inFrameRequest = inFrameCount * 2;
+ }
+
+ if (mOutFrameCount < outFrameCount) {
+ mOutFrameCount = outFrameCount;
+ if (mTmpBuf) {
+ delete [] mTmpBuf;
+ }
+ if(mResamplerOutBuf) {
+ delete [] mResamplerOutBuf;
+ }
+ mTmpBuf = new int16_t[inFrameRequest + 16];
+ mResamplerOutBuf = new int32_t[out_count];
+ }
+
+ if (mChannelCount == 1) {
+ // buffer is empty, fetch a new one
+ while (index < inFrameCount) {
+ if (!mBuffer.frameCount) {
+ mBuffer.frameCount = inFrameCount;
+ provider->getNextBuffer(&mBuffer);
+ frameIndex = 0;
+ }
+
+ if (mBuffer.raw == NULL) {
+ while (index < inFrameCount) {
+ mTmpBuf[index++] = 0;
+ }
+ QCT_Resampler::Resample90dB(mState, mTmpBuf, mResamplerOutBuf, inFrameCount, outFrameCount);
+ goto resample_exit;
+ }
+
+ mTmpBuf[index++] = clamp16_from_float(*((float *)mBuffer.raw + frameIndex++));
+
+ if (frameIndex >= mBuffer.frameCount) {
+ provider->releaseBuffer(&mBuffer);
+ }
+ }
+
+ QCT_Resampler::Resample90dB(mState, mTmpBuf, mResamplerOutBuf, inFrameCount, outFrameCount);
+ } else {
+ pBuf = &mTmpBuf[inFrameCount];
+ // buffer is empty, fetch a new one
+ while (index < inFrameCount) {
+ if (!mBuffer.frameCount) {
+ mBuffer.frameCount = inFrameCount;
+ provider->getNextBuffer(&mBuffer);
+ frameIndex = 0;
+ }
+ if (mBuffer.raw == NULL) {
+ while (index < inFrameCount) {
+ mTmpBuf[index] = 0;
+ pBuf[index++] = 0;
+ }
+ QCT_Resampler::Resample90dB(mState, mTmpBuf, mResamplerOutBuf, inFrameCount, outFrameCount);
+ goto resample_exit;
+ }
+
+ mTmpBuf[index] = clamp16_from_float(*((float *)mBuffer.raw + frameIndex++));
+ pBuf[index++] = clamp16_from_float(*((float *)mBuffer.raw + frameIndex++));
+ if (frameIndex >= mBuffer.frameCount * 2) {
+ provider->releaseBuffer(&mBuffer);
+ }
+ }
+
+ QCT_Resampler::Resample90dB(mState, mTmpBuf, mResamplerOutBuf, inFrameCount, outFrameCount);
+ }
+
+resample_exit:
+ for (int i = 0; i < out_count; i += 2) {
+ fout[i] += float_from_q4_27(mResamplerOutBuf[i] * vl);
+ fout[i+1] += float_from_q4_27(mResamplerOutBuf[i+1] * vr);
+ }
+
+ mFrameIndex = frameIndex;
+ return index;
+}
+
+void AudioResamplerQTI::setSampleRate(int32_t inSampleRate)
+{
+ if (mInSampleRate != inSampleRate) {
+ mInSampleRate = inSampleRate;
+ init();
+ }
+}
+
+void AudioResamplerQTI::init()
+{
+ QCT_Resampler::Init(mState, mChannelCount, mInSampleRate, mSampleRate);
+}
+
+size_t AudioResamplerQTI::getNumInSample(size_t outFrameCount)
+{
+ size_t size = (size_t)QCT_Resampler::GetNumInSamp(mState, outFrameCount);
+ return size;
+}
+
+void AudioResamplerQTI::reset()
+{
+ AudioResampler::reset();
+}
+
+}; // namespace android
diff --git a/services/audioflinger/AudioResamplerQTI.h b/services/audioflinger/AudioResamplerQTI.h
new file mode 100644
index 0000000..0b30a9f
--- /dev/null
+++ b/services/audioflinger/AudioResamplerQTI.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2014, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <cutils/log.h>
+
+#include "AudioResampler.h"
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+class AudioResamplerQTI : public AudioResampler {
+public:
+ AudioResamplerQTI(int format, int inChannelCount, int32_t sampleRate);
+ ~AudioResamplerQTI();
+ size_t resample(int32_t* out, size_t outFrameCount,
+ AudioBufferProvider* provider);
+ void setSampleRate(int32_t inSampleRate);
+ size_t getNumInSample(size_t outFrameCount);
+
+ int16_t *mState;
+ int16_t *mTmpBuf;
+ int32_t *mResamplerOutBuf;
+ size_t mFrameIndex;
+ size_t stateSize;
+ size_t mOutFrameCount;
+
+ static const int kNumTmpBufSize = 1024;
+
+ void init();
+ void reset();
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
diff --git a/services/audioflinger/BufferProviders.cpp b/services/audioflinger/BufferProviders.cpp
index a8be206..434a514 100644
--- a/services/audioflinger/BufferProviders.cpp
+++ b/services/audioflinger/BufferProviders.cpp
@@ -24,6 +24,7 @@
#include <media/EffectsFactoryApi.h>
#include <utils/Log.h>
+#include <media/stagefright/foundation/ADebug.h>
#include "Configuration.h"
#include "BufferProviders.h"
@@ -205,6 +206,7 @@ DownmixerBufferProvider::DownmixerBufferProvider(
const int downmixParamSize =
sizeof(effect_param_t) + psizePadded + sizeof(downmix_type_t);
effect_param_t * const param = (effect_param_t *) malloc(downmixParamSize);
+ CHECK(param != NULL);
param->psize = sizeof(downmix_params_t);
const downmix_params_t downmixParam = DOWNMIX_PARAM_TYPE;
memcpy(param->data, &downmixParam, param->psize);
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 949c91d..19fc942 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -318,6 +318,7 @@ void AudioFlinger::EffectModule::reset_l()
status_t AudioFlinger::EffectModule::configure()
{
status_t status;
+ status_t cmdStatus = 0;
sp<ThreadBase> thread;
uint32_t size;
audio_channel_mask_t channelMask;
@@ -383,7 +384,6 @@ status_t AudioFlinger::EffectModule::configure()
ALOGV("configure() %p thread %p buffer %p framecount %d",
this, thread.get(), mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);
- status_t cmdStatus;
size = sizeof(int);
status = (*mEffectInterface)->command(mEffectInterface,
EFFECT_CMD_SET_CONFIG,
@@ -434,7 +434,7 @@ status_t AudioFlinger::EffectModule::init()
if (mEffectInterface == NULL) {
return NO_INIT;
}
- status_t cmdStatus;
+ status_t cmdStatus = 0;
uint32_t size = sizeof(status_t);
status_t status = (*mEffectInterface)->command(mEffectInterface,
EFFECT_CMD_INIT,
@@ -476,7 +476,7 @@ status_t AudioFlinger::EffectModule::start_l()
if (mStatus != NO_ERROR) {
return mStatus;
}
- status_t cmdStatus;
+ status_t cmdStatus = 0;
uint32_t size = sizeof(status_t);
status_t status = (*mEffectInterface)->command(mEffectInterface,
EFFECT_CMD_ENABLE,
@@ -677,7 +677,7 @@ status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right,
if (isProcessEnabled() &&
((mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL ||
(mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_IND)) {
- status_t cmdStatus;
+ status_t cmdStatus = 0;
uint32_t volume[2];
uint32_t *pVolume = NULL;
uint32_t size = sizeof(volume);
@@ -712,7 +712,7 @@ status_t AudioFlinger::EffectModule::setDevice(audio_devices_t device)
}
status_t status = NO_ERROR;
if ((mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
- status_t cmdStatus;
+ status_t cmdStatus = 0;
uint32_t size = sizeof(status_t);
uint32_t cmd = audio_is_output_devices(device) ? EFFECT_CMD_SET_DEVICE :
EFFECT_CMD_SET_INPUT_DEVICE;
@@ -734,7 +734,7 @@ status_t AudioFlinger::EffectModule::setMode(audio_mode_t mode)
}
status_t status = NO_ERROR;
if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_MODE_MASK) == EFFECT_FLAG_AUDIO_MODE_IND) {
- status_t cmdStatus;
+ status_t cmdStatus = 0;
uint32_t size = sizeof(status_t);
status = (*mEffectInterface)->command(mEffectInterface,
EFFECT_CMD_SET_AUDIO_MODE,
@@ -1113,7 +1113,8 @@ status_t AudioFlinger::EffectHandle::enable()
mEnabled = false;
} else {
if (thread != 0) {
- if (thread->type() == ThreadBase::OFFLOAD) {
+ if ((thread->type() == ThreadBase::OFFLOAD) ||
+ (thread->type() == ThreadBase::DIRECT && thread->mIsDirectPcm)) {
PlaybackThread *t = (PlaybackThread *)thread.get();
Mutex::Autolock _l(t->mLock);
t->broadcast_l();
@@ -1461,14 +1462,14 @@ void AudioFlinger::EffectChain::process_l()
}
size_t size = mEffects.size();
+ for (size_t i = 0; i < size; i++) {
+ mEffects[i]->updateState();
+ }
if (doProcess) {
for (size_t i = 0; i < size; i++) {
mEffects[i]->process();
}
}
- for (size_t i = 0; i < size; i++) {
- mEffects[i]->updateState();
- }
}
// addEffect_l() must be called with PlaybackThread::mLock held
diff --git a/services/audioflinger/FastCapture.cpp b/services/audioflinger/FastCapture.cpp
index 1bba5f6..2493fb7 100644
--- a/services/audioflinger/FastCapture.cpp
+++ b/services/audioflinger/FastCapture.cpp
@@ -105,7 +105,7 @@ void FastCapture::onStateChange()
mFormat = mInputSource->format();
mSampleRate = Format_sampleRate(mFormat);
unsigned channelCount = Format_channelCount(mFormat);
- ALOG_ASSERT(channelCount >= 1 && channelCount <= FCC_8);
+ ALOG_ASSERT(channelCount >= 1 && channelCount <= 8);
}
dumpState->mSampleRate = mSampleRate;
eitherChanged = true;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 71fc498..e80221e 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -544,6 +544,7 @@ AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio
mSystemReady(systemReady)
{
memset(&mPatch, 0, sizeof(struct audio_patch));
+ mIsDirectPcm = false;
}
AudioFlinger::ThreadBase::~ThreadBase()
@@ -1154,7 +1155,8 @@ sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l(
// Reject any effect on Direct output threads for now, since the format of
// mSinkBuffer is not guaranteed to be compatible with effect processing (PCM 16 stereo).
- if (mType == DIRECT) {
+ // Exception: allow effects for Direct PCM
+ if (mType == DIRECT && !mIsDirectPcm) {
ALOGW("createEffect_l() Cannot add effect %s on Direct output type thread %s",
desc->name, mThreadName);
lStatus = BAD_VALUE;
@@ -1163,7 +1165,7 @@ sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l(
// Reject any effect on mixer or duplicating multichannel sinks.
// TODO: fix both format and multichannel issues with effects.
- if ((mType == MIXER || mType == DUPLICATING) && mChannelCount != FCC_2) {
+ if ((mType == MIXER || mType == DUPLICATING) && mChannelCount > FCC_2) {
ALOGW("createEffect_l() Cannot add effect %s for multichannel(%d) %s threads",
desc->name, mChannelCount, mType == MIXER ? "MIXER" : "DUPLICATING");
lStatus = BAD_VALUE;
@@ -1171,12 +1173,17 @@ sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l(
}
// Allow global effects only on offloaded and mixer threads
+ // Exception: allow effects for Direct PCM
if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
switch (mType) {
case MIXER:
case OFFLOAD:
break;
case DIRECT:
+ if (mIsDirectPcm) {
+ // Allow effects when direct PCM enabled on Direct output
+ break;
+ }
case DUPLICATING:
case RECORD:
default:
@@ -1229,7 +1236,13 @@ sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l(
if (lStatus != NO_ERROR) {
goto Exit;
}
- effect->setOffloaded(mType == OFFLOAD, mId);
+
+ bool setVal = false;
+ if (mType == OFFLOAD || (mType == DIRECT && mIsDirectPcm)) {
+ setVal = true;
+ }
+
+ effect->setOffloaded(setVal, mId);
lStatus = chain->addEffect_l(effect);
if (lStatus != NO_ERROR) {
@@ -1313,7 +1326,13 @@ status_t AudioFlinger::ThreadBase::addEffect_l(const sp<EffectModule>& effect)
return BAD_VALUE;
}
- effect->setOffloaded(mType == OFFLOAD, mId);
+ bool setval = false;
+
+ if ((mType == OFFLOAD) || (mType == DIRECT && mIsDirectPcm)) {
+ setval = true;
+ }
+
+ effect->setOffloaded(setval, mId);
status_t status = chain->addEffect_l(effect);
if (status != NO_ERROR) {
@@ -2971,8 +2990,9 @@ bool AudioFlinger::PlaybackThread::threadLoop()
// the app won't fill fast enough to handle the sudden draw).
const int32_t deltaMs = delta / 1000000;
- const int32_t throttleMs = mHalfBufferMs - deltaMs;
- if ((signed)mHalfBufferMs >= throttleMs && throttleMs > 0) {
+ const int32_t halfBufferMs = mHalfBufferMs / (mEffectBufferValid ? 4 : 1);
+ const int32_t throttleMs = halfBufferMs - deltaMs;
+ if ((signed)halfBufferMs >= throttleMs && throttleMs > 0) {
usleep(throttleMs * 1000);
// notify of throttle start on verbose log
ALOGV_IF(mThreadThrottleEndMs == mThreadThrottleTimeMs,
@@ -3300,11 +3320,15 @@ AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, Aud
}
if (initFastMixer) {
audio_format_t fastMixerFormat;
+#ifdef LEGACY_ALSA_AUDIO
+ fastMixerFormat = AUDIO_FORMAT_PCM_16_BIT;
+#else
if (mMixerBufferEnabled && mEffectBufferEnabled) {
fastMixerFormat = AUDIO_FORMAT_PCM_FLOAT;
} else {
fastMixerFormat = AUDIO_FORMAT_PCM_16_BIT;
}
+#endif
if (mFormat != fastMixerFormat) {
// change our Sink format to accept our intermediate precision
mFormat = fastMixerFormat;
@@ -5295,6 +5319,8 @@ void AudioFlinger::DuplicatingThread::threadLoop_mix()
} else {
if (mMixerBufferValid) {
memset(mMixerBuffer, 0, mMixerBufferSize);
+ } else if (mEffectBufferValid) {
+ memset(mEffectBuffer, 0, mEffectBufferSize);
} else {
memset(mSinkBuffer, 0, mSinkBufferSize);
}
@@ -5316,7 +5342,11 @@ void AudioFlinger::DuplicatingThread::threadLoop_sleepTime()
} else if (mBytesWritten != 0) {
if (mMixerStatus == MIXER_TRACKS_ENABLED) {
writeFrames = mNormalFrameCount;
- memset(mSinkBuffer, 0, mSinkBufferSize);
+ if (mMixerBufferValid) {
+ memset(mMixerBuffer, 0, mMixerBufferSize);
+ } else {
+ memset(mSinkBuffer, 0, mSinkBufferSize);
+ }
} else {
// flush remaining overflow buffers in output tracks
writeFrames = 0;
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 46ac300..9e32ea1 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -457,6 +457,7 @@ protected:
static const size_t kLogSize = 4 * 1024;
sp<NBLog::Writer> mNBLogWriter;
bool mSystemReady;
+ bool mIsDirectPcm; // flag to indicate unique Direct thread
};
// --- PlaybackThread ---
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 0e24b52..f3b5375 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -24,6 +24,7 @@
#include <math.h>
#include <sys/syscall.h>
#include <utils/Log.h>
+#include <media/stagefright/foundation/ADebug.h>
#include <private/media/AudioTrackShared.h>
@@ -706,10 +707,11 @@ status_t AudioFlinger::PlaybackThread::Track::start(AudioSystem::sync_event_t ev
mState = state;
}
}
- // track was already in the active list, not a problem
- if (status == ALREADY_EXISTS) {
- status = NO_ERROR;
- } else {
+ // If track was already in the active list, not a problem unless
+ // track is fast and sharedBuffer is used and frameReady has already become 0.
+ // In such case we need to call obtainbuffer() to refresh the framesReady value.
+ if ((status != ALREADY_EXISTS) ||
+ (isFastTrack() && (mSharedBuffer != 0) && (framesReady() == 0))) {
// Acknowledge any pending flush(), so that subsequent new data isn't discarded.
// It is usually unsafe to access the server proxy from a binder thread.
// But in this case we know the mixer thread (whether normal mixer or fast mixer)
@@ -720,6 +722,9 @@ status_t AudioFlinger::PlaybackThread::Track::start(AudioSystem::sync_event_t ev
buffer.mFrameCount = 1;
(void) mAudioTrackServerProxy->obtainBuffer(&buffer, true /*ackFlush*/);
}
+
+ if (status == ALREADY_EXISTS)
+ status = NO_ERROR;
} else {
status = BAD_VALUE;
}
@@ -1775,6 +1780,7 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(void* data, uint32_t frame
if (mBufferQueue.size() < kMaxOverFlowBuffers) {
pInBuffer = new Buffer;
pInBuffer->mBuffer = malloc(inBuffer.frameCount * mFrameSize);
+ CHECK(pInBuffer->mBuffer != NULL);
pInBuffer->frameCount = inBuffer.frameCount;
pInBuffer->raw = pInBuffer->mBuffer;
memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * mFrameSize);