Improvements/fixes to ACodec.
- Make sure ACodec reverts its state when it's shutdown
- Defer "resume" to after handling the OutputPortSettingsChange
- If the OMX_EventPortSettingsChanged event comes in while we're flushing, defer it
and make sure the output port can be disabled by deleting all buffers not already
owned by the component.
Change-Id: I1f8cdffa71237b57d4275a48b834647a7b263e8b
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 4599d70..a969796 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -109,7 +109,7 @@
status_t allocateOutputBuffersFromNativeWindow();
status_t cancelBufferToNativeWindow(BufferInfo *info);
- status_t freeOutputBuffersOwnedByNativeWindow();
+ status_t freeOutputBuffersNotOwnedByComponent();
BufferInfo *dequeueBufferFromNativeWindow();
BufferInfo *findBufferByID(
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index dfb4e00..505d9d4 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -197,6 +197,9 @@
// to fill with data.
void resume();
+ // Returns true iff input and output buffers are in play.
+ bool active() const { return mActive; }
+
protected:
virtual PortMode getPortMode(OMX_U32 portIndex);
virtual bool onMessageReceived(const sp<AMessage> &msg);
@@ -205,6 +208,8 @@
virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
private:
+ bool mActive;
+
DISALLOW_EVIL_CONSTRUCTORS(ExecutingState);
};
@@ -564,13 +569,17 @@
return OK;
}
-status_t ACodec::freeOutputBuffersOwnedByNativeWindow() {
+status_t ACodec::freeOutputBuffersNotOwnedByComponent() {
for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
BufferInfo *info =
&mBuffers[kPortIndexOutput].editItemAt(i);
- if (info->mStatus ==
- BufferInfo::OWNED_BY_NATIVE_WINDOW) {
+ if (info->mStatus !=
+ BufferInfo::OWNED_BY_COMPONENT) {
+ // We shouldn't have sent out any buffers to the client at this
+ // point.
+ CHECK_NE((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
+
CHECK_EQ((status_t)OK, freeBuffer(kPortIndexOutput, i));
}
}
@@ -1195,6 +1204,9 @@
}
bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) {
+ LOGV("[%s] onOMXEmptyBufferDone %p",
+ mCodec->mComponentName.c_str(), bufferID);
+
BufferInfo *info =
mCodec->findBufferByID(kPortIndexInput, bufferID);
@@ -1295,7 +1307,7 @@
}
if (buffer != info->mData) {
- if (!(flags & OMX_BUFFERFLAG_CODECCONFIG)) {
+ if (0 && !(flags & OMX_BUFFERFLAG_CODECCONFIG)) {
LOGV("[%s] Needs to copy input data.",
mCodec->mComponentName.c_str());
}
@@ -1304,6 +1316,9 @@
memcpy(info->mData->data(), buffer->data(), buffer->size());
}
+ LOGV("[%s] calling emptyBuffer %p",
+ mCodec->mComponentName.c_str(), bufferID);
+
CHECK_EQ(mCodec->mOMX->emptyBuffer(
mCodec->mNode,
bufferID,
@@ -1320,6 +1335,9 @@
LOGV("[%s] Signalling EOS on the input port",
mCodec->mComponentName.c_str());
+ LOGV("[%s] calling emptyBuffer %p",
+ mCodec->mComponentName.c_str(), bufferID);
+
CHECK_EQ(mCodec->mOMX->emptyBuffer(
mCodec->mNode,
bufferID,
@@ -1378,6 +1396,9 @@
int64_t timeUs,
void *platformPrivate,
void *dataPtr) {
+ LOGV("[%s] onOMXFillBufferDone %p",
+ mCodec->mComponentName.c_str(), bufferID);
+
ssize_t index;
BufferInfo *info =
mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
@@ -1396,6 +1417,9 @@
{
if (rangeLength == 0) {
if (!(flags & OMX_BUFFERFLAG_EOS)) {
+ LOGV("[%s] calling fillBuffer %p",
+ mCodec->mComponentName.c_str(), info->mBufferID);
+
CHECK_EQ(mCodec->mOMX->fillBuffer(
mCodec->mNode, info->mBufferID),
(status_t)OK);
@@ -1503,6 +1527,9 @@
info = mCodec->dequeueBufferFromNativeWindow();
}
+ LOGV("[%s] calling fillBuffer %p",
+ mCodec->mComponentName.c_str(), info->mBufferID);
+
CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
(status_t)OK);
@@ -1600,6 +1627,9 @@
mCodec->mOMX = omx;
mCodec->mNode = node;
+ mCodec->mPortEOS[kPortIndexInput] =
+ mCodec->mPortEOS[kPortIndexOutput] = false;
+
mCodec->configureCodec(mime.c_str(), msg);
sp<RefBase> obj;
@@ -1717,7 +1747,8 @@
////////////////////////////////////////////////////////////////////////////////
ACodec::ExecutingState::ExecutingState(ACodec *codec)
- : BaseState(codec) {
+ : BaseState(codec),
+ mActive(false) {
}
ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
@@ -1745,6 +1776,9 @@
CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
}
+ LOGV("[%s] calling fillBuffer %p",
+ mCodec->mComponentName.c_str(), info->mBufferID);
+
CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
(status_t)OK);
@@ -1753,6 +1787,13 @@
}
void ACodec::ExecutingState::resume() {
+ if (mActive) {
+ LOGV("[%s] We're already active, no need to resume.",
+ mCodec->mComponentName.c_str());
+
+ return;
+ }
+
submitOutputBuffers();
// Post the first input buffer.
@@ -1760,6 +1801,8 @@
BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0);
postFillThisBuffer(info);
+
+ mActive = true;
}
void ACodec::ExecutingState::stateEntered() {
@@ -1774,6 +1817,8 @@
switch (msg->what()) {
case kWhatShutdown:
{
+ mActive = false;
+
CHECK_EQ(mCodec->mOMX->sendCommand(
mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
(status_t)OK);
@@ -1786,6 +1831,8 @@
case kWhatFlush:
{
+ mActive = false;
+
CHECK_EQ(mCodec->mOMX->sendCommand(
mCodec->mNode, OMX_CommandFlush, OMX_ALL),
(status_t)OK);
@@ -1825,10 +1872,7 @@
OMX_CommandPortDisable, kPortIndexOutput),
(status_t)OK);
- if (mCodec->mNativeWindow != NULL) {
- CHECK_EQ((status_t)OK,
- mCodec->freeOutputBuffersOwnedByNativeWindow());
- }
+ mCodec->freeOutputBuffersNotOwnedByComponent();
mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
} else if (data2 == OMX_IndexConfigCommonOutputCrop) {
@@ -1876,7 +1920,12 @@
switch (msg->what()) {
case kWhatFlush:
case kWhatShutdown:
+ case kWhatResume:
{
+ if (msg->what() == kWhatResume) {
+ LOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
+ }
+
mCodec->deferMessage(msg);
handled = true;
break;
@@ -1925,7 +1974,10 @@
LOGV("[%s] Output port now reenabled.",
mCodec->mComponentName.c_str());
- mCodec->mExecutingState->submitOutputBuffers();
+ if (mCodec->mExecutingState->active()) {
+ mCodec->mExecutingState->submitOutputBuffers();
+ }
+
mCodec->changeState(mCodec->mExecutingState);
return true;
@@ -1992,6 +2044,13 @@
return true;
}
+ case OMX_EventPortSettingsChanged:
+ case OMX_EventBufferFlag:
+ {
+ // We're shutting down and don't care about this anymore.
+ return true;
+ }
+
default:
return BaseState::onOMXEvent(event, data1, data2);
}
@@ -2170,6 +2229,23 @@
return true;
}
+ case OMX_EventPortSettingsChanged:
+ {
+ sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id());
+ msg->setInt32("type", omx_message::EVENT);
+ msg->setPointer("node", mCodec->mNode);
+ msg->setInt32("event", event);
+ msg->setInt32("data1", data1);
+ msg->setInt32("data2", data2);
+
+ LOGV("[%s] Deferring OMX_EventPortSettingsChanged",
+ mCodec->mComponentName.c_str());
+
+ mCodec->deferMessage(msg);
+
+ return true;
+ }
+
default:
return BaseState::onOMXEvent(event, data1, data2);
}