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/libmedia | |
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/libmedia')
-rw-r--r-- | media/libmedia/IMediaPlayer.cpp | 30 | ||||
-rw-r--r-- | media/libmedia/IMediaRecorder.cpp | 16 | ||||
-rw-r--r-- | media/libmedia/mediaplayer.cpp | 60 | ||||
-rwxr-xr-x[-rw-r--r--] | media/libmedia/mediarecorder.cpp | 28 |
4 files changed, 129 insertions, 5 deletions
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp index 942aec3..bad84b7 100644 --- a/media/libmedia/IMediaPlayer.cpp +++ b/media/libmedia/IMediaPlayer.cpp @@ -67,6 +67,8 @@ enum { SET_RETRANSMIT_ENDPOINT, GET_RETRANSMIT_ENDPOINT, SET_NEXT_PLAYER, + SUSPEND, + RESUME, }; class BpMediaPlayer: public BpInterface<IMediaPlayer> @@ -419,6 +421,22 @@ public: return err; } + + status_t suspend() + { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); + remote()->transact(SUSPEND, data, &reply); + return reply.readInt32(); + } + + status_t resume() + { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); + remote()->transact(RESUME, data, &reply); + return reply.readInt32(); + } }; IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer"); @@ -682,6 +700,18 @@ status_t BnMediaPlayer::onTransact( return NO_ERROR; } break; + case SUSPEND: { + CHECK_INTERFACE(IMediaPlayer, data, reply); + status_t ret = suspend(); + reply->writeInt32(ret); + return NO_ERROR; + } break; + case RESUME: { + CHECK_INTERFACE(IMediaPlayer, data, reply); + status_t ret = resume(); + reply->writeInt32(ret); + return NO_ERROR; + } break; default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp index ee3b584..4711c1b 100644 --- a/media/libmedia/IMediaRecorder.cpp +++ b/media/libmedia/IMediaRecorder.cpp @@ -39,6 +39,7 @@ enum { QUERY_SURFACE_MEDIASOURCE, RESET, STOP, + PAUSE, START, PREPARE, GET_MAX_AMPLITUDE, @@ -258,6 +259,15 @@ public: return reply.readInt32(); } + status_t pause() + { + ALOGV("pause"); + Parcel data, reply; + data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); + remote()->transact(PAUSE, data, &reply); + return reply.readInt32(); + } + status_t stop() { ALOGV("stop"); @@ -334,6 +344,12 @@ status_t BnMediaRecorder::onTransact( reply->writeInt32(stop()); return NO_ERROR; } break; + case PAUSE: { + ALOGV("PAUSE"); + CHECK_INTERFACE(IMediaRecorder, data, reply); + reply->writeInt32(pause()); + return NO_ERROR; + } break; case START: { ALOGV("START"); CHECK_INTERFACE(IMediaRecorder, data, reply); diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index 6c0606c..3c6bef3 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -333,6 +333,9 @@ status_t MediaPlayer::start() ALOGV("playback completed immediately following start()"); } } + } else if ( (mPlayer != 0) && (mCurrentState & MEDIA_PLAYER_SUSPENDED) ) { + ALOGV("start while suspended, so ignore this start"); + ret = NO_ERROR; } else { ALOGE("start called in state %d", mCurrentState); ret = INVALID_OPERATION; @@ -488,7 +491,8 @@ status_t MediaPlayer::getDuration_l(int *msec) { ALOGV("getDuration_l"); bool isValidState = (mCurrentState & (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED | - MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_STOPPED | MEDIA_PLAYER_PLAYBACK_COMPLETE)); + MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_STOPPED | MEDIA_PLAYER_PLAYBACK_COMPLETE | + MEDIA_PLAYER_SUSPENDED)); if (mPlayer != 0 && isValidState) { int durationMs; status_t ret = mPlayer->getDuration(&durationMs); @@ -518,7 +522,7 @@ status_t MediaPlayer::seekTo_l(int msec) { ALOGV("seekTo %d", msec); if ((mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED | - MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE) ) ) { + MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_SUSPENDED) ) ) { if ( msec < 0 ) { ALOGW("Attempt to seek to invalid position: %d", msec); msec = 0; @@ -939,4 +943,54 @@ status_t MediaPlayer::setNextMediaPlayer(const sp<MediaPlayer>& next) { return mPlayer->setNextPlayer(next == NULL ? NULL : next->mPlayer); } -} // namespace android +status_t MediaPlayer::suspend() { + ALOGV("MediaPlayer::suspend()"); + Mutex::Autolock _l(mLock); + if (mPlayer == NULL) { + ALOGE("mPlayer = NULL"); + return NO_INIT; + } + + bool isValidState = (mCurrentState & (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_STOPPED | MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_SUSPENDED)); + + if (!isValidState) { + ALOGE("suspend while in a invalid state = %d", mCurrentState); + return UNKNOWN_ERROR; + } + + status_t ret = mPlayer->suspend(); + + if (OK != ret) { + ALOGE("MediaPlayer::suspend() return with error ret = %d", ret); + return ret; + } + mCurrentState = MEDIA_PLAYER_SUSPENDED; + return OK; +} + +status_t MediaPlayer::resume() { + ALOGV("MediaPlayer::resume()"); + Mutex::Autolock _l(mLock); + if (mPlayer == NULL) { + ALOGE("mPlayer == NULL"); + return NO_INIT; + } + + bool isValidState = (mCurrentState == MEDIA_PLAYER_SUSPENDED); + + if (!isValidState) { + ALOGE("resume while in a invalid state = %d", mCurrentState); + return UNKNOWN_ERROR; + } + + status_t ret = mPlayer->resume(); + + if (OK != ret) { + ALOGE("MediaPlayer::resume() return with error ret = %d", ret); + return ret; + } + mCurrentState = MEDIA_PLAYER_PREPARED; + return OK; +} + +}; // namespace android diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp index 8bbd8f1..8b7b171 100644..100755 --- a/media/libmedia/mediarecorder.cpp +++ b/media/libmedia/mediarecorder.cpp @@ -482,7 +482,7 @@ status_t MediaRecorder::start() ALOGE("media recorder is not initialized yet"); return INVALID_OPERATION; } - if (!(mCurrentState & MEDIA_RECORDER_PREPARED)) { + if (!(mCurrentState & (MEDIA_RECORDER_PREPARED | MEDIA_RECORDER_PAUSED))) { ALOGE("start called in an invalid state: %d", mCurrentState); return INVALID_OPERATION; } @@ -497,6 +497,29 @@ status_t MediaRecorder::start() return ret; } +status_t MediaRecorder::pause() +{ + ALOGV("pause"); + if (mMediaRecorder == NULL) { + ALOGE("media recorder is not initialized yet"); + return INVALID_OPERATION; + } + if (!(mCurrentState & MEDIA_RECORDER_RECORDING)) { + ALOGE("pause called in an invalid state: %d", mCurrentState); + return INVALID_OPERATION; + } + + status_t ret = mMediaRecorder->pause(); + if (OK != ret) { + ALOGE("pause failed: %d", ret); + mCurrentState = MEDIA_RECORDER_ERROR; + return ret; + } + + mCurrentState = MEDIA_RECORDER_PAUSED; + return ret; +} + status_t MediaRecorder::stop() { ALOGV("stop"); @@ -504,7 +527,7 @@ status_t MediaRecorder::stop() ALOGE("media recorder is not initialized yet"); return INVALID_OPERATION; } - if (!(mCurrentState & MEDIA_RECORDER_RECORDING)) { + if (!(mCurrentState & (MEDIA_RECORDER_RECORDING | MEDIA_RECORDER_PAUSED))) { ALOGE("stop called in an invalid state: %d", mCurrentState); return INVALID_OPERATION; } @@ -540,6 +563,7 @@ status_t MediaRecorder::reset() ret = OK; break; + case MEDIA_RECORDER_PAUSED: case MEDIA_RECORDER_RECORDING: case MEDIA_RECORDER_DATASOURCE_CONFIGURED: case MEDIA_RECORDER_PREPARED: |