diff options
Diffstat (limited to 'services/audioflinger/Threads.cpp')
-rw-r--r-- | services/audioflinger/Threads.cpp | 86 |
1 files changed, 55 insertions, 31 deletions
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 82c516c..12d453e 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -1145,7 +1145,7 @@ AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinge AudioFlinger::PlaybackThread::~PlaybackThread() { mAudioFlinger->unregisterWriter(mNBLogWriter); - delete[] mSinkBuffer; + free(mSinkBuffer); free(mMixerBuffer); free(mEffectBuffer); } @@ -1340,7 +1340,9 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrac } *pFrameCount = frameCount; - if (mType == DIRECT) { + switch (mType) { + + case DIRECT: if ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM) { if (sampleRate != mSampleRate || format != mFormat || channelMask != mChannelMask) { ALOGE("createTrack_l() Bad parameter: sampleRate %u format %#x, channelMask 0x%08x " @@ -1350,7 +1352,9 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrac goto Exit; } } - } else if (mType == OFFLOAD) { + break; + + case OFFLOAD: if (sampleRate != mSampleRate || format != mFormat || channelMask != mChannelMask) { ALOGE("createTrack_l() Bad parameter: sampleRate %d format %#x, channelMask 0x%08x \"" "for output %p with format %#x", @@ -1358,7 +1362,9 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrac lStatus = BAD_VALUE; goto Exit; } - } else { + break; + + default: if ((format & AUDIO_FORMAT_MAIN_MASK) != AUDIO_FORMAT_PCM) { ALOGE("createTrack_l() Bad parameter: format %#x \"" "for output %p with format %#x", @@ -1372,11 +1378,13 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrac lStatus = BAD_VALUE; goto Exit; } + break; + } lStatus = initCheck(); if (lStatus != NO_ERROR) { - ALOGE("Audio driver not initialized."); + ALOGE("createTrack_l() audio driver not initialized"); goto Exit; } @@ -1416,7 +1424,6 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrac // track must be cleared from the caller as the caller has the AF lock goto Exit; } - mTracks.add(track); sp<EffectChain> chain = getEffectChain_l(sessionId); @@ -1782,11 +1789,14 @@ void AudioFlinger::PlaybackThread::readOutputParameters_l() ALOGI("HAL output buffer size %u frames, normal sink buffer size %u frames", mFrameCount, mNormalFrameCount); - delete[] mSinkBuffer; - size_t normalBufferSize = mNormalFrameCount * mFrameSize; - // For historical reasons mSinkBuffer is int16_t[], but mFrameSize can be odd (such as 1) - mSinkBuffer = new int16_t[(normalBufferSize + 1) >> 1]; - memset(mSinkBuffer, 0, normalBufferSize); + // mSinkBuffer is the sink buffer. Size is always multiple-of-16 frames. + // Originally this was int16_t[] array, need to remove legacy implications. + free(mSinkBuffer); + mSinkBuffer = NULL; + // For sink buffer size, we use the frame size from the downstream sink to avoid problems + // with non PCM formats for compressed music, e.g. AAC, and Offload threads. + const size_t sinkBufferSize = mNormalFrameCount * mFrameSize; + (void)posix_memalign(&mSinkBuffer, 32, sinkBufferSize); // We resize the mMixerBuffer according to the requirements of the sink buffer which // drives the output. @@ -1984,12 +1994,12 @@ ssize_t AudioFlinger::PlaybackThread::threadLoop_write() mLastWriteTime = systemTime(); mInWrite = true; ssize_t bytesWritten; + const size_t offset = mCurrentWriteLength - mBytesRemaining; // If an NBAIO sink is present, use it to write the normal mixer's submix if (mNormalSink != 0) { -#define mBitShift 2 // FIXME - size_t count = mBytesRemaining >> mBitShift; - size_t offset = (mCurrentWriteLength - mBytesRemaining) >> 1; + const size_t count = mBytesRemaining / mFrameSize; + ATRACE_BEGIN("write"); // update the setpoint when AudioFlinger::mScreenState changes uint32_t screenState = AudioFlinger::mScreenState; @@ -2001,10 +2011,10 @@ ssize_t AudioFlinger::PlaybackThread::threadLoop_write() (pipe->maxFrames() * 7) / 8 : mNormalFrameCount * 2); } } - ssize_t framesWritten = mNormalSink->write(mSinkBuffer + offset, count); + ssize_t framesWritten = mNormalSink->write((char *)mSinkBuffer + offset, count); ATRACE_END(); if (framesWritten > 0) { - bytesWritten = framesWritten << mBitShift; + bytesWritten = framesWritten * mFrameSize; } else { bytesWritten = framesWritten; } @@ -2019,7 +2029,7 @@ ssize_t AudioFlinger::PlaybackThread::threadLoop_write() // otherwise use the HAL / AudioStreamOut directly } else { // Direct output and offload threads - size_t offset = (mCurrentWriteLength - mBytesRemaining); + if (mUseAsyncWrite) { ALOGW_IF(mWriteAckSequence & 1, "threadLoop_write(): out of sequence write request"); mWriteAckSequence += 2; @@ -2111,8 +2121,8 @@ void AudioFlinger::PlaybackThread::invalidateTracks(audio_stream_type_t streamTy status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& chain) { int session = chain->sessionId(); - int16_t *buffer = mEffectBufferEnabled - ? reinterpret_cast<int16_t*>(mEffectBuffer) : mSinkBuffer; + int16_t* buffer = reinterpret_cast<int16_t*>(mEffectBufferEnabled + ? mEffectBuffer : mSinkBuffer); bool ownsBuffer = false; ALOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session); @@ -2152,8 +2162,8 @@ status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& c } chain->setInBuffer(buffer, ownsBuffer); - chain->setOutBuffer(mEffectBufferEnabled - ? reinterpret_cast<int16_t*>(mEffectBuffer) : mSinkBuffer); + chain->setOutBuffer(reinterpret_cast<int16_t*>(mEffectBufferEnabled + ? mEffectBuffer : mSinkBuffer)); // Effect chain for session AUDIO_SESSION_OUTPUT_STAGE is inserted at end of effect // chains list in order to be processed last as it contains output stage effects // Effect chain for session AUDIO_SESSION_OUTPUT_MIX is inserted before @@ -2203,7 +2213,7 @@ size_t AudioFlinger::PlaybackThread::removeEffectChain_l(const sp<EffectChain>& for (size_t i = 0; i < mTracks.size(); ++i) { sp<Track> track = mTracks[i]; if (session == track->sessionId()) { - track->setMainBuffer(mSinkBuffer); + track->setMainBuffer(reinterpret_cast<int16_t*>(mSinkBuffer)); chain->decTrackCnt(); } } @@ -4471,7 +4481,15 @@ void AudioFlinger::DuplicatingThread::threadLoop_sleepTime() ssize_t AudioFlinger::DuplicatingThread::threadLoop_write() { for (size_t i = 0; i < outputTracks.size(); i++) { - outputTracks[i]->write(mSinkBuffer, writeFrames); + // We convert the duplicating thread format to AUDIO_FORMAT_PCM_16_BIT + // for delivery downstream as needed. This in-place conversion is safe as + // AUDIO_FORMAT_PCM_16_BIT is smaller than any other supported format + // (AUDIO_FORMAT_PCM_8_BIT is not allowed here). + if (mFormat != AUDIO_FORMAT_PCM_16_BIT) { + memcpy_by_audio_format(mSinkBuffer, AUDIO_FORMAT_PCM_16_BIT, + mSinkBuffer, mFormat, writeFrames * mChannelCount); + } + outputTracks[i]->write(reinterpret_cast<int16_t*>(mSinkBuffer), writeFrames); } mStandby = false; return (ssize_t)mSinkBufferSize; @@ -4500,10 +4518,16 @@ void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread) Mutex::Autolock _l(mLock); // FIXME explain this formula size_t frameCount = (3 * mNormalFrameCount * mSampleRate) / thread->sampleRate(); + // OutputTrack is forced to AUDIO_FORMAT_PCM_16_BIT regardless of mFormat + // due to current usage case and restrictions on the AudioBufferProvider. + // Actual buffer conversion is done in threadLoop_write(). + // + // TODO: This may change in the future, depending on multichannel + // (and non int16_t*) support on AF::PlaybackThread::OutputTrack OutputTrack *outputTrack = new OutputTrack(thread, this, mSampleRate, - mFormat, + AUDIO_FORMAT_PCM_16_BIT, mChannelMask, frameCount, IPCThreadState::self()->getCallingUid()); @@ -5036,6 +5060,7 @@ void AudioFlinger::RecordThread::inputStandBy() mInput->stream->common.standby(&mInput->stream->common); } +// RecordThread::createRecordTrack_l() must be called with AudioFlinger::mLock held sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRecordTrack_l( const sp<AudioFlinger::Client>& client, uint32_t sampleRate, @@ -5052,12 +5077,6 @@ sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRe sp<RecordTrack> track; status_t lStatus; - lStatus = initCheck(); - if (lStatus != NO_ERROR) { - ALOGE("createRecordTrack_l() audio driver not initialized"); - goto Exit; - } - // client expresses a preference for FAST, but we get the final say if (*flags & IAudioFlinger::TRACK_FAST) { if ( @@ -5110,7 +5129,11 @@ sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRe } *pFrameCount = frameCount; - // FIXME use flags and tid similar to createTrack_l() + lStatus = initCheck(); + if (lStatus != NO_ERROR) { + ALOGE("createRecordTrack_l() audio driver not initialized"); + goto Exit; + } { // scope for mLock Mutex::Autolock _l(mLock); @@ -5139,6 +5162,7 @@ sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRe sendPrioConfigEvent_l(callingPid, tid, kPriorityAudioApp); } } + lStatus = NO_ERROR; Exit: |