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/OMXCodec.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/OMXCodec.cpp')
-rw-r--r-- | media/libstagefright/OMXCodec.cpp | 92 |
1 files changed, 86 insertions, 6 deletions
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp index b2bfceb..3ec02d4 100644 --- a/media/libstagefright/OMXCodec.cpp +++ b/media/libstagefright/OMXCodec.cpp @@ -1614,6 +1614,8 @@ bool OMXCodec::isIntermediateState(State state) { return state == LOADED_TO_IDLE || state == IDLE_TO_EXECUTING || state == EXECUTING_TO_IDLE + || state == PAUSING + || state == FLUSHING || state == IDLE_TO_LOADED || state == RECONFIGURING; } @@ -2665,6 +2667,14 @@ void OMXCodec::onStateChange(OMX_STATETYPE newState) { break; } + case OMX_StatePause: + { + CODEC_LOGV("Now paused."); + CHECK_EQ((int)mState, (int)PAUSING); + setState(PAUSED); + break; + } + case OMX_StateInvalid: { setState(ERROR); @@ -2780,7 +2790,7 @@ void OMXCodec::onPortSettingsChanged(OMX_U32 portIndex) { bool OMXCodec::flushPortAsync(OMX_U32 portIndex) { CHECK(mState == EXECUTING || mState == RECONFIGURING - || mState == EXECUTING_TO_IDLE); + || mState == EXECUTING_TO_IDLE || mState == FLUSHING); CODEC_LOGV("flushPortAsync(%u): we own %zu out of %zu buffers already.", portIndex, countBuffersWeOwn(mPortBuffers[portIndex]), @@ -2830,7 +2840,7 @@ status_t OMXCodec::enablePortAsync(OMX_U32 portIndex) { } void OMXCodec::fillOutputBuffers() { - CHECK_EQ((int)mState, (int)EXECUTING); + CHECK(mState == EXECUTING || mState == FLUSHING); // This is a workaround for some decoders not properly reporting // end-of-output-stream. If we own all input buffers and also own @@ -2857,7 +2867,7 @@ void OMXCodec::fillOutputBuffers() { } void OMXCodec::drainInputBuffers() { - CHECK(mState == EXECUTING || mState == RECONFIGURING); + CHECK(mState == EXECUTING || mState == RECONFIGURING || mState == FLUSHING); if (mFlags & kUseSecureInputBuffers) { Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput]; @@ -3604,6 +3614,11 @@ void OMXCodec::clearCodecSpecificData() { status_t OMXCodec::start(MetaData *meta) { Mutex::Autolock autoLock(mLock); + if (mPaused) { + status_t err = resumeLocked(true); + return err; + } + if (mState != LOADED) { CODEC_LOGE("called start in the unexpected state: %d", mState); return UNKNOWN_ERROR; @@ -3714,6 +3729,7 @@ status_t OMXCodec::stopOmxComponent_l() { isError = true; } + case PAUSED: case EXECUTING: { setState(EXECUTING_TO_IDLE); @@ -3785,6 +3801,14 @@ status_t OMXCodec::read( Mutex::Autolock autoLock(mLock); + if (mPaused) { + err = resumeLocked(false); + if(err != OK) { + CODEC_LOGE("Failed to restart codec err= %d", err); + return err; + } + } + if (mState != EXECUTING && mState != RECONFIGURING) { return UNKNOWN_ERROR; } @@ -3841,6 +3865,8 @@ status_t OMXCodec::read( mFilledBuffers.clear(); CHECK_EQ((int)mState, (int)EXECUTING); + //DSP supports flushing of ports simultaneously. Flushing individual port is not supported. + setState(FLUSHING); bool emulateInputFlushCompletion = !flushPortAsync(kPortIndexInput); bool emulateOutputFlushCompletion = !flushPortAsync(kPortIndexOutput); @@ -3870,6 +3896,11 @@ status_t OMXCodec::read( return UNKNOWN_ERROR; } + if (seeking) { + CHECK_EQ((int)mState, (int)FLUSHING); + setState(EXECUTING); + } + if (mFilledBuffers.empty()) { return mSignalledEOS ? mFinalStatus : ERROR_END_OF_STREAM; } @@ -4303,11 +4334,60 @@ void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) { } status_t OMXCodec::pause() { - Mutex::Autolock autoLock(mLock); + CODEC_LOGV("pause mState=%d", mState); + + Mutex::Autolock autoLock(mLock); + + if (mState != EXECUTING) { + return UNKNOWN_ERROR; + } + + while (isIntermediateState(mState)) { + mAsyncCompletion.wait(mLock); + } + if (!strncmp(mComponentName, "OMX.qcom.", 9)) { + status_t err = mOMX->sendCommand(mNode, + OMX_CommandStateSet, OMX_StatePause); + CHECK_EQ(err, (status_t)OK); + setState(PAUSING); + + mPaused = true; + while (mState != PAUSED && mState != ERROR) { + mAsyncCompletion.wait(mLock); + } + return mState == ERROR ? UNKNOWN_ERROR : OK; + } else { + mPaused = true; + return OK; + } - mPaused = true; +} - return OK; +status_t OMXCodec::resumeLocked(bool drainInputBuf) { + CODEC_LOGV("resume mState=%d", mState); + + if (!strncmp(mComponentName, "OMX.qcom.", 9)) { + while (isIntermediateState(mState)) { + mAsyncCompletion.wait(mLock); + } + CHECK_EQ(mState, (status_t)PAUSED); + status_t err = mOMX->sendCommand(mNode, + OMX_CommandStateSet, OMX_StateExecuting); + CHECK_EQ(err, (status_t)OK); + setState(IDLE_TO_EXECUTING); + mPaused = false; + while (mState != EXECUTING && mState != ERROR) { + mAsyncCompletion.wait(mLock); + } + if(drainInputBuf) + drainInputBuffers(); + return mState == ERROR ? UNKNOWN_ERROR : OK; + } else { // SW Codec + mPaused = false; + if(drainInputBuf) + drainInputBuffers(); + return OK; + } } //////////////////////////////////////////////////////////////////////////////// |