Merge "Smoothen audio "real" time by compensating with system_time()" into jb-dev
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 0aa73db..5a5a00e 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -425,6 +425,7 @@
         } else if (!haveAudio && !strncasecmp(mime.string(), "audio/", 6)) {
             setAudioSource(extractor->getTrack(i));
             haveAudio = true;
+            mActiveAudioTrackIndex = i;
 
             {
                 Mutex::Autolock autoLock(mStatsLock);
@@ -467,6 +468,7 @@
 }
 
 void AwesomePlayer::reset_l() {
+    mActiveAudioTrackIndex = -1;
     mDisplayWidth = 0;
     mDisplayHeight = 0;
 
@@ -880,9 +882,10 @@
                 bool allowDeepBuffering;
                 int64_t cachedDurationUs;
                 bool eos;
-                if (mVideoSource == NULL && (mDurationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US ||
-                        getCachedDuration_l(&cachedDurationUs, &eos) &&
-                        cachedDurationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US)) {
+                if (mVideoSource == NULL
+                        && (mDurationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US ||
+                        (getCachedDuration_l(&cachedDurationUs, &eos) &&
+                        cachedDurationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US))) {
                     allowDeepBuffering = true;
                 } else {
                     allowDeepBuffering = false;
@@ -2336,8 +2339,77 @@
     return OK;
 }
 
-// FIXME:
-// At present, only timed text track is able to be selected or unselected.
+status_t AwesomePlayer::selectAudioTrack_l(
+        const sp<MediaSource>& source, size_t trackIndex) {
+
+    ALOGI("selectAudioTrack_l: trackIndex=%d, mFlags=0x%x", trackIndex, mFlags);
+
+    {
+        Mutex::Autolock autoLock(mStatsLock);
+        if ((ssize_t)trackIndex == mActiveAudioTrackIndex) {
+            ALOGI("Track %d is active. Does nothing.", trackIndex);
+            return OK;
+        }
+        //mStats.mFlags = mFlags;
+    }
+
+    if (mSeeking != NO_SEEK) {
+        ALOGE("Selecting a track while seeking is not supported");
+        return ERROR_UNSUPPORTED;
+    }
+
+    if ((mFlags & PREPARED) == 0) {
+        ALOGE("Data source has not finished preparation");
+        return ERROR_UNSUPPORTED;
+    }
+
+    CHECK(source != NULL);
+    bool wasPlaying = (mFlags & PLAYING) != 0;
+
+    pause_l();
+
+    int64_t curTimeUs;
+    CHECK_EQ(getPosition(&curTimeUs), (status_t)OK);
+
+    if ((mAudioPlayer == NULL || !(mFlags & AUDIOPLAYER_STARTED))
+            && mAudioSource != NULL) {
+        // If we had an audio player, it would have effectively
+        // taken possession of the audio source and stopped it when
+        // _it_ is stopped. Otherwise this is still our responsibility.
+        mAudioSource->stop();
+    }
+    mAudioSource.clear();
+
+    mTimeSource = NULL;
+
+    delete mAudioPlayer;
+    mAudioPlayer = NULL;
+
+    modifyFlags(AUDIOPLAYER_STARTED, CLEAR);
+
+    setAudioSource(source);
+
+    modifyFlags(AUDIO_AT_EOS, CLEAR);
+    modifyFlags(AT_EOS, CLEAR);
+
+    status_t err;
+    if ((err = initAudioDecoder()) != OK) {
+        ALOGE("Failed to init audio decoder: 0x%x", err);
+        return err;
+    }
+
+    mSeekNotificationSent = true;
+    seekTo_l(curTimeUs);
+
+    if (wasPlaying) {
+        play_l();
+    }
+
+    mActiveAudioTrackIndex = trackIndex;
+
+    return OK;
+}
+
 status_t AwesomePlayer::selectTrack(size_t trackIndex, bool select) {
     ATRACE_CALL();
     ALOGV("selectTrack: trackIndex = %d and select=%d", trackIndex, select);
@@ -2346,23 +2418,32 @@
     if (mTextDriver != NULL) {
         trackCount += mTextDriver->countExternalTracks();
     }
-
     if (trackIndex >= trackCount) {
         ALOGE("Track index (%d) is out of range [0, %d)", trackIndex, trackCount);
         return ERROR_OUT_OF_RANGE;
     }
 
+    bool isAudioTrack = false;
     if (trackIndex < mExtractor->countTracks()) {
         sp<MetaData> meta = mExtractor->getTrackMetaData(trackIndex);
-        const char *_mime;
-        CHECK(meta->findCString(kKeyMIMEType, &_mime));
-        String8 mime = String8(_mime);
+        const char *mime;
+        CHECK(meta->findCString(kKeyMIMEType, &mime));
+        isAudioTrack = !strncasecmp(mime, "audio/", 6);
 
-        if (strcasecmp(mime.string(), MEDIA_MIMETYPE_TEXT_3GPP)) {
+        if (!isAudioTrack && !strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
+            ALOGE("Track %d is not either audio or timed text", trackIndex);
             return ERROR_UNSUPPORTED;
         }
     }
 
+    if (isAudioTrack) {
+        if (!select) {
+            ALOGE("Deselect an audio track (%d) is not supported", trackIndex);
+            return ERROR_UNSUPPORTED;
+        }
+        return selectAudioTrack_l(mExtractor->getTrack(trackIndex), trackIndex);
+    }
+
     // Timed text track handling
     if (mTextDriver == NULL) {
         return INVALID_OPERATION;
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 909654a..68380a8 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -168,6 +168,7 @@
     sp<AwesomeRenderer> mVideoRenderer;
     bool mVideoRendererIsPreview;
 
+    ssize_t mActiveAudioTrackIndex;
     sp<MediaSource> mAudioTrack;
     sp<MediaSource> mAudioSource;
     AudioPlayer *mAudioPlayer;
@@ -309,8 +310,14 @@
         int mFd;
         String8 mURI;
         int64_t mBitrate;
+
+        // FIXME:
+        // These two indices are just 0 or 1 for now
+        // They are not representing the actual track
+        // indices in the stream.
         ssize_t mAudioTrackIndex;
         ssize_t mVideoTrackIndex;
+
         int64_t mNumVideoFramesDecoded;
         int64_t mNumVideoFramesDropped;
         int32_t mVideoWidth;
@@ -323,6 +330,8 @@
     status_t setVideoScalingMode_l(int32_t mode);
     status_t getTrackInfo(Parcel* reply) const;
 
+    status_t selectAudioTrack_l(const sp<MediaSource>& source, size_t trackIndex);
+
     // when select is true, the given track is selected.
     // otherwise, the given track is unselected.
     status_t selectTrack(size_t trackIndex, bool select);
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 51a8367..e1fae82 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -142,6 +142,8 @@
 
 // minimum normal mix buffer size, expressed in milliseconds rather than frames
 static const uint32_t kMinNormalMixBufferSizeMs = 20;
+// maximum normal mix buffer size
+static const uint32_t kMaxNormalMixBufferSizeMs = 24;
 
 nsecs_t AudioFlinger::mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
 
@@ -151,9 +153,9 @@
     FastMixer_Always,   // always initialize and use, even if not needed: for debugging only
                         // normal mixer multiplier is 1
     FastMixer_Static,   // initialize if needed, then use all the time if initialized,
-                        // multipler is calculated based on minimum normal mixer buffer size
+                        // multiplier is calculated based on min & max normal mixer buffer size
     FastMixer_Dynamic,  // initialize if needed, then use dynamically depending on track load,
-                        // multipler is calculated based on minimum normal mixer buffer size
+                        // multiplier is calculated based on min & max normal mixer buffer size
     // FIXME for FastMixer_Dynamic:
     //  Supporting this option will require fixing HALs that can't handle large writes.
     //  For example, one HAL implementation returns an error from a large write,
@@ -1950,18 +1952,42 @@
     }
 
     // Calculate size of normal mix buffer relative to the HAL output buffer size
-    uint32_t multiple = 1;
+    double multiplier = 1.0;
     if (mType == MIXER && (kUseFastMixer == FastMixer_Static || kUseFastMixer == FastMixer_Dynamic)) {
         size_t minNormalFrameCount = (kMinNormalMixBufferSizeMs * mSampleRate) / 1000;
-        multiple = (minNormalFrameCount + mFrameCount - 1) / mFrameCount;
-        // force multiple to be even, for compatibility with doubling of fast tracks due to HAL SRC
-        // (it would be unusual for the normal mix buffer size to not be a multiple of fast track)
-        // FIXME this rounding up should not be done if no HAL SRC
-        if ((multiple > 2) && (multiple & 1)) {
-            ++multiple;
+        size_t maxNormalFrameCount = (kMaxNormalMixBufferSizeMs * mSampleRate) / 1000;
+        // round up minimum and round down maximum to nearest 16 frames to satisfy AudioMixer
+        minNormalFrameCount = (minNormalFrameCount + 15) & ~15;
+        maxNormalFrameCount = maxNormalFrameCount & ~15;
+        if (maxNormalFrameCount < minNormalFrameCount) {
+            maxNormalFrameCount = minNormalFrameCount;
+        }
+        multiplier = (double) minNormalFrameCount / (double) mFrameCount;
+        if (multiplier <= 1.0) {
+            multiplier = 1.0;
+        } else if (multiplier <= 2.0) {
+            if (2 * mFrameCount <= maxNormalFrameCount) {
+                multiplier = 2.0;
+            } else {
+                multiplier = (double) maxNormalFrameCount / (double) mFrameCount;
+            }
+        } else {
+            // prefer an even multiplier, for compatibility with doubling of fast tracks due to HAL SRC
+            // (it would be unusual for the normal mix buffer size to not be a multiple of fast
+            // track, but we sometimes have to do this to satisfy the maximum frame count constraint)
+            // FIXME this rounding up should not be done if no HAL SRC
+            uint32_t truncMult = (uint32_t) multiplier;
+            if ((truncMult & 1)) {
+                if ((truncMult + 1) * mFrameCount <= maxNormalFrameCount) {
+                    ++truncMult;
+                }
+            }
+            multiplier = (double) truncMult;
         }
     }
-    mNormalFrameCount = multiple * mFrameCount;
+    mNormalFrameCount = multiplier * mFrameCount;
+    // round up to nearest 16 frames to satisfy AudioMixer
+    mNormalFrameCount = (mNormalFrameCount + 15) & ~15;
     ALOGI("HAL output buffer size %u frames, normal mix buffer size %u frames", mFrameCount, mNormalFrameCount);
 
     // FIXME - Current mixer implementation only supports stereo output: Always