Merge "Use default sample rate for only sw effect"
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 7b3b81d..93125aa 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -467,8 +467,15 @@
if (__builtin_mul_overflow(media_time, samplerate, &delay) ||
__builtin_add_overflow(delay, halfscale, &delay) ||
(delay /= mHeaderTimescale, false) ||
- delay > INT32_MAX ||
- delay < INT32_MIN) {
+ /* the calculated delay should be small, but some apps
+ * appear to write a bogus edit list that causes a really
+ * large delay, resulting in playback problems.
+ * Ignore such edit lists.
+ * (4096 is enough to drop 4 full samples)
+ */
+ delay > 4096 ||
+ delay < 0) {
+ ALOGW("ignoring edit list with bogus values");
return;
}
ALOGV("delay = %" PRId64, delay);
diff --git a/media/libaudioclient/AudioEffect.cpp b/media/libaudioclient/AudioEffect.cpp
index b1cb0e7..b40f0db 100644
--- a/media/libaudioclient/AudioEffect.cpp
+++ b/media/libaudioclient/AudioEffect.cpp
@@ -52,6 +52,7 @@
)
: mStatus(NO_INIT), mOpPackageName(opPackageName)
{
+ AutoMutex lock(mConstructLock);
mStatus = set(type, uuid, priority, cbf, user, sessionId, io);
}
@@ -85,6 +86,7 @@
}
}
+ AutoMutex lock(mConstructLock);
mStatus = set(pType, pUuid, priority, cbf, user, sessionId, io);
}
diff --git a/media/libaudioclient/include/media/AudioEffect.h b/media/libaudioclient/include/media/AudioEffect.h
index bfc068b..324bcb9 100644
--- a/media/libaudioclient/include/media/AudioEffect.h
+++ b/media/libaudioclient/include/media/AudioEffect.h
@@ -414,6 +414,7 @@
effect_descriptor_t mDescriptor; // effect descriptor
int32_t mId; // system wide unique effect engine instance ID
Mutex mLock; // Mutex for mEnabled access
+ Mutex mConstructLock; // Mutex for integrality construction
String16 mOpPackageName; // The package name used for app op checks.
@@ -440,12 +441,22 @@
virtual void controlStatusChanged(bool controlGranted) {
sp<AudioEffect> effect = mEffect.promote();
if (effect != 0) {
+ {
+ // Got the mConstructLock means the construction of AudioEffect
+ // has finished, we should release the mConstructLock immediately.
+ AutoMutex lock(effect->mConstructLock);
+ }
effect->controlStatusChanged(controlGranted);
}
}
virtual void enableStatusChanged(bool enabled) {
sp<AudioEffect> effect = mEffect.promote();
if (effect != 0) {
+ {
+ // Got the mConstructLock means the construction of AudioEffect
+ // has finished, we should release the mConstructLock immediately.
+ AutoMutex lock(effect->mConstructLock);
+ }
effect->enableStatusChanged(enabled);
}
}
@@ -456,6 +467,11 @@
void *pReplyData) {
sp<AudioEffect> effect = mEffect.promote();
if (effect != 0) {
+ {
+ // Got the mConstructLock means the construction of AudioEffect
+ // has finished, we should release the mConstructLock immediately.
+ AutoMutex lock(effect->mConstructLock);
+ }
effect->commandExecuted(
cmdCode, cmdSize, pCmdData, replySize, pReplyData);
}
@@ -465,6 +481,11 @@
virtual void binderDied(const wp<IBinder>& /*who*/) {
sp<AudioEffect> effect = mEffect.promote();
if (effect != 0) {
+ {
+ // Got the mConstructLock means the construction of AudioEffect
+ // has finished, we should release the mConstructLock immediately.
+ AutoMutex lock(effect->mConstructLock);
+ }
effect->binderDied();
}
}
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 0361322..20c9d37 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -265,7 +265,9 @@
}
break;
case STOPPING:
- if (stop_l() == NO_ERROR) {
+ // volume control for offload and direct threads must take effect immediately.
+ if (stop_l() == NO_ERROR
+ && !(isVolumeControl() && isOffloadedOrDirect())) {
mDisableWaitCnt = mMaxDisableWaitCnt;
} else {
mDisableWaitCnt = 1; // will cause immediate transition to IDLE
@@ -787,6 +789,16 @@
}
status_t cmdStatus = NO_ERROR;
uint32_t size = sizeof(status_t);
+
+ if (isVolumeControl() && isOffloadedOrDirect()) {
+ sp<EffectChain>chain = mChain.promote();
+ // We have the EffectChain and EffectModule lock, permit a reentrant call to setVolume:
+ // resetVolume_l --> setVolume_l --> EffectModule::setVolume
+ mSetVolumeReentrantTid = gettid();
+ chain->resetVolume_l();
+ mSetVolumeReentrantTid = INVALID_PID;
+ }
+
status_t status = mEffectInterface->command(EFFECT_CMD_DISABLE,
0,
NULL,
@@ -1002,6 +1014,16 @@
}
}
+bool AudioFlinger::EffectModule::isOffloadedOrDirect() const
+{
+ return (mThreadType == ThreadBase::OFFLOAD || mThreadType == ThreadBase::DIRECT);
+}
+
+bool AudioFlinger::EffectModule::isVolumeControlEnabled() const
+{
+ return (isVolumeControl() && (isOffloadedOrDirect() ? isEnabled() : isProcessEnabled()));
+}
+
void AudioFlinger::EffectModule::setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
ALOGVV("setInBuffer %p",(&buffer));
@@ -1100,7 +1122,7 @@
status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
{
- Mutex::Autolock _l(mLock);
+ AutoLockReentrant _l(mLock, mSetVolumeReentrantTid);
if (mStatus != NO_ERROR) {
return mStatus;
}
@@ -1131,6 +1153,18 @@
return status;
}
+void AudioFlinger::EffectChain::setVolumeForOutput_l(uint32_t left, uint32_t right)
+{
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != 0 &&
+ (thread->type() == ThreadBase::OFFLOAD || thread->type() == ThreadBase::DIRECT)) {
+ PlaybackThread *t = (PlaybackThread *)thread.get();
+ float vol_l = (float)left / (1 << 24);
+ float vol_r = (float)right / (1 << 24);
+ t->setVolumeForOutput_l(vol_l, vol_r);
+ }
+}
+
status_t AudioFlinger::EffectModule::setDevice(audio_devices_t device)
{
if (device == AUDIO_DEVICE_NONE) {
@@ -2209,8 +2243,7 @@
// first update volume controller
for (size_t i = size; i > 0; i--) {
- if (mEffects[i - 1]->isProcessEnabled() &&
- (mEffects[i - 1]->desc().flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL) {
+ if (mEffects[i - 1]->isVolumeControlEnabled()) {
ctrlIdx = i - 1;
hasControl = true;
break;
@@ -2256,6 +2289,8 @@
*left = newLeft;
*right = newRight;
+ setVolumeForOutput_l(*left, *right);
+
return hasControl;
}
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 2327bb9..e04ee8e 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -85,6 +85,8 @@
status_t setEnabled_l(bool enabled);
bool isEnabled() const;
bool isProcessEnabled() const;
+ bool isOffloadedOrDirect() const;
+ bool isVolumeControlEnabled() const;
void setInBuffer(const sp<EffectBufferHalInterface>& buffer);
int16_t *inBuffer() const {
@@ -95,7 +97,8 @@
return mOutBuffer != 0 ? reinterpret_cast<int16_t*>(mOutBuffer->ptr()) : NULL;
}
void setChain(const wp<EffectChain>& chain) { mChain = chain; }
- void setThread(const wp<ThreadBase>& thread) { mThread = thread; }
+ void setThread(const wp<ThreadBase>& thread)
+ { mThread = thread; mThreadType = thread.promote()->type(); }
const wp<ThreadBase>& thread() { return mThread; }
status_t addHandle(EffectHandle *handle);
@@ -128,6 +131,9 @@
{ return (mDescriptor.flags & EFFECT_FLAG_HW_ACC_MASK) == 0; }
bool isProcessImplemented() const
{ return (mDescriptor.flags & EFFECT_FLAG_NO_PROCESS) == 0; }
+ bool isVolumeControl() const
+ { return (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK)
+ == EFFECT_FLAG_VOLUME_CTRL; }
status_t setOffloaded(bool offloaded, audio_io_handle_t io);
bool isOffloaded() const;
void addEffectToHal_l();
@@ -150,6 +156,7 @@
mutable Mutex mLock; // mutex for process, commands and handles list protection
wp<ThreadBase> mThread; // parent thread
+ ThreadBase::type_t mThreadType; // parent thread type
wp<EffectChain> mChain; // parent effect chain
const int mId; // this instance unique ID
const audio_session_t mSessionId; // audio session ID
@@ -176,6 +183,24 @@
uint32_t mInChannelCountRequested;
uint32_t mOutChannelCountRequested;
#endif
+
+ class AutoLockReentrant {
+ public:
+ AutoLockReentrant(Mutex& mutex, pid_t allowedTid)
+ : mMutex(gettid() == allowedTid ? nullptr : &mutex)
+ {
+ if (mMutex != nullptr) mMutex->lock();
+ }
+ ~AutoLockReentrant() {
+ if (mMutex != nullptr) mMutex->unlock();
+ }
+ private:
+ Mutex * const mMutex;
+ };
+
+ static constexpr pid_t INVALID_PID = (pid_t)-1;
+ // this tid is allowed to call setVolume() without acquiring the mutex.
+ pid_t mSetVolumeReentrantTid = INVALID_PID;
};
// The EffectHandle class implements the IEffect interface. It provides resources
@@ -403,6 +428,8 @@
void setThread(const sp<ThreadBase>& thread);
+ void setVolumeForOutput_l(uint32_t left, uint32_t right);
+
wp<ThreadBase> mThread; // parent mixer thread
mutable Mutex mLock; // mutex protecting effect list
Vector< sp<EffectModule> > mEffects; // list of effect modules
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index dcad866..4ca50d7 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2286,6 +2286,11 @@
return mStreamTypes[stream].volume;
}
+void AudioFlinger::PlaybackThread::setVolumeForOutput_l(float left, float right) const
+{
+ mOutput->stream->setVolume(left, right);
+}
+
// addTrack_l() must be called with ThreadBase::mLock held
status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
{
@@ -5142,20 +5147,20 @@
mLeftVolFloat = left;
mRightVolFloat = right;
- // Convert volumes from float to 8.24
- uint32_t vl = (uint32_t)(left * (1 << 24));
- uint32_t vr = (uint32_t)(right * (1 << 24));
-
// Delegate volume control to effect in track effect chain if needed
// only one effect chain can be present on DirectOutputThread, so if
// there is one, the track is connected to it
if (!mEffectChains.isEmpty()) {
- mEffectChains[0]->setVolume_l(&vl, &vr);
- left = (float)vl / (1 << 24);
- right = (float)vr / (1 << 24);
+ // if effect chain exists, volume is handled by it.
+ // Convert volumes from float to 8.24
+ uint32_t vl = (uint32_t)(left * (1 << 24));
+ uint32_t vr = (uint32_t)(right * (1 << 24));
+ // Direct/Offload effect chains set output volume in setVolume_l().
+ (void)mEffectChains[0]->setVolume_l(&vl, &vr);
+ } else {
+ // otherwise we directly set the volume.
+ setVolumeForOutput_l(left, right);
}
- status_t result = mOutput->stream->setVolume(left, right);
- ALOGE_IF(result != OK, "Error when setting output stream volume: %d", result);
}
}
}
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 28d4482..ea29455 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -712,6 +712,8 @@
virtual void setStreamMute(audio_stream_type_t stream, bool muted);
virtual float streamVolume(audio_stream_type_t stream) const;
+ void setVolumeForOutput_l(float left, float right) const;
+
sp<Track> createTrack_l(
const sp<AudioFlinger::Client>& client,
audio_stream_type_t streamType,