summaryrefslogtreecommitdiffstats
path: root/media/libmedia/AudioTrack.cpp
diff options
context:
space:
mode:
authorAndy Hung <hunga@google.com>2014-12-15 16:42:05 -0800
committerAndy Hung <hunga@google.com>2015-01-06 11:59:41 -0800
commit53c3b5fc1afe162a8669cb3d27d6bb14e1847e39 (patch)
tree1ccceb0cb183f01cdca8198606933b8fefc724a6 /media/libmedia/AudioTrack.cpp
parent4ede21d9c1f957baf5e561849ff9bbe4bcbefc20 (diff)
downloadframeworks_av-53c3b5fc1afe162a8669cb3d27d6bb14e1847e39.zip
frameworks_av-53c3b5fc1afe162a8669cb3d27d6bb14e1847e39.tar.gz
frameworks_av-53c3b5fc1afe162a8669cb3d27d6bb14e1847e39.tar.bz2
Improve AudioTrack EVENT_LOOP_END and EVENT_BUFFER_END accuracy
Fix timing computation to consider current position. Fix EVENT_LOOP_END count accuracy (some could be dropped before) for non-infinite loop static AudioTracks. Change-Id: I255f692915b55ab6f08ccd6a2365fee3f5d0a4fe
Diffstat (limited to 'media/libmedia/AudioTrack.cpp')
-rw-r--r--media/libmedia/AudioTrack.cpp51
1 files changed, 40 insertions, 11 deletions
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 422ead1..ea7b2df 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -33,7 +33,7 @@
#define WAIT_PERIOD_MS 10
#define WAIT_STREAM_END_TIMEOUT_SEC 120
-
+static const int kMaxLoopCountNotifications = 32;
namespace android {
// ---------------------------------------------------------------------------
@@ -428,6 +428,7 @@ status_t AudioTrack::set(
mLoopCount = 0;
mLoopStart = 0;
mLoopEnd = 0;
+ mLoopCountNotified = 0;
mMarkerPosition = 0;
mMarkerReached = false;
mNewPosition = 0;
@@ -750,6 +751,7 @@ void AudioTrack::setLoop_l(uint32_t loopStart, uint32_t loopEnd, int loopCount)
mLoopCount = loopCount;
mLoopEnd = loopEnd;
mLoopStart = loopStart;
+ mLoopCountNotified = loopCount;
mStaticProxy->setLoop(loopStart, loopEnd, loopCount);
}
@@ -899,10 +901,15 @@ status_t AudioTrack::reload()
mNewPosition = mUpdatePeriod;
(void) updateAndGetPosition_l();
mPosition = 0;
+#if 0
// The documentation is not clear on the behavior of reload() and the restoration
- // of loop count. Historically we have not restored loop count, start, end;
- // rather we just reset the buffer position. However, restoring the last setLoop
- // information makes sense if one desires to repeat playing a particular sound.
+ // of loop count. Historically we have not restored loop count, start, end,
+ // but it makes sense if one desires to repeat playing a particular sound.
+ if (mLoopCount != 0) {
+ mLoopCountNotified = mLoopCount;
+ mStaticProxy->setLoop(mLoopStart, mLoopEnd, mLoopCount);
+ }
+#endif
mStaticProxy->setBufferPosition(0);
return NO_ERROR;
}
@@ -1566,9 +1573,8 @@ nsecs_t AudioTrack::processAudioBuffer()
// that the upper layers can recreate the track
if (!isOffloadedOrDirect_l() || (mSequence == mObservedSequence)) {
status_t status = restoreTrack_l("processAudioBuffer");
- mLock.unlock();
- // Run again immediately, but with a new IAudioTrack
- return 0;
+ // after restoration, continue below to make sure that the loop and buffer events
+ // are notified because they have been cleared from mCblk->mFlags above.
}
}
@@ -1617,7 +1623,6 @@ nsecs_t AudioTrack::processAudioBuffer()
}
// Cache other fields that will be needed soon
- uint32_t loopPeriod = mLoopCount != 0 ? mLoopEnd - mLoopStart : 0;
uint32_t sampleRate = mSampleRate;
uint32_t notificationFrames = mNotificationFramesAct;
if (mRefreshRemaining) {
@@ -1629,6 +1634,28 @@ nsecs_t AudioTrack::processAudioBuffer()
uint32_t sequence = mSequence;
sp<AudioTrackClientProxy> proxy = mProxy;
+ // Determine the number of new loop callback(s) that will be needed, while locked.
+ int loopCountNotifications = 0;
+ uint32_t loopPeriod = 0; // time in frames for next EVENT_LOOP_END or EVENT_BUFFER_END
+
+ if (mLoopCount > 0) {
+ int loopCount;
+ size_t bufferPosition;
+ mStaticProxy->getBufferPositionAndLoopCount(&bufferPosition, &loopCount);
+ loopPeriod = ((loopCount > 0) ? mLoopEnd : mFrameCount) - bufferPosition;
+ loopCountNotifications = min(mLoopCountNotified - loopCount, kMaxLoopCountNotifications);
+ mLoopCountNotified = loopCount; // discard any excess notifications
+ } else if (mLoopCount < 0) {
+ // FIXME: We're not accurate with notification count and position with infinite looping
+ // since loopCount from server side will always return -1 (we could decrement it).
+ size_t bufferPosition = mStaticProxy->getBufferPosition();
+ loopCountNotifications = int((flags & (CBLK_LOOP_CYCLE | CBLK_LOOP_FINAL)) != 0);
+ loopPeriod = mLoopEnd - bufferPosition;
+ } else if (/* mLoopCount == 0 && */ mSharedBuffer != 0) {
+ size_t bufferPosition = mStaticProxy->getBufferPosition();
+ loopPeriod = mFrameCount - bufferPosition;
+ }
+
// These fields don't need to be cached, because they are assigned only by set():
// mTransfer, mCbf, mUserData, mFormat, mFrameSize, mFrameSizeAF, mFlags
// mFlags is also assigned by createTrack_l(), but not the bit we care about.
@@ -1669,10 +1696,9 @@ nsecs_t AudioTrack::processAudioBuffer()
if (newUnderrun) {
mCbf(EVENT_UNDERRUN, mUserData, NULL);
}
- // FIXME we will miss loops if loop cycle was signaled several times since last call
- // to processAudioBuffer()
- if (flags & (CBLK_LOOP_CYCLE | CBLK_LOOP_FINAL)) {
+ while (loopCountNotifications > 0) {
mCbf(EVENT_LOOP_END, mUserData, NULL);
+ --loopCountNotifications;
}
if (flags & CBLK_BUFFER_END) {
mCbf(EVENT_BUFFER_END, mUserData, NULL);
@@ -1891,6 +1917,9 @@ status_t AudioTrack::restoreTrack_l(const char *from)
mLoopStart, mLoopEnd, loopCount);
} else {
mStaticProxy->setBufferPosition(bufferPosition);
+ if (bufferPosition == mFrameCount) {
+ ALOGD("restoring track at end of static buffer");
+ }
}
}
if (mState == STATE_ACTIVE) {