diff options
author | James Dong <jdong@google.com> | 2012-04-26 17:11:28 -0700 |
---|---|---|
committer | James Dong <jdong@google.com> | 2012-05-14 14:06:50 -0700 |
commit | ab7a2e544643edcb2e09ed5f204580afd763edc1 (patch) | |
tree | 8cc651013168e8d5d5373d74f2b73025f847bad9 /media | |
parent | 94f60e297b9e45fac387cf10b6ce1acc067cb4a1 (diff) | |
download | frameworks_av-ab7a2e544643edcb2e09ed5f204580afd763edc1.zip frameworks_av-ab7a2e544643edcb2e09ed5f204580afd763edc1.tar.gz frameworks_av-ab7a2e544643edcb2e09ed5f204580afd763edc1.tar.bz2 |
Switch audio tracks at runtime
o The switching is not allowed if there is an audio seek operation ongoing.
o related-to-bug: 6110705
Change-Id: Ib92a165f3984aa033d97800184d3d17319522db5
Diffstat (limited to 'media')
-rw-r--r-- | media/libstagefright/AwesomePlayer.cpp | 101 | ||||
-rw-r--r-- | media/libstagefright/include/AwesomePlayer.h | 9 |
2 files changed, 100 insertions, 10 deletions
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 @@ status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) { } 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() { } void AwesomePlayer::reset_l() { + mActiveAudioTrackIndex = -1; mDisplayWidth = 0; mDisplayHeight = 0; @@ -880,9 +882,10 @@ status_t AwesomePlayer::play_l() { 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 @@ status_t AwesomePlayer::getTrackInfo(Parcel *reply) const { 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,21 +2418,30 @@ status_t AwesomePlayer::selectTrack(size_t trackIndex, bool select) { 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 (!isAudioTrack && !strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) { + ALOGE("Track %d is not either audio or timed text", trackIndex); + return ERROR_UNSUPPORTED; + } + } - if (strcasecmp(mime.string(), MEDIA_MIMETYPE_TEXT_3GPP)) { + 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 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 @@ private: sp<AwesomeRenderer> mVideoRenderer; bool mVideoRendererIsPreview; + ssize_t mActiveAudioTrackIndex; sp<MediaSource> mAudioTrack; sp<MediaSource> mAudioSource; AudioPlayer *mAudioPlayer; @@ -309,8 +310,14 @@ private: 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 @@ private: 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); |