ACodec.cpp revision 94705aff3c9eef58cbb72ec6fe5d2dcfd9481646
1e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy/*
2e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * Copyright (C) 2010 The Android Open Source Project
3e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy *
4e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * Licensed under the Apache License, Version 2.0 (the "License");
5e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * you may not use this file except in compliance with the License.
6e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * You may obtain a copy of the License at
7e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy *
8e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy *      http://www.apache.org/licenses/LICENSE-2.0
9e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy *
10e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * Unless required by applicable law or agreed to in writing, software
11e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * distributed under the License is distributed on an "AS IS" BASIS,
12e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * See the License for the specific language governing permissions and
14e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * limitations under the License.
15e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy */
16e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
1785bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy//#define LOG_NDEBUG 0
18e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy#define LOG_TAG "ACodec"
19e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
20e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy#include <media/stagefright/ACodec.h>
21e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
22e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy#include <binder/MemoryDealer.h>
23bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
245cbbce535744b89df5ecea95de21ee3733298260Romain Guy#include <media/stagefright/foundation/hexdump.h>
255cbbce535744b89df5ecea95de21ee3733298260Romain Guy#include <media/stagefright/foundation/ABuffer.h>
2685bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy#include <media/stagefright/foundation/ADebug.h>
2785bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy#include <media/stagefright/foundation/AMessage.h>
28e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
29e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy#include <media/stagefright/BufferProducerWrapper.h>
309d5316e3f56d138504565ff311145ac01621dff4Romain Guy#include <media/stagefright/MediaCodecList.h>
319d5316e3f56d138504565ff311145ac01621dff4Romain Guy#include <media/stagefright/MediaDefs.h>
329d5316e3f56d138504565ff311145ac01621dff4Romain Guy#include <media/stagefright/NativeWindowWrapper.h>
339d5316e3f56d138504565ff311145ac01621dff4Romain Guy#include <media/stagefright/OMXClient.h>
349d5316e3f56d138504565ff311145ac01621dff4Romain Guy#include <media/stagefright/OMXCodec.h>
359d5316e3f56d138504565ff311145ac01621dff4Romain Guy
36ce0537b80087a6225273040a987414b1dd081aa0Romain Guy#include <media/hardware/HardwareAPI.h>
37ce0537b80087a6225273040a987414b1dd081aa0Romain Guy
38bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy#include <OMX_Component.h>
39bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
409d5316e3f56d138504565ff311145ac01621dff4Romain Guy#include "include/avc_utils.h"
419d5316e3f56d138504565ff311145ac01621dff4Romain Guy
429d5316e3f56d138504565ff311145ac01621dff4Romain Guynamespace android {
439d5316e3f56d138504565ff311145ac01621dff4Romain Guy
449d5316e3f56d138504565ff311145ac01621dff4Romain Guytemplate<class T>
45026c5e16704e817cac7d9c382914c947e34f87e0Romain Guystatic void InitOMXParams(T *params) {
46bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    params->nSize = sizeof(T);
47bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    params->nVersion.s.nVersionMajor = 1;
48bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    params->nVersion.s.nVersionMinor = 0;
49bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    params->nVersion.s.nRevision = 0;
509d5316e3f56d138504565ff311145ac01621dff4Romain Guy    params->nVersion.s.nStep = 0;
51026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy}
52026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy
539d5316e3f56d138504565ff311145ac01621dff4Romain Guystruct CodecObserver : public BnOMXObserver {
54026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy    CodecObserver() {}
55026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy
56026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy    void setNotificationMessage(const sp<AMessage> &msg) {
57c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy        mNotify = msg;
58c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy    }
59c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy
60c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy    // from IOMXObserver
61bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    virtual void onMessage(const omx_message &omx_msg) {
62026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy        sp<AMessage> msg = mNotify->dup();
63026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy
64026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy        msg->setInt32("type", omx_msg.type);
65026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy        msg->setPointer("node", omx_msg.node);
66026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy
67026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy        switch (omx_msg.type) {
68026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy            case omx_message::EVENT:
69026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy            {
70026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy                msg->setInt32("event", omx_msg.u.event_data.event);
71026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy                msg->setInt32("data1", omx_msg.u.event_data.data1);
72026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy                msg->setInt32("data2", omx_msg.u.event_data.data2);
73026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy                break;
74026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy            }
75026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy
76026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy            case omx_message::EMPTY_BUFFER_DONE:
77026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy            {
78026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy                msg->setPointer("buffer", omx_msg.u.buffer_data.buffer);
79026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy                break;
80026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy            }
81e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
82f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy            case omx_message::FILL_BUFFER_DONE:
83f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy            {
84f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy                msg->setPointer(
85f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy                        "buffer", omx_msg.u.extended_buffer_data.buffer);
86ce0537b80087a6225273040a987414b1dd081aa0Romain Guy                msg->setInt32(
8785bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy                        "range_offset",
889d5316e3f56d138504565ff311145ac01621dff4Romain Guy                        omx_msg.u.extended_buffer_data.range_offset);
899d5316e3f56d138504565ff311145ac01621dff4Romain Guy                msg->setInt32(
90bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy                        "range_length",
91026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy                        omx_msg.u.extended_buffer_data.range_length);
92026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy                msg->setInt32(
93e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy                        "flags",
94e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy                        omx_msg.u.extended_buffer_data.flags);
9585bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy                msg->setInt64(
9685bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy                        "timestamp",
97ce0537b80087a6225273040a987414b1dd081aa0Romain Guy                        omx_msg.u.extended_buffer_data.timestamp);
98ce0537b80087a6225273040a987414b1dd081aa0Romain Guy                msg->setPointer(
99e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy                        "platform_private",
100e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy                        omx_msg.u.extended_buffer_data.platform_private);
101f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy                msg->setPointer(
102f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy                        "data_ptr",
103f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy                        omx_msg.u.extended_buffer_data.data_ptr);
104f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy                break;
10585bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy            }
10608ae317c21ec3086b5017672bba87420cc38a407Romain Guy
10708ae317c21ec3086b5017672bba87420cc38a407Romain Guy            default:
10808ae317c21ec3086b5017672bba87420cc38a407Romain Guy                TRESPASS();
109c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy                break;
11008ae317c21ec3086b5017672bba87420cc38a407Romain Guy        }
111bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
112bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        msg->post();
113bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    }
114f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy
115e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guyprotected:
116e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    virtual ~CodecObserver() {}
11785bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy
1187ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guyprivate:
1197ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    sp<AMessage> mNotify;
120f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
12108ae317c21ec3086b5017672bba87420cc38a407Romain Guy    DISALLOW_EVIL_CONSTRUCTORS(CodecObserver);
122bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy};
12308ae317c21ec3086b5017672bba87420cc38a407Romain Guy
12408ae317c21ec3086b5017672bba87420cc38a407Romain Guy////////////////////////////////////////////////////////////////////////////////
125bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
12608ae317c21ec3086b5017672bba87420cc38a407Romain Guystruct ACodec::BaseState : public AState {
127c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    BaseState(ACodec *codec, const sp<AState> &parentState = NULL);
128f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
129bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guyprotected:
130bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    enum PortMode {
131bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        KEEP_BUFFERS,
132f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy        RESUBMIT_BUFFERS,
133f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy        FREE_BUFFERS,
134f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy    };
135f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
136bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    ACodec *mCodec;
1377ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
138bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    virtual PortMode getPortMode(OMX_U32 portIndex);
139bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
140bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    virtual bool onMessageReceived(const sp<AMessage> &msg);
1417ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
142bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
143bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
144bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
1457ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    virtual void onInputBufferFilled(const sp<AMessage> &msg);
146bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
1477ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    void postFillThisBuffer(BufferInfo *info);
1487ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
1497ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guyprivate:
150bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    bool onOMXMessage(const sp<AMessage> &msg);
151bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
152bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID);
1537ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
154bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    bool onOMXFillBufferDone(
1557ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy            IOMX::buffer_id bufferID,
156bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy            size_t rangeOffset, size_t rangeLength,
1577ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy            OMX_U32 flags,
1587ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy            int64_t timeUs,
1597ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy            void *platformPrivate,
160bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy            void *dataPtr);
1617ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
1627ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    void getMoreInputDataIfPossible();
1637ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
164bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    DISALLOW_EVIL_CONSTRUCTORS(BaseState);
165bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy};
166bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
1677ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy////////////////////////////////////////////////////////////////////////////////
1687ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
169bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guystruct ACodec::DeathNotifier : public IBinder::DeathRecipient {
170bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    DeathNotifier(const sp<AMessage> &notify)
171bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        : mNotify(notify) {
1727ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    }
173bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
174f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy    virtual void binderDied(const wp<IBinder> &) {
175bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        mNotify->post();
176bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    }
1777ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
178bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guyprotected:
179f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy    virtual ~DeathNotifier() {}
180f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy
181f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guyprivate:
182f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy    sp<AMessage> mNotify;
183bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
184d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    DISALLOW_EVIL_CONSTRUCTORS(DeathNotifier);
185d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy};
186bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
187d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guystruct ACodec::UninitializedState : public ACodec::BaseState {
188d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    UninitializedState(ACodec *codec);
1895cbbce535744b89df5ecea95de21ee3733298260Romain Guy
190d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guyprotected:
191d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    virtual bool onMessageReceived(const sp<AMessage> &msg);
1925cbbce535744b89df5ecea95de21ee3733298260Romain Guy    virtual void stateEntered();
193d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy
194d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guyprivate:
195d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    void onSetup(const sp<AMessage> &msg);
196d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    bool onAllocateComponent(const sp<AMessage> &msg);
1975cbbce535744b89df5ecea95de21ee3733298260Romain Guy
198d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    sp<DeathNotifier> mDeathNotifier;
199d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy
200d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    DISALLOW_EVIL_CONSTRUCTORS(UninitializedState);
201bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy};
202d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy
203d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy////////////////////////////////////////////////////////////////////////////////
204d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy
205d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guystruct ACodec::LoadedState : public ACodec::BaseState {
206bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    LoadedState(ACodec *codec);
207d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy
208c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guyprotected:
209bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    virtual bool onMessageReceived(const sp<AMessage> &msg);
210f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy    virtual void stateEntered();
211d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy
212d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guyprivate:
213bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    friend struct ACodec::UninitializedState;
214bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
215f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy    bool onConfigureComponent(const sp<AMessage> &msg);
216bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    void onCreateInputSurface(const sp<AMessage> &msg);
217bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    void onStart();
218bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    void onShutdown(bool keepComponentAllocated);
219bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
220bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    DISALLOW_EVIL_CONSTRUCTORS(LoadedState);
221d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy};
222d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy
223d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy////////////////////////////////////////////////////////////////////////////////
224d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy
225d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guystruct ACodec::LoadedToIdleState : public ACodec::BaseState {
226d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    LoadedToIdleState(ACodec *codec);
227d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy
228d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guyprotected:
229d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    virtual bool onMessageReceived(const sp<AMessage> &msg);
230d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
231d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    virtual void stateEntered();
232d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy
233d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guyprivate:
234d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    status_t allocateBuffers();
235d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy
236d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState);
237d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy};
238d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy
239d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy////////////////////////////////////////////////////////////////////////////////
240bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
241bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guystruct ACodec::IdleToExecutingState : public ACodec::BaseState {
242bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    IdleToExecutingState(ACodec *codec);
243bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
244bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guyprotected:
245d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    virtual bool onMessageReceived(const sp<AMessage> &msg);
246d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
247d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    virtual void stateEntered();
248bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
249d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guyprivate:
250d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState);
251bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy};
252d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy
253d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy////////////////////////////////////////////////////////////////////////////////
254bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
255bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guystruct ACodec::ExecutingState : public ACodec::BaseState {
256d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    ExecutingState(ACodec *codec);
257d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy
258bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    void submitOutputBuffers();
259bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
260bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    // Submit output buffers to the decoder, submit input buffers to client
261bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    // to fill with data.
2628ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy    void resume();
2635cbbce535744b89df5ecea95de21ee3733298260Romain Guy
2645cbbce535744b89df5ecea95de21ee3733298260Romain Guy    // Returns true iff input and output buffers are in play.
265bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    bool active() const { return mActive; }
2668ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy
267f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guyprotected:
268bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    virtual PortMode getPortMode(OMX_U32 portIndex);
269f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy    virtual bool onMessageReceived(const sp<AMessage> &msg);
270f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy    virtual void stateEntered();
271bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
272bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
273bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
274bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guyprivate:
275bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    bool mActive;
276bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
277bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    DISALLOW_EVIL_CONSTRUCTORS(ExecutingState);
278d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy};
279bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
280bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy////////////////////////////////////////////////////////////////////////////////
281bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
282f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guystruct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState {
283bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    OutputPortSettingsChangedState(ACodec *codec);
284d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy
285d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guyprotected:
286d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    virtual PortMode getPortMode(OMX_U32 portIndex);
287d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    virtual bool onMessageReceived(const sp<AMessage> &msg);
288bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    virtual void stateEntered();
289bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
290f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
291f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy
292f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guyprivate:
293f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy    DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState);
294f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy};
295f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy
296d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy////////////////////////////////////////////////////////////////////////////////
297d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy
298d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guystruct ACodec::ExecutingToIdleState : public ACodec::BaseState {
299d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    ExecutingToIdleState(ACodec *codec);
300d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy
301f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guyprotected:
302f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy    virtual bool onMessageReceived(const sp<AMessage> &msg);
303f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy    virtual void stateEntered();
304f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy
305f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
306f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy
307f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
308f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy    virtual void onInputBufferFilled(const sp<AMessage> &msg);
309f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy
310f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guyprivate:
311f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy    void changeStateIfWeOwnAllBuffers();
312f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy
313f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy    bool mComponentNowIdle;
314f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy
315f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy    DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState);
316f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy};
317f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy
318d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy////////////////////////////////////////////////////////////////////////////////
319bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
320bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guystruct ACodec::IdleToLoadedState : public ACodec::BaseState {
321bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    IdleToLoadedState(ACodec *codec);
322f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
323f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyprotected:
324f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy    virtual bool onMessageReceived(const sp<AMessage> &msg);
325f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy    virtual void stateEntered();
3267ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
3277ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
328f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
329f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyprivate:
330f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy    DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState);
3317ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy};
3327ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
333f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy////////////////////////////////////////////////////////////////////////////////
334f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
335f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guystruct ACodec::FlushingState : public ACodec::BaseState {
3367ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    FlushingState(ACodec *codec);
3377ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
338f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyprotected:
339f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy    virtual bool onMessageReceived(const sp<AMessage> &msg);
340f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy    virtual void stateEntered();
3417ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
3427ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
343f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
344f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
345f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy    virtual void onInputBufferFilled(const sp<AMessage> &msg);
3467ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
347f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyprivate:
348f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy    bool mFlushComplete[2];
349f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
3507ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    void changeStateIfWeOwnAllBuffers();
3517ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
3527ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    DISALLOW_EVIL_CONSTRUCTORS(FlushingState);
353f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy};
354f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
355f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy////////////////////////////////////////////////////////////////////////////////
356f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
357f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain GuyACodec::ACodec()
358f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy    : mQuirks(0),
359bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy      mNode(NULL),
3607ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy      mSentFormat(false),
361f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy      mIsEncoder(false),
3629d5316e3f56d138504565ff311145ac01621dff4Romain Guy      mUseMetadataOnEncoderOutput(false),
3639d5316e3f56d138504565ff311145ac01621dff4Romain Guy      mShutdownInProgress(false),
3649d5316e3f56d138504565ff311145ac01621dff4Romain Guy      mEncoderDelay(0),
3657ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy      mEncoderPadding(0),
366bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy      mChannelMaskPresent(false),
367bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy      mChannelMask(0) {
368c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    mUninitializedState = new UninitializedState(this);
369c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    mLoadedState = new LoadedState(this);
370c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    mLoadedToIdleState = new LoadedToIdleState(this);
371c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    mIdleToExecutingState = new IdleToExecutingState(this);
372c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    mExecutingState = new ExecutingState(this);
373c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy
374c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    mOutputPortSettingsChangedState =
375c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy        new OutputPortSettingsChangedState(this);
376c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy
377c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    mExecutingToIdleState = new ExecutingToIdleState(this);
378c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    mIdleToLoadedState = new IdleToLoadedState(this);
379c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    mFlushingState = new FlushingState(this);
380c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy
381c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false;
382c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    mInputEOSResult = OK;
383c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy
384c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    changeState(mUninitializedState);
385bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy}
3867ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
3877ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain GuyACodec::~ACodec() {
3887ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy}
3897ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
3907ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guyvoid ACodec::setNotificationMessage(const sp<AMessage> &msg) {
3917ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    mNotify = msg;
392e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy}
393e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
394f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyvoid ACodec::initiateSetup(const sp<AMessage> &msg) {
395f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy    msg->setWhat(kWhatSetup);
396f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy    msg->setTarget(id());
397f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy    msg->post();
398c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy}
399f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy
400c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guyvoid ACodec::signalSetParameters(const sp<AMessage> &params) {
4018ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy    sp<AMessage> msg = new AMessage(kWhatSetParameters, id());
402c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy    msg->setMessage("params", params);
4038ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy    msg->post();
4048ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy}
4058ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy
4068ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guyvoid ACodec::initiateAllocateComponent(const sp<AMessage> &msg) {
4078ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy    msg->setWhat(kWhatAllocateComponent);
4088ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy    msg->setTarget(id());
409f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy    msg->post();
410f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy}
411f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy
412f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guyvoid ACodec::initiateConfigureComponent(const sp<AMessage> &msg) {
413f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy    msg->setWhat(kWhatConfigureComponent);
414f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy    msg->setTarget(id());
415f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy    msg->post();
416f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy}
417f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy
418f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guyvoid ACodec::initiateCreateInputSurface() {
419f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy    (new AMessage(kWhatCreateInputSurface, id()))->post();
420f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy}
421f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy
422f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guyvoid ACodec::signalEndOfInputStream() {
423f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy    (new AMessage(kWhatSignalEndOfInputStream, id()))->post();
4248ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy}
4258ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy
4268ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guyvoid ACodec::initiateStart() {
427f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy    (new AMessage(kWhatStart, id()))->post();
428f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy}
4298ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy
430c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guyvoid ACodec::signalFlush() {
4318ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy    ALOGV("[%s] signalFlush", mComponentName.c_str());
4328ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy    (new AMessage(kWhatFlush, id()))->post();
433c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy}
4348ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy
4358ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guyvoid ACodec::signalResume() {
436c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy    (new AMessage(kWhatResume, id()))->post();
4378ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy}
4388ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy
4398ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guyvoid ACodec::initiateShutdown(bool keepComponentAllocated) {
4408ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy    sp<AMessage> msg = new AMessage(kWhatShutdown, id());
441c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy    msg->setInt32("keepComponentAllocated", keepComponentAllocated);
4428ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy    msg->post();
4438ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy}
4448ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy
445c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guyvoid ACodec::signalRequestIDRFrame() {
4468ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy    (new AMessage(kWhatRequestIDRFrame, id()))->post();
4478ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy}
448ce0537b80087a6225273040a987414b1dd081aa0Romain Guy
449ce0537b80087a6225273040a987414b1dd081aa0Romain Guystatus_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
45085bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
451c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy
452026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy    CHECK(mDealer[portIndex] == NULL);
453c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy    CHECK(mBuffers[portIndex].isEmpty());
4549d5316e3f56d138504565ff311145ac01621dff4Romain Guy
455bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    status_t err;
456026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy    if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
457026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy        err = allocateOutputBuffersFromNativeWindow();
458026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy    } else {
459026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy        OMX_PARAM_PORTDEFINITIONTYPE def;
460026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy        InitOMXParams(&def);
461026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy        def.nPortIndex = portIndex;
462026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy
463026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy        err = mOMX->getParameter(
464026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
465026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy
466026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy        if (err == OK) {
467026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy            ALOGV("[%s] Allocating %lu buffers of size %lu on %s port",
468026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy                    mComponentName.c_str(),
469026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy                    def.nBufferCountActual, def.nBufferSize,
470026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy                    portIndex == kPortIndexInput ? "input" : "output");
471026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy
472c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy            size_t totalSize = def.nBufferCountActual * def.nBufferSize;
4739d5316e3f56d138504565ff311145ac01621dff4Romain Guy            mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec");
474026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy
475026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy            for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
476026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy                sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
477026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy                CHECK(mem.get() != NULL);
478026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy
479026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy                BufferInfo info;
480026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy                info.mStatus = BufferInfo::OWNED_BY_US;
481026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy
482026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy                uint32_t requiresAllocateBufferBit =
483026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy                    (portIndex == kPortIndexInput)
484026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy                        ? OMXCodec::kRequiresAllocateBufferOnInputPorts
485026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy                        : OMXCodec::kRequiresAllocateBufferOnOutputPorts;
486026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy
487026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy                if ((portIndex == kPortIndexInput && (mFlags & kFlagIsSecure))
4889d5316e3f56d138504565ff311145ac01621dff4Romain Guy                        || mUseMetadataOnEncoderOutput) {
489c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy                    mem.clear();
490c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy
4919d5316e3f56d138504565ff311145ac01621dff4Romain Guy                    void *ptr;
492c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy                    err = mOMX->allocateBuffer(
4939d5316e3f56d138504565ff311145ac01621dff4Romain Guy                            mNode, portIndex, def.nBufferSize, &info.mBufferID,
494c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy                            &ptr);
4959d5316e3f56d138504565ff311145ac01621dff4Romain Guy
496c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy                    int32_t bufSize = mUseMetadataOnEncoderOutput ?
497c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy                            (4 + sizeof(buffer_handle_t)) : def.nBufferSize;
498c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy
499c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy                    info.mData = new ABuffer(ptr, bufSize);
5009d5316e3f56d138504565ff311145ac01621dff4Romain Guy                } else if (mQuirks & requiresAllocateBufferBit) {
501c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy                    err = mOMX->allocateBufferWithBackup(
5029d5316e3f56d138504565ff311145ac01621dff4Romain Guy                            mNode, portIndex, mem, &info.mBufferID);
503c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy                } else {
504026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy                    err = mOMX->useBuffer(mNode, portIndex, mem, &info.mBufferID);
505026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy                }
506026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy
507026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy                if (mem != NULL) {
50885bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy                    info.mData = new ABuffer(mem->pointer(), def.nBufferSize);
50985bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy                }
510bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
511c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy                mBuffers[portIndex].push(info);
512bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy            }
513bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        }
514bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    }
515bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
516bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    if (err != OK) {
517c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy        return err;
518c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy    }
519c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy
520c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy    sp<AMessage> notify = mNotify->dup();
521c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy    notify->setInt32("what", ACodec::kWhatBuffersAllocated);
522d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy
523c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy    notify->setInt32("portIndex", portIndex);
524c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy
525c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy    sp<PortDescription> desc = new PortDescription;
526bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
527bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
528bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        const BufferInfo &info = mBuffers[portIndex][i];
529c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy
530c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy        desc->addBuffer(info.mBufferID, info.mData);
531bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    }
532bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
533bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    notify->setObject("portDesc", desc);
534026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy    notify->post();
535026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy
536bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    return OK;
537bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy}
538bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
539bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guystatus_t ACodec::allocateOutputBuffersFromNativeWindow() {
540bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    OMX_PARAM_PORTDEFINITIONTYPE def;
541bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    InitOMXParams(&def);
542bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    def.nPortIndex = kPortIndexOutput;
543bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
544bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    status_t err = mOMX->getParameter(
545bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
546bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
547bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    if (err != OK) {
548bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        return err;
549bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    }
550bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
551bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    err = native_window_set_buffers_geometry(
552bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy            mNativeWindow.get(),
553bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy            def.format.video.nFrameWidth,
554bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy            def.format.video.nFrameHeight,
555bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy            def.format.video.eColorFormat);
556026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy
557026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy    if (err != 0) {
5588ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy        ALOGE("native_window_set_buffers_geometry failed: %s (%d)",
559026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy                strerror(-err), -err);
5608ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy        return err;
561026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy    }
5628ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy
563026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy    // Set up the native window.
5648ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy    OMX_U32 usage = 0;
5658ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy    err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage);
5668ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy    if (err != 0) {
5678ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy        ALOGW("querying usage flags from OMX IL component failed: %d", err);
5688ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy        // XXX: Currently this error is logged, but not fatal.
5698ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy        usage = 0;
5708ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy    }
5718ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy
5728ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy    if (mFlags & kFlagIsSecure) {
5738ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy        usage |= GRALLOC_USAGE_PROTECTED;
5748ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy    }
5758ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy
5768ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy    // Make sure to check whether either Stagefright or the video decoder
5778ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy    // requested protected buffers.
5788ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy    if (usage & GRALLOC_USAGE_PROTECTED) {
5798ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy        // Verify that the ANativeWindow sends images directly to
5808ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy        // SurfaceFlinger.
5818ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy        int queuesToNativeWindow = 0;
5828ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy        err = mNativeWindow->query(
5838ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy                mNativeWindow.get(), NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER,
5848ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy                &queuesToNativeWindow);
5858ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy        if (err != 0) {
586026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy            ALOGE("error authenticating native window: %d", err);
587026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy            return err;
5889d5316e3f56d138504565ff311145ac01621dff4Romain Guy        }
589e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        if (queuesToNativeWindow != 1) {
590            ALOGE("native window could not be authenticated");
591            return PERMISSION_DENIED;
592        }
593    }
594
595    err = native_window_set_usage(
596            mNativeWindow.get(),
597            usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP);
598
599    if (err != 0) {
600        ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err);
601        return err;
602    }
603
604    int minUndequeuedBufs = 0;
605    err = mNativeWindow->query(
606            mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
607            &minUndequeuedBufs);
608
609    if (err != 0) {
610        ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
611                strerror(-err), -err);
612        return err;
613    }
614
615    // XXX: Is this the right logic to use?  It's not clear to me what the OMX
616    // buffer counts refer to - how do they account for the renderer holding on
617    // to buffers?
618    if (def.nBufferCountActual < def.nBufferCountMin + minUndequeuedBufs) {
619        OMX_U32 newBufferCount = def.nBufferCountMin + minUndequeuedBufs;
620        def.nBufferCountActual = newBufferCount;
621        err = mOMX->setParameter(
622                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
623
624        if (err != OK) {
625            ALOGE("[%s] setting nBufferCountActual to %lu failed: %d",
626                    mComponentName.c_str(), newBufferCount, err);
627            return err;
628        }
629    }
630
631    err = native_window_set_buffer_count(
632            mNativeWindow.get(), def.nBufferCountActual);
633
634    if (err != 0) {
635        ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
636                -err);
637        return err;
638    }
639
640    ALOGV("[%s] Allocating %lu buffers from a native window of size %lu on "
641         "output port",
642         mComponentName.c_str(), def.nBufferCountActual, def.nBufferSize);
643
644    // Dequeue buffers and send them to OMX
645    for (OMX_U32 i = 0; i < def.nBufferCountActual; i++) {
646        ANativeWindowBuffer *buf;
647        err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf);
648        if (err != 0) {
649            ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
650            break;
651        }
652
653        sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
654        BufferInfo info;
655        info.mStatus = BufferInfo::OWNED_BY_US;
656        info.mData = new ABuffer(NULL /* data */, def.nBufferSize /* capacity */);
657        info.mGraphicBuffer = graphicBuffer;
658        mBuffers[kPortIndexOutput].push(info);
659
660        IOMX::buffer_id bufferId;
661        err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer,
662                &bufferId);
663        if (err != 0) {
664            ALOGE("registering GraphicBuffer %lu with OMX IL component failed: "
665                 "%d", i, err);
666            break;
667        }
668
669        mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId;
670
671        ALOGV("[%s] Registered graphic buffer with ID %p (pointer = %p)",
672             mComponentName.c_str(),
673             bufferId, graphicBuffer.get());
674    }
675
676    OMX_U32 cancelStart;
677    OMX_U32 cancelEnd;
678
679    if (err != 0) {
680        // If an error occurred while dequeuing we need to cancel any buffers
681        // that were dequeued.
682        cancelStart = 0;
683        cancelEnd = mBuffers[kPortIndexOutput].size();
684    } else {
685        // Return the last two buffers to the native window.
686        cancelStart = def.nBufferCountActual - minUndequeuedBufs;
687        cancelEnd = def.nBufferCountActual;
688    }
689
690    for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
691        BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
692        cancelBufferToNativeWindow(info);
693    }
694
695    return err;
696}
697
698status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) {
699    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
700
701    ALOGV("[%s] Calling cancelBuffer on buffer %p",
702         mComponentName.c_str(), info->mBufferID);
703
704    int err = mNativeWindow->cancelBuffer(
705        mNativeWindow.get(), info->mGraphicBuffer.get(), -1);
706
707    CHECK_EQ(err, 0);
708
709    info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
710
711    return OK;
712}
713
714ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
715    ANativeWindowBuffer *buf;
716    int fenceFd = -1;
717    if (native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf) != 0) {
718        ALOGE("dequeueBuffer failed.");
719        return NULL;
720    }
721
722    for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
723        BufferInfo *info =
724            &mBuffers[kPortIndexOutput].editItemAt(i);
725
726        if (info->mGraphicBuffer->handle == buf->handle) {
727            CHECK_EQ((int)info->mStatus,
728                     (int)BufferInfo::OWNED_BY_NATIVE_WINDOW);
729
730            info->mStatus = BufferInfo::OWNED_BY_US;
731
732            return info;
733        }
734    }
735
736    TRESPASS();
737
738    return NULL;
739}
740
741status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) {
742    for (size_t i = mBuffers[portIndex].size(); i-- > 0;) {
743        CHECK_EQ((status_t)OK, freeBuffer(portIndex, i));
744    }
745
746    mDealer[portIndex].clear();
747
748    return OK;
749}
750
751status_t ACodec::freeOutputBuffersNotOwnedByComponent() {
752    for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
753        BufferInfo *info =
754            &mBuffers[kPortIndexOutput].editItemAt(i);
755
756        // At this time some buffers may still be with the component
757        // or being drained.
758        if (info->mStatus != BufferInfo::OWNED_BY_COMPONENT &&
759            info->mStatus != BufferInfo::OWNED_BY_DOWNSTREAM) {
760            CHECK_EQ((status_t)OK, freeBuffer(kPortIndexOutput, i));
761        }
762    }
763
764    return OK;
765}
766
767status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) {
768    BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
769
770    CHECK(info->mStatus == BufferInfo::OWNED_BY_US
771            || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
772
773    if (portIndex == kPortIndexOutput && mNativeWindow != NULL
774            && info->mStatus == BufferInfo::OWNED_BY_US) {
775        CHECK_EQ((status_t)OK, cancelBufferToNativeWindow(info));
776    }
777
778    CHECK_EQ(mOMX->freeBuffer(
779                mNode, portIndex, info->mBufferID),
780             (status_t)OK);
781
782    mBuffers[portIndex].removeAt(i);
783
784    return OK;
785}
786
787ACodec::BufferInfo *ACodec::findBufferByID(
788        uint32_t portIndex, IOMX::buffer_id bufferID,
789        ssize_t *index) {
790    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
791        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
792
793        if (info->mBufferID == bufferID) {
794            if (index != NULL) {
795                *index = i;
796            }
797            return info;
798        }
799    }
800
801    TRESPASS();
802
803    return NULL;
804}
805
806status_t ACodec::setComponentRole(
807        bool isEncoder, const char *mime) {
808    struct MimeToRole {
809        const char *mime;
810        const char *decoderRole;
811        const char *encoderRole;
812    };
813
814    static const MimeToRole kMimeToRole[] = {
815        { MEDIA_MIMETYPE_AUDIO_MPEG,
816            "audio_decoder.mp3", "audio_encoder.mp3" },
817        { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I,
818            "audio_decoder.mp1", "audio_encoder.mp1" },
819        { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II,
820            "audio_decoder.mp2", "audio_encoder.mp2" },
821        { MEDIA_MIMETYPE_AUDIO_AMR_NB,
822            "audio_decoder.amrnb", "audio_encoder.amrnb" },
823        { MEDIA_MIMETYPE_AUDIO_AMR_WB,
824            "audio_decoder.amrwb", "audio_encoder.amrwb" },
825        { MEDIA_MIMETYPE_AUDIO_AAC,
826            "audio_decoder.aac", "audio_encoder.aac" },
827        { MEDIA_MIMETYPE_AUDIO_VORBIS,
828            "audio_decoder.vorbis", "audio_encoder.vorbis" },
829        { MEDIA_MIMETYPE_AUDIO_G711_MLAW,
830            "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" },
831        { MEDIA_MIMETYPE_AUDIO_G711_ALAW,
832            "audio_decoder.g711alaw", "audio_encoder.g711alaw" },
833        { MEDIA_MIMETYPE_VIDEO_AVC,
834            "video_decoder.avc", "video_encoder.avc" },
835        { MEDIA_MIMETYPE_VIDEO_MPEG4,
836            "video_decoder.mpeg4", "video_encoder.mpeg4" },
837        { MEDIA_MIMETYPE_VIDEO_H263,
838            "video_decoder.h263", "video_encoder.h263" },
839        { MEDIA_MIMETYPE_VIDEO_VP8,
840            "video_decoder.vp8", "video_encoder.vp8" },
841        { MEDIA_MIMETYPE_VIDEO_VP9,
842            "video_decoder.vp9", "video_encoder.vp9" },
843        { MEDIA_MIMETYPE_AUDIO_RAW,
844            "audio_decoder.raw", "audio_encoder.raw" },
845        { MEDIA_MIMETYPE_AUDIO_FLAC,
846            "audio_decoder.flac", "audio_encoder.flac" },
847        { MEDIA_MIMETYPE_AUDIO_MSGSM,
848            "audio_decoder.gsm", "audio_encoder.gsm" },
849    };
850
851    static const size_t kNumMimeToRole =
852        sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
853
854    size_t i;
855    for (i = 0; i < kNumMimeToRole; ++i) {
856        if (!strcasecmp(mime, kMimeToRole[i].mime)) {
857            break;
858        }
859    }
860
861    if (i == kNumMimeToRole) {
862        return ERROR_UNSUPPORTED;
863    }
864
865    const char *role =
866        isEncoder ? kMimeToRole[i].encoderRole
867                  : kMimeToRole[i].decoderRole;
868
869    if (role != NULL) {
870        OMX_PARAM_COMPONENTROLETYPE roleParams;
871        InitOMXParams(&roleParams);
872
873        strncpy((char *)roleParams.cRole,
874                role, OMX_MAX_STRINGNAME_SIZE - 1);
875
876        roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
877
878        status_t err = mOMX->setParameter(
879                mNode, OMX_IndexParamStandardComponentRole,
880                &roleParams, sizeof(roleParams));
881
882        if (err != OK) {
883            ALOGW("[%s] Failed to set standard component role '%s'.",
884                 mComponentName.c_str(), role);
885
886            return err;
887        }
888    }
889
890    return OK;
891}
892
893status_t ACodec::configureCodec(
894        const char *mime, const sp<AMessage> &msg) {
895    int32_t encoder;
896    if (!msg->findInt32("encoder", &encoder)) {
897        encoder = false;
898    }
899
900    mIsEncoder = encoder;
901
902    status_t err = setComponentRole(encoder /* isEncoder */, mime);
903
904    if (err != OK) {
905        return err;
906    }
907
908    int32_t bitRate = 0;
909    // FLAC encoder doesn't need a bitrate, other encoders do
910    if (encoder && strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)
911            && !msg->findInt32("bitrate", &bitRate)) {
912        return INVALID_OPERATION;
913    }
914
915    int32_t storeMeta;
916    if (encoder
917            && msg->findInt32("store-metadata-in-buffers", &storeMeta)
918            && storeMeta != 0) {
919        err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexInput, OMX_TRUE);
920
921        if (err != OK) {
922              ALOGE("[%s] storeMetaDataInBuffers (input) failed w/ err %d",
923                    mComponentName.c_str(), err);
924
925              return err;
926          }
927      }
928
929    int32_t prependSPSPPS = 0;
930    if (encoder
931            && msg->findInt32("prepend-sps-pps-to-idr-frames", &prependSPSPPS)
932            && prependSPSPPS != 0) {
933        OMX_INDEXTYPE index;
934        err = mOMX->getExtensionIndex(
935                mNode,
936                "OMX.google.android.index.prependSPSPPSToIDRFrames",
937                &index);
938
939        if (err == OK) {
940            PrependSPSPPSToIDRFramesParams params;
941            InitOMXParams(&params);
942            params.bEnable = OMX_TRUE;
943
944            err = mOMX->setParameter(
945                    mNode, index, &params, sizeof(params));
946        }
947
948        if (err != OK) {
949            ALOGE("Encoder could not be configured to emit SPS/PPS before "
950                  "IDR frames. (err %d)", err);
951
952            return err;
953        }
954    }
955
956    // Only enable metadata mode on encoder output if encoder can prepend
957    // sps/pps to idr frames, since in metadata mode the bitstream is in an
958    // opaque handle, to which we don't have access.
959    int32_t video = !strncasecmp(mime, "video/", 6);
960    if (encoder && video) {
961        OMX_BOOL enable = (OMX_BOOL) (prependSPSPPS
962            && msg->findInt32("store-metadata-in-buffers-output", &storeMeta)
963            && storeMeta != 0);
964
965        err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, enable);
966
967        if (err != OK) {
968            ALOGE("[%s] storeMetaDataInBuffers (output) failed w/ err %d",
969                mComponentName.c_str(), err);
970            mUseMetadataOnEncoderOutput = 0;
971        } else {
972            mUseMetadataOnEncoderOutput = enable;
973        }
974    }
975
976    if (video) {
977        if (encoder) {
978            err = setupVideoEncoder(mime, msg);
979        } else {
980            int32_t width, height;
981            if (!msg->findInt32("width", &width)
982                    || !msg->findInt32("height", &height)) {
983                err = INVALID_OPERATION;
984            } else {
985                err = setupVideoDecoder(mime, width, height);
986            }
987        }
988    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
989        int32_t numChannels, sampleRate;
990        if (!msg->findInt32("channel-count", &numChannels)
991                || !msg->findInt32("sample-rate", &sampleRate)) {
992            // Since we did not always check for these, leave them optional
993            // and have the decoder figure it all out.
994            err = OK;
995        } else {
996            err = setupRawAudioFormat(
997                    encoder ? kPortIndexInput : kPortIndexOutput,
998                    sampleRate,
999                    numChannels);
1000        }
1001    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
1002        int32_t numChannels, sampleRate;
1003        if (!msg->findInt32("channel-count", &numChannels)
1004                || !msg->findInt32("sample-rate", &sampleRate)) {
1005            err = INVALID_OPERATION;
1006        } else {
1007            int32_t isADTS, aacProfile;
1008            if (!msg->findInt32("is-adts", &isADTS)) {
1009                isADTS = 0;
1010            }
1011            if (!msg->findInt32("aac-profile", &aacProfile)) {
1012                aacProfile = OMX_AUDIO_AACObjectNull;
1013            }
1014
1015            err = setupAACCodec(
1016                    encoder, numChannels, sampleRate, bitRate, aacProfile,
1017                    isADTS != 0);
1018        }
1019    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
1020        err = setupAMRCodec(encoder, false /* isWAMR */, bitRate);
1021    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
1022        err = setupAMRCodec(encoder, true /* isWAMR */, bitRate);
1023    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW)
1024            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) {
1025        // These are PCM-like formats with a fixed sample rate but
1026        // a variable number of channels.
1027
1028        int32_t numChannels;
1029        if (!msg->findInt32("channel-count", &numChannels)) {
1030            err = INVALID_OPERATION;
1031        } else {
1032            err = setupG711Codec(encoder, numChannels);
1033        }
1034    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) {
1035        int32_t numChannels, sampleRate, compressionLevel = -1;
1036        if (encoder &&
1037                (!msg->findInt32("channel-count", &numChannels)
1038                        || !msg->findInt32("sample-rate", &sampleRate))) {
1039            ALOGE("missing channel count or sample rate for FLAC encoder");
1040            err = INVALID_OPERATION;
1041        } else {
1042            if (encoder) {
1043                if (!msg->findInt32(
1044                            "flac-compression-level", &compressionLevel)) {
1045                    compressionLevel = 5;// default FLAC compression level
1046                } else if (compressionLevel < 0) {
1047                    ALOGW("compression level %d outside [0..8] range, "
1048                          "using 0",
1049                          compressionLevel);
1050                    compressionLevel = 0;
1051                } else if (compressionLevel > 8) {
1052                    ALOGW("compression level %d outside [0..8] range, "
1053                          "using 8",
1054                          compressionLevel);
1055                    compressionLevel = 8;
1056                }
1057            }
1058            err = setupFlacCodec(
1059                    encoder, numChannels, sampleRate, compressionLevel);
1060        }
1061    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
1062        int32_t numChannels, sampleRate;
1063        if (encoder
1064                || !msg->findInt32("channel-count", &numChannels)
1065                || !msg->findInt32("sample-rate", &sampleRate)) {
1066            err = INVALID_OPERATION;
1067        } else {
1068            err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
1069        }
1070    }
1071
1072    if (err != OK) {
1073        return err;
1074    }
1075
1076    if (!msg->findInt32("encoder-delay", &mEncoderDelay)) {
1077        mEncoderDelay = 0;
1078    }
1079
1080    if (!msg->findInt32("encoder-padding", &mEncoderPadding)) {
1081        mEncoderPadding = 0;
1082    }
1083
1084    if (msg->findInt32("channel-mask", &mChannelMask)) {
1085        mChannelMaskPresent = true;
1086    } else {
1087        mChannelMaskPresent = false;
1088    }
1089
1090    int32_t maxInputSize;
1091    if (msg->findInt32("max-input-size", &maxInputSize)) {
1092        err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize);
1093    } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) {
1094        err = setMinBufferSize(kPortIndexInput, 8192);  // XXX
1095    }
1096
1097    return err;
1098}
1099
1100status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) {
1101    OMX_PARAM_PORTDEFINITIONTYPE def;
1102    InitOMXParams(&def);
1103    def.nPortIndex = portIndex;
1104
1105    status_t err = mOMX->getParameter(
1106            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1107
1108    if (err != OK) {
1109        return err;
1110    }
1111
1112    if (def.nBufferSize >= size) {
1113        return OK;
1114    }
1115
1116    def.nBufferSize = size;
1117
1118    err = mOMX->setParameter(
1119            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1120
1121    if (err != OK) {
1122        return err;
1123    }
1124
1125    err = mOMX->getParameter(
1126            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1127
1128    if (err != OK) {
1129        return err;
1130    }
1131
1132    CHECK(def.nBufferSize >= size);
1133
1134    return OK;
1135}
1136
1137status_t ACodec::selectAudioPortFormat(
1138        OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) {
1139    OMX_AUDIO_PARAM_PORTFORMATTYPE format;
1140    InitOMXParams(&format);
1141
1142    format.nPortIndex = portIndex;
1143    for (OMX_U32 index = 0;; ++index) {
1144        format.nIndex = index;
1145
1146        status_t err = mOMX->getParameter(
1147                mNode, OMX_IndexParamAudioPortFormat,
1148                &format, sizeof(format));
1149
1150        if (err != OK) {
1151            return err;
1152        }
1153
1154        if (format.eEncoding == desiredFormat) {
1155            break;
1156        }
1157    }
1158
1159    return mOMX->setParameter(
1160            mNode, OMX_IndexParamAudioPortFormat, &format, sizeof(format));
1161}
1162
1163status_t ACodec::setupAACCodec(
1164        bool encoder, int32_t numChannels, int32_t sampleRate,
1165        int32_t bitRate, int32_t aacProfile, bool isADTS) {
1166    if (encoder && isADTS) {
1167        return -EINVAL;
1168    }
1169
1170    status_t err = setupRawAudioFormat(
1171            encoder ? kPortIndexInput : kPortIndexOutput,
1172            sampleRate,
1173            numChannels);
1174
1175    if (err != OK) {
1176        return err;
1177    }
1178
1179    if (encoder) {
1180        err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC);
1181
1182        if (err != OK) {
1183            return err;
1184        }
1185
1186        OMX_PARAM_PORTDEFINITIONTYPE def;
1187        InitOMXParams(&def);
1188        def.nPortIndex = kPortIndexOutput;
1189
1190        err = mOMX->getParameter(
1191                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1192
1193        if (err != OK) {
1194            return err;
1195        }
1196
1197        def.format.audio.bFlagErrorConcealment = OMX_TRUE;
1198        def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
1199
1200        err = mOMX->setParameter(
1201                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1202
1203        if (err != OK) {
1204            return err;
1205        }
1206
1207        OMX_AUDIO_PARAM_AACPROFILETYPE profile;
1208        InitOMXParams(&profile);
1209        profile.nPortIndex = kPortIndexOutput;
1210
1211        err = mOMX->getParameter(
1212                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1213
1214        if (err != OK) {
1215            return err;
1216        }
1217
1218        profile.nChannels = numChannels;
1219
1220        profile.eChannelMode =
1221            (numChannels == 1)
1222                ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo;
1223
1224        profile.nSampleRate = sampleRate;
1225        profile.nBitRate = bitRate;
1226        profile.nAudioBandWidth = 0;
1227        profile.nFrameLength = 0;
1228        profile.nAACtools = OMX_AUDIO_AACToolAll;
1229        profile.nAACERtools = OMX_AUDIO_AACERNone;
1230        profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile;
1231        profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
1232
1233        err = mOMX->setParameter(
1234                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1235
1236        if (err != OK) {
1237            return err;
1238        }
1239
1240        return err;
1241    }
1242
1243    OMX_AUDIO_PARAM_AACPROFILETYPE profile;
1244    InitOMXParams(&profile);
1245    profile.nPortIndex = kPortIndexInput;
1246
1247    err = mOMX->getParameter(
1248            mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1249
1250    if (err != OK) {
1251        return err;
1252    }
1253
1254    profile.nChannels = numChannels;
1255    profile.nSampleRate = sampleRate;
1256
1257    profile.eAACStreamFormat =
1258        isADTS
1259            ? OMX_AUDIO_AACStreamFormatMP4ADTS
1260            : OMX_AUDIO_AACStreamFormatMP4FF;
1261
1262    return mOMX->setParameter(
1263            mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1264}
1265
1266static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(
1267        bool isAMRWB, int32_t bps) {
1268    if (isAMRWB) {
1269        if (bps <= 6600) {
1270            return OMX_AUDIO_AMRBandModeWB0;
1271        } else if (bps <= 8850) {
1272            return OMX_AUDIO_AMRBandModeWB1;
1273        } else if (bps <= 12650) {
1274            return OMX_AUDIO_AMRBandModeWB2;
1275        } else if (bps <= 14250) {
1276            return OMX_AUDIO_AMRBandModeWB3;
1277        } else if (bps <= 15850) {
1278            return OMX_AUDIO_AMRBandModeWB4;
1279        } else if (bps <= 18250) {
1280            return OMX_AUDIO_AMRBandModeWB5;
1281        } else if (bps <= 19850) {
1282            return OMX_AUDIO_AMRBandModeWB6;
1283        } else if (bps <= 23050) {
1284            return OMX_AUDIO_AMRBandModeWB7;
1285        }
1286
1287        // 23850 bps
1288        return OMX_AUDIO_AMRBandModeWB8;
1289    } else {  // AMRNB
1290        if (bps <= 4750) {
1291            return OMX_AUDIO_AMRBandModeNB0;
1292        } else if (bps <= 5150) {
1293            return OMX_AUDIO_AMRBandModeNB1;
1294        } else if (bps <= 5900) {
1295            return OMX_AUDIO_AMRBandModeNB2;
1296        } else if (bps <= 6700) {
1297            return OMX_AUDIO_AMRBandModeNB3;
1298        } else if (bps <= 7400) {
1299            return OMX_AUDIO_AMRBandModeNB4;
1300        } else if (bps <= 7950) {
1301            return OMX_AUDIO_AMRBandModeNB5;
1302        } else if (bps <= 10200) {
1303            return OMX_AUDIO_AMRBandModeNB6;
1304        }
1305
1306        // 12200 bps
1307        return OMX_AUDIO_AMRBandModeNB7;
1308    }
1309}
1310
1311status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) {
1312    OMX_AUDIO_PARAM_AMRTYPE def;
1313    InitOMXParams(&def);
1314    def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput;
1315
1316    status_t err =
1317        mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1318
1319    if (err != OK) {
1320        return err;
1321    }
1322
1323    def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
1324    def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate);
1325
1326    err = mOMX->setParameter(
1327            mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1328
1329    if (err != OK) {
1330        return err;
1331    }
1332
1333    return setupRawAudioFormat(
1334            encoder ? kPortIndexInput : kPortIndexOutput,
1335            isWAMR ? 16000 : 8000 /* sampleRate */,
1336            1 /* numChannels */);
1337}
1338
1339status_t ACodec::setupG711Codec(bool encoder, int32_t numChannels) {
1340    CHECK(!encoder);  // XXX TODO
1341
1342    return setupRawAudioFormat(
1343            kPortIndexInput, 8000 /* sampleRate */, numChannels);
1344}
1345
1346status_t ACodec::setupFlacCodec(
1347        bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel) {
1348
1349    if (encoder) {
1350        OMX_AUDIO_PARAM_FLACTYPE def;
1351        InitOMXParams(&def);
1352        def.nPortIndex = kPortIndexOutput;
1353
1354        // configure compression level
1355        status_t err = mOMX->getParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def));
1356        if (err != OK) {
1357            ALOGE("setupFlacCodec(): Error %d getting OMX_IndexParamAudioFlac parameter", err);
1358            return err;
1359        }
1360        def.nCompressionLevel = compressionLevel;
1361        err = mOMX->setParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def));
1362        if (err != OK) {
1363            ALOGE("setupFlacCodec(): Error %d setting OMX_IndexParamAudioFlac parameter", err);
1364            return err;
1365        }
1366    }
1367
1368    return setupRawAudioFormat(
1369            encoder ? kPortIndexInput : kPortIndexOutput,
1370            sampleRate,
1371            numChannels);
1372}
1373
1374status_t ACodec::setupRawAudioFormat(
1375        OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
1376    OMX_PARAM_PORTDEFINITIONTYPE def;
1377    InitOMXParams(&def);
1378    def.nPortIndex = portIndex;
1379
1380    status_t err = mOMX->getParameter(
1381            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1382
1383    if (err != OK) {
1384        return err;
1385    }
1386
1387    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
1388
1389    err = mOMX->setParameter(
1390            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1391
1392    if (err != OK) {
1393        return err;
1394    }
1395
1396    OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
1397    InitOMXParams(&pcmParams);
1398    pcmParams.nPortIndex = portIndex;
1399
1400    err = mOMX->getParameter(
1401            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
1402
1403    if (err != OK) {
1404        return err;
1405    }
1406
1407    pcmParams.nChannels = numChannels;
1408    pcmParams.eNumData = OMX_NumericalDataSigned;
1409    pcmParams.bInterleaved = OMX_TRUE;
1410    pcmParams.nBitPerSample = 16;
1411    pcmParams.nSamplingRate = sampleRate;
1412    pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
1413
1414    if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) {
1415        return OMX_ErrorNone;
1416    }
1417
1418    return mOMX->setParameter(
1419            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
1420}
1421
1422status_t ACodec::setVideoPortFormatType(
1423        OMX_U32 portIndex,
1424        OMX_VIDEO_CODINGTYPE compressionFormat,
1425        OMX_COLOR_FORMATTYPE colorFormat) {
1426    OMX_VIDEO_PARAM_PORTFORMATTYPE format;
1427    InitOMXParams(&format);
1428    format.nPortIndex = portIndex;
1429    format.nIndex = 0;
1430    bool found = false;
1431
1432    OMX_U32 index = 0;
1433    for (;;) {
1434        format.nIndex = index;
1435        status_t err = mOMX->getParameter(
1436                mNode, OMX_IndexParamVideoPortFormat,
1437                &format, sizeof(format));
1438
1439        if (err != OK) {
1440            return err;
1441        }
1442
1443        // The following assertion is violated by TI's video decoder.
1444        // CHECK_EQ(format.nIndex, index);
1445
1446        if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) {
1447            if (portIndex == kPortIndexInput
1448                    && colorFormat == format.eColorFormat) {
1449                // eCompressionFormat does not seem right.
1450                found = true;
1451                break;
1452            }
1453            if (portIndex == kPortIndexOutput
1454                    && compressionFormat == format.eCompressionFormat) {
1455                // eColorFormat does not seem right.
1456                found = true;
1457                break;
1458            }
1459        }
1460
1461        if (format.eCompressionFormat == compressionFormat
1462            && format.eColorFormat == colorFormat) {
1463            found = true;
1464            break;
1465        }
1466
1467        ++index;
1468    }
1469
1470    if (!found) {
1471        return UNKNOWN_ERROR;
1472    }
1473
1474    status_t err = mOMX->setParameter(
1475            mNode, OMX_IndexParamVideoPortFormat,
1476            &format, sizeof(format));
1477
1478    return err;
1479}
1480
1481status_t ACodec::setSupportedOutputFormat() {
1482    OMX_VIDEO_PARAM_PORTFORMATTYPE format;
1483    InitOMXParams(&format);
1484    format.nPortIndex = kPortIndexOutput;
1485    format.nIndex = 0;
1486
1487    status_t err = mOMX->getParameter(
1488            mNode, OMX_IndexParamVideoPortFormat,
1489            &format, sizeof(format));
1490    CHECK_EQ(err, (status_t)OK);
1491    CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused);
1492
1493    return mOMX->setParameter(
1494            mNode, OMX_IndexParamVideoPortFormat,
1495            &format, sizeof(format));
1496}
1497
1498static const struct VideoCodingMapEntry {
1499    const char *mMime;
1500    OMX_VIDEO_CODINGTYPE mVideoCodingType;
1501} kVideoCodingMapEntry[] = {
1502    { MEDIA_MIMETYPE_VIDEO_AVC, OMX_VIDEO_CodingAVC },
1503    { MEDIA_MIMETYPE_VIDEO_MPEG4, OMX_VIDEO_CodingMPEG4 },
1504    { MEDIA_MIMETYPE_VIDEO_H263, OMX_VIDEO_CodingH263 },
1505    { MEDIA_MIMETYPE_VIDEO_MPEG2, OMX_VIDEO_CodingMPEG2 },
1506    { MEDIA_MIMETYPE_VIDEO_VP8, OMX_VIDEO_CodingVP8 },
1507    { MEDIA_MIMETYPE_VIDEO_VP9, OMX_VIDEO_CodingVP9 },
1508};
1509
1510static status_t GetVideoCodingTypeFromMime(
1511        const char *mime, OMX_VIDEO_CODINGTYPE *codingType) {
1512    for (size_t i = 0;
1513         i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
1514         ++i) {
1515        if (!strcasecmp(mime, kVideoCodingMapEntry[i].mMime)) {
1516            *codingType = kVideoCodingMapEntry[i].mVideoCodingType;
1517            return OK;
1518        }
1519    }
1520
1521    *codingType = OMX_VIDEO_CodingUnused;
1522
1523    return ERROR_UNSUPPORTED;
1524}
1525
1526static status_t GetMimeTypeForVideoCoding(
1527        OMX_VIDEO_CODINGTYPE codingType, AString *mime) {
1528    for (size_t i = 0;
1529         i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
1530         ++i) {
1531        if (codingType == kVideoCodingMapEntry[i].mVideoCodingType) {
1532            *mime = kVideoCodingMapEntry[i].mMime;
1533            return OK;
1534        }
1535    }
1536
1537    mime->clear();
1538
1539    return ERROR_UNSUPPORTED;
1540}
1541
1542status_t ACodec::setupVideoDecoder(
1543        const char *mime, int32_t width, int32_t height) {
1544    OMX_VIDEO_CODINGTYPE compressionFormat;
1545    status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
1546
1547    if (err != OK) {
1548        return err;
1549    }
1550
1551    err = setVideoPortFormatType(
1552            kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
1553
1554    if (err != OK) {
1555        return err;
1556    }
1557
1558    err = setSupportedOutputFormat();
1559
1560    if (err != OK) {
1561        return err;
1562    }
1563
1564    err = setVideoFormatOnPort(
1565            kPortIndexInput, width, height, compressionFormat);
1566
1567    if (err != OK) {
1568        return err;
1569    }
1570
1571    err = setVideoFormatOnPort(
1572            kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused);
1573
1574    if (err != OK) {
1575        return err;
1576    }
1577
1578    return OK;
1579}
1580
1581status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) {
1582    int32_t tmp;
1583    if (!msg->findInt32("color-format", &tmp)) {
1584        return INVALID_OPERATION;
1585    }
1586
1587    OMX_COLOR_FORMATTYPE colorFormat =
1588        static_cast<OMX_COLOR_FORMATTYPE>(tmp);
1589
1590    status_t err = setVideoPortFormatType(
1591            kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat);
1592
1593    if (err != OK) {
1594        ALOGE("[%s] does not support color format %d",
1595              mComponentName.c_str(), colorFormat);
1596
1597        return err;
1598    }
1599
1600    /* Input port configuration */
1601
1602    OMX_PARAM_PORTDEFINITIONTYPE def;
1603    InitOMXParams(&def);
1604
1605    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
1606
1607    def.nPortIndex = kPortIndexInput;
1608
1609    err = mOMX->getParameter(
1610            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1611
1612    if (err != OK) {
1613        return err;
1614    }
1615
1616    int32_t width, height, bitrate;
1617    if (!msg->findInt32("width", &width)
1618            || !msg->findInt32("height", &height)
1619            || !msg->findInt32("bitrate", &bitrate)) {
1620        return INVALID_OPERATION;
1621    }
1622
1623    video_def->nFrameWidth = width;
1624    video_def->nFrameHeight = height;
1625
1626    int32_t stride;
1627    if (!msg->findInt32("stride", &stride)) {
1628        stride = width;
1629    }
1630
1631    video_def->nStride = stride;
1632
1633    int32_t sliceHeight;
1634    if (!msg->findInt32("slice-height", &sliceHeight)) {
1635        sliceHeight = height;
1636    }
1637
1638    video_def->nSliceHeight = sliceHeight;
1639
1640    def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2;
1641
1642    float frameRate;
1643    if (!msg->findFloat("frame-rate", &frameRate)) {
1644        int32_t tmp;
1645        if (!msg->findInt32("frame-rate", &tmp)) {
1646            return INVALID_OPERATION;
1647        }
1648        frameRate = (float)tmp;
1649    }
1650
1651    video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
1652    video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
1653    video_def->eColorFormat = colorFormat;
1654
1655    err = mOMX->setParameter(
1656            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1657
1658    if (err != OK) {
1659        ALOGE("[%s] failed to set input port definition parameters.",
1660              mComponentName.c_str());
1661
1662        return err;
1663    }
1664
1665    /* Output port configuration */
1666
1667    OMX_VIDEO_CODINGTYPE compressionFormat;
1668    err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
1669
1670    if (err != OK) {
1671        return err;
1672    }
1673
1674    err = setVideoPortFormatType(
1675            kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused);
1676
1677    if (err != OK) {
1678        ALOGE("[%s] does not support compression format %d",
1679             mComponentName.c_str(), compressionFormat);
1680
1681        return err;
1682    }
1683
1684    def.nPortIndex = kPortIndexOutput;
1685
1686    err = mOMX->getParameter(
1687            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1688
1689    if (err != OK) {
1690        return err;
1691    }
1692
1693    video_def->nFrameWidth = width;
1694    video_def->nFrameHeight = height;
1695    video_def->xFramerate = 0;
1696    video_def->nBitrate = bitrate;
1697    video_def->eCompressionFormat = compressionFormat;
1698    video_def->eColorFormat = OMX_COLOR_FormatUnused;
1699
1700    err = mOMX->setParameter(
1701            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1702
1703    if (err != OK) {
1704        ALOGE("[%s] failed to set output port definition parameters.",
1705              mComponentName.c_str());
1706
1707        return err;
1708    }
1709
1710    switch (compressionFormat) {
1711        case OMX_VIDEO_CodingMPEG4:
1712            err = setupMPEG4EncoderParameters(msg);
1713            break;
1714
1715        case OMX_VIDEO_CodingH263:
1716            err = setupH263EncoderParameters(msg);
1717            break;
1718
1719        case OMX_VIDEO_CodingAVC:
1720            err = setupAVCEncoderParameters(msg);
1721            break;
1722
1723        default:
1724            break;
1725    }
1726
1727    ALOGI("setupVideoEncoder succeeded");
1728
1729    return err;
1730}
1731
1732status_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) {
1733    OMX_VIDEO_PARAM_INTRAREFRESHTYPE params;
1734    InitOMXParams(&params);
1735    params.nPortIndex = kPortIndexOutput;
1736
1737    params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode);
1738
1739    if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic ||
1740            params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
1741        int32_t mbs;
1742        if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) {
1743            return INVALID_OPERATION;
1744        }
1745        params.nCirMBs = mbs;
1746    }
1747
1748    if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive ||
1749            params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
1750        int32_t mbs;
1751        if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) {
1752            return INVALID_OPERATION;
1753        }
1754        params.nAirMBs = mbs;
1755
1756        int32_t ref;
1757        if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) {
1758            return INVALID_OPERATION;
1759        }
1760        params.nAirRef = ref;
1761    }
1762
1763    status_t err = mOMX->setParameter(
1764            mNode, OMX_IndexParamVideoIntraRefresh,
1765            &params, sizeof(params));
1766    return err;
1767}
1768
1769static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) {
1770    if (iFramesInterval < 0) {
1771        return 0xFFFFFFFF;
1772    } else if (iFramesInterval == 0) {
1773        return 0;
1774    }
1775    OMX_U32 ret = frameRate * iFramesInterval;
1776    CHECK(ret > 1);
1777    return ret;
1778}
1779
1780static OMX_VIDEO_CONTROLRATETYPE getBitrateMode(const sp<AMessage> &msg) {
1781    int32_t tmp;
1782    if (!msg->findInt32("bitrate-mode", &tmp)) {
1783        return OMX_Video_ControlRateVariable;
1784    }
1785
1786    return static_cast<OMX_VIDEO_CONTROLRATETYPE>(tmp);
1787}
1788
1789status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) {
1790    int32_t bitrate, iFrameInterval;
1791    if (!msg->findInt32("bitrate", &bitrate)
1792            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
1793        return INVALID_OPERATION;
1794    }
1795
1796    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
1797
1798    float frameRate;
1799    if (!msg->findFloat("frame-rate", &frameRate)) {
1800        int32_t tmp;
1801        if (!msg->findInt32("frame-rate", &tmp)) {
1802            return INVALID_OPERATION;
1803        }
1804        frameRate = (float)tmp;
1805    }
1806
1807    OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
1808    InitOMXParams(&mpeg4type);
1809    mpeg4type.nPortIndex = kPortIndexOutput;
1810
1811    status_t err = mOMX->getParameter(
1812            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
1813
1814    if (err != OK) {
1815        return err;
1816    }
1817
1818    mpeg4type.nSliceHeaderSpacing = 0;
1819    mpeg4type.bSVH = OMX_FALSE;
1820    mpeg4type.bGov = OMX_FALSE;
1821
1822    mpeg4type.nAllowedPictureTypes =
1823        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1824
1825    mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
1826    if (mpeg4type.nPFrames == 0) {
1827        mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1828    }
1829    mpeg4type.nBFrames = 0;
1830    mpeg4type.nIDCVLCThreshold = 0;
1831    mpeg4type.bACPred = OMX_TRUE;
1832    mpeg4type.nMaxPacketSize = 256;
1833    mpeg4type.nTimeIncRes = 1000;
1834    mpeg4type.nHeaderExtension = 0;
1835    mpeg4type.bReversibleVLC = OMX_FALSE;
1836
1837    int32_t profile;
1838    if (msg->findInt32("profile", &profile)) {
1839        int32_t level;
1840        if (!msg->findInt32("level", &level)) {
1841            return INVALID_OPERATION;
1842        }
1843
1844        err = verifySupportForProfileAndLevel(profile, level);
1845
1846        if (err != OK) {
1847            return err;
1848        }
1849
1850        mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile);
1851        mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level);
1852    }
1853
1854    err = mOMX->setParameter(
1855            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
1856
1857    if (err != OK) {
1858        return err;
1859    }
1860
1861    err = configureBitrate(bitrate, bitrateMode);
1862
1863    if (err != OK) {
1864        return err;
1865    }
1866
1867    return setupErrorCorrectionParameters();
1868}
1869
1870status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) {
1871    int32_t bitrate, iFrameInterval;
1872    if (!msg->findInt32("bitrate", &bitrate)
1873            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
1874        return INVALID_OPERATION;
1875    }
1876
1877    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
1878
1879    float frameRate;
1880    if (!msg->findFloat("frame-rate", &frameRate)) {
1881        int32_t tmp;
1882        if (!msg->findInt32("frame-rate", &tmp)) {
1883            return INVALID_OPERATION;
1884        }
1885        frameRate = (float)tmp;
1886    }
1887
1888    OMX_VIDEO_PARAM_H263TYPE h263type;
1889    InitOMXParams(&h263type);
1890    h263type.nPortIndex = kPortIndexOutput;
1891
1892    status_t err = mOMX->getParameter(
1893            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
1894
1895    if (err != OK) {
1896        return err;
1897    }
1898
1899    h263type.nAllowedPictureTypes =
1900        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1901
1902    h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
1903    if (h263type.nPFrames == 0) {
1904        h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
1905    }
1906    h263type.nBFrames = 0;
1907
1908    int32_t profile;
1909    if (msg->findInt32("profile", &profile)) {
1910        int32_t level;
1911        if (!msg->findInt32("level", &level)) {
1912            return INVALID_OPERATION;
1913        }
1914
1915        err = verifySupportForProfileAndLevel(profile, level);
1916
1917        if (err != OK) {
1918            return err;
1919        }
1920
1921        h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile);
1922        h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level);
1923    }
1924
1925    h263type.bPLUSPTYPEAllowed = OMX_FALSE;
1926    h263type.bForceRoundingTypeToZero = OMX_FALSE;
1927    h263type.nPictureHeaderRepetition = 0;
1928    h263type.nGOBHeaderInterval = 0;
1929
1930    err = mOMX->setParameter(
1931            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
1932
1933    if (err != OK) {
1934        return err;
1935    }
1936
1937    err = configureBitrate(bitrate, bitrateMode);
1938
1939    if (err != OK) {
1940        return err;
1941    }
1942
1943    return setupErrorCorrectionParameters();
1944}
1945
1946status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
1947    int32_t bitrate, iFrameInterval;
1948    if (!msg->findInt32("bitrate", &bitrate)
1949            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
1950        return INVALID_OPERATION;
1951    }
1952
1953    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
1954
1955    float frameRate;
1956    if (!msg->findFloat("frame-rate", &frameRate)) {
1957        int32_t tmp;
1958        if (!msg->findInt32("frame-rate", &tmp)) {
1959            return INVALID_OPERATION;
1960        }
1961        frameRate = (float)tmp;
1962    }
1963
1964    status_t err = OK;
1965    int32_t intraRefreshMode = 0;
1966    if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) {
1967        err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode);
1968        if (err != OK) {
1969            ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x",
1970                    err, intraRefreshMode);
1971            return err;
1972        }
1973    }
1974
1975    OMX_VIDEO_PARAM_AVCTYPE h264type;
1976    InitOMXParams(&h264type);
1977    h264type.nPortIndex = kPortIndexOutput;
1978
1979    err = mOMX->getParameter(
1980            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
1981
1982    if (err != OK) {
1983        return err;
1984    }
1985
1986    h264type.nAllowedPictureTypes =
1987        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
1988
1989    int32_t profile;
1990    if (msg->findInt32("profile", &profile)) {
1991        int32_t level;
1992        if (!msg->findInt32("level", &level)) {
1993            return INVALID_OPERATION;
1994        }
1995
1996        err = verifySupportForProfileAndLevel(profile, level);
1997
1998        if (err != OK) {
1999            return err;
2000        }
2001
2002        h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile);
2003        h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level);
2004    }
2005
2006    // XXX
2007    if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) {
2008        ALOGW("Use baseline profile instead of %d for AVC recording",
2009            h264type.eProfile);
2010        h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
2011    }
2012
2013    if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
2014        h264type.nSliceHeaderSpacing = 0;
2015        h264type.bUseHadamard = OMX_TRUE;
2016        h264type.nRefFrames = 1;
2017        h264type.nBFrames = 0;
2018        h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
2019        if (h264type.nPFrames == 0) {
2020            h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
2021        }
2022        h264type.nRefIdx10ActiveMinus1 = 0;
2023        h264type.nRefIdx11ActiveMinus1 = 0;
2024        h264type.bEntropyCodingCABAC = OMX_FALSE;
2025        h264type.bWeightedPPrediction = OMX_FALSE;
2026        h264type.bconstIpred = OMX_FALSE;
2027        h264type.bDirect8x8Inference = OMX_FALSE;
2028        h264type.bDirectSpatialTemporal = OMX_FALSE;
2029        h264type.nCabacInitIdc = 0;
2030    }
2031
2032    if (h264type.nBFrames != 0) {
2033        h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
2034    }
2035
2036    h264type.bEnableUEP = OMX_FALSE;
2037    h264type.bEnableFMO = OMX_FALSE;
2038    h264type.bEnableASO = OMX_FALSE;
2039    h264type.bEnableRS = OMX_FALSE;
2040    h264type.bFrameMBsOnly = OMX_TRUE;
2041    h264type.bMBAFF = OMX_FALSE;
2042    h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
2043
2044    err = mOMX->setParameter(
2045            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
2046
2047    if (err != OK) {
2048        return err;
2049    }
2050
2051    return configureBitrate(bitrate, bitrateMode);
2052}
2053
2054status_t ACodec::verifySupportForProfileAndLevel(
2055        int32_t profile, int32_t level) {
2056    OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
2057    InitOMXParams(&params);
2058    params.nPortIndex = kPortIndexOutput;
2059
2060    for (params.nProfileIndex = 0;; ++params.nProfileIndex) {
2061        status_t err = mOMX->getParameter(
2062                mNode,
2063                OMX_IndexParamVideoProfileLevelQuerySupported,
2064                &params,
2065                sizeof(params));
2066
2067        if (err != OK) {
2068            return err;
2069        }
2070
2071        int32_t supportedProfile = static_cast<int32_t>(params.eProfile);
2072        int32_t supportedLevel = static_cast<int32_t>(params.eLevel);
2073
2074        if (profile == supportedProfile && level <= supportedLevel) {
2075            return OK;
2076        }
2077    }
2078}
2079
2080status_t ACodec::configureBitrate(
2081        int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode) {
2082    OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
2083    InitOMXParams(&bitrateType);
2084    bitrateType.nPortIndex = kPortIndexOutput;
2085
2086    status_t err = mOMX->getParameter(
2087            mNode, OMX_IndexParamVideoBitrate,
2088            &bitrateType, sizeof(bitrateType));
2089
2090    if (err != OK) {
2091        return err;
2092    }
2093
2094    bitrateType.eControlRate = bitrateMode;
2095    bitrateType.nTargetBitrate = bitrate;
2096
2097    return mOMX->setParameter(
2098            mNode, OMX_IndexParamVideoBitrate,
2099            &bitrateType, sizeof(bitrateType));
2100}
2101
2102status_t ACodec::setupErrorCorrectionParameters() {
2103    OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
2104    InitOMXParams(&errorCorrectionType);
2105    errorCorrectionType.nPortIndex = kPortIndexOutput;
2106
2107    status_t err = mOMX->getParameter(
2108            mNode, OMX_IndexParamVideoErrorCorrection,
2109            &errorCorrectionType, sizeof(errorCorrectionType));
2110
2111    if (err != OK) {
2112        return OK;  // Optional feature. Ignore this failure
2113    }
2114
2115    errorCorrectionType.bEnableHEC = OMX_FALSE;
2116    errorCorrectionType.bEnableResync = OMX_TRUE;
2117    errorCorrectionType.nResynchMarkerSpacing = 256;
2118    errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
2119    errorCorrectionType.bEnableRVLC = OMX_FALSE;
2120
2121    return mOMX->setParameter(
2122            mNode, OMX_IndexParamVideoErrorCorrection,
2123            &errorCorrectionType, sizeof(errorCorrectionType));
2124}
2125
2126status_t ACodec::setVideoFormatOnPort(
2127        OMX_U32 portIndex,
2128        int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) {
2129    OMX_PARAM_PORTDEFINITIONTYPE def;
2130    InitOMXParams(&def);
2131    def.nPortIndex = portIndex;
2132
2133    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
2134
2135    status_t err = mOMX->getParameter(
2136            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2137
2138    CHECK_EQ(err, (status_t)OK);
2139
2140    if (portIndex == kPortIndexInput) {
2141        // XXX Need a (much) better heuristic to compute input buffer sizes.
2142        const size_t X = 64 * 1024;
2143        if (def.nBufferSize < X) {
2144            def.nBufferSize = X;
2145        }
2146    }
2147
2148    CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
2149
2150    video_def->nFrameWidth = width;
2151    video_def->nFrameHeight = height;
2152
2153    if (portIndex == kPortIndexInput) {
2154        video_def->eCompressionFormat = compressionFormat;
2155        video_def->eColorFormat = OMX_COLOR_FormatUnused;
2156    }
2157
2158    err = mOMX->setParameter(
2159            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2160
2161    return err;
2162}
2163
2164status_t ACodec::initNativeWindow() {
2165    if (mNativeWindow != NULL) {
2166        return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
2167    }
2168
2169    mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE);
2170    return OK;
2171}
2172
2173size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const {
2174    size_t n = 0;
2175
2176    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
2177        const BufferInfo &info = mBuffers[portIndex].itemAt(i);
2178
2179        if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
2180            ++n;
2181        }
2182    }
2183
2184    return n;
2185}
2186
2187size_t ACodec::countBuffersOwnedByNativeWindow() const {
2188    size_t n = 0;
2189
2190    for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) {
2191        const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i);
2192
2193        if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
2194            ++n;
2195        }
2196    }
2197
2198    return n;
2199}
2200
2201void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() {
2202    if (mNativeWindow == NULL) {
2203        return;
2204    }
2205
2206    int minUndequeuedBufs = 0;
2207    status_t err = mNativeWindow->query(
2208            mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
2209            &minUndequeuedBufs);
2210
2211    if (err != OK) {
2212        ALOGE("[%s] NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
2213                mComponentName.c_str(), strerror(-err), -err);
2214
2215        minUndequeuedBufs = 0;
2216    }
2217
2218    while (countBuffersOwnedByNativeWindow() > (size_t)minUndequeuedBufs
2219            && dequeueBufferFromNativeWindow() != NULL) {
2220    }
2221}
2222
2223bool ACodec::allYourBuffersAreBelongToUs(
2224        OMX_U32 portIndex) {
2225    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
2226        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
2227
2228        if (info->mStatus != BufferInfo::OWNED_BY_US
2229                && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
2230            ALOGV("[%s] Buffer %p on port %ld still has status %d",
2231                    mComponentName.c_str(),
2232                    info->mBufferID, portIndex, info->mStatus);
2233            return false;
2234        }
2235    }
2236
2237    return true;
2238}
2239
2240bool ACodec::allYourBuffersAreBelongToUs() {
2241    return allYourBuffersAreBelongToUs(kPortIndexInput)
2242        && allYourBuffersAreBelongToUs(kPortIndexOutput);
2243}
2244
2245void ACodec::deferMessage(const sp<AMessage> &msg) {
2246    bool wasEmptyBefore = mDeferredQueue.empty();
2247    mDeferredQueue.push_back(msg);
2248}
2249
2250void ACodec::processDeferredMessages() {
2251    List<sp<AMessage> > queue = mDeferredQueue;
2252    mDeferredQueue.clear();
2253
2254    List<sp<AMessage> >::iterator it = queue.begin();
2255    while (it != queue.end()) {
2256        onMessageReceived(*it++);
2257    }
2258}
2259
2260void ACodec::sendFormatChange(const sp<AMessage> &reply) {
2261    sp<AMessage> notify = mNotify->dup();
2262    notify->setInt32("what", kWhatOutputFormatChanged);
2263
2264    OMX_PARAM_PORTDEFINITIONTYPE def;
2265    InitOMXParams(&def);
2266    def.nPortIndex = kPortIndexOutput;
2267
2268    CHECK_EQ(mOMX->getParameter(
2269                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)),
2270             (status_t)OK);
2271
2272    CHECK_EQ((int)def.eDir, (int)OMX_DirOutput);
2273
2274    switch (def.eDomain) {
2275        case OMX_PortDomainVideo:
2276        {
2277            OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
2278
2279            AString mime;
2280            if (!mIsEncoder) {
2281                notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
2282            } else if (GetMimeTypeForVideoCoding(
2283                        videoDef->eCompressionFormat, &mime) != OK) {
2284                notify->setString("mime", "application/octet-stream");
2285            } else {
2286                notify->setString("mime", mime.c_str());
2287            }
2288
2289            notify->setInt32("width", videoDef->nFrameWidth);
2290            notify->setInt32("height", videoDef->nFrameHeight);
2291
2292            if (!mIsEncoder) {
2293                notify->setInt32("stride", videoDef->nStride);
2294                notify->setInt32("slice-height", videoDef->nSliceHeight);
2295                notify->setInt32("color-format", videoDef->eColorFormat);
2296
2297                OMX_CONFIG_RECTTYPE rect;
2298                InitOMXParams(&rect);
2299                rect.nPortIndex = kPortIndexOutput;
2300
2301                if (mOMX->getConfig(
2302                            mNode, OMX_IndexConfigCommonOutputCrop,
2303                            &rect, sizeof(rect)) != OK) {
2304                    rect.nLeft = 0;
2305                    rect.nTop = 0;
2306                    rect.nWidth = videoDef->nFrameWidth;
2307                    rect.nHeight = videoDef->nFrameHeight;
2308                }
2309
2310                CHECK_GE(rect.nLeft, 0);
2311                CHECK_GE(rect.nTop, 0);
2312                CHECK_GE(rect.nWidth, 0u);
2313                CHECK_GE(rect.nHeight, 0u);
2314                CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth);
2315                CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight);
2316
2317                notify->setRect(
2318                        "crop",
2319                        rect.nLeft,
2320                        rect.nTop,
2321                        rect.nLeft + rect.nWidth - 1,
2322                        rect.nTop + rect.nHeight - 1);
2323
2324                if (mNativeWindow != NULL) {
2325                    reply->setRect(
2326                            "crop",
2327                            rect.nLeft,
2328                            rect.nTop,
2329                            rect.nLeft + rect.nWidth,
2330                            rect.nTop + rect.nHeight);
2331                }
2332            }
2333            break;
2334        }
2335
2336        case OMX_PortDomainAudio:
2337        {
2338            OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
2339
2340            switch (audioDef->eEncoding) {
2341                case OMX_AUDIO_CodingPCM:
2342                {
2343                    OMX_AUDIO_PARAM_PCMMODETYPE params;
2344                    InitOMXParams(&params);
2345                    params.nPortIndex = kPortIndexOutput;
2346
2347                    CHECK_EQ(mOMX->getParameter(
2348                                mNode, OMX_IndexParamAudioPcm,
2349                                &params, sizeof(params)),
2350                             (status_t)OK);
2351
2352                    CHECK_GT(params.nChannels, 0);
2353                    CHECK(params.nChannels == 1 || params.bInterleaved);
2354                    CHECK_EQ(params.nBitPerSample, 16u);
2355
2356                    CHECK_EQ((int)params.eNumData,
2357                             (int)OMX_NumericalDataSigned);
2358
2359                    CHECK_EQ((int)params.ePCMMode,
2360                             (int)OMX_AUDIO_PCMModeLinear);
2361
2362                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
2363                    notify->setInt32("channel-count", params.nChannels);
2364                    notify->setInt32("sample-rate", params.nSamplingRate);
2365                    if (mEncoderDelay + mEncoderPadding) {
2366                        size_t frameSize = params.nChannels * sizeof(int16_t);
2367                        if (mSkipCutBuffer != NULL) {
2368                            size_t prevbufsize = mSkipCutBuffer->size();
2369                            if (prevbufsize != 0) {
2370                                ALOGW("Replacing SkipCutBuffer holding %d "
2371                                      "bytes",
2372                                      prevbufsize);
2373                            }
2374                        }
2375                        mSkipCutBuffer = new SkipCutBuffer(
2376                                mEncoderDelay * frameSize,
2377                                mEncoderPadding * frameSize);
2378                    }
2379
2380                    if (mChannelMaskPresent) {
2381                        notify->setInt32("channel-mask", mChannelMask);
2382                    }
2383                    break;
2384                }
2385
2386                case OMX_AUDIO_CodingAAC:
2387                {
2388                    OMX_AUDIO_PARAM_AACPROFILETYPE params;
2389                    InitOMXParams(&params);
2390                    params.nPortIndex = kPortIndexOutput;
2391
2392                    CHECK_EQ(mOMX->getParameter(
2393                                mNode, OMX_IndexParamAudioAac,
2394                                &params, sizeof(params)),
2395                             (status_t)OK);
2396
2397                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
2398                    notify->setInt32("channel-count", params.nChannels);
2399                    notify->setInt32("sample-rate", params.nSampleRate);
2400                    break;
2401                }
2402
2403                case OMX_AUDIO_CodingAMR:
2404                {
2405                    OMX_AUDIO_PARAM_AMRTYPE params;
2406                    InitOMXParams(&params);
2407                    params.nPortIndex = kPortIndexOutput;
2408
2409                    CHECK_EQ(mOMX->getParameter(
2410                                mNode, OMX_IndexParamAudioAmr,
2411                                &params, sizeof(params)),
2412                             (status_t)OK);
2413
2414                    notify->setInt32("channel-count", 1);
2415                    if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) {
2416                        notify->setString(
2417                                "mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
2418
2419                        notify->setInt32("sample-rate", 16000);
2420                    } else {
2421                        notify->setString(
2422                                "mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
2423
2424                        notify->setInt32("sample-rate", 8000);
2425                    }
2426                    break;
2427                }
2428
2429                case OMX_AUDIO_CodingFLAC:
2430                {
2431                    OMX_AUDIO_PARAM_FLACTYPE params;
2432                    InitOMXParams(&params);
2433                    params.nPortIndex = kPortIndexOutput;
2434
2435                    CHECK_EQ(mOMX->getParameter(
2436                                mNode, OMX_IndexParamAudioFlac,
2437                                &params, sizeof(params)),
2438                             (status_t)OK);
2439
2440                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC);
2441                    notify->setInt32("channel-count", params.nChannels);
2442                    notify->setInt32("sample-rate", params.nSampleRate);
2443                    break;
2444                }
2445
2446                default:
2447                    TRESPASS();
2448            }
2449            break;
2450        }
2451
2452        default:
2453            TRESPASS();
2454    }
2455
2456    notify->post();
2457
2458    mSentFormat = true;
2459}
2460
2461void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) {
2462    sp<AMessage> notify = mNotify->dup();
2463    notify->setInt32("what", ACodec::kWhatError);
2464    notify->setInt32("omx-error", error);
2465    notify->setInt32("err", internalError);
2466    notify->post();
2467}
2468
2469status_t ACodec::pushBlankBuffersToNativeWindow() {
2470    status_t err = NO_ERROR;
2471    ANativeWindowBuffer* anb = NULL;
2472    int numBufs = 0;
2473    int minUndequeuedBufs = 0;
2474
2475    // We need to reconnect to the ANativeWindow as a CPU client to ensure that
2476    // no frames get dropped by SurfaceFlinger assuming that these are video
2477    // frames.
2478    err = native_window_api_disconnect(mNativeWindow.get(),
2479            NATIVE_WINDOW_API_MEDIA);
2480    if (err != NO_ERROR) {
2481        ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
2482                strerror(-err), -err);
2483        return err;
2484    }
2485
2486    err = native_window_api_connect(mNativeWindow.get(),
2487            NATIVE_WINDOW_API_CPU);
2488    if (err != NO_ERROR) {
2489        ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
2490                strerror(-err), -err);
2491        return err;
2492    }
2493
2494    err = native_window_set_buffers_geometry(mNativeWindow.get(), 1, 1,
2495            HAL_PIXEL_FORMAT_RGBX_8888);
2496    if (err != NO_ERROR) {
2497        ALOGE("error pushing blank frames: set_buffers_geometry failed: %s (%d)",
2498                strerror(-err), -err);
2499        goto error;
2500    }
2501
2502    err = native_window_set_usage(mNativeWindow.get(),
2503            GRALLOC_USAGE_SW_WRITE_OFTEN);
2504    if (err != NO_ERROR) {
2505        ALOGE("error pushing blank frames: set_usage failed: %s (%d)",
2506                strerror(-err), -err);
2507        goto error;
2508    }
2509
2510    err = mNativeWindow->query(mNativeWindow.get(),
2511            NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs);
2512    if (err != NO_ERROR) {
2513        ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query "
2514                "failed: %s (%d)", strerror(-err), -err);
2515        goto error;
2516    }
2517
2518    numBufs = minUndequeuedBufs + 1;
2519    err = native_window_set_buffer_count(mNativeWindow.get(), numBufs);
2520    if (err != NO_ERROR) {
2521        ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)",
2522                strerror(-err), -err);
2523        goto error;
2524    }
2525
2526    // We  push numBufs + 1 buffers to ensure that we've drawn into the same
2527    // buffer twice.  This should guarantee that the buffer has been displayed
2528    // on the screen and then been replaced, so an previous video frames are
2529    // guaranteed NOT to be currently displayed.
2530    for (int i = 0; i < numBufs + 1; i++) {
2531        int fenceFd = -1;
2532        err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &anb);
2533        if (err != NO_ERROR) {
2534            ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)",
2535                    strerror(-err), -err);
2536            goto error;
2537        }
2538
2539        sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
2540
2541        // Fill the buffer with the a 1x1 checkerboard pattern ;)
2542        uint32_t* img = NULL;
2543        err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
2544        if (err != NO_ERROR) {
2545            ALOGE("error pushing blank frames: lock failed: %s (%d)",
2546                    strerror(-err), -err);
2547            goto error;
2548        }
2549
2550        *img = 0;
2551
2552        err = buf->unlock();
2553        if (err != NO_ERROR) {
2554            ALOGE("error pushing blank frames: unlock failed: %s (%d)",
2555                    strerror(-err), -err);
2556            goto error;
2557        }
2558
2559        err = mNativeWindow->queueBuffer(mNativeWindow.get(),
2560                buf->getNativeBuffer(), -1);
2561        if (err != NO_ERROR) {
2562            ALOGE("error pushing blank frames: queueBuffer failed: %s (%d)",
2563                    strerror(-err), -err);
2564            goto error;
2565        }
2566
2567        anb = NULL;
2568    }
2569
2570error:
2571
2572    if (err != NO_ERROR) {
2573        // Clean up after an error.
2574        if (anb != NULL) {
2575            mNativeWindow->cancelBuffer(mNativeWindow.get(), anb, -1);
2576        }
2577
2578        native_window_api_disconnect(mNativeWindow.get(),
2579                NATIVE_WINDOW_API_CPU);
2580        native_window_api_connect(mNativeWindow.get(),
2581                NATIVE_WINDOW_API_MEDIA);
2582
2583        return err;
2584    } else {
2585        // Clean up after success.
2586        err = native_window_api_disconnect(mNativeWindow.get(),
2587                NATIVE_WINDOW_API_CPU);
2588        if (err != NO_ERROR) {
2589            ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
2590                    strerror(-err), -err);
2591            return err;
2592        }
2593
2594        err = native_window_api_connect(mNativeWindow.get(),
2595                NATIVE_WINDOW_API_MEDIA);
2596        if (err != NO_ERROR) {
2597            ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
2598                    strerror(-err), -err);
2599            return err;
2600        }
2601
2602        return NO_ERROR;
2603    }
2604}
2605
2606////////////////////////////////////////////////////////////////////////////////
2607
2608ACodec::PortDescription::PortDescription() {
2609}
2610
2611status_t ACodec::requestIDRFrame() {
2612    if (!mIsEncoder) {
2613        return ERROR_UNSUPPORTED;
2614    }
2615
2616    OMX_CONFIG_INTRAREFRESHVOPTYPE params;
2617    InitOMXParams(&params);
2618
2619    params.nPortIndex = kPortIndexOutput;
2620    params.IntraRefreshVOP = OMX_TRUE;
2621
2622    return mOMX->setConfig(
2623            mNode,
2624            OMX_IndexConfigVideoIntraVOPRefresh,
2625            &params,
2626            sizeof(params));
2627}
2628
2629void ACodec::PortDescription::addBuffer(
2630        IOMX::buffer_id id, const sp<ABuffer> &buffer) {
2631    mBufferIDs.push_back(id);
2632    mBuffers.push_back(buffer);
2633}
2634
2635size_t ACodec::PortDescription::countBuffers() {
2636    return mBufferIDs.size();
2637}
2638
2639IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const {
2640    return mBufferIDs.itemAt(index);
2641}
2642
2643sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const {
2644    return mBuffers.itemAt(index);
2645}
2646
2647////////////////////////////////////////////////////////////////////////////////
2648
2649ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
2650    : AState(parentState),
2651      mCodec(codec) {
2652}
2653
2654ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(OMX_U32 portIndex) {
2655    return KEEP_BUFFERS;
2656}
2657
2658bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
2659    switch (msg->what()) {
2660        case kWhatInputBufferFilled:
2661        {
2662            onInputBufferFilled(msg);
2663            break;
2664        }
2665
2666        case kWhatOutputBufferDrained:
2667        {
2668            onOutputBufferDrained(msg);
2669            break;
2670        }
2671
2672        case ACodec::kWhatOMXMessage:
2673        {
2674            return onOMXMessage(msg);
2675        }
2676
2677        case ACodec::kWhatCreateInputSurface:
2678        case ACodec::kWhatSignalEndOfInputStream:
2679        {
2680            ALOGE("Message 0x%x was not handled", msg->what());
2681            mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION);
2682            return true;
2683        }
2684
2685        case ACodec::kWhatOMXDied:
2686        {
2687            ALOGE("OMX/mediaserver died, signalling error!");
2688            mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT);
2689            break;
2690        }
2691
2692        default:
2693            return false;
2694    }
2695
2696    return true;
2697}
2698
2699bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
2700    int32_t type;
2701    CHECK(msg->findInt32("type", &type));
2702
2703    IOMX::node_id nodeID;
2704    CHECK(msg->findPointer("node", &nodeID));
2705    CHECK_EQ(nodeID, mCodec->mNode);
2706
2707    switch (type) {
2708        case omx_message::EVENT:
2709        {
2710            int32_t event, data1, data2;
2711            CHECK(msg->findInt32("event", &event));
2712            CHECK(msg->findInt32("data1", &data1));
2713            CHECK(msg->findInt32("data2", &data2));
2714
2715            if (event == OMX_EventCmdComplete
2716                    && data1 == OMX_CommandFlush
2717                    && data2 == (int32_t)OMX_ALL) {
2718                // Use of this notification is not consistent across
2719                // implementations. We'll drop this notification and rely
2720                // on flush-complete notifications on the individual port
2721                // indices instead.
2722
2723                return true;
2724            }
2725
2726            return onOMXEvent(
2727                    static_cast<OMX_EVENTTYPE>(event),
2728                    static_cast<OMX_U32>(data1),
2729                    static_cast<OMX_U32>(data2));
2730        }
2731
2732        case omx_message::EMPTY_BUFFER_DONE:
2733        {
2734            IOMX::buffer_id bufferID;
2735            CHECK(msg->findPointer("buffer", &bufferID));
2736
2737            return onOMXEmptyBufferDone(bufferID);
2738        }
2739
2740        case omx_message::FILL_BUFFER_DONE:
2741        {
2742            IOMX::buffer_id bufferID;
2743            CHECK(msg->findPointer("buffer", &bufferID));
2744
2745            int32_t rangeOffset, rangeLength, flags;
2746            int64_t timeUs;
2747            void *platformPrivate;
2748            void *dataPtr;
2749
2750            CHECK(msg->findInt32("range_offset", &rangeOffset));
2751            CHECK(msg->findInt32("range_length", &rangeLength));
2752            CHECK(msg->findInt32("flags", &flags));
2753            CHECK(msg->findInt64("timestamp", &timeUs));
2754            CHECK(msg->findPointer("platform_private", &platformPrivate));
2755            CHECK(msg->findPointer("data_ptr", &dataPtr));
2756
2757            return onOMXFillBufferDone(
2758                    bufferID,
2759                    (size_t)rangeOffset, (size_t)rangeLength,
2760                    (OMX_U32)flags,
2761                    timeUs,
2762                    platformPrivate,
2763                    dataPtr);
2764        }
2765
2766        default:
2767            TRESPASS();
2768            break;
2769    }
2770}
2771
2772bool ACodec::BaseState::onOMXEvent(
2773        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
2774    if (event != OMX_EventError) {
2775        ALOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)",
2776             mCodec->mComponentName.c_str(), event, data1, data2);
2777
2778        return false;
2779    }
2780
2781    ALOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1);
2782
2783    mCodec->signalError((OMX_ERRORTYPE)data1);
2784
2785    return true;
2786}
2787
2788bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) {
2789    ALOGV("[%s] onOMXEmptyBufferDone %p",
2790         mCodec->mComponentName.c_str(), bufferID);
2791
2792    BufferInfo *info =
2793        mCodec->findBufferByID(kPortIndexInput, bufferID);
2794
2795    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
2796    info->mStatus = BufferInfo::OWNED_BY_US;
2797
2798    const sp<AMessage> &bufferMeta = info->mData->meta();
2799    void *mediaBuffer;
2800    if (bufferMeta->findPointer("mediaBuffer", &mediaBuffer)
2801            && mediaBuffer != NULL) {
2802        // We're in "store-metadata-in-buffers" mode, the underlying
2803        // OMX component had access to data that's implicitly refcounted
2804        // by this "mediaBuffer" object. Now that the OMX component has
2805        // told us that it's done with the input buffer, we can decrement
2806        // the mediaBuffer's reference count.
2807
2808        ALOGV("releasing mbuf %p", mediaBuffer);
2809
2810        ((MediaBuffer *)mediaBuffer)->release();
2811        mediaBuffer = NULL;
2812
2813        bufferMeta->setPointer("mediaBuffer", NULL);
2814    }
2815
2816    PortMode mode = getPortMode(kPortIndexInput);
2817
2818    switch (mode) {
2819        case KEEP_BUFFERS:
2820            break;
2821
2822        case RESUBMIT_BUFFERS:
2823            postFillThisBuffer(info);
2824            break;
2825
2826        default:
2827        {
2828            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
2829            TRESPASS();  // Not currently used
2830            break;
2831        }
2832    }
2833
2834    return true;
2835}
2836
2837void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
2838    if (mCodec->mPortEOS[kPortIndexInput]) {
2839        return;
2840    }
2841
2842    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
2843
2844    sp<AMessage> notify = mCodec->mNotify->dup();
2845    notify->setInt32("what", ACodec::kWhatFillThisBuffer);
2846    notify->setPointer("buffer-id", info->mBufferID);
2847
2848    info->mData->meta()->clear();
2849    notify->setBuffer("buffer", info->mData);
2850
2851    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id());
2852    reply->setPointer("buffer-id", info->mBufferID);
2853
2854    notify->setMessage("reply", reply);
2855
2856    notify->post();
2857
2858    info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
2859}
2860
2861void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
2862    IOMX::buffer_id bufferID;
2863    CHECK(msg->findPointer("buffer-id", &bufferID));
2864
2865    sp<ABuffer> buffer;
2866    int32_t err = OK;
2867    bool eos = false;
2868
2869    if (!msg->findBuffer("buffer", &buffer)) {
2870        CHECK(msg->findInt32("err", &err));
2871
2872        ALOGV("[%s] saw error %d instead of an input buffer",
2873             mCodec->mComponentName.c_str(), err);
2874
2875        buffer.clear();
2876
2877        eos = true;
2878    }
2879
2880    int32_t tmp;
2881    if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
2882        eos = true;
2883        err = ERROR_END_OF_STREAM;
2884    }
2885
2886    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
2887    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM);
2888
2889    info->mStatus = BufferInfo::OWNED_BY_US;
2890
2891    PortMode mode = getPortMode(kPortIndexInput);
2892
2893    switch (mode) {
2894        case KEEP_BUFFERS:
2895        {
2896            if (eos) {
2897                if (!mCodec->mPortEOS[kPortIndexInput]) {
2898                    mCodec->mPortEOS[kPortIndexInput] = true;
2899                    mCodec->mInputEOSResult = err;
2900                }
2901            }
2902            break;
2903        }
2904
2905        case RESUBMIT_BUFFERS:
2906        {
2907            if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) {
2908                int64_t timeUs;
2909                CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
2910
2911                OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
2912
2913                int32_t isCSD;
2914                if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
2915                    flags |= OMX_BUFFERFLAG_CODECCONFIG;
2916                }
2917
2918                if (eos) {
2919                    flags |= OMX_BUFFERFLAG_EOS;
2920                }
2921
2922                if (buffer != info->mData) {
2923                    ALOGV("[%s] Needs to copy input data for buffer %p. (%p != %p)",
2924                         mCodec->mComponentName.c_str(),
2925                         bufferID,
2926                         buffer.get(), info->mData.get());
2927
2928                    CHECK_LE(buffer->size(), info->mData->capacity());
2929                    memcpy(info->mData->data(), buffer->data(), buffer->size());
2930                }
2931
2932                if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
2933                    ALOGV("[%s] calling emptyBuffer %p w/ codec specific data",
2934                         mCodec->mComponentName.c_str(), bufferID);
2935                } else if (flags & OMX_BUFFERFLAG_EOS) {
2936                    ALOGV("[%s] calling emptyBuffer %p w/ EOS",
2937                         mCodec->mComponentName.c_str(), bufferID);
2938                } else {
2939#if TRACK_BUFFER_TIMING
2940                    ALOGI("[%s] calling emptyBuffer %p w/ time %lld us",
2941                         mCodec->mComponentName.c_str(), bufferID, timeUs);
2942#else
2943                    ALOGV("[%s] calling emptyBuffer %p w/ time %lld us",
2944                         mCodec->mComponentName.c_str(), bufferID, timeUs);
2945#endif
2946                }
2947
2948#if TRACK_BUFFER_TIMING
2949                ACodec::BufferStats stats;
2950                stats.mEmptyBufferTimeUs = ALooper::GetNowUs();
2951                stats.mFillBufferDoneTimeUs = -1ll;
2952                mCodec->mBufferStats.add(timeUs, stats);
2953#endif
2954
2955                CHECK_EQ(mCodec->mOMX->emptyBuffer(
2956                            mCodec->mNode,
2957                            bufferID,
2958                            0,
2959                            buffer->size(),
2960                            flags,
2961                            timeUs),
2962                         (status_t)OK);
2963
2964                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2965
2966                if (!eos) {
2967                    getMoreInputDataIfPossible();
2968                } else {
2969                    ALOGV("[%s] Signalled EOS on the input port",
2970                         mCodec->mComponentName.c_str());
2971
2972                    mCodec->mPortEOS[kPortIndexInput] = true;
2973                    mCodec->mInputEOSResult = err;
2974                }
2975            } else if (!mCodec->mPortEOS[kPortIndexInput]) {
2976                if (err != ERROR_END_OF_STREAM) {
2977                    ALOGV("[%s] Signalling EOS on the input port "
2978                         "due to error %d",
2979                         mCodec->mComponentName.c_str(), err);
2980                } else {
2981                    ALOGV("[%s] Signalling EOS on the input port",
2982                         mCodec->mComponentName.c_str());
2983                }
2984
2985                ALOGV("[%s] calling emptyBuffer %p signalling EOS",
2986                     mCodec->mComponentName.c_str(), bufferID);
2987
2988                CHECK_EQ(mCodec->mOMX->emptyBuffer(
2989                            mCodec->mNode,
2990                            bufferID,
2991                            0,
2992                            0,
2993                            OMX_BUFFERFLAG_EOS,
2994                            0),
2995                         (status_t)OK);
2996
2997                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
2998
2999                mCodec->mPortEOS[kPortIndexInput] = true;
3000                mCodec->mInputEOSResult = err;
3001            }
3002            break;
3003
3004            default:
3005                CHECK_EQ((int)mode, (int)FREE_BUFFERS);
3006                break;
3007        }
3008    }
3009}
3010
3011void ACodec::BaseState::getMoreInputDataIfPossible() {
3012    if (mCodec->mPortEOS[kPortIndexInput]) {
3013        return;
3014    }
3015
3016    BufferInfo *eligible = NULL;
3017
3018    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
3019        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
3020
3021#if 0
3022        if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
3023            // There's already a "read" pending.
3024            return;
3025        }
3026#endif
3027
3028        if (info->mStatus == BufferInfo::OWNED_BY_US) {
3029            eligible = info;
3030        }
3031    }
3032
3033    if (eligible == NULL) {
3034        return;
3035    }
3036
3037    postFillThisBuffer(eligible);
3038}
3039
3040bool ACodec::BaseState::onOMXFillBufferDone(
3041        IOMX::buffer_id bufferID,
3042        size_t rangeOffset, size_t rangeLength,
3043        OMX_U32 flags,
3044        int64_t timeUs,
3045        void *platformPrivate,
3046        void *dataPtr) {
3047    ALOGV("[%s] onOMXFillBufferDone %p time %lld us, flags = 0x%08lx",
3048         mCodec->mComponentName.c_str(), bufferID, timeUs, flags);
3049
3050    ssize_t index;
3051
3052#if TRACK_BUFFER_TIMING
3053    index = mCodec->mBufferStats.indexOfKey(timeUs);
3054    if (index >= 0) {
3055        ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index);
3056        stats->mFillBufferDoneTimeUs = ALooper::GetNowUs();
3057
3058        ALOGI("frame PTS %lld: %lld",
3059                timeUs,
3060                stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs);
3061
3062        mCodec->mBufferStats.removeItemsAt(index);
3063        stats = NULL;
3064    }
3065#endif
3066
3067    BufferInfo *info =
3068        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
3069
3070    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
3071
3072    info->mStatus = BufferInfo::OWNED_BY_US;
3073
3074    PortMode mode = getPortMode(kPortIndexOutput);
3075
3076    switch (mode) {
3077        case KEEP_BUFFERS:
3078            break;
3079
3080        case RESUBMIT_BUFFERS:
3081        {
3082            if (rangeLength == 0 && !(flags & OMX_BUFFERFLAG_EOS)) {
3083                ALOGV("[%s] calling fillBuffer %p",
3084                     mCodec->mComponentName.c_str(), info->mBufferID);
3085
3086                CHECK_EQ(mCodec->mOMX->fillBuffer(
3087                            mCodec->mNode, info->mBufferID),
3088                         (status_t)OK);
3089
3090                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
3091                break;
3092            }
3093
3094            sp<AMessage> reply =
3095                new AMessage(kWhatOutputBufferDrained, mCodec->id());
3096
3097            if (!mCodec->mSentFormat) {
3098                mCodec->sendFormatChange(reply);
3099            }
3100
3101            if (mCodec->mUseMetadataOnEncoderOutput) {
3102                native_handle_t* handle =
3103                        *(native_handle_t**)(info->mData->data() + 4);
3104                info->mData->meta()->setPointer("handle", handle);
3105                info->mData->meta()->setInt32("rangeOffset", rangeOffset);
3106                info->mData->meta()->setInt32("rangeLength", rangeLength);
3107            } else {
3108                info->mData->setRange(rangeOffset, rangeLength);
3109            }
3110#if 0
3111            if (mCodec->mNativeWindow == NULL) {
3112                if (IsIDR(info->mData)) {
3113                    ALOGI("IDR frame");
3114                }
3115            }
3116#endif
3117
3118            if (mCodec->mSkipCutBuffer != NULL) {
3119                mCodec->mSkipCutBuffer->submit(info->mData);
3120            }
3121            info->mData->meta()->setInt64("timeUs", timeUs);
3122
3123            sp<AMessage> notify = mCodec->mNotify->dup();
3124            notify->setInt32("what", ACodec::kWhatDrainThisBuffer);
3125            notify->setPointer("buffer-id", info->mBufferID);
3126            notify->setBuffer("buffer", info->mData);
3127            notify->setInt32("flags", flags);
3128
3129            reply->setPointer("buffer-id", info->mBufferID);
3130
3131            notify->setMessage("reply", reply);
3132
3133            notify->post();
3134
3135            info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
3136
3137            if (flags & OMX_BUFFERFLAG_EOS) {
3138                ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str());
3139
3140                sp<AMessage> notify = mCodec->mNotify->dup();
3141                notify->setInt32("what", ACodec::kWhatEOS);
3142                notify->setInt32("err", mCodec->mInputEOSResult);
3143                notify->post();
3144
3145                mCodec->mPortEOS[kPortIndexOutput] = true;
3146            }
3147            break;
3148        }
3149
3150        default:
3151        {
3152            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
3153
3154            CHECK_EQ((status_t)OK,
3155                     mCodec->freeBuffer(kPortIndexOutput, index));
3156            break;
3157        }
3158    }
3159
3160    return true;
3161}
3162
3163void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
3164    IOMX::buffer_id bufferID;
3165    CHECK(msg->findPointer("buffer-id", &bufferID));
3166
3167    ssize_t index;
3168    BufferInfo *info =
3169        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
3170    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
3171
3172    android_native_rect_t crop;
3173    if (msg->findRect("crop",
3174            &crop.left, &crop.top, &crop.right, &crop.bottom)) {
3175        CHECK_EQ(0, native_window_set_crop(
3176                mCodec->mNativeWindow.get(), &crop));
3177    }
3178
3179    int32_t render;
3180    if (mCodec->mNativeWindow != NULL
3181            && msg->findInt32("render", &render) && render != 0
3182            && (info->mData == NULL || info->mData->size() != 0)) {
3183        // The client wants this buffer to be rendered.
3184
3185        status_t err;
3186        if ((err = mCodec->mNativeWindow->queueBuffer(
3187                    mCodec->mNativeWindow.get(),
3188                    info->mGraphicBuffer.get(), -1)) == OK) {
3189            info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
3190        } else {
3191            mCodec->signalError(OMX_ErrorUndefined, err);
3192            info->mStatus = BufferInfo::OWNED_BY_US;
3193        }
3194    } else {
3195        info->mStatus = BufferInfo::OWNED_BY_US;
3196    }
3197
3198    PortMode mode = getPortMode(kPortIndexOutput);
3199
3200    switch (mode) {
3201        case KEEP_BUFFERS:
3202        {
3203            // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
3204
3205            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
3206                // We cannot resubmit the buffer we just rendered, dequeue
3207                // the spare instead.
3208
3209                info = mCodec->dequeueBufferFromNativeWindow();
3210            }
3211            break;
3212        }
3213
3214        case RESUBMIT_BUFFERS:
3215        {
3216            if (!mCodec->mPortEOS[kPortIndexOutput]) {
3217                if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
3218                    // We cannot resubmit the buffer we just rendered, dequeue
3219                    // the spare instead.
3220
3221                    info = mCodec->dequeueBufferFromNativeWindow();
3222                }
3223
3224                if (info != NULL) {
3225                    ALOGV("[%s] calling fillBuffer %p",
3226                         mCodec->mComponentName.c_str(), info->mBufferID);
3227
3228                    CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
3229                             (status_t)OK);
3230
3231                    info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
3232                }
3233            }
3234            break;
3235        }
3236
3237        default:
3238        {
3239            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
3240
3241            CHECK_EQ((status_t)OK,
3242                     mCodec->freeBuffer(kPortIndexOutput, index));
3243            break;
3244        }
3245    }
3246}
3247
3248////////////////////////////////////////////////////////////////////////////////
3249
3250ACodec::UninitializedState::UninitializedState(ACodec *codec)
3251    : BaseState(codec) {
3252}
3253
3254void ACodec::UninitializedState::stateEntered() {
3255    ALOGV("Now uninitialized");
3256
3257    if (mDeathNotifier != NULL) {
3258        mCodec->mOMX->asBinder()->unlinkToDeath(mDeathNotifier);
3259        mDeathNotifier.clear();
3260    }
3261
3262    mCodec->mNativeWindow.clear();
3263    mCodec->mNode = NULL;
3264    mCodec->mOMX.clear();
3265    mCodec->mQuirks = 0;
3266    mCodec->mFlags = 0;
3267    mCodec->mUseMetadataOnEncoderOutput = 0;
3268    mCodec->mComponentName.clear();
3269}
3270
3271bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
3272    bool handled = false;
3273
3274    switch (msg->what()) {
3275        case ACodec::kWhatSetup:
3276        {
3277            onSetup(msg);
3278
3279            handled = true;
3280            break;
3281        }
3282
3283        case ACodec::kWhatAllocateComponent:
3284        {
3285            onAllocateComponent(msg);
3286            handled = true;
3287            break;
3288        }
3289
3290        case ACodec::kWhatShutdown:
3291        {
3292            int32_t keepComponentAllocated;
3293            CHECK(msg->findInt32(
3294                        "keepComponentAllocated", &keepComponentAllocated));
3295            CHECK(!keepComponentAllocated);
3296
3297            sp<AMessage> notify = mCodec->mNotify->dup();
3298            notify->setInt32("what", ACodec::kWhatShutdownCompleted);
3299            notify->post();
3300
3301            handled = true;
3302            break;
3303        }
3304
3305        case ACodec::kWhatFlush:
3306        {
3307            sp<AMessage> notify = mCodec->mNotify->dup();
3308            notify->setInt32("what", ACodec::kWhatFlushCompleted);
3309            notify->post();
3310
3311            handled = true;
3312            break;
3313        }
3314
3315        default:
3316            return BaseState::onMessageReceived(msg);
3317    }
3318
3319    return handled;
3320}
3321
3322void ACodec::UninitializedState::onSetup(
3323        const sp<AMessage> &msg) {
3324    if (onAllocateComponent(msg)
3325            && mCodec->mLoadedState->onConfigureComponent(msg)) {
3326        mCodec->mLoadedState->onStart();
3327    }
3328}
3329
3330bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
3331    ALOGV("onAllocateComponent");
3332
3333    CHECK(mCodec->mNode == NULL);
3334
3335    OMXClient client;
3336    CHECK_EQ(client.connect(), (status_t)OK);
3337
3338    sp<IOMX> omx = client.interface();
3339
3340    sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec->id());
3341
3342    mDeathNotifier = new DeathNotifier(notify);
3343    if (omx->asBinder()->linkToDeath(mDeathNotifier) != OK) {
3344        // This was a local binder, if it dies so do we, we won't care
3345        // about any notifications in the afterlife.
3346        mDeathNotifier.clear();
3347    }
3348
3349    Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs;
3350
3351    AString mime;
3352
3353    AString componentName;
3354    uint32_t quirks = 0;
3355    if (msg->findString("componentName", &componentName)) {
3356        ssize_t index = matchingCodecs.add();
3357        OMXCodec::CodecNameAndQuirks *entry = &matchingCodecs.editItemAt(index);
3358        entry->mName = String8(componentName.c_str());
3359
3360        if (!OMXCodec::findCodecQuirks(
3361                    componentName.c_str(), &entry->mQuirks)) {
3362            entry->mQuirks = 0;
3363        }
3364    } else {
3365        CHECK(msg->findString("mime", &mime));
3366
3367        int32_t encoder;
3368        if (!msg->findInt32("encoder", &encoder)) {
3369            encoder = false;
3370        }
3371
3372        OMXCodec::findMatchingCodecs(
3373                mime.c_str(),
3374                encoder, // createEncoder
3375                NULL,  // matchComponentName
3376                0,     // flags
3377                &matchingCodecs);
3378    }
3379
3380    sp<CodecObserver> observer = new CodecObserver;
3381    IOMX::node_id node = NULL;
3382
3383    for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
3384            ++matchIndex) {
3385        componentName = matchingCodecs.itemAt(matchIndex).mName.string();
3386        quirks = matchingCodecs.itemAt(matchIndex).mQuirks;
3387
3388        pid_t tid = androidGetTid();
3389        int prevPriority = androidGetThreadPriority(tid);
3390        androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
3391        status_t err = omx->allocateNode(componentName.c_str(), observer, &node);
3392        androidSetThreadPriority(tid, prevPriority);
3393
3394        if (err == OK) {
3395            break;
3396        }
3397
3398        node = NULL;
3399    }
3400
3401    if (node == NULL) {
3402        if (!mime.empty()) {
3403            ALOGE("Unable to instantiate a decoder for type '%s'.",
3404                 mime.c_str());
3405        } else {
3406            ALOGE("Unable to instantiate decoder '%s'.", componentName.c_str());
3407        }
3408
3409        mCodec->signalError(OMX_ErrorComponentNotFound);
3410        return false;
3411    }
3412
3413    notify = new AMessage(kWhatOMXMessage, mCodec->id());
3414    observer->setNotificationMessage(notify);
3415
3416    mCodec->mComponentName = componentName;
3417    mCodec->mFlags = 0;
3418
3419    if (componentName.endsWith(".secure")) {
3420        mCodec->mFlags |= kFlagIsSecure;
3421    }
3422
3423    mCodec->mQuirks = quirks;
3424    mCodec->mOMX = omx;
3425    mCodec->mNode = node;
3426
3427    {
3428        sp<AMessage> notify = mCodec->mNotify->dup();
3429        notify->setInt32("what", ACodec::kWhatComponentAllocated);
3430        notify->setString("componentName", mCodec->mComponentName.c_str());
3431        notify->post();
3432    }
3433
3434    mCodec->changeState(mCodec->mLoadedState);
3435
3436    return true;
3437}
3438
3439////////////////////////////////////////////////////////////////////////////////
3440
3441ACodec::LoadedState::LoadedState(ACodec *codec)
3442    : BaseState(codec) {
3443}
3444
3445void ACodec::LoadedState::stateEntered() {
3446    ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
3447
3448    mCodec->mPortEOS[kPortIndexInput] =
3449        mCodec->mPortEOS[kPortIndexOutput] = false;
3450
3451    mCodec->mInputEOSResult = OK;
3452
3453    if (mCodec->mShutdownInProgress) {
3454        bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
3455
3456        mCodec->mShutdownInProgress = false;
3457        mCodec->mKeepComponentAllocated = false;
3458
3459        onShutdown(keepComponentAllocated);
3460    }
3461}
3462
3463void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
3464    if (!keepComponentAllocated) {
3465        CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
3466
3467        mCodec->changeState(mCodec->mUninitializedState);
3468    }
3469
3470    sp<AMessage> notify = mCodec->mNotify->dup();
3471    notify->setInt32("what", ACodec::kWhatShutdownCompleted);
3472    notify->post();
3473}
3474
3475bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
3476    bool handled = false;
3477
3478    switch (msg->what()) {
3479        case ACodec::kWhatConfigureComponent:
3480        {
3481            onConfigureComponent(msg);
3482            handled = true;
3483            break;
3484        }
3485
3486        case ACodec::kWhatCreateInputSurface:
3487        {
3488            onCreateInputSurface(msg);
3489            handled = true;
3490            break;
3491        }
3492
3493        case ACodec::kWhatStart:
3494        {
3495            onStart();
3496            handled = true;
3497            break;
3498        }
3499
3500        case ACodec::kWhatShutdown:
3501        {
3502            int32_t keepComponentAllocated;
3503            CHECK(msg->findInt32(
3504                        "keepComponentAllocated", &keepComponentAllocated));
3505
3506            onShutdown(keepComponentAllocated);
3507
3508            handled = true;
3509            break;
3510        }
3511
3512        case ACodec::kWhatFlush:
3513        {
3514            sp<AMessage> notify = mCodec->mNotify->dup();
3515            notify->setInt32("what", ACodec::kWhatFlushCompleted);
3516            notify->post();
3517
3518            handled = true;
3519            break;
3520        }
3521
3522        default:
3523            return BaseState::onMessageReceived(msg);
3524    }
3525
3526    return handled;
3527}
3528
3529bool ACodec::LoadedState::onConfigureComponent(
3530        const sp<AMessage> &msg) {
3531    ALOGV("onConfigureComponent");
3532
3533    CHECK(mCodec->mNode != NULL);
3534
3535    AString mime;
3536    CHECK(msg->findString("mime", &mime));
3537
3538    status_t err = mCodec->configureCodec(mime.c_str(), msg);
3539
3540    if (err != OK) {
3541        ALOGE("[%s] configureCodec returning error %d",
3542              mCodec->mComponentName.c_str(), err);
3543
3544        mCodec->signalError(OMX_ErrorUndefined, err);
3545        return false;
3546    }
3547
3548    sp<RefBase> obj;
3549    if (msg->findObject("native-window", &obj)
3550            && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) {
3551        sp<NativeWindowWrapper> nativeWindow(
3552                static_cast<NativeWindowWrapper *>(obj.get()));
3553        CHECK(nativeWindow != NULL);
3554        mCodec->mNativeWindow = nativeWindow->getNativeWindow();
3555
3556        native_window_set_scaling_mode(
3557                mCodec->mNativeWindow.get(),
3558                NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
3559    }
3560    CHECK_EQ((status_t)OK, mCodec->initNativeWindow());
3561
3562    {
3563        sp<AMessage> notify = mCodec->mNotify->dup();
3564        notify->setInt32("what", ACodec::kWhatComponentConfigured);
3565        notify->post();
3566    }
3567
3568    return true;
3569}
3570
3571void ACodec::LoadedState::onCreateInputSurface(
3572        const sp<AMessage> &msg) {
3573    ALOGV("onCreateInputSurface");
3574
3575    sp<AMessage> notify = mCodec->mNotify->dup();
3576    notify->setInt32("what", ACodec::kWhatInputSurfaceCreated);
3577
3578    sp<IGraphicBufferProducer> bufferProducer;
3579    status_t err;
3580
3581    err = mCodec->mOMX->createInputSurface(mCodec->mNode, kPortIndexInput,
3582            &bufferProducer);
3583    if (err == OK) {
3584        notify->setObject("input-surface",
3585                new BufferProducerWrapper(bufferProducer));
3586    } else {
3587        // Can't use mCodec->signalError() here -- MediaCodec won't forward
3588        // the error through because it's in the "configured" state.  We
3589        // send a kWhatInputSurfaceCreated with an error value instead.
3590        ALOGE("[%s] onCreateInputSurface returning error %d",
3591                mCodec->mComponentName.c_str(), err);
3592        notify->setInt32("err", err);
3593    }
3594    notify->post();
3595}
3596
3597void ACodec::LoadedState::onStart() {
3598    ALOGV("onStart");
3599
3600    CHECK_EQ(mCodec->mOMX->sendCommand(
3601                mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
3602             (status_t)OK);
3603
3604    mCodec->changeState(mCodec->mLoadedToIdleState);
3605}
3606
3607////////////////////////////////////////////////////////////////////////////////
3608
3609ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
3610    : BaseState(codec) {
3611}
3612
3613void ACodec::LoadedToIdleState::stateEntered() {
3614    ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
3615
3616    status_t err;
3617    if ((err = allocateBuffers()) != OK) {
3618        ALOGE("Failed to allocate buffers after transitioning to IDLE state "
3619             "(error 0x%08x)",
3620             err);
3621
3622        mCodec->signalError(OMX_ErrorUndefined, err);
3623
3624        mCodec->changeState(mCodec->mLoadedState);
3625    }
3626}
3627
3628status_t ACodec::LoadedToIdleState::allocateBuffers() {
3629    status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
3630
3631    if (err != OK) {
3632        return err;
3633    }
3634
3635    return mCodec->allocateBuffersOnPort(kPortIndexOutput);
3636}
3637
3638bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
3639    switch (msg->what()) {
3640        case kWhatShutdown:
3641        {
3642            mCodec->deferMessage(msg);
3643            return true;
3644        }
3645
3646        case kWhatSignalEndOfInputStream:
3647        {
3648            mCodec->onSignalEndOfInputStream();
3649            return true;
3650        }
3651
3652        case kWhatResume:
3653        {
3654            // We'll be active soon enough.
3655            return true;
3656        }
3657
3658        case kWhatFlush:
3659        {
3660            // We haven't even started yet, so we're flushed alright...
3661            sp<AMessage> notify = mCodec->mNotify->dup();
3662            notify->setInt32("what", ACodec::kWhatFlushCompleted);
3663            notify->post();
3664            return true;
3665        }
3666
3667        default:
3668            return BaseState::onMessageReceived(msg);
3669    }
3670}
3671
3672bool ACodec::LoadedToIdleState::onOMXEvent(
3673        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3674    switch (event) {
3675        case OMX_EventCmdComplete:
3676        {
3677            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
3678            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
3679
3680            CHECK_EQ(mCodec->mOMX->sendCommand(
3681                        mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
3682                     (status_t)OK);
3683
3684            mCodec->changeState(mCodec->mIdleToExecutingState);
3685
3686            return true;
3687        }
3688
3689        default:
3690            return BaseState::onOMXEvent(event, data1, data2);
3691    }
3692}
3693
3694////////////////////////////////////////////////////////////////////////////////
3695
3696ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
3697    : BaseState(codec) {
3698}
3699
3700void ACodec::IdleToExecutingState::stateEntered() {
3701    ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
3702}
3703
3704bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
3705    switch (msg->what()) {
3706        case kWhatShutdown:
3707        {
3708            mCodec->deferMessage(msg);
3709            return true;
3710        }
3711
3712        case kWhatResume:
3713        {
3714            // We'll be active soon enough.
3715            return true;
3716        }
3717
3718        case kWhatFlush:
3719        {
3720            // We haven't even started yet, so we're flushed alright...
3721            sp<AMessage> notify = mCodec->mNotify->dup();
3722            notify->setInt32("what", ACodec::kWhatFlushCompleted);
3723            notify->post();
3724
3725            return true;
3726        }
3727
3728        case kWhatSignalEndOfInputStream:
3729        {
3730            mCodec->onSignalEndOfInputStream();
3731            return true;
3732        }
3733
3734        default:
3735            return BaseState::onMessageReceived(msg);
3736    }
3737}
3738
3739bool ACodec::IdleToExecutingState::onOMXEvent(
3740        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3741    switch (event) {
3742        case OMX_EventCmdComplete:
3743        {
3744            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
3745            CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
3746
3747            mCodec->mExecutingState->resume();
3748            mCodec->changeState(mCodec->mExecutingState);
3749
3750            return true;
3751        }
3752
3753        default:
3754            return BaseState::onOMXEvent(event, data1, data2);
3755    }
3756}
3757
3758////////////////////////////////////////////////////////////////////////////////
3759
3760ACodec::ExecutingState::ExecutingState(ACodec *codec)
3761    : BaseState(codec),
3762      mActive(false) {
3763}
3764
3765ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
3766        OMX_U32 portIndex) {
3767    return RESUBMIT_BUFFERS;
3768}
3769
3770void ACodec::ExecutingState::submitOutputBuffers() {
3771    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
3772        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
3773
3774        if (mCodec->mNativeWindow != NULL) {
3775            CHECK(info->mStatus == BufferInfo::OWNED_BY_US
3776                    || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
3777
3778            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
3779                continue;
3780            }
3781        } else {
3782            CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
3783        }
3784
3785        ALOGV("[%s] calling fillBuffer %p",
3786             mCodec->mComponentName.c_str(), info->mBufferID);
3787
3788        CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
3789                 (status_t)OK);
3790
3791        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
3792    }
3793}
3794
3795void ACodec::ExecutingState::resume() {
3796    if (mActive) {
3797        ALOGV("[%s] We're already active, no need to resume.",
3798             mCodec->mComponentName.c_str());
3799
3800        return;
3801    }
3802
3803    submitOutputBuffers();
3804
3805    // Post the first input buffer.
3806    CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
3807    BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0);
3808
3809    postFillThisBuffer(info);
3810
3811    mActive = true;
3812}
3813
3814void ACodec::ExecutingState::stateEntered() {
3815    ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
3816
3817    mCodec->processDeferredMessages();
3818}
3819
3820bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
3821    bool handled = false;
3822
3823    switch (msg->what()) {
3824        case kWhatShutdown:
3825        {
3826            int32_t keepComponentAllocated;
3827            CHECK(msg->findInt32(
3828                        "keepComponentAllocated", &keepComponentAllocated));
3829
3830            mCodec->mShutdownInProgress = true;
3831            mCodec->mKeepComponentAllocated = keepComponentAllocated;
3832
3833            mActive = false;
3834
3835            CHECK_EQ(mCodec->mOMX->sendCommand(
3836                        mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
3837                     (status_t)OK);
3838
3839            mCodec->changeState(mCodec->mExecutingToIdleState);
3840
3841            handled = true;
3842            break;
3843        }
3844
3845        case kWhatFlush:
3846        {
3847            ALOGV("[%s] ExecutingState flushing now "
3848                 "(codec owns %d/%d input, %d/%d output).",
3849                    mCodec->mComponentName.c_str(),
3850                    mCodec->countBuffersOwnedByComponent(kPortIndexInput),
3851                    mCodec->mBuffers[kPortIndexInput].size(),
3852                    mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
3853                    mCodec->mBuffers[kPortIndexOutput].size());
3854
3855            mActive = false;
3856
3857            CHECK_EQ(mCodec->mOMX->sendCommand(
3858                        mCodec->mNode, OMX_CommandFlush, OMX_ALL),
3859                     (status_t)OK);
3860
3861            mCodec->changeState(mCodec->mFlushingState);
3862            handled = true;
3863            break;
3864        }
3865
3866        case kWhatResume:
3867        {
3868            resume();
3869
3870            handled = true;
3871            break;
3872        }
3873
3874        case kWhatRequestIDRFrame:
3875        {
3876            status_t err = mCodec->requestIDRFrame();
3877            if (err != OK) {
3878                ALOGW("Requesting an IDR frame failed.");
3879            }
3880
3881            handled = true;
3882            break;
3883        }
3884
3885        case kWhatSetParameters:
3886        {
3887            sp<AMessage> params;
3888            CHECK(msg->findMessage("params", &params));
3889
3890            status_t err = mCodec->setParameters(params);
3891
3892            sp<AMessage> reply;
3893            if (msg->findMessage("reply", &reply)) {
3894                reply->setInt32("err", err);
3895                reply->post();
3896            }
3897
3898            handled = true;
3899            break;
3900        }
3901
3902        case ACodec::kWhatSignalEndOfInputStream:
3903        {
3904            mCodec->onSignalEndOfInputStream();
3905            handled = true;
3906            break;
3907        }
3908
3909        default:
3910            handled = BaseState::onMessageReceived(msg);
3911            break;
3912    }
3913
3914    return handled;
3915}
3916
3917status_t ACodec::setParameters(const sp<AMessage> &params) {
3918    int32_t videoBitrate;
3919    if (params->findInt32("videoBitrate", &videoBitrate)) {
3920        OMX_VIDEO_CONFIG_BITRATETYPE configParams;
3921        InitOMXParams(&configParams);
3922        configParams.nPortIndex = kPortIndexOutput;
3923        configParams.nEncodeBitrate = videoBitrate;
3924
3925        status_t err = mOMX->setConfig(
3926                mNode,
3927                OMX_IndexConfigVideoBitrate,
3928                &configParams,
3929                sizeof(configParams));
3930
3931        if (err != OK) {
3932            ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d",
3933                   videoBitrate, err);
3934
3935            return err;
3936        }
3937    }
3938
3939    return OK;
3940}
3941
3942void ACodec::onSignalEndOfInputStream() {
3943    sp<AMessage> notify = mNotify->dup();
3944    notify->setInt32("what", ACodec::kWhatSignaledInputEOS);
3945
3946    status_t err = mOMX->signalEndOfInputStream(mNode);
3947    if (err != OK) {
3948        notify->setInt32("err", err);
3949    }
3950    notify->post();
3951}
3952
3953bool ACodec::ExecutingState::onOMXEvent(
3954        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3955    switch (event) {
3956        case OMX_EventPortSettingsChanged:
3957        {
3958            CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
3959
3960            if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
3961                CHECK_EQ(mCodec->mOMX->sendCommand(
3962                            mCodec->mNode,
3963                            OMX_CommandPortDisable, kPortIndexOutput),
3964                         (status_t)OK);
3965
3966                mCodec->freeOutputBuffersNotOwnedByComponent();
3967
3968                mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
3969            } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
3970                mCodec->mSentFormat = false;
3971            } else {
3972                ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
3973                     mCodec->mComponentName.c_str(), data2);
3974            }
3975
3976            return true;
3977        }
3978
3979        case OMX_EventBufferFlag:
3980        {
3981            return true;
3982        }
3983
3984        default:
3985            return BaseState::onOMXEvent(event, data1, data2);
3986    }
3987}
3988
3989////////////////////////////////////////////////////////////////////////////////
3990
3991ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
3992        ACodec *codec)
3993    : BaseState(codec) {
3994}
3995
3996ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
3997        OMX_U32 portIndex) {
3998    if (portIndex == kPortIndexOutput) {
3999        return FREE_BUFFERS;
4000    }
4001
4002    CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
4003
4004    return RESUBMIT_BUFFERS;
4005}
4006
4007bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
4008        const sp<AMessage> &msg) {
4009    bool handled = false;
4010
4011    switch (msg->what()) {
4012        case kWhatFlush:
4013        case kWhatShutdown:
4014        case kWhatResume:
4015        {
4016            if (msg->what() == kWhatResume) {
4017                ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
4018            }
4019
4020            mCodec->deferMessage(msg);
4021            handled = true;
4022            break;
4023        }
4024
4025        default:
4026            handled = BaseState::onMessageReceived(msg);
4027            break;
4028    }
4029
4030    return handled;
4031}
4032
4033void ACodec::OutputPortSettingsChangedState::stateEntered() {
4034    ALOGV("[%s] Now handling output port settings change",
4035         mCodec->mComponentName.c_str());
4036}
4037
4038bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
4039        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
4040    switch (event) {
4041        case OMX_EventCmdComplete:
4042        {
4043            if (data1 == (OMX_U32)OMX_CommandPortDisable) {
4044                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
4045
4046                ALOGV("[%s] Output port now disabled.",
4047                        mCodec->mComponentName.c_str());
4048
4049                CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
4050                mCodec->mDealer[kPortIndexOutput].clear();
4051
4052                CHECK_EQ(mCodec->mOMX->sendCommand(
4053                            mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
4054                         (status_t)OK);
4055
4056                status_t err;
4057                if ((err = mCodec->allocateBuffersOnPort(
4058                                kPortIndexOutput)) != OK) {
4059                    ALOGE("Failed to allocate output port buffers after "
4060                         "port reconfiguration (error 0x%08x)",
4061                         err);
4062
4063                    mCodec->signalError(OMX_ErrorUndefined, err);
4064
4065                    // This is technically not correct, but appears to be
4066                    // the only way to free the component instance.
4067                    // Controlled transitioning from excecuting->idle
4068                    // and idle->loaded seem impossible probably because
4069                    // the output port never finishes re-enabling.
4070                    mCodec->mShutdownInProgress = true;
4071                    mCodec->mKeepComponentAllocated = false;
4072                    mCodec->changeState(mCodec->mLoadedState);
4073                }
4074
4075                return true;
4076            } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
4077                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
4078
4079                mCodec->mSentFormat = false;
4080
4081                ALOGV("[%s] Output port now reenabled.",
4082                        mCodec->mComponentName.c_str());
4083
4084                if (mCodec->mExecutingState->active()) {
4085                    mCodec->mExecutingState->submitOutputBuffers();
4086                }
4087
4088                mCodec->changeState(mCodec->mExecutingState);
4089
4090                return true;
4091            }
4092
4093            return false;
4094        }
4095
4096        default:
4097            return false;
4098    }
4099}
4100
4101////////////////////////////////////////////////////////////////////////////////
4102
4103ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
4104    : BaseState(codec),
4105      mComponentNowIdle(false) {
4106}
4107
4108bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
4109    bool handled = false;
4110
4111    switch (msg->what()) {
4112        case kWhatFlush:
4113        {
4114            // Don't send me a flush request if you previously wanted me
4115            // to shutdown.
4116            TRESPASS();
4117            break;
4118        }
4119
4120        case kWhatShutdown:
4121        {
4122            // We're already doing that...
4123
4124            handled = true;
4125            break;
4126        }
4127
4128        default:
4129            handled = BaseState::onMessageReceived(msg);
4130            break;
4131    }
4132
4133    return handled;
4134}
4135
4136void ACodec::ExecutingToIdleState::stateEntered() {
4137    ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
4138
4139    mComponentNowIdle = false;
4140    mCodec->mSentFormat = false;
4141}
4142
4143bool ACodec::ExecutingToIdleState::onOMXEvent(
4144        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
4145    switch (event) {
4146        case OMX_EventCmdComplete:
4147        {
4148            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
4149            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
4150
4151            mComponentNowIdle = true;
4152
4153            changeStateIfWeOwnAllBuffers();
4154
4155            return true;
4156        }
4157
4158        case OMX_EventPortSettingsChanged:
4159        case OMX_EventBufferFlag:
4160        {
4161            // We're shutting down and don't care about this anymore.
4162            return true;
4163        }
4164
4165        default:
4166            return BaseState::onOMXEvent(event, data1, data2);
4167    }
4168}
4169
4170void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
4171    if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
4172        CHECK_EQ(mCodec->mOMX->sendCommand(
4173                    mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
4174                 (status_t)OK);
4175
4176        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
4177        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
4178
4179        if (mCodec->mFlags & kFlagIsSecure && mCodec->mNativeWindow != NULL) {
4180            // We push enough 1x1 blank buffers to ensure that one of
4181            // them has made it to the display.  This allows the OMX
4182            // component teardown to zero out any protected buffers
4183            // without the risk of scanning out one of those buffers.
4184            mCodec->pushBlankBuffersToNativeWindow();
4185        }
4186
4187        mCodec->changeState(mCodec->mIdleToLoadedState);
4188    }
4189}
4190
4191void ACodec::ExecutingToIdleState::onInputBufferFilled(
4192        const sp<AMessage> &msg) {
4193    BaseState::onInputBufferFilled(msg);
4194
4195    changeStateIfWeOwnAllBuffers();
4196}
4197
4198void ACodec::ExecutingToIdleState::onOutputBufferDrained(
4199        const sp<AMessage> &msg) {
4200    BaseState::onOutputBufferDrained(msg);
4201
4202    changeStateIfWeOwnAllBuffers();
4203}
4204
4205////////////////////////////////////////////////////////////////////////////////
4206
4207ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
4208    : BaseState(codec) {
4209}
4210
4211bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
4212    bool handled = false;
4213
4214    switch (msg->what()) {
4215        case kWhatShutdown:
4216        {
4217            // We're already doing that...
4218
4219            handled = true;
4220            break;
4221        }
4222
4223        case kWhatFlush:
4224        {
4225            // Don't send me a flush request if you previously wanted me
4226            // to shutdown.
4227            TRESPASS();
4228            break;
4229        }
4230
4231        default:
4232            handled = BaseState::onMessageReceived(msg);
4233            break;
4234    }
4235
4236    return handled;
4237}
4238
4239void ACodec::IdleToLoadedState::stateEntered() {
4240    ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
4241}
4242
4243bool ACodec::IdleToLoadedState::onOMXEvent(
4244        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
4245    switch (event) {
4246        case OMX_EventCmdComplete:
4247        {
4248            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
4249            CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
4250
4251            mCodec->changeState(mCodec->mLoadedState);
4252
4253            return true;
4254        }
4255
4256        default:
4257            return BaseState::onOMXEvent(event, data1, data2);
4258    }
4259}
4260
4261////////////////////////////////////////////////////////////////////////////////
4262
4263ACodec::FlushingState::FlushingState(ACodec *codec)
4264    : BaseState(codec) {
4265}
4266
4267void ACodec::FlushingState::stateEntered() {
4268    ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
4269
4270    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
4271}
4272
4273bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
4274    bool handled = false;
4275
4276    switch (msg->what()) {
4277        case kWhatShutdown:
4278        {
4279            mCodec->deferMessage(msg);
4280            break;
4281        }
4282
4283        case kWhatFlush:
4284        {
4285            // We're already doing this right now.
4286            handled = true;
4287            break;
4288        }
4289
4290        default:
4291            handled = BaseState::onMessageReceived(msg);
4292            break;
4293    }
4294
4295    return handled;
4296}
4297
4298bool ACodec::FlushingState::onOMXEvent(
4299        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
4300    ALOGV("[%s] FlushingState onOMXEvent(%d,%ld)",
4301            mCodec->mComponentName.c_str(), event, data1);
4302
4303    switch (event) {
4304        case OMX_EventCmdComplete:
4305        {
4306            CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
4307
4308            if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
4309                CHECK(!mFlushComplete[data2]);
4310                mFlushComplete[data2] = true;
4311
4312                if (mFlushComplete[kPortIndexInput]
4313                        && mFlushComplete[kPortIndexOutput]) {
4314                    changeStateIfWeOwnAllBuffers();
4315                }
4316            } else {
4317                CHECK_EQ(data2, OMX_ALL);
4318                CHECK(mFlushComplete[kPortIndexInput]);
4319                CHECK(mFlushComplete[kPortIndexOutput]);
4320
4321                changeStateIfWeOwnAllBuffers();
4322            }
4323
4324            return true;
4325        }
4326
4327        case OMX_EventPortSettingsChanged:
4328        {
4329            sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id());
4330            msg->setInt32("type", omx_message::EVENT);
4331            msg->setPointer("node", mCodec->mNode);
4332            msg->setInt32("event", event);
4333            msg->setInt32("data1", data1);
4334            msg->setInt32("data2", data2);
4335
4336            ALOGV("[%s] Deferring OMX_EventPortSettingsChanged",
4337                 mCodec->mComponentName.c_str());
4338
4339            mCodec->deferMessage(msg);
4340
4341            return true;
4342        }
4343
4344        default:
4345            return BaseState::onOMXEvent(event, data1, data2);
4346    }
4347
4348    return true;
4349}
4350
4351void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
4352    BaseState::onOutputBufferDrained(msg);
4353
4354    changeStateIfWeOwnAllBuffers();
4355}
4356
4357void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
4358    BaseState::onInputBufferFilled(msg);
4359
4360    changeStateIfWeOwnAllBuffers();
4361}
4362
4363void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
4364    if (mFlushComplete[kPortIndexInput]
4365            && mFlushComplete[kPortIndexOutput]
4366            && mCodec->allYourBuffersAreBelongToUs()) {
4367        // We now own all buffers except possibly those still queued with
4368        // the native window for rendering. Let's get those back as well.
4369        mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs();
4370
4371        sp<AMessage> notify = mCodec->mNotify->dup();
4372        notify->setInt32("what", ACodec::kWhatFlushCompleted);
4373        notify->post();
4374
4375        mCodec->mPortEOS[kPortIndexInput] =
4376            mCodec->mPortEOS[kPortIndexOutput] = false;
4377
4378        mCodec->mInputEOSResult = OK;
4379
4380        if (mCodec->mSkipCutBuffer != NULL) {
4381            mCodec->mSkipCutBuffer->clear();
4382        }
4383
4384        mCodec->changeState(mCodec->mExecutingState);
4385    }
4386}
4387
4388}  // namespace android
4389