diff options
Diffstat (limited to 'services')
-rw-r--r-- | services/audioflinger/AudioFlinger.h | 1 | ||||
-rw-r--r-- | services/audioflinger/PlaybackTracks.h | 3 | ||||
-rw-r--r-- | services/audioflinger/RecordTracks.h | 2 | ||||
-rw-r--r-- | services/audioflinger/Threads.cpp | 21 | ||||
-rw-r--r-- | services/audioflinger/TrackBase.h | 9 | ||||
-rw-r--r-- | services/audioflinger/Tracks.cpp | 97 |
6 files changed, 63 insertions, 70 deletions
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index 6d3f0a1..64a9871 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -61,6 +61,7 @@ class AudioMixer; class AudioBuffer; class AudioResampler; class FastMixer; +class ServerProxy; // ---------------------------------------------------------------------------- diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h index aaa5333..adec938 100644 --- a/services/audioflinger/PlaybackTracks.h +++ b/services/audioflinger/PlaybackTracks.h @@ -107,7 +107,6 @@ public: bool isInvalid() const { return mIsInvalid; } virtual bool isTimedTrack() const { return false; } bool isFastTrack() const { return (mFlags & IAudioFlinger::TRACK_FAST) != 0; } - virtual bool isOut() const; protected: @@ -277,5 +276,5 @@ private: AudioBufferProvider::Buffer mOutBuffer; bool mActive; DuplicatingThread* const mSourceThread; // for waitTimeMs() in write() - void* mBuffers; // starting address of buffers in plain memory + AudioTrackClientProxy* mClientProxy; }; // end of OutputTrack diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h index fe681d7..6c0d1d3 100644 --- a/services/audioflinger/RecordTracks.h +++ b/services/audioflinger/RecordTracks.h @@ -45,8 +45,6 @@ public: static void appendDumpHeader(String8& result); void dump(char* buffer, size_t size); - virtual bool isOut() const; - private: friend class AudioFlinger; // for mState diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index d2b2931..82acd3a 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -2643,7 +2643,8 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac // read original volumes with volume control float typeVolume = mStreamTypes[track->streamType()].volume; float v = masterVolume * typeVolume; - uint32_t vlr = cblk->getVolumeLR(); + ServerProxy *proxy = track->mServerProxy; + uint32_t vlr = proxy->getVolumeLR(); vl = vlr & 0xFFFF; vr = vlr >> 16; // track volumes come from shared memory, so can't be trusted and must be clamped @@ -2661,7 +2662,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac // assuming master volume and stream type volume each go up to 1.0, // vl and vr are now in 8.24 format - uint16_t sendLevel = cblk->getSendLevel_U4_12(); + uint16_t sendLevel = proxy->getSendLevel_U4_12(); // send level comes from shared memory and so may be corrupt if (sendLevel > MAX_GAIN_INT) { ALOGV("Track send level out of range: %04X", sendLevel); @@ -2713,11 +2714,19 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac name, AudioMixer::TRACK, AudioMixer::CHANNEL_MASK, (void *)track->channelMask()); + // limit track sample rate to 2 x output sample rate, which changes at re-configuration + uint32_t maxSampleRate = mSampleRate * 2; + uint32_t reqSampleRate = track->mServerProxy->getSampleRate(); + if (reqSampleRate == 0) { + reqSampleRate = mSampleRate; + } else if (reqSampleRate > maxSampleRate) { + reqSampleRate = maxSampleRate; + } mAudioMixer->setParameter( name, AudioMixer::RESAMPLE, AudioMixer::SAMPLE_RATE, - (void *)(cblk->sampleRate)); + (void *)reqSampleRate); mAudioMixer->setParameter( name, AudioMixer::TRACK, @@ -2990,10 +2999,6 @@ bool AudioFlinger::MixerThread::checkForNewParameters_l() break; } mTracks[i]->mName = name; - // limit track sample rate to 2 x new output sample rate - if (mTracks[i]->mCblk->sampleRate > 2 * sampleRate()) { - mTracks[i]->mCblk->sampleRate = 2 * sampleRate(); - } } sendIoConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED); } @@ -3142,7 +3147,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep } else { float typeVolume = mStreamTypes[track->streamType()].volume; float v = mMasterVolume * typeVolume; - uint32_t vlr = cblk->getVolumeLR(); + uint32_t vlr = track->mServerProxy->getVolumeLR(); float v_clamped = v * (vlr & 0xFFFF); if (v_clamped > MAX_GAIN) { v_clamped = MAX_GAIN; diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h index 17de49b..e0bd97a 100644 --- a/services/audioflinger/TrackBase.h +++ b/services/audioflinger/TrackBase.h @@ -44,7 +44,8 @@ public: audio_channel_mask_t channelMask, size_t frameCount, const sp<IMemory>& sharedBuffer, - int sessionId); + int sessionId, + bool isOut); virtual ~TrackBase(); virtual status_t start(AudioSystem::sync_event_t event, @@ -108,7 +109,8 @@ protected: bool step(); // mStepCount is an implicit input void reset(); - virtual bool isOut() const = 0; // true for Track and TimedTrack, false for RecordTrack, + bool isOut() const { return mIsOut; } + // true for Track and TimedTrack, false for RecordTrack, // this could be a track type if needed later const wp<ThreadBase> mThread; @@ -116,6 +118,7 @@ protected: sp<IMemory> mCblkMemory; audio_track_cblk_t* mCblk; void* mBuffer; // start of track buffer, typically in shared memory + // except for OutputTrack when it is in local memory void* mBufferEnd; // &mBuffer[mFrameCount * frameSize], where frameSize // is based on mChannelCount and 16-bit samples uint32_t mStepCount; // saves AudioBufferProvider::Buffer::frameCount as of @@ -136,4 +139,6 @@ protected: bool mStepServerFailed; const int mSessionId; Vector < sp<SyncEvent> >mSyncEvents; + const bool mIsOut; + ServerProxy* mServerProxy; }; diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp index 9b611d2..c5f0ed7 100644 --- a/services/audioflinger/Tracks.cpp +++ b/services/audioflinger/Tracks.cpp @@ -62,7 +62,8 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( audio_channel_mask_t channelMask, size_t frameCount, const sp<IMemory>& sharedBuffer, - int sessionId) + int sessionId, + bool isOut) : RefBase(), mThread(thread), mClient(client), @@ -79,7 +80,9 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( mChannelCount * audio_bytes_per_sample(format) : sizeof(int8_t)), mFrameCount(frameCount), mStepServerFailed(false), - mSessionId(sessionId) + mSessionId(sessionId), + mIsOut(isOut), + mServerProxy(NULL) { // client == 0 implies sharedBuffer == 0 ALOG_ASSERT(!(client == 0 && sharedBuffer != 0)); @@ -105,7 +108,8 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( return; } } else { - mCblk = (audio_track_cblk_t *)(new uint8_t[size]); + // this syntax avoids calling the audio_track_cblk_t constructor twice + mCblk = (audio_track_cblk_t *) new uint8_t[size]; // assume mCblk != NULL } @@ -114,7 +118,6 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( new(mCblk) audio_track_cblk_t(); // clear all buffers mCblk->frameCount_ = frameCount; - mCblk->sampleRate = sampleRate; // uncomment the following lines to quickly test 32-bit wraparound // mCblk->user = 0xffff0000; // mCblk->server = 0xffff0000; @@ -130,11 +133,14 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( mBuffer = sharedBuffer->pointer(); } mBufferEnd = (uint8_t *)mBuffer + bufferSize; + mServerProxy = new ServerProxy(mCblk, mBuffer, frameCount, mFrameSize, isOut); } } AudioFlinger::ThreadBase::TrackBase::~TrackBase() { + // delete the proxy before deleting the shared memory it refers to, to avoid dangling reference + delete mServerProxy; if (mCblk != NULL) { if (mClient == 0) { delete mCblk; @@ -166,10 +172,7 @@ void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buf } bool AudioFlinger::ThreadBase::TrackBase::step() { - bool result; - audio_track_cblk_t* cblk = this->cblk(); - - result = cblk->stepServer(mStepCount, mFrameCount, isOut()); + bool result = mServerProxy->step(mStepCount); if (!result) { ALOGV("stepServer failed acquiring cblk mutex"); mStepServerFailed = true; @@ -189,7 +192,7 @@ void AudioFlinger::ThreadBase::TrackBase::reset() { } uint32_t AudioFlinger::ThreadBase::TrackBase::sampleRate() const { - return mCblk->sampleRate; + return mServerProxy->getSampleRate(); } void* AudioFlinger::ThreadBase::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const { @@ -310,7 +313,7 @@ AudioFlinger::PlaybackThread::Track::Track( int sessionId, IAudioFlinger::track_flags_t flags) : TrackBase(thread, client, sampleRate, format, channelMask, frameCount, sharedBuffer, - sessionId), + sessionId, true /*isOut*/), mFillingUpStatus(FS_INVALID), // mRetryCount initialized later when needed mSharedBuffer(sharedBuffer), @@ -399,7 +402,7 @@ void AudioFlinger::PlaybackThread::Track::destroy() void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size) { - uint32_t vlr = mCblk->getVolumeLR(); + uint32_t vlr = mServerProxy->getVolumeLR(); if (isFastTrack()) { sprintf(buffer, " F %2d", mFastIndex); } else { @@ -468,7 +471,7 @@ void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size) mFrameCount, stateChar, mFillingUpStatus, - mCblk->sampleRate, + mServerProxy->getSampleRate(), 20.0 * log10((vlr & 0xFFFF) / 4096.0), 20.0 * log10((vlr >> 16) / 4096.0), mCblk->server, @@ -503,7 +506,7 @@ status_t AudioFlinger::PlaybackThread::Track::getNextBuffer( } // FIXME Same as above - framesReady = cblk->framesReadyOut(); + framesReady = mServerProxy->framesReady(); if (CC_LIKELY(framesReady)) { uint32_t s = cblk->server; @@ -538,7 +541,7 @@ getNextBuffer_exit: // the tryLock() could block for up to 1 ms, and a sequence of these could delay fast mixer. // FIXME Replace AudioTrackShared control block implementation by a non-blocking FIFO queue. size_t AudioFlinger::PlaybackThread::Track::framesReady() const { - return mCblk->framesReadyOut(); + return mServerProxy->framesReady(); } // Don't call for fast tracks; the framesReady() could result in priority inversion @@ -795,7 +798,7 @@ uint32_t AudioFlinger::PlaybackThread::Track::getVolumeLR() { // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs ALOG_ASSERT(isFastTrack() && (mCblk != NULL)); - uint32_t vlr = mCblk->getVolumeLR(); + uint32_t vlr = mServerProxy->getVolumeLR(); uint32_t vl = vlr & 0xFFFF; uint32_t vr = vlr >> 16; // track volumes come from shared memory, so can't be trusted and must be clamped @@ -830,11 +833,6 @@ status_t AudioFlinger::PlaybackThread::Track::setSyncEvent(const sp<SyncEvent>& return NO_ERROR; } -bool AudioFlinger::PlaybackThread::Track::isOut() const -{ - return true; -} - void AudioFlinger::PlaybackThread::Track::invalidate() { // FIXME should use proxy @@ -1369,17 +1367,19 @@ AudioFlinger::PlaybackThread::OutputTrack::OutputTrack( size_t frameCount) : Track(playbackThread, NULL, AUDIO_STREAM_CNT, sampleRate, format, channelMask, frameCount, NULL, 0, IAudioFlinger::TRACK_DEFAULT), - mActive(false), mSourceThread(sourceThread), mBuffers(NULL) + mActive(false), mSourceThread(sourceThread), mClientProxy(NULL) { if (mCblk != NULL) { - mBuffers = (char*)mCblk + sizeof(audio_track_cblk_t); mOutBuffer.frameCount = 0; playbackThread->mTracks.add(this); - ALOGV("OutputTrack constructor mCblk %p, mBuffer %p, mBuffers %p, " \ - "mCblk->frameCount %d, mCblk->sampleRate %u, mChannelMask 0x%08x mBufferEnd %p", - mCblk, mBuffer, mBuffers, - mCblk->frameCount, mCblk->sampleRate, mChannelMask, mBufferEnd); + ALOGV("OutputTrack constructor mCblk %p, mBuffer %p, " + "mCblk->frameCount_ %u, mChannelMask 0x%08x mBufferEnd %p", + mCblk, mBuffer, + mCblk->frameCount_, mChannelMask, mBufferEnd); + // since client and server are in the same process, + // the buffer has the same virtual address on both sides + mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize); } else { ALOGW("Error creating output track on thread %p", playbackThread); } @@ -1388,6 +1388,8 @@ AudioFlinger::PlaybackThread::OutputTrack::OutputTrack( AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack() { clearBufferQueue(); + delete mClientProxy; + // superclass destructor will now delete the server proxy and shared memory both refer to } status_t AudioFlinger::PlaybackThread::OutputTrack::start(AudioSystem::sync_event_t event, @@ -1475,7 +1477,7 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t fr uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount; memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channelCount * sizeof(int16_t)); - mCblk->stepUserOut(outFrames, mFrameCount); + mClientProxy->stepUser(outFrames); pInBuffer->frameCount -= outFrames; pInBuffer->i16 += outFrames * channelCount; mOutBuffer.frameCount -= outFrames; @@ -1538,40 +1540,29 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t fr status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer( AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs) { - int active; - status_t result; audio_track_cblk_t* cblk = mCblk; uint32_t framesReq = buffer->frameCount; ALOGVV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server); buffer->frameCount = 0; - uint32_t framesAvail = cblk->framesAvailableOut(mFrameCount); - - - if (framesAvail == 0) { + size_t framesAvail; + { Mutex::Autolock _l(cblk->lock); - goto start_loop_here; - while (framesAvail == 0) { - active = mActive; - if (CC_UNLIKELY(!active)) { + + // read the server count again + while (!(framesAvail = mClientProxy->framesAvailable_l())) { + if (CC_UNLIKELY(!mActive)) { ALOGV("Not active and NO_MORE_BUFFERS"); return NO_MORE_BUFFERS; } - result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs)); + status_t result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs)); if (result != NO_ERROR) { return NO_MORE_BUFFERS; } - // read the server count again - start_loop_here: - framesAvail = cblk->framesAvailableOut_l(mFrameCount); } } -// if (framesAvail < framesReq) { -// return NO_MORE_BUFFERS; -// } - if (framesReq > framesAvail) { framesReq = framesAvail; } @@ -1584,7 +1575,7 @@ status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer( } buffer->frameCount = framesReq; - buffer->raw = cblk->buffer(mBuffers, mFrameSize, u); + buffer->raw = mClientProxy->buffer(u); return NO_ERROR; } @@ -1655,7 +1646,7 @@ AudioFlinger::RecordThread::RecordTrack::RecordTrack( size_t frameCount, int sessionId) : TrackBase(thread, client, sampleRate, format, - channelMask, frameCount, 0 /*sharedBuffer*/, sessionId), + channelMask, frameCount, 0 /*sharedBuffer*/, sessionId, false /*isOut*/), mOverflow(false) { ALOGV("RecordTrack constructor, size %d", (int)mBufferEnd - (int)mBuffer); @@ -1684,7 +1675,7 @@ status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvi } // FIXME lock is not actually held, so overrun is possible - framesAvail = cblk->framesAvailableIn_l(mFrameCount); + framesAvail = mServerProxy->framesAvailableIn_l(); if (CC_LIKELY(framesAvail)) { uint32_t s = cblk->server; @@ -1761,27 +1752,21 @@ void AudioFlinger::RecordThread::RecordTrack::destroy() /*static*/ void AudioFlinger::RecordThread::RecordTrack::appendDumpHeader(String8& result) { - result.append(" Clien Fmt Chn mask Session Step S SRate Serv User FrameCount\n"); + result.append(" Clien Fmt Chn mask Session Step S Serv User FrameCount\n"); } void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size) { - snprintf(buffer, size, " %05d %03u 0x%08x %05d %04u %01d %05u %08x %08x %05d\n", + snprintf(buffer, size, " %05d %03u 0x%08x %05d %04u %01d %08x %08x %05d\n", (mClient == 0) ? getpid_cached : mClient->pid(), mFormat, mChannelMask, mSessionId, mStepCount, mState, - mCblk->sampleRate, mCblk->server, mCblk->user, mFrameCount); } -bool AudioFlinger::RecordThread::RecordTrack::isOut() const -{ - return false; -} - }; // namespace android |