From 63614c132b320a6146b6be85b8f3131135db4ba2 Mon Sep 17 00:00:00 2001 From: ApurupaPattapu Date: Thu, 28 Jun 2012 15:00:26 -0700 Subject: ACodec: Support for dynamic port reconfig - On port settings changed first flush output port - Move ACodec to new state called FlushingOutputState - Flush all output buffers, wait till all decoded buffers are rendered - Then disable output port, and allocate output buffers with new resolution, and reset native window Change-Id: Iafa266371ed2a87b909fbcb4eeae6b64208df617 --- media/libstagefright/ACodec.cpp | 167 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 165 insertions(+), 2 deletions(-) (limited to 'media') diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index 19bf28a..ddf95dc 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -337,8 +337,33 @@ private: DISALLOW_EVIL_CONSTRUCTORS(FlushingState); }; +#ifdef QCOM_HARDWARE //////////////////////////////////////////////////////////////////////////////// +struct ACodec::FlushingOutputState : public ACodec::BaseState { + FlushingOutputState(ACodec *codec); + +protected: + virtual PortMode getPortMode(OMX_U32 portIndex); + virtual bool onMessageReceived(const sp &msg); + virtual void stateEntered(); + + virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); + + virtual void onOutputBufferDrained(const sp &msg); + virtual void onInputBufferFilled(const sp &msg); + +private: + bool mFlushComplete; + + void changeStateIfWeOwnAllBuffers(); + + DISALLOW_EVIL_CONSTRUCTORS(FlushingOutputState); +}; + +//////////////////////////////////////////////////////////////////////////////// +#endif + ACodec::ACodec() : mQuirks(0), mNode(NULL), @@ -361,6 +386,9 @@ ACodec::ACodec() mExecutingToIdleState = new ExecutingToIdleState(this); mIdleToLoadedState = new IdleToLoadedState(this); mFlushingState = new FlushingState(this); +#ifdef QCOM_HARDWARE + mFlushingOutputState = new FlushingOutputState(this); +#endif mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false; mInputEOSResult = OK; @@ -3599,14 +3627,22 @@ bool ACodec::ExecutingState::onOMXEvent( CHECK_EQ(data1, (OMX_U32)kPortIndexOutput); if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) { +#ifdef QCOM_HARDWARE + ALOGV("Flush output port before disable"); + CHECK_EQ(mCodec->mOMX->sendCommand( + mCodec->mNode, OMX_CommandFlush, kPortIndexOutput), + (status_t)OK); + + mCodec->changeState(mCodec->mFlushingOutputState); +#else CHECK_EQ(mCodec->mOMX->sendCommand( mCodec->mNode, OMX_CommandPortDisable, kPortIndexOutput), - (status_t)OK); + (status_t)OK); mCodec->freeOutputBuffersNotOwnedByComponent(); - mCodec->changeState(mCodec->mOutputPortSettingsChangedState); +#endif } else if (data2 == OMX_IndexConfigCommonOutputCrop) { mCodec->mSentFormat = false; } else { @@ -4018,4 +4054,131 @@ void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() { } } +#ifdef QCOM_HARDWARE +//////////////////////////////////////////////////////////////////////////////// + +ACodec::FlushingOutputState::FlushingOutputState(ACodec *codec) + : BaseState(codec) { +} + +ACodec::BaseState::PortMode ACodec::FlushingOutputState::getPortMode(OMX_U32 portIndex) { + if (portIndex == kPortIndexOutput) + { + return KEEP_BUFFERS; + } + return RESUBMIT_BUFFERS; +} + +void ACodec::FlushingOutputState::stateEntered() { + ALOGV("[%s] Now Flushing Output Port", mCodec->mComponentName.c_str()); + + mFlushComplete = false; +} + +bool ACodec::FlushingOutputState::onMessageReceived(const sp &msg) { + bool handled = false; + + switch (msg->what()) { + case kWhatShutdown: + { + mCodec->deferMessage(msg); + handled = true; + break; + } + + case kWhatFlush: + { + ALOGV("Flush received during port reconfig, deferring it"); + mCodec->deferMessage(msg); + handled = true; + break; + } + + case kWhatInputBufferFilled: + { + mCodec->deferMessage(msg); + changeStateIfWeOwnAllBuffers(); + handled = true; + break; + } + + default: + handled = BaseState::onMessageReceived(msg); + break; + } + + return handled; +} + +bool ACodec::FlushingOutputState::onOMXEvent( + OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { + switch (event) { + case OMX_EventCmdComplete: + { + CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush); + CHECK_EQ(data2,(OMX_U32)kPortIndexOutput); + ALOGV("FlushingOutputState::onOMXEvent Output port flush complete"); + mFlushComplete = true; + changeStateIfWeOwnAllBuffers(); + return true; + } + + case OMX_EventPortSettingsChanged: + { + sp 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); + + ALOGV("[%s] Deferring OMX_EventPortSettingsChanged", + mCodec->mComponentName.c_str()); + + mCodec->deferMessage(msg); + + return true; + } + + default: + return BaseState::onOMXEvent(event, data1, data2); + } + + return true; +} + +void ACodec::FlushingOutputState::onOutputBufferDrained(const sp &msg) { + BaseState::onOutputBufferDrained(msg); + + changeStateIfWeOwnAllBuffers(); +} + +void ACodec::FlushingOutputState::onInputBufferFilled(const sp &msg) { + BaseState::onInputBufferFilled(msg); + + changeStateIfWeOwnAllBuffers(); +} + +void ACodec::FlushingOutputState::changeStateIfWeOwnAllBuffers() { + ALOGV("FlushingOutputState::ChangeState %d",mFlushComplete); + + if (mFlushComplete && mCodec->allYourBuffersAreBelongToUs( kPortIndexOutput )) { + ALOGV("FlushingOutputState Sending port disable "); + CHECK_EQ(mCodec->mOMX->sendCommand( + mCodec->mNode, + OMX_CommandPortDisable, kPortIndexOutput), + (status_t)OK); + + mCodec->mPortEOS[kPortIndexInput] = false; + mCodec->mPortEOS[kPortIndexOutput] = false; + + ALOGV("FlushingOutputState Calling freeOutputBuffersNotOwnedByComponent"); + mCodec->freeOutputBuffersNotOwnedByComponent(); + + ALOGV("FlushingOutputState Change state to port settings changed"); + mCodec->changeState(mCodec->mOutputPortSettingsChangedState); + } +} +#endif + } // namespace android -- cgit v1.1