Merge "Separate the notion of "stop" from that of "release", i.e."
diff --git a/cmds/stagefright/SimplePlayer.cpp b/cmds/stagefright/SimplePlayer.cpp
index f269e80..fac3a8c 100644
--- a/cmds/stagefright/SimplePlayer.cpp
+++ b/cmds/stagefright/SimplePlayer.cpp
@@ -396,7 +396,7 @@
for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) {
CodecState *state = &mStateByTrackIndex.editValueAt(i);
- CHECK_EQ(state->mCodec->stop(), (status_t)OK);
+ CHECK_EQ(state->mCodec->release(), (status_t)OK);
}
mStartTimeRealUs = -1ll;
diff --git a/cmds/stagefright/codec.cpp b/cmds/stagefright/codec.cpp
index b850190..fbf800c 100644
--- a/cmds/stagefright/codec.cpp
+++ b/cmds/stagefright/codec.cpp
@@ -295,7 +295,7 @@
for (size_t i = 0; i < stateByTrack.size(); ++i) {
CodecState *state = &stateByTrack.editValueAt(i);
- CHECK_EQ((status_t)OK, state->mCodec->stop());
+ CHECK_EQ((status_t)OK, state->mCodec->release());
}
return 0;
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 70799a6..6735aff 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -49,7 +49,7 @@
void initiateSetup(const sp<AMessage> &msg);
void signalFlush();
void signalResume();
- void initiateShutdown();
+ void initiateShutdown(bool keepComponentAllocated = false);
void initiateAllocateComponent(const sp<AMessage> &msg);
void initiateConfigureComponent(const sp<AMessage> &msg);
@@ -61,6 +61,7 @@
private:
struct BaseState;
struct UninitializedState;
+ struct LoadedState;
struct LoadedToIdleState;
struct IdleToExecutingState;
struct ExecutingState;
@@ -107,6 +108,7 @@
sp<AMessage> mNotify;
sp<UninitializedState> mUninitializedState;
+ sp<LoadedState> mLoadedState;
sp<LoadedToIdleState> mLoadedToIdleState;
sp<IdleToExecutingState> mIdleToExecutingState;
sp<ExecutingState> mExecutingState;
@@ -131,6 +133,12 @@
bool mSentFormat;
bool mIsEncoder;
+ bool mShutdownInProgress;
+
+ // If "mKeepComponentAllocated" we only transition back to Loaded state
+ // and do not release the component instance.
+ bool mKeepComponentAllocated;
+
status_t allocateBuffersOnPort(OMX_U32 portIndex);
status_t freeBuffersOnPort(OMX_U32 portIndex);
status_t freeBuffer(OMX_U32 portIndex, size_t i);
diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h
index 8c11c9c..72ac56a 100644
--- a/include/media/stagefright/MediaCodec.h
+++ b/include/media/stagefright/MediaCodec.h
@@ -53,8 +53,15 @@
uint32_t flags);
status_t start();
+
+ // Returns to a state in which the component remains allocated but
+ // unconfigured.
status_t stop();
+ // Client MUST call release before releasing final reference to this
+ // object.
+ status_t release();
+
status_t flush();
status_t queueInputBuffer(
@@ -97,6 +104,7 @@
STARTED,
FLUSHING,
STOPPING,
+ RELEASING,
};
enum {
@@ -109,6 +117,7 @@
kWhatConfigure = 'conf',
kWhatStart = 'strt',
kWhatStop = 'stop',
+ kWhatRelease = 'rele',
kWhatDequeueInputBuffer = 'deqI',
kWhatQueueInputBuffer = 'queI',
kWhatDequeueOutputBuffer = 'deqO',
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 675339e..71e698f 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -84,7 +84,7 @@
}
JMediaCodec::~JMediaCodec() {
- mCodec->stop();
+ mCodec->release();
JNIEnv *env = AndroidRuntime::getJNIEnv();
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 85bd7ba..9a9d094 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -165,18 +165,36 @@
protected:
virtual bool onMessageReceived(const sp<AMessage> &msg);
+ virtual void stateEntered();
private:
void onSetup(const sp<AMessage> &msg);
- void onAllocateComponent(const sp<AMessage> &msg);
- void onConfigureComponent(const sp<AMessage> &msg);
- void onStart();
+ bool onAllocateComponent(const sp<AMessage> &msg);
DISALLOW_EVIL_CONSTRUCTORS(UninitializedState);
};
////////////////////////////////////////////////////////////////////////////////
+struct ACodec::LoadedState : public ACodec::BaseState {
+ LoadedState(ACodec *codec);
+
+protected:
+ virtual bool onMessageReceived(const sp<AMessage> &msg);
+ virtual void stateEntered();
+
+private:
+ friend struct ACodec::UninitializedState;
+
+ bool onConfigureComponent(const sp<AMessage> &msg);
+ void onStart();
+ void onShutdown(bool keepComponentAllocated);
+
+ DISALLOW_EVIL_CONSTRUCTORS(LoadedState);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
struct ACodec::LoadedToIdleState : public ACodec::BaseState {
LoadedToIdleState(ACodec *codec);
@@ -312,8 +330,10 @@
ACodec::ACodec()
: mNode(NULL),
mSentFormat(false),
- mIsEncoder(false) {
+ mIsEncoder(false),
+ mShutdownInProgress(false) {
mUninitializedState = new UninitializedState(this);
+ mLoadedState = new LoadedState(this);
mLoadedToIdleState = new LoadedToIdleState(this);
mIdleToExecutingState = new IdleToExecutingState(this);
mExecutingState = new ExecutingState(this);
@@ -369,8 +389,10 @@
(new AMessage(kWhatResume, id()))->post();
}
-void ACodec::initiateShutdown() {
- (new AMessage(kWhatShutdown, id()))->post();
+void ACodec::initiateShutdown(bool keepComponentAllocated) {
+ sp<AMessage> msg = new AMessage(kWhatShutdown, id());
+ msg->setInt32("keepComponentAllocated", keepComponentAllocated);
+ msg->post();
}
status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
@@ -2492,6 +2514,10 @@
: BaseState(codec) {
}
+void ACodec::UninitializedState::stateEntered() {
+ ALOGV("Now uninitialized");
+}
+
bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
bool handled = false;
@@ -2511,22 +2537,13 @@
break;
}
- case ACodec::kWhatConfigureComponent:
- {
- onConfigureComponent(msg);
- handled = true;
- break;
- }
-
- case ACodec::kWhatStart:
- {
- onStart();
- handled = true;
- break;
- }
-
case ACodec::kWhatShutdown:
{
+ int32_t keepComponentAllocated;
+ CHECK(msg->findInt32(
+ "keepComponentAllocated", &keepComponentAllocated));
+ CHECK(!keepComponentAllocated);
+
sp<AMessage> notify = mCodec->mNotify->dup();
notify->setInt32("what", ACodec::kWhatShutdownCompleted);
notify->post();
@@ -2554,22 +2571,16 @@
void ACodec::UninitializedState::onSetup(
const sp<AMessage> &msg) {
- onAllocateComponent(msg);
- onConfigureComponent(msg);
- onStart();
+ if (onAllocateComponent(msg)
+ && mCodec->mLoadedState->onConfigureComponent(msg)) {
+ mCodec->mLoadedState->onStart();
+ }
}
-void ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
+bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
ALOGV("onAllocateComponent");
- if (mCodec->mNode != NULL) {
- CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
-
- mCodec->mNativeWindow.clear();
- mCodec->mNode = NULL;
- mCodec->mOMX.clear();
- mCodec->mComponentName.clear();
- }
+ CHECK(mCodec->mNode == NULL);
OMXClient client;
CHECK_EQ(client.connect(), (status_t)OK);
@@ -2628,7 +2639,7 @@
}
mCodec->signalError(OMX_ErrorComponentNotFound);
- return;
+ return false;
}
sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id());
@@ -2649,9 +2660,96 @@
notify->setString("componentName", mCodec->mComponentName.c_str());
notify->post();
}
+
+ mCodec->changeState(mCodec->mLoadedState);
+
+ return true;
}
-void ACodec::UninitializedState::onConfigureComponent(
+////////////////////////////////////////////////////////////////////////////////
+
+ACodec::LoadedState::LoadedState(ACodec *codec)
+ : BaseState(codec) {
+}
+
+void ACodec::LoadedState::stateEntered() {
+ ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
+
+ if (mCodec->mShutdownInProgress) {
+ bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
+
+ mCodec->mShutdownInProgress = false;
+ mCodec->mKeepComponentAllocated = false;
+
+ onShutdown(keepComponentAllocated);
+ }
+}
+
+void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
+ if (!keepComponentAllocated) {
+ CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
+
+ mCodec->mNativeWindow.clear();
+ mCodec->mNode = NULL;
+ mCodec->mOMX.clear();
+ mCodec->mComponentName.clear();
+
+ mCodec->changeState(mCodec->mUninitializedState);
+ }
+
+ sp<AMessage> notify = mCodec->mNotify->dup();
+ notify->setInt32("what", ACodec::kWhatShutdownCompleted);
+ notify->post();
+}
+
+bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
+ bool handled = false;
+
+ switch (msg->what()) {
+ case ACodec::kWhatConfigureComponent:
+ {
+ onConfigureComponent(msg);
+ handled = true;
+ break;
+ }
+
+ case ACodec::kWhatStart:
+ {
+ onStart();
+ handled = true;
+ break;
+ }
+
+ case ACodec::kWhatShutdown:
+ {
+ int32_t keepComponentAllocated;
+ CHECK(msg->findInt32(
+ "keepComponentAllocated", &keepComponentAllocated));
+
+ onShutdown(keepComponentAllocated);
+
+ handled = true;
+ break;
+ }
+
+ case ACodec::kWhatFlush:
+ {
+ sp<AMessage> notify = mCodec->mNotify->dup();
+ notify->setInt32("what", ACodec::kWhatFlushCompleted);
+ notify->post();
+
+ handled = true;
+ break;
+ }
+
+ default:
+ return BaseState::onMessageReceived(msg);
+ }
+
+ return handled;
+}
+
+bool ACodec::LoadedState::onConfigureComponent(
const sp<AMessage> &msg) {
ALOGV("onConfigureComponent");
@@ -2664,7 +2762,7 @@
if (err != OK) {
mCodec->signalError(OMX_ErrorUndefined, err);
- return;
+ return false;
}
sp<RefBase> obj;
@@ -2682,9 +2780,11 @@
notify->setInt32("what", ACodec::kWhatComponentConfigured);
notify->post();
}
+
+ return true;
}
-void ACodec::UninitializedState::onStart() {
+void ACodec::LoadedState::onStart() {
ALOGV("onStart");
CHECK_EQ(mCodec->mOMX->sendCommand(
@@ -2873,6 +2973,13 @@
switch (msg->what()) {
case kWhatShutdown:
{
+ int32_t keepComponentAllocated;
+ CHECK(msg->findInt32(
+ "keepComponentAllocated", &keepComponentAllocated));
+
+ mCodec->mShutdownInProgress = true;
+ mCodec->mKeepComponentAllocated = keepComponentAllocated;
+
mActive = false;
CHECK_EQ(mCodec->mOMX->sendCommand(
@@ -3210,20 +3317,7 @@
CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
- ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
-
- CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
-
- mCodec->mNativeWindow.clear();
- mCodec->mNode = NULL;
- mCodec->mOMX.clear();
- mCodec->mComponentName.clear();
-
- mCodec->changeState(mCodec->mUninitializedState);
-
- sp<AMessage> notify = mCodec->mNotify->dup();
- notify->setInt32("what", ACodec::kWhatShutdownCompleted);
- notify->post();
+ mCodec->changeState(mCodec->mLoadedState);
return true;
}
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index e14b1c4..a9e7f360 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -164,6 +164,13 @@
return PostAndAwaitResponse(msg, &response);
}
+status_t MediaCodec::release() {
+ sp<AMessage> msg = new AMessage(kWhatRelease, id());
+
+ sp<AMessage> response;
+ return PostAndAwaitResponse(msg, &response);
+}
+
status_t MediaCodec::queueInputBuffer(
size_t index,
size_t offset,
@@ -422,6 +429,7 @@
}
case STOPPING:
+ case RELEASING:
{
// Ignore the error, assuming we'll still get
// the shutdown complete notification.
@@ -577,7 +585,9 @@
{
/* size_t index = */updateBuffers(kPortIndexInput, msg);
- if (mState == FLUSHING || mState == STOPPING) {
+ if (mState == FLUSHING
+ || mState == STOPPING
+ || mState == RELEASING) {
returnBuffersToCodecOnPort(kPortIndexInput);
break;
}
@@ -596,7 +606,9 @@
{
/* size_t index = */updateBuffers(kPortIndexOutput, msg);
- if (mState == FLUSHING || mState == STOPPING) {
+ if (mState == FLUSHING
+ || mState == STOPPING
+ || mState == RELEASING) {
returnBuffersToCodecOnPort(kPortIndexOutput);
break;
}
@@ -628,8 +640,12 @@
case ACodec::kWhatShutdownCompleted:
{
- CHECK_EQ(mState, STOPPING);
- setState(UNINITIALIZED);
+ if (mState == STOPPING) {
+ setState(INITIALIZED);
+ } else {
+ CHECK_EQ(mState, RELEASING);
+ setState(UNINITIALIZED);
+ }
(new AMessage)->postReply(mReplyID);
break;
@@ -767,6 +783,28 @@
mReplyID = replyID;
setState(STOPPING);
+ mCodec->initiateShutdown(true /* keepComponentAllocated */);
+ returnBuffersToCodec();
+ break;
+ }
+
+ case kWhatRelease:
+ {
+ uint32_t replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+
+ if (mState != INITIALIZED
+ && mState != CONFIGURED && mState != STARTED) {
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", INVALID_OPERATION);
+
+ response->postReply(replyID);
+ break;
+ }
+
+ mReplyID = replyID;
+ setState(RELEASING);
+
mCodec->initiateShutdown();
returnBuffersToCodec();
break;