diff options
-rw-r--r-- | include/private/media/AudioTrackShared.h | 31 | ||||
-rw-r--r-- | media/libmedia/AudioRecord.cpp | 22 | ||||
-rw-r--r-- | media/libmedia/AudioTrack.cpp | 62 | ||||
-rw-r--r-- | services/audioflinger/AudioFlinger.cpp | 26 |
4 files changed, 64 insertions, 77 deletions
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h index fe42afa..6a86a00 100644 --- a/include/private/media/AudioTrackShared.h +++ b/include/private/media/AudioTrackShared.h @@ -33,28 +33,15 @@ namespace android { #define WAIT_PERIOD_MS 10 #define RESTORE_TIMEOUT_MS 5000 // Maximum waiting time for a track to be restored -#define CBLK_UNDERRUN_MSK 0x0001 -#define CBLK_UNDERRUN_ON 0x0001 // underrun (out) or overrrun (in) indication -#define CBLK_UNDERRUN_OFF 0x0000 // no underrun -#define CBLK_DIRECTION_MSK 0x0002 -#define CBLK_DIRECTION_OUT 0x0002 // this cblk is for an AudioTrack -#define CBLK_DIRECTION_IN 0x0000 // this cblk is for an AudioRecord -#define CBLK_FORCEREADY_MSK 0x0004 -#define CBLK_FORCEREADY_ON 0x0004 // track is considered ready immediately by AudioFlinger -#define CBLK_FORCEREADY_OFF 0x0000 // track is ready when buffer full -#define CBLK_INVALID_MSK 0x0008 -#define CBLK_INVALID_ON 0x0008 // track buffer is invalidated by AudioFlinger: -#define CBLK_INVALID_OFF 0x0000 // must be re-created -#define CBLK_DISABLED_MSK 0x0010 -#define CBLK_DISABLED_ON 0x0010 // track disabled by AudioFlinger due to underrun: -#define CBLK_DISABLED_OFF 0x0000 // must be re-started -#define CBLK_RESTORING_MSK 0x0020 -#define CBLK_RESTORING_ON 0x0020 // track is being restored after invalidation -#define CBLK_RESTORING_OFF 0x0000 // by AudioFlinger -#define CBLK_RESTORED_MSK 0x0040 -#define CBLK_RESTORED_ON 0x0040 // track has been restored after invalidation -#define CBLK_RESTORED_OFF 0x0040 // by AudioFlinger -#define CBLK_FAST 0x0080 // AudioFlinger successfully created a fast track +#define CBLK_UNDERRUN 0x01 // set: underrun (out) or overrrun (in), clear: no underrun or overrun +#define CBLK_DIRECTION 0x02 // set: cblk is for an AudioTrack, clear: for AudioRecord +#define CBLK_FORCEREADY 0x04 // set: track is considered ready immediately by AudioFlinger, + // clear: track is ready when buffer full +#define CBLK_INVALID 0x08 // track buffer invalidated by AudioFlinger, need to re-create +#define CBLK_DISABLED 0x10 // track disabled by AudioFlinger due to underrun, need to re-start +#define CBLK_RESTORING 0x20 // track is being restored after invalidation by AudioFlinger +#define CBLK_RESTORED 0x40 // track has been restored after invalidation by AudioFlinger +#define CBLK_FAST 0x80 // AudioFlinger successfully created a fast track // Important: do not add any virtual methods, including ~ struct audio_track_cblk_t diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index bdbee0d..bd558fa 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -292,16 +292,16 @@ status_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession) mActive = true; cblk->lock.lock(); - if (!(cblk->flags & CBLK_INVALID_MSK)) { + if (!(cblk->flags & CBLK_INVALID)) { cblk->lock.unlock(); ALOGV("mAudioRecord->start()"); ret = mAudioRecord->start(event, triggerSession); cblk->lock.lock(); if (ret == DEAD_OBJECT) { - android_atomic_or(CBLK_INVALID_ON, &cblk->flags); + android_atomic_or(CBLK_INVALID, &cblk->flags); } } - if (cblk->flags & CBLK_INVALID_MSK) { + if (cblk->flags & CBLK_INVALID) { ret = restoreRecord_l(cblk); } cblk->lock.unlock(); @@ -466,7 +466,7 @@ status_t AudioRecord::openRecord_l( mCblkMemory = cblk; mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer()); mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t); - android_atomic_and(~CBLK_DIRECTION_MSK, &mCblk->flags); + android_atomic_and(~CBLK_DIRECTION, &mCblk->flags); mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; mCblk->waitTimeMs = 0; return NO_ERROR; @@ -499,7 +499,7 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) cblk->lock.unlock(); return WOULD_BLOCK; } - if (!(cblk->flags & CBLK_INVALID_MSK)) { + if (!(cblk->flags & CBLK_INVALID)) { mLock.unlock(); result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs)); cblk->lock.unlock(); @@ -509,7 +509,7 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) } cblk->lock.lock(); } - if (cblk->flags & CBLK_INVALID_MSK) { + if (cblk->flags & CBLK_INVALID) { goto create_new_record; } if (CC_UNLIKELY(result != NO_ERROR)) { @@ -522,7 +522,7 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) result = mAudioRecord->start(AudioSystem::SYNC_EVENT_SAME, 0); cblk->lock.lock(); if (result == DEAD_OBJECT) { - android_atomic_or(CBLK_INVALID_ON, &cblk->flags); + android_atomic_or(CBLK_INVALID, &cblk->flags); create_new_record: result = AudioRecord::restoreRecord_l(cblk); } @@ -739,7 +739,7 @@ bool AudioRecord::processAudioBuffer(const sp<AudioRecordThread>& thread) // The value of active is stale, but we are almost sure to be active here because // otherwise we would have exited when obtainBuffer returned STOPPED earlier. ALOGV("Overrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags); - if (!(android_atomic_or(CBLK_UNDERRUN_ON, &cblk->flags) & CBLK_UNDERRUN_MSK)) { + if (!(android_atomic_or(CBLK_UNDERRUN, &cblk->flags) & CBLK_UNDERRUN)) { mCbf(EVENT_OVERRUN, mUserData, NULL); } } @@ -759,7 +759,7 @@ status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& cblk) { status_t result; - if (!(android_atomic_or(CBLK_RESTORING_ON, &cblk->flags) & CBLK_RESTORING_MSK)) { + if (!(android_atomic_or(CBLK_RESTORING, &cblk->flags) & CBLK_RESTORING)) { ALOGW("dead IAudioRecord, creating a new one"); // signal old cblk condition so that other threads waiting for available buffers stop // waiting now @@ -780,10 +780,10 @@ status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& cblk) } // signal old cblk condition for other threads waiting for restore completion - android_atomic_or(CBLK_RESTORED_ON, &cblk->flags); + android_atomic_or(CBLK_RESTORED, &cblk->flags); cblk->cv.broadcast(); } else { - if (!(cblk->flags & CBLK_RESTORED_MSK)) { + if (!(cblk->flags & CBLK_RESTORED)) { ALOGW("dead IAudioRecord, waiting for a new one to be created"); mLock.unlock(); result = cblk->cv.waitRelative(cblk->lock, milliseconds(RESTORE_TIMEOUT_MS)); diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index ffed161..5bd1aa7 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -391,7 +391,7 @@ void AudioTrack::start() cblk->lock.lock(); cblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS; cblk->waitTimeMs = 0; - android_atomic_and(~CBLK_DISABLED_ON, &cblk->flags); + android_atomic_and(~CBLK_DISABLED, &cblk->flags); if (t != 0) { t->resume(); } else { @@ -402,16 +402,16 @@ void AudioTrack::start() ALOGV("start %p before lock cblk %p", this, mCblk); status_t status = NO_ERROR; - if (!(cblk->flags & CBLK_INVALID_MSK)) { + if (!(cblk->flags & CBLK_INVALID)) { cblk->lock.unlock(); ALOGV("mAudioTrack->start()"); status = mAudioTrack->start(); cblk->lock.lock(); if (status == DEAD_OBJECT) { - android_atomic_or(CBLK_INVALID_ON, &cblk->flags); + android_atomic_or(CBLK_INVALID, &cblk->flags); } } - if (cblk->flags & CBLK_INVALID_MSK) { + if (cblk->flags & CBLK_INVALID) { status = restoreTrack_l(cblk, true); } cblk->lock.unlock(); @@ -691,7 +691,7 @@ status_t AudioTrack::setPosition(uint32_t position) if (position > mCblk->user) return BAD_VALUE; mCblk->server = position; - android_atomic_or(CBLK_FORCEREADY_ON, &mCblk->flags); + android_atomic_or(CBLK_FORCEREADY, &mCblk->flags); return NO_ERROR; } @@ -905,7 +905,7 @@ status_t AudioTrack::createTrack_l( mCblkMemory = cblk; mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer()); // old has the previous value of mCblk->flags before the "or" operation - int32_t old = android_atomic_or(CBLK_DIRECTION_OUT, &mCblk->flags); + int32_t old = android_atomic_or(CBLK_DIRECTION, &mCblk->flags); if (flags & AUDIO_OUTPUT_FLAG_FAST) { if (old & CBLK_FAST) { ALOGV("AUDIO_OUTPUT_FLAG_FAST successful; frameCount %u", mCblk->frameCount); @@ -959,7 +959,7 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) uint32_t framesAvail = cblk->framesAvailable(); cblk->lock.lock(); - if (cblk->flags & CBLK_INVALID_MSK) { + if (cblk->flags & CBLK_INVALID) { goto create_new_track; } cblk->lock.unlock(); @@ -978,7 +978,7 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) cblk->lock.unlock(); return WOULD_BLOCK; } - if (!(cblk->flags & CBLK_INVALID_MSK)) { + if (!(cblk->flags & CBLK_INVALID)) { mLock.unlock(); result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs)); cblk->lock.unlock(); @@ -989,7 +989,7 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) cblk->lock.lock(); } - if (cblk->flags & CBLK_INVALID_MSK) { + if (cblk->flags & CBLK_INVALID) { goto create_new_track; } if (CC_UNLIKELY(result != NO_ERROR)) { @@ -1005,7 +1005,7 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) result = mAudioTrack->start(); cblk->lock.lock(); if (result == DEAD_OBJECT) { - android_atomic_or(CBLK_INVALID_ON, &cblk->flags); + android_atomic_or(CBLK_INVALID, &cblk->flags); create_new_track: result = restoreTrack_l(cblk, false); } @@ -1063,8 +1063,8 @@ void AudioTrack::releaseBuffer(Buffer* audioBuffer) mCblk->stepUser(audioBuffer->frameCount); if (audioBuffer->frameCount > 0) { // restart track if it was disabled by audioflinger due to previous underrun - if (mActive && (mCblk->flags & CBLK_DISABLED_MSK)) { - android_atomic_and(~CBLK_DISABLED_ON, &mCblk->flags); + if (mActive && (mCblk->flags & CBLK_DISABLED)) { + android_atomic_and(~CBLK_DISABLED, &mCblk->flags); ALOGW("releaseBuffer() track %p name=%#x disabled, restarting", this, mCblk->mName); mAudioTrack->start(); } @@ -1149,16 +1149,16 @@ status_t TimedAudioTrack::allocateTimedBuffer(size_t size, sp<IMemory>* buffer) // If the track is not invalid already, try to allocate a buffer. alloc // fails indicating that the server is dead, flag the track as invalid so // we can attempt to restore in just a bit. - if (!(mCblk->flags & CBLK_INVALID_MSK)) { + if (!(mCblk->flags & CBLK_INVALID)) { result = mAudioTrack->allocateTimedBuffer(size, buffer); if (result == DEAD_OBJECT) { - android_atomic_or(CBLK_INVALID_ON, &mCblk->flags); + android_atomic_or(CBLK_INVALID, &mCblk->flags); } } // If the track is invalid at this point, attempt to restore it. and try the // allocation one more time. - if (mCblk->flags & CBLK_INVALID_MSK) { + if (mCblk->flags & CBLK_INVALID) { mCblk->lock.lock(); result = restoreTrack_l(mCblk, false); mCblk->lock.unlock(); @@ -1178,8 +1178,8 @@ status_t TimedAudioTrack::queueTimedBuffer(const sp<IMemory>& buffer, AutoMutex lock(mLock); // restart track if it was disabled by audioflinger due to previous underrun if (buffer->size() != 0 && status == NO_ERROR && - mActive && (mCblk->flags & CBLK_DISABLED_MSK)) { - android_atomic_and(~CBLK_DISABLED_ON, &mCblk->flags); + mActive && (mCblk->flags & CBLK_DISABLED)) { + android_atomic_and(~CBLK_DISABLED, &mCblk->flags); ALOGW("queueTimedBuffer() track %p disabled, restarting", this); mAudioTrack->start(); } @@ -1213,7 +1213,7 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread) // Manage underrun callback if (active && (cblk->framesAvailable() == cblk->frameCount)) { ALOGV("Underrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags); - if (!(android_atomic_or(CBLK_UNDERRUN_ON, &cblk->flags) & CBLK_UNDERRUN_MSK)) { + if (!(android_atomic_or(CBLK_UNDERRUN, &cblk->flags) & CBLK_UNDERRUN)) { mCbf(EVENT_UNDERRUN, mUserData, 0); if (cblk->server == cblk->frameCount) { mCbf(EVENT_BUFFER_END, mUserData, 0); @@ -1333,7 +1333,7 @@ status_t AudioTrack::restoreTrack_l(audio_track_cblk_t*& cblk, bool fromStart) { status_t result; - if (!(android_atomic_or(CBLK_RESTORING_ON, &cblk->flags) & CBLK_RESTORING_MSK)) { + if (!(android_atomic_or(CBLK_RESTORING, &cblk->flags) & CBLK_RESTORING)) { ALOGW("dead IAudioTrack, creating a new one from %s TID %d", fromStart ? "start()" : "obtainBuffer()", gettid()); @@ -1381,8 +1381,8 @@ status_t AudioTrack::restoreTrack_l(audio_track_cblk_t*& cblk, bool fromStart) memset(mCblk->buffers, 0, frames * mCblk->frameSize); } // restart playback even if buffer is not completely filled. - android_atomic_or(CBLK_FORCEREADY_ON, &mCblk->flags); - // stepUser() clears CBLK_UNDERRUN_ON flag enabling underrun callbacks to + android_atomic_or(CBLK_FORCEREADY, &mCblk->flags); + // stepUser() clears CBLK_UNDERRUN flag enabling underrun callbacks to // the client mCblk->stepUser(frames); } @@ -1399,17 +1399,17 @@ status_t AudioTrack::restoreTrack_l(audio_track_cblk_t*& cblk, bool fromStart) } } if (result != NO_ERROR) { - android_atomic_and(~CBLK_RESTORING_ON, &cblk->flags); + android_atomic_and(~CBLK_RESTORING, &cblk->flags); ALOGW_IF(result != NO_ERROR, "restoreTrack_l() failed status %d", result); } mRestoreStatus = result; // signal old cblk condition for other threads waiting for restore completion - android_atomic_or(CBLK_RESTORED_ON, &cblk->flags); + android_atomic_or(CBLK_RESTORED, &cblk->flags); cblk->cv.broadcast(); } else { bool haveLogged = false; for (;;) { - if (cblk->flags & CBLK_RESTORED_MSK) { + if (cblk->flags & CBLK_RESTORED) { ALOGW("dead IAudioTrack restored"); result = mRestoreStatus; cblk->lock.unlock(); @@ -1534,7 +1534,7 @@ uint32_t audio_track_cblk_t::stepUser(uint32_t frameCount) uint32_t u = user; u += frameCount; // Ensure that user is never ahead of server for AudioRecord - if (flags & CBLK_DIRECTION_MSK) { + if (flags & CBLK_DIRECTION) { // If stepServer() has been called once, switch to normal obtainBuffer() timeout period if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS-1) { bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; @@ -1558,8 +1558,8 @@ uint32_t audio_track_cblk_t::stepUser(uint32_t frameCount) user = u; // Clear flow control error condition as new data has been written/read to/from buffer. - if (flags & CBLK_UNDERRUN_MSK) { - android_atomic_and(~CBLK_UNDERRUN_MSK, &flags); + if (flags & CBLK_UNDERRUN) { + android_atomic_and(~CBLK_UNDERRUN, &flags); } return u; @@ -1578,7 +1578,7 @@ bool audio_track_cblk_t::stepServer(uint32_t frameCount) bool flushed = (s == user); s += frameCount; - if (flags & CBLK_DIRECTION_MSK) { + if (flags & CBLK_DIRECTION) { // Mark that we have read the first buffer so that next time stepUser() is called // we switch to normal obtainBuffer() timeout period if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS) { @@ -1616,7 +1616,7 @@ bool audio_track_cblk_t::stepServer(uint32_t frameCount) server = s; - if (!(flags & CBLK_INVALID_MSK)) { + if (!(flags & CBLK_INVALID)) { cv.signal(); } lock.unlock(); @@ -1639,7 +1639,7 @@ uint32_t audio_track_cblk_t::framesAvailable_l() uint32_t u = user; uint32_t s = server; - if (flags & CBLK_DIRECTION_MSK) { + if (flags & CBLK_DIRECTION) { uint32_t limit = (s < loopStart) ? s : loopStart; return limit + frameCount - u; } else { @@ -1652,7 +1652,7 @@ uint32_t audio_track_cblk_t::framesReady() uint32_t u = user; uint32_t s = server; - if (flags & CBLK_DIRECTION_MSK) { + if (flags & CBLK_DIRECTION) { if (u < loopEnd) { return u - s; } else { diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 35bd431..5f2f441 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -2167,7 +2167,7 @@ uint32_t AudioFlinger::PlaybackThread::hasAudioSession(int sessionId) const for (size_t i = 0; i < mTracks.size(); ++i) { sp<Track> track = mTracks[i]; if (sessionId == track->sessionId() && - !(track->mCblk->flags & CBLK_INVALID_MSK)) { + !(track->mCblk->flags & CBLK_INVALID)) { result |= TRACK_SESSION; break; } @@ -2186,7 +2186,7 @@ uint32_t AudioFlinger::PlaybackThread::getStrategyForSession_l(int sessionId) for (size_t i = 0; i < mTracks.size(); i++) { sp<Track> track = mTracks[i]; if (sessionId == track->sessionId() && - !(track->mCblk->flags & CBLK_INVALID_MSK)) { + !(track->mCblk->flags & CBLK_INVALID)) { return AudioSystem::getStrategyForStream(track->streamType()); } } @@ -3032,7 +3032,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac } // indicate to client process that the track was disabled because of underrun; // it will then automatically call start() when data is available - android_atomic_or(CBLK_DISABLED_ON, &track->mCblk->flags); + android_atomic_or(CBLK_DISABLED, &track->mCblk->flags); // remove from active list, but state remains ACTIVE [confusing but true] isActive = false; break; @@ -3314,7 +3314,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac tracksToRemove->add(track); // indicate to client process that the track was disabled because of underrun; // it will then automatically call start() when data is available - android_atomic_or(CBLK_DISABLED_ON, &cblk->flags); + android_atomic_or(CBLK_DISABLED, &cblk->flags); // If one track is not ready, mark the mixer also not ready if: // - the mixer was ready during previous round OR // - no other track is ready @@ -3447,7 +3447,7 @@ void AudioFlinger::PlaybackThread::invalidateTracks(audio_stream_type_t streamTy for (size_t i = 0; i < size; i++) { sp<Track> t = mTracks[i]; if (t->streamType() == streamType) { - android_atomic_or(CBLK_INVALID_ON, &t->mCblk->flags); + android_atomic_or(CBLK_INVALID, &t->mCblk->flags); t->mCblk->cv.signal(); } } @@ -4227,7 +4227,7 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t)); // Force underrun condition to avoid false underrun callback until first data is // written to buffer (other flags are cleared) - mCblk->flags = CBLK_UNDERRUN_ON; + mCblk->flags = CBLK_UNDERRUN; } else { mBuffer = sharedBuffer->pointer(); } @@ -4256,7 +4256,7 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t)); // Force underrun condition to avoid false underrun callback until first data is // written to buffer (other flags are cleared) - mCblk->flags = CBLK_UNDERRUN_ON; + mCblk->flags = CBLK_UNDERRUN; mBufferEnd = (uint8_t *)mBuffer + bufferSize; } } @@ -4600,9 +4600,9 @@ bool AudioFlinger::PlaybackThread::Track::isReady() const { if (mFillingUpStatus != FS_FILLING || isStopped() || isPausing()) return true; if (framesReady() >= mCblk->frameCount || - (mCblk->flags & CBLK_FORCEREADY_MSK)) { + (mCblk->flags & CBLK_FORCEREADY)) { mFillingUpStatus = FS_FILLED; - android_atomic_and(~CBLK_FORCEREADY_MSK, &mCblk->flags); + android_atomic_and(~CBLK_FORCEREADY, &mCblk->flags); return true; } return false; @@ -4745,8 +4745,8 @@ void AudioFlinger::PlaybackThread::Track::reset() TrackBase::reset(); // Force underrun condition to avoid false underrun callback until first data is // written to buffer - android_atomic_and(~CBLK_FORCEREADY_MSK, &mCblk->flags); - android_atomic_or(CBLK_UNDERRUN_ON, &mCblk->flags); + android_atomic_and(~CBLK_FORCEREADY, &mCblk->flags); + android_atomic_or(CBLK_UNDERRUN, &mCblk->flags); mFillingUpStatus = FS_FILLING; mResetDone = true; if (mState == FLUSHED) { @@ -5495,7 +5495,7 @@ void AudioFlinger::RecordThread::RecordTrack::stop() TrackBase::reset(); // Force overrun condition to avoid false overrun callback until first data is // read from buffer - android_atomic_or(CBLK_UNDERRUN_ON, &mCblk->flags); + android_atomic_or(CBLK_UNDERRUN, &mCblk->flags); } recordThread->mLock.unlock(); if (doStop) { @@ -5540,7 +5540,7 @@ AudioFlinger::PlaybackThread::OutputTrack::OutputTrack( { if (mCblk != NULL) { - mCblk->flags |= CBLK_DIRECTION_OUT; + mCblk->flags |= CBLK_DIRECTION; mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t); mOutBuffer.frameCount = 0; playbackThread->mTracks.add(this); |