summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorGlenn Kasten <gkasten@google.com>2012-12-04 12:22:46 -0800
committerGlenn Kasten <gkasten@google.com>2012-12-12 12:21:59 -0800
commite3aa659e9cee7df5c12a80d285cc29ab3b2cbb39 (patch)
tree90fdb6e9da1a03f4f24691aae27ae94ff913f1c7 /media
parent84b6440fa1d1274267deabe0bd8dc626b5548e4c (diff)
downloadframeworks_av-e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39.zip
frameworks_av-e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39.tar.gz
frameworks_av-e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39.tar.bz2
Start isolating control block accesses in a proxy
The proxy object will eventually be the only code that understands the details of the control block. This should make it easier to change the control block in the future. Initial set of control block fields that are isolated: - sample rate - send level - volume Prepare for streaming/static separation by adding a union to the control block for the new fields. Fix bug in handling of max sample rate on a track. It was only checking at re-configuration, not at each mix. Simplify OutputTrack::obtainBuffer. Change-Id: I2249f9d04f73a911a922ad1d7f6197292c74cd92
Diffstat (limited to 'media')
-rw-r--r--media/libmedia/AudioRecord.cpp47
-rw-r--r--media/libmedia/AudioTrack.cpp109
-rw-r--r--media/libmedia/AudioTrackShared.cpp2
3 files changed, 103 insertions, 55 deletions
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)
{
}