Don't use control block frame count after create
This is part of a series to clean up the control block.
Change-Id: I7f4cb05aef63053f8e2ab05b286d302260ef4758
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 979ee37..0be5534 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -257,6 +257,7 @@
mVolume[RIGHT] = 1.0f;
mSendLevel = 0.0f;
mFrameCount = frameCount;
+ mReqFrameCount = frameCount;
mNotificationFramesReq = notificationFrames;
mSessionId = sessionId;
mAuxEffectId = 0;
@@ -344,7 +345,7 @@
size_t AudioTrack::frameCount() const
{
- return mCblk->frameCount;
+ return mFrameCount;
}
sp<IMemory>& AudioTrack::sharedBuffer()
@@ -596,17 +597,17 @@
}
if (loopStart >= loopEnd ||
- loopEnd - loopStart > cblk->frameCount ||
+ loopEnd - loopStart > mFrameCount ||
cblk->server > loopStart) {
ALOGE("setLoop invalid value: loopStart %d, loopEnd %d, loopCount %d, framecount %d, "
- "user %d", loopStart, loopEnd, loopCount, cblk->frameCount, cblk->user);
+ "user %d", loopStart, loopEnd, loopCount, mFrameCount, cblk->user);
return BAD_VALUE;
}
- if ((mSharedBuffer != 0) && (loopEnd > cblk->frameCount)) {
+ if ((mSharedBuffer != 0) && (loopEnd > mFrameCount)) {
ALOGE("setLoop invalid value: loop markers beyond data: loopStart %d, loopEnd %d, "
"framecount %d",
- loopStart, loopEnd, cblk->frameCount);
+ loopStart, loopEnd, mFrameCount);
return BAD_VALUE;
}
@@ -695,7 +696,7 @@
flush_l();
audio_track_cblk_t* cblk = mCblk;
- cblk->stepUserOut(cblk->frameCount);
+ cblk->stepUserOut(mFrameCount, mFrameCount);
return NO_ERROR;
}
@@ -889,17 +890,25 @@
mCblkMemory = iMem;
audio_track_cblk_t* cblk = static_cast<audio_track_cblk_t*>(iMem->pointer());
mCblk = cblk;
+ size_t temp = cblk->frameCount_;
+ if (temp < frameCount || (frameCount == 0 && temp == 0)) {
+ // In current design, AudioTrack client checks and ensures frame count validity before
+ // passing it to AudioFlinger so AudioFlinger should not return a different value except
+ // for fast track as it uses a special method of assigning frame count.
+ ALOGW("Requested frameCount %u but received frameCount %u", frameCount, temp);
+ }
+ frameCount = temp;
if (flags & AUDIO_OUTPUT_FLAG_FAST) {
if (trackFlags & IAudioFlinger::TRACK_FAST) {
- ALOGV("AUDIO_OUTPUT_FLAG_FAST successful; frameCount %u", cblk->frameCount);
+ ALOGV("AUDIO_OUTPUT_FLAG_FAST successful; frameCount %u", frameCount);
} else {
- ALOGV("AUDIO_OUTPUT_FLAG_FAST denied by server; frameCount %u", cblk->frameCount);
+ ALOGV("AUDIO_OUTPUT_FLAG_FAST denied by server; frameCount %u", frameCount);
// once denied, do not request again if IAudioTrack is re-created
flags = (audio_output_flags_t) (flags & ~AUDIO_OUTPUT_FLAG_FAST);
mFlags = flags;
}
if (sharedBuffer == 0) {
- mNotificationFramesAct = cblk->frameCount/2;
+ mNotificationFramesAct = frameCount/2;
}
}
if (sharedBuffer == 0) {
@@ -907,7 +916,7 @@
} else {
mBuffers = sharedBuffer->pointer();
// Force buffer full condition as data is already present in shared memory
- cblk->stepUserOut(cblk->frameCount);
+ cblk->stepUserOut(frameCount, frameCount);
}
cblk->setVolumeLR((uint32_t(uint16_t(mVolume[RIGHT] * 0x1000)) << 16) |
@@ -918,11 +927,12 @@
cblk->waitTimeMs = 0;
mRemainingFrames = mNotificationFramesAct;
// FIXME don't believe this lie
- mLatency = afLatency + (1000*cblk->frameCount) / sampleRate;
+ mLatency = afLatency + (1000*frameCount) / sampleRate;
+ mFrameCount = frameCount;
// If IAudioTrack is re-created, don't let the requested frameCount
// decrease. This can confuse clients that cache frameCount().
- if (cblk->frameCount > mFrameCount) {
- mFrameCount = cblk->frameCount;
+ if (frameCount > mReqFrameCount) {
+ mReqFrameCount = frameCount;
}
return NO_ERROR;
}
@@ -939,7 +949,7 @@
audioBuffer->frameCount = 0;
audioBuffer->size = 0;
- uint32_t framesAvail = cblk->framesAvailableOut();
+ uint32_t framesAvail = cblk->framesAvailableOut(mFrameCount);
cblk->lock.lock();
if (cblk->flags & CBLK_INVALID) {
@@ -1015,7 +1025,7 @@
}
// read the server count again
start_loop_here:
- framesAvail = cblk->framesAvailableOut_l();
+ framesAvail = cblk->framesAvailableOut_l(mFrameCount);
}
cblk->lock.unlock();
}
@@ -1027,7 +1037,7 @@
}
uint32_t u = cblk->user;
- uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
+ uint32_t bufferEnd = cblk->userBase + mFrameCount;
if (framesReq > bufferEnd - u) {
framesReq = bufferEnd - u;
@@ -1044,7 +1054,7 @@
{
AutoMutex lock(mLock);
audio_track_cblk_t* cblk = mCblk;
- cblk->stepUserOut(audioBuffer->frameCount);
+ cblk->stepUserOut(audioBuffer->frameCount, mFrameCount);
if (audioBuffer->frameCount > 0) {
// restart track if it was disabled by audioflinger due to previous underrun
if (mActive && (cblk->flags & CBLK_DISABLED)) {
@@ -1211,11 +1221,11 @@
// so all cblk references might still refer to old shared memory, but that should be benign
// Manage underrun callback
- if (active && (cblk->framesAvailableOut() == cblk->frameCount)) {
+ if (active && (cblk->framesAvailableOut(mFrameCount) == mFrameCount)) {
ALOGV("Underrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags);
if (!(android_atomic_or(CBLK_UNDERRUN, &cblk->flags) & CBLK_UNDERRUN)) {
mCbf(EVENT_UNDERRUN, mUserData, 0);
- if (cblk->server == cblk->frameCount) {
+ if (cblk->server == mFrameCount) {
mCbf(EVENT_BUFFER_END, mUserData, 0);
}
if (mSharedBuffer != 0) return false;
@@ -1355,7 +1365,7 @@
cblk->sampleRate,
mFormat,
mChannelMask,
- mFrameCount,
+ mReqFrameCount, // so that frame count never goes down
mFlags,
mSharedBuffer,
getOutput_l());
@@ -1379,19 +1389,19 @@
if (mSharedBuffer == 0) {
uint32_t frames = 0;
if (user > server) {
- frames = ((user - server) > newCblk->frameCount) ?
- newCblk->frameCount : (user - server);
+ frames = ((user - server) > mFrameCount) ?
+ mFrameCount : (user - server);
memset(mBuffers, 0, frames * mFrameSizeAF);
}
// restart playback even if buffer is not completely filled.
android_atomic_or(CBLK_FORCEREADY, &newCblk->flags);
// stepUser() clears CBLK_UNDERRUN flag enabling underrun callbacks to
// the client
- newCblk->stepUserOut(frames);
+ newCblk->stepUserOut(frames, mFrameCount);
}
}
if (mSharedBuffer != 0) {
- newCblk->stepUserOut(newCblk->frameCount);
+ newCblk->stepUserOut(mFrameCount, mFrameCount);
}
if (mActive) {
result = mAudioTrack->start();
@@ -1429,7 +1439,7 @@
mVolume[0], mVolume[1]);
result.append(buffer);
snprintf(buffer, 255, " format(%d), channel count(%d), frame count(%d)\n", mFormat,
- mChannelCount, cblk->frameCount);
+ mChannelCount, mFrameCount);
result.append(buffer);
snprintf(buffer, 255, " sample rate(%u), status(%d), muted(%d)\n",
(cblk == 0) ? 0 : cblk->sampleRate, mStatus, mMuted);
@@ -1494,18 +1504,18 @@
audio_track_cblk_t::audio_track_cblk_t()
: lock(Mutex::SHARED), cv(Condition::SHARED), user(0), server(0),
- userBase(0), serverBase(0), frameCount(0),
+ userBase(0), serverBase(0), frameCount_(0),
loopStart(UINT_MAX), loopEnd(UINT_MAX), loopCount(0), mVolumeLR(0x10001000),
mSendLevel(0), flags(0)
{
}
-uint32_t audio_track_cblk_t::stepUser(uint32_t frameCount, bool isOut)
+uint32_t audio_track_cblk_t::stepUser(size_t stepCount, size_t frameCount, bool isOut)
{
- ALOGV("stepuser %08x %08x %d", user, server, frameCount);
+ ALOGV("stepuser %08x %08x %d", user, server, stepCount);
uint32_t u = user;
- u += frameCount;
+ u += stepCount;
// Ensure that user is never ahead of server for AudioRecord
if (isOut) {
// If stepServer() has been called once, switch to normal obtainBuffer() timeout period
@@ -1517,15 +1527,14 @@
u = server;
}
- uint32_t fc = this->frameCount;
- if (u >= fc) {
+ if (u >= frameCount) {
// common case, user didn't just wrap
- if (u - fc >= userBase ) {
- userBase += fc;
+ if (u - frameCount >= userBase ) {
+ userBase += frameCount;
}
- } else if (u >= userBase + fc) {
+ } else if (u >= userBase + frameCount) {
// user just wrapped
- userBase += fc;
+ userBase += frameCount;
}
user = u;
@@ -1538,9 +1547,9 @@
return u;
}
-bool audio_track_cblk_t::stepServer(uint32_t frameCount, bool isOut)
+bool audio_track_cblk_t::stepServer(size_t stepCount, size_t frameCount, bool isOut)
{
- ALOGV("stepserver %08x %08x %d", user, server, frameCount);
+ ALOGV("stepserver %08x %08x %d", user, server, stepCount);
if (!tryLock()) {
ALOGW("stepServer() could not lock cblk");
@@ -1550,7 +1559,7 @@
uint32_t s = server;
bool flushed = (s == user);
- s += frameCount;
+ s += stepCount;
if (isOut) {
// Mark that we have read the first buffer so that next time stepUser() is called
// we switch to normal obtainBuffer() timeout period
@@ -1576,15 +1585,14 @@
}
}
- uint32_t fc = this->frameCount;
- if (s >= fc) {
+ if (s >= frameCount) {
// common case, server didn't just wrap
- if (s - fc >= serverBase ) {
- serverBase += fc;
+ if (s - frameCount >= serverBase ) {
+ serverBase += frameCount;
}
- } else if (s >= serverBase + fc) {
+ } else if (s >= serverBase + frameCount) {
// server just wrapped
- serverBase += fc;
+ serverBase += frameCount;
}
server = s;
@@ -1601,13 +1609,13 @@
return (int8_t *)buffers + (offset - userBase) * frameSize;
}
-uint32_t audio_track_cblk_t::framesAvailable(bool isOut)
+uint32_t audio_track_cblk_t::framesAvailable(size_t frameCount, bool isOut)
{
Mutex::Autolock _l(lock);
- return framesAvailable_l(isOut);
+ return framesAvailable_l(frameCount, isOut);
}
-uint32_t audio_track_cblk_t::framesAvailable_l(bool isOut)
+uint32_t audio_track_cblk_t::framesAvailable_l(size_t frameCount, bool isOut)
{
uint32_t u = user;
uint32_t s = server;