ACodec.cpp revision 74006804065941841883c4b46ee785070164023f
189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project//#define LOG_NDEBUG 0 289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#define LOG_TAG "ACodec" 389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <media/stagefright/ACodec.h> 589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <binder/MemoryDealer.h> 789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <media/stagefright/foundation/hexdump.h> 989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <media/stagefright/foundation/ABuffer.h> 1089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <media/stagefright/foundation/ADebug.h> 1189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <media/stagefright/foundation/AMessage.h> 1289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 1389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <media/stagefright/MediaDefs.h> 1489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <media/stagefright/NativeWindowWrapper.h> 1589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <media/stagefright/OMXClient.h> 1689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 1789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <surfaceflinger/Surface.h> 1889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <gui/SurfaceTextureClient.h> 1989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 2089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <OMX_Component.h> 2189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 2289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectnamespace android { 2389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 2464760240f931714858a59c1579f07264d7182ba2Dima Zavintemplate<class T> 257394a4f358fa9908a9f0a7c954b65c399f4268e6Dima Zavinstatic void InitOMXParams(T *params) { 26fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin params->nSize = sizeof(T); 27db5cb14318bb24cd6ea14ff7ceea0d5e1f83d903Dima Zavin params->nVersion.s.nVersionMajor = 1; 28db5cb14318bb24cd6ea14ff7ceea0d5e1f83d903Dima Zavin params->nVersion.s.nVersionMinor = 0; 29db5cb14318bb24cd6ea14ff7ceea0d5e1f83d903Dima Zavin params->nVersion.s.nRevision = 0; 3089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project params->nVersion.s.nStep = 0; 3189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 3289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 33c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurentstruct CodecObserver : public BnOMXObserver { 34c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent CodecObserver() {} 35c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent 3689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project void setNotificationMessage(const sp<AMessage> &msg) { 3789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project mNotify = msg; 3889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 3989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 4089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project // from IOMXObserver 4189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project virtual void onMessage(const omx_message &omx_msg) { 4289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project sp<AMessage> msg = mNotify->dup(); 4389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 4489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project msg->setInt32("type", omx_msg.type); 45c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent msg->setPointer("node", omx_msg.node); 4689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 4789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project switch (omx_msg.type) { 4889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project case omx_message::EVENT: 49c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent { 5089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project msg->setInt32("event", omx_msg.u.event_data.event); 5189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project msg->setInt32("data1", omx_msg.u.event_data.data1); 524bcae82f9b07d1a39956c45a6f5bec0b696c4dd1Glenn Kasten msg->setInt32("data2", omx_msg.u.event_data.data2); 53c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent break; 54c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent } 5589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 5689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project case omx_message::EMPTY_BUFFER_DONE: 57c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent { 5872ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten msg->setPointer("buffer", omx_msg.u.buffer_data.buffer); 5972ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten break; 6072ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten } 6172ef00de10fa95bfcb948ed88ab9b7a177ed0b48Glenn Kasten 62c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent case omx_message::FILL_BUFFER_DONE: 63c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent { 64fff6d715a8db0daf08a50634f242c40268de3d49Glenn Kasten msg->setPointer( 65fff6d715a8db0daf08a50634f242c40268de3d49Glenn Kasten "buffer", omx_msg.u.extended_buffer_data.buffer); 6689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project msg->setInt32( 67f78aee70d15daf4690de7e7b4983ee68b0d1381dGlenn Kasten "range_offset", 68f78aee70d15daf4690de7e7b4983ee68b0d1381dGlenn Kasten omx_msg.u.extended_buffer_data.range_offset); 6989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project msg->setInt32( 70eda6c364c253ba97ee45a3adeb8c2b45db1f81dbEric Laurent "range_length", 71eda6c364c253ba97ee45a3adeb8c2b45db1f81dbEric Laurent omx_msg.u.extended_buffer_data.range_length); 72fff6d715a8db0daf08a50634f242c40268de3d49Glenn Kasten msg->setInt32( 7389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project "flags", 74c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent omx_msg.u.extended_buffer_data.flags); 75c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent msg->setInt64( 76c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent "timestamp", 77c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent omx_msg.u.extended_buffer_data.timestamp); 78c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent msg->setPointer( 79c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent "platform_private", 8089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project omx_msg.u.extended_buffer_data.platform_private); 8189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project msg->setPointer( 8289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project "data_ptr", 8389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project omx_msg.u.extended_buffer_data.data_ptr); 8489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project break; 8589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 8689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 8789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project default: 88fff6d715a8db0daf08a50634f242c40268de3d49Glenn Kasten TRESPASS(); 89fff6d715a8db0daf08a50634f242c40268de3d49Glenn Kasten break; 90fff6d715a8db0daf08a50634f242c40268de3d49Glenn Kasten } 911a9ed11a472493cac7f6dfcbfac2064526a493edEric Laurent 921a9ed11a472493cac7f6dfcbfac2064526a493edEric Laurent msg->post(); 931a9ed11a472493cac7f6dfcbfac2064526a493edEric Laurent } 941a9ed11a472493cac7f6dfcbfac2064526a493edEric Laurent 951a9ed11a472493cac7f6dfcbfac2064526a493edEric Laurentprotected: 961a9ed11a472493cac7f6dfcbfac2064526a493edEric Laurent virtual ~CodecObserver() {} 971a9ed11a472493cac7f6dfcbfac2064526a493edEric Laurent 981a9ed11a472493cac7f6dfcbfac2064526a493edEric Laurentprivate: 991a9ed11a472493cac7f6dfcbfac2064526a493edEric Laurent sp<AMessage> mNotify; 1001a9ed11a472493cac7f6dfcbfac2064526a493edEric Laurent 1011a9ed11a472493cac7f6dfcbfac2064526a493edEric Laurent DISALLOW_EVIL_CONSTRUCTORS(CodecObserver); 1021a9ed11a472493cac7f6dfcbfac2064526a493edEric Laurent}; 1031a9ed11a472493cac7f6dfcbfac2064526a493edEric Laurent 104c813985abd8ba61e999b3505f6a332574f87a1beAndreas Huber//////////////////////////////////////////////////////////////////////////////// 105c813985abd8ba61e999b3505f6a332574f87a1beAndreas Huber 106c813985abd8ba61e999b3505f6a332574f87a1beAndreas Huberstruct ACodec::BaseState : public AState { 107c813985abd8ba61e999b3505f6a332574f87a1beAndreas Huber BaseState(ACodec *codec, const sp<AState> &parentState = NULL); 108c813985abd8ba61e999b3505f6a332574f87a1beAndreas Huber 109c813985abd8ba61e999b3505f6a332574f87a1beAndreas Huberprotected: 11089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project enum PortMode { 111fff6d715a8db0daf08a50634f242c40268de3d49Glenn Kasten KEEP_BUFFERS, 112c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent RESUBMIT_BUFFERS, 11358f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten FREE_BUFFERS, 11489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project }; 11589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 116f0ee6f4055e26fb35d9c526a596668a4dc9da5baEric Laurent ACodec *mCodec; 117c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent 118342e9cf388cceb807def720e40e8b0a217f4bcaaEric Laurent virtual PortMode getPortMode(OMX_U32 portIndex); 1194bcae82f9b07d1a39956c45a6f5bec0b696c4dd1Glenn Kasten 120342e9cf388cceb807def720e40e8b0a217f4bcaaEric Laurent virtual bool onMessageReceived(const sp<AMessage> &msg); 121342e9cf388cceb807def720e40e8b0a217f4bcaaEric Laurent 122342e9cf388cceb807def720e40e8b0a217f4bcaaEric Laurent virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 123342e9cf388cceb807def720e40e8b0a217f4bcaaEric Laurent 124342e9cf388cceb807def720e40e8b0a217f4bcaaEric Laurent virtual void onOutputBufferDrained(const sp<AMessage> &msg); 125342e9cf388cceb807def720e40e8b0a217f4bcaaEric Laurent virtual void onInputBufferFilled(const sp<AMessage> &msg); 126342e9cf388cceb807def720e40e8b0a217f4bcaaEric Laurent 127fff6d715a8db0daf08a50634f242c40268de3d49Glenn Kasten void postFillThisBuffer(BufferInfo *info); 128342e9cf388cceb807def720e40e8b0a217f4bcaaEric Laurent 12905bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurentprivate: 130be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent bool onOMXMessage(const sp<AMessage> &msg); 131be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent 1323a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID); 1333a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen 134c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent bool onOMXFillBufferDone( 135c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent IOMX::buffer_id bufferID, 136c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent size_t rangeOffset, size_t rangeLength, 137c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent OMX_U32 flags, 138c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent int64_t timeUs, 139c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent void *platformPrivate, 140c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent void *dataPtr); 141c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent 142c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent void getMoreInputDataIfPossible(); 143c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent 144c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent DISALLOW_EVIL_CONSTRUCTORS(BaseState); 145c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent}; 146c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent 14799e53b86eebb605b70dd7591b89bf61a9414ed0eGlenn Kasten//////////////////////////////////////////////////////////////////////////////// 148c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent 149c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurentstruct ACodec::UninitializedState : public ACodec::BaseState { 150c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent UninitializedState(ACodec *codec); 151c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent 15258f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kastenprotected: 153c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent virtual bool onMessageReceived(const sp<AMessage> &msg); 154c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent 155c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurentprivate: 156c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent void onSetup(const sp<AMessage> &msg); 157c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent 158c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent DISALLOW_EVIL_CONSTRUCTORS(UninitializedState); 159c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent}; 160c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent 161a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent//////////////////////////////////////////////////////////////////////////////// 162a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent 163a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurentstruct ACodec::LoadedToIdleState : public ACodec::BaseState { 164a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent LoadedToIdleState(ACodec *codec); 165a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent 166a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurentprotected: 167a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent virtual bool onMessageReceived(const sp<AMessage> &msg); 168a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 169a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent virtual void stateEntered(); 170a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent 171a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurentprivate: 172a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent status_t allocateBuffers(); 173a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent 174a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState); 175a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent}; 1762986460984580833161bdaabc7f17da1005a8961Eric Laurent 1772986460984580833161bdaabc7f17da1005a8961Eric Laurent//////////////////////////////////////////////////////////////////////////////// 1782986460984580833161bdaabc7f17da1005a8961Eric Laurent 1792986460984580833161bdaabc7f17da1005a8961Eric Laurentstruct ACodec::IdleToExecutingState : public ACodec::BaseState { 180c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent IdleToExecutingState(ACodec *codec); 181c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent 182c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurentprotected: 183fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin virtual bool onMessageReceived(const sp<AMessage> &msg); 184fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 185f78aee70d15daf4690de7e7b4983ee68b0d1381dGlenn Kasten virtual void stateEntered(); 186fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin 187fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavinprivate: 188fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState); 189c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent}; 19058f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten 191fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin//////////////////////////////////////////////////////////////////////////////// 1920ca3cf94c0dfc173ad7886ae162c4b67067539f6Eric Laurent 193de070137f11d346fba77605bd76a44c040a618fcEric Laurentstruct ACodec::ExecutingState : public ACodec::BaseState { 194fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin ExecutingState(ACodec *codec); 195de070137f11d346fba77605bd76a44c040a618fcEric Laurent 196de070137f11d346fba77605bd76a44c040a618fcEric Laurent void submitOutputBuffers(); 197fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin 198de070137f11d346fba77605bd76a44c040a618fcEric Laurent // Submit output buffers to the decoder, submit input buffers to client 199c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent // to fill with data. 200eba51fb3a361f67a6a64d5a16eba6084fe27d60eGlenn Kasten void resume(); 201c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent 20258f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten // Returns true iff input and output buffers are in play. 203fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin bool active() const { return mActive; } 2047c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent 2057c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurentprotected: 206c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent virtual PortMode getPortMode(OMX_U32 portIndex); 207c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent virtual bool onMessageReceived(const sp<AMessage> &msg); 208c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent virtual void stateEntered(); 209fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin 210c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 211c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent 21283844cc2f95dc279015b47fd1e18c7cb4eabe9a1Eric Laurentprivate: 21383844cc2f95dc279015b47fd1e18c7cb4eabe9a1Eric Laurent bool mActive; 21483844cc2f95dc279015b47fd1e18c7cb4eabe9a1Eric Laurent 21583844cc2f95dc279015b47fd1e18c7cb4eabe9a1Eric Laurent DISALLOW_EVIL_CONSTRUCTORS(ExecutingState); 21683844cc2f95dc279015b47fd1e18c7cb4eabe9a1Eric Laurent}; 21783844cc2f95dc279015b47fd1e18c7cb4eabe9a1Eric Laurent 218c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent//////////////////////////////////////////////////////////////////////////////// 219fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin 2206374252107fd6539397598195ea6defd5870fafbEric Laurentstruct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState { 221de070137f11d346fba77605bd76a44c040a618fcEric Laurent OutputPortSettingsChangedState(ACodec *codec); 222de070137f11d346fba77605bd76a44c040a618fcEric Laurent 223de070137f11d346fba77605bd76a44c040a618fcEric Laurentprotected: 2247c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent virtual PortMode getPortMode(OMX_U32 portIndex); 225de070137f11d346fba77605bd76a44c040a618fcEric Laurent virtual bool onMessageReceived(const sp<AMessage> &msg); 226de070137f11d346fba77605bd76a44c040a618fcEric Laurent virtual void stateEntered(); 227de070137f11d346fba77605bd76a44c040a618fcEric Laurent 228de070137f11d346fba77605bd76a44c040a618fcEric Laurent virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 229db7c079f284f6e91266f6653ae0ec198b1c5006eEric Laurent 230de070137f11d346fba77605bd76a44c040a618fcEric Laurentprivate: 2319f6530f53ae9eda43f4e7c1cb30d2379db00aa00Eric Laurent DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState); 2329f6530f53ae9eda43f4e7c1cb30d2379db00aa00Eric Laurent}; 2339f6530f53ae9eda43f4e7c1cb30d2379db00aa00Eric Laurent 2349f6530f53ae9eda43f4e7c1cb30d2379db00aa00Eric Laurent//////////////////////////////////////////////////////////////////////////////// 235c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent 236c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurentstruct ACodec::ExecutingToIdleState : public ACodec::BaseState { 23789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project ExecutingToIdleState(ACodec *codec); 23889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 23989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectprotected: 24089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project virtual bool onMessageReceived(const sp<AMessage> &msg); 24189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project virtual void stateEntered(); 24289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 24389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 244c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent 24589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project virtual void onOutputBufferDrained(const sp<AMessage> &msg); 246c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent virtual void onInputBufferFilled(const sp<AMessage> &msg); 24789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 24889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectprivate: 249c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent void changeStateIfWeOwnAllBuffers(); 25089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 251c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState); 252c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent}; 253b81cc8c6f3eec9edb255ea99b6a6f243585b1e38Glenn Kasten 254b81cc8c6f3eec9edb255ea99b6a6f243585b1e38Glenn Kasten//////////////////////////////////////////////////////////////////////////////// 25589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 25689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstruct ACodec::IdleToLoadedState : public ACodec::BaseState { 257c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent IdleToLoadedState(ACodec *codec); 258c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent 259c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurentprotected: 260c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent virtual bool onMessageReceived(const sp<AMessage> &msg); 261c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent virtual void stateEntered(); 26289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 263c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 264c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent 265c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurentprivate: 266c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState); 267c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent}; 268c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent 26989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project//////////////////////////////////////////////////////////////////////////////// 270c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent 27189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstruct ACodec::ErrorState : public ACodec::BaseState { 27289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project ErrorState(ACodec *codec); 27389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 27489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectprotected: 275c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent virtual bool onMessageReceived(const sp<AMessage> &msg); 27689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project virtual void stateEntered(); 27789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 27889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 27958f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten 28089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectprivate: 28189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project DISALLOW_EVIL_CONSTRUCTORS(ErrorState); 282c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent}; 283c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent 284c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent//////////////////////////////////////////////////////////////////////////////// 285211eeaf17e5565b68447d29799dbf158a33cf4cfGlenn Kasten 2869f6530f53ae9eda43f4e7c1cb30d2379db00aa00Eric Laurentstruct ACodec::FlushingState : public ACodec::BaseState { 2879f6530f53ae9eda43f4e7c1cb30d2379db00aa00Eric Laurent FlushingState(ACodec *codec); 288c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent 289c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurentprotected: 290c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent virtual bool onMessageReceived(const sp<AMessage> &msg); 29189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project virtual void stateEntered(); 29289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 29389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 294 295 virtual void onOutputBufferDrained(const sp<AMessage> &msg); 296 virtual void onInputBufferFilled(const sp<AMessage> &msg); 297 298private: 299 bool mFlushComplete[2]; 300 301 void changeStateIfWeOwnAllBuffers(); 302 303 DISALLOW_EVIL_CONSTRUCTORS(FlushingState); 304}; 305 306//////////////////////////////////////////////////////////////////////////////// 307 308ACodec::ACodec() 309 : mNode(NULL), 310 mSentFormat(false) { 311 mUninitializedState = new UninitializedState(this); 312 mLoadedToIdleState = new LoadedToIdleState(this); 313 mIdleToExecutingState = new IdleToExecutingState(this); 314 mExecutingState = new ExecutingState(this); 315 316 mOutputPortSettingsChangedState = 317 new OutputPortSettingsChangedState(this); 318 319 mExecutingToIdleState = new ExecutingToIdleState(this); 320 mIdleToLoadedState = new IdleToLoadedState(this); 321 mErrorState = new ErrorState(this); 322 mFlushingState = new FlushingState(this); 323 324 mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false; 325 326 changeState(mUninitializedState); 327} 328 329ACodec::~ACodec() { 330} 331 332void ACodec::setNotificationMessage(const sp<AMessage> &msg) { 333 mNotify = msg; 334} 335 336void ACodec::initiateSetup(const sp<AMessage> &msg) { 337 msg->setWhat(kWhatSetup); 338 msg->setTarget(id()); 339 msg->post(); 340} 341 342void ACodec::signalFlush() { 343 (new AMessage(kWhatFlush, id()))->post(); 344} 345 346void ACodec::signalResume() { 347 (new AMessage(kWhatResume, id()))->post(); 348} 349 350void ACodec::initiateShutdown() { 351 (new AMessage(kWhatShutdown, id()))->post(); 352} 353 354status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) { 355 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 356 357 CHECK(mDealer[portIndex] == NULL); 358 CHECK(mBuffers[portIndex].isEmpty()); 359 360 if (mNativeWindow != NULL && portIndex == kPortIndexOutput) { 361 return allocateOutputBuffersFromNativeWindow(); 362 } 363 364 OMX_PARAM_PORTDEFINITIONTYPE def; 365 InitOMXParams(&def); 366 def.nPortIndex = portIndex; 367 368 status_t err = mOMX->getParameter( 369 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 370 371 if (err != OK) { 372 return err; 373 } 374 375 LOGV("[%s] Allocating %lu buffers of size %lu on %s port", 376 mComponentName.c_str(), 377 def.nBufferCountActual, def.nBufferSize, 378 portIndex == kPortIndexInput ? "input" : "output"); 379 380 size_t totalSize = def.nBufferCountActual * def.nBufferSize; 381 mDealer[portIndex] = new MemoryDealer(totalSize, "OMXCodec"); 382 383 for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) { 384 sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize); 385 CHECK(mem.get() != NULL); 386 387 IOMX::buffer_id buffer; 388#if 0 389 err = mOMX->allocateBufferWithBackup(mNode, portIndex, mem, &buffer); 390#else 391 err = mOMX->useBuffer(mNode, portIndex, mem, &buffer); 392#endif 393 394 if (err != OK) { 395 return err; 396 } 397 398 BufferInfo info; 399 info.mBufferID = buffer; 400 info.mStatus = BufferInfo::OWNED_BY_US; 401 info.mData = new ABuffer(mem->pointer(), def.nBufferSize); 402 mBuffers[portIndex].push(info); 403 } 404 405 return OK; 406} 407 408status_t ACodec::allocateOutputBuffersFromNativeWindow() { 409 OMX_PARAM_PORTDEFINITIONTYPE def; 410 InitOMXParams(&def); 411 def.nPortIndex = kPortIndexOutput; 412 413 status_t err = mOMX->getParameter( 414 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 415 416 if (err != OK) { 417 return err; 418 } 419 420 err = native_window_set_buffers_geometry( 421 mNativeWindow.get(), 422 def.format.video.nFrameWidth, 423 def.format.video.nFrameHeight, 424 def.format.video.eColorFormat); 425 426 if (err != 0) { 427 LOGE("native_window_set_buffers_geometry failed: %s (%d)", 428 strerror(-err), -err); 429 return err; 430 } 431 432 // Increase the buffer count by one to allow for the ANativeWindow to hold 433 // on to one of the buffers. 434 def.nBufferCountActual++; 435 err = mOMX->setParameter( 436 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 437 438 if (err != OK) { 439 return err; 440 } 441 442 // Set up the native window. 443 // XXX TODO: Get the gralloc usage flags from the OMX plugin! 444 err = native_window_set_usage( 445 mNativeWindow.get(), 446 GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP); 447 448 if (err != 0) { 449 LOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err); 450 return err; 451 } 452 453 err = native_window_set_buffer_count( 454 mNativeWindow.get(), def.nBufferCountActual); 455 456 if (err != 0) { 457 LOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), 458 -err); 459 return err; 460 } 461 462 LOGV("[%s] Allocating %lu buffers from a native window of size %lu on " 463 "output port", 464 mComponentName.c_str(), def.nBufferCountActual, def.nBufferSize); 465 466 // Dequeue buffers and send them to OMX 467 for (OMX_U32 i = 0; i < def.nBufferCountActual; i++) { 468 android_native_buffer_t *buf; 469 err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf); 470 if (err != 0) { 471 LOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err); 472 break; 473 } 474 475 sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false)); 476 BufferInfo info; 477 info.mStatus = BufferInfo::OWNED_BY_US; 478 info.mData = new ABuffer(0); 479 info.mGraphicBuffer = graphicBuffer; 480 mBuffers[kPortIndexOutput].push(info); 481 482 IOMX::buffer_id bufferId; 483 err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer, 484 &bufferId); 485 if (err != 0) { 486 LOGE("registering GraphicBuffer %lu with OMX IL component failed: " 487 "%d", i, err); 488 break; 489 } 490 491 mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId; 492 493 LOGV("[%s] Registered graphic buffer with ID %p (pointer = %p)", 494 mComponentName.c_str(), 495 bufferId, graphicBuffer.get()); 496 } 497 498 OMX_U32 cancelStart; 499 OMX_U32 cancelEnd; 500 501 if (err != 0) { 502 // If an error occurred while dequeuing we need to cancel any buffers 503 // that were dequeued. 504 cancelStart = 0; 505 cancelEnd = mBuffers[kPortIndexOutput].size(); 506 } else { 507 // Return the last two buffers to the native window. 508 // XXX TODO: The number of buffers the native window owns should 509 // probably be queried from it when we put the native window in 510 // fixed buffer pool mode (which needs to be implemented). 511 // Currently it's hard-coded to 2. 512 cancelStart = def.nBufferCountActual - 2; 513 cancelEnd = def.nBufferCountActual; 514 } 515 516 for (OMX_U32 i = cancelStart; i < cancelEnd; i++) { 517 BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i); 518 cancelBufferToNativeWindow(info); 519 } 520 521 return err; 522} 523 524status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) { 525 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 526 527 LOGV("[%s] Calling cancelBuffer on buffer %p", 528 mComponentName.c_str(), info->mBufferID); 529 530 int err = mNativeWindow->cancelBuffer( 531 mNativeWindow.get(), info->mGraphicBuffer.get()); 532 533 CHECK_EQ(err, 0); 534 535 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 536 537 return OK; 538} 539 540ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() { 541 android_native_buffer_t *buf; 542 CHECK_EQ(mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf), 0); 543 544 for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) { 545 BufferInfo *info = 546 &mBuffers[kPortIndexOutput].editItemAt(i); 547 548 if (info->mGraphicBuffer->handle == buf->handle) { 549 CHECK_EQ((int)info->mStatus, 550 (int)BufferInfo::OWNED_BY_NATIVE_WINDOW); 551 552 info->mStatus = BufferInfo::OWNED_BY_US; 553 554 return info; 555 } 556 } 557 558 TRESPASS(); 559 560 return NULL; 561} 562 563status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) { 564 for (size_t i = mBuffers[portIndex].size(); i-- > 0;) { 565 CHECK_EQ((status_t)OK, freeBuffer(portIndex, i)); 566 } 567 568 mDealer[portIndex].clear(); 569 570 return OK; 571} 572 573status_t ACodec::freeOutputBuffersNotOwnedByComponent() { 574 for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) { 575 BufferInfo *info = 576 &mBuffers[kPortIndexOutput].editItemAt(i); 577 578 if (info->mStatus != 579 BufferInfo::OWNED_BY_COMPONENT) { 580 // We shouldn't have sent out any buffers to the client at this 581 // point. 582 CHECK_NE((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM); 583 584 CHECK_EQ((status_t)OK, freeBuffer(kPortIndexOutput, i)); 585 } 586 } 587 588 return OK; 589} 590 591status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) { 592 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 593 594 CHECK(info->mStatus == BufferInfo::OWNED_BY_US 595 || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW); 596 597 if (portIndex == kPortIndexOutput && mNativeWindow != NULL 598 && info->mStatus == BufferInfo::OWNED_BY_US) { 599 CHECK_EQ((status_t)OK, cancelBufferToNativeWindow(info)); 600 } 601 602 CHECK_EQ(mOMX->freeBuffer( 603 mNode, portIndex, info->mBufferID), 604 (status_t)OK); 605 606 mBuffers[portIndex].removeAt(i); 607 608 return OK; 609} 610 611ACodec::BufferInfo *ACodec::findBufferByID( 612 uint32_t portIndex, IOMX::buffer_id bufferID, 613 ssize_t *index) { 614 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 615 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 616 617 if (info->mBufferID == bufferID) { 618 if (index != NULL) { 619 *index = i; 620 } 621 return info; 622 } 623 } 624 625 TRESPASS(); 626 627 return NULL; 628} 629 630void ACodec::setComponentRole( 631 bool isEncoder, const char *mime) { 632 struct MimeToRole { 633 const char *mime; 634 const char *decoderRole; 635 const char *encoderRole; 636 }; 637 638 static const MimeToRole kMimeToRole[] = { 639 { MEDIA_MIMETYPE_AUDIO_MPEG, 640 "audio_decoder.mp3", "audio_encoder.mp3" }, 641 { MEDIA_MIMETYPE_AUDIO_AMR_NB, 642 "audio_decoder.amrnb", "audio_encoder.amrnb" }, 643 { MEDIA_MIMETYPE_AUDIO_AMR_WB, 644 "audio_decoder.amrwb", "audio_encoder.amrwb" }, 645 { MEDIA_MIMETYPE_AUDIO_AAC, 646 "audio_decoder.aac", "audio_encoder.aac" }, 647 { MEDIA_MIMETYPE_VIDEO_AVC, 648 "video_decoder.avc", "video_encoder.avc" }, 649 { MEDIA_MIMETYPE_VIDEO_MPEG4, 650 "video_decoder.mpeg4", "video_encoder.mpeg4" }, 651 { MEDIA_MIMETYPE_VIDEO_H263, 652 "video_decoder.h263", "video_encoder.h263" }, 653 }; 654 655 static const size_t kNumMimeToRole = 656 sizeof(kMimeToRole) / sizeof(kMimeToRole[0]); 657 658 size_t i; 659 for (i = 0; i < kNumMimeToRole; ++i) { 660 if (!strcasecmp(mime, kMimeToRole[i].mime)) { 661 break; 662 } 663 } 664 665 if (i == kNumMimeToRole) { 666 return; 667 } 668 669 const char *role = 670 isEncoder ? kMimeToRole[i].encoderRole 671 : kMimeToRole[i].decoderRole; 672 673 if (role != NULL) { 674 OMX_PARAM_COMPONENTROLETYPE roleParams; 675 InitOMXParams(&roleParams); 676 677 strncpy((char *)roleParams.cRole, 678 role, OMX_MAX_STRINGNAME_SIZE - 1); 679 680 roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0'; 681 682 status_t err = mOMX->setParameter( 683 mNode, OMX_IndexParamStandardComponentRole, 684 &roleParams, sizeof(roleParams)); 685 686 if (err != OK) { 687 LOGW("[%s] Failed to set standard component role '%s'.", 688 mComponentName.c_str(), role); 689 } 690 } 691} 692 693void ACodec::configureCodec( 694 const char *mime, const sp<AMessage> &msg) { 695 setComponentRole(false /* isEncoder */, mime); 696 697 if (!strncasecmp(mime, "video/", 6)) { 698 int32_t width, height; 699 CHECK(msg->findInt32("width", &width)); 700 CHECK(msg->findInt32("height", &height)); 701 702 CHECK_EQ(setupVideoDecoder(mime, width, height), 703 (status_t)OK); 704 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 705 int32_t numChannels, sampleRate; 706 CHECK(msg->findInt32("channel-count", &numChannels)); 707 CHECK(msg->findInt32("sample-rate", &sampleRate)); 708 709 CHECK_EQ(setupAACDecoder(numChannels, sampleRate), (status_t)OK); 710 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) { 711 } else { 712 TRESPASS(); 713 } 714 715 int32_t maxInputSize; 716 if (msg->findInt32("max-input-size", &maxInputSize)) { 717 CHECK_EQ(setMinBufferSize(kPortIndexInput, (size_t)maxInputSize), 718 (status_t)OK); 719 } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) { 720 CHECK_EQ(setMinBufferSize(kPortIndexInput, 8192), // XXX 721 (status_t)OK); 722 } 723} 724 725status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) { 726 OMX_PARAM_PORTDEFINITIONTYPE def; 727 InitOMXParams(&def); 728 def.nPortIndex = portIndex; 729 730 status_t err = mOMX->getParameter( 731 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 732 733 if (err != OK) { 734 return err; 735 } 736 737 if (def.nBufferSize >= size) { 738 return OK; 739 } 740 741 def.nBufferSize = size; 742 743 err = mOMX->setParameter( 744 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 745 746 if (err != OK) { 747 return err; 748 } 749 750 err = mOMX->getParameter( 751 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 752 753 if (err != OK) { 754 return err; 755 } 756 757 CHECK(def.nBufferSize >= size); 758 759 return OK; 760} 761 762status_t ACodec::setupAACDecoder(int32_t numChannels, int32_t sampleRate) { 763 OMX_AUDIO_PARAM_AACPROFILETYPE profile; 764 InitOMXParams(&profile); 765 profile.nPortIndex = kPortIndexInput; 766 767 status_t err = mOMX->getParameter( 768 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 769 770 if (err != OK) { 771 return err; 772 } 773 774 profile.nChannels = numChannels; 775 profile.nSampleRate = sampleRate; 776 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS; 777 778 err = mOMX->setParameter( 779 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 780 781 return err; 782} 783 784status_t ACodec::setVideoPortFormatType( 785 OMX_U32 portIndex, 786 OMX_VIDEO_CODINGTYPE compressionFormat, 787 OMX_COLOR_FORMATTYPE colorFormat) { 788 OMX_VIDEO_PARAM_PORTFORMATTYPE format; 789 InitOMXParams(&format); 790 format.nPortIndex = portIndex; 791 format.nIndex = 0; 792 bool found = false; 793 794 OMX_U32 index = 0; 795 for (;;) { 796 format.nIndex = index; 797 status_t err = mOMX->getParameter( 798 mNode, OMX_IndexParamVideoPortFormat, 799 &format, sizeof(format)); 800 801 if (err != OK) { 802 return err; 803 } 804 805 // The following assertion is violated by TI's video decoder. 806 // CHECK_EQ(format.nIndex, index); 807 808 if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) { 809 if (portIndex == kPortIndexInput 810 && colorFormat == format.eColorFormat) { 811 // eCompressionFormat does not seem right. 812 found = true; 813 break; 814 } 815 if (portIndex == kPortIndexOutput 816 && compressionFormat == format.eCompressionFormat) { 817 // eColorFormat does not seem right. 818 found = true; 819 break; 820 } 821 } 822 823 if (format.eCompressionFormat == compressionFormat 824 && format.eColorFormat == colorFormat) { 825 found = true; 826 break; 827 } 828 829 ++index; 830 } 831 832 if (!found) { 833 return UNKNOWN_ERROR; 834 } 835 836 status_t err = mOMX->setParameter( 837 mNode, OMX_IndexParamVideoPortFormat, 838 &format, sizeof(format)); 839 840 return err; 841} 842 843status_t ACodec::setSupportedOutputFormat() { 844 OMX_VIDEO_PARAM_PORTFORMATTYPE format; 845 InitOMXParams(&format); 846 format.nPortIndex = kPortIndexOutput; 847 format.nIndex = 0; 848 849 status_t err = mOMX->getParameter( 850 mNode, OMX_IndexParamVideoPortFormat, 851 &format, sizeof(format)); 852 CHECK_EQ(err, (status_t)OK); 853 CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused); 854 855 static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00; 856 857 CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar 858 || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar 859 || format.eColorFormat == OMX_COLOR_FormatCbYCrY 860 || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar); 861 862 return mOMX->setParameter( 863 mNode, OMX_IndexParamVideoPortFormat, 864 &format, sizeof(format)); 865} 866 867status_t ACodec::setupVideoDecoder( 868 const char *mime, int32_t width, int32_t height) { 869 OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused; 870 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 871 compressionFormat = OMX_VIDEO_CodingAVC; 872 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 873 compressionFormat = OMX_VIDEO_CodingMPEG4; 874 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 875 compressionFormat = OMX_VIDEO_CodingH263; 876 } else { 877 TRESPASS(); 878 } 879 880 status_t err = setVideoPortFormatType( 881 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused); 882 883 if (err != OK) { 884 return err; 885 } 886 887 err = setSupportedOutputFormat(); 888 889 if (err != OK) { 890 return err; 891 } 892 893 err = setVideoFormatOnPort( 894 kPortIndexInput, width, height, compressionFormat); 895 896 if (err != OK) { 897 return err; 898 } 899 900 err = setVideoFormatOnPort( 901 kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused); 902 903 if (err != OK) { 904 return err; 905 } 906 907 return OK; 908} 909 910status_t ACodec::setVideoFormatOnPort( 911 OMX_U32 portIndex, 912 int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) { 913 OMX_PARAM_PORTDEFINITIONTYPE def; 914 InitOMXParams(&def); 915 def.nPortIndex = portIndex; 916 917 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 918 919 status_t err = mOMX->getParameter( 920 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 921 922 CHECK_EQ(err, (status_t)OK); 923 924 if (portIndex == kPortIndexInput) { 925 // XXX Need a (much) better heuristic to compute input buffer sizes. 926 const size_t X = 64 * 1024; 927 if (def.nBufferSize < X) { 928 def.nBufferSize = X; 929 } 930 } 931 932 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo); 933 934 video_def->nFrameWidth = width; 935 video_def->nFrameHeight = height; 936 937 if (portIndex == kPortIndexInput) { 938 video_def->eCompressionFormat = compressionFormat; 939 video_def->eColorFormat = OMX_COLOR_FormatUnused; 940 } 941 942 err = mOMX->setParameter( 943 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 944 945 return err; 946} 947 948status_t ACodec::initNativeWindow() { 949 if (mNativeWindow != NULL) { 950 return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE); 951 } 952 953 mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE); 954 return OK; 955} 956 957bool ACodec::allYourBuffersAreBelongToUs( 958 OMX_U32 portIndex) { 959 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 960 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 961 962 if (info->mStatus != BufferInfo::OWNED_BY_US 963 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) { 964 LOGV("[%s] Buffer %p on port %ld still has status %d", 965 mComponentName.c_str(), 966 info->mBufferID, portIndex, info->mStatus); 967 return false; 968 } 969 } 970 971 return true; 972} 973 974bool ACodec::allYourBuffersAreBelongToUs() { 975 return allYourBuffersAreBelongToUs(kPortIndexInput) 976 && allYourBuffersAreBelongToUs(kPortIndexOutput); 977} 978 979void ACodec::deferMessage(const sp<AMessage> &msg) { 980 bool wasEmptyBefore = mDeferredQueue.empty(); 981 mDeferredQueue.push_back(msg); 982} 983 984void ACodec::processDeferredMessages() { 985 List<sp<AMessage> > queue = mDeferredQueue; 986 mDeferredQueue.clear(); 987 988 List<sp<AMessage> >::iterator it = queue.begin(); 989 while (it != queue.end()) { 990 onMessageReceived(*it++); 991 } 992} 993 994void ACodec::sendFormatChange() { 995 sp<AMessage> notify = mNotify->dup(); 996 notify->setInt32("what", kWhatOutputFormatChanged); 997 998 OMX_PARAM_PORTDEFINITIONTYPE def; 999 InitOMXParams(&def); 1000 def.nPortIndex = kPortIndexOutput; 1001 1002 CHECK_EQ(mOMX->getParameter( 1003 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)), 1004 (status_t)OK); 1005 1006 CHECK_EQ((int)def.eDir, (int)OMX_DirOutput); 1007 1008 switch (def.eDomain) { 1009 case OMX_PortDomainVideo: 1010 { 1011 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video; 1012 1013 notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW); 1014 notify->setInt32("width", videoDef->nFrameWidth); 1015 notify->setInt32("height", videoDef->nFrameHeight); 1016 1017 OMX_CONFIG_RECTTYPE rect; 1018 InitOMXParams(&rect); 1019 rect.nPortIndex = kPortIndexOutput; 1020 1021 if (mOMX->getConfig( 1022 mNode, OMX_IndexConfigCommonOutputCrop, 1023 &rect, sizeof(rect)) != OK) { 1024 rect.nLeft = 0; 1025 rect.nTop = 0; 1026 rect.nWidth = videoDef->nFrameWidth; 1027 rect.nHeight = videoDef->nFrameHeight; 1028 } 1029 1030 CHECK_GE(rect.nLeft, 0); 1031 CHECK_GE(rect.nTop, 0); 1032 CHECK_GE(rect.nWidth, 0u); 1033 CHECK_GE(rect.nHeight, 0u); 1034 CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth); 1035 CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight); 1036 1037 notify->setRect( 1038 "crop", 1039 rect.nLeft, 1040 rect.nTop, 1041 rect.nLeft + rect.nWidth - 1, 1042 rect.nTop + rect.nHeight - 1); 1043 1044 if (mNativeWindow != NULL) { 1045 android_native_rect_t crop; 1046 crop.left = rect.nLeft; 1047 crop.top = rect.nTop; 1048 crop.right = rect.nLeft + rect.nWidth - 1; 1049 crop.bottom = rect.nTop + rect.nHeight - 1; 1050 1051 CHECK_EQ(0, native_window_set_crop( 1052 mNativeWindow.get(), &crop)); 1053 } 1054 break; 1055 } 1056 1057 case OMX_PortDomainAudio: 1058 { 1059 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio; 1060 CHECK_EQ((int)audioDef->eEncoding, (int)OMX_AUDIO_CodingPCM); 1061 1062 OMX_AUDIO_PARAM_PCMMODETYPE params; 1063 InitOMXParams(¶ms); 1064 params.nPortIndex = kPortIndexOutput; 1065 1066 CHECK_EQ(mOMX->getParameter( 1067 mNode, OMX_IndexParamAudioPcm, 1068 ¶ms, sizeof(params)), 1069 (status_t)OK); 1070 1071 CHECK(params.nChannels == 1 || params.bInterleaved); 1072 CHECK_EQ(params.nBitPerSample, 16u); 1073 CHECK_EQ((int)params.eNumData, (int)OMX_NumericalDataSigned); 1074 CHECK_EQ((int)params.ePCMMode, (int)OMX_AUDIO_PCMModeLinear); 1075 1076 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW); 1077 notify->setInt32("channel-count", params.nChannels); 1078 notify->setInt32("sample-rate", params.nSamplingRate); 1079 break; 1080 } 1081 1082 default: 1083 TRESPASS(); 1084 } 1085 1086 notify->post(); 1087 1088 mSentFormat = true; 1089} 1090 1091//////////////////////////////////////////////////////////////////////////////// 1092 1093ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState) 1094 : AState(parentState), 1095 mCodec(codec) { 1096} 1097 1098ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(OMX_U32 portIndex) { 1099 return KEEP_BUFFERS; 1100} 1101 1102bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) { 1103 switch (msg->what()) { 1104 case kWhatInputBufferFilled: 1105 { 1106 onInputBufferFilled(msg); 1107 break; 1108 } 1109 1110 case kWhatOutputBufferDrained: 1111 { 1112 onOutputBufferDrained(msg); 1113 break; 1114 } 1115 1116 case ACodec::kWhatOMXMessage: 1117 { 1118 return onOMXMessage(msg); 1119 } 1120 1121 default: 1122 return false; 1123 } 1124 1125 return true; 1126} 1127 1128bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) { 1129 int32_t type; 1130 CHECK(msg->findInt32("type", &type)); 1131 1132 IOMX::node_id nodeID; 1133 CHECK(msg->findPointer("node", &nodeID)); 1134 CHECK_EQ(nodeID, mCodec->mNode); 1135 1136 switch (type) { 1137 case omx_message::EVENT: 1138 { 1139 int32_t event, data1, data2; 1140 CHECK(msg->findInt32("event", &event)); 1141 CHECK(msg->findInt32("data1", &data1)); 1142 CHECK(msg->findInt32("data2", &data2)); 1143 1144 return onOMXEvent( 1145 static_cast<OMX_EVENTTYPE>(event), 1146 static_cast<OMX_U32>(data1), 1147 static_cast<OMX_U32>(data2)); 1148 } 1149 1150 case omx_message::EMPTY_BUFFER_DONE: 1151 { 1152 IOMX::buffer_id bufferID; 1153 CHECK(msg->findPointer("buffer", &bufferID)); 1154 1155 return onOMXEmptyBufferDone(bufferID); 1156 } 1157 1158 case omx_message::FILL_BUFFER_DONE: 1159 { 1160 IOMX::buffer_id bufferID; 1161 CHECK(msg->findPointer("buffer", &bufferID)); 1162 1163 int32_t rangeOffset, rangeLength, flags; 1164 int64_t timeUs; 1165 void *platformPrivate; 1166 void *dataPtr; 1167 1168 CHECK(msg->findInt32("range_offset", &rangeOffset)); 1169 CHECK(msg->findInt32("range_length", &rangeLength)); 1170 CHECK(msg->findInt32("flags", &flags)); 1171 CHECK(msg->findInt64("timestamp", &timeUs)); 1172 CHECK(msg->findPointer("platform_private", &platformPrivate)); 1173 CHECK(msg->findPointer("data_ptr", &dataPtr)); 1174 1175 return onOMXFillBufferDone( 1176 bufferID, 1177 (size_t)rangeOffset, (size_t)rangeLength, 1178 (OMX_U32)flags, 1179 timeUs, 1180 platformPrivate, 1181 dataPtr); 1182 } 1183 1184 default: 1185 TRESPASS(); 1186 break; 1187 } 1188} 1189 1190bool ACodec::BaseState::onOMXEvent( 1191 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 1192 if (event != OMX_EventError) { 1193 LOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)", 1194 mCodec->mComponentName.c_str(), event, data1, data2); 1195 1196 return false; 1197 } 1198 1199 LOGE("[%s] ERROR(0x%08lx, 0x%08lx)", 1200 mCodec->mComponentName.c_str(), data1, data2); 1201 1202 mCodec->changeState(mCodec->mErrorState); 1203 1204 return true; 1205} 1206 1207bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) { 1208 LOGV("[%s] onOMXEmptyBufferDone %p", 1209 mCodec->mComponentName.c_str(), bufferID); 1210 1211 BufferInfo *info = 1212 mCodec->findBufferByID(kPortIndexInput, bufferID); 1213 1214 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); 1215 info->mStatus = BufferInfo::OWNED_BY_US; 1216 1217 PortMode mode = getPortMode(kPortIndexInput); 1218 1219 switch (mode) { 1220 case KEEP_BUFFERS: 1221 break; 1222 1223 case RESUBMIT_BUFFERS: 1224 postFillThisBuffer(info); 1225 break; 1226 1227 default: 1228 { 1229 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 1230 TRESPASS(); // Not currently used 1231 break; 1232 } 1233 } 1234 1235 return true; 1236} 1237 1238void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) { 1239 if (mCodec->mPortEOS[kPortIndexInput]) { 1240 return; 1241 } 1242 1243 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 1244 1245 sp<AMessage> notify = mCodec->mNotify->dup(); 1246 notify->setInt32("what", ACodec::kWhatFillThisBuffer); 1247 notify->setPointer("buffer-id", info->mBufferID); 1248 1249 info->mData->meta()->clear(); 1250 notify->setObject("buffer", info->mData); 1251 1252 sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id()); 1253 reply->setPointer("buffer-id", info->mBufferID); 1254 1255 notify->setMessage("reply", reply); 1256 1257 notify->post(); 1258 1259 info->mStatus = BufferInfo::OWNED_BY_UPSTREAM; 1260} 1261 1262void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { 1263 IOMX::buffer_id bufferID; 1264 CHECK(msg->findPointer("buffer-id", &bufferID)); 1265 1266 sp<RefBase> obj; 1267 int32_t err = OK; 1268 if (!msg->findObject("buffer", &obj)) { 1269 CHECK(msg->findInt32("err", &err)); 1270 1271 LOGV("[%s] saw error %d instead of an input buffer", 1272 mCodec->mComponentName.c_str(), err); 1273 1274 obj.clear(); 1275 } 1276 1277 sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get()); 1278 1279 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID); 1280 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM); 1281 1282 info->mStatus = BufferInfo::OWNED_BY_US; 1283 1284 PortMode mode = getPortMode(kPortIndexInput); 1285 1286 switch (mode) { 1287 case KEEP_BUFFERS: 1288 { 1289 if (buffer == NULL) { 1290 mCodec->mPortEOS[kPortIndexInput] = true; 1291 } 1292 break; 1293 } 1294 1295 case RESUBMIT_BUFFERS: 1296 { 1297 if (buffer != NULL) { 1298 CHECK(!mCodec->mPortEOS[kPortIndexInput]); 1299 1300 int64_t timeUs; 1301 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 1302 1303 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME; 1304 1305 int32_t isCSD; 1306 if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) { 1307 flags |= OMX_BUFFERFLAG_CODECCONFIG; 1308 } 1309 1310 if (buffer != info->mData) { 1311 if (0 && !(flags & OMX_BUFFERFLAG_CODECCONFIG)) { 1312 LOGV("[%s] Needs to copy input data.", 1313 mCodec->mComponentName.c_str()); 1314 } 1315 1316 CHECK_LE(buffer->size(), info->mData->capacity()); 1317 memcpy(info->mData->data(), buffer->data(), buffer->size()); 1318 } 1319 1320 LOGV("[%s] calling emptyBuffer %p", 1321 mCodec->mComponentName.c_str(), bufferID); 1322 1323 CHECK_EQ(mCodec->mOMX->emptyBuffer( 1324 mCodec->mNode, 1325 bufferID, 1326 0, 1327 buffer->size(), 1328 flags, 1329 timeUs), 1330 (status_t)OK); 1331 1332 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 1333 1334 getMoreInputDataIfPossible(); 1335 } else if (!mCodec->mPortEOS[kPortIndexInput]) { 1336 LOGV("[%s] Signalling EOS on the input port", 1337 mCodec->mComponentName.c_str()); 1338 1339 LOGV("[%s] calling emptyBuffer %p", 1340 mCodec->mComponentName.c_str(), bufferID); 1341 1342 CHECK_EQ(mCodec->mOMX->emptyBuffer( 1343 mCodec->mNode, 1344 bufferID, 1345 0, 1346 0, 1347 OMX_BUFFERFLAG_EOS, 1348 0), 1349 (status_t)OK); 1350 1351 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 1352 1353 mCodec->mPortEOS[kPortIndexInput] = true; 1354 } 1355 break; 1356 1357 default: 1358 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 1359 break; 1360 } 1361 } 1362} 1363 1364void ACodec::BaseState::getMoreInputDataIfPossible() { 1365 if (mCodec->mPortEOS[kPortIndexInput]) { 1366 return; 1367 } 1368 1369 BufferInfo *eligible = NULL; 1370 1371 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 1372 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 1373 1374#if 0 1375 if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) { 1376 // There's already a "read" pending. 1377 return; 1378 } 1379#endif 1380 1381 if (info->mStatus == BufferInfo::OWNED_BY_US) { 1382 eligible = info; 1383 } 1384 } 1385 1386 if (eligible == NULL) { 1387 return; 1388 } 1389 1390 postFillThisBuffer(eligible); 1391} 1392 1393bool ACodec::BaseState::onOMXFillBufferDone( 1394 IOMX::buffer_id bufferID, 1395 size_t rangeOffset, size_t rangeLength, 1396 OMX_U32 flags, 1397 int64_t timeUs, 1398 void *platformPrivate, 1399 void *dataPtr) { 1400 LOGV("[%s] onOMXFillBufferDone %p", 1401 mCodec->mComponentName.c_str(), bufferID); 1402 1403 ssize_t index; 1404 BufferInfo *info = 1405 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 1406 1407 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); 1408 1409 info->mStatus = BufferInfo::OWNED_BY_US; 1410 1411 PortMode mode = getPortMode(kPortIndexOutput); 1412 1413 switch (mode) { 1414 case KEEP_BUFFERS: 1415 break; 1416 1417 case RESUBMIT_BUFFERS: 1418 { 1419 if (rangeLength == 0) { 1420 if (!(flags & OMX_BUFFERFLAG_EOS)) { 1421 LOGV("[%s] calling fillBuffer %p", 1422 mCodec->mComponentName.c_str(), info->mBufferID); 1423 1424 CHECK_EQ(mCodec->mOMX->fillBuffer( 1425 mCodec->mNode, info->mBufferID), 1426 (status_t)OK); 1427 1428 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 1429 } 1430 } else { 1431 if (!mCodec->mSentFormat) { 1432 mCodec->sendFormatChange(); 1433 } 1434 1435 if (mCodec->mNativeWindow == NULL) { 1436 info->mData->setRange(rangeOffset, rangeLength); 1437 } 1438 1439 info->mData->meta()->setInt64("timeUs", timeUs); 1440 1441 sp<AMessage> notify = mCodec->mNotify->dup(); 1442 notify->setInt32("what", ACodec::kWhatDrainThisBuffer); 1443 notify->setPointer("buffer-id", info->mBufferID); 1444 notify->setObject("buffer", info->mData); 1445 1446 sp<AMessage> reply = 1447 new AMessage(kWhatOutputBufferDrained, mCodec->id()); 1448 1449 reply->setPointer("buffer-id", info->mBufferID); 1450 1451 notify->setMessage("reply", reply); 1452 1453 notify->post(); 1454 1455 info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM; 1456 } 1457 1458 if (flags & OMX_BUFFERFLAG_EOS) { 1459 sp<AMessage> notify = mCodec->mNotify->dup(); 1460 notify->setInt32("what", ACodec::kWhatEOS); 1461 notify->post(); 1462 1463 mCodec->mPortEOS[kPortIndexOutput] = true; 1464 } 1465 break; 1466 } 1467 1468 default: 1469 { 1470 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 1471 1472 CHECK_EQ((status_t)OK, 1473 mCodec->freeBuffer(kPortIndexOutput, index)); 1474 break; 1475 } 1476 } 1477 1478 return true; 1479} 1480 1481void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { 1482 IOMX::buffer_id bufferID; 1483 CHECK(msg->findPointer("buffer-id", &bufferID)); 1484 1485 ssize_t index; 1486 BufferInfo *info = 1487 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 1488 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM); 1489 1490 int32_t render; 1491 if (mCodec->mNativeWindow != NULL 1492 && msg->findInt32("render", &render) && render != 0) { 1493 // The client wants this buffer to be rendered. 1494 1495 CHECK_EQ(mCodec->mNativeWindow->queueBuffer( 1496 mCodec->mNativeWindow.get(), 1497 info->mGraphicBuffer.get()), 1498 0); 1499 1500 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 1501 } else { 1502 info->mStatus = BufferInfo::OWNED_BY_US; 1503 } 1504 1505 PortMode mode = getPortMode(kPortIndexOutput); 1506 1507 switch (mode) { 1508 case KEEP_BUFFERS: 1509 { 1510 // XXX fishy, revisit!!! What about the FREE_BUFFERS case below? 1511 1512 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 1513 // We cannot resubmit the buffer we just rendered, dequeue 1514 // the spare instead. 1515 1516 info = mCodec->dequeueBufferFromNativeWindow(); 1517 } 1518 break; 1519 } 1520 1521 case RESUBMIT_BUFFERS: 1522 { 1523 if (!mCodec->mPortEOS[kPortIndexOutput]) { 1524 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 1525 // We cannot resubmit the buffer we just rendered, dequeue 1526 // the spare instead. 1527 1528 info = mCodec->dequeueBufferFromNativeWindow(); 1529 } 1530 1531 LOGV("[%s] calling fillBuffer %p", 1532 mCodec->mComponentName.c_str(), info->mBufferID); 1533 1534 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), 1535 (status_t)OK); 1536 1537 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 1538 } 1539 break; 1540 } 1541 1542 default: 1543 { 1544 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 1545 1546 CHECK_EQ((status_t)OK, 1547 mCodec->freeBuffer(kPortIndexOutput, index)); 1548 break; 1549 } 1550 } 1551} 1552 1553//////////////////////////////////////////////////////////////////////////////// 1554 1555ACodec::UninitializedState::UninitializedState(ACodec *codec) 1556 : BaseState(codec) { 1557} 1558 1559bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) { 1560 bool handled = false; 1561 1562 switch (msg->what()) { 1563 case ACodec::kWhatSetup: 1564 { 1565 onSetup(msg); 1566 1567 handled = true; 1568 break; 1569 } 1570 1571 case ACodec::kWhatShutdown: 1572 { 1573 sp<AMessage> notify = mCodec->mNotify->dup(); 1574 notify->setInt32("what", ACodec::kWhatShutdownCompleted); 1575 notify->post(); 1576 1577 handled = true; 1578 } 1579 1580 case ACodec::kWhatFlush: 1581 { 1582 sp<AMessage> notify = mCodec->mNotify->dup(); 1583 notify->setInt32("what", ACodec::kWhatFlushCompleted); 1584 notify->post(); 1585 1586 handled = true; 1587 } 1588 1589 default: 1590 return BaseState::onMessageReceived(msg); 1591 } 1592 1593 return handled; 1594} 1595 1596void ACodec::UninitializedState::onSetup( 1597 const sp<AMessage> &msg) { 1598 OMXClient client; 1599 CHECK_EQ(client.connect(), (status_t)OK); 1600 1601 sp<IOMX> omx = client.interface(); 1602 1603 AString mime; 1604 CHECK(msg->findString("mime", &mime)); 1605 1606 AString componentName; 1607 1608 if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) { 1609 componentName = "OMX.Nvidia.h264.decode"; 1610 } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) { 1611 componentName = "OMX.Nvidia.aac.decoder"; 1612 } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_MPEG)) { 1613 componentName = "OMX.Nvidia.mp3.decoder"; 1614 } else { 1615 TRESPASS(); 1616 } 1617 1618 sp<CodecObserver> observer = new CodecObserver; 1619 1620 IOMX::node_id node; 1621 CHECK_EQ(omx->allocateNode(componentName.c_str(), observer, &node), 1622 (status_t)OK); 1623 1624 sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id()); 1625 observer->setNotificationMessage(notify); 1626 1627 mCodec->mComponentName = componentName; 1628 mCodec->mOMX = omx; 1629 mCodec->mNode = node; 1630 1631 mCodec->mPortEOS[kPortIndexInput] = 1632 mCodec->mPortEOS[kPortIndexOutput] = false; 1633 1634 mCodec->configureCodec(mime.c_str(), msg); 1635 1636 sp<RefBase> obj; 1637 if (msg->findObject("native-window", &obj)) { 1638 sp<NativeWindowWrapper> nativeWindow( 1639 static_cast<NativeWindowWrapper *>(obj.get())); 1640 CHECK(nativeWindow != NULL); 1641 mCodec->mNativeWindow = nativeWindow->getNativeWindow(); 1642 } 1643 1644 CHECK_EQ((status_t)OK, mCodec->initNativeWindow()); 1645 1646 CHECK_EQ(omx->sendCommand(node, OMX_CommandStateSet, OMX_StateIdle), 1647 (status_t)OK); 1648 1649 mCodec->changeState(mCodec->mLoadedToIdleState); 1650} 1651 1652//////////////////////////////////////////////////////////////////////////////// 1653 1654ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec) 1655 : BaseState(codec) { 1656} 1657 1658void ACodec::LoadedToIdleState::stateEntered() { 1659 LOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str()); 1660 1661 CHECK_EQ(allocateBuffers(), (status_t)OK); 1662} 1663 1664status_t ACodec::LoadedToIdleState::allocateBuffers() { 1665 status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput); 1666 1667 if (err != OK) { 1668 return err; 1669 } 1670 1671 return mCodec->allocateBuffersOnPort(kPortIndexOutput); 1672} 1673 1674bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) { 1675 switch (msg->what()) { 1676 case kWhatShutdown: 1677 { 1678 mCodec->deferMessage(msg); 1679 return true; 1680 } 1681 1682 default: 1683 return BaseState::onMessageReceived(msg); 1684 } 1685} 1686 1687bool ACodec::LoadedToIdleState::onOMXEvent( 1688 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 1689 switch (event) { 1690 case OMX_EventCmdComplete: 1691 { 1692 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 1693 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); 1694 1695 CHECK_EQ(mCodec->mOMX->sendCommand( 1696 mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting), 1697 (status_t)OK); 1698 1699 mCodec->changeState(mCodec->mIdleToExecutingState); 1700 1701 return true; 1702 } 1703 1704 default: 1705 return BaseState::onOMXEvent(event, data1, data2); 1706 } 1707} 1708 1709//////////////////////////////////////////////////////////////////////////////// 1710 1711ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec) 1712 : BaseState(codec) { 1713} 1714 1715void ACodec::IdleToExecutingState::stateEntered() { 1716 LOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str()); 1717} 1718 1719bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) { 1720 switch (msg->what()) { 1721 case kWhatShutdown: 1722 { 1723 mCodec->deferMessage(msg); 1724 return true; 1725 } 1726 1727 default: 1728 return BaseState::onMessageReceived(msg); 1729 } 1730} 1731 1732bool ACodec::IdleToExecutingState::onOMXEvent( 1733 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 1734 switch (event) { 1735 case OMX_EventCmdComplete: 1736 { 1737 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 1738 CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting); 1739 1740 mCodec->mExecutingState->resume(); 1741 mCodec->changeState(mCodec->mExecutingState); 1742 1743 return true; 1744 } 1745 1746 default: 1747 return BaseState::onOMXEvent(event, data1, data2); 1748 } 1749} 1750 1751//////////////////////////////////////////////////////////////////////////////// 1752 1753ACodec::ExecutingState::ExecutingState(ACodec *codec) 1754 : BaseState(codec), 1755 mActive(false) { 1756} 1757 1758ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode( 1759 OMX_U32 portIndex) { 1760 return RESUBMIT_BUFFERS; 1761} 1762 1763void ACodec::ExecutingState::submitOutputBuffers() { 1764 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) { 1765 BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i); 1766 1767 if (mCodec->mNativeWindow != NULL) { 1768 CHECK(info->mStatus == BufferInfo::OWNED_BY_US 1769 || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW); 1770 1771 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 1772 continue; 1773 } 1774 1775 status_t err = mCodec->mNativeWindow->lockBuffer( 1776 mCodec->mNativeWindow.get(), 1777 info->mGraphicBuffer.get()); 1778 CHECK_EQ(err, (status_t)OK); 1779 } else { 1780 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 1781 } 1782 1783 LOGV("[%s] calling fillBuffer %p", 1784 mCodec->mComponentName.c_str(), info->mBufferID); 1785 1786 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), 1787 (status_t)OK); 1788 1789 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 1790 } 1791} 1792 1793void ACodec::ExecutingState::resume() { 1794 if (mActive) { 1795 LOGV("[%s] We're already active, no need to resume.", 1796 mCodec->mComponentName.c_str()); 1797 1798 return; 1799 } 1800 1801 submitOutputBuffers(); 1802 1803 // Post the first input buffer. 1804 CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u); 1805 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0); 1806 1807 postFillThisBuffer(info); 1808 1809 mActive = true; 1810} 1811 1812void ACodec::ExecutingState::stateEntered() { 1813 LOGV("[%s] Now Executing", mCodec->mComponentName.c_str()); 1814 1815 mCodec->processDeferredMessages(); 1816} 1817 1818bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) { 1819 bool handled = false; 1820 1821 switch (msg->what()) { 1822 case kWhatShutdown: 1823 { 1824 mActive = false; 1825 1826 CHECK_EQ(mCodec->mOMX->sendCommand( 1827 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle), 1828 (status_t)OK); 1829 1830 mCodec->changeState(mCodec->mExecutingToIdleState); 1831 1832 handled = true; 1833 break; 1834 } 1835 1836 case kWhatFlush: 1837 { 1838 mActive = false; 1839 1840 CHECK_EQ(mCodec->mOMX->sendCommand( 1841 mCodec->mNode, OMX_CommandFlush, OMX_ALL), 1842 (status_t)OK); 1843 1844 mCodec->changeState(mCodec->mFlushingState); 1845 1846 handled = true; 1847 break; 1848 } 1849 1850 case kWhatResume: 1851 { 1852 resume(); 1853 1854 handled = true; 1855 break; 1856 } 1857 1858 default: 1859 handled = BaseState::onMessageReceived(msg); 1860 break; 1861 } 1862 1863 return handled; 1864} 1865 1866bool ACodec::ExecutingState::onOMXEvent( 1867 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 1868 switch (event) { 1869 case OMX_EventPortSettingsChanged: 1870 { 1871 CHECK_EQ(data1, (OMX_U32)kPortIndexOutput); 1872 1873 if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) { 1874 CHECK_EQ(mCodec->mOMX->sendCommand( 1875 mCodec->mNode, 1876 OMX_CommandPortDisable, kPortIndexOutput), 1877 (status_t)OK); 1878 1879 mCodec->freeOutputBuffersNotOwnedByComponent(); 1880 1881 mCodec->changeState(mCodec->mOutputPortSettingsChangedState); 1882 } else if (data2 == OMX_IndexConfigCommonOutputCrop) { 1883 mCodec->mSentFormat = false; 1884 } else { 1885 LOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx", 1886 mCodec->mComponentName.c_str(), data2); 1887 } 1888 1889 return true; 1890 } 1891 1892 case OMX_EventBufferFlag: 1893 { 1894 return true; 1895 } 1896 1897 default: 1898 return BaseState::onOMXEvent(event, data1, data2); 1899 } 1900} 1901 1902//////////////////////////////////////////////////////////////////////////////// 1903 1904ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState( 1905 ACodec *codec) 1906 : BaseState(codec) { 1907} 1908 1909ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode( 1910 OMX_U32 portIndex) { 1911 if (portIndex == kPortIndexOutput) { 1912 return FREE_BUFFERS; 1913 } 1914 1915 CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput); 1916 1917 return RESUBMIT_BUFFERS; 1918} 1919 1920bool ACodec::OutputPortSettingsChangedState::onMessageReceived( 1921 const sp<AMessage> &msg) { 1922 bool handled = false; 1923 1924 switch (msg->what()) { 1925 case kWhatFlush: 1926 case kWhatShutdown: 1927 case kWhatResume: 1928 { 1929 if (msg->what() == kWhatResume) { 1930 LOGV("[%s] Deferring resume", mCodec->mComponentName.c_str()); 1931 } 1932 1933 mCodec->deferMessage(msg); 1934 handled = true; 1935 break; 1936 } 1937 1938 default: 1939 handled = BaseState::onMessageReceived(msg); 1940 break; 1941 } 1942 1943 return handled; 1944} 1945 1946void ACodec::OutputPortSettingsChangedState::stateEntered() { 1947 LOGV("[%s] Now handling output port settings change", 1948 mCodec->mComponentName.c_str()); 1949} 1950 1951bool ACodec::OutputPortSettingsChangedState::onOMXEvent( 1952 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 1953 switch (event) { 1954 case OMX_EventCmdComplete: 1955 { 1956 if (data1 == (OMX_U32)OMX_CommandPortDisable) { 1957 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput); 1958 1959 LOGV("[%s] Output port now disabled.", 1960 mCodec->mComponentName.c_str()); 1961 1962 CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty()); 1963 mCodec->mDealer[kPortIndexOutput].clear(); 1964 1965 CHECK_EQ(mCodec->mOMX->sendCommand( 1966 mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput), 1967 (status_t)OK); 1968 1969 CHECK_EQ(mCodec->allocateBuffersOnPort(kPortIndexOutput), 1970 (status_t)OK); 1971 1972 return true; 1973 } else if (data1 == (OMX_U32)OMX_CommandPortEnable) { 1974 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput); 1975 1976 mCodec->mSentFormat = false; 1977 1978 LOGV("[%s] Output port now reenabled.", 1979 mCodec->mComponentName.c_str()); 1980 1981 if (mCodec->mExecutingState->active()) { 1982 mCodec->mExecutingState->submitOutputBuffers(); 1983 } 1984 1985 mCodec->changeState(mCodec->mExecutingState); 1986 1987 return true; 1988 } 1989 1990 return false; 1991 } 1992 1993 default: 1994 return false; 1995 } 1996} 1997 1998//////////////////////////////////////////////////////////////////////////////// 1999 2000ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec) 2001 : BaseState(codec) { 2002} 2003 2004bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) { 2005 bool handled = false; 2006 2007 switch (msg->what()) { 2008 case kWhatFlush: 2009 { 2010 // Don't send me a flush request if you previously wanted me 2011 // to shutdown. 2012 TRESPASS(); 2013 break; 2014 } 2015 2016 case kWhatShutdown: 2017 { 2018 // We're already doing that... 2019 2020 handled = true; 2021 break; 2022 } 2023 2024 default: 2025 handled = BaseState::onMessageReceived(msg); 2026 break; 2027 } 2028 2029 return handled; 2030} 2031 2032void ACodec::ExecutingToIdleState::stateEntered() { 2033 LOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str()); 2034 2035 mCodec->mSentFormat = false; 2036} 2037 2038bool ACodec::ExecutingToIdleState::onOMXEvent( 2039 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 2040 switch (event) { 2041 case OMX_EventCmdComplete: 2042 { 2043 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 2044 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); 2045 2046 changeStateIfWeOwnAllBuffers(); 2047 2048 return true; 2049 } 2050 2051 case OMX_EventPortSettingsChanged: 2052 case OMX_EventBufferFlag: 2053 { 2054 // We're shutting down and don't care about this anymore. 2055 return true; 2056 } 2057 2058 default: 2059 return BaseState::onOMXEvent(event, data1, data2); 2060 } 2061} 2062void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() { 2063 if (mCodec->allYourBuffersAreBelongToUs()) { 2064 CHECK_EQ(mCodec->mOMX->sendCommand( 2065 mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded), 2066 (status_t)OK); 2067 2068 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK); 2069 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK); 2070 2071 mCodec->changeState(mCodec->mIdleToLoadedState); 2072 } 2073} 2074 2075void ACodec::ExecutingToIdleState::onInputBufferFilled( 2076 const sp<AMessage> &msg) { 2077 BaseState::onInputBufferFilled(msg); 2078 2079 changeStateIfWeOwnAllBuffers(); 2080} 2081 2082void ACodec::ExecutingToIdleState::onOutputBufferDrained( 2083 const sp<AMessage> &msg) { 2084 BaseState::onOutputBufferDrained(msg); 2085 2086 changeStateIfWeOwnAllBuffers(); 2087} 2088 2089//////////////////////////////////////////////////////////////////////////////// 2090 2091ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec) 2092 : BaseState(codec) { 2093} 2094 2095bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) { 2096 bool handled = false; 2097 2098 switch (msg->what()) { 2099 case kWhatShutdown: 2100 { 2101 // We're already doing that... 2102 2103 handled = true; 2104 break; 2105 } 2106 2107 case kWhatFlush: 2108 { 2109 // Don't send me a flush request if you previously wanted me 2110 // to shutdown. 2111 TRESPASS(); 2112 break; 2113 } 2114 2115 default: 2116 handled = BaseState::onMessageReceived(msg); 2117 break; 2118 } 2119 2120 return handled; 2121} 2122 2123void ACodec::IdleToLoadedState::stateEntered() { 2124 LOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str()); 2125} 2126 2127bool ACodec::IdleToLoadedState::onOMXEvent( 2128 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 2129 switch (event) { 2130 case OMX_EventCmdComplete: 2131 { 2132 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 2133 CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded); 2134 2135 LOGV("[%s] Now Loaded", mCodec->mComponentName.c_str()); 2136 2137 CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK); 2138 2139 mCodec->mNativeWindow.clear(); 2140 mCodec->mNode = NULL; 2141 mCodec->mOMX.clear(); 2142 mCodec->mComponentName.clear(); 2143 2144 mCodec->changeState(mCodec->mUninitializedState); 2145 2146 sp<AMessage> notify = mCodec->mNotify->dup(); 2147 notify->setInt32("what", ACodec::kWhatShutdownCompleted); 2148 notify->post(); 2149 2150 return true; 2151 } 2152 2153 default: 2154 return BaseState::onOMXEvent(event, data1, data2); 2155 } 2156} 2157 2158//////////////////////////////////////////////////////////////////////////////// 2159 2160ACodec::ErrorState::ErrorState(ACodec *codec) 2161 : BaseState(codec) { 2162} 2163 2164bool ACodec::ErrorState::onMessageReceived(const sp<AMessage> &msg) { 2165 return BaseState::onMessageReceived(msg); 2166} 2167 2168void ACodec::ErrorState::stateEntered() { 2169 LOGV("[%s] Now in ErrorState", mCodec->mComponentName.c_str()); 2170} 2171 2172bool ACodec::ErrorState::onOMXEvent( 2173 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 2174 LOGV("EVENT(%d, 0x%08lx, 0x%08lx)", event, data1, data2); 2175 return true; 2176} 2177 2178//////////////////////////////////////////////////////////////////////////////// 2179 2180ACodec::FlushingState::FlushingState(ACodec *codec) 2181 : BaseState(codec) { 2182} 2183 2184void ACodec::FlushingState::stateEntered() { 2185 LOGV("[%s] Now Flushing", mCodec->mComponentName.c_str()); 2186 2187 mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false; 2188} 2189 2190bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) { 2191 bool handled = false; 2192 2193 switch (msg->what()) { 2194 case kWhatShutdown: 2195 { 2196 mCodec->deferMessage(msg); 2197 break; 2198 } 2199 2200 case kWhatFlush: 2201 { 2202 // We're already doing this right now. 2203 handled = true; 2204 break; 2205 } 2206 2207 default: 2208 handled = BaseState::onMessageReceived(msg); 2209 break; 2210 } 2211 2212 return handled; 2213} 2214 2215bool ACodec::FlushingState::onOMXEvent( 2216 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 2217 switch (event) { 2218 case OMX_EventCmdComplete: 2219 { 2220 CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush); 2221 2222 if (data2 == kPortIndexInput || data2 == kPortIndexOutput) { 2223 CHECK(!mFlushComplete[data2]); 2224 mFlushComplete[data2] = true; 2225 } else { 2226 CHECK_EQ(data2, OMX_ALL); 2227 CHECK(mFlushComplete[kPortIndexInput]); 2228 CHECK(mFlushComplete[kPortIndexOutput]); 2229 2230 changeStateIfWeOwnAllBuffers(); 2231 } 2232 2233 return true; 2234 } 2235 2236 case OMX_EventPortSettingsChanged: 2237 { 2238 sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id()); 2239 msg->setInt32("type", omx_message::EVENT); 2240 msg->setPointer("node", mCodec->mNode); 2241 msg->setInt32("event", event); 2242 msg->setInt32("data1", data1); 2243 msg->setInt32("data2", data2); 2244 2245 LOGV("[%s] Deferring OMX_EventPortSettingsChanged", 2246 mCodec->mComponentName.c_str()); 2247 2248 mCodec->deferMessage(msg); 2249 2250 return true; 2251 } 2252 2253 default: 2254 return BaseState::onOMXEvent(event, data1, data2); 2255 } 2256 2257 return true; 2258} 2259 2260void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) { 2261 BaseState::onOutputBufferDrained(msg); 2262 2263 changeStateIfWeOwnAllBuffers(); 2264} 2265 2266void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) { 2267 BaseState::onInputBufferFilled(msg); 2268 2269 changeStateIfWeOwnAllBuffers(); 2270} 2271 2272void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() { 2273 if (mFlushComplete[kPortIndexInput] 2274 && mFlushComplete[kPortIndexOutput] 2275 && mCodec->allYourBuffersAreBelongToUs()) { 2276 sp<AMessage> notify = mCodec->mNotify->dup(); 2277 notify->setInt32("what", ACodec::kWhatFlushCompleted); 2278 notify->post(); 2279 2280 mCodec->mPortEOS[kPortIndexInput] = 2281 mCodec->mPortEOS[kPortIndexOutput] = false; 2282 2283 mCodec->changeState(mCodec->mExecutingState); 2284 } 2285} 2286 2287} // namespace android 2288