diff options
author | Steve Kondik <steve@cyngn.com> | 2014-01-31 22:08:54 +0800 |
---|---|---|
committer | Steve Kondik <steve@cyngn.com> | 2015-11-07 12:03:16 -0800 |
commit | e79ee6494c2a1f2d3b1f1b1393ca85beee41a29d (patch) | |
tree | 26430e8fe59a53da3d0161b6123b575bef05b49e /media/libstagefright/AwesomePlayer.cpp | |
parent | 5d9ec7585ad39f73690fddbd864f3e3f5c1bde4d (diff) | |
download | frameworks_av-e79ee6494c2a1f2d3b1f1b1393ca85beee41a29d.zip frameworks_av-e79ee6494c2a1f2d3b1f1b1393ca85beee41a29d.tar.gz frameworks_av-e79ee6494c2a1f2d3b1f1b1393ca85beee41a29d.tar.bz2 |
stagefright: Squashed commit of pause/resume features
Add 2 APIs (suspend/resume) in MediaPlayer
- API:suspend() will just pause the player and release all the decoders
to replace release() which will release the whole player
- API:resume() will just init the decoders again,
then start() will be called to restart streaming playback
- Add a check in AwesomePlayer::onVideoEvent()
to make sure the first seek operation will always seek to the next
i-frame
Change-Id: Ie4c82906a2a056378119921a656128ebdc1007c4
audio: Add pause support for hardware omx component
- ADSP doesn't enter sleep state after wma playback is paused
and power suspended.
- No support for NT session pause in case of hardware component.
NT session need to be paused to put ADSP into power collapse.
- Add support of pause in stagefright to ensure device enters
suspend mode. Also add intermediate states to avoid concurrency
issues between read and pause.
Change-Id: I41b946b8c8805e6ee303646b63513b5b16514ef6
libstagefright: Drain input buffer on resume
- Buffers returned from codec in paused state are not drained. When
codec is resumed these buffers are not drained until the next flush,
and may cause timed out issue.
- Added change to drain input buffers for sw decoders when resuming.
Change-Id: Ida2ab1d5dc3a1910accdd6fb89548262a912d8e7
CRs-Fixed: 569585, 574967
libstagefright: camcorder pause-resume implementation
- Add pause resume feature in camcorder app. So that
user can pause recording and resume later which results
in a single recorded clip.
Change-Id: Id19c45ae5bb85265aa4d5304b160ebf119d9575a
libstagefright: support pause/resume for timelapse recording
Modify the timestamp calculation mechanism in CameraSourceTimeLapse
in order to support pause/resume.
Change-Id: Icb02ea798b0b807ffb7ada2d1ef5b2414b74edfb
Diffstat (limited to 'media/libstagefright/AwesomePlayer.cpp')
-rw-r--r-- | media/libstagefright/AwesomePlayer.cpp | 98 |
1 files changed, 94 insertions, 4 deletions
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index 3cd0b0e..778dfa5 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -216,7 +216,8 @@ AwesomePlayer::AwesomePlayer() mLastVideoTimeUs(-1), mTextDriver(NULL), mOffloadAudio(false), - mAudioTearDown(false) { + mAudioTearDown(false), + mIsFirstFrameAfterResume(false) { CHECK_EQ(mClient.connect(), (status_t)OK); DataSource::RegisterDefaultSniffers(); @@ -1804,11 +1805,18 @@ void AwesomePlayer::onVideoEvent() { if (mSeeking != NO_SEEK) { ALOGV("seeking to %" PRId64 " us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6); + MediaSource::ReadOptions::SeekMode seekmode = (mSeeking == SEEK_VIDEO_ONLY) + ? MediaSource::ReadOptions::SEEK_NEXT_SYNC + : MediaSource::ReadOptions::SEEK_CLOSEST_SYNC; + // Seek to the next key-frame after resume for http streaming + if (mCachedSource != NULL && mIsFirstFrameAfterResume) { + seekmode = MediaSource::ReadOptions::SEEK_NEXT_SYNC; + mIsFirstFrameAfterResume = false; + } + options.setSeekTo( mSeekTimeUs, - mSeeking == SEEK_VIDEO_ONLY - ? MediaSource::ReadOptions::SEEK_NEXT_SYNC - : MediaSource::ReadOptions::SEEK_CLOSEST_SYNC); + seekmode); } for (;;) { status_t err = mVideoSource->read(&mVideoBuffer, &options); @@ -3044,4 +3052,86 @@ void AwesomePlayer::onAudioTearDownEvent() { beginPrepareAsync_l(); } +// suspend() will release the decoders, the renderers and the buffers allocated for decoders +// Releasing decoders eliminates draining power in suspended state. +status_t AwesomePlayer::suspend() { + ALOGV("suspend()"); + Mutex::Autolock autoLock(mLock); + + // Set PAUSE to DrmManagerClient which will be set START in play_l() + if (mDecryptHandle != NULL) { + mDrmManagerClient->setPlaybackStatus(mDecryptHandle, + Playback::PAUSE, 0); + } + + cancelPlayerEvents(); + if (mQueueStarted) { + mQueue.stop(); + mQueueStarted = false; + } + + // Shutdown audio decoder first + if ((mAudioPlayer == NULL || !(mFlags & AUDIOPLAYER_STARTED)) + && mAudioSource != NULL) { + mAudioSource->stop(); + } + mAudioSource.clear(); + mOmxSource.clear(); + delete mAudioPlayer; + mAudioPlayer = NULL; + modifyFlags(AUDIO_RUNNING | AUDIOPLAYER_STARTED, CLEAR); + + // Shutdown the video decoder + mVideoRenderer.clear(); + if (mVideoSource != NULL) { + shutdownVideoDecoder_l(); + } + modifyFlags(PLAYING, CLEAR); + mVideoRenderingStarted = false; + + // Disconnect the source + if (mCachedSource != NULL) { + status_t err = mCachedSource->disconnectWhileSuspend(); + if (err != OK) { + return err; + } + } + + return OK; +} + +status_t AwesomePlayer::resume() { + ALOGV("resume()"); + Mutex::Autolock autoLock(mLock); + + // Reconnect the source + status_t err = mCachedSource->connectWhileResume(); + if (err != OK) { + return err; + } + + if (mVideoTrack != NULL && mVideoSource == NULL) { + status_t err = initVideoDecoder(); + if (err != OK) { + return err; + } + } + + if (mAudioTrack != NULL && mAudioSource == NULL) { + status_t err = initAudioDecoder(); + if (err != OK) { + return err; + } + } + + mIsFirstFrameAfterResume = true; + + if (!mQueueStarted) { + mQueue.start(); + mQueueStarted = true; + } + + return OK; +} + } // namespace android |