OSDN Git Service

AudioTrack: When paused, return cached playback position
authorHaynes Mathew George <hgeorge@codeaurora.org>
Wed, 8 Jan 2014 21:59:53 +0000 (13:59 -0800)
committerEric Laurent <elaurent@google.com>
Thu, 6 Mar 2014 19:38:38 +0000 (11:38 -0800)
An offload output can be re-used between two audio tracks having
the same configuration. A timestamp query for a paused track
while the other is running would return an incorrect time.
To fix this, cache the playback position on a pause() and return
this time when requested until the track is resumed.

Bug: 12826612.
Change-Id: I324112ea9827e52fff53ef44cd8513c8d85a0bc4

include/media/AudioTrack.h
media/libmedia/AudioTrack.cpp

index 7e9d557..7d23d02 100644 (file)
@@ -746,6 +746,7 @@ protected:
 
     bool                    mInUnderrun;            // whether track is currently in underrun state
     String8                 mName;                  // server's name for this IAudioTrack
+    uint32_t                mPausedPosition;
 
 private:
     class DeathNotifier : public IBinder::DeathRecipient {
index d25c40b..f353fac 100644 (file)
@@ -99,7 +99,8 @@ AudioTrack::AudioTrack()
     : mStatus(NO_INIT),
       mIsTimed(false),
       mPreviousPriority(ANDROID_PRIORITY_NORMAL),
-      mPreviousSchedulingGroup(SP_DEFAULT)
+      mPreviousSchedulingGroup(SP_DEFAULT),
+      mPausedPosition(0)
 {
 }
 
@@ -121,7 +122,8 @@ AudioTrack::AudioTrack(
     : mStatus(NO_INIT),
       mIsTimed(false),
       mPreviousPriority(ANDROID_PRIORITY_NORMAL),
-      mPreviousSchedulingGroup(SP_DEFAULT)
+      mPreviousSchedulingGroup(SP_DEFAULT),
+      mPausedPosition(0)
 {
     mStatus = set(streamType, sampleRate, format, channelMask,
             frameCount, flags, cbf, user, notificationFrames,
@@ -147,7 +149,8 @@ AudioTrack::AudioTrack(
     : mStatus(NO_INIT),
       mIsTimed(false),
       mPreviousPriority(ANDROID_PRIORITY_NORMAL),
-      mPreviousSchedulingGroup(SP_DEFAULT)
+      mPreviousSchedulingGroup(SP_DEFAULT),
+      mPausedPosition(0)
 {
     mStatus = set(streamType, sampleRate, format, channelMask,
             0 /*frameCount*/, flags, cbf, user, notificationFrames,
@@ -551,6 +554,16 @@ void AudioTrack::pause()
     }
     mProxy->interrupt();
     mAudioTrack->pause();
+
+    if (isOffloaded()) {
+        if (mOutput != 0) {
+            uint32_t halFrames;
+            // OffloadThread sends HAL pause in its threadLoop.. time saved
+            // here can be slightly off
+            AudioSystem::getRenderPosition(mOutput, &halFrames, &mPausedPosition);
+            ALOGV("AudioTrack::pause for offload, cache current position %u", mPausedPosition);
+        }
+    }
 }
 
 status_t AudioTrack::setVolume(float left, float right)
@@ -770,6 +783,12 @@ status_t AudioTrack::getPosition(uint32_t *position) const
     if (isOffloaded_l()) {
         uint32_t dspFrames = 0;
 
+        if ((mState == STATE_PAUSED) || (mState == STATE_PAUSED_STOPPING)) {
+            ALOGV("getPosition called in paused state, return cached position %u", mPausedPosition);
+            *position = mPausedPosition;
+            return NO_ERROR;
+        }
+
         if (mOutput != 0) {
             uint32_t halFrames;
             AudioSystem::getRenderPosition(mOutput, &halFrames, &dspFrames);