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