Loading include/media/AudioRecord.h +3 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ namespace android { class audio_track_cblk_t; class AudioRecordClientProxy; // ---------------------------------------------------------------------------- Loading Loading @@ -374,6 +375,7 @@ private: uint32_t mUpdatePeriod; // in ms // constant after constructor or set() uint32_t mSampleRate; size_t mFrameCount; audio_format_t mFormat; uint8_t mChannelCount; Loading @@ -393,6 +395,7 @@ private: int mPreviousPriority; // before start() SchedPolicy mPreviousSchedulingGroup; AudioRecordClientProxy* mProxy; }; }; // namespace android Loading include/media/AudioTrack.h +3 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ namespace android { // ---------------------------------------------------------------------------- class audio_track_cblk_t; class AudioTrackClientProxy; // ---------------------------------------------------------------------------- Loading Loading @@ -538,6 +539,7 @@ protected: float mVolume[2]; float mSendLevel; uint32_t mSampleRate; size_t mFrameCount; // corresponds to current IAudioTrack size_t mReqFrameCount; // frame count to request the next time a new // IAudioTrack is needed Loading Loading @@ -596,6 +598,7 @@ protected: bool mIsTimed; int mPreviousPriority; // before start() SchedPolicy mPreviousSchedulingGroup; AudioTrackClientProxy* mProxy; }; class TimedAudioTrack : public AudioTrack Loading include/private/media/AudioTrackShared.h +183 −45 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <sys/types.h> #include <utils/threads.h> #include <utils/Log.h> namespace android { Loading @@ -38,9 +39,26 @@ namespace android { #define CBLK_INVALID 0x04 // track buffer invalidated by AudioFlinger, need to re-create #define CBLK_DISABLED 0x08 // track disabled by AudioFlinger due to underrun, need to re-start struct AudioTrackSharedStreaming { // similar to NBAIO MonoPipe volatile int32_t mFront; volatile int32_t mRear; }; // future struct AudioTrackSharedStatic { int mReserved; }; // ---------------------------------------------------------------------------- // Important: do not add any virtual methods, including ~ struct audio_track_cblk_t { friend class Proxy; friend class AudioTrackClientProxy; friend class AudioRecordClientProxy; friend class ServerProxy; // The data members are grouped so that members accessed frequently and in the same context // are in the same line of data cache. Loading Loading @@ -72,12 +90,13 @@ struct audio_track_cblk_t // For AudioTrack only, not used by AudioRecord. private: uint32_t mVolumeLR; public: uint32_t sampleRate; uint32_t mSampleRate; // AudioTrack only: client's requested sample rate in Hz // or 0 == default. Write-only client, read-only server. uint8_t mPad2; // unused public: // read-only for client, server writes once at initialization and is then read-only uint8_t mName; // normal tracks: track name, fast tracks: track index Loading @@ -94,65 +113,184 @@ public: // Cache line boundary (32 bytes) #if 0 union { AudioTrackSharedStreaming mStreaming; AudioTrackSharedStatic mStatic; int mAlign[8]; } u; // Cache line boundary (32 bytes) #endif // Since the control block is always located in shared memory, this constructor // is only used for placement new(). It is never used for regular new() or stack. audio_track_cblk_t(); // called by client only, where client includes regular // AudioTrack and AudioFlinger::PlaybackThread::OutputTrack uint32_t stepUserIn(size_t stepCount, size_t frameCount) { return stepUser(stepCount, frameCount, false); } uint32_t stepUserOut(size_t stepCount, size_t frameCount) { return stepUser(stepCount, frameCount, true); } bool stepServer(size_t stepCount, size_t frameCount, bool isOut); private: // if there is a shared buffer, "buffers" is the value of pointer() for the shared // buffer, otherwise "buffers" points immediately after the control block void* buffer(void *buffers, uint32_t frameSize, uint32_t offset) const; uint32_t framesAvailableIn(size_t frameCount) { return framesAvailable(frameCount, false); } uint32_t framesAvailableOut(size_t frameCount) { return framesAvailable(frameCount, true); } uint32_t framesAvailableIn_l(size_t frameCount) { return framesAvailable_l(frameCount, false); } uint32_t framesAvailableOut_l(size_t frameCount) { return framesAvailable_l(frameCount, true); } uint32_t framesReadyIn() { return framesReady(false); } uint32_t framesReadyOut() { return framesReady(true); } void* buffer(void *buffers, uint32_t frameSize, size_t offset) const; bool tryLock(); // isOut == true means AudioTrack, isOut == false means AudioRecord bool stepServer(size_t stepCount, size_t frameCount, bool isOut); uint32_t stepUser(size_t stepCount, size_t frameCount, bool isOut); uint32_t framesAvailable(size_t frameCount, bool isOut); uint32_t framesAvailable_l(size_t frameCount, bool isOut); uint32_t framesReady(bool isOut); }; // ---------------------------------------------------------------------------- // Proxy for shared memory control block, to isolate callers from needing to know the details. // There is exactly one ClientProxy and one ServerProxy per shared memory control block. // The proxies are located in normal memory, and are not multi-thread safe within a given side. class Proxy { protected: Proxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize) : mCblk(cblk), mBuffers(buffers), mFrameCount(frameCount), mFrameSize(frameSize) { } virtual ~Proxy() { } public: void* buffer(size_t offset) const { return mCblk->buffer(mBuffers, mFrameSize, offset); } protected: // These refer to shared memory, and are virtual addresses with respect to the current process. // They may have different virtual addresses within the other process. audio_track_cblk_t* const mCblk; // the control block void* const mBuffers; // starting address of buffers const size_t mFrameCount; // not necessarily a power of 2 const size_t mFrameSize; // in bytes #if 0 const size_t mFrameCountP2; // mFrameCount rounded to power of 2, streaming mode #endif }; // ---------------------------------------------------------------------------- // Proxy seen by AudioTrack client and AudioRecord client class ClientProxy : public Proxy { protected: ClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize) : Proxy(cblk, buffers, frameCount, frameSize) { } virtual ~ClientProxy() { } }; // ---------------------------------------------------------------------------- // Proxy used by AudioTrack client, which also includes AudioFlinger::PlaybackThread::OutputTrack class AudioTrackClientProxy : public ClientProxy { public: AudioTrackClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize) : ClientProxy(cblk, buffers, frameCount, frameSize) { } virtual ~AudioTrackClientProxy() { } // No barriers on the following operations, so the ordering of loads/stores // with respect to other parameters is UNPREDICTABLE. That's considered safe. // for AudioTrack client only, caller must limit to 0.0 <= sendLevel <= 1.0 // caller must limit to 0.0 <= sendLevel <= 1.0 void setSendLevel(float sendLevel) { mSendLevel = uint16_t(sendLevel * 0x1000); mCblk->mSendLevel = uint16_t(sendLevel * 0x1000); } // for AudioFlinger only; the return value must be validated by the caller uint16_t getSendLevel_U4_12() const { return mSendLevel; // caller must limit to 0 <= volumeLR <= 0x10001000 void setVolumeLR(uint32_t volumeLR) { mCblk->mVolumeLR = volumeLR; } // for AudioTrack client only, caller must limit to 0 <= volumeLR <= 0x10001000 void setVolumeLR(uint32_t volumeLR) { mVolumeLR = volumeLR; void setSampleRate(uint32_t sampleRate) { mCblk->mSampleRate = sampleRate; } // for AudioFlinger only; the return value must be validated by the caller uint32_t getVolumeLR() const { return mVolumeLR; // called by: // PlaybackThread::OutputTrack::write // AudioTrack::createTrack_l // AudioTrack::releaseBuffer // AudioTrack::reload // AudioTrack::restoreTrack_l (2 places) size_t stepUser(size_t stepCount) { return mCblk->stepUser(stepCount, mFrameCount, true /*isOut*/); } // called by AudioTrack::obtainBuffer and AudioTrack::processBuffer size_t framesAvailable() { return mCblk->framesAvailable(mFrameCount, true /*isOut*/); } // called by AudioTrack::obtainBuffer and PlaybackThread::OutputTrack::obtainBuffer // FIXME remove this API since it assumes a lock that should be invisible to caller size_t framesAvailable_l() { return mCblk->framesAvailable_l(mFrameCount, true /*isOut*/); } private: // isOut == true means AudioTrack, isOut == false means AudioRecord uint32_t stepUser(size_t stepCount, size_t frameCount, bool isOut); uint32_t framesAvailable(size_t frameCount, bool isOut); uint32_t framesAvailable_l(size_t frameCount, bool isOut); uint32_t framesReady(bool isOut); }; // ---------------------------------------------------------------------------- // Proxy used by AudioRecord client class AudioRecordClientProxy : public ClientProxy { public: AudioRecordClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize) : ClientProxy(cblk, buffers, frameCount, frameSize) { } ~AudioRecordClientProxy() { } // called by AudioRecord::releaseBuffer size_t stepUser(size_t stepCount) { return mCblk->stepUser(stepCount, mFrameCount, false /*isOut*/); } // called by AudioRecord::processBuffer size_t framesAvailable() { return mCblk->framesAvailable(mFrameCount, false /*isOut*/); } // called by AudioRecord::obtainBuffer size_t framesReady() { return mCblk->framesReady(false /*isOut*/); } }; // ---------------------------------------------------------------------------- // Proxy used by AudioFlinger server class ServerProxy : public Proxy { public: ServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, bool isOut) : Proxy(cblk, buffers, frameCount, frameSize), mIsOut(isOut) { } virtual ~ServerProxy() { } // for AudioTrack and AudioRecord bool step(size_t stepCount) { return mCblk->stepServer(stepCount, mFrameCount, mIsOut); } // return value of these methods must be validated by the caller uint32_t getSampleRate() const { return mCblk->mSampleRate; } uint16_t getSendLevel_U4_12() const { return mCblk->mSendLevel; } uint32_t getVolumeLR() const { return mCblk->mVolumeLR; } // for AudioTrack only size_t framesReady() { ALOG_ASSERT(mIsOut); return mCblk->framesReady(true); } // for AudioRecord only, called by RecordThread::RecordTrack::getNextBuffer // FIXME remove this API since it assumes a lock that should be invisible to caller size_t framesAvailableIn_l() { ALOG_ASSERT(!mIsOut); return mCblk->framesAvailable_l(mFrameCount, false); } private: const bool mIsOut; // true for AudioTrack, false for AudioRecord }; // ---------------------------------------------------------------------------- Loading media/libmedia/AudioRecord.cpp +31 −16 Original line number Diff line number Diff line Loading @@ -75,7 +75,8 @@ status_t AudioRecord::getMinFrameCount( AudioRecord::AudioRecord() : mStatus(NO_INIT), mSessionId(0), mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT) mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT), mProxy(NULL) { } Loading @@ -90,7 +91,9 @@ AudioRecord::AudioRecord( int notificationFrames, int sessionId) : mStatus(NO_INIT), mSessionId(0), mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT) mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT), mProxy(NULL) { mStatus = set(inputSource, sampleRate, format, channelMask, frameCount, cbf, user, notificationFrames, sessionId); Loading @@ -112,6 +115,7 @@ AudioRecord::~AudioRecord() IPCThreadState::self()->flushCommands(); AudioSystem::releaseAudioSessionId(mSessionId); } delete mProxy; } status_t AudioRecord::set( Loading Loading @@ -149,6 +153,8 @@ status_t AudioRecord::set( if (sampleRate == 0) { sampleRate = DEFAULT_SAMPLE_RATE; } mSampleRate = sampleRate; // these below should probably come from the audioFlinger too... if (format == AUDIO_FORMAT_DEFAULT) { format = AUDIO_FORMAT_PCM_16_BIT; Loading @@ -166,6 +172,12 @@ status_t AudioRecord::set( uint32_t channelCount = popcount(channelMask); mChannelCount = channelCount; if (audio_is_linear_pcm(mFormat)) { mFrameSize = channelCount * audio_bytes_per_sample(format); } else { mFrameSize = sizeof(uint8_t); } if (sessionId == 0 ) { mSessionId = AudioSystem::newAudioSessionId(); } else { Loading Loading @@ -218,12 +230,6 @@ status_t AudioRecord::set( // Update buffer size in case it has been limited by AudioFlinger during track creation mFrameCount = mCblk->frameCount_; if (audio_is_linear_pcm(mFormat)) { mFrameSize = channelCount * audio_bytes_per_sample(format); } else { mFrameSize = sizeof(uint8_t); } mActive = false; mCbf = cbf; mNotificationFrames = notificationFrames; Loading Loading @@ -360,7 +366,7 @@ bool AudioRecord::stopped() const uint32_t AudioRecord::getSampleRate() const { return mCblk->sampleRate; return mSampleRate; } status_t AudioRecord::setMarkerPosition(uint32_t marker) Loading Loading @@ -473,11 +479,18 @@ status_t AudioRecord::openRecord_l( mBuffers = (char*)cblk + sizeof(audio_track_cblk_t); cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; cblk->waitTimeMs = 0; // update proxy delete mProxy; mProxy = new AudioRecordClientProxy(cblk, mBuffers, frameCount, mFrameSize); return NO_ERROR; } status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) { ALOG_ASSERT(mStatus == NO_ERROR && mProxy != NULL); AutoMutex lock(mLock); bool active; status_t result = NO_ERROR; Loading @@ -488,7 +501,7 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) audioBuffer->frameCount = 0; audioBuffer->size = 0; uint32_t framesReady = cblk->framesReadyIn(); size_t framesReady = mProxy->framesReady(); if (framesReady == 0) { cblk->lock.lock(); Loading Loading @@ -551,7 +564,7 @@ create_new_record: } // read the server count again start_loop_here: framesReady = cblk->framesReadyIn(); framesReady = mProxy->framesReady(); } cblk->lock.unlock(); } Loading @@ -573,15 +586,17 @@ create_new_record: audioBuffer->frameCount = framesReq; audioBuffer->size = framesReq * mFrameSize; audioBuffer->raw = cblk->buffer(mBuffers, mFrameSize, u); audioBuffer->raw = mProxy->buffer(u); active = mActive; return active ? status_t(NO_ERROR) : status_t(STOPPED); } void AudioRecord::releaseBuffer(Buffer* audioBuffer) { ALOG_ASSERT(mStatus == NO_ERROR && mProxy != NULL); AutoMutex lock(mLock); mCblk->stepUserIn(audioBuffer->frameCount, mFrameCount); (void) mProxy->stepUser(audioBuffer->frameCount); } audio_io_handle_t AudioRecord::getInput() const Loading @@ -594,7 +609,7 @@ audio_io_handle_t AudioRecord::getInput() const audio_io_handle_t AudioRecord::getInput_l() { mInput = AudioSystem::getInput(mInputSource, mCblk->sampleRate, mSampleRate, mFormat, mChannelMask, mSessionId); Loading Loading @@ -746,7 +761,7 @@ bool AudioRecord::processAudioBuffer(const sp<AudioRecordThread>& thread) // Manage overrun callback if (active && (cblk->framesAvailableIn(mFrameCount) == 0)) { if (active && (mProxy->framesAvailable() == 0)) { // 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); Loading Loading @@ -782,7 +797,7 @@ status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& refCblk) // if the new IAudioRecord is created, openRecord_l() will modify the // following member variables: mAudioRecord, mCblkMemory and mCblk. // It will also delete the strong references on previous IAudioRecord and IMemory result = openRecord_l(cblk->sampleRate, mFormat, mFrameCount, getInput_l()); result = openRecord_l(mSampleRate, mFormat, mFrameCount, getInput_l()); if (result == NO_ERROR) { newCblk = mCblk; // callback thread or sync event hasn't changed Loading media/libmedia/AudioTrack.cpp +71 −38 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
include/media/AudioRecord.h +3 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ namespace android { class audio_track_cblk_t; class AudioRecordClientProxy; // ---------------------------------------------------------------------------- Loading Loading @@ -374,6 +375,7 @@ private: uint32_t mUpdatePeriod; // in ms // constant after constructor or set() uint32_t mSampleRate; size_t mFrameCount; audio_format_t mFormat; uint8_t mChannelCount; Loading @@ -393,6 +395,7 @@ private: int mPreviousPriority; // before start() SchedPolicy mPreviousSchedulingGroup; AudioRecordClientProxy* mProxy; }; }; // namespace android Loading
include/media/AudioTrack.h +3 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ namespace android { // ---------------------------------------------------------------------------- class audio_track_cblk_t; class AudioTrackClientProxy; // ---------------------------------------------------------------------------- Loading Loading @@ -538,6 +539,7 @@ protected: float mVolume[2]; float mSendLevel; uint32_t mSampleRate; size_t mFrameCount; // corresponds to current IAudioTrack size_t mReqFrameCount; // frame count to request the next time a new // IAudioTrack is needed Loading Loading @@ -596,6 +598,7 @@ protected: bool mIsTimed; int mPreviousPriority; // before start() SchedPolicy mPreviousSchedulingGroup; AudioTrackClientProxy* mProxy; }; class TimedAudioTrack : public AudioTrack Loading
include/private/media/AudioTrackShared.h +183 −45 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <sys/types.h> #include <utils/threads.h> #include <utils/Log.h> namespace android { Loading @@ -38,9 +39,26 @@ namespace android { #define CBLK_INVALID 0x04 // track buffer invalidated by AudioFlinger, need to re-create #define CBLK_DISABLED 0x08 // track disabled by AudioFlinger due to underrun, need to re-start struct AudioTrackSharedStreaming { // similar to NBAIO MonoPipe volatile int32_t mFront; volatile int32_t mRear; }; // future struct AudioTrackSharedStatic { int mReserved; }; // ---------------------------------------------------------------------------- // Important: do not add any virtual methods, including ~ struct audio_track_cblk_t { friend class Proxy; friend class AudioTrackClientProxy; friend class AudioRecordClientProxy; friend class ServerProxy; // The data members are grouped so that members accessed frequently and in the same context // are in the same line of data cache. Loading Loading @@ -72,12 +90,13 @@ struct audio_track_cblk_t // For AudioTrack only, not used by AudioRecord. private: uint32_t mVolumeLR; public: uint32_t sampleRate; uint32_t mSampleRate; // AudioTrack only: client's requested sample rate in Hz // or 0 == default. Write-only client, read-only server. uint8_t mPad2; // unused public: // read-only for client, server writes once at initialization and is then read-only uint8_t mName; // normal tracks: track name, fast tracks: track index Loading @@ -94,65 +113,184 @@ public: // Cache line boundary (32 bytes) #if 0 union { AudioTrackSharedStreaming mStreaming; AudioTrackSharedStatic mStatic; int mAlign[8]; } u; // Cache line boundary (32 bytes) #endif // Since the control block is always located in shared memory, this constructor // is only used for placement new(). It is never used for regular new() or stack. audio_track_cblk_t(); // called by client only, where client includes regular // AudioTrack and AudioFlinger::PlaybackThread::OutputTrack uint32_t stepUserIn(size_t stepCount, size_t frameCount) { return stepUser(stepCount, frameCount, false); } uint32_t stepUserOut(size_t stepCount, size_t frameCount) { return stepUser(stepCount, frameCount, true); } bool stepServer(size_t stepCount, size_t frameCount, bool isOut); private: // if there is a shared buffer, "buffers" is the value of pointer() for the shared // buffer, otherwise "buffers" points immediately after the control block void* buffer(void *buffers, uint32_t frameSize, uint32_t offset) const; uint32_t framesAvailableIn(size_t frameCount) { return framesAvailable(frameCount, false); } uint32_t framesAvailableOut(size_t frameCount) { return framesAvailable(frameCount, true); } uint32_t framesAvailableIn_l(size_t frameCount) { return framesAvailable_l(frameCount, false); } uint32_t framesAvailableOut_l(size_t frameCount) { return framesAvailable_l(frameCount, true); } uint32_t framesReadyIn() { return framesReady(false); } uint32_t framesReadyOut() { return framesReady(true); } void* buffer(void *buffers, uint32_t frameSize, size_t offset) const; bool tryLock(); // isOut == true means AudioTrack, isOut == false means AudioRecord bool stepServer(size_t stepCount, size_t frameCount, bool isOut); uint32_t stepUser(size_t stepCount, size_t frameCount, bool isOut); uint32_t framesAvailable(size_t frameCount, bool isOut); uint32_t framesAvailable_l(size_t frameCount, bool isOut); uint32_t framesReady(bool isOut); }; // ---------------------------------------------------------------------------- // Proxy for shared memory control block, to isolate callers from needing to know the details. // There is exactly one ClientProxy and one ServerProxy per shared memory control block. // The proxies are located in normal memory, and are not multi-thread safe within a given side. class Proxy { protected: Proxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize) : mCblk(cblk), mBuffers(buffers), mFrameCount(frameCount), mFrameSize(frameSize) { } virtual ~Proxy() { } public: void* buffer(size_t offset) const { return mCblk->buffer(mBuffers, mFrameSize, offset); } protected: // These refer to shared memory, and are virtual addresses with respect to the current process. // They may have different virtual addresses within the other process. audio_track_cblk_t* const mCblk; // the control block void* const mBuffers; // starting address of buffers const size_t mFrameCount; // not necessarily a power of 2 const size_t mFrameSize; // in bytes #if 0 const size_t mFrameCountP2; // mFrameCount rounded to power of 2, streaming mode #endif }; // ---------------------------------------------------------------------------- // Proxy seen by AudioTrack client and AudioRecord client class ClientProxy : public Proxy { protected: ClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize) : Proxy(cblk, buffers, frameCount, frameSize) { } virtual ~ClientProxy() { } }; // ---------------------------------------------------------------------------- // Proxy used by AudioTrack client, which also includes AudioFlinger::PlaybackThread::OutputTrack class AudioTrackClientProxy : public ClientProxy { public: AudioTrackClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize) : ClientProxy(cblk, buffers, frameCount, frameSize) { } virtual ~AudioTrackClientProxy() { } // No barriers on the following operations, so the ordering of loads/stores // with respect to other parameters is UNPREDICTABLE. That's considered safe. // for AudioTrack client only, caller must limit to 0.0 <= sendLevel <= 1.0 // caller must limit to 0.0 <= sendLevel <= 1.0 void setSendLevel(float sendLevel) { mSendLevel = uint16_t(sendLevel * 0x1000); mCblk->mSendLevel = uint16_t(sendLevel * 0x1000); } // for AudioFlinger only; the return value must be validated by the caller uint16_t getSendLevel_U4_12() const { return mSendLevel; // caller must limit to 0 <= volumeLR <= 0x10001000 void setVolumeLR(uint32_t volumeLR) { mCblk->mVolumeLR = volumeLR; } // for AudioTrack client only, caller must limit to 0 <= volumeLR <= 0x10001000 void setVolumeLR(uint32_t volumeLR) { mVolumeLR = volumeLR; void setSampleRate(uint32_t sampleRate) { mCblk->mSampleRate = sampleRate; } // for AudioFlinger only; the return value must be validated by the caller uint32_t getVolumeLR() const { return mVolumeLR; // called by: // PlaybackThread::OutputTrack::write // AudioTrack::createTrack_l // AudioTrack::releaseBuffer // AudioTrack::reload // AudioTrack::restoreTrack_l (2 places) size_t stepUser(size_t stepCount) { return mCblk->stepUser(stepCount, mFrameCount, true /*isOut*/); } // called by AudioTrack::obtainBuffer and AudioTrack::processBuffer size_t framesAvailable() { return mCblk->framesAvailable(mFrameCount, true /*isOut*/); } // called by AudioTrack::obtainBuffer and PlaybackThread::OutputTrack::obtainBuffer // FIXME remove this API since it assumes a lock that should be invisible to caller size_t framesAvailable_l() { return mCblk->framesAvailable_l(mFrameCount, true /*isOut*/); } private: // isOut == true means AudioTrack, isOut == false means AudioRecord uint32_t stepUser(size_t stepCount, size_t frameCount, bool isOut); uint32_t framesAvailable(size_t frameCount, bool isOut); uint32_t framesAvailable_l(size_t frameCount, bool isOut); uint32_t framesReady(bool isOut); }; // ---------------------------------------------------------------------------- // Proxy used by AudioRecord client class AudioRecordClientProxy : public ClientProxy { public: AudioRecordClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize) : ClientProxy(cblk, buffers, frameCount, frameSize) { } ~AudioRecordClientProxy() { } // called by AudioRecord::releaseBuffer size_t stepUser(size_t stepCount) { return mCblk->stepUser(stepCount, mFrameCount, false /*isOut*/); } // called by AudioRecord::processBuffer size_t framesAvailable() { return mCblk->framesAvailable(mFrameCount, false /*isOut*/); } // called by AudioRecord::obtainBuffer size_t framesReady() { return mCblk->framesReady(false /*isOut*/); } }; // ---------------------------------------------------------------------------- // Proxy used by AudioFlinger server class ServerProxy : public Proxy { public: ServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, bool isOut) : Proxy(cblk, buffers, frameCount, frameSize), mIsOut(isOut) { } virtual ~ServerProxy() { } // for AudioTrack and AudioRecord bool step(size_t stepCount) { return mCblk->stepServer(stepCount, mFrameCount, mIsOut); } // return value of these methods must be validated by the caller uint32_t getSampleRate() const { return mCblk->mSampleRate; } uint16_t getSendLevel_U4_12() const { return mCblk->mSendLevel; } uint32_t getVolumeLR() const { return mCblk->mVolumeLR; } // for AudioTrack only size_t framesReady() { ALOG_ASSERT(mIsOut); return mCblk->framesReady(true); } // for AudioRecord only, called by RecordThread::RecordTrack::getNextBuffer // FIXME remove this API since it assumes a lock that should be invisible to caller size_t framesAvailableIn_l() { ALOG_ASSERT(!mIsOut); return mCblk->framesAvailable_l(mFrameCount, false); } private: const bool mIsOut; // true for AudioTrack, false for AudioRecord }; // ---------------------------------------------------------------------------- Loading
media/libmedia/AudioRecord.cpp +31 −16 Original line number Diff line number Diff line Loading @@ -75,7 +75,8 @@ status_t AudioRecord::getMinFrameCount( AudioRecord::AudioRecord() : mStatus(NO_INIT), mSessionId(0), mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT) mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT), mProxy(NULL) { } Loading @@ -90,7 +91,9 @@ AudioRecord::AudioRecord( int notificationFrames, int sessionId) : mStatus(NO_INIT), mSessionId(0), mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT) mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT), mProxy(NULL) { mStatus = set(inputSource, sampleRate, format, channelMask, frameCount, cbf, user, notificationFrames, sessionId); Loading @@ -112,6 +115,7 @@ AudioRecord::~AudioRecord() IPCThreadState::self()->flushCommands(); AudioSystem::releaseAudioSessionId(mSessionId); } delete mProxy; } status_t AudioRecord::set( Loading Loading @@ -149,6 +153,8 @@ status_t AudioRecord::set( if (sampleRate == 0) { sampleRate = DEFAULT_SAMPLE_RATE; } mSampleRate = sampleRate; // these below should probably come from the audioFlinger too... if (format == AUDIO_FORMAT_DEFAULT) { format = AUDIO_FORMAT_PCM_16_BIT; Loading @@ -166,6 +172,12 @@ status_t AudioRecord::set( uint32_t channelCount = popcount(channelMask); mChannelCount = channelCount; if (audio_is_linear_pcm(mFormat)) { mFrameSize = channelCount * audio_bytes_per_sample(format); } else { mFrameSize = sizeof(uint8_t); } if (sessionId == 0 ) { mSessionId = AudioSystem::newAudioSessionId(); } else { Loading Loading @@ -218,12 +230,6 @@ status_t AudioRecord::set( // Update buffer size in case it has been limited by AudioFlinger during track creation mFrameCount = mCblk->frameCount_; if (audio_is_linear_pcm(mFormat)) { mFrameSize = channelCount * audio_bytes_per_sample(format); } else { mFrameSize = sizeof(uint8_t); } mActive = false; mCbf = cbf; mNotificationFrames = notificationFrames; Loading Loading @@ -360,7 +366,7 @@ bool AudioRecord::stopped() const uint32_t AudioRecord::getSampleRate() const { return mCblk->sampleRate; return mSampleRate; } status_t AudioRecord::setMarkerPosition(uint32_t marker) Loading Loading @@ -473,11 +479,18 @@ status_t AudioRecord::openRecord_l( mBuffers = (char*)cblk + sizeof(audio_track_cblk_t); cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; cblk->waitTimeMs = 0; // update proxy delete mProxy; mProxy = new AudioRecordClientProxy(cblk, mBuffers, frameCount, mFrameSize); return NO_ERROR; } status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) { ALOG_ASSERT(mStatus == NO_ERROR && mProxy != NULL); AutoMutex lock(mLock); bool active; status_t result = NO_ERROR; Loading @@ -488,7 +501,7 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) audioBuffer->frameCount = 0; audioBuffer->size = 0; uint32_t framesReady = cblk->framesReadyIn(); size_t framesReady = mProxy->framesReady(); if (framesReady == 0) { cblk->lock.lock(); Loading Loading @@ -551,7 +564,7 @@ create_new_record: } // read the server count again start_loop_here: framesReady = cblk->framesReadyIn(); framesReady = mProxy->framesReady(); } cblk->lock.unlock(); } Loading @@ -573,15 +586,17 @@ create_new_record: audioBuffer->frameCount = framesReq; audioBuffer->size = framesReq * mFrameSize; audioBuffer->raw = cblk->buffer(mBuffers, mFrameSize, u); audioBuffer->raw = mProxy->buffer(u); active = mActive; return active ? status_t(NO_ERROR) : status_t(STOPPED); } void AudioRecord::releaseBuffer(Buffer* audioBuffer) { ALOG_ASSERT(mStatus == NO_ERROR && mProxy != NULL); AutoMutex lock(mLock); mCblk->stepUserIn(audioBuffer->frameCount, mFrameCount); (void) mProxy->stepUser(audioBuffer->frameCount); } audio_io_handle_t AudioRecord::getInput() const Loading @@ -594,7 +609,7 @@ audio_io_handle_t AudioRecord::getInput() const audio_io_handle_t AudioRecord::getInput_l() { mInput = AudioSystem::getInput(mInputSource, mCblk->sampleRate, mSampleRate, mFormat, mChannelMask, mSessionId); Loading Loading @@ -746,7 +761,7 @@ bool AudioRecord::processAudioBuffer(const sp<AudioRecordThread>& thread) // Manage overrun callback if (active && (cblk->framesAvailableIn(mFrameCount) == 0)) { if (active && (mProxy->framesAvailable() == 0)) { // 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); Loading Loading @@ -782,7 +797,7 @@ status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& refCblk) // if the new IAudioRecord is created, openRecord_l() will modify the // following member variables: mAudioRecord, mCblkMemory and mCblk. // It will also delete the strong references on previous IAudioRecord and IMemory result = openRecord_l(cblk->sampleRate, mFormat, mFrameCount, getInput_l()); result = openRecord_l(mSampleRate, mFormat, mFrameCount, getInput_l()); if (result == NO_ERROR) { newCblk = mCblk; // callback thread or sync event hasn't changed Loading
media/libmedia/AudioTrack.cpp +71 −38 File changed.Preview size limit exceeded, changes collapsed. Show changes