ACodec.cpp revision 349d3fcb4afacf754f7b5b5186d2f258f5bf35e7
1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt//#define LOG_NDEBUG 0
2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define LOG_TAG "ACodec"
3526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
4526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <media/stagefright/ACodec.h>
5526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
6526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <binder/MemoryDealer.h>
7526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
8526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <media/stagefright/foundation/hexdump.h>
9526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <media/stagefright/foundation/ABuffer.h>
10526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <media/stagefright/foundation/ADebug.h>
11526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <media/stagefright/foundation/AMessage.h>
12526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
13526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <media/stagefright/MediaDefs.h>
14526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <media/stagefright/OMXClient.h>
15526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
16526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <surfaceflinger/Surface.h>
17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
18526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <OMX_Component.h>
19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
20526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtnamespace android {
21526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
22526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidttemplate<class T>
23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void InitOMXParams(T *params) {
24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    params->nSize = sizeof(T);
25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    params->nVersion.s.nVersionMajor = 1;
26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    params->nVersion.s.nVersionMinor = 0;
27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    params->nVersion.s.nRevision = 0;
28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    params->nVersion.s.nStep = 0;
29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct CodecObserver : public BnOMXObserver {
32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    CodecObserver() {}
33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    void setNotificationMessage(const sp<AMessage> &msg) {
35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        mNotify = msg;
36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    // from IOMXObserver
39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual void onMessage(const omx_message &omx_msg) {
40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        sp<AMessage> msg = mNotify->dup();
41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        msg->setInt32("type", omx_msg.type);
43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        msg->setPointer("node", omx_msg.node);
44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        switch (omx_msg.type) {
46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            case omx_message::EVENT:
47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            {
48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                msg->setInt32("event", omx_msg.u.event_data.event);
49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                msg->setInt32("data1", omx_msg.u.event_data.data1);
50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                msg->setInt32("data2", omx_msg.u.event_data.data2);
51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                break;
52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            }
53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            case omx_message::EMPTY_BUFFER_DONE:
55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            {
56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                msg->setPointer("buffer", omx_msg.u.buffer_data.buffer);
57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                break;
58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            }
59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            case omx_message::FILL_BUFFER_DONE:
61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            {
62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                msg->setPointer(
63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                        "buffer", omx_msg.u.extended_buffer_data.buffer);
64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                msg->setInt32(
65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                        "range_offset",
66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                        omx_msg.u.extended_buffer_data.range_offset);
67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                msg->setInt32(
68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                        "range_length",
69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                        omx_msg.u.extended_buffer_data.range_length);
70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                msg->setInt32(
71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                        "flags",
72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                        omx_msg.u.extended_buffer_data.flags);
73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                msg->setInt64(
74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                        "timestamp",
75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                        omx_msg.u.extended_buffer_data.timestamp);
76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                msg->setPointer(
77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                        "platform_private",
78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                        omx_msg.u.extended_buffer_data.platform_private);
79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                msg->setPointer(
80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                        "data_ptr",
81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                        omx_msg.u.extended_buffer_data.data_ptr);
82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                break;
83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            }
84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            default:
86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                TRESPASS();
87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                break;
88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        }
89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        msg->post();
91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtprotected:
94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual ~CodecObserver() {}
95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtprivate:
97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    sp<AMessage> mNotify;
98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    DISALLOW_EVIL_CONSTRUCTORS(CodecObserver);
100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt////////////////////////////////////////////////////////////////////////////////
103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct ACodec::BaseState : public AState {
105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    BaseState(ACodec *codec, const sp<AState> &parentState = NULL);
106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtprotected:
108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    enum PortMode {
109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        KEEP_BUFFERS,
110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        RESUBMIT_BUFFERS,
111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        FREE_BUFFERS,
112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    };
113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    ACodec *mCodec;
115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual PortMode getPortMode(OMX_U32 portIndex);
117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual bool onMessageReceived(const sp<AMessage> &msg);
119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual void onInputBufferFilled(const sp<AMessage> &msg);
124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    void postFillThisBuffer(BufferInfo *info);
126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtprivate:
128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    bool onOMXMessage(const sp<AMessage> &msg);
129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID);
131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    bool onOMXFillBufferDone(
133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            IOMX::buffer_id bufferID,
134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            size_t rangeOffset, size_t rangeLength,
135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            OMX_U32 flags,
136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            int64_t timeUs,
137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            void *platformPrivate,
138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            void *dataPtr);
139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    void getMoreInputDataIfPossible();
141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    DISALLOW_EVIL_CONSTRUCTORS(BaseState);
143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt////////////////////////////////////////////////////////////////////////////////
146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct ACodec::UninitializedState : public ACodec::BaseState {
148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    UninitializedState(ACodec *codec);
149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtprotected:
151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual bool onMessageReceived(const sp<AMessage> &msg);
152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtprivate:
154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    void onSetup(const sp<AMessage> &msg);
155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    DISALLOW_EVIL_CONSTRUCTORS(UninitializedState);
157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt////////////////////////////////////////////////////////////////////////////////
160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct ACodec::LoadedToIdleState : public ACodec::BaseState {
162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    LoadedToIdleState(ACodec *codec);
163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtprotected:
165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual bool onMessageReceived(const sp<AMessage> &msg);
166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual void stateEntered();
168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtprivate:
170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    status_t allocateBuffers();
171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState);
173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt////////////////////////////////////////////////////////////////////////////////
176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct ACodec::IdleToExecutingState : public ACodec::BaseState {
178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    IdleToExecutingState(ACodec *codec);
179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtprotected:
181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual bool onMessageReceived(const sp<AMessage> &msg);
182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual void stateEntered();
184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtprivate:
186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState);
187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt////////////////////////////////////////////////////////////////////////////////
190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct ACodec::ExecutingState : public ACodec::BaseState {
192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    ExecutingState(ACodec *codec);
193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    void submitOutputBuffers();
195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    // Submit output buffers to the decoder, submit input buffers to client
197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    // to fill with data.
198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    void resume();
199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    // Returns true iff input and output buffers are in play.
201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    bool active() const { return mActive; }
202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtprotected:
204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual PortMode getPortMode(OMX_U32 portIndex);
205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual bool onMessageReceived(const sp<AMessage> &msg);
206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual void stateEntered();
207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtprivate:
211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    bool mActive;
212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    DISALLOW_EVIL_CONSTRUCTORS(ExecutingState);
214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt////////////////////////////////////////////////////////////////////////////////
217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState {
219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    OutputPortSettingsChangedState(ACodec *codec);
220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtprotected:
222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual PortMode getPortMode(OMX_U32 portIndex);
223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual bool onMessageReceived(const sp<AMessage> &msg);
224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual void stateEntered();
225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtprivate:
229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState);
230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt////////////////////////////////////////////////////////////////////////////////
233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct ACodec::ExecutingToIdleState : public ACodec::BaseState {
235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    ExecutingToIdleState(ACodec *codec);
236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtprotected:
238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual bool onMessageReceived(const sp<AMessage> &msg);
239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual void stateEntered();
240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual void onInputBufferFilled(const sp<AMessage> &msg);
245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtprivate:
247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    void changeStateIfWeOwnAllBuffers();
248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState);
250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt////////////////////////////////////////////////////////////////////////////////
253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct ACodec::IdleToLoadedState : public ACodec::BaseState {
255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    IdleToLoadedState(ACodec *codec);
256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtprotected:
258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual bool onMessageReceived(const sp<AMessage> &msg);
259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual void stateEntered();
260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtprivate:
264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState);
265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt////////////////////////////////////////////////////////////////////////////////
268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct ACodec::ErrorState : public ACodec::BaseState {
270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    ErrorState(ACodec *codec);
271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtprotected:
273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual bool onMessageReceived(const sp<AMessage> &msg);
274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual void stateEntered();
275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtprivate:
279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    DISALLOW_EVIL_CONSTRUCTORS(ErrorState);
280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt////////////////////////////////////////////////////////////////////////////////
283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct ACodec::FlushingState : public ACodec::BaseState {
285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    FlushingState(ACodec *codec);
286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtprotected:
288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual bool onMessageReceived(const sp<AMessage> &msg);
289526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual void stateEntered();
290526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
291526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
292526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
293526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
294526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    virtual void onInputBufferFilled(const sp<AMessage> &msg);
295526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtprivate:
297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    bool mFlushComplete[2];
298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    void changeStateIfWeOwnAllBuffers();
300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    DISALLOW_EVIL_CONSTRUCTORS(FlushingState);
302526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
303526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
304526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt////////////////////////////////////////////////////////////////////////////////
305526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
306526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtACodec::ACodec()
307526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    : mNode(NULL),
308526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt      mSentFormat(false) {
309526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    mUninitializedState = new UninitializedState(this);
310526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    mLoadedToIdleState = new LoadedToIdleState(this);
311526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    mIdleToExecutingState = new IdleToExecutingState(this);
312526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    mExecutingState = new ExecutingState(this);
313526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
314526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    mOutputPortSettingsChangedState =
315526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        new OutputPortSettingsChangedState(this);
316526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
317526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    mExecutingToIdleState = new ExecutingToIdleState(this);
318526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    mIdleToLoadedState = new IdleToLoadedState(this);
319526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    mErrorState = new ErrorState(this);
320526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    mFlushingState = new FlushingState(this);
321526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
322526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false;
323526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
324526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    changeState(mUninitializedState);
325526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
326526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
327526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtACodec::~ACodec() {
328526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
329526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
330526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid ACodec::setNotificationMessage(const sp<AMessage> &msg) {
331526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    mNotify = msg;
332526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
333526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
334526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid ACodec::initiateSetup(const sp<AMessage> &msg) {
335526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    msg->setWhat(kWhatSetup);
336526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    msg->setTarget(id());
337526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    msg->post();
338526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
339526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
340526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid ACodec::signalFlush() {
341526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    (new AMessage(kWhatFlush, id()))->post();
342526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
343526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
344526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid ACodec::signalResume() {
345526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    (new AMessage(kWhatResume, id()))->post();
346526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
347526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
348526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid ACodec::initiateShutdown() {
349526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    (new AMessage(kWhatShutdown, id()))->post();
350526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
351526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
352526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatus_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
353526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
354526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
355526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    CHECK(mDealer[portIndex] == NULL);
356526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    CHECK(mBuffers[portIndex].isEmpty());
357526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
358526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
359526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        return allocateOutputBuffersFromNativeWindow();
360526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
361526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
362526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    OMX_PARAM_PORTDEFINITIONTYPE def;
363526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    InitOMXParams(&def);
364526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    def.nPortIndex = portIndex;
365526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
366526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    status_t err = mOMX->getParameter(
367526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
368526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
369526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    if (err != OK) {
370526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        return err;
371526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
372526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
373526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    LOGV("[%s] Allocating %lu buffers of size %lu on %s port",
374526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            mComponentName.c_str(),
375526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            def.nBufferCountActual, def.nBufferSize,
376526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            portIndex == kPortIndexInput ? "input" : "output");
377526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
378526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    size_t totalSize = def.nBufferCountActual * def.nBufferSize;
379526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    mDealer[portIndex] = new MemoryDealer(totalSize, "OMXCodec");
380526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
381526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
382526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
383526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        CHECK(mem.get() != NULL);
384526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
385526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        IOMX::buffer_id buffer;
386526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#if 0
387526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        err = mOMX->allocateBufferWithBackup(mNode, portIndex, mem, &buffer);
388526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#else
389526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        err = mOMX->useBuffer(mNode, portIndex, mem, &buffer);
390526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif
391526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
392526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        if (err != OK) {
393526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            return err;
394526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        }
395526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
396526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        BufferInfo info;
397526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        info.mBufferID = buffer;
398526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        info.mStatus = BufferInfo::OWNED_BY_US;
399526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        info.mData = new ABuffer(mem->pointer(), def.nBufferSize);
400526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        mBuffers[portIndex].push(info);
401526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
402526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
403526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    return OK;
404526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
405526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
406526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatus_t ACodec::allocateOutputBuffersFromNativeWindow() {
407526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    OMX_PARAM_PORTDEFINITIONTYPE def;
408526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    InitOMXParams(&def);
409526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    def.nPortIndex = kPortIndexOutput;
410526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
411526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    status_t err = mOMX->getParameter(
412526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
413526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
414526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    if (err != OK) {
415526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        return err;
416526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
417526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
418526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    err = native_window_set_buffers_geometry(
419526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            mNativeWindow.get(),
420526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            def.format.video.nFrameWidth,
421526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            def.format.video.nFrameHeight,
422526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            def.format.video.eColorFormat);
423526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
424526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    if (err != 0) {
425526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        LOGE("native_window_set_buffers_geometry failed: %s (%d)",
426526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                strerror(-err), -err);
427526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        return err;
428526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
429526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
430526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    // Increase the buffer count by one to allow for the ANativeWindow to hold
431526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    // on to one of the buffers.
432526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    def.nBufferCountActual++;
433526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    err = mOMX->setParameter(
434526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
435526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
436526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    if (err != OK) {
437526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        return err;
438526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
439526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
440526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    // Set up the native window.
441526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    // XXX TODO: Get the gralloc usage flags from the OMX plugin!
442526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    err = native_window_set_usage(
443526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            mNativeWindow.get(),
444526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP);
445526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
446526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    if (err != 0) {
447526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        LOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err);
448526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        return err;
449526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
450526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
451526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    err = native_window_set_buffer_count(
452526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            mNativeWindow.get(), def.nBufferCountActual);
453526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
454526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    if (err != 0) {
455526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        LOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
456526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                -err);
457526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        return err;
458526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
459526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
460526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    // XXX TODO: Do something so the ANativeWindow knows that we'll need to get
461526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    // the same set of buffers.
462526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
463526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    LOGV("[%s] Allocating %lu buffers from a native window of size %lu on "
464526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt         "output port",
465526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt         mComponentName.c_str(), def.nBufferCountActual, def.nBufferSize);
466526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
467526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    // Dequeue buffers and send them to OMX
468526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    OMX_U32 i;
469526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    for (i = 0; i < def.nBufferCountActual; i++) {
470526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        android_native_buffer_t *buf;
471526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf);
472526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        if (err != 0) {
473526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            LOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
474526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            break;
475526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        }
476526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
477526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
478526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        IOMX::buffer_id bufferId;
479526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer,
480526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                &bufferId);
481526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        if (err != 0) {
482526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            break;
483526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        }
484526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
485526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        LOGV("[%s] Registered graphic buffer with ID %p (pointer = %p)",
486526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt             mComponentName.c_str(),
487526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt             bufferId, graphicBuffer.get());
488526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
489526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        BufferInfo info;
490526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        info.mBufferID = bufferId;
491526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        info.mStatus = BufferInfo::OWNED_BY_US;
492526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        info.mData = new ABuffer(0);
493526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        info.mGraphicBuffer = graphicBuffer;
494526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        mBuffers[kPortIndexOutput].push(info);
495526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
496526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
497526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    OMX_U32 cancelStart;
498526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    OMX_U32 cancelEnd;
499526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
500526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    if (err != 0) {
501526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        // If an error occurred while dequeuing we need to cancel any buffers
502526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        // that were dequeued.
503526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        cancelStart = 0;
504526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        cancelEnd = i;
505526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    } else {
506526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        // Return the last two buffers to the native window.
507526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        // XXX TODO: The number of buffers the native window owns should
508526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        // probably be queried from it when we put the native window in
509526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        // fixed buffer pool mode (which needs to be implemented).
510526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        // Currently it's hard-coded to 2.
511526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        cancelStart = def.nBufferCountActual - 2;
512526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        cancelEnd = def.nBufferCountActual;
513526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
514526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
515526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
516526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
517526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        cancelBufferToNativeWindow(info);
518526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
519526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
520526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    return err;
521526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
522526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
523526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatus_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) {
524526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
525526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
526526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    LOGV("[%s] Calling cancelBuffer on buffer %p",
527526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt         mComponentName.c_str(), info->mBufferID);
528526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
529526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    int err = mNativeWindow->cancelBuffer(
530526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        mNativeWindow.get(), info->mGraphicBuffer.get());
531526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
532526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    CHECK_EQ(err, 0);
533526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
534526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
535526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
536526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    return OK;
537526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
538526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
539526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
540526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    android_native_buffer_t *buf;
541526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    CHECK_EQ(mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf), 0);
542526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
543526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
544526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        BufferInfo *info =
545526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            &mBuffers[kPortIndexOutput].editItemAt(i);
546526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
547526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        if (info->mGraphicBuffer->handle == buf->handle) {
548526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            CHECK_EQ((int)info->mStatus,
549526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                     (int)BufferInfo::OWNED_BY_NATIVE_WINDOW);
550526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
551526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            info->mStatus = BufferInfo::OWNED_BY_US;
552526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
553526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            return info;
554526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        }
555526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
556526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
557526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    TRESPASS();
558526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
559526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    return NULL;
560526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
561526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
562526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatus_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) {
563526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    for (size_t i = mBuffers[portIndex].size(); i-- > 0;) {
564526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        CHECK_EQ((status_t)OK, freeBuffer(portIndex, i));
565526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
566526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
567526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    mDealer[portIndex].clear();
568526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
569526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    return OK;
570526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
571526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
572526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatus_t ACodec::freeOutputBuffersNotOwnedByComponent() {
573526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
574526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        BufferInfo *info =
575526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            &mBuffers[kPortIndexOutput].editItemAt(i);
576526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
577526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        if (info->mStatus !=
578526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                BufferInfo::OWNED_BY_COMPONENT) {
579526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            // We shouldn't have sent out any buffers to the client at this
580526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            // point.
581526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            CHECK_NE((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
582526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
583526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            CHECK_EQ((status_t)OK, freeBuffer(kPortIndexOutput, i));
584526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        }
585526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
586526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
587526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    return OK;
588526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
589526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
590526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatus_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) {
591526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
592526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
593526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    CHECK(info->mStatus == BufferInfo::OWNED_BY_US
594526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
595526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
596526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    if (portIndex == kPortIndexOutput && mNativeWindow != NULL
597526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            && info->mStatus == BufferInfo::OWNED_BY_US) {
598526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        CHECK_EQ((status_t)OK, cancelBufferToNativeWindow(info));
599526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
600526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
601526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    CHECK_EQ(mOMX->freeBuffer(
602526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                mNode, portIndex, info->mBufferID),
603526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt             (status_t)OK);
604526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
605526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    mBuffers[portIndex].removeAt(i);
606526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
607526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    return OK;
608526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
609526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
610526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtACodec::BufferInfo *ACodec::findBufferByID(
611526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        uint32_t portIndex, IOMX::buffer_id bufferID,
612526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        ssize_t *index) {
613526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
614526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
615526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
616526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        if (info->mBufferID == bufferID) {
617526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            if (index != NULL) {
618526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                *index = i;
619526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            }
620526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            return info;
621526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        }
622526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
623526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
624526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    TRESPASS();
625526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
626526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    return NULL;
627526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
628526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
629526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid ACodec::setComponentRole(
630526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        bool isEncoder, const char *mime) {
631526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    struct MimeToRole {
632526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        const char *mime;
633526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        const char *decoderRole;
634526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        const char *encoderRole;
635526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    };
636526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
637526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    static const MimeToRole kMimeToRole[] = {
638526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        { MEDIA_MIMETYPE_AUDIO_MPEG,
639526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            "audio_decoder.mp3", "audio_encoder.mp3" },
640526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        { MEDIA_MIMETYPE_AUDIO_AMR_NB,
641526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            "audio_decoder.amrnb", "audio_encoder.amrnb" },
642526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        { MEDIA_MIMETYPE_AUDIO_AMR_WB,
643526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            "audio_decoder.amrwb", "audio_encoder.amrwb" },
644526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        { MEDIA_MIMETYPE_AUDIO_AAC,
645526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            "audio_decoder.aac", "audio_encoder.aac" },
646526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        { MEDIA_MIMETYPE_VIDEO_AVC,
647526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            "video_decoder.avc", "video_encoder.avc" },
648526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        { MEDIA_MIMETYPE_VIDEO_MPEG4,
649526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            "video_decoder.mpeg4", "video_encoder.mpeg4" },
650526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        { MEDIA_MIMETYPE_VIDEO_H263,
651526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            "video_decoder.h263", "video_encoder.h263" },
652526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    };
653526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
654526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    static const size_t kNumMimeToRole =
655526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
656526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
657526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    size_t i;
658526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    for (i = 0; i < kNumMimeToRole; ++i) {
659526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        if (!strcasecmp(mime, kMimeToRole[i].mime)) {
660526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            break;
661526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        }
662526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
663526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
664526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    if (i == kNumMimeToRole) {
665526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        return;
666526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
667526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
668526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    const char *role =
669526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        isEncoder ? kMimeToRole[i].encoderRole
670526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                  : kMimeToRole[i].decoderRole;
671526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
672526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    if (role != NULL) {
673526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        OMX_PARAM_COMPONENTROLETYPE roleParams;
674526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        InitOMXParams(&roleParams);
675526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
676526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        strncpy((char *)roleParams.cRole,
677526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                role, OMX_MAX_STRINGNAME_SIZE - 1);
678526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
679526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
680526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
681526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        status_t err = mOMX->setParameter(
682526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                mNode, OMX_IndexParamStandardComponentRole,
683526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                &roleParams, sizeof(roleParams));
684526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
685526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        if (err != OK) {
686526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            LOGW("[%s] Failed to set standard component role '%s'.",
687526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                 mComponentName.c_str(), role);
688526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        }
689526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
690526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
691526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
692526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid ACodec::configureCodec(
693526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        const char *mime, const sp<AMessage> &msg) {
694526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    setComponentRole(false /* isEncoder */, mime);
695526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
696526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    if (!strncasecmp(mime, "video/", 6)) {
697526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        int32_t width, height;
698526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        CHECK(msg->findInt32("width", &width));
699526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        CHECK(msg->findInt32("height", &height));
700526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
701526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        CHECK_EQ(setupVideoDecoder(mime, width, height),
702526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                 (status_t)OK);
703526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
704526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        int32_t numChannels, sampleRate;
705526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        CHECK(msg->findInt32("channel-count", &numChannels));
706526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        CHECK(msg->findInt32("sample-rate", &sampleRate));
707526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
708526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        CHECK_EQ(setupAACDecoder(numChannels, sampleRate), (status_t)OK);
709526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
710526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    } else {
711526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        TRESPASS();
712526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
713526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
714526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    int32_t maxInputSize;
715526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    if (msg->findInt32("max-input-size", &maxInputSize)) {
716526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        CHECK_EQ(setMinBufferSize(kPortIndexInput, (size_t)maxInputSize),
717526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                 (status_t)OK);
718526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) {
719526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        CHECK_EQ(setMinBufferSize(kPortIndexInput, 8192),  // XXX
720526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                 (status_t)OK);
721526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
722526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
723526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
724526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatus_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) {
725526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    OMX_PARAM_PORTDEFINITIONTYPE def;
726526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    InitOMXParams(&def);
727526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    def.nPortIndex = portIndex;
728526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
729526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    status_t err = mOMX->getParameter(
730526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
731526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
732526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    if (err != OK) {
733526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        return err;
734526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
735526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
736526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    if (def.nBufferSize >= size) {
737526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        return OK;
738526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
739526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
740526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    def.nBufferSize = size;
741526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
742526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    err = mOMX->setParameter(
743526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
744526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
745526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    if (err != OK) {
746526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        return err;
747526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
748526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
749526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    err = mOMX->getParameter(
750526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
751526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
752526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    if (err != OK) {
753526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        return err;
754526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
755526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
756526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    CHECK(def.nBufferSize >= size);
757526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
758526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    return OK;
759526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
760526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
761526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatus_t ACodec::setupAACDecoder(int32_t numChannels, int32_t sampleRate) {
762526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    OMX_AUDIO_PARAM_AACPROFILETYPE profile;
763526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    InitOMXParams(&profile);
764526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    profile.nPortIndex = kPortIndexInput;
765526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
766526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    status_t err = mOMX->getParameter(
767526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
768526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
769526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    if (err != OK) {
770526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        return err;
771526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
772526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
773526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    profile.nChannels = numChannels;
774526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    profile.nSampleRate = sampleRate;
775526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
776526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
777526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    err = mOMX->setParameter(
778526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
779526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
780526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    return err;
781526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
782526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
783526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatus_t ACodec::setVideoPortFormatType(
784526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        OMX_U32 portIndex,
785526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        OMX_VIDEO_CODINGTYPE compressionFormat,
786526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        OMX_COLOR_FORMATTYPE colorFormat) {
787526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    OMX_VIDEO_PARAM_PORTFORMATTYPE format;
788526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    InitOMXParams(&format);
789526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    format.nPortIndex = portIndex;
790526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    format.nIndex = 0;
791526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    bool found = false;
792526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
793526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    OMX_U32 index = 0;
794526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    for (;;) {
795526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        format.nIndex = index;
796526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        status_t err = mOMX->getParameter(
797526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                mNode, OMX_IndexParamVideoPortFormat,
798526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                &format, sizeof(format));
799526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
800526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        if (err != OK) {
801526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            return err;
802526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        }
803526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
804526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        // The following assertion is violated by TI's video decoder.
805526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        // CHECK_EQ(format.nIndex, index);
806526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
807526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) {
808526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            if (portIndex == kPortIndexInput
809526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                    && colorFormat == format.eColorFormat) {
810526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                // eCompressionFormat does not seem right.
811526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                found = true;
812526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                break;
813526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            }
814526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            if (portIndex == kPortIndexOutput
815526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                    && compressionFormat == format.eCompressionFormat) {
816526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                // eColorFormat does not seem right.
817526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                found = true;
818526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                break;
819526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            }
820526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        }
821526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
822526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        if (format.eCompressionFormat == compressionFormat
823526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            && format.eColorFormat == colorFormat) {
824526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            found = true;
825526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            break;
826526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        }
827526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
828526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        ++index;
829526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
830526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
831526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    if (!found) {
832526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        return UNKNOWN_ERROR;
833526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
834526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
835526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    status_t err = mOMX->setParameter(
836526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            mNode, OMX_IndexParamVideoPortFormat,
837526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            &format, sizeof(format));
838526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
839526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    return err;
840526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
841526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
842526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatus_t ACodec::setSupportedOutputFormat() {
843526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    OMX_VIDEO_PARAM_PORTFORMATTYPE format;
844526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    InitOMXParams(&format);
845526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    format.nPortIndex = kPortIndexOutput;
846526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    format.nIndex = 0;
847526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
848526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    status_t err = mOMX->getParameter(
849526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            mNode, OMX_IndexParamVideoPortFormat,
850526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            &format, sizeof(format));
851526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    CHECK_EQ(err, (status_t)OK);
852526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused);
853526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
854526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
855526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
856526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
857526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt           || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
858526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt           || format.eColorFormat == OMX_COLOR_FormatCbYCrY
859526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt           || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
860526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
861526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    return mOMX->setParameter(
862526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            mNode, OMX_IndexParamVideoPortFormat,
863526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            &format, sizeof(format));
864526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
865526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
866526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatus_t ACodec::setupVideoDecoder(
867526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        const char *mime, int32_t width, int32_t height) {
868526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
869526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
870526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        compressionFormat = OMX_VIDEO_CodingAVC;
871526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
872526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        compressionFormat = OMX_VIDEO_CodingMPEG4;
873526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
874526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        compressionFormat = OMX_VIDEO_CodingH263;
875526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    } else {
876526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        TRESPASS();
877526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
878526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
879526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    status_t err = setVideoPortFormatType(
880526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
881526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
882526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    if (err != OK) {
883526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        return err;
884526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
885526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
886526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    err = setSupportedOutputFormat();
887526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
888526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    if (err != OK) {
889526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        return err;
890526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
891526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
892526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    err = setVideoFormatOnPort(
893526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            kPortIndexInput, width, height, compressionFormat);
894526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
895526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    if (err != OK) {
896526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        return err;
897526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
898526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
899526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    err = setVideoFormatOnPort(
900526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused);
901526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
902526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    if (err != OK) {
903526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        return err;
904526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
905526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
906526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    return OK;
907526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
908526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
909526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatus_t ACodec::setVideoFormatOnPort(
910526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        OMX_U32 portIndex,
911526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) {
912526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    OMX_PARAM_PORTDEFINITIONTYPE def;
913526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    InitOMXParams(&def);
914526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    def.nPortIndex = portIndex;
915526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
916526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
917526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
918526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    status_t err = mOMX->getParameter(
919526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
920526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
921526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    CHECK_EQ(err, (status_t)OK);
922526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
923526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    if (portIndex == kPortIndexInput) {
924526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        // XXX Need a (much) better heuristic to compute input buffer sizes.
925526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        const size_t X = 64 * 1024;
926526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        if (def.nBufferSize < X) {
927526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            def.nBufferSize = X;
928526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        }
929526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
930526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
931526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
932526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
933526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    video_def->nFrameWidth = width;
934526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    video_def->nFrameHeight = height;
935526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
936526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    if (portIndex == kPortIndexInput) {
937526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        video_def->eCompressionFormat = compressionFormat;
938526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        video_def->eColorFormat = OMX_COLOR_FormatUnused;
939526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
940526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
941526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    err = mOMX->setParameter(
942526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
943526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
944526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    return err;
945526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
946526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
947526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatus_t ACodec::initNativeWindow() {
948526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    if (mNativeWindow != NULL) {
949526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
950526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
951526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
952526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE);
953526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    return OK;
954526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
955526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
956526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtbool ACodec::allYourBuffersAreBelongToUs(
957526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        OMX_U32 portIndex) {
958526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
959526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
960526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
961526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        if (info->mStatus != BufferInfo::OWNED_BY_US
962526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
963526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            LOGV("[%s] Buffer %p on port %ld still has status %d",
964526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                    mComponentName.c_str(),
965526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                    info->mBufferID, portIndex, info->mStatus);
966526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            return false;
967526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        }
968526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
969526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
970526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    return true;
971526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
972526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
973526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtbool ACodec::allYourBuffersAreBelongToUs() {
974526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    return allYourBuffersAreBelongToUs(kPortIndexInput)
975526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        && allYourBuffersAreBelongToUs(kPortIndexOutput);
976526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
977526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
978526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid ACodec::deferMessage(const sp<AMessage> &msg) {
979526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    bool wasEmptyBefore = mDeferredQueue.empty();
980526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    mDeferredQueue.push_back(msg);
981526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
982526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
983526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid ACodec::processDeferredMessages() {
984526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    List<sp<AMessage> > queue = mDeferredQueue;
985526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    mDeferredQueue.clear();
986526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
987526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    List<sp<AMessage> >::iterator it = queue.begin();
988526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    while (it != queue.end()) {
989526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        onMessageReceived(*it++);
990526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
991526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
992526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
993526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid ACodec::sendFormatChange() {
994526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    sp<AMessage> notify = mNotify->dup();
995526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    notify->setInt32("what", kWhatOutputFormatChanged);
996526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
997526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    OMX_PARAM_PORTDEFINITIONTYPE def;
998526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    InitOMXParams(&def);
999526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    def.nPortIndex = kPortIndexOutput;
1000526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1001526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    CHECK_EQ(mOMX->getParameter(
1002526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)),
1003526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt             (status_t)OK);
1004526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1005526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    CHECK_EQ((int)def.eDir, (int)OMX_DirOutput);
1006526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1007526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    switch (def.eDomain) {
1008526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        case OMX_PortDomainVideo:
1009526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        {
1010526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
1011526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1012526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
1013526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            notify->setInt32("width", videoDef->nFrameWidth);
1014526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            notify->setInt32("height", videoDef->nFrameHeight);
1015526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1016526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            OMX_CONFIG_RECTTYPE rect;
1017526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            InitOMXParams(&rect);
1018526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            rect.nPortIndex = kPortIndexOutput;
1019526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1020526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            if (mOMX->getConfig(
1021526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                        mNode, OMX_IndexConfigCommonOutputCrop,
1022526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                        &rect, sizeof(rect)) != OK) {
1023526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                rect.nLeft = 0;
1024526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                rect.nTop = 0;
1025526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                rect.nWidth = videoDef->nFrameWidth;
1026526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                rect.nHeight = videoDef->nFrameHeight;
1027526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            }
1028526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1029526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            CHECK_GE(rect.nLeft, 0);
1030526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            CHECK_GE(rect.nTop, 0);
1031526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            CHECK_GE(rect.nWidth, 0u);
1032526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            CHECK_GE(rect.nHeight, 0u);
1033526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth);
1034526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight);
1035526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1036526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            notify->setRect(
1037526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                    "crop",
1038526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                    rect.nLeft,
1039526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                    rect.nTop,
1040526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                    rect.nLeft + rect.nWidth - 1,
1041526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                    rect.nTop + rect.nHeight - 1);
1042526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1043526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            if (mNativeWindow != NULL) {
1044526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                android_native_rect_t crop;
1045526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                crop.left = rect.nLeft;
1046526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                crop.top = rect.nTop;
1047526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                crop.right = rect.nLeft + rect.nWidth - 1;
1048526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                crop.bottom = rect.nTop + rect.nHeight - 1;
1049526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1050526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                CHECK_EQ(0, native_window_set_crop(
1051526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                            mNativeWindow.get(), &crop));
1052526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            }
1053526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            break;
1054526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        }
1055526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1056526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        case OMX_PortDomainAudio:
1057526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        {
1058526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
1059526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            CHECK_EQ((int)audioDef->eEncoding, (int)OMX_AUDIO_CodingPCM);
1060526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1061526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            OMX_AUDIO_PARAM_PCMMODETYPE params;
1062526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            InitOMXParams(&params);
1063526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            params.nPortIndex = kPortIndexOutput;
1064526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1065526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            CHECK_EQ(mOMX->getParameter(
1066526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                        mNode, OMX_IndexParamAudioPcm,
1067526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                        &params, sizeof(params)),
1068526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                     (status_t)OK);
1069526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1070526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            CHECK(params.nChannels == 1 || params.bInterleaved);
1071526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            CHECK_EQ(params.nBitPerSample, 16u);
1072526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            CHECK_EQ((int)params.eNumData, (int)OMX_NumericalDataSigned);
1073526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            CHECK_EQ((int)params.ePCMMode, (int)OMX_AUDIO_PCMModeLinear);
1074526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1075526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
1076526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            notify->setInt32("channel-count", params.nChannels);
1077526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            notify->setInt32("sample-rate", params.nSamplingRate);
1078526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            break;
1079526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        }
1080526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1081526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        default:
1082526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            TRESPASS();
1083526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
1084526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1085526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    notify->post();
1086526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1087526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    mSentFormat = true;
1088526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
1089526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1090526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt////////////////////////////////////////////////////////////////////////////////
1091526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1092526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
1093526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    : AState(parentState),
1094526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt      mCodec(codec) {
1095526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
1096526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1097526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtACodec::BaseState::PortMode ACodec::BaseState::getPortMode(OMX_U32 portIndex) {
1098526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    return KEEP_BUFFERS;
1099526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
1100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtbool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
1102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    switch (msg->what()) {
1103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        case kWhatInputBufferFilled:
1104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        {
1105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            onInputBufferFilled(msg);
1106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            break;
1107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        }
1108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        case kWhatOutputBufferDrained:
1110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        {
1111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            onOutputBufferDrained(msg);
1112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            break;
1113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        }
1114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        case ACodec::kWhatOMXMessage:
1116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        {
1117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            return onOMXMessage(msg);
1118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        }
1119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        default:
1121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            return false;
1122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
1123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    return true;
1125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
1126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtbool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
1128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    int32_t type;
1129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    CHECK(msg->findInt32("type", &type));
1130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    IOMX::node_id nodeID;
1132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    CHECK(msg->findPointer("node", &nodeID));
1133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    CHECK_EQ(nodeID, mCodec->mNode);
1134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    switch (type) {
1136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        case omx_message::EVENT:
1137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        {
1138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            int32_t event, data1, data2;
1139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            CHECK(msg->findInt32("event", &event));
1140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            CHECK(msg->findInt32("data1", &data1));
1141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            CHECK(msg->findInt32("data2", &data2));
1142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            return onOMXEvent(
1144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                    static_cast<OMX_EVENTTYPE>(event),
1145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                    static_cast<OMX_U32>(data1),
1146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                    static_cast<OMX_U32>(data2));
1147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        }
1148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        case omx_message::EMPTY_BUFFER_DONE:
1150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        {
1151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            IOMX::buffer_id bufferID;
1152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            CHECK(msg->findPointer("buffer", &bufferID));
1153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            return onOMXEmptyBufferDone(bufferID);
1155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        }
1156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        case omx_message::FILL_BUFFER_DONE:
1158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        {
1159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            IOMX::buffer_id bufferID;
1160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            CHECK(msg->findPointer("buffer", &bufferID));
1161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            int32_t rangeOffset, rangeLength, flags;
1163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            int64_t timeUs;
1164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            void *platformPrivate;
1165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            void *dataPtr;
1166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            CHECK(msg->findInt32("range_offset", &rangeOffset));
1168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            CHECK(msg->findInt32("range_length", &rangeLength));
1169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            CHECK(msg->findInt32("flags", &flags));
1170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            CHECK(msg->findInt64("timestamp", &timeUs));
1171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            CHECK(msg->findPointer("platform_private", &platformPrivate));
1172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            CHECK(msg->findPointer("data_ptr", &dataPtr));
1173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            return onOMXFillBufferDone(
1175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                    bufferID,
1176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                    (size_t)rangeOffset, (size_t)rangeLength,
1177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                    (OMX_U32)flags,
1178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                    timeUs,
1179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                    platformPrivate,
1180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt                    dataPtr);
1181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        }
1182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        default:
1184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            TRESPASS();
1185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt            break;
1186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
1187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
1188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtbool ACodec::BaseState::onOMXEvent(
1190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    if (event != OMX_EventError) {
1192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        LOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)",
1193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt             mCodec->mComponentName.c_str(), event, data1, data2);
1194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        return false;
1196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    }
1197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    LOGE("[%s] ERROR(0x%08lx, 0x%08lx)",
1199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt         mCodec->mComponentName.c_str(), data1, data2);
1200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    mCodec->changeState(mCodec->mErrorState);
1202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    return true;
1204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
1205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtbool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) {
1207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    LOGV("[%s] onOMXEmptyBufferDone %p",
1208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt         mCodec->mComponentName.c_str(), bufferID);
1209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    BufferInfo *info =
1211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt        mCodec->findBufferByID(kPortIndexInput, bufferID);
1212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
1214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    info->mStatus = BufferInfo::OWNED_BY_US;
1215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt    PortMode mode = getPortMode(kPortIndexInput);
1217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
1218    switch (mode) {
1219        case KEEP_BUFFERS:
1220            break;
1221
1222        case RESUBMIT_BUFFERS:
1223            postFillThisBuffer(info);
1224            break;
1225
1226        default:
1227        {
1228            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1229            TRESPASS();  // Not currently used
1230            break;
1231        }
1232    }
1233
1234    return true;
1235}
1236
1237void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
1238    if (mCodec->mPortEOS[kPortIndexInput]) {
1239        return;
1240    }
1241
1242    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
1243
1244    sp<AMessage> notify = mCodec->mNotify->dup();
1245    notify->setInt32("what", ACodec::kWhatFillThisBuffer);
1246    notify->setPointer("buffer-id", info->mBufferID);
1247
1248    info->mData->meta()->clear();
1249    notify->setObject("buffer", info->mData);
1250
1251    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id());
1252    reply->setPointer("buffer-id", info->mBufferID);
1253
1254    notify->setMessage("reply", reply);
1255
1256    notify->post();
1257
1258    info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
1259}
1260
1261void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
1262    IOMX::buffer_id bufferID;
1263    CHECK(msg->findPointer("buffer-id", &bufferID));
1264
1265    sp<RefBase> obj;
1266    int32_t err = OK;
1267    if (!msg->findObject("buffer", &obj)) {
1268        CHECK(msg->findInt32("err", &err));
1269
1270        LOGV("[%s] saw error %d instead of an input buffer",
1271             mCodec->mComponentName.c_str(), err);
1272
1273        obj.clear();
1274    }
1275
1276    sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get());
1277
1278    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
1279    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM);
1280
1281    info->mStatus = BufferInfo::OWNED_BY_US;
1282
1283    PortMode mode = getPortMode(kPortIndexInput);
1284
1285    switch (mode) {
1286        case KEEP_BUFFERS:
1287        {
1288            if (buffer == NULL) {
1289                mCodec->mPortEOS[kPortIndexInput] = true;
1290            }
1291            break;
1292        }
1293
1294        case RESUBMIT_BUFFERS:
1295        {
1296            if (buffer != NULL) {
1297                CHECK(!mCodec->mPortEOS[kPortIndexInput]);
1298
1299                int64_t timeUs;
1300                CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
1301
1302                OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
1303
1304                int32_t isCSD;
1305                if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
1306                    flags |= OMX_BUFFERFLAG_CODECCONFIG;
1307                }
1308
1309                if (buffer != info->mData) {
1310                    if (0 && !(flags & OMX_BUFFERFLAG_CODECCONFIG)) {
1311                        LOGV("[%s] Needs to copy input data.",
1312                             mCodec->mComponentName.c_str());
1313                    }
1314
1315                    CHECK_LE(buffer->size(), info->mData->capacity());
1316                    memcpy(info->mData->data(), buffer->data(), buffer->size());
1317                }
1318
1319                LOGV("[%s] calling emptyBuffer %p",
1320                     mCodec->mComponentName.c_str(), bufferID);
1321
1322                CHECK_EQ(mCodec->mOMX->emptyBuffer(
1323                            mCodec->mNode,
1324                            bufferID,
1325                            0,
1326                            buffer->size(),
1327                            flags,
1328                            timeUs),
1329                         (status_t)OK);
1330
1331                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1332
1333                getMoreInputDataIfPossible();
1334            } else if (!mCodec->mPortEOS[kPortIndexInput]) {
1335                LOGV("[%s] Signalling EOS on the input port",
1336                     mCodec->mComponentName.c_str());
1337
1338                LOGV("[%s] calling emptyBuffer %p",
1339                     mCodec->mComponentName.c_str(), bufferID);
1340
1341                CHECK_EQ(mCodec->mOMX->emptyBuffer(
1342                            mCodec->mNode,
1343                            bufferID,
1344                            0,
1345                            0,
1346                            OMX_BUFFERFLAG_EOS,
1347                            0),
1348                         (status_t)OK);
1349
1350                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1351
1352                mCodec->mPortEOS[kPortIndexInput] = true;
1353            }
1354            break;
1355
1356            default:
1357                CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1358                break;
1359        }
1360    }
1361}
1362
1363void ACodec::BaseState::getMoreInputDataIfPossible() {
1364    if (mCodec->mPortEOS[kPortIndexInput]) {
1365        return;
1366    }
1367
1368    BufferInfo *eligible = NULL;
1369
1370    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
1371        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
1372
1373#if 0
1374        if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
1375            // There's already a "read" pending.
1376            return;
1377        }
1378#endif
1379
1380        if (info->mStatus == BufferInfo::OWNED_BY_US) {
1381            eligible = info;
1382        }
1383    }
1384
1385    if (eligible == NULL) {
1386        return;
1387    }
1388
1389    postFillThisBuffer(eligible);
1390}
1391
1392bool ACodec::BaseState::onOMXFillBufferDone(
1393        IOMX::buffer_id bufferID,
1394        size_t rangeOffset, size_t rangeLength,
1395        OMX_U32 flags,
1396        int64_t timeUs,
1397        void *platformPrivate,
1398        void *dataPtr) {
1399    LOGV("[%s] onOMXFillBufferDone %p",
1400         mCodec->mComponentName.c_str(), bufferID);
1401
1402    ssize_t index;
1403    BufferInfo *info =
1404        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
1405
1406    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
1407
1408    info->mStatus = BufferInfo::OWNED_BY_US;
1409
1410    PortMode mode = getPortMode(kPortIndexOutput);
1411
1412    switch (mode) {
1413        case KEEP_BUFFERS:
1414            break;
1415
1416        case RESUBMIT_BUFFERS:
1417        {
1418            if (rangeLength == 0) {
1419                if (!(flags & OMX_BUFFERFLAG_EOS)) {
1420                    LOGV("[%s] calling fillBuffer %p",
1421                         mCodec->mComponentName.c_str(), info->mBufferID);
1422
1423                    CHECK_EQ(mCodec->mOMX->fillBuffer(
1424                                mCodec->mNode, info->mBufferID),
1425                             (status_t)OK);
1426
1427                    info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1428                }
1429            } else {
1430                if (!mCodec->mSentFormat) {
1431                    mCodec->sendFormatChange();
1432                }
1433
1434                if (mCodec->mNativeWindow == NULL) {
1435                    info->mData->setRange(rangeOffset, rangeLength);
1436                }
1437
1438                info->mData->meta()->setInt64("timeUs", timeUs);
1439
1440                sp<AMessage> notify = mCodec->mNotify->dup();
1441                notify->setInt32("what", ACodec::kWhatDrainThisBuffer);
1442                notify->setPointer("buffer-id", info->mBufferID);
1443                notify->setObject("buffer", info->mData);
1444
1445                sp<AMessage> reply =
1446                    new AMessage(kWhatOutputBufferDrained, mCodec->id());
1447
1448                reply->setPointer("buffer-id", info->mBufferID);
1449
1450                notify->setMessage("reply", reply);
1451
1452                notify->post();
1453
1454                info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
1455            }
1456
1457            if (flags & OMX_BUFFERFLAG_EOS) {
1458                sp<AMessage> notify = mCodec->mNotify->dup();
1459                notify->setInt32("what", ACodec::kWhatEOS);
1460                notify->post();
1461
1462                mCodec->mPortEOS[kPortIndexOutput] = true;
1463            }
1464            break;
1465        }
1466
1467        default:
1468        {
1469            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1470
1471            CHECK_EQ((status_t)OK,
1472                     mCodec->freeBuffer(kPortIndexOutput, index));
1473            break;
1474        }
1475    }
1476
1477    return true;
1478}
1479
1480void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
1481    IOMX::buffer_id bufferID;
1482    CHECK(msg->findPointer("buffer-id", &bufferID));
1483
1484    ssize_t index;
1485    BufferInfo *info =
1486        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
1487    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
1488
1489    int32_t render;
1490    if (mCodec->mNativeWindow != NULL
1491            && msg->findInt32("render", &render) && render != 0) {
1492        // The client wants this buffer to be rendered.
1493
1494        CHECK_EQ(mCodec->mNativeWindow->queueBuffer(
1495                    mCodec->mNativeWindow.get(),
1496                    info->mGraphicBuffer.get()),
1497                 0);
1498
1499        info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
1500    } else {
1501        info->mStatus = BufferInfo::OWNED_BY_US;
1502    }
1503
1504    PortMode mode = getPortMode(kPortIndexOutput);
1505
1506    switch (mode) {
1507        case KEEP_BUFFERS:
1508        {
1509            // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
1510
1511            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1512                // We cannot resubmit the buffer we just rendered, dequeue
1513                // the spare instead.
1514
1515                info = mCodec->dequeueBufferFromNativeWindow();
1516            }
1517            break;
1518        }
1519
1520        case RESUBMIT_BUFFERS:
1521        {
1522            if (!mCodec->mPortEOS[kPortIndexOutput]) {
1523                if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1524                    // We cannot resubmit the buffer we just rendered, dequeue
1525                    // the spare instead.
1526
1527                    info = mCodec->dequeueBufferFromNativeWindow();
1528                }
1529
1530                LOGV("[%s] calling fillBuffer %p",
1531                     mCodec->mComponentName.c_str(), info->mBufferID);
1532
1533                CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
1534                         (status_t)OK);
1535
1536                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1537            }
1538            break;
1539        }
1540
1541        default:
1542        {
1543            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
1544
1545            CHECK_EQ((status_t)OK,
1546                     mCodec->freeBuffer(kPortIndexOutput, index));
1547            break;
1548        }
1549    }
1550}
1551
1552////////////////////////////////////////////////////////////////////////////////
1553
1554ACodec::UninitializedState::UninitializedState(ACodec *codec)
1555    : BaseState(codec) {
1556}
1557
1558bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
1559    bool handled = false;
1560
1561    switch (msg->what()) {
1562        case ACodec::kWhatSetup:
1563        {
1564            onSetup(msg);
1565
1566            handled = true;
1567            break;
1568        }
1569
1570        case ACodec::kWhatShutdown:
1571        {
1572            sp<AMessage> notify = mCodec->mNotify->dup();
1573            notify->setInt32("what", ACodec::kWhatShutdownCompleted);
1574            notify->post();
1575
1576            handled = true;
1577        }
1578
1579        case ACodec::kWhatFlush:
1580        {
1581            sp<AMessage> notify = mCodec->mNotify->dup();
1582            notify->setInt32("what", ACodec::kWhatFlushCompleted);
1583            notify->post();
1584
1585            handled = true;
1586        }
1587
1588        default:
1589            return BaseState::onMessageReceived(msg);
1590    }
1591
1592    return handled;
1593}
1594
1595void ACodec::UninitializedState::onSetup(
1596        const sp<AMessage> &msg) {
1597    OMXClient client;
1598    CHECK_EQ(client.connect(), (status_t)OK);
1599
1600    sp<IOMX> omx = client.interface();
1601
1602    AString mime;
1603    CHECK(msg->findString("mime", &mime));
1604
1605    AString componentName;
1606
1607    if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
1608        componentName = "OMX.Nvidia.h264.decode";
1609    } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) {
1610        componentName = "OMX.Nvidia.aac.decoder";
1611    } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_MPEG)) {
1612        componentName = "OMX.Nvidia.mp3.decoder";
1613    } else {
1614        TRESPASS();
1615    }
1616
1617    sp<CodecObserver> observer = new CodecObserver;
1618
1619    IOMX::node_id node;
1620    CHECK_EQ(omx->allocateNode(componentName.c_str(), observer, &node),
1621             (status_t)OK);
1622
1623    sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id());
1624    observer->setNotificationMessage(notify);
1625
1626    mCodec->mComponentName = componentName;
1627    mCodec->mOMX = omx;
1628    mCodec->mNode = node;
1629
1630    mCodec->mPortEOS[kPortIndexInput] =
1631        mCodec->mPortEOS[kPortIndexOutput] = false;
1632
1633    mCodec->configureCodec(mime.c_str(), msg);
1634
1635    sp<RefBase> obj;
1636    if (msg->findObject("surface", &obj)) {
1637        mCodec->mNativeWindow = static_cast<Surface *>(obj.get());
1638    }
1639
1640    CHECK_EQ((status_t)OK, mCodec->initNativeWindow());
1641
1642    CHECK_EQ(omx->sendCommand(node, OMX_CommandStateSet, OMX_StateIdle),
1643             (status_t)OK);
1644
1645    mCodec->changeState(mCodec->mLoadedToIdleState);
1646}
1647
1648////////////////////////////////////////////////////////////////////////////////
1649
1650ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
1651    : BaseState(codec) {
1652}
1653
1654void ACodec::LoadedToIdleState::stateEntered() {
1655    LOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
1656
1657    CHECK_EQ(allocateBuffers(), (status_t)OK);
1658}
1659
1660status_t ACodec::LoadedToIdleState::allocateBuffers() {
1661    status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
1662
1663    if (err != OK) {
1664        return err;
1665    }
1666
1667    return mCodec->allocateBuffersOnPort(kPortIndexOutput);
1668}
1669
1670bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
1671    switch (msg->what()) {
1672        case kWhatShutdown:
1673        {
1674            mCodec->deferMessage(msg);
1675            return true;
1676        }
1677
1678        default:
1679            return BaseState::onMessageReceived(msg);
1680    }
1681}
1682
1683bool ACodec::LoadedToIdleState::onOMXEvent(
1684        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1685    switch (event) {
1686        case OMX_EventCmdComplete:
1687        {
1688            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
1689            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
1690
1691            CHECK_EQ(mCodec->mOMX->sendCommand(
1692                        mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
1693                     (status_t)OK);
1694
1695            mCodec->changeState(mCodec->mIdleToExecutingState);
1696
1697            return true;
1698        }
1699
1700        default:
1701            return BaseState::onOMXEvent(event, data1, data2);
1702    }
1703}
1704
1705////////////////////////////////////////////////////////////////////////////////
1706
1707ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
1708    : BaseState(codec) {
1709}
1710
1711void ACodec::IdleToExecutingState::stateEntered() {
1712    LOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
1713}
1714
1715bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
1716    switch (msg->what()) {
1717        case kWhatShutdown:
1718        {
1719            mCodec->deferMessage(msg);
1720            return true;
1721        }
1722
1723        default:
1724            return BaseState::onMessageReceived(msg);
1725    }
1726}
1727
1728bool ACodec::IdleToExecutingState::onOMXEvent(
1729        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1730    switch (event) {
1731        case OMX_EventCmdComplete:
1732        {
1733            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
1734            CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
1735
1736            mCodec->mExecutingState->resume();
1737            mCodec->changeState(mCodec->mExecutingState);
1738
1739            return true;
1740        }
1741
1742        default:
1743            return BaseState::onOMXEvent(event, data1, data2);
1744    }
1745}
1746
1747////////////////////////////////////////////////////////////////////////////////
1748
1749ACodec::ExecutingState::ExecutingState(ACodec *codec)
1750    : BaseState(codec),
1751      mActive(false) {
1752}
1753
1754ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
1755        OMX_U32 portIndex) {
1756    return RESUBMIT_BUFFERS;
1757}
1758
1759void ACodec::ExecutingState::submitOutputBuffers() {
1760    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
1761        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
1762
1763        if (mCodec->mNativeWindow != NULL) {
1764            CHECK(info->mStatus == BufferInfo::OWNED_BY_US
1765                    || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
1766
1767            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1768                continue;
1769            }
1770
1771            status_t err = mCodec->mNativeWindow->lockBuffer(
1772                    mCodec->mNativeWindow.get(),
1773                    info->mGraphicBuffer.get());
1774            CHECK_EQ(err, (status_t)OK);
1775        } else {
1776            CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
1777        }
1778
1779        LOGV("[%s] calling fillBuffer %p",
1780             mCodec->mComponentName.c_str(), info->mBufferID);
1781
1782        CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
1783                 (status_t)OK);
1784
1785        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1786    }
1787}
1788
1789void ACodec::ExecutingState::resume() {
1790    if (mActive) {
1791        LOGV("[%s] We're already active, no need to resume.",
1792             mCodec->mComponentName.c_str());
1793
1794        return;
1795    }
1796
1797    submitOutputBuffers();
1798
1799    // Post the first input buffer.
1800    CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
1801    BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0);
1802
1803    postFillThisBuffer(info);
1804
1805    mActive = true;
1806}
1807
1808void ACodec::ExecutingState::stateEntered() {
1809    LOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
1810
1811    mCodec->processDeferredMessages();
1812}
1813
1814bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
1815    bool handled = false;
1816
1817    switch (msg->what()) {
1818        case kWhatShutdown:
1819        {
1820            mActive = false;
1821
1822            CHECK_EQ(mCodec->mOMX->sendCommand(
1823                        mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
1824                     (status_t)OK);
1825
1826            mCodec->changeState(mCodec->mExecutingToIdleState);
1827
1828            handled = true;
1829            break;
1830        }
1831
1832        case kWhatFlush:
1833        {
1834            mActive = false;
1835
1836            CHECK_EQ(mCodec->mOMX->sendCommand(
1837                        mCodec->mNode, OMX_CommandFlush, OMX_ALL),
1838                     (status_t)OK);
1839
1840            mCodec->changeState(mCodec->mFlushingState);
1841
1842            handled = true;
1843            break;
1844        }
1845
1846        case kWhatResume:
1847        {
1848            resume();
1849
1850            handled = true;
1851            break;
1852        }
1853
1854        default:
1855            handled = BaseState::onMessageReceived(msg);
1856            break;
1857    }
1858
1859    return handled;
1860}
1861
1862bool ACodec::ExecutingState::onOMXEvent(
1863        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1864    switch (event) {
1865        case OMX_EventPortSettingsChanged:
1866        {
1867            CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
1868
1869            if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
1870                CHECK_EQ(mCodec->mOMX->sendCommand(
1871                            mCodec->mNode,
1872                            OMX_CommandPortDisable, kPortIndexOutput),
1873                         (status_t)OK);
1874
1875                mCodec->freeOutputBuffersNotOwnedByComponent();
1876
1877                mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
1878            } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
1879                mCodec->mSentFormat = false;
1880            } else {
1881                LOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
1882                     mCodec->mComponentName.c_str(), data2);
1883            }
1884
1885            return true;
1886        }
1887
1888        case OMX_EventBufferFlag:
1889        {
1890            return true;
1891        }
1892
1893        default:
1894            return BaseState::onOMXEvent(event, data1, data2);
1895    }
1896}
1897
1898////////////////////////////////////////////////////////////////////////////////
1899
1900ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
1901        ACodec *codec)
1902    : BaseState(codec) {
1903}
1904
1905ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
1906        OMX_U32 portIndex) {
1907    if (portIndex == kPortIndexOutput) {
1908        return FREE_BUFFERS;
1909    }
1910
1911    CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
1912
1913    return RESUBMIT_BUFFERS;
1914}
1915
1916bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
1917        const sp<AMessage> &msg) {
1918    bool handled = false;
1919
1920    switch (msg->what()) {
1921        case kWhatFlush:
1922        case kWhatShutdown:
1923        case kWhatResume:
1924        {
1925            if (msg->what() == kWhatResume) {
1926                LOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
1927            }
1928
1929            mCodec->deferMessage(msg);
1930            handled = true;
1931            break;
1932        }
1933
1934        default:
1935            handled = BaseState::onMessageReceived(msg);
1936            break;
1937    }
1938
1939    return handled;
1940}
1941
1942void ACodec::OutputPortSettingsChangedState::stateEntered() {
1943    LOGV("[%s] Now handling output port settings change",
1944         mCodec->mComponentName.c_str());
1945}
1946
1947bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
1948        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
1949    switch (event) {
1950        case OMX_EventCmdComplete:
1951        {
1952            if (data1 == (OMX_U32)OMX_CommandPortDisable) {
1953                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
1954
1955                LOGV("[%s] Output port now disabled.",
1956                        mCodec->mComponentName.c_str());
1957
1958                CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
1959                mCodec->mDealer[kPortIndexOutput].clear();
1960
1961                CHECK_EQ(mCodec->mOMX->sendCommand(
1962                            mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
1963                         (status_t)OK);
1964
1965                CHECK_EQ(mCodec->allocateBuffersOnPort(kPortIndexOutput),
1966                         (status_t)OK);
1967
1968                return true;
1969            } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
1970                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
1971
1972                mCodec->mSentFormat = false;
1973
1974                LOGV("[%s] Output port now reenabled.",
1975                        mCodec->mComponentName.c_str());
1976
1977                if (mCodec->mExecutingState->active()) {
1978                    mCodec->mExecutingState->submitOutputBuffers();
1979                }
1980
1981                mCodec->changeState(mCodec->mExecutingState);
1982
1983                return true;
1984            }
1985
1986            return false;
1987        }
1988
1989        default:
1990            return false;
1991    }
1992}
1993
1994////////////////////////////////////////////////////////////////////////////////
1995
1996ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
1997    : BaseState(codec) {
1998}
1999
2000bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
2001    bool handled = false;
2002
2003    switch (msg->what()) {
2004        case kWhatFlush:
2005        {
2006            // Don't send me a flush request if you previously wanted me
2007            // to shutdown.
2008            TRESPASS();
2009            break;
2010        }
2011
2012        case kWhatShutdown:
2013        {
2014            // We're already doing that...
2015
2016            handled = true;
2017            break;
2018        }
2019
2020        default:
2021            handled = BaseState::onMessageReceived(msg);
2022            break;
2023    }
2024
2025    return handled;
2026}
2027
2028void ACodec::ExecutingToIdleState::stateEntered() {
2029    LOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
2030
2031    mCodec->mSentFormat = false;
2032}
2033
2034bool ACodec::ExecutingToIdleState::onOMXEvent(
2035        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2036    switch (event) {
2037        case OMX_EventCmdComplete:
2038        {
2039            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
2040            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
2041
2042            changeStateIfWeOwnAllBuffers();
2043
2044            return true;
2045        }
2046
2047        case OMX_EventPortSettingsChanged:
2048        case OMX_EventBufferFlag:
2049        {
2050            // We're shutting down and don't care about this anymore.
2051            return true;
2052        }
2053
2054        default:
2055            return BaseState::onOMXEvent(event, data1, data2);
2056    }
2057}
2058void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
2059    if (mCodec->allYourBuffersAreBelongToUs()) {
2060        CHECK_EQ(mCodec->mOMX->sendCommand(
2061                    mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
2062                 (status_t)OK);
2063
2064        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
2065        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
2066
2067        mCodec->changeState(mCodec->mIdleToLoadedState);
2068    }
2069}
2070
2071void ACodec::ExecutingToIdleState::onInputBufferFilled(
2072        const sp<AMessage> &msg) {
2073    BaseState::onInputBufferFilled(msg);
2074
2075    changeStateIfWeOwnAllBuffers();
2076}
2077
2078void ACodec::ExecutingToIdleState::onOutputBufferDrained(
2079        const sp<AMessage> &msg) {
2080    BaseState::onOutputBufferDrained(msg);
2081
2082    changeStateIfWeOwnAllBuffers();
2083}
2084
2085////////////////////////////////////////////////////////////////////////////////
2086
2087ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
2088    : BaseState(codec) {
2089}
2090
2091bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
2092    bool handled = false;
2093
2094    switch (msg->what()) {
2095        case kWhatShutdown:
2096        {
2097            // We're already doing that...
2098
2099            handled = true;
2100            break;
2101        }
2102
2103        case kWhatFlush:
2104        {
2105            // Don't send me a flush request if you previously wanted me
2106            // to shutdown.
2107            TRESPASS();
2108            break;
2109        }
2110
2111        default:
2112            handled = BaseState::onMessageReceived(msg);
2113            break;
2114    }
2115
2116    return handled;
2117}
2118
2119void ACodec::IdleToLoadedState::stateEntered() {
2120    LOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
2121}
2122
2123bool ACodec::IdleToLoadedState::onOMXEvent(
2124        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2125    switch (event) {
2126        case OMX_EventCmdComplete:
2127        {
2128            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
2129            CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
2130
2131            LOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
2132
2133            CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
2134
2135            mCodec->mNativeWindow.clear();
2136            mCodec->mNode = NULL;
2137            mCodec->mOMX.clear();
2138            mCodec->mComponentName.clear();
2139
2140            mCodec->changeState(mCodec->mUninitializedState);
2141
2142            sp<AMessage> notify = mCodec->mNotify->dup();
2143            notify->setInt32("what", ACodec::kWhatShutdownCompleted);
2144            notify->post();
2145
2146            return true;
2147        }
2148
2149        default:
2150            return BaseState::onOMXEvent(event, data1, data2);
2151    }
2152}
2153
2154////////////////////////////////////////////////////////////////////////////////
2155
2156ACodec::ErrorState::ErrorState(ACodec *codec)
2157    : BaseState(codec) {
2158}
2159
2160bool ACodec::ErrorState::onMessageReceived(const sp<AMessage> &msg) {
2161    return BaseState::onMessageReceived(msg);
2162}
2163
2164void ACodec::ErrorState::stateEntered() {
2165    LOGV("[%s] Now in ErrorState", mCodec->mComponentName.c_str());
2166}
2167
2168bool ACodec::ErrorState::onOMXEvent(
2169        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2170    LOGV("EVENT(%d, 0x%08lx, 0x%08lx)", event, data1, data2);
2171    return true;
2172}
2173
2174////////////////////////////////////////////////////////////////////////////////
2175
2176ACodec::FlushingState::FlushingState(ACodec *codec)
2177    : BaseState(codec) {
2178}
2179
2180void ACodec::FlushingState::stateEntered() {
2181    LOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
2182
2183    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
2184}
2185
2186bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
2187    bool handled = false;
2188
2189    switch (msg->what()) {
2190        case kWhatShutdown:
2191        {
2192            mCodec->deferMessage(msg);
2193            break;
2194        }
2195
2196        case kWhatFlush:
2197        {
2198            // We're already doing this right now.
2199            handled = true;
2200            break;
2201        }
2202
2203        default:
2204            handled = BaseState::onMessageReceived(msg);
2205            break;
2206    }
2207
2208    return handled;
2209}
2210
2211bool ACodec::FlushingState::onOMXEvent(
2212        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2213    switch (event) {
2214        case OMX_EventCmdComplete:
2215        {
2216            CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
2217
2218            if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
2219                CHECK(!mFlushComplete[data2]);
2220                mFlushComplete[data2] = true;
2221            } else {
2222                CHECK_EQ(data2, OMX_ALL);
2223                CHECK(mFlushComplete[kPortIndexInput]);
2224                CHECK(mFlushComplete[kPortIndexOutput]);
2225
2226                changeStateIfWeOwnAllBuffers();
2227            }
2228
2229            return true;
2230        }
2231
2232        case OMX_EventPortSettingsChanged:
2233        {
2234            sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id());
2235            msg->setInt32("type", omx_message::EVENT);
2236            msg->setPointer("node", mCodec->mNode);
2237            msg->setInt32("event", event);
2238            msg->setInt32("data1", data1);
2239            msg->setInt32("data2", data2);
2240
2241            LOGV("[%s] Deferring OMX_EventPortSettingsChanged",
2242                 mCodec->mComponentName.c_str());
2243
2244            mCodec->deferMessage(msg);
2245
2246            return true;
2247        }
2248
2249        default:
2250            return BaseState::onOMXEvent(event, data1, data2);
2251    }
2252
2253    return true;
2254}
2255
2256void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
2257    BaseState::onOutputBufferDrained(msg);
2258
2259    changeStateIfWeOwnAllBuffers();
2260}
2261
2262void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
2263    BaseState::onInputBufferFilled(msg);
2264
2265    changeStateIfWeOwnAllBuffers();
2266}
2267
2268void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
2269    if (mFlushComplete[kPortIndexInput]
2270            && mFlushComplete[kPortIndexOutput]
2271            && mCodec->allYourBuffersAreBelongToUs()) {
2272        sp<AMessage> notify = mCodec->mNotify->dup();
2273        notify->setInt32("what", ACodec::kWhatFlushCompleted);
2274        notify->post();
2275
2276        mCodec->mPortEOS[kPortIndexInput] =
2277            mCodec->mPortEOS[kPortIndexOutput] = false;
2278
2279        mCodec->changeState(mCodec->mExecutingState);
2280    }
2281}
2282
2283}  // namespace android
2284
2285