summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/media/AudioRecord.h3
-rw-r--r--include/media/AudioTrack.h3
-rw-r--r--include/private/media/AudioTrackShared.h228
-rw-r--r--media/libmedia/AudioRecord.cpp47
-rw-r--r--media/libmedia/AudioTrack.cpp109
-rw-r--r--media/libmedia/AudioTrackShared.cpp2
-rw-r--r--services/audioflinger/AudioFlinger.h1
-rw-r--r--services/audioflinger/PlaybackTracks.h3
-rw-r--r--services/audioflinger/RecordTracks.h2
-rw-r--r--services/audioflinger/Threads.cpp21
-rw-r--r--services/audioflinger/TrackBase.h9
-rw-r--r--services/audioflinger/Tracks.cpp97
12 files changed, 355 insertions, 170 deletions
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index ae444c3..38c6548 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -29,6 +29,7 @@
namespace android {
class audio_track_cblk_t;
+class AudioRecordClientProxy;
// ----------------------------------------------------------------------------
@@ -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;
@@ -393,6 +395,7 @@ private:
int mPreviousPriority; // before start()
SchedPolicy mPreviousSchedulingGroup;
+ AudioRecordClientProxy* mProxy;
};
}; // namespace android
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 6f85527..9d07ed5 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -36,6 +36,7 @@ namespace android {
// ----------------------------------------------------------------------------
class audio_track_cblk_t;
+class AudioTrackClientProxy;
// ----------------------------------------------------------------------------
@@ -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
@@ -596,6 +598,7 @@ protected:
bool mIsTimed;
int mPreviousPriority; // before start()
SchedPolicy mPreviousSchedulingGroup;
+ AudioTrackClientProxy* mProxy;
};
class TimedAudioTrack : public AudioTrack
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index 48b6b21..41e20f8 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -21,6 +21,7 @@
#include <sys/types.h>
#include <utils/threads.h>
+#include <utils/Log.h>
namespace android {
@@ -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.
@@ -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
@@ -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();
- // 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
- void setSendLevel(float sendLevel) {
- 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;
- }
-
- // for AudioTrack client only, caller must limit to 0 <= volumeLR <= 0x10001000
- void setVolumeLR(uint32_t volumeLR) {
- mVolumeLR = volumeLR;
- }
-
- // for AudioFlinger only; the return value must be validated by the caller
- uint32_t getVolumeLR() const {
- return mVolumeLR;
- }
-
-private:
// 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.
+
+ // caller must limit to 0.0 <= sendLevel <= 1.0
+ void setSendLevel(float sendLevel) {
+ mCblk->mSendLevel = uint16_t(sendLevel * 0x1000);
+ }
+
+ // caller must limit to 0 <= volumeLR <= 0x10001000
+ void setVolumeLR(uint32_t volumeLR) {
+ mCblk->mVolumeLR = volumeLR;
+ }
+
+ void setSampleRate(uint32_t sampleRate) {
+ mCblk->mSampleRate = sampleRate;
+ }
+
+ // 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*/);
+ }
+
+};
+
+// ----------------------------------------------------------------------------
+
+// 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
+
+};
// ----------------------------------------------------------------------------
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index c2ef68c..8eb1656 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -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)
{
}
@@ -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);
@@ -112,6 +115,7 @@ AudioRecord::~AudioRecord()
IPCThreadState::self()->flushCommands();
AudioSystem::releaseAudioSessionId(mSessionId);
}
+ delete mProxy;
}
status_t AudioRecord::set(
@@ -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;
@@ -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 {
@@ -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;
@@ -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)
@@ -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;
@@ -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();
@@ -551,7 +564,7 @@ create_new_record:
}
// read the server count again
start_loop_here:
- framesReady = cblk->framesReadyIn();
+ framesReady = mProxy->framesReady();
}
cblk->lock.unlock();
}
@@ -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
@@ -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);
@@ -745,7 +760,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);
@@ -781,7 +796,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
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 1d87ff8..86a5579 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -97,7 +97,8 @@ AudioTrack::AudioTrack()
: mStatus(NO_INIT),
mIsTimed(false),
mPreviousPriority(ANDROID_PRIORITY_NORMAL),
- mPreviousSchedulingGroup(SP_DEFAULT)
+ mPreviousSchedulingGroup(SP_DEFAULT),
+ mProxy(NULL)
{
}
@@ -115,7 +116,8 @@ AudioTrack::AudioTrack(
: mStatus(NO_INIT),
mIsTimed(false),
mPreviousPriority(ANDROID_PRIORITY_NORMAL),
- mPreviousSchedulingGroup(SP_DEFAULT)
+ mPreviousSchedulingGroup(SP_DEFAULT),
+ mProxy(NULL)
{
mStatus = set(streamType, sampleRate, format, channelMask,
frameCount, flags, cbf, user, notificationFrames,
@@ -136,7 +138,8 @@ AudioTrack::AudioTrack(
: mStatus(NO_INIT),
mIsTimed(false),
mPreviousPriority(ANDROID_PRIORITY_NORMAL),
- mPreviousSchedulingGroup(SP_DEFAULT)
+ mPreviousSchedulingGroup(SP_DEFAULT),
+ mProxy(NULL)
{
if (sharedBuffer == 0) {
ALOGE("sharedBuffer must be non-0");
@@ -166,6 +169,7 @@ AudioTrack::~AudioTrack()
IPCThreadState::self()->flushCommands();
AudioSystem::releaseAudioSessionId(mSessionId);
}
+ delete mProxy;
}
status_t AudioTrack::set(
@@ -212,6 +216,7 @@ status_t AudioTrack::set(
}
sampleRate = afSampleRate;
}
+ mSampleRate = sampleRate;
// these below should probably come from the audioFlinger too...
if (format == AUDIO_FORMAT_DEFAULT) {
@@ -252,6 +257,14 @@ status_t AudioTrack::set(
uint32_t channelCount = popcount(channelMask);
mChannelCount = channelCount;
+ if (audio_is_linear_pcm(format)) {
+ mFrameSize = channelCount * audio_bytes_per_sample(format);
+ mFrameSizeAF = channelCount * sizeof(int16_t);
+ } else {
+ mFrameSize = sizeof(uint8_t);
+ mFrameSizeAF = sizeof(uint8_t);
+ }
+
audio_io_handle_t output = AudioSystem::getOutput(
streamType,
sampleRate, format, channelMask,
@@ -300,14 +313,6 @@ status_t AudioTrack::set(
mStreamType = streamType;
mFormat = format;
- if (audio_is_linear_pcm(format)) {
- mFrameSize = channelCount * audio_bytes_per_sample(format);
- mFrameSizeAF = channelCount * sizeof(int16_t);
- } else {
- mFrameSize = sizeof(uint8_t);
- mFrameSizeAF = sizeof(uint8_t);
- }
-
mSharedBuffer = sharedBuffer;
mActive = false;
mUserData = user;
@@ -460,6 +465,11 @@ void AudioTrack::pause()
status_t AudioTrack::setVolume(float left, float right)
{
+ if (mStatus != NO_ERROR) {
+ return mStatus;
+ }
+ ALOG_ASSERT(mProxy != NULL);
+
if (left < 0.0f || left > 1.0f || right < 0.0f || right > 1.0f) {
return BAD_VALUE;
}
@@ -468,7 +478,7 @@ status_t AudioTrack::setVolume(float left, float right)
mVolume[LEFT] = left;
mVolume[RIGHT] = right;
- mCblk->setVolumeLR((uint32_t(uint16_t(right * 0x1000)) << 16) | uint16_t(left * 0x1000));
+ mProxy->setVolumeLR((uint32_t(uint16_t(right * 0x1000)) << 16) | uint16_t(left * 0x1000));
return NO_ERROR;
}
@@ -481,14 +491,19 @@ status_t AudioTrack::setVolume(float volume)
status_t AudioTrack::setAuxEffectSendLevel(float level)
{
ALOGV("setAuxEffectSendLevel(%f)", level);
+
+ if (mStatus != NO_ERROR) {
+ return mStatus;
+ }
+ ALOG_ASSERT(mProxy != NULL);
+
if (level < 0.0f || level > 1.0f) {
return BAD_VALUE;
}
AutoMutex lock(mLock);
mSendLevel = level;
-
- mCblk->setSendLevel(level);
+ mProxy->setSendLevel(level);
return NO_ERROR;
}
@@ -517,7 +532,9 @@ status_t AudioTrack::setSampleRate(uint32_t rate)
}
AutoMutex lock(mLock);
- mCblk->sampleRate = rate;
+ mSampleRate = rate;
+ mProxy->setSampleRate(rate);
+
return NO_ERROR;
}
@@ -528,7 +545,7 @@ uint32_t AudioTrack::getSampleRate() const
}
AutoMutex lock(mLock);
- return mCblk->sampleRate;
+ return mSampleRate;
}
status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount)
@@ -665,6 +682,11 @@ status_t AudioTrack::getPosition(uint32_t *position)
status_t AudioTrack::reload()
{
+ if (mStatus != NO_ERROR) {
+ return mStatus;
+ }
+ ALOG_ASSERT(mProxy != NULL);
+
if (mSharedBuffer == 0 || mIsTimed) {
return INVALID_OPERATION;
}
@@ -677,8 +699,7 @@ status_t AudioTrack::reload()
flush_l();
- audio_track_cblk_t* cblk = mCblk;
- cblk->stepUserOut(mFrameCount, mFrameCount);
+ (void) mProxy->stepUser(mFrameCount);
return NO_ERROR;
}
@@ -693,7 +714,7 @@ audio_io_handle_t AudioTrack::getOutput()
audio_io_handle_t AudioTrack::getOutput_l()
{
return AudioSystem::getOutput(mStreamType,
- mCblk->sampleRate, mFormat, mChannelMask, mFlags);
+ mSampleRate, mFormat, mChannelMask, mFlags);
}
status_t AudioTrack::attachAuxEffect(int effectId)
@@ -890,13 +911,8 @@ status_t AudioTrack::createTrack_l(
mBuffers = (char*)cblk + sizeof(audio_track_cblk_t);
} else {
mBuffers = sharedBuffer->pointer();
- // Force buffer full condition as data is already present in shared memory
- cblk->stepUserOut(frameCount, frameCount);
}
- cblk->setVolumeLR((uint32_t(uint16_t(mVolume[RIGHT] * 0x1000)) << 16) |
- uint16_t(mVolume[LEFT] * 0x1000));
- cblk->setSendLevel(mSendLevel);
mAudioTrack->attachAuxEffect(mAuxEffectId);
cblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
cblk->waitTimeMs = 0;
@@ -909,11 +925,26 @@ status_t AudioTrack::createTrack_l(
if (frameCount > mReqFrameCount) {
mReqFrameCount = frameCount;
}
+
+ // update proxy
+ delete mProxy;
+ mProxy = new AudioTrackClientProxy(cblk, mBuffers, frameCount, mFrameSizeAF);
+ mProxy->setVolumeLR((uint32_t(uint16_t(mVolume[RIGHT] * 0x1000)) << 16) |
+ uint16_t(mVolume[LEFT] * 0x1000));
+ mProxy->setSendLevel(mSendLevel);
+ mProxy->setSampleRate(mSampleRate);
+ if (sharedBuffer != 0) {
+ // Force buffer full condition as data is already present in shared memory
+ mProxy->stepUser(frameCount);
+ }
+
return NO_ERROR;
}
status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
{
+ ALOG_ASSERT(mStatus == NO_ERROR && mProxy != NULL);
+
AutoMutex lock(mLock);
bool active;
status_t result = NO_ERROR;
@@ -924,7 +955,7 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
audioBuffer->frameCount = 0;
audioBuffer->size = 0;
- uint32_t framesAvail = cblk->framesAvailableOut(mFrameCount);
+ size_t framesAvail = mProxy->framesAvailable();
cblk->lock.lock();
if (cblk->flags & CBLK_INVALID) {
@@ -1000,7 +1031,7 @@ create_new_track:
}
// read the server count again
start_loop_here:
- framesAvail = cblk->framesAvailableOut_l(mFrameCount);
+ framesAvail = mProxy->framesAvailable_l();
}
cblk->lock.unlock();
}
@@ -1020,16 +1051,18 @@ create_new_track:
audioBuffer->frameCount = framesReq;
audioBuffer->size = framesReq * mFrameSizeAF;
- audioBuffer->raw = cblk->buffer(mBuffers, mFrameSizeAF, u);
+ audioBuffer->raw = mProxy->buffer(u);
active = mActive;
return active ? status_t(NO_ERROR) : status_t(STOPPED);
}
void AudioTrack::releaseBuffer(Buffer* audioBuffer)
{
+ ALOG_ASSERT(mStatus == NO_ERROR && mProxy != NULL);
+
AutoMutex lock(mLock);
audio_track_cblk_t* cblk = mCblk;
- cblk->stepUserOut(audioBuffer->frameCount, mFrameCount);
+ (void) mProxy->stepUser(audioBuffer->frameCount);
if (audioBuffer->frameCount > 0) {
// restart track if it was disabled by audioflinger due to previous underrun
if (mActive && (cblk->flags & CBLK_DISABLED)) {
@@ -1199,7 +1232,7 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread)
// so all cblk references might still refer to old shared memory, but that should be benign
// Manage underrun callback
- if (active && (cblk->framesAvailableOut(mFrameCount) == mFrameCount)) {
+ if (active && (mProxy->framesAvailable() == 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);
@@ -1346,7 +1379,7 @@ status_t AudioTrack::restoreTrack_l(audio_track_cblk_t*& refCblk, bool fromStart
// following member variables: mAudioTrack, mCblkMemory and mCblk.
// It will also delete the strong references on previous IAudioTrack and IMemory
result = createTrack_l(mStreamType,
- cblk->sampleRate,
+ mSampleRate,
mFormat,
mReqFrameCount, // so that frame count never goes down
mFlags,
@@ -1365,12 +1398,12 @@ status_t AudioTrack::restoreTrack_l(audio_track_cblk_t*& refCblk, bool fromStart
// restore loop: this is not guaranteed to succeed if new frame count is not
// compatible with loop length
setLoop_l(cblk->loopStart, cblk->loopEnd, cblk->loopCount);
+ size_t frames = 0;
if (!fromStart) {
newCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
// Make sure that a client relying on callback events indicating underrun or
// the actual amount of audio frames played (e.g SoundPool) receives them.
if (mSharedBuffer == 0) {
- uint32_t frames = 0;
if (user > server) {
frames = ((user - server) > mFrameCount) ?
mFrameCount : (user - server);
@@ -1378,13 +1411,15 @@ status_t AudioTrack::restoreTrack_l(audio_track_cblk_t*& refCblk, bool fromStart
}
// 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, mFrameCount);
}
}
if (mSharedBuffer != 0) {
- newCblk->stepUserOut(mFrameCount, mFrameCount);
+ frames = mFrameCount;
+ }
+ if (frames > 0) {
+ // stepUser() clears CBLK_UNDERRUN flag enabling underrun callbacks to
+ // the client
+ mProxy->stepUser(frames);
}
if (mActive) {
result = mAudioTrack->start();
@@ -1416,7 +1451,6 @@ status_t AudioTrack::dump(int fd, const Vector<String16>& args) const
char buffer[SIZE];
String8 result;
- audio_track_cblk_t* cblk = mCblk;
result.append(" AudioTrack::dump\n");
snprintf(buffer, 255, " stream type(%d), left - right volume(%f, %f)\n", mStreamType,
mVolume[0], mVolume[1]);
@@ -1424,8 +1458,7 @@ status_t AudioTrack::dump(int fd, const Vector<String16>& args) const
snprintf(buffer, 255, " format(%d), channel count(%d), frame count(%d)\n", mFormat,
mChannelCount, mFrameCount);
result.append(buffer);
- snprintf(buffer, 255, " sample rate(%u), status(%d)\n",
- (cblk == 0) ? 0 : cblk->sampleRate, mStatus);
+ snprintf(buffer, 255, " sample rate(%u), status(%d)\n", mSampleRate, mStatus);
result.append(buffer);
snprintf(buffer, 255, " active(%d), latency (%d)\n", mActive, mLatency);
result.append(buffer);
diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp
index bee13c8..13d47c9 100644
--- a/media/libmedia/AudioTrackShared.cpp
+++ b/media/libmedia/AudioTrackShared.cpp
@@ -26,7 +26,7 @@ audio_track_cblk_t::audio_track_cblk_t()
: lock(Mutex::SHARED), cv(Condition::SHARED), user(0), server(0),
userBase(0), serverBase(0), frameCount_(0),
loopStart(UINT_MAX), loopEnd(UINT_MAX), loopCount(0), mVolumeLR(0x10001000),
- mSendLevel(0), flags(0)
+ mSampleRate(0), mSendLevel(0), flags(0)
{
}
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