ACodec.cpp revision cd39746f8d83bb3f12e8f613e77c3c3b5f77c077
1a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch/*
2a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch * Copyright (C) 2010 The Android Open Source Project
3a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch *
4a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch * Licensed under the Apache License, Version 2.0 (the "License");
5a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch * you may not use this file except in compliance with the License.
6a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch * You may obtain a copy of the License at
7a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch *
8a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch *      http://www.apache.org/licenses/LICENSE-2.0
9a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch *
10a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch * Unless required by applicable law or agreed to in writing, software
11a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch * distributed under the License is distributed on an "AS IS" BASIS,
12a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch * See the License for the specific language governing permissions and
14a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch * limitations under the License.
15a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch */
16a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
17a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch//#define LOG_NDEBUG 0
18a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#define LOG_TAG "ACodec"
19a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
20a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#ifdef __LP64__
21a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
22a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#endif
23a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
24a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <inttypes.h>
25a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <utils/Trace.h>
26a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
27a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <media/stagefright/ACodec.h>
28a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
29a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <binder/MemoryDealer.h>
30a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
31a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <media/stagefright/foundation/hexdump.h>
32a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <media/stagefright/foundation/ABuffer.h>
33a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <media/stagefright/foundation/ADebug.h>
34a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <media/stagefright/foundation/AMessage.h>
35a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
36a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <media/stagefright/BufferProducerWrapper.h>
375d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include <media/stagefright/MediaCodecList.h>
38a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <media/stagefright/MediaDefs.h>
39a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <media/stagefright/NativeWindowWrapper.h>
40a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <media/stagefright/OMXClient.h>
41a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <media/stagefright/OMXCodec.h>
42a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
43a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <media/hardware/HardwareAPI.h>
44c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
45a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <OMX_AudioExt.h>
46a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <OMX_VideoExt.h>
47a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <OMX_Component.h>
48f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#include <OMX_IndexExt.h>
49f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
50f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#include "include/avc_utils.h"
51f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
52f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liunamespace android {
53f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
54f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// OMX errors are directly mapped into status_t range if
55f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// there is no corresponding MediaError status code.
56f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// Use the statusFromOMXError(int32_t omxError) function.
57f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu//
58f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// Currently this is a direct map.
59f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// See frameworks/native/include/media/openmax/OMX_Core.h
60f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu//
61f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// Vendor OMX errors     from 0x90000000 - 0x9000FFFF
62f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// Extension OMX errors  from 0x8F000000 - 0x90000000
63f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// Standard OMX errors   from 0x80001000 - 0x80001024 (0x80001024 current)
64f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu//
65f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
66f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// returns true if err is a recognized OMX error code.
67f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// as OMX error is OMX_S32, this is an int32_t type
68f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liustatic inline bool isOMXError(int32_t err) {
69f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    return (ERROR_CODEC_MIN <= err && err <= ERROR_CODEC_MAX);
70f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu}
71f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
725d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)// converts an OMX error to a status_t
735d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)static inline status_t statusFromOMXError(int32_t omxError) {
74197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    switch (omxError) {
75197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    case OMX_ErrorInvalidComponentName:
76197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    case OMX_ErrorComponentNotFound:
77197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return NAME_NOT_FOUND; // can trigger illegal argument error for provided names.
78197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    default:
795d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        return isOMXError(omxError) ? omxError : 0; // no translation required
805d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    }
815d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)}
825d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
835d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)// checks and converts status_t to a non-side-effect status_t
845d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)static inline status_t makeNoSideEffectStatus(status_t err) {
855d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    switch (err) {
865d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // the following errors have side effects and may come
875d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // from other code modules. Remap for safety reasons.
885d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    case INVALID_OPERATION:
895d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    case DEAD_OBJECT:
90197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return UNKNOWN_ERROR;
91197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    default:
92197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return err;
93197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
94197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}
955d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
965d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)template<class T>
975d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)static void InitOMXParams(T *params) {
985d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    params->nSize = sizeof(T);
995d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    params->nVersion.s.nVersionMajor = 1;
1005d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    params->nVersion.s.nVersionMinor = 0;
1015d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    params->nVersion.s.nRevision = 0;
1025d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    params->nVersion.s.nStep = 0;
1035d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)}
1045d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
105197021e6b966cfb06891637935ef33fff06433d1Ben Murdochstruct CodecObserver : public BnOMXObserver {
106197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    CodecObserver() {}
1075d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
1085d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    void setNotificationMessage(const sp<AMessage> &msg) {
1095d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        mNotify = msg;
1105d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    }
111a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
112a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    // from IOMXObserver
113a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual void onMessage(const omx_message &omx_msg) {
114a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        sp<AMessage> msg = mNotify->dup();
115a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
116a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        msg->setInt32("type", omx_msg.type);
117a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        msg->setInt32("node", omx_msg.node);
118a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
119a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        switch (omx_msg.type) {
120a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            case omx_message::EVENT:
121a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            {
122a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                msg->setInt32("event", omx_msg.u.event_data.event);
123a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                msg->setInt32("data1", omx_msg.u.event_data.data1);
124a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                msg->setInt32("data2", omx_msg.u.event_data.data2);
125a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                break;
126a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            }
127a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
128a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            case omx_message::EMPTY_BUFFER_DONE:
129a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            {
130a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                msg->setInt32("buffer", omx_msg.u.buffer_data.buffer);
131a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                break;
132a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            }
133a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
134a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            case omx_message::FILL_BUFFER_DONE:
135a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            {
136a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                msg->setInt32(
137a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                        "buffer", omx_msg.u.extended_buffer_data.buffer);
138a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                msg->setInt32(
139a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                        "range_offset",
140a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                        omx_msg.u.extended_buffer_data.range_offset);
141a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                msg->setInt32(
142a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                        "range_length",
143a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                        omx_msg.u.extended_buffer_data.range_length);
144a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                msg->setInt32(
145a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                        "flags",
146a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                        omx_msg.u.extended_buffer_data.flags);
147a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                msg->setInt64(
148a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                        "timestamp",
149a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                        omx_msg.u.extended_buffer_data.timestamp);
150a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                break;
151a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            }
152a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
153a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            default:
154a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                TRESPASS();
155a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                break;
156a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        }
157a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
158a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        msg->post();
159a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
160a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
161a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprotected:
162a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual ~CodecObserver() {}
163a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
164a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprivate:
165a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    sp<AMessage> mNotify;
166a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
167a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    DISALLOW_EVIL_CONSTRUCTORS(CodecObserver);
168a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch};
169a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
170a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch////////////////////////////////////////////////////////////////////////////////
171a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
172a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstruct ACodec::BaseState : public AState {
173a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    BaseState(ACodec *codec, const sp<AState> &parentState = NULL);
174a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
175a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprotected:
176a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    enum PortMode {
177a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        KEEP_BUFFERS,
178a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        RESUBMIT_BUFFERS,
179a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        FREE_BUFFERS,
180a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    };
181a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
182a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    ACodec *mCodec;
183a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
184a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual PortMode getPortMode(OMX_U32 portIndex);
185a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
186a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual bool onMessageReceived(const sp<AMessage> &msg);
187a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
188a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
189a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
190a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
191a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual void onInputBufferFilled(const sp<AMessage> &msg);
192a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
193a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    void postFillThisBuffer(BufferInfo *info);
194a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
195a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprivate:
196a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    bool onOMXMessage(const sp<AMessage> &msg);
197a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
198a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID);
199a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
200a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    bool onOMXFillBufferDone(
201a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            IOMX::buffer_id bufferID,
202a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            size_t rangeOffset, size_t rangeLength,
203a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            OMX_U32 flags,
204a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            int64_t timeUs);
205a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
206197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    void getMoreInputDataIfPossible();
207a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
208a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    DISALLOW_EVIL_CONSTRUCTORS(BaseState);
209a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch};
210a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
211a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch////////////////////////////////////////////////////////////////////////////////
212a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
213a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstruct ACodec::DeathNotifier : public IBinder::DeathRecipient {
214a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    DeathNotifier(const sp<AMessage> &notify)
215a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        : mNotify(notify) {
216a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
217a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
218a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual void binderDied(const wp<IBinder> &) {
219197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        mNotify->post();
220a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
221a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
222a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprotected:
223197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    virtual ~DeathNotifier() {}
224197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
225197021e6b966cfb06891637935ef33fff06433d1Ben Murdochprivate:
226a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    sp<AMessage> mNotify;
227a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
228a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    DISALLOW_EVIL_CONSTRUCTORS(DeathNotifier);
229a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch};
230a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
231a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstruct ACodec::UninitializedState : public ACodec::BaseState {
232a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    UninitializedState(ACodec *codec);
233a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
234a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprotected:
235a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual bool onMessageReceived(const sp<AMessage> &msg);
236a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual void stateEntered();
237197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
238a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprivate:
239a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    void onSetup(const sp<AMessage> &msg);
240a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    bool onAllocateComponent(const sp<AMessage> &msg);
241a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
242a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    sp<DeathNotifier> mDeathNotifier;
243a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
244a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    DISALLOW_EVIL_CONSTRUCTORS(UninitializedState);
245a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch};
246a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
247a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch////////////////////////////////////////////////////////////////////////////////
248a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
249a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstruct ACodec::LoadedState : public ACodec::BaseState {
250a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    LoadedState(ACodec *codec);
251a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
252a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprotected:
253197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    virtual bool onMessageReceived(const sp<AMessage> &msg);
254197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    virtual void stateEntered();
255197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
256197021e6b966cfb06891637935ef33fff06433d1Ben Murdochprivate:
257197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    friend struct ACodec::UninitializedState;
258197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
259197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    bool onConfigureComponent(const sp<AMessage> &msg);
260197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    void onCreateInputSurface(const sp<AMessage> &msg);
261a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    void onStart();
262a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    void onShutdown(bool keepComponentAllocated);
263a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
264a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    DISALLOW_EVIL_CONSTRUCTORS(LoadedState);
265a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch};
266a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
267a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch////////////////////////////////////////////////////////////////////////////////
268a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
269a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstruct ACodec::LoadedToIdleState : public ACodec::BaseState {
270a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    LoadedToIdleState(ACodec *codec);
271a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
272a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprotected:
273a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual bool onMessageReceived(const sp<AMessage> &msg);
274a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
275a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual void stateEntered();
276a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
277a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprivate:
278a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    status_t allocateBuffers();
279197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
280a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState);
281a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch};
282a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
283a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch////////////////////////////////////////////////////////////////////////////////
284a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
285a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstruct ACodec::IdleToExecutingState : public ACodec::BaseState {
286a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    IdleToExecutingState(ACodec *codec);
287a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
288a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprotected:
289a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual bool onMessageReceived(const sp<AMessage> &msg);
290a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
291a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual void stateEntered();
292a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
293a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprivate:
294a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState);
295a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch};
296a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
297a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch////////////////////////////////////////////////////////////////////////////////
298a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
299a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstruct ACodec::ExecutingState : public ACodec::BaseState {
300a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    ExecutingState(ACodec *codec);
301a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
302a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    void submitRegularOutputBuffers();
303a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    void submitOutputMetaBuffers();
304a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    void submitOutputBuffers();
305a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
306a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    // Submit output buffers to the decoder, submit input buffers to client
307a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    // to fill with data.
308a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    void resume();
309a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
310a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    // Returns true iff input and output buffers are in play.
311a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    bool active() const { return mActive; }
312f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
313a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprotected:
314f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    virtual PortMode getPortMode(OMX_U32 portIndex);
315a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual bool onMessageReceived(const sp<AMessage> &msg);
316a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual void stateEntered();
317a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
318a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
3195d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
320a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprivate:
321a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    bool mActive;
322a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
323a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    DISALLOW_EVIL_CONSTRUCTORS(ExecutingState);
324a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch};
3255d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
326a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch////////////////////////////////////////////////////////////////////////////////
327a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
3285d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)struct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState {
329a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    OutputPortSettingsChangedState(ACodec *codec);
330a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
3315d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)protected:
332a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual PortMode getPortMode(OMX_U32 portIndex);
333a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual bool onMessageReceived(const sp<AMessage> &msg);
3345d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    virtual void stateEntered();
335a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
336a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
3375d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
338a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprivate:
339a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState);
340a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch};
341a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
342a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch////////////////////////////////////////////////////////////////////////////////
3435d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
344a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstruct ACodec::ExecutingToIdleState : public ACodec::BaseState {
345a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    ExecutingToIdleState(ACodec *codec);
346a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
347a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprotected:
348a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual bool onMessageReceived(const sp<AMessage> &msg);
349a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual void stateEntered();
350a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
351a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
352a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
353a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
354a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual void onInputBufferFilled(const sp<AMessage> &msg);
355a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
356a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprivate:
357a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    void changeStateIfWeOwnAllBuffers();
358a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
359a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    bool mComponentNowIdle;
360a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
361a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState);
362a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch};
363a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
364a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch////////////////////////////////////////////////////////////////////////////////
365a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
366f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liustruct ACodec::IdleToLoadedState : public ACodec::BaseState {
367f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    IdleToLoadedState(ACodec *codec);
368f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
369e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)protected:
3705d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    virtual bool onMessageReceived(const sp<AMessage> &msg);
371f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    virtual void stateEntered();
372f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
373f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
374a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
375a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprivate:
376a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState);
377a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch};
378a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
379a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch////////////////////////////////////////////////////////////////////////////////
380a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
381a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstruct ACodec::FlushingState : public ACodec::BaseState {
382a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    FlushingState(ACodec *codec);
383a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
384a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprotected:
385a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual bool onMessageReceived(const sp<AMessage> &msg);
386a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual void stateEntered();
387a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
388a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
389a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
390a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
391a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    virtual void onInputBufferFilled(const sp<AMessage> &msg);
392a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
393a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprivate:
3945d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    bool mFlushComplete[2];
395a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
396a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    void changeStateIfWeOwnAllBuffers();
397a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
398a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    DISALLOW_EVIL_CONSTRUCTORS(FlushingState);
399a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch};
400a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
401a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch////////////////////////////////////////////////////////////////////////////////
4025d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
403a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben MurdochACodec::ACodec()
404a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    : mQuirks(0),
405a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch      mNode(0),
406a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch      mSentFormat(false),
407a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch      mIsEncoder(false),
408a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch      mUseMetadataOnEncoderOutput(false),
409a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch      mShutdownInProgress(false),
4105d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)      mExplicitShutdown(false),
411a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch      mEncoderDelay(0),
412a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch      mEncoderPadding(0),
413a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch      mRotationDegrees(0),
414a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch      mChannelMaskPresent(false),
415a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch      mChannelMask(0),
416a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch      mDequeueCounter(0),
417a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch      mStoreMetaDataInOutputBuffers(false),
4185d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)      mMetaDataBuffersToSubmit(0),
419a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch      mRepeatFrameDelayUs(-1ll),
420a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch      mMaxPtsGapUs(-1ll),
421a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch      mTimePerFrameUs(-1ll),
422a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch      mTimePerCaptureUs(-1ll),
423a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch      mCreateInputBuffersSuspended(false) {
424a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    mUninitializedState = new UninitializedState(this);
425e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    mLoadedState = new LoadedState(this);
4265d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    mLoadedToIdleState = new LoadedToIdleState(this);
4275d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    mIdleToExecutingState = new IdleToExecutingState(this);
4285d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    mExecutingState = new ExecutingState(this);
4295d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
4305d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    mOutputPortSettingsChangedState =
4315d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        new OutputPortSettingsChangedState(this);
4325d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
4335d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    mExecutingToIdleState = new ExecutingToIdleState(this);
4345d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    mIdleToLoadedState = new IdleToLoadedState(this);
4355d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    mFlushingState = new FlushingState(this);
436a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
437a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false;
438a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    mInputEOSResult = OK;
439a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
440a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    changeState(mUninitializedState);
441a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
442a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
443a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben MurdochACodec::~ACodec() {
444a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
445a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
446a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochvoid ACodec::setNotificationMessage(const sp<AMessage> &msg) {
447a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    mNotify = msg;
448a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
449a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
450a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochvoid ACodec::initiateSetup(const sp<AMessage> &msg) {
451a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    msg->setWhat(kWhatSetup);
452a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    msg->setTarget(id());
453a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    msg->post();
454a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
455a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
456a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochvoid ACodec::signalSetParameters(const sp<AMessage> &params) {
457a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    sp<AMessage> msg = new AMessage(kWhatSetParameters, id());
458f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    msg->setMessage("params", params);
459f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    msg->post();
460f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu}
461f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
462a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochvoid ACodec::initiateAllocateComponent(const sp<AMessage> &msg) {
463a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    msg->setWhat(kWhatAllocateComponent);
464a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    msg->setTarget(id());
465a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    msg->post();
466a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
467a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
4685d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)void ACodec::initiateConfigureComponent(const sp<AMessage> &msg) {
4695d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    msg->setWhat(kWhatConfigureComponent);
470e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    msg->setTarget(id());
4715d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    msg->post();
4725d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)}
4735d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
4745d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)void ACodec::initiateCreateInputSurface() {
475a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    (new AMessage(kWhatCreateInputSurface, id()))->post();
476a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
477a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
478a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochvoid ACodec::signalEndOfInputStream() {
479a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    (new AMessage(kWhatSignalEndOfInputStream, id()))->post();
480a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
481a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
482a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochvoid ACodec::initiateStart() {
483a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    (new AMessage(kWhatStart, id()))->post();
484a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
485a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
486a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochvoid ACodec::signalFlush() {
487a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    ALOGV("[%s] signalFlush", mComponentName.c_str());
488a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    (new AMessage(kWhatFlush, id()))->post();
489a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
490a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
4916f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdochvoid ACodec::signalResume() {
4926f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    (new AMessage(kWhatResume, id()))->post();
4936f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch}
4946f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch
4956f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdochvoid ACodec::initiateShutdown(bool keepComponentAllocated) {
4966f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    sp<AMessage> msg = new AMessage(kWhatShutdown, id());
497323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    msg->setInt32("keepComponentAllocated", keepComponentAllocated);
498323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    msg->post();
499323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)}
500323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
501323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)void ACodec::signalRequestIDRFrame() {
502323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    (new AMessage(kWhatRequestIDRFrame, id()))->post();
503f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu}
504f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
505f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
506a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// Some codecs may return input buffers before having them processed.
507a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// This causes a halt if we already signaled an EOS on the input
508a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// port.  For now keep submitting an output buffer if there was an
509a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// EOS on the input port, but not yet on the output port.
510a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochvoid ACodec::signalSubmitOutputMetaDataBufferIfEOS_workaround() {
511a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (mPortEOS[kPortIndexInput] && !mPortEOS[kPortIndexOutput] &&
512a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            mMetaDataBuffersToSubmit > 0) {
513a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        (new AMessage(kWhatSubmitOutputMetaDataBufferIfEOS, id()))->post();
514a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
515a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
516a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
517a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstatus_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
518a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
519a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
520a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    CHECK(mDealer[portIndex] == NULL);
521a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    CHECK(mBuffers[portIndex].isEmpty());
522a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
523a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    status_t err;
524a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
525a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        if (mStoreMetaDataInOutputBuffers) {
526a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            err = allocateOutputMetaDataBuffers();
527a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        } else {
528a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            err = allocateOutputBuffersFromNativeWindow();
529a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        }
530a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    } else {
531a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        OMX_PARAM_PORTDEFINITIONTYPE def;
532a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        InitOMXParams(&def);
533a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        def.nPortIndex = portIndex;
534a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
535a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        err = mOMX->getParameter(
536a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
537a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
538a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        if (err == OK) {
539a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            ALOGV("[%s] Allocating %u buffers of size %u on %s port",
540a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                    mComponentName.c_str(),
541a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                    def.nBufferCountActual, def.nBufferSize,
542a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                    portIndex == kPortIndexInput ? "input" : "output");
543a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
544a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            size_t totalSize = def.nBufferCountActual * def.nBufferSize;
545a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec");
546a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
547a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
548a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
549a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                CHECK(mem.get() != NULL);
550a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
551a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                BufferInfo info;
552a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                info.mStatus = BufferInfo::OWNED_BY_US;
553a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
554a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                uint32_t requiresAllocateBufferBit =
555a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                    (portIndex == kPortIndexInput)
556a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                        ? OMXCodec::kRequiresAllocateBufferOnInputPorts
557a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                        : OMXCodec::kRequiresAllocateBufferOnOutputPorts;
558a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
559a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                if ((portIndex == kPortIndexInput && (mFlags & kFlagIsSecure))
560a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                        || mUseMetadataOnEncoderOutput) {
561a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                    mem.clear();
562a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
563a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                    void *ptr;
564a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                    err = mOMX->allocateBuffer(
565a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                            mNode, portIndex, def.nBufferSize, &info.mBufferID,
566a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                            &ptr);
567a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
568a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                    int32_t bufSize = mUseMetadataOnEncoderOutput ?
569a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                            (4 + sizeof(buffer_handle_t)) : def.nBufferSize;
570a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
571a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                    info.mData = new ABuffer(ptr, bufSize);
572a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                } else if (mQuirks & requiresAllocateBufferBit) {
573a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                    err = mOMX->allocateBufferWithBackup(
574a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                            mNode, portIndex, mem, &info.mBufferID);
575a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                } else {
576a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                    err = mOMX->useBuffer(mNode, portIndex, mem, &info.mBufferID);
577a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                }
578a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
579a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                if (mem != NULL) {
580a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                    info.mData = new ABuffer(mem->pointer(), def.nBufferSize);
581a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                }
582a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
583a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                mBuffers[portIndex].push(info);
584a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            }
585a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        }
586a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
587a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
588a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (err != OK) {
589a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        return err;
590a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
591a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
592a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    sp<AMessage> notify = mNotify->dup();
593a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    notify->setInt32("what", CodecBase::kWhatBuffersAllocated);
594f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
595f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    notify->setInt32("portIndex", portIndex);
596a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
597a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    sp<PortDescription> desc = new PortDescription;
598a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
599a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
600a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        const BufferInfo &info = mBuffers[portIndex][i];
601a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
602a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        desc->addBuffer(info.mBufferID, info.mData);
603a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
604a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
605a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    notify->setObject("portDesc", desc);
606a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    notify->post();
607a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
608a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    return OK;
609a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
610a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
611a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstatus_t ACodec::configureOutputBuffersFromNativeWindow(
612a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        OMX_U32 *bufferCount, OMX_U32 *bufferSize,
613a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        OMX_U32 *minUndequeuedBuffers) {
614a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    OMX_PARAM_PORTDEFINITIONTYPE def;
615a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    InitOMXParams(&def);
616a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    def.nPortIndex = kPortIndexOutput;
617a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
618a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    status_t err = mOMX->getParameter(
619a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
620a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
621a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (err != OK) {
622a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        return err;
623a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
624a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
625a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    err = native_window_set_buffers_geometry(
626a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            mNativeWindow.get(),
627a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            def.format.video.nFrameWidth,
628a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            def.format.video.nFrameHeight,
629a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            def.format.video.eColorFormat);
630a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
631a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (err != 0) {
632a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        ALOGE("native_window_set_buffers_geometry failed: %s (%d)",
633a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                strerror(-err), -err);
634a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        return err;
635a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
636a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
637323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    if (mRotationDegrees != 0) {
638a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        uint32_t transform = 0;
639f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        switch (mRotationDegrees) {
640f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            case 0: transform = 0; break;
641f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            case 90: transform = HAL_TRANSFORM_ROT_90; break;
642f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            case 180: transform = HAL_TRANSFORM_ROT_180; break;
643f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            case 270: transform = HAL_TRANSFORM_ROT_270; break;
644a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            default: transform = 0; break;
645a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        }
646197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
647f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        if (transform > 0) {
648a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            err = native_window_set_buffers_transform(
649a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                    mNativeWindow.get(), transform);
650a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            if (err != 0) {
651a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                ALOGE("native_window_set_buffers_transform failed: %s (%d)",
652a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                        strerror(-err), -err);
653a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                return err;
654a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            }
655a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        }
656a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
657a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
658a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    // Set up the native window.
659a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    OMX_U32 usage = 0;
660a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage);
661a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (err != 0) {
662a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        ALOGW("querying usage flags from OMX IL component failed: %d", err);
663a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        // XXX: Currently this error is logged, but not fatal.
664a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        usage = 0;
665a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
666a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
667a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (mFlags & kFlagIsSecure) {
668a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        usage |= GRALLOC_USAGE_PROTECTED;
669a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
670a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
671a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    // Make sure to check whether either Stagefright or the video decoder
672a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    // requested protected buffers.
673a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (usage & GRALLOC_USAGE_PROTECTED) {
674a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        // Verify that the ANativeWindow sends images directly to
675c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        // SurfaceFlinger.
676a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        int queuesToNativeWindow = 0;
677a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        err = mNativeWindow->query(
678a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                mNativeWindow.get(), NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER,
679c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                &queuesToNativeWindow);
680c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        if (err != 0) {
681a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            ALOGE("error authenticating native window: %d", err);
682a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            return err;
683c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        }
684a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        if (queuesToNativeWindow != 1) {
685a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            ALOGE("native window could not be authenticated");
686a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            return PERMISSION_DENIED;
687a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        }
688c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
689a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
690a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    err = native_window_set_usage(
691a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            mNativeWindow.get(),
692a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP);
693a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
694a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (err != 0) {
695c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err);
696c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        return err;
697c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
698c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
699c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    *minUndequeuedBuffers = 0;
700c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    err = mNativeWindow->query(
701c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
702c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            (int *)minUndequeuedBuffers);
703c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
704c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (err != 0) {
705c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
706a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                strerror(-err), -err);
707a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        return err;
708a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
709a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
710a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    // FIXME: assume that surface is controlled by app (native window
711a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    // returns the number for the case when surface is not controlled by app)
712a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    // FIXME2: This means that minUndeqeueudBufs can be 1 larger than reported
713a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    // For now, try to allocate 1 more buffer, but don't fail if unsuccessful
714a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
715a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    // Use conservative allocation while also trying to reduce starvation
716c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    //
717c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    // 1. allocate at least nBufferCountMin + minUndequeuedBuffers - that is the
718a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    //    minimum needed for the consumer to be able to work
719a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    // 2. try to allocate two (2) additional buffers to reduce starvation from
720a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    //    the consumer
721a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    //    plus an extra buffer to account for incorrect minUndequeuedBufs
722a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    for (OMX_U32 extraBuffers = 2 + 1; /* condition inside loop */; extraBuffers--) {
723a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        OMX_U32 newBufferCount =
724a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            def.nBufferCountMin + *minUndequeuedBuffers + extraBuffers;
725a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        def.nBufferCountActual = newBufferCount;
726a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        err = mOMX->setParameter(
727a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
728a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
729a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        if (err == OK) {
730a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            *minUndequeuedBuffers += extraBuffers;
731a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            break;
732f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        }
733a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
734f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        ALOGW("[%s] setting nBufferCountActual to %u failed: %d",
735a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                mComponentName.c_str(), newBufferCount, err);
736f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        /* exit condition */
737a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        if (extraBuffers == 0) {
738f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu            return err;
739a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        }
740a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
741a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
742a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    err = native_window_set_buffer_count(
743a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            mNativeWindow.get(), def.nBufferCountActual);
744a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
745a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (err != 0) {
746a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
747a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                -err);
748a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        return err;
749a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
750a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
751a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    *bufferCount = def.nBufferCountActual;
752a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    *bufferSize =  def.nBufferSize;
753a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    return err;
754a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
755a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
756a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstatus_t ACodec::allocateOutputBuffersFromNativeWindow() {
757a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers;
758a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    status_t err = configureOutputBuffersFromNativeWindow(
759a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            &bufferCount, &bufferSize, &minUndequeuedBuffers);
760a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (err != 0)
761a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        return err;
762a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    mNumUndequeuedBuffers = minUndequeuedBuffers;
763a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
764a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    ALOGV("[%s] Allocating %u buffers from a native window of size %u on "
765a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch         "output port",
766a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch         mComponentName.c_str(), bufferCount, bufferSize);
767a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
768a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    // Dequeue buffers and send them to OMX
769a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    for (OMX_U32 i = 0; i < bufferCount; i++) {
770a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        ANativeWindowBuffer *buf;
771a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf);
772a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        if (err != 0) {
773a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
774a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            break;
775a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        }
776a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
777a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
778a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        BufferInfo info;
779a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        info.mStatus = BufferInfo::OWNED_BY_US;
780a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        info.mData = new ABuffer(NULL /* data */, bufferSize /* capacity */);
781a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        info.mGraphicBuffer = graphicBuffer;
782a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        mBuffers[kPortIndexOutput].push(info);
783a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
784a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        IOMX::buffer_id bufferId;
785a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer,
786a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                &bufferId);
787a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        if (err != 0) {
788a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            ALOGE("registering GraphicBuffer %u with OMX IL component failed: "
789a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                 "%d", i, err);
790a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            break;
791a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        }
792a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
793a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId;
794a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
795a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        ALOGV("[%s] Registered graphic buffer with ID %u (pointer = %p)",
796a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch             mComponentName.c_str(),
797a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch             bufferId, graphicBuffer.get());
798a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
799a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
800a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    OMX_U32 cancelStart;
801a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    OMX_U32 cancelEnd;
802a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
803a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (err != 0) {
804c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        // If an error occurred while dequeuing we need to cancel any buffers
805a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        // that were dequeued.
806c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        cancelStart = 0;
807a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        cancelEnd = mBuffers[kPortIndexOutput].size();
808a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    } else {
809a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        // Return the required minimum undequeued buffers to the native window.
810a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        cancelStart = bufferCount - minUndequeuedBuffers;
811a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        cancelEnd = bufferCount;
812a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
813a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
814a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
815c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
816c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        cancelBufferToNativeWindow(info);
817c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
818c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
819c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    return err;
820c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
821c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
822c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)status_t ACodec::allocateOutputMetaDataBuffers() {
823c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers;
824a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    status_t err = configureOutputBuffersFromNativeWindow(
825c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            &bufferCount, &bufferSize, &minUndequeuedBuffers);
826c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (err != 0)
827c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        return err;
828c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    mNumUndequeuedBuffers = minUndequeuedBuffers;
829e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
830c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    ALOGV("[%s] Allocating %u meta buffers on output port",
831c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)         mComponentName.c_str(), bufferCount);
832c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
833a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    size_t totalSize = bufferCount * 8;
834a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    mDealer[kPortIndexOutput] = new MemoryDealer(totalSize, "ACodec");
835c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
836f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    // Dequeue buffers and send them to OMX
837c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    for (OMX_U32 i = 0; i < bufferCount; i++) {
838c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        BufferInfo info;
839c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        info.mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
840c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        info.mGraphicBuffer = NULL;
841c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        info.mDequeuedAt = mDequeueCounter;
842c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
843c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        sp<IMemory> mem = mDealer[kPortIndexOutput]->allocate(
844c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                sizeof(struct VideoDecoderOutputMetaData));
845c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        CHECK(mem.get() != NULL);
846c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        info.mData = new ABuffer(mem->pointer(), mem->size());
847c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
848c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        // we use useBuffer for metadata regardless of quirks
849c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        err = mOMX->useBuffer(
850c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                mNode, kPortIndexOutput, mem, &info.mBufferID);
851c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
852c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        mBuffers[kPortIndexOutput].push(info);
853c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
854c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        ALOGV("[%s] allocated meta buffer with ID %u (pointer = %p)",
855c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)             mComponentName.c_str(), info.mBufferID, mem->pointer());
856c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
857c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
858c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    mMetaDataBuffersToSubmit = bufferCount - minUndequeuedBuffers;
859c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    return err;
860c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
861c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
862c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)status_t ACodec::submitOutputMetaDataBuffer() {
863c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    CHECK(mStoreMetaDataInOutputBuffers);
864c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (mMetaDataBuffersToSubmit == 0)
865c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        return OK;
866a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
867a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    BufferInfo *info = dequeueBufferFromNativeWindow();
868a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (info == NULL)
869d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        return ERROR_IO;
870d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
871a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    ALOGV("[%s] submitting output meta buffer ID %u for graphic buffer %p",
872a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch          mComponentName.c_str(), info->mBufferID, info->mGraphicBuffer.get());
873a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
874a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    --mMetaDataBuffersToSubmit;
875a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    CHECK_EQ(mOMX->fillBuffer(mNode, info->mBufferID),
876a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch             (status_t)OK);
877a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
878d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
879a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    return OK;
880a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
881a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
882a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstatus_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) {
883323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
884323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
885d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    ALOGV("[%s] Calling cancelBuffer on buffer %u",
886323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)         mComponentName.c_str(), info->mBufferID);
887323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
888323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    int err = mNativeWindow->cancelBuffer(
889323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        mNativeWindow.get(), info->mGraphicBuffer.get(), -1);
890a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
891a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    CHECK_EQ(err, 0);
892d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
893d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
894a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
895a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    return OK;
896a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
897a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
898a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben MurdochACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
899d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    ANativeWindowBuffer *buf;
900d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    int fenceFd = -1;
901d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    CHECK(mNativeWindow.get() != NULL);
902d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf) != 0) {
903d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        ALOGE("dequeueBuffer failed.");
904d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        return NULL;
905d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    }
9065d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
9075d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    BufferInfo *oldest = NULL;
9085d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
9095d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        BufferInfo *info =
9105d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            &mBuffers[kPortIndexOutput].editItemAt(i);
9115d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
9125d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        if (info->mGraphicBuffer != NULL &&
9135d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            info->mGraphicBuffer->handle == buf->handle) {
9145d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            CHECK_EQ((int)info->mStatus,
915a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                     (int)BufferInfo::OWNED_BY_NATIVE_WINDOW);
916a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
917a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            info->mStatus = BufferInfo::OWNED_BY_US;
918a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
919a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            return info;
920323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        }
921197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
922323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW &&
923a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            (oldest == NULL ||
924a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch             // avoid potential issues from counter rolling over
925a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch             mDequeueCounter - info->mDequeuedAt >
926a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                    mDequeueCounter - oldest->mDequeuedAt)) {
927a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            oldest = info;
928a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        }
929a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
930a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
931a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (oldest) {
9325d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        CHECK(mStoreMetaDataInOutputBuffers);
9335d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
9345d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        // discard buffer in LRU info and replace with new buffer
9355d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        oldest->mGraphicBuffer = new GraphicBuffer(buf, false);
936a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        oldest->mStatus = BufferInfo::OWNED_BY_US;
937a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
938a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        mOMX->updateGraphicBufferInMeta(
939a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                mNode, kPortIndexOutput, oldest->mGraphicBuffer,
940c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                oldest->mBufferID);
941a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
942a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        VideoDecoderOutputMetaData *metaData =
943323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)            reinterpret_cast<VideoDecoderOutputMetaData *>(
944c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                    oldest->mData->base());
945a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        CHECK_EQ(metaData->eType, kMetadataBufferTypeGrallocSource);
946a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
947a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)",
948d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)                oldest - &mBuffers[kPortIndexOutput][0],
949a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                mDequeueCounter - oldest->mDequeuedAt,
950a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                metaData->pHandle,
951e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)                oldest->mGraphicBuffer->handle, oldest->mData->base());
952a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
953a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        return oldest;
954a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
955a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
956a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    TRESPASS();
957f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
958f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    return NULL;
959197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}
960f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
961c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) {
962c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    for (size_t i = mBuffers[portIndex].size(); i-- > 0;) {
963c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        CHECK_EQ((status_t)OK, freeBuffer(portIndex, i));
964a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
965a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
966a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    mDealer[portIndex].clear();
967a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
9686f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    return OK;
9696f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch}
970323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
971323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)status_t ACodec::freeOutputBuffersNotOwnedByComponent() {
972a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
973a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        BufferInfo *info =
974a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            &mBuffers[kPortIndexOutput].editItemAt(i);
975a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
976197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        // At this time some buffers may still be with the component
977197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        // or being drained.
978c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        if (info->mStatus != BufferInfo::OWNED_BY_COMPONENT &&
979c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            info->mStatus != BufferInfo::OWNED_BY_DOWNSTREAM) {
980c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            CHECK_EQ((status_t)OK, freeBuffer(kPortIndexOutput, i));
981c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        }
982a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
983a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
984a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    return OK;
985c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
986c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
987c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) {
988a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
989a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
990a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    CHECK(info->mStatus == BufferInfo::OWNED_BY_US
991323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)            || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
992a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
993d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (portIndex == kPortIndexOutput && mNativeWindow != NULL
994a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            && info->mStatus == BufferInfo::OWNED_BY_US) {
9955d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        CHECK_EQ((status_t)OK, cancelBufferToNativeWindow(info));
9965d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    }
9975d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
9985d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    CHECK_EQ(mOMX->freeBuffer(
9995d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)                mNode, portIndex, info->mBufferID),
10005d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)             (status_t)OK);
10015d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
10025d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    mBuffers[portIndex].removeAt(i);
1003a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
1004a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    return OK;
1005a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
1006a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
1007a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben MurdochACodec::BufferInfo *ACodec::findBufferByID(
1008a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        uint32_t portIndex, IOMX::buffer_id bufferID,
1009a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        ssize_t *index) {
1010a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
1011a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
1012a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
1013a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        if (info->mBufferID == bufferID) {
1014a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            if (index != NULL) {
1015a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                *index = i;
1016323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)            }
1017323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)            return info;
1018323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        }
1019a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
1020a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
1021c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    TRESPASS();
1022a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
1023a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    return NULL;
1024a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
1025c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
1026a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstatus_t ACodec::setComponentRole(
1027a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        bool isEncoder, const char *mime) {
1028a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    struct MimeToRole {
1029a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        const char *mime;
1030a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        const char *decoderRole;
1031c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        const char *encoderRole;
1032a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    };
1033a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
1034a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    static const MimeToRole kMimeToRole[] = {
1035a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        { MEDIA_MIMETYPE_AUDIO_MPEG,
1036a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            "audio_decoder.mp3", "audio_encoder.mp3" },
1037c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I,
1038a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            "audio_decoder.mp1", "audio_encoder.mp1" },
1039a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II,
1040a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            "audio_decoder.mp2", "audio_encoder.mp2" },
1041a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        { MEDIA_MIMETYPE_AUDIO_AMR_NB,
1042a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            "audio_decoder.amrnb", "audio_encoder.amrnb" },
1043c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        { MEDIA_MIMETYPE_AUDIO_AMR_WB,
1044a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            "audio_decoder.amrwb", "audio_encoder.amrwb" },
1045a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        { MEDIA_MIMETYPE_AUDIO_AAC,
1046a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            "audio_decoder.aac", "audio_encoder.aac" },
1047a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        { MEDIA_MIMETYPE_AUDIO_VORBIS,
1048a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            "audio_decoder.vorbis", "audio_encoder.vorbis" },
1049c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        { MEDIA_MIMETYPE_AUDIO_OPUS,
1050a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            "audio_decoder.opus", "audio_encoder.opus" },
1051a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        { MEDIA_MIMETYPE_AUDIO_G711_MLAW,
1052a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" },
1053a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        { MEDIA_MIMETYPE_AUDIO_G711_ALAW,
1054a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            "audio_decoder.g711alaw", "audio_encoder.g711alaw" },
1055c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        { MEDIA_MIMETYPE_VIDEO_AVC,
1056a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            "video_decoder.avc", "video_encoder.avc" },
1057a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        { MEDIA_MIMETYPE_VIDEO_HEVC,
1058a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            "video_decoder.hevc", "video_encoder.hevc" },
1059a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        { MEDIA_MIMETYPE_VIDEO_MPEG4,
1060a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            "video_decoder.mpeg4", "video_encoder.mpeg4" },
1061c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        { MEDIA_MIMETYPE_VIDEO_H263,
1062a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            "video_decoder.h263", "video_encoder.h263" },
1063a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        { MEDIA_MIMETYPE_VIDEO_VP8,
1064a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            "video_decoder.vp8", "video_encoder.vp8" },
1065a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        { MEDIA_MIMETYPE_VIDEO_VP9,
1066a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            "video_decoder.vp9", "video_encoder.vp9" },
1067a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        { MEDIA_MIMETYPE_AUDIO_RAW,
1068a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            "audio_decoder.raw", "audio_encoder.raw" },
1069a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        { MEDIA_MIMETYPE_AUDIO_FLAC,
1070c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            "audio_decoder.flac", "audio_encoder.flac" },
1071c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        { MEDIA_MIMETYPE_AUDIO_MSGSM,
1072c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            "audio_decoder.gsm", "audio_encoder.gsm" },
1073a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        { MEDIA_MIMETYPE_VIDEO_MPEG2,
1074a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            "video_decoder.mpeg2", "video_encoder.mpeg2" },
1075a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        { MEDIA_MIMETYPE_AUDIO_AC3,
1076a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            "audio_decoder.ac3", "audio_encoder.ac3" },
1077a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    };
1078a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
1079a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    static const size_t kNumMimeToRole =
1080a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
1081a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
1082c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    size_t i;
1083a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    for (i = 0; i < kNumMimeToRole; ++i) {
1084c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        if (!strcasecmp(mime, kMimeToRole[i].mime)) {
1085c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            break;
1086a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        }
1087a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
1088c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
1089a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (i == kNumMimeToRole) {
1090a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        return ERROR_UNSUPPORTED;
1091a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
1092a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
1093a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    const char *role =
1094a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        isEncoder ? kMimeToRole[i].encoderRole
1095a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                  : kMimeToRole[i].decoderRole;
1096a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
1097c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (role != NULL) {
1098c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        OMX_PARAM_COMPONENTROLETYPE roleParams;
1099c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        InitOMXParams(&roleParams);
1100a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
1101a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        strncpy((char *)roleParams.cRole,
1102a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                role, OMX_MAX_STRINGNAME_SIZE - 1);
1103a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
1104a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
1105a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
1106a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        status_t err = mOMX->setParameter(
1107a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                mNode, OMX_IndexParamStandardComponentRole,
1108a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                &roleParams, sizeof(roleParams));
1109c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
1110a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        if (err != OK) {
1111c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            ALOGW("[%s] Failed to set standard component role '%s'.",
1112c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                 mComponentName.c_str(), role);
1113c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
11145d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            return err;
1115197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        }
1116c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
1117197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
1118197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    return OK;
1119197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}
11205d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
1121a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstatus_t ACodec::configureCodec(
1122a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        const char *mime, const sp<AMessage> &msg) {
1123c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    int32_t encoder;
1124a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (!msg->findInt32("encoder", &encoder)) {
1125a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        encoder = false;
1126c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
1127c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
1128a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    sp<AMessage> inputFormat = new AMessage();
1129a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    sp<AMessage> outputFormat = new AMessage();
1130a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
1131a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    mIsEncoder = encoder;
1132c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
1133a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    status_t err = setComponentRole(encoder /* isEncoder */, mime);
1134a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
1135c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (err != OK) {
1136a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        return err;
1137a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
1138a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
1139a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    int32_t bitRate = 0;
1140a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    // FLAC encoder doesn't need a bitrate, other encoders do
1141a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (encoder && strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)
1142a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            && !msg->findInt32("bitrate", &bitRate)) {
1143a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        return INVALID_OPERATION;
1144a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
1145c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
1146c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    int32_t storeMeta;
1147a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (encoder
1148a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            && msg->findInt32("store-metadata-in-buffers", &storeMeta)
1149c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            && storeMeta != 0) {
1150c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexInput, OMX_TRUE);
1151a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
1152a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        if (err != OK) {
1153c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)              ALOGE("[%s] storeMetaDataInBuffers (input) failed w/ err %d",
1154c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                    mComponentName.c_str(), err);
1155a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
1156a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch              return err;
1157a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch          }
1158c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)      }
1159a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
1160a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    int32_t prependSPSPPS = 0;
1161a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (encoder
1162a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            && msg->findInt32("prepend-sps-pps-to-idr-frames", &prependSPSPPS)
1163c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            && prependSPSPPS != 0) {
1164a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        OMX_INDEXTYPE index;
1165a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        err = mOMX->getExtensionIndex(
1166a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                mNode,
1167c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                "OMX.google.android.index.prependSPSPPSToIDRFrames",
1168a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                &index);
1169a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
1170a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        if (err == OK) {
1171a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            PrependSPSPPSToIDRFramesParams params;
1172c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            InitOMXParams(&params);
1173197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            params.bEnable = OMX_TRUE;
1174197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
1175197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            err = mOMX->setParameter(
1176a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch                    mNode, index, &params, sizeof(params));
1177323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        }
1178c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
1179323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        if (err != OK) {
1180323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)            ALOGE("Encoder could not be configured to emit SPS/PPS before "
1181323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)                  "IDR frames. (err %d)", err);
1182323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
1183323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)            return err;
1184323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        }
11855d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    }
11865d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
11875d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // Only enable metadata mode on encoder output if encoder can prepend
11885d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // sps/pps to idr frames, since in metadata mode the bitstream is in an
11895d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // opaque handle, to which we don't have access.
11905d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    int32_t video = !strncasecmp(mime, "video/", 6);
11915d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    if (encoder && video) {
11925d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        OMX_BOOL enable = (OMX_BOOL) (prependSPSPPS
11935d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            && msg->findInt32("store-metadata-in-buffers-output", &storeMeta)
11945d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            && storeMeta != 0);
11955d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
11965d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, enable);
11975d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
1198c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        if (err != OK) {
11995d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            ALOGE("[%s] storeMetaDataInBuffers (output) failed w/ err %d",
12005d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)                mComponentName.c_str(), err);
12015d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            mUseMetadataOnEncoderOutput = 0;
12025d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        } else {
12035d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            mUseMetadataOnEncoderOutput = enable;
12045d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        }
1205c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
12065d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        if (!msg->findInt64(
12075d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)                    "repeat-previous-frame-after",
12085d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)                    &mRepeatFrameDelayUs)) {
1209c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            mRepeatFrameDelayUs = -1ll;
12105d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        }
12115d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
1212a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        if (!msg->findInt64("max-pts-gap-to-encoder", &mMaxPtsGapUs)) {
1213a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            mMaxPtsGapUs = -1ll;
1214a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        }
1215
1216        if (!msg->findInt64("time-lapse", &mTimePerCaptureUs)) {
1217            mTimePerCaptureUs = -1ll;
1218        }
1219
1220        if (!msg->findInt32(
1221                    "create-input-buffers-suspended",
1222                    (int32_t*)&mCreateInputBuffersSuspended)) {
1223            mCreateInputBuffersSuspended = false;
1224        }
1225    }
1226
1227    sp<RefBase> obj;
1228    int32_t haveNativeWindow = msg->findObject("native-window", &obj) &&
1229        obj != NULL;
1230    mStoreMetaDataInOutputBuffers = false;
1231    if (video && !encoder) {
1232        inputFormat->setInt32("adaptive-playback", false);
1233    }
1234    if (!encoder && video && haveNativeWindow) {
1235        sp<NativeWindowWrapper> windowWrapper(
1236                static_cast<NativeWindowWrapper *>(obj.get()));
1237        sp<ANativeWindow> nativeWindow = windowWrapper->getNativeWindow();
1238
1239        int32_t tunneled;
1240        if (msg->findInt32("feature-tunneled-playback", &tunneled) &&
1241            tunneled != 0) {
1242            ALOGI("Configuring TUNNELED video playback.");
1243
1244            int64_t audioHwSync = 0;
1245            if (!msg->findInt64("audio-hw-sync", &audioHwSync)) {
1246                ALOGW("No Audio HW Sync provided for video tunnel");
1247            }
1248            err = configureTunneledVideoPlayback(audioHwSync, nativeWindow);
1249            if (err != OK) {
1250                ALOGE("configureTunneledVideoPlayback(%" PRId64 ",%p) failed!",
1251                        audioHwSync, nativeWindow.get());
1252                return err;
1253            }
1254
1255            inputFormat->setInt32("adaptive-playback", true);
1256        } else {
1257            // Always try to enable dynamic output buffers on native surface
1258            err = mOMX->storeMetaDataInBuffers(
1259                    mNode, kPortIndexOutput, OMX_TRUE);
1260            if (err != OK) {
1261                ALOGE("[%s] storeMetaDataInBuffers failed w/ err %d",
1262                        mComponentName.c_str(), err);
1263
1264                // if adaptive playback has been requested, try JB fallback
1265                // NOTE: THIS FALLBACK MECHANISM WILL BE REMOVED DUE TO ITS
1266                // LARGE MEMORY REQUIREMENT
1267
1268                // we will not do adaptive playback on software accessed
1269                // surfaces as they never had to respond to changes in the
1270                // crop window, and we don't trust that they will be able to.
1271                int usageBits = 0;
1272                bool canDoAdaptivePlayback;
1273
1274                if (nativeWindow->query(
1275                        nativeWindow.get(),
1276                        NATIVE_WINDOW_CONSUMER_USAGE_BITS,
1277                        &usageBits) != OK) {
1278                    canDoAdaptivePlayback = false;
1279                } else {
1280                    canDoAdaptivePlayback =
1281                        (usageBits &
1282                                (GRALLOC_USAGE_SW_READ_MASK |
1283                                 GRALLOC_USAGE_SW_WRITE_MASK)) == 0;
1284                }
1285
1286                int32_t maxWidth = 0, maxHeight = 0;
1287                if (canDoAdaptivePlayback &&
1288                        msg->findInt32("max-width", &maxWidth) &&
1289                        msg->findInt32("max-height", &maxHeight)) {
1290                    ALOGV("[%s] prepareForAdaptivePlayback(%dx%d)",
1291                            mComponentName.c_str(), maxWidth, maxHeight);
1292
1293                    err = mOMX->prepareForAdaptivePlayback(
1294                            mNode, kPortIndexOutput, OMX_TRUE, maxWidth,
1295                            maxHeight);
1296                    ALOGW_IF(err != OK,
1297                            "[%s] prepareForAdaptivePlayback failed w/ err %d",
1298                            mComponentName.c_str(), err);
1299
1300                    if (err == OK) {
1301                        inputFormat->setInt32("max-width", maxWidth);
1302                        inputFormat->setInt32("max-height", maxHeight);
1303                        inputFormat->setInt32("adaptive-playback", true);
1304                    }
1305                }
1306                // allow failure
1307                err = OK;
1308            } else {
1309                ALOGV("[%s] storeMetaDataInBuffers succeeded",
1310                        mComponentName.c_str());
1311                mStoreMetaDataInOutputBuffers = true;
1312                inputFormat->setInt32("adaptive-playback", true);
1313            }
1314
1315            int32_t push;
1316            if (msg->findInt32("push-blank-buffers-on-shutdown", &push)
1317                    && push != 0) {
1318                mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
1319            }
1320        }
1321
1322        int32_t rotationDegrees;
1323        if (msg->findInt32("rotation-degrees", &rotationDegrees)) {
1324            mRotationDegrees = rotationDegrees;
1325        } else {
1326            mRotationDegrees = 0;
1327        }
1328    }
1329
1330    if (video) {
1331        if (encoder) {
1332            err = setupVideoEncoder(mime, msg);
1333        } else {
1334            err = setupVideoDecoder(mime, msg);
1335        }
1336    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
1337        int32_t numChannels, sampleRate;
1338        if (!msg->findInt32("channel-count", &numChannels)
1339                || !msg->findInt32("sample-rate", &sampleRate)) {
1340            // Since we did not always check for these, leave them optional
1341            // and have the decoder figure it all out.
1342            err = OK;
1343        } else {
1344            err = setupRawAudioFormat(
1345                    encoder ? kPortIndexInput : kPortIndexOutput,
1346                    sampleRate,
1347                    numChannels);
1348        }
1349    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
1350        int32_t numChannels, sampleRate;
1351        if (!msg->findInt32("channel-count", &numChannels)
1352                || !msg->findInt32("sample-rate", &sampleRate)) {
1353            err = INVALID_OPERATION;
1354        } else {
1355            int32_t isADTS, aacProfile;
1356            int32_t sbrMode;
1357            int32_t maxOutputChannelCount;
1358            drcParams_t drc;
1359            if (!msg->findInt32("is-adts", &isADTS)) {
1360                isADTS = 0;
1361            }
1362            if (!msg->findInt32("aac-profile", &aacProfile)) {
1363                aacProfile = OMX_AUDIO_AACObjectNull;
1364            }
1365            if (!msg->findInt32("aac-sbr-mode", &sbrMode)) {
1366                sbrMode = -1;
1367            }
1368
1369            if (!msg->findInt32("aac-max-output-channel_count", &maxOutputChannelCount)) {
1370                maxOutputChannelCount = -1;
1371            }
1372            if (!msg->findInt32("aac-encoded-target-level", &drc.encodedTargetLevel)) {
1373                // value is unknown
1374                drc.encodedTargetLevel = -1;
1375            }
1376            if (!msg->findInt32("aac-drc-cut-level", &drc.drcCut)) {
1377                // value is unknown
1378                drc.drcCut = -1;
1379            }
1380            if (!msg->findInt32("aac-drc-boost-level", &drc.drcBoost)) {
1381                // value is unknown
1382                drc.drcBoost = -1;
1383            }
1384            if (!msg->findInt32("aac-drc-heavy-compression", &drc.heavyCompression)) {
1385                // value is unknown
1386                drc.heavyCompression = -1;
1387            }
1388            if (!msg->findInt32("aac-target-ref-level", &drc.targetRefLevel)) {
1389                // value is unknown
1390                drc.targetRefLevel = -1;
1391            }
1392
1393            err = setupAACCodec(
1394                    encoder, numChannels, sampleRate, bitRate, aacProfile,
1395                    isADTS != 0, sbrMode, maxOutputChannelCount, drc);
1396        }
1397    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
1398        err = setupAMRCodec(encoder, false /* isWAMR */, bitRate);
1399    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
1400        err = setupAMRCodec(encoder, true /* isWAMR */, bitRate);
1401    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW)
1402            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) {
1403        // These are PCM-like formats with a fixed sample rate but
1404        // a variable number of channels.
1405
1406        int32_t numChannels;
1407        if (!msg->findInt32("channel-count", &numChannels)) {
1408            err = INVALID_OPERATION;
1409        } else {
1410            err = setupG711Codec(encoder, numChannels);
1411        }
1412    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) {
1413        int32_t numChannels, sampleRate, compressionLevel = -1;
1414        if (encoder &&
1415                (!msg->findInt32("channel-count", &numChannels)
1416                        || !msg->findInt32("sample-rate", &sampleRate))) {
1417            ALOGE("missing channel count or sample rate for FLAC encoder");
1418            err = INVALID_OPERATION;
1419        } else {
1420            if (encoder) {
1421                if (!msg->findInt32(
1422                            "complexity", &compressionLevel) &&
1423                    !msg->findInt32(
1424                            "flac-compression-level", &compressionLevel)) {
1425                    compressionLevel = 5; // default FLAC compression level
1426                } else if (compressionLevel < 0) {
1427                    ALOGW("compression level %d outside [0..8] range, "
1428                          "using 0",
1429                          compressionLevel);
1430                    compressionLevel = 0;
1431                } else if (compressionLevel > 8) {
1432                    ALOGW("compression level %d outside [0..8] range, "
1433                          "using 8",
1434                          compressionLevel);
1435                    compressionLevel = 8;
1436                }
1437            }
1438            err = setupFlacCodec(
1439                    encoder, numChannels, sampleRate, compressionLevel);
1440        }
1441    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
1442        int32_t numChannels, sampleRate;
1443        if (encoder
1444                || !msg->findInt32("channel-count", &numChannels)
1445                || !msg->findInt32("sample-rate", &sampleRate)) {
1446            err = INVALID_OPERATION;
1447        } else {
1448            err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
1449        }
1450    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AC3)) {
1451        int32_t numChannels;
1452        int32_t sampleRate;
1453        if (!msg->findInt32("channel-count", &numChannels)
1454                || !msg->findInt32("sample-rate", &sampleRate)) {
1455            err = INVALID_OPERATION;
1456        } else {
1457            err = setupAC3Codec(encoder, numChannels, sampleRate);
1458        }
1459    }
1460
1461    if (err != OK) {
1462        return err;
1463    }
1464
1465    if (!msg->findInt32("encoder-delay", &mEncoderDelay)) {
1466        mEncoderDelay = 0;
1467    }
1468
1469    if (!msg->findInt32("encoder-padding", &mEncoderPadding)) {
1470        mEncoderPadding = 0;
1471    }
1472
1473    if (msg->findInt32("channel-mask", &mChannelMask)) {
1474        mChannelMaskPresent = true;
1475    } else {
1476        mChannelMaskPresent = false;
1477    }
1478
1479    int32_t maxInputSize;
1480    if (msg->findInt32("max-input-size", &maxInputSize)) {
1481        err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize);
1482    } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) {
1483        err = setMinBufferSize(kPortIndexInput, 8192);  // XXX
1484    }
1485
1486    CHECK_EQ(getPortFormat(kPortIndexInput, inputFormat), (status_t)OK);
1487    CHECK_EQ(getPortFormat(kPortIndexOutput, outputFormat), (status_t)OK);
1488    mInputFormat = inputFormat;
1489    mOutputFormat = outputFormat;
1490
1491    return err;
1492}
1493
1494status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) {
1495    OMX_PARAM_PORTDEFINITIONTYPE def;
1496    InitOMXParams(&def);
1497    def.nPortIndex = portIndex;
1498
1499    status_t err = mOMX->getParameter(
1500            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1501
1502    if (err != OK) {
1503        return err;
1504    }
1505
1506    if (def.nBufferSize >= size) {
1507        return OK;
1508    }
1509
1510    def.nBufferSize = size;
1511
1512    err = mOMX->setParameter(
1513            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1514
1515    if (err != OK) {
1516        return err;
1517    }
1518
1519    err = mOMX->getParameter(
1520            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1521
1522    if (err != OK) {
1523        return err;
1524    }
1525
1526    CHECK(def.nBufferSize >= size);
1527
1528    return OK;
1529}
1530
1531status_t ACodec::selectAudioPortFormat(
1532        OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) {
1533    OMX_AUDIO_PARAM_PORTFORMATTYPE format;
1534    InitOMXParams(&format);
1535
1536    format.nPortIndex = portIndex;
1537    for (OMX_U32 index = 0;; ++index) {
1538        format.nIndex = index;
1539
1540        status_t err = mOMX->getParameter(
1541                mNode, OMX_IndexParamAudioPortFormat,
1542                &format, sizeof(format));
1543
1544        if (err != OK) {
1545            return err;
1546        }
1547
1548        if (format.eEncoding == desiredFormat) {
1549            break;
1550        }
1551    }
1552
1553    return mOMX->setParameter(
1554            mNode, OMX_IndexParamAudioPortFormat, &format, sizeof(format));
1555}
1556
1557status_t ACodec::setupAACCodec(
1558        bool encoder, int32_t numChannels, int32_t sampleRate,
1559        int32_t bitRate, int32_t aacProfile, bool isADTS, int32_t sbrMode,
1560        int32_t maxOutputChannelCount, const drcParams_t& drc) {
1561    if (encoder && isADTS) {
1562        return -EINVAL;
1563    }
1564
1565    status_t err = setupRawAudioFormat(
1566            encoder ? kPortIndexInput : kPortIndexOutput,
1567            sampleRate,
1568            numChannels);
1569
1570    if (err != OK) {
1571        return err;
1572    }
1573
1574    if (encoder) {
1575        err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC);
1576
1577        if (err != OK) {
1578            return err;
1579        }
1580
1581        OMX_PARAM_PORTDEFINITIONTYPE def;
1582        InitOMXParams(&def);
1583        def.nPortIndex = kPortIndexOutput;
1584
1585        err = mOMX->getParameter(
1586                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1587
1588        if (err != OK) {
1589            return err;
1590        }
1591
1592        def.format.audio.bFlagErrorConcealment = OMX_TRUE;
1593        def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
1594
1595        err = mOMX->setParameter(
1596                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1597
1598        if (err != OK) {
1599            return err;
1600        }
1601
1602        OMX_AUDIO_PARAM_AACPROFILETYPE profile;
1603        InitOMXParams(&profile);
1604        profile.nPortIndex = kPortIndexOutput;
1605
1606        err = mOMX->getParameter(
1607                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1608
1609        if (err != OK) {
1610            return err;
1611        }
1612
1613        profile.nChannels = numChannels;
1614
1615        profile.eChannelMode =
1616            (numChannels == 1)
1617                ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo;
1618
1619        profile.nSampleRate = sampleRate;
1620        profile.nBitRate = bitRate;
1621        profile.nAudioBandWidth = 0;
1622        profile.nFrameLength = 0;
1623        profile.nAACtools = OMX_AUDIO_AACToolAll;
1624        profile.nAACERtools = OMX_AUDIO_AACERNone;
1625        profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile;
1626        profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
1627        switch (sbrMode) {
1628        case 0:
1629            // disable sbr
1630            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
1631            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
1632            break;
1633        case 1:
1634            // enable single-rate sbr
1635            profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
1636            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
1637            break;
1638        case 2:
1639            // enable dual-rate sbr
1640            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
1641            profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
1642            break;
1643        case -1:
1644            // enable both modes -> the codec will decide which mode should be used
1645            profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
1646            profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
1647            break;
1648        default:
1649            // unsupported sbr mode
1650            return BAD_VALUE;
1651        }
1652
1653
1654        err = mOMX->setParameter(
1655                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1656
1657        if (err != OK) {
1658            return err;
1659        }
1660
1661        return err;
1662    }
1663
1664    OMX_AUDIO_PARAM_AACPROFILETYPE profile;
1665    InitOMXParams(&profile);
1666    profile.nPortIndex = kPortIndexInput;
1667
1668    err = mOMX->getParameter(
1669            mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1670
1671    if (err != OK) {
1672        return err;
1673    }
1674
1675    profile.nChannels = numChannels;
1676    profile.nSampleRate = sampleRate;
1677
1678    profile.eAACStreamFormat =
1679        isADTS
1680            ? OMX_AUDIO_AACStreamFormatMP4ADTS
1681            : OMX_AUDIO_AACStreamFormatMP4FF;
1682
1683    OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE presentation;
1684    presentation.nMaxOutputChannels = maxOutputChannelCount;
1685    presentation.nDrcCut = drc.drcCut;
1686    presentation.nDrcBoost = drc.drcBoost;
1687    presentation.nHeavyCompression = drc.heavyCompression;
1688    presentation.nTargetReferenceLevel = drc.targetRefLevel;
1689    presentation.nEncodedTargetLevel = drc.encodedTargetLevel;
1690
1691    status_t res = mOMX->setParameter(mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1692    if (res == OK) {
1693        // optional parameters, will not cause configuration failure
1694        mOMX->setParameter(mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacPresentation,
1695                &presentation, sizeof(presentation));
1696    } else {
1697        ALOGW("did not set AudioAndroidAacPresentation due to error %d when setting AudioAac", res);
1698    }
1699    return res;
1700}
1701
1702status_t ACodec::setupAC3Codec(
1703        bool encoder, int32_t numChannels, int32_t sampleRate) {
1704    status_t err = setupRawAudioFormat(
1705            encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
1706
1707    if (err != OK) {
1708        return err;
1709    }
1710
1711    if (encoder) {
1712        ALOGW("AC3 encoding is not supported.");
1713        return INVALID_OPERATION;
1714    }
1715
1716    OMX_AUDIO_PARAM_ANDROID_AC3TYPE def;
1717    InitOMXParams(&def);
1718    def.nPortIndex = kPortIndexInput;
1719
1720    err = mOMX->getParameter(
1721            mNode,
1722            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
1723            &def,
1724            sizeof(def));
1725
1726    if (err != OK) {
1727        return err;
1728    }
1729
1730    def.nChannels = numChannels;
1731    def.nSampleRate = sampleRate;
1732
1733    return mOMX->setParameter(
1734            mNode,
1735            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
1736            &def,
1737            sizeof(def));
1738}
1739
1740static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(
1741        bool isAMRWB, int32_t bps) {
1742    if (isAMRWB) {
1743        if (bps <= 6600) {
1744            return OMX_AUDIO_AMRBandModeWB0;
1745        } else if (bps <= 8850) {
1746            return OMX_AUDIO_AMRBandModeWB1;
1747        } else if (bps <= 12650) {
1748            return OMX_AUDIO_AMRBandModeWB2;
1749        } else if (bps <= 14250) {
1750            return OMX_AUDIO_AMRBandModeWB3;
1751        } else if (bps <= 15850) {
1752            return OMX_AUDIO_AMRBandModeWB4;
1753        } else if (bps <= 18250) {
1754            return OMX_AUDIO_AMRBandModeWB5;
1755        } else if (bps <= 19850) {
1756            return OMX_AUDIO_AMRBandModeWB6;
1757        } else if (bps <= 23050) {
1758            return OMX_AUDIO_AMRBandModeWB7;
1759        }
1760
1761        // 23850 bps
1762        return OMX_AUDIO_AMRBandModeWB8;
1763    } else {  // AMRNB
1764        if (bps <= 4750) {
1765            return OMX_AUDIO_AMRBandModeNB0;
1766        } else if (bps <= 5150) {
1767            return OMX_AUDIO_AMRBandModeNB1;
1768        } else if (bps <= 5900) {
1769            return OMX_AUDIO_AMRBandModeNB2;
1770        } else if (bps <= 6700) {
1771            return OMX_AUDIO_AMRBandModeNB3;
1772        } else if (bps <= 7400) {
1773            return OMX_AUDIO_AMRBandModeNB4;
1774        } else if (bps <= 7950) {
1775            return OMX_AUDIO_AMRBandModeNB5;
1776        } else if (bps <= 10200) {
1777            return OMX_AUDIO_AMRBandModeNB6;
1778        }
1779
1780        // 12200 bps
1781        return OMX_AUDIO_AMRBandModeNB7;
1782    }
1783}
1784
1785status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) {
1786    OMX_AUDIO_PARAM_AMRTYPE def;
1787    InitOMXParams(&def);
1788    def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput;
1789
1790    status_t err =
1791        mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1792
1793    if (err != OK) {
1794        return err;
1795    }
1796
1797    def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
1798    def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate);
1799
1800    err = mOMX->setParameter(
1801            mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1802
1803    if (err != OK) {
1804        return err;
1805    }
1806
1807    return setupRawAudioFormat(
1808            encoder ? kPortIndexInput : kPortIndexOutput,
1809            isWAMR ? 16000 : 8000 /* sampleRate */,
1810            1 /* numChannels */);
1811}
1812
1813status_t ACodec::setupG711Codec(bool encoder, int32_t numChannels) {
1814    CHECK(!encoder);  // XXX TODO
1815
1816    return setupRawAudioFormat(
1817            kPortIndexInput, 8000 /* sampleRate */, numChannels);
1818}
1819
1820status_t ACodec::setupFlacCodec(
1821        bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel) {
1822
1823    if (encoder) {
1824        OMX_AUDIO_PARAM_FLACTYPE def;
1825        InitOMXParams(&def);
1826        def.nPortIndex = kPortIndexOutput;
1827
1828        // configure compression level
1829        status_t err = mOMX->getParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def));
1830        if (err != OK) {
1831            ALOGE("setupFlacCodec(): Error %d getting OMX_IndexParamAudioFlac parameter", err);
1832            return err;
1833        }
1834        def.nCompressionLevel = compressionLevel;
1835        err = mOMX->setParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def));
1836        if (err != OK) {
1837            ALOGE("setupFlacCodec(): Error %d setting OMX_IndexParamAudioFlac parameter", err);
1838            return err;
1839        }
1840    }
1841
1842    return setupRawAudioFormat(
1843            encoder ? kPortIndexInput : kPortIndexOutput,
1844            sampleRate,
1845            numChannels);
1846}
1847
1848status_t ACodec::setupRawAudioFormat(
1849        OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
1850    OMX_PARAM_PORTDEFINITIONTYPE def;
1851    InitOMXParams(&def);
1852    def.nPortIndex = portIndex;
1853
1854    status_t err = mOMX->getParameter(
1855            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1856
1857    if (err != OK) {
1858        return err;
1859    }
1860
1861    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
1862
1863    err = mOMX->setParameter(
1864            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1865
1866    if (err != OK) {
1867        return err;
1868    }
1869
1870    OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
1871    InitOMXParams(&pcmParams);
1872    pcmParams.nPortIndex = portIndex;
1873
1874    err = mOMX->getParameter(
1875            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
1876
1877    if (err != OK) {
1878        return err;
1879    }
1880
1881    pcmParams.nChannels = numChannels;
1882    pcmParams.eNumData = OMX_NumericalDataSigned;
1883    pcmParams.bInterleaved = OMX_TRUE;
1884    pcmParams.nBitPerSample = 16;
1885    pcmParams.nSamplingRate = sampleRate;
1886    pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
1887
1888    if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) {
1889        return OMX_ErrorNone;
1890    }
1891
1892    return mOMX->setParameter(
1893            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
1894}
1895
1896status_t ACodec::configureTunneledVideoPlayback(
1897        int64_t audioHwSync, const sp<ANativeWindow> &nativeWindow) {
1898    native_handle_t* sidebandHandle;
1899
1900    status_t err = mOMX->configureVideoTunnelMode(
1901            mNode, kPortIndexOutput, OMX_TRUE, audioHwSync, &sidebandHandle);
1902    if (err != OK) {
1903        ALOGE("configureVideoTunnelMode failed! (err %d).", err);
1904        return err;
1905    }
1906
1907    err = native_window_set_sideband_stream(nativeWindow.get(), sidebandHandle);
1908    if (err != OK) {
1909        ALOGE("native_window_set_sideband_stream(%p) failed! (err %d).",
1910                sidebandHandle, err);
1911        return err;
1912    }
1913
1914    return OK;
1915}
1916
1917status_t ACodec::setVideoPortFormatType(
1918        OMX_U32 portIndex,
1919        OMX_VIDEO_CODINGTYPE compressionFormat,
1920        OMX_COLOR_FORMATTYPE colorFormat) {
1921    OMX_VIDEO_PARAM_PORTFORMATTYPE format;
1922    InitOMXParams(&format);
1923    format.nPortIndex = portIndex;
1924    format.nIndex = 0;
1925    bool found = false;
1926
1927    OMX_U32 index = 0;
1928    for (;;) {
1929        format.nIndex = index;
1930        status_t err = mOMX->getParameter(
1931                mNode, OMX_IndexParamVideoPortFormat,
1932                &format, sizeof(format));
1933
1934        if (err != OK) {
1935            return err;
1936        }
1937
1938        // substitute back flexible color format to codec supported format
1939        OMX_U32 flexibleEquivalent;
1940        if (compressionFormat == OMX_VIDEO_CodingUnused &&
1941                isFlexibleColorFormat(
1942                        mOMX, mNode, format.eColorFormat, &flexibleEquivalent) &&
1943                colorFormat == flexibleEquivalent) {
1944            ALOGI("[%s] using color format %#x in place of %#x",
1945                    mComponentName.c_str(), format.eColorFormat, colorFormat);
1946            colorFormat = format.eColorFormat;
1947        }
1948
1949        // The following assertion is violated by TI's video decoder.
1950        // CHECK_EQ(format.nIndex, index);
1951
1952        if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) {
1953            if (portIndex == kPortIndexInput
1954                    && colorFormat == format.eColorFormat) {
1955                // eCompressionFormat does not seem right.
1956                found = true;
1957                break;
1958            }
1959            if (portIndex == kPortIndexOutput
1960                    && compressionFormat == format.eCompressionFormat) {
1961                // eColorFormat does not seem right.
1962                found = true;
1963                break;
1964            }
1965        }
1966
1967        if (format.eCompressionFormat == compressionFormat
1968            && format.eColorFormat == colorFormat) {
1969            found = true;
1970            break;
1971        }
1972
1973        ++index;
1974    }
1975
1976    if (!found) {
1977        return UNKNOWN_ERROR;
1978    }
1979
1980    status_t err = mOMX->setParameter(
1981            mNode, OMX_IndexParamVideoPortFormat,
1982            &format, sizeof(format));
1983
1984    return err;
1985}
1986
1987status_t ACodec::setSupportedOutputFormat() {
1988    OMX_VIDEO_PARAM_PORTFORMATTYPE format;
1989    InitOMXParams(&format);
1990    format.nPortIndex = kPortIndexOutput;
1991    format.nIndex = 0;
1992
1993    status_t err = mOMX->getParameter(
1994            mNode, OMX_IndexParamVideoPortFormat,
1995            &format, sizeof(format));
1996    CHECK_EQ(err, (status_t)OK);
1997    CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused);
1998
1999    return mOMX->setParameter(
2000            mNode, OMX_IndexParamVideoPortFormat,
2001            &format, sizeof(format));
2002}
2003
2004static const struct VideoCodingMapEntry {
2005    const char *mMime;
2006    OMX_VIDEO_CODINGTYPE mVideoCodingType;
2007} kVideoCodingMapEntry[] = {
2008    { MEDIA_MIMETYPE_VIDEO_AVC, OMX_VIDEO_CodingAVC },
2009    { MEDIA_MIMETYPE_VIDEO_HEVC, OMX_VIDEO_CodingHEVC },
2010    { MEDIA_MIMETYPE_VIDEO_MPEG4, OMX_VIDEO_CodingMPEG4 },
2011    { MEDIA_MIMETYPE_VIDEO_H263, OMX_VIDEO_CodingH263 },
2012    { MEDIA_MIMETYPE_VIDEO_MPEG2, OMX_VIDEO_CodingMPEG2 },
2013    { MEDIA_MIMETYPE_VIDEO_VP8, OMX_VIDEO_CodingVP8 },
2014    { MEDIA_MIMETYPE_VIDEO_VP9, OMX_VIDEO_CodingVP9 },
2015};
2016
2017static status_t GetVideoCodingTypeFromMime(
2018        const char *mime, OMX_VIDEO_CODINGTYPE *codingType) {
2019    for (size_t i = 0;
2020         i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
2021         ++i) {
2022        if (!strcasecmp(mime, kVideoCodingMapEntry[i].mMime)) {
2023            *codingType = kVideoCodingMapEntry[i].mVideoCodingType;
2024            return OK;
2025        }
2026    }
2027
2028    *codingType = OMX_VIDEO_CodingUnused;
2029
2030    return ERROR_UNSUPPORTED;
2031}
2032
2033static status_t GetMimeTypeForVideoCoding(
2034        OMX_VIDEO_CODINGTYPE codingType, AString *mime) {
2035    for (size_t i = 0;
2036         i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
2037         ++i) {
2038        if (codingType == kVideoCodingMapEntry[i].mVideoCodingType) {
2039            *mime = kVideoCodingMapEntry[i].mMime;
2040            return OK;
2041        }
2042    }
2043
2044    mime->clear();
2045
2046    return ERROR_UNSUPPORTED;
2047}
2048
2049status_t ACodec::setupVideoDecoder(
2050        const char *mime, const sp<AMessage> &msg) {
2051    int32_t width, height;
2052    if (!msg->findInt32("width", &width)
2053            || !msg->findInt32("height", &height)) {
2054        return INVALID_OPERATION;
2055    }
2056
2057    OMX_VIDEO_CODINGTYPE compressionFormat;
2058    status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
2059
2060    if (err != OK) {
2061        return err;
2062    }
2063
2064    err = setVideoPortFormatType(
2065            kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
2066
2067    if (err != OK) {
2068        return err;
2069    }
2070
2071    int32_t tmp;
2072    if (msg->findInt32("color-format", &tmp)) {
2073        OMX_COLOR_FORMATTYPE colorFormat =
2074            static_cast<OMX_COLOR_FORMATTYPE>(tmp);
2075        err = setVideoPortFormatType(
2076                kPortIndexOutput, OMX_VIDEO_CodingUnused, colorFormat);
2077        if (err != OK) {
2078            ALOGW("[%s] does not support color format %d",
2079                  mComponentName.c_str(), colorFormat);
2080            err = setSupportedOutputFormat();
2081        }
2082    } else {
2083        err = setSupportedOutputFormat();
2084    }
2085
2086    if (err != OK) {
2087        return err;
2088    }
2089
2090    err = setVideoFormatOnPort(
2091            kPortIndexInput, width, height, compressionFormat);
2092
2093    if (err != OK) {
2094        return err;
2095    }
2096
2097    err = setVideoFormatOnPort(
2098            kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused);
2099
2100    if (err != OK) {
2101        return err;
2102    }
2103
2104    return OK;
2105}
2106
2107status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) {
2108    int32_t tmp;
2109    if (!msg->findInt32("color-format", &tmp)) {
2110        return INVALID_OPERATION;
2111    }
2112
2113    OMX_COLOR_FORMATTYPE colorFormat =
2114        static_cast<OMX_COLOR_FORMATTYPE>(tmp);
2115
2116    status_t err = setVideoPortFormatType(
2117            kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat);
2118
2119    if (err != OK) {
2120        ALOGE("[%s] does not support color format %d",
2121              mComponentName.c_str(), colorFormat);
2122
2123        return err;
2124    }
2125
2126    /* Input port configuration */
2127
2128    OMX_PARAM_PORTDEFINITIONTYPE def;
2129    InitOMXParams(&def);
2130
2131    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
2132
2133    def.nPortIndex = kPortIndexInput;
2134
2135    err = mOMX->getParameter(
2136            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2137
2138    if (err != OK) {
2139        return err;
2140    }
2141
2142    int32_t width, height, bitrate;
2143    if (!msg->findInt32("width", &width)
2144            || !msg->findInt32("height", &height)
2145            || !msg->findInt32("bitrate", &bitrate)) {
2146        return INVALID_OPERATION;
2147    }
2148
2149    video_def->nFrameWidth = width;
2150    video_def->nFrameHeight = height;
2151
2152    int32_t stride;
2153    if (!msg->findInt32("stride", &stride)) {
2154        stride = width;
2155    }
2156
2157    video_def->nStride = stride;
2158
2159    int32_t sliceHeight;
2160    if (!msg->findInt32("slice-height", &sliceHeight)) {
2161        sliceHeight = height;
2162    }
2163
2164    video_def->nSliceHeight = sliceHeight;
2165
2166    def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2;
2167
2168    float frameRate;
2169    if (!msg->findFloat("frame-rate", &frameRate)) {
2170        int32_t tmp;
2171        if (!msg->findInt32("frame-rate", &tmp)) {
2172            return INVALID_OPERATION;
2173        }
2174        frameRate = (float)tmp;
2175        mTimePerFrameUs = (int64_t) (1000000.0f / frameRate);
2176    }
2177
2178    video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
2179    video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
2180    video_def->eColorFormat = colorFormat;
2181
2182    err = mOMX->setParameter(
2183            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2184
2185    if (err != OK) {
2186        ALOGE("[%s] failed to set input port definition parameters.",
2187              mComponentName.c_str());
2188
2189        return err;
2190    }
2191
2192    /* Output port configuration */
2193
2194    OMX_VIDEO_CODINGTYPE compressionFormat;
2195    err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
2196
2197    if (err != OK) {
2198        return err;
2199    }
2200
2201    err = setVideoPortFormatType(
2202            kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused);
2203
2204    if (err != OK) {
2205        ALOGE("[%s] does not support compression format %d",
2206             mComponentName.c_str(), compressionFormat);
2207
2208        return err;
2209    }
2210
2211    def.nPortIndex = kPortIndexOutput;
2212
2213    err = mOMX->getParameter(
2214            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2215
2216    if (err != OK) {
2217        return err;
2218    }
2219
2220    video_def->nFrameWidth = width;
2221    video_def->nFrameHeight = height;
2222    video_def->xFramerate = 0;
2223    video_def->nBitrate = bitrate;
2224    video_def->eCompressionFormat = compressionFormat;
2225    video_def->eColorFormat = OMX_COLOR_FormatUnused;
2226
2227    err = mOMX->setParameter(
2228            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2229
2230    if (err != OK) {
2231        ALOGE("[%s] failed to set output port definition parameters.",
2232              mComponentName.c_str());
2233
2234        return err;
2235    }
2236
2237    switch (compressionFormat) {
2238        case OMX_VIDEO_CodingMPEG4:
2239            err = setupMPEG4EncoderParameters(msg);
2240            break;
2241
2242        case OMX_VIDEO_CodingH263:
2243            err = setupH263EncoderParameters(msg);
2244            break;
2245
2246        case OMX_VIDEO_CodingAVC:
2247            err = setupAVCEncoderParameters(msg);
2248            break;
2249
2250        case OMX_VIDEO_CodingHEVC:
2251            err = setupHEVCEncoderParameters(msg);
2252            break;
2253
2254        case OMX_VIDEO_CodingVP8:
2255        case OMX_VIDEO_CodingVP9:
2256            err = setupVPXEncoderParameters(msg);
2257            break;
2258
2259        default:
2260            break;
2261    }
2262
2263    ALOGI("setupVideoEncoder succeeded");
2264
2265    return err;
2266}
2267
2268status_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) {
2269    OMX_VIDEO_PARAM_INTRAREFRESHTYPE params;
2270    InitOMXParams(&params);
2271    params.nPortIndex = kPortIndexOutput;
2272
2273    params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode);
2274
2275    if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic ||
2276            params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
2277        int32_t mbs;
2278        if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) {
2279            return INVALID_OPERATION;
2280        }
2281        params.nCirMBs = mbs;
2282    }
2283
2284    if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive ||
2285            params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
2286        int32_t mbs;
2287        if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) {
2288            return INVALID_OPERATION;
2289        }
2290        params.nAirMBs = mbs;
2291
2292        int32_t ref;
2293        if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) {
2294            return INVALID_OPERATION;
2295        }
2296        params.nAirRef = ref;
2297    }
2298
2299    status_t err = mOMX->setParameter(
2300            mNode, OMX_IndexParamVideoIntraRefresh,
2301            &params, sizeof(params));
2302    return err;
2303}
2304
2305static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) {
2306    if (iFramesInterval < 0) {
2307        return 0xFFFFFFFF;
2308    } else if (iFramesInterval == 0) {
2309        return 0;
2310    }
2311    OMX_U32 ret = frameRate * iFramesInterval;
2312    CHECK(ret > 1);
2313    return ret;
2314}
2315
2316static OMX_VIDEO_CONTROLRATETYPE getBitrateMode(const sp<AMessage> &msg) {
2317    int32_t tmp;
2318    if (!msg->findInt32("bitrate-mode", &tmp)) {
2319        return OMX_Video_ControlRateVariable;
2320    }
2321
2322    return static_cast<OMX_VIDEO_CONTROLRATETYPE>(tmp);
2323}
2324
2325status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) {
2326    int32_t bitrate, iFrameInterval;
2327    if (!msg->findInt32("bitrate", &bitrate)
2328            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2329        return INVALID_OPERATION;
2330    }
2331
2332    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2333
2334    float frameRate;
2335    if (!msg->findFloat("frame-rate", &frameRate)) {
2336        int32_t tmp;
2337        if (!msg->findInt32("frame-rate", &tmp)) {
2338            return INVALID_OPERATION;
2339        }
2340        frameRate = (float)tmp;
2341    }
2342
2343    OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
2344    InitOMXParams(&mpeg4type);
2345    mpeg4type.nPortIndex = kPortIndexOutput;
2346
2347    status_t err = mOMX->getParameter(
2348            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
2349
2350    if (err != OK) {
2351        return err;
2352    }
2353
2354    mpeg4type.nSliceHeaderSpacing = 0;
2355    mpeg4type.bSVH = OMX_FALSE;
2356    mpeg4type.bGov = OMX_FALSE;
2357
2358    mpeg4type.nAllowedPictureTypes =
2359        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
2360
2361    mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
2362    if (mpeg4type.nPFrames == 0) {
2363        mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
2364    }
2365    mpeg4type.nBFrames = 0;
2366    mpeg4type.nIDCVLCThreshold = 0;
2367    mpeg4type.bACPred = OMX_TRUE;
2368    mpeg4type.nMaxPacketSize = 256;
2369    mpeg4type.nTimeIncRes = 1000;
2370    mpeg4type.nHeaderExtension = 0;
2371    mpeg4type.bReversibleVLC = OMX_FALSE;
2372
2373    int32_t profile;
2374    if (msg->findInt32("profile", &profile)) {
2375        int32_t level;
2376        if (!msg->findInt32("level", &level)) {
2377            return INVALID_OPERATION;
2378        }
2379
2380        err = verifySupportForProfileAndLevel(profile, level);
2381
2382        if (err != OK) {
2383            return err;
2384        }
2385
2386        mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile);
2387        mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level);
2388    }
2389
2390    err = mOMX->setParameter(
2391            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
2392
2393    if (err != OK) {
2394        return err;
2395    }
2396
2397    err = configureBitrate(bitrate, bitrateMode);
2398
2399    if (err != OK) {
2400        return err;
2401    }
2402
2403    return setupErrorCorrectionParameters();
2404}
2405
2406status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) {
2407    int32_t bitrate, iFrameInterval;
2408    if (!msg->findInt32("bitrate", &bitrate)
2409            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2410        return INVALID_OPERATION;
2411    }
2412
2413    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2414
2415    float frameRate;
2416    if (!msg->findFloat("frame-rate", &frameRate)) {
2417        int32_t tmp;
2418        if (!msg->findInt32("frame-rate", &tmp)) {
2419            return INVALID_OPERATION;
2420        }
2421        frameRate = (float)tmp;
2422    }
2423
2424    OMX_VIDEO_PARAM_H263TYPE h263type;
2425    InitOMXParams(&h263type);
2426    h263type.nPortIndex = kPortIndexOutput;
2427
2428    status_t err = mOMX->getParameter(
2429            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
2430
2431    if (err != OK) {
2432        return err;
2433    }
2434
2435    h263type.nAllowedPictureTypes =
2436        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
2437
2438    h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
2439    if (h263type.nPFrames == 0) {
2440        h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
2441    }
2442    h263type.nBFrames = 0;
2443
2444    int32_t profile;
2445    if (msg->findInt32("profile", &profile)) {
2446        int32_t level;
2447        if (!msg->findInt32("level", &level)) {
2448            return INVALID_OPERATION;
2449        }
2450
2451        err = verifySupportForProfileAndLevel(profile, level);
2452
2453        if (err != OK) {
2454            return err;
2455        }
2456
2457        h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile);
2458        h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level);
2459    }
2460
2461    h263type.bPLUSPTYPEAllowed = OMX_FALSE;
2462    h263type.bForceRoundingTypeToZero = OMX_FALSE;
2463    h263type.nPictureHeaderRepetition = 0;
2464    h263type.nGOBHeaderInterval = 0;
2465
2466    err = mOMX->setParameter(
2467            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
2468
2469    if (err != OK) {
2470        return err;
2471    }
2472
2473    err = configureBitrate(bitrate, bitrateMode);
2474
2475    if (err != OK) {
2476        return err;
2477    }
2478
2479    return setupErrorCorrectionParameters();
2480}
2481
2482status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
2483    int32_t bitrate, iFrameInterval;
2484    if (!msg->findInt32("bitrate", &bitrate)
2485            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2486        return INVALID_OPERATION;
2487    }
2488
2489    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2490
2491    float frameRate;
2492    if (!msg->findFloat("frame-rate", &frameRate)) {
2493        int32_t tmp;
2494        if (!msg->findInt32("frame-rate", &tmp)) {
2495            return INVALID_OPERATION;
2496        }
2497        frameRate = (float)tmp;
2498    }
2499
2500    status_t err = OK;
2501    int32_t intraRefreshMode = 0;
2502    if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) {
2503        err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode);
2504        if (err != OK) {
2505            ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x",
2506                    err, intraRefreshMode);
2507            return err;
2508        }
2509    }
2510
2511    OMX_VIDEO_PARAM_AVCTYPE h264type;
2512    InitOMXParams(&h264type);
2513    h264type.nPortIndex = kPortIndexOutput;
2514
2515    err = mOMX->getParameter(
2516            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
2517
2518    if (err != OK) {
2519        return err;
2520    }
2521
2522    h264type.nAllowedPictureTypes =
2523        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
2524
2525    int32_t profile;
2526    if (msg->findInt32("profile", &profile)) {
2527        int32_t level;
2528        if (!msg->findInt32("level", &level)) {
2529            return INVALID_OPERATION;
2530        }
2531
2532        err = verifySupportForProfileAndLevel(profile, level);
2533
2534        if (err != OK) {
2535            return err;
2536        }
2537
2538        h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile);
2539        h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level);
2540    }
2541
2542    // XXX
2543    if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) {
2544        ALOGW("Use baseline profile instead of %d for AVC recording",
2545            h264type.eProfile);
2546        h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
2547    }
2548
2549    if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
2550        h264type.nSliceHeaderSpacing = 0;
2551        h264type.bUseHadamard = OMX_TRUE;
2552        h264type.nRefFrames = 1;
2553        h264type.nBFrames = 0;
2554        h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
2555        if (h264type.nPFrames == 0) {
2556            h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
2557        }
2558        h264type.nRefIdx10ActiveMinus1 = 0;
2559        h264type.nRefIdx11ActiveMinus1 = 0;
2560        h264type.bEntropyCodingCABAC = OMX_FALSE;
2561        h264type.bWeightedPPrediction = OMX_FALSE;
2562        h264type.bconstIpred = OMX_FALSE;
2563        h264type.bDirect8x8Inference = OMX_FALSE;
2564        h264type.bDirectSpatialTemporal = OMX_FALSE;
2565        h264type.nCabacInitIdc = 0;
2566    }
2567
2568    if (h264type.nBFrames != 0) {
2569        h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
2570    }
2571
2572    h264type.bEnableUEP = OMX_FALSE;
2573    h264type.bEnableFMO = OMX_FALSE;
2574    h264type.bEnableASO = OMX_FALSE;
2575    h264type.bEnableRS = OMX_FALSE;
2576    h264type.bFrameMBsOnly = OMX_TRUE;
2577    h264type.bMBAFF = OMX_FALSE;
2578    h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
2579
2580    err = mOMX->setParameter(
2581            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
2582
2583    if (err != OK) {
2584        return err;
2585    }
2586
2587    return configureBitrate(bitrate, bitrateMode);
2588}
2589
2590status_t ACodec::setupHEVCEncoderParameters(const sp<AMessage> &msg) {
2591    int32_t bitrate, iFrameInterval;
2592    if (!msg->findInt32("bitrate", &bitrate)
2593            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2594        return INVALID_OPERATION;
2595    }
2596
2597    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2598
2599    float frameRate;
2600    if (!msg->findFloat("frame-rate", &frameRate)) {
2601        int32_t tmp;
2602        if (!msg->findInt32("frame-rate", &tmp)) {
2603            return INVALID_OPERATION;
2604        }
2605        frameRate = (float)tmp;
2606    }
2607
2608    OMX_VIDEO_PARAM_HEVCTYPE hevcType;
2609    InitOMXParams(&hevcType);
2610    hevcType.nPortIndex = kPortIndexOutput;
2611
2612    status_t err = OK;
2613    err = mOMX->getParameter(
2614            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
2615    if (err != OK) {
2616        return err;
2617    }
2618
2619    int32_t profile;
2620    if (msg->findInt32("profile", &profile)) {
2621        int32_t level;
2622        if (!msg->findInt32("level", &level)) {
2623            return INVALID_OPERATION;
2624        }
2625
2626        err = verifySupportForProfileAndLevel(profile, level);
2627        if (err != OK) {
2628            return err;
2629        }
2630
2631        hevcType.eProfile = static_cast<OMX_VIDEO_HEVCPROFILETYPE>(profile);
2632        hevcType.eLevel = static_cast<OMX_VIDEO_HEVCLEVELTYPE>(level);
2633    }
2634
2635    // TODO: Need OMX structure definition for setting iFrameInterval
2636
2637    err = mOMX->setParameter(
2638            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
2639    if (err != OK) {
2640        return err;
2641    }
2642
2643    return configureBitrate(bitrate, bitrateMode);
2644}
2645
2646status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg) {
2647    int32_t bitrate;
2648    int32_t iFrameInterval = 0;
2649    size_t tsLayers = 0;
2650    OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE pattern =
2651        OMX_VIDEO_VPXTemporalLayerPatternNone;
2652    static const uint32_t kVp8LayerRateAlloction
2653        [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS]
2654        [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] = {
2655        {100, 100, 100},  // 1 layer
2656        { 60, 100, 100},  // 2 layers {60%, 40%}
2657        { 40,  60, 100},  // 3 layers {40%, 20%, 40%}
2658    };
2659    if (!msg->findInt32("bitrate", &bitrate)) {
2660        return INVALID_OPERATION;
2661    }
2662    msg->findInt32("i-frame-interval", &iFrameInterval);
2663
2664    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2665
2666    float frameRate;
2667    if (!msg->findFloat("frame-rate", &frameRate)) {
2668        int32_t tmp;
2669        if (!msg->findInt32("frame-rate", &tmp)) {
2670            return INVALID_OPERATION;
2671        }
2672        frameRate = (float)tmp;
2673    }
2674
2675    AString tsSchema;
2676    if (msg->findString("ts-schema", &tsSchema)) {
2677        if (tsSchema == "webrtc.vp8.1-layer") {
2678            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
2679            tsLayers = 1;
2680        } else if (tsSchema == "webrtc.vp8.2-layer") {
2681            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
2682            tsLayers = 2;
2683        } else if (tsSchema == "webrtc.vp8.3-layer") {
2684            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
2685            tsLayers = 3;
2686        } else {
2687            ALOGW("Unsupported ts-schema [%s]", tsSchema.c_str());
2688        }
2689    }
2690
2691    OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
2692    InitOMXParams(&vp8type);
2693    vp8type.nPortIndex = kPortIndexOutput;
2694    status_t err = mOMX->getParameter(
2695            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
2696            &vp8type, sizeof(vp8type));
2697
2698    if (err == OK) {
2699        if (iFrameInterval > 0) {
2700            vp8type.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate);
2701        }
2702        vp8type.eTemporalPattern = pattern;
2703        vp8type.nTemporalLayerCount = tsLayers;
2704        if (tsLayers > 0) {
2705            for (size_t i = 0; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) {
2706                vp8type.nTemporalLayerBitrateRatio[i] =
2707                    kVp8LayerRateAlloction[tsLayers - 1][i];
2708            }
2709        }
2710        if (bitrateMode == OMX_Video_ControlRateConstant) {
2711            vp8type.nMinQuantizer = 2;
2712            vp8type.nMaxQuantizer = 63;
2713        }
2714
2715        err = mOMX->setParameter(
2716                mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
2717                &vp8type, sizeof(vp8type));
2718        if (err != OK) {
2719            ALOGW("Extended VP8 parameters set failed: %d", err);
2720        }
2721    }
2722
2723    return configureBitrate(bitrate, bitrateMode);
2724}
2725
2726status_t ACodec::verifySupportForProfileAndLevel(
2727        int32_t profile, int32_t level) {
2728    OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
2729    InitOMXParams(&params);
2730    params.nPortIndex = kPortIndexOutput;
2731
2732    for (params.nProfileIndex = 0;; ++params.nProfileIndex) {
2733        status_t err = mOMX->getParameter(
2734                mNode,
2735                OMX_IndexParamVideoProfileLevelQuerySupported,
2736                &params,
2737                sizeof(params));
2738
2739        if (err != OK) {
2740            return err;
2741        }
2742
2743        int32_t supportedProfile = static_cast<int32_t>(params.eProfile);
2744        int32_t supportedLevel = static_cast<int32_t>(params.eLevel);
2745
2746        if (profile == supportedProfile && level <= supportedLevel) {
2747            return OK;
2748        }
2749    }
2750}
2751
2752status_t ACodec::configureBitrate(
2753        int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode) {
2754    OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
2755    InitOMXParams(&bitrateType);
2756    bitrateType.nPortIndex = kPortIndexOutput;
2757
2758    status_t err = mOMX->getParameter(
2759            mNode, OMX_IndexParamVideoBitrate,
2760            &bitrateType, sizeof(bitrateType));
2761
2762    if (err != OK) {
2763        return err;
2764    }
2765
2766    bitrateType.eControlRate = bitrateMode;
2767    bitrateType.nTargetBitrate = bitrate;
2768
2769    return mOMX->setParameter(
2770            mNode, OMX_IndexParamVideoBitrate,
2771            &bitrateType, sizeof(bitrateType));
2772}
2773
2774status_t ACodec::setupErrorCorrectionParameters() {
2775    OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
2776    InitOMXParams(&errorCorrectionType);
2777    errorCorrectionType.nPortIndex = kPortIndexOutput;
2778
2779    status_t err = mOMX->getParameter(
2780            mNode, OMX_IndexParamVideoErrorCorrection,
2781            &errorCorrectionType, sizeof(errorCorrectionType));
2782
2783    if (err != OK) {
2784        return OK;  // Optional feature. Ignore this failure
2785    }
2786
2787    errorCorrectionType.bEnableHEC = OMX_FALSE;
2788    errorCorrectionType.bEnableResync = OMX_TRUE;
2789    errorCorrectionType.nResynchMarkerSpacing = 256;
2790    errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
2791    errorCorrectionType.bEnableRVLC = OMX_FALSE;
2792
2793    return mOMX->setParameter(
2794            mNode, OMX_IndexParamVideoErrorCorrection,
2795            &errorCorrectionType, sizeof(errorCorrectionType));
2796}
2797
2798status_t ACodec::setVideoFormatOnPort(
2799        OMX_U32 portIndex,
2800        int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) {
2801    OMX_PARAM_PORTDEFINITIONTYPE def;
2802    InitOMXParams(&def);
2803    def.nPortIndex = portIndex;
2804
2805    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
2806
2807    status_t err = mOMX->getParameter(
2808            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2809
2810    CHECK_EQ(err, (status_t)OK);
2811
2812    if (portIndex == kPortIndexInput) {
2813        // XXX Need a (much) better heuristic to compute input buffer sizes.
2814        const size_t X = 64 * 1024;
2815        if (def.nBufferSize < X) {
2816            def.nBufferSize = X;
2817        }
2818    }
2819
2820    CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
2821
2822    video_def->nFrameWidth = width;
2823    video_def->nFrameHeight = height;
2824
2825    if (portIndex == kPortIndexInput) {
2826        video_def->eCompressionFormat = compressionFormat;
2827        video_def->eColorFormat = OMX_COLOR_FormatUnused;
2828    }
2829
2830    err = mOMX->setParameter(
2831            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2832
2833    return err;
2834}
2835
2836status_t ACodec::initNativeWindow() {
2837    if (mNativeWindow != NULL) {
2838        return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
2839    }
2840
2841    mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE);
2842    return OK;
2843}
2844
2845size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const {
2846    size_t n = 0;
2847
2848    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
2849        const BufferInfo &info = mBuffers[portIndex].itemAt(i);
2850
2851        if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
2852            ++n;
2853        }
2854    }
2855
2856    return n;
2857}
2858
2859size_t ACodec::countBuffersOwnedByNativeWindow() const {
2860    size_t n = 0;
2861
2862    for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) {
2863        const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i);
2864
2865        if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
2866            ++n;
2867        }
2868    }
2869
2870    return n;
2871}
2872
2873void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() {
2874    if (mNativeWindow == NULL) {
2875        return;
2876    }
2877
2878    while (countBuffersOwnedByNativeWindow() > mNumUndequeuedBuffers
2879            && dequeueBufferFromNativeWindow() != NULL) {
2880        // these buffers will be submitted as regular buffers; account for this
2881        if (mStoreMetaDataInOutputBuffers && mMetaDataBuffersToSubmit > 0) {
2882            --mMetaDataBuffersToSubmit;
2883        }
2884    }
2885}
2886
2887bool ACodec::allYourBuffersAreBelongToUs(
2888        OMX_U32 portIndex) {
2889    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
2890        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
2891
2892        if (info->mStatus != BufferInfo::OWNED_BY_US
2893                && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
2894            ALOGV("[%s] Buffer %u on port %u still has status %d",
2895                    mComponentName.c_str(),
2896                    info->mBufferID, portIndex, info->mStatus);
2897            return false;
2898        }
2899    }
2900
2901    return true;
2902}
2903
2904bool ACodec::allYourBuffersAreBelongToUs() {
2905    return allYourBuffersAreBelongToUs(kPortIndexInput)
2906        && allYourBuffersAreBelongToUs(kPortIndexOutput);
2907}
2908
2909void ACodec::deferMessage(const sp<AMessage> &msg) {
2910    bool wasEmptyBefore = mDeferredQueue.empty();
2911    mDeferredQueue.push_back(msg);
2912}
2913
2914void ACodec::processDeferredMessages() {
2915    List<sp<AMessage> > queue = mDeferredQueue;
2916    mDeferredQueue.clear();
2917
2918    List<sp<AMessage> >::iterator it = queue.begin();
2919    while (it != queue.end()) {
2920        onMessageReceived(*it++);
2921    }
2922}
2923
2924// static
2925bool ACodec::describeDefaultColorFormat(DescribeColorFormatParams &params) {
2926    MediaImage &image = params.sMediaImage;
2927    memset(&image, 0, sizeof(image));
2928
2929    image.mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
2930    image.mNumPlanes = 0;
2931
2932    const OMX_COLOR_FORMATTYPE fmt = params.eColorFormat;
2933    // we need stride and slice-height to be non-zero
2934    if (params.nStride == 0 || params.nSliceHeight == 0) {
2935        ALOGW("cannot describe color format 0x%x = %d with stride=%u and sliceHeight=%u",
2936                fmt, fmt, params.nStride, params.nSliceHeight);
2937        return false;
2938    }
2939
2940    image.mWidth = params.nFrameWidth;
2941    image.mHeight = params.nFrameHeight;
2942
2943    // only supporting YUV420
2944    if (fmt != OMX_COLOR_FormatYUV420Planar &&
2945        fmt != OMX_COLOR_FormatYUV420PackedPlanar &&
2946        fmt != OMX_COLOR_FormatYUV420SemiPlanar &&
2947        fmt != OMX_COLOR_FormatYUV420PackedSemiPlanar) {
2948        ALOGW("do not know color format 0x%x = %d", fmt, fmt);
2949        return false;
2950    }
2951
2952    // set-up YUV format
2953    image.mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
2954    image.mNumPlanes = 3;
2955    image.mBitDepth = 8;
2956    image.mPlane[image.Y].mOffset = 0;
2957    image.mPlane[image.Y].mColInc = 1;
2958    image.mPlane[image.Y].mRowInc = params.nStride;
2959    image.mPlane[image.Y].mHorizSubsampling = 1;
2960    image.mPlane[image.Y].mVertSubsampling = 1;
2961
2962    switch (fmt) {
2963        case OMX_COLOR_FormatYUV420Planar: // used for YV12
2964        case OMX_COLOR_FormatYUV420PackedPlanar:
2965            image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
2966            image.mPlane[image.U].mColInc = 1;
2967            image.mPlane[image.U].mRowInc = params.nStride / 2;
2968            image.mPlane[image.U].mHorizSubsampling = 2;
2969            image.mPlane[image.U].mVertSubsampling = 2;
2970
2971            image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset
2972                    + (params.nStride * params.nSliceHeight / 4);
2973            image.mPlane[image.V].mColInc = 1;
2974            image.mPlane[image.V].mRowInc = params.nStride / 2;
2975            image.mPlane[image.V].mHorizSubsampling = 2;
2976            image.mPlane[image.V].mVertSubsampling = 2;
2977            break;
2978
2979        case OMX_COLOR_FormatYUV420SemiPlanar:
2980            // FIXME: NV21 for sw-encoder, NV12 for decoder and hw-encoder
2981        case OMX_COLOR_FormatYUV420PackedSemiPlanar:
2982            // NV12
2983            image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
2984            image.mPlane[image.U].mColInc = 2;
2985            image.mPlane[image.U].mRowInc = params.nStride;
2986            image.mPlane[image.U].mHorizSubsampling = 2;
2987            image.mPlane[image.U].mVertSubsampling = 2;
2988
2989            image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset + 1;
2990            image.mPlane[image.V].mColInc = 2;
2991            image.mPlane[image.V].mRowInc = params.nStride;
2992            image.mPlane[image.V].mHorizSubsampling = 2;
2993            image.mPlane[image.V].mVertSubsampling = 2;
2994            break;
2995
2996        default:
2997            TRESPASS();
2998    }
2999    return true;
3000}
3001
3002// static
3003bool ACodec::describeColorFormat(
3004        const sp<IOMX> &omx, IOMX::node_id node,
3005        DescribeColorFormatParams &describeParams)
3006{
3007    OMX_INDEXTYPE describeColorFormatIndex;
3008    if (omx->getExtensionIndex(
3009            node, "OMX.google.android.index.describeColorFormat",
3010            &describeColorFormatIndex) != OK ||
3011        omx->getParameter(
3012            node, describeColorFormatIndex,
3013            &describeParams, sizeof(describeParams)) != OK) {
3014        return describeDefaultColorFormat(describeParams);
3015    }
3016    return describeParams.sMediaImage.mType !=
3017            MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
3018}
3019
3020// static
3021bool ACodec::isFlexibleColorFormat(
3022         const sp<IOMX> &omx, IOMX::node_id node,
3023         uint32_t colorFormat, OMX_U32 *flexibleEquivalent) {
3024    DescribeColorFormatParams describeParams;
3025    InitOMXParams(&describeParams);
3026    describeParams.eColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat;
3027    // reasonable dummy values
3028    describeParams.nFrameWidth = 128;
3029    describeParams.nFrameHeight = 128;
3030    describeParams.nStride = 128;
3031    describeParams.nSliceHeight = 128;
3032
3033    CHECK(flexibleEquivalent != NULL);
3034
3035    if (!describeColorFormat(omx, node, describeParams)) {
3036        return false;
3037    }
3038
3039    const MediaImage &img = describeParams.sMediaImage;
3040    if (img.mType == MediaImage::MEDIA_IMAGE_TYPE_YUV) {
3041        if (img.mNumPlanes != 3 ||
3042            img.mPlane[img.Y].mHorizSubsampling != 1 ||
3043            img.mPlane[img.Y].mVertSubsampling != 1) {
3044            return false;
3045        }
3046
3047        // YUV 420
3048        if (img.mPlane[img.U].mHorizSubsampling == 2
3049                && img.mPlane[img.U].mVertSubsampling == 2
3050                && img.mPlane[img.V].mHorizSubsampling == 2
3051                && img.mPlane[img.V].mVertSubsampling == 2) {
3052            // possible flexible YUV420 format
3053            if (img.mBitDepth <= 8) {
3054               *flexibleEquivalent = OMX_COLOR_FormatYUV420Flexible;
3055               return true;
3056            }
3057        }
3058    }
3059    return false;
3060}
3061
3062status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
3063    // TODO: catch errors an return them instead of using CHECK
3064    OMX_PARAM_PORTDEFINITIONTYPE def;
3065    InitOMXParams(&def);
3066    def.nPortIndex = portIndex;
3067
3068    CHECK_EQ(mOMX->getParameter(
3069                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)),
3070             (status_t)OK);
3071
3072    CHECK_EQ((int)def.eDir,
3073            (int)(portIndex == kPortIndexOutput ? OMX_DirOutput : OMX_DirInput));
3074
3075    switch (def.eDomain) {
3076        case OMX_PortDomainVideo:
3077        {
3078            OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
3079            switch ((int)videoDef->eCompressionFormat) {
3080                case OMX_VIDEO_CodingUnused:
3081                {
3082                    CHECK(mIsEncoder ^ (portIndex == kPortIndexOutput));
3083                    notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
3084
3085                    notify->setInt32("stride", videoDef->nStride);
3086                    notify->setInt32("slice-height", videoDef->nSliceHeight);
3087                    notify->setInt32("color-format", videoDef->eColorFormat);
3088
3089                    DescribeColorFormatParams describeParams;
3090                    InitOMXParams(&describeParams);
3091                    describeParams.eColorFormat = videoDef->eColorFormat;
3092                    describeParams.nFrameWidth = videoDef->nFrameWidth;
3093                    describeParams.nFrameHeight = videoDef->nFrameHeight;
3094                    describeParams.nStride = videoDef->nStride;
3095                    describeParams.nSliceHeight = videoDef->nSliceHeight;
3096
3097                    if (describeColorFormat(mOMX, mNode, describeParams)) {
3098                        notify->setBuffer(
3099                                "image-data",
3100                                ABuffer::CreateAsCopy(
3101                                        &describeParams.sMediaImage,
3102                                        sizeof(describeParams.sMediaImage)));
3103                    }
3104
3105                    OMX_CONFIG_RECTTYPE rect;
3106                    InitOMXParams(&rect);
3107                    rect.nPortIndex = kPortIndexOutput;
3108
3109                    if (mOMX->getConfig(
3110                                mNode, OMX_IndexConfigCommonOutputCrop,
3111                                &rect, sizeof(rect)) != OK) {
3112                        rect.nLeft = 0;
3113                        rect.nTop = 0;
3114                        rect.nWidth = videoDef->nFrameWidth;
3115                        rect.nHeight = videoDef->nFrameHeight;
3116                    }
3117
3118                    CHECK_GE(rect.nLeft, 0);
3119                    CHECK_GE(rect.nTop, 0);
3120                    CHECK_GE(rect.nWidth, 0u);
3121                    CHECK_GE(rect.nHeight, 0u);
3122                    CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth);
3123                    CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight);
3124
3125                    notify->setRect(
3126                            "crop",
3127                            rect.nLeft,
3128                            rect.nTop,
3129                            rect.nLeft + rect.nWidth - 1,
3130                            rect.nTop + rect.nHeight - 1);
3131
3132                    break;
3133                }
3134
3135                case OMX_VIDEO_CodingVP8:
3136                case OMX_VIDEO_CodingVP9:
3137                {
3138                    OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
3139                    InitOMXParams(&vp8type);
3140                    vp8type.nPortIndex = kPortIndexOutput;
3141                    status_t err = mOMX->getParameter(
3142                            mNode,
3143                            (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
3144                            &vp8type,
3145                            sizeof(vp8type));
3146
3147                    if (err == OK) {
3148                        AString tsSchema = "none";
3149                        if (vp8type.eTemporalPattern
3150                                == OMX_VIDEO_VPXTemporalLayerPatternWebRTC) {
3151                            switch (vp8type.nTemporalLayerCount) {
3152                                case 1:
3153                                {
3154                                    tsSchema = "webrtc.vp8.1-layer";
3155                                    break;
3156                                }
3157                                case 2:
3158                                {
3159                                    tsSchema = "webrtc.vp8.2-layer";
3160                                    break;
3161                                }
3162                                case 3:
3163                                {
3164                                    tsSchema = "webrtc.vp8.3-layer";
3165                                    break;
3166                                }
3167                                default:
3168                                {
3169                                    break;
3170                                }
3171                            }
3172                        }
3173                        notify->setString("ts-schema", tsSchema);
3174                    }
3175                    // Fall through to set up mime.
3176                }
3177
3178                default:
3179                {
3180                    CHECK(mIsEncoder ^ (portIndex == kPortIndexInput));
3181                    AString mime;
3182                    if (GetMimeTypeForVideoCoding(
3183                        videoDef->eCompressionFormat, &mime) != OK) {
3184                        notify->setString("mime", "application/octet-stream");
3185                    } else {
3186                        notify->setString("mime", mime.c_str());
3187                    }
3188                    break;
3189                }
3190            }
3191
3192            notify->setInt32("width", videoDef->nFrameWidth);
3193            notify->setInt32("height", videoDef->nFrameHeight);
3194            break;
3195        }
3196
3197        case OMX_PortDomainAudio:
3198        {
3199            OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
3200
3201            switch ((int)audioDef->eEncoding) {
3202                case OMX_AUDIO_CodingPCM:
3203                {
3204                    OMX_AUDIO_PARAM_PCMMODETYPE params;
3205                    InitOMXParams(&params);
3206                    params.nPortIndex = portIndex;
3207
3208                    CHECK_EQ(mOMX->getParameter(
3209                                mNode, OMX_IndexParamAudioPcm,
3210                                &params, sizeof(params)),
3211                             (status_t)OK);
3212
3213                    CHECK_GT(params.nChannels, 0);
3214                    CHECK(params.nChannels == 1 || params.bInterleaved);
3215                    CHECK_EQ(params.nBitPerSample, 16u);
3216
3217                    CHECK_EQ((int)params.eNumData,
3218                             (int)OMX_NumericalDataSigned);
3219
3220                    CHECK_EQ((int)params.ePCMMode,
3221                             (int)OMX_AUDIO_PCMModeLinear);
3222
3223                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
3224                    notify->setInt32("channel-count", params.nChannels);
3225                    notify->setInt32("sample-rate", params.nSamplingRate);
3226
3227                    if (mChannelMaskPresent) {
3228                        notify->setInt32("channel-mask", mChannelMask);
3229                    }
3230                    break;
3231                }
3232
3233                case OMX_AUDIO_CodingAAC:
3234                {
3235                    OMX_AUDIO_PARAM_AACPROFILETYPE params;
3236                    InitOMXParams(&params);
3237                    params.nPortIndex = portIndex;
3238
3239                    CHECK_EQ(mOMX->getParameter(
3240                                mNode, OMX_IndexParamAudioAac,
3241                                &params, sizeof(params)),
3242                             (status_t)OK);
3243
3244                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
3245                    notify->setInt32("channel-count", params.nChannels);
3246                    notify->setInt32("sample-rate", params.nSampleRate);
3247                    break;
3248                }
3249
3250                case OMX_AUDIO_CodingAMR:
3251                {
3252                    OMX_AUDIO_PARAM_AMRTYPE params;
3253                    InitOMXParams(&params);
3254                    params.nPortIndex = portIndex;
3255
3256                    CHECK_EQ(mOMX->getParameter(
3257                                mNode, OMX_IndexParamAudioAmr,
3258                                &params, sizeof(params)),
3259                             (status_t)OK);
3260
3261                    notify->setInt32("channel-count", 1);
3262                    if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) {
3263                        notify->setString(
3264                                "mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
3265
3266                        notify->setInt32("sample-rate", 16000);
3267                    } else {
3268                        notify->setString(
3269                                "mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
3270
3271                        notify->setInt32("sample-rate", 8000);
3272                    }
3273                    break;
3274                }
3275
3276                case OMX_AUDIO_CodingFLAC:
3277                {
3278                    OMX_AUDIO_PARAM_FLACTYPE params;
3279                    InitOMXParams(&params);
3280                    params.nPortIndex = portIndex;
3281
3282                    CHECK_EQ(mOMX->getParameter(
3283                                mNode, OMX_IndexParamAudioFlac,
3284                                &params, sizeof(params)),
3285                             (status_t)OK);
3286
3287                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC);
3288                    notify->setInt32("channel-count", params.nChannels);
3289                    notify->setInt32("sample-rate", params.nSampleRate);
3290                    break;
3291                }
3292
3293                case OMX_AUDIO_CodingMP3:
3294                {
3295                    OMX_AUDIO_PARAM_MP3TYPE params;
3296                    InitOMXParams(&params);
3297                    params.nPortIndex = portIndex;
3298
3299                    CHECK_EQ(mOMX->getParameter(
3300                                mNode, OMX_IndexParamAudioMp3,
3301                                &params, sizeof(params)),
3302                             (status_t)OK);
3303
3304                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MPEG);
3305                    notify->setInt32("channel-count", params.nChannels);
3306                    notify->setInt32("sample-rate", params.nSampleRate);
3307                    break;
3308                }
3309
3310                case OMX_AUDIO_CodingVORBIS:
3311                {
3312                    OMX_AUDIO_PARAM_VORBISTYPE params;
3313                    InitOMXParams(&params);
3314                    params.nPortIndex = portIndex;
3315
3316                    CHECK_EQ(mOMX->getParameter(
3317                                mNode, OMX_IndexParamAudioVorbis,
3318                                &params, sizeof(params)),
3319                             (status_t)OK);
3320
3321                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_VORBIS);
3322                    notify->setInt32("channel-count", params.nChannels);
3323                    notify->setInt32("sample-rate", params.nSampleRate);
3324                    break;
3325                }
3326
3327                case OMX_AUDIO_CodingAndroidAC3:
3328                {
3329                    OMX_AUDIO_PARAM_ANDROID_AC3TYPE params;
3330                    InitOMXParams(&params);
3331                    params.nPortIndex = portIndex;
3332
3333                    CHECK_EQ((status_t)OK, mOMX->getParameter(
3334                            mNode,
3335                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
3336                            &params,
3337                            sizeof(params)));
3338
3339                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3);
3340                    notify->setInt32("channel-count", params.nChannels);
3341                    notify->setInt32("sample-rate", params.nSampleRate);
3342                    break;
3343                }
3344
3345                case OMX_AUDIO_CodingAndroidOPUS:
3346                {
3347                    OMX_AUDIO_PARAM_ANDROID_OPUSTYPE params;
3348                    InitOMXParams(&params);
3349                    params.nPortIndex = portIndex;
3350
3351                    CHECK_EQ((status_t)OK, mOMX->getParameter(
3352                            mNode,
3353                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
3354                            &params,
3355                            sizeof(params)));
3356
3357                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_OPUS);
3358                    notify->setInt32("channel-count", params.nChannels);
3359                    notify->setInt32("sample-rate", params.nSampleRate);
3360                    break;
3361                }
3362
3363                default:
3364                    ALOGE("UNKNOWN AUDIO CODING: %d\n", audioDef->eEncoding);
3365                    TRESPASS();
3366            }
3367            break;
3368        }
3369
3370        default:
3371            TRESPASS();
3372    }
3373
3374    return OK;
3375}
3376
3377void ACodec::sendFormatChange(const sp<AMessage> &reply) {
3378    sp<AMessage> notify = mNotify->dup();
3379    notify->setInt32("what", kWhatOutputFormatChanged);
3380
3381    CHECK_EQ(getPortFormat(kPortIndexOutput, notify), (status_t)OK);
3382
3383    AString mime;
3384    CHECK(notify->findString("mime", &mime));
3385
3386    int32_t left, top, right, bottom;
3387    if (mime == MEDIA_MIMETYPE_VIDEO_RAW &&
3388        mNativeWindow != NULL &&
3389        notify->findRect("crop", &left, &top, &right, &bottom)) {
3390        // notify renderer of the crop change
3391        // NOTE: native window uses extended right-bottom coordinate
3392        reply->setRect("crop", left, top, right + 1, bottom + 1);
3393    } else if (mime == MEDIA_MIMETYPE_AUDIO_RAW &&
3394               (mEncoderDelay || mEncoderPadding)) {
3395        int32_t channelCount;
3396        CHECK(notify->findInt32("channel-count", &channelCount));
3397        size_t frameSize = channelCount * sizeof(int16_t);
3398        if (mSkipCutBuffer != NULL) {
3399            size_t prevbufsize = mSkipCutBuffer->size();
3400            if (prevbufsize != 0) {
3401                ALOGW("Replacing SkipCutBuffer holding %d "
3402                      "bytes",
3403                      prevbufsize);
3404            }
3405        }
3406        mSkipCutBuffer = new SkipCutBuffer(
3407                mEncoderDelay * frameSize,
3408                mEncoderPadding * frameSize);
3409    }
3410
3411    notify->post();
3412
3413    mSentFormat = true;
3414}
3415
3416void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) {
3417    sp<AMessage> notify = mNotify->dup();
3418    notify->setInt32("what", CodecBase::kWhatError);
3419    ALOGE("signalError(omxError %#x, internalError %d)", error, internalError);
3420
3421    if (internalError == UNKNOWN_ERROR) { // find better error code
3422        const status_t omxStatus = statusFromOMXError(error);
3423        if (omxStatus != 0) {
3424            internalError = omxStatus;
3425        } else {
3426            ALOGW("Invalid OMX error %#x", error);
3427        }
3428    }
3429    notify->setInt32("err", internalError);
3430    notify->setInt32("actionCode", ACTION_CODE_FATAL); // could translate from OMX error.
3431    notify->post();
3432}
3433
3434status_t ACodec::pushBlankBuffersToNativeWindow() {
3435    status_t err = NO_ERROR;
3436    ANativeWindowBuffer* anb = NULL;
3437    int numBufs = 0;
3438    int minUndequeuedBufs = 0;
3439
3440    // We need to reconnect to the ANativeWindow as a CPU client to ensure that
3441    // no frames get dropped by SurfaceFlinger assuming that these are video
3442    // frames.
3443    err = native_window_api_disconnect(mNativeWindow.get(),
3444            NATIVE_WINDOW_API_MEDIA);
3445    if (err != NO_ERROR) {
3446        ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
3447                strerror(-err), -err);
3448        return err;
3449    }
3450
3451    err = native_window_api_connect(mNativeWindow.get(),
3452            NATIVE_WINDOW_API_CPU);
3453    if (err != NO_ERROR) {
3454        ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
3455                strerror(-err), -err);
3456        return err;
3457    }
3458
3459    err = native_window_set_buffers_geometry(mNativeWindow.get(), 1, 1,
3460            HAL_PIXEL_FORMAT_RGBX_8888);
3461    if (err != NO_ERROR) {
3462        ALOGE("error pushing blank frames: set_buffers_geometry failed: %s (%d)",
3463                strerror(-err), -err);
3464        goto error;
3465    }
3466
3467    err = native_window_set_scaling_mode(mNativeWindow.get(),
3468                NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
3469    if (err != NO_ERROR) {
3470        ALOGE("error pushing blank_frames: set_scaling_mode failed: %s (%d)",
3471              strerror(-err), -err);
3472        goto error;
3473    }
3474
3475    err = native_window_set_usage(mNativeWindow.get(),
3476            GRALLOC_USAGE_SW_WRITE_OFTEN);
3477    if (err != NO_ERROR) {
3478        ALOGE("error pushing blank frames: set_usage failed: %s (%d)",
3479                strerror(-err), -err);
3480        goto error;
3481    }
3482
3483    err = mNativeWindow->query(mNativeWindow.get(),
3484            NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs);
3485    if (err != NO_ERROR) {
3486        ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query "
3487                "failed: %s (%d)", strerror(-err), -err);
3488        goto error;
3489    }
3490
3491    numBufs = minUndequeuedBufs + 1;
3492    err = native_window_set_buffer_count(mNativeWindow.get(), numBufs);
3493    if (err != NO_ERROR) {
3494        ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)",
3495                strerror(-err), -err);
3496        goto error;
3497    }
3498
3499    // We  push numBufs + 1 buffers to ensure that we've drawn into the same
3500    // buffer twice.  This should guarantee that the buffer has been displayed
3501    // on the screen and then been replaced, so an previous video frames are
3502    // guaranteed NOT to be currently displayed.
3503    for (int i = 0; i < numBufs + 1; i++) {
3504        int fenceFd = -1;
3505        err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &anb);
3506        if (err != NO_ERROR) {
3507            ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)",
3508                    strerror(-err), -err);
3509            goto error;
3510        }
3511
3512        sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
3513
3514        // Fill the buffer with the a 1x1 checkerboard pattern ;)
3515        uint32_t* img = NULL;
3516        err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
3517        if (err != NO_ERROR) {
3518            ALOGE("error pushing blank frames: lock failed: %s (%d)",
3519                    strerror(-err), -err);
3520            goto error;
3521        }
3522
3523        *img = 0;
3524
3525        err = buf->unlock();
3526        if (err != NO_ERROR) {
3527            ALOGE("error pushing blank frames: unlock failed: %s (%d)",
3528                    strerror(-err), -err);
3529            goto error;
3530        }
3531
3532        err = mNativeWindow->queueBuffer(mNativeWindow.get(),
3533                buf->getNativeBuffer(), -1);
3534        if (err != NO_ERROR) {
3535            ALOGE("error pushing blank frames: queueBuffer failed: %s (%d)",
3536                    strerror(-err), -err);
3537            goto error;
3538        }
3539
3540        anb = NULL;
3541    }
3542
3543error:
3544
3545    if (err != NO_ERROR) {
3546        // Clean up after an error.
3547        if (anb != NULL) {
3548            mNativeWindow->cancelBuffer(mNativeWindow.get(), anb, -1);
3549        }
3550
3551        native_window_api_disconnect(mNativeWindow.get(),
3552                NATIVE_WINDOW_API_CPU);
3553        native_window_api_connect(mNativeWindow.get(),
3554                NATIVE_WINDOW_API_MEDIA);
3555
3556        return err;
3557    } else {
3558        // Clean up after success.
3559        err = native_window_api_disconnect(mNativeWindow.get(),
3560                NATIVE_WINDOW_API_CPU);
3561        if (err != NO_ERROR) {
3562            ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
3563                    strerror(-err), -err);
3564            return err;
3565        }
3566
3567        err = native_window_api_connect(mNativeWindow.get(),
3568                NATIVE_WINDOW_API_MEDIA);
3569        if (err != NO_ERROR) {
3570            ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
3571                    strerror(-err), -err);
3572            return err;
3573        }
3574
3575        return NO_ERROR;
3576    }
3577}
3578
3579////////////////////////////////////////////////////////////////////////////////
3580
3581ACodec::PortDescription::PortDescription() {
3582}
3583
3584status_t ACodec::requestIDRFrame() {
3585    if (!mIsEncoder) {
3586        return ERROR_UNSUPPORTED;
3587    }
3588
3589    OMX_CONFIG_INTRAREFRESHVOPTYPE params;
3590    InitOMXParams(&params);
3591
3592    params.nPortIndex = kPortIndexOutput;
3593    params.IntraRefreshVOP = OMX_TRUE;
3594
3595    return mOMX->setConfig(
3596            mNode,
3597            OMX_IndexConfigVideoIntraVOPRefresh,
3598            &params,
3599            sizeof(params));
3600}
3601
3602void ACodec::PortDescription::addBuffer(
3603        IOMX::buffer_id id, const sp<ABuffer> &buffer) {
3604    mBufferIDs.push_back(id);
3605    mBuffers.push_back(buffer);
3606}
3607
3608size_t ACodec::PortDescription::countBuffers() {
3609    return mBufferIDs.size();
3610}
3611
3612IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const {
3613    return mBufferIDs.itemAt(index);
3614}
3615
3616sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const {
3617    return mBuffers.itemAt(index);
3618}
3619
3620////////////////////////////////////////////////////////////////////////////////
3621
3622ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
3623    : AState(parentState),
3624      mCodec(codec) {
3625}
3626
3627ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(
3628        OMX_U32 /* portIndex */) {
3629    return KEEP_BUFFERS;
3630}
3631
3632bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
3633    switch (msg->what()) {
3634        case kWhatInputBufferFilled:
3635        {
3636            onInputBufferFilled(msg);
3637            break;
3638        }
3639
3640        case kWhatOutputBufferDrained:
3641        {
3642            onOutputBufferDrained(msg);
3643            break;
3644        }
3645
3646        case ACodec::kWhatOMXMessage:
3647        {
3648            return onOMXMessage(msg);
3649        }
3650
3651        case ACodec::kWhatCreateInputSurface:
3652        case ACodec::kWhatSignalEndOfInputStream:
3653        {
3654            // This may result in an app illegal state exception.
3655            ALOGE("Message 0x%x was not handled", msg->what());
3656            mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION);
3657            return true;
3658        }
3659
3660        case ACodec::kWhatOMXDied:
3661        {
3662            // This will result in kFlagSawMediaServerDie handling in MediaCodec.
3663            ALOGE("OMX/mediaserver died, signalling error!");
3664            mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT);
3665            break;
3666        }
3667
3668        default:
3669            return false;
3670    }
3671
3672    return true;
3673}
3674
3675bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
3676    int32_t type;
3677    CHECK(msg->findInt32("type", &type));
3678
3679    // there is a possibility that this is an outstanding message for a
3680    // codec that we have already destroyed
3681    if (mCodec->mNode == NULL) {
3682        ALOGI("ignoring message as already freed component: %s",
3683                msg->debugString().c_str());
3684        return true;
3685    }
3686
3687    IOMX::node_id nodeID;
3688    CHECK(msg->findInt32("node", (int32_t*)&nodeID));
3689    CHECK_EQ(nodeID, mCodec->mNode);
3690
3691    switch (type) {
3692        case omx_message::EVENT:
3693        {
3694            int32_t event, data1, data2;
3695            CHECK(msg->findInt32("event", &event));
3696            CHECK(msg->findInt32("data1", &data1));
3697            CHECK(msg->findInt32("data2", &data2));
3698
3699            if (event == OMX_EventCmdComplete
3700                    && data1 == OMX_CommandFlush
3701                    && data2 == (int32_t)OMX_ALL) {
3702                // Use of this notification is not consistent across
3703                // implementations. We'll drop this notification and rely
3704                // on flush-complete notifications on the individual port
3705                // indices instead.
3706
3707                return true;
3708            }
3709
3710            return onOMXEvent(
3711                    static_cast<OMX_EVENTTYPE>(event),
3712                    static_cast<OMX_U32>(data1),
3713                    static_cast<OMX_U32>(data2));
3714        }
3715
3716        case omx_message::EMPTY_BUFFER_DONE:
3717        {
3718            IOMX::buffer_id bufferID;
3719            CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
3720
3721            return onOMXEmptyBufferDone(bufferID);
3722        }
3723
3724        case omx_message::FILL_BUFFER_DONE:
3725        {
3726            IOMX::buffer_id bufferID;
3727            CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
3728
3729            int32_t rangeOffset, rangeLength, flags;
3730            int64_t timeUs;
3731
3732            CHECK(msg->findInt32("range_offset", &rangeOffset));
3733            CHECK(msg->findInt32("range_length", &rangeLength));
3734            CHECK(msg->findInt32("flags", &flags));
3735            CHECK(msg->findInt64("timestamp", &timeUs));
3736
3737            return onOMXFillBufferDone(
3738                    bufferID,
3739                    (size_t)rangeOffset, (size_t)rangeLength,
3740                    (OMX_U32)flags,
3741                    timeUs);
3742        }
3743
3744        default:
3745            TRESPASS();
3746            break;
3747    }
3748}
3749
3750bool ACodec::BaseState::onOMXEvent(
3751        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
3752    if (event != OMX_EventError) {
3753        ALOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)",
3754             mCodec->mComponentName.c_str(), event, data1, data2);
3755
3756        return false;
3757    }
3758
3759    ALOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1);
3760
3761    // verify OMX component sends back an error we expect.
3762    OMX_ERRORTYPE omxError = (OMX_ERRORTYPE)data1;
3763    if (!isOMXError(omxError)) {
3764        ALOGW("Invalid OMX error %#x", omxError);
3765        omxError = OMX_ErrorUndefined;
3766    }
3767    mCodec->signalError(omxError);
3768
3769    return true;
3770}
3771
3772bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) {
3773    ALOGV("[%s] onOMXEmptyBufferDone %p",
3774         mCodec->mComponentName.c_str(), bufferID);
3775
3776    BufferInfo *info =
3777        mCodec->findBufferByID(kPortIndexInput, bufferID);
3778
3779    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
3780    info->mStatus = BufferInfo::OWNED_BY_US;
3781
3782    const sp<AMessage> &bufferMeta = info->mData->meta();
3783    void *mediaBuffer;
3784    if (bufferMeta->findPointer("mediaBuffer", &mediaBuffer)
3785            && mediaBuffer != NULL) {
3786        // We're in "store-metadata-in-buffers" mode, the underlying
3787        // OMX component had access to data that's implicitly refcounted
3788        // by this "mediaBuffer" object. Now that the OMX component has
3789        // told us that it's done with the input buffer, we can decrement
3790        // the mediaBuffer's reference count.
3791
3792        ALOGV("releasing mbuf %p", mediaBuffer);
3793
3794        ((MediaBuffer *)mediaBuffer)->release();
3795        mediaBuffer = NULL;
3796
3797        bufferMeta->setPointer("mediaBuffer", NULL);
3798    }
3799
3800    PortMode mode = getPortMode(kPortIndexInput);
3801
3802    switch (mode) {
3803        case KEEP_BUFFERS:
3804            break;
3805
3806        case RESUBMIT_BUFFERS:
3807            postFillThisBuffer(info);
3808            break;
3809
3810        default:
3811        {
3812            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
3813            TRESPASS();  // Not currently used
3814            break;
3815        }
3816    }
3817
3818    return true;
3819}
3820
3821void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
3822    if (mCodec->mPortEOS[kPortIndexInput]) {
3823        return;
3824    }
3825
3826    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
3827
3828    sp<AMessage> notify = mCodec->mNotify->dup();
3829    notify->setInt32("what", CodecBase::kWhatFillThisBuffer);
3830    notify->setInt32("buffer-id", info->mBufferID);
3831
3832    info->mData->meta()->clear();
3833    notify->setBuffer("buffer", info->mData);
3834
3835    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id());
3836    reply->setInt32("buffer-id", info->mBufferID);
3837
3838    notify->setMessage("reply", reply);
3839
3840    notify->post();
3841
3842    info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
3843}
3844
3845void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
3846    IOMX::buffer_id bufferID;
3847    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
3848    sp<ABuffer> buffer;
3849    int32_t err = OK;
3850    bool eos = false;
3851    PortMode mode = getPortMode(kPortIndexInput);
3852
3853    if (!msg->findBuffer("buffer", &buffer)) {
3854        /* these are unfilled buffers returned by client */
3855        CHECK(msg->findInt32("err", &err));
3856
3857        if (err == OK) {
3858            /* buffers with no errors are returned on MediaCodec.flush */
3859            mode = KEEP_BUFFERS;
3860        } else {
3861            ALOGV("[%s] saw error %d instead of an input buffer",
3862                 mCodec->mComponentName.c_str(), err);
3863            eos = true;
3864        }
3865
3866        buffer.clear();
3867    }
3868
3869    int32_t tmp;
3870    if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
3871        eos = true;
3872        err = ERROR_END_OF_STREAM;
3873    }
3874
3875    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
3876    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM);
3877
3878    info->mStatus = BufferInfo::OWNED_BY_US;
3879
3880    switch (mode) {
3881        case KEEP_BUFFERS:
3882        {
3883            if (eos) {
3884                if (!mCodec->mPortEOS[kPortIndexInput]) {
3885                    mCodec->mPortEOS[kPortIndexInput] = true;
3886                    mCodec->mInputEOSResult = err;
3887                }
3888            }
3889            break;
3890        }
3891
3892        case RESUBMIT_BUFFERS:
3893        {
3894            if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) {
3895                int64_t timeUs;
3896                CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
3897
3898                OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
3899
3900                int32_t isCSD;
3901                if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
3902                    flags |= OMX_BUFFERFLAG_CODECCONFIG;
3903                }
3904
3905                if (eos) {
3906                    flags |= OMX_BUFFERFLAG_EOS;
3907                }
3908
3909                if (buffer != info->mData) {
3910                    ALOGV("[%s] Needs to copy input data for buffer %p. (%p != %p)",
3911                         mCodec->mComponentName.c_str(),
3912                         bufferID,
3913                         buffer.get(), info->mData.get());
3914
3915                    CHECK_LE(buffer->size(), info->mData->capacity());
3916                    memcpy(info->mData->data(), buffer->data(), buffer->size());
3917                }
3918
3919                if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
3920                    ALOGV("[%s] calling emptyBuffer %p w/ codec specific data",
3921                         mCodec->mComponentName.c_str(), bufferID);
3922                } else if (flags & OMX_BUFFERFLAG_EOS) {
3923                    ALOGV("[%s] calling emptyBuffer %p w/ EOS",
3924                         mCodec->mComponentName.c_str(), bufferID);
3925                } else {
3926#if TRACK_BUFFER_TIMING
3927                    ALOGI("[%s] calling emptyBuffer %p w/ time %lld us",
3928                         mCodec->mComponentName.c_str(), bufferID, timeUs);
3929#else
3930                    ALOGV("[%s] calling emptyBuffer %p w/ time %lld us",
3931                         mCodec->mComponentName.c_str(), bufferID, timeUs);
3932#endif
3933                }
3934
3935#if TRACK_BUFFER_TIMING
3936                ACodec::BufferStats stats;
3937                stats.mEmptyBufferTimeUs = ALooper::GetNowUs();
3938                stats.mFillBufferDoneTimeUs = -1ll;
3939                mCodec->mBufferStats.add(timeUs, stats);
3940#endif
3941
3942                if (mCodec->mStoreMetaDataInOutputBuffers) {
3943                    // try to submit an output buffer for each input buffer
3944                    PortMode outputMode = getPortMode(kPortIndexOutput);
3945
3946                    ALOGV("MetaDataBuffersToSubmit=%u portMode=%s",
3947                            mCodec->mMetaDataBuffersToSubmit,
3948                            (outputMode == FREE_BUFFERS ? "FREE" :
3949                             outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT"));
3950                    if (outputMode == RESUBMIT_BUFFERS) {
3951                        mCodec->submitOutputMetaDataBuffer();
3952                    }
3953                }
3954
3955                CHECK_EQ(mCodec->mOMX->emptyBuffer(
3956                            mCodec->mNode,
3957                            bufferID,
3958                            0,
3959                            buffer->size(),
3960                            flags,
3961                            timeUs),
3962                         (status_t)OK);
3963
3964                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
3965
3966                if (!eos) {
3967                    getMoreInputDataIfPossible();
3968                } else {
3969                    ALOGV("[%s] Signalled EOS on the input port",
3970                         mCodec->mComponentName.c_str());
3971
3972                    mCodec->mPortEOS[kPortIndexInput] = true;
3973                    mCodec->mInputEOSResult = err;
3974                }
3975            } else if (!mCodec->mPortEOS[kPortIndexInput]) {
3976                if (err != ERROR_END_OF_STREAM) {
3977                    ALOGV("[%s] Signalling EOS on the input port "
3978                         "due to error %d",
3979                         mCodec->mComponentName.c_str(), err);
3980                } else {
3981                    ALOGV("[%s] Signalling EOS on the input port",
3982                         mCodec->mComponentName.c_str());
3983                }
3984
3985                ALOGV("[%s] calling emptyBuffer %p signalling EOS",
3986                     mCodec->mComponentName.c_str(), bufferID);
3987
3988                CHECK_EQ(mCodec->mOMX->emptyBuffer(
3989                            mCodec->mNode,
3990                            bufferID,
3991                            0,
3992                            0,
3993                            OMX_BUFFERFLAG_EOS,
3994                            0),
3995                         (status_t)OK);
3996
3997                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
3998
3999                mCodec->mPortEOS[kPortIndexInput] = true;
4000                mCodec->mInputEOSResult = err;
4001            }
4002            break;
4003        }
4004
4005        default:
4006            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4007            break;
4008    }
4009}
4010
4011void ACodec::BaseState::getMoreInputDataIfPossible() {
4012    if (mCodec->mPortEOS[kPortIndexInput]) {
4013        return;
4014    }
4015
4016    BufferInfo *eligible = NULL;
4017
4018    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
4019        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
4020
4021#if 0
4022        if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
4023            // There's already a "read" pending.
4024            return;
4025        }
4026#endif
4027
4028        if (info->mStatus == BufferInfo::OWNED_BY_US) {
4029            eligible = info;
4030        }
4031    }
4032
4033    if (eligible == NULL) {
4034        return;
4035    }
4036
4037    postFillThisBuffer(eligible);
4038}
4039
4040bool ACodec::BaseState::onOMXFillBufferDone(
4041        IOMX::buffer_id bufferID,
4042        size_t rangeOffset, size_t rangeLength,
4043        OMX_U32 flags,
4044        int64_t timeUs) {
4045    ALOGV("[%s] onOMXFillBufferDone %u time %" PRId64 " us, flags = 0x%08x",
4046         mCodec->mComponentName.c_str(), bufferID, timeUs, flags);
4047
4048    ssize_t index;
4049
4050#if TRACK_BUFFER_TIMING
4051    index = mCodec->mBufferStats.indexOfKey(timeUs);
4052    if (index >= 0) {
4053        ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index);
4054        stats->mFillBufferDoneTimeUs = ALooper::GetNowUs();
4055
4056        ALOGI("frame PTS %lld: %lld",
4057                timeUs,
4058                stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs);
4059
4060        mCodec->mBufferStats.removeItemsAt(index);
4061        stats = NULL;
4062    }
4063#endif
4064
4065    BufferInfo *info =
4066        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
4067
4068    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
4069
4070    info->mDequeuedAt = ++mCodec->mDequeueCounter;
4071    info->mStatus = BufferInfo::OWNED_BY_US;
4072
4073    PortMode mode = getPortMode(kPortIndexOutput);
4074
4075    switch (mode) {
4076        case KEEP_BUFFERS:
4077            break;
4078
4079        case RESUBMIT_BUFFERS:
4080        {
4081            if (rangeLength == 0 && !(flags & OMX_BUFFERFLAG_EOS)) {
4082                ALOGV("[%s] calling fillBuffer %u",
4083                     mCodec->mComponentName.c_str(), info->mBufferID);
4084
4085                CHECK_EQ(mCodec->mOMX->fillBuffer(
4086                            mCodec->mNode, info->mBufferID),
4087                         (status_t)OK);
4088
4089                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4090                break;
4091            }
4092
4093            sp<AMessage> reply =
4094                new AMessage(kWhatOutputBufferDrained, mCodec->id());
4095
4096            if (!mCodec->mSentFormat && rangeLength > 0) {
4097                mCodec->sendFormatChange(reply);
4098            }
4099
4100            if (mCodec->mUseMetadataOnEncoderOutput) {
4101                native_handle_t* handle =
4102                        *(native_handle_t**)(info->mData->data() + 4);
4103                info->mData->meta()->setPointer("handle", handle);
4104                info->mData->meta()->setInt32("rangeOffset", rangeOffset);
4105                info->mData->meta()->setInt32("rangeLength", rangeLength);
4106            } else {
4107                info->mData->setRange(rangeOffset, rangeLength);
4108            }
4109#if 0
4110            if (mCodec->mNativeWindow == NULL) {
4111                if (IsIDR(info->mData)) {
4112                    ALOGI("IDR frame");
4113                }
4114            }
4115#endif
4116
4117            if (mCodec->mSkipCutBuffer != NULL) {
4118                mCodec->mSkipCutBuffer->submit(info->mData);
4119            }
4120            info->mData->meta()->setInt64("timeUs", timeUs);
4121
4122            sp<AMessage> notify = mCodec->mNotify->dup();
4123            notify->setInt32("what", CodecBase::kWhatDrainThisBuffer);
4124            notify->setInt32("buffer-id", info->mBufferID);
4125            notify->setBuffer("buffer", info->mData);
4126            notify->setInt32("flags", flags);
4127
4128            reply->setInt32("buffer-id", info->mBufferID);
4129
4130            notify->setMessage("reply", reply);
4131
4132            notify->post();
4133
4134            info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
4135
4136            if (flags & OMX_BUFFERFLAG_EOS) {
4137                ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str());
4138
4139                sp<AMessage> notify = mCodec->mNotify->dup();
4140                notify->setInt32("what", CodecBase::kWhatEOS);
4141                notify->setInt32("err", mCodec->mInputEOSResult);
4142                notify->post();
4143
4144                mCodec->mPortEOS[kPortIndexOutput] = true;
4145            }
4146            break;
4147        }
4148
4149        default:
4150        {
4151            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4152
4153            CHECK_EQ((status_t)OK,
4154                     mCodec->freeBuffer(kPortIndexOutput, index));
4155            break;
4156        }
4157    }
4158
4159    return true;
4160}
4161
4162void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
4163    IOMX::buffer_id bufferID;
4164    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
4165    ssize_t index;
4166    BufferInfo *info =
4167        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
4168    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
4169
4170    android_native_rect_t crop;
4171    if (msg->findRect("crop",
4172            &crop.left, &crop.top, &crop.right, &crop.bottom)) {
4173        CHECK_EQ(0, native_window_set_crop(
4174                mCodec->mNativeWindow.get(), &crop));
4175    }
4176
4177    int32_t render;
4178    if (mCodec->mNativeWindow != NULL
4179            && msg->findInt32("render", &render) && render != 0
4180            && info->mData != NULL && info->mData->size() != 0) {
4181        ATRACE_NAME("render");
4182        // The client wants this buffer to be rendered.
4183
4184        int64_t timestampNs = 0;
4185        if (!msg->findInt64("timestampNs", &timestampNs)) {
4186            // TODO: it seems like we should use the timestamp
4187            // in the (media)buffer as it potentially came from
4188            // an input surface, but we did not propagate it prior to
4189            // API 20.  Perhaps check for target SDK version.
4190#if 0
4191            if (info->mData->meta()->findInt64("timeUs", &timestampNs)) {
4192                ALOGV("using buffer PTS of %" PRId64, timestampNs);
4193                timestampNs *= 1000;
4194            }
4195#endif
4196        }
4197
4198        status_t err;
4199        err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs);
4200        if (err != OK) {
4201            ALOGW("failed to set buffer timestamp: %d", err);
4202        }
4203
4204        if ((err = mCodec->mNativeWindow->queueBuffer(
4205                    mCodec->mNativeWindow.get(),
4206                    info->mGraphicBuffer.get(), -1)) == OK) {
4207            info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
4208        } else {
4209            mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
4210            info->mStatus = BufferInfo::OWNED_BY_US;
4211        }
4212    } else {
4213        if (mCodec->mNativeWindow != NULL &&
4214            (info->mData == NULL || info->mData->size() != 0)) {
4215            ATRACE_NAME("frame-drop");
4216        }
4217        info->mStatus = BufferInfo::OWNED_BY_US;
4218    }
4219
4220    PortMode mode = getPortMode(kPortIndexOutput);
4221
4222    switch (mode) {
4223        case KEEP_BUFFERS:
4224        {
4225            // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
4226
4227            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4228                // We cannot resubmit the buffer we just rendered, dequeue
4229                // the spare instead.
4230
4231                info = mCodec->dequeueBufferFromNativeWindow();
4232            }
4233            break;
4234        }
4235
4236        case RESUBMIT_BUFFERS:
4237        {
4238            if (!mCodec->mPortEOS[kPortIndexOutput]) {
4239                if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4240                    // We cannot resubmit the buffer we just rendered, dequeue
4241                    // the spare instead.
4242
4243                    info = mCodec->dequeueBufferFromNativeWindow();
4244                }
4245
4246                if (info != NULL) {
4247                    ALOGV("[%s] calling fillBuffer %u",
4248                         mCodec->mComponentName.c_str(), info->mBufferID);
4249
4250                    CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
4251                             (status_t)OK);
4252
4253                    info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4254                }
4255            }
4256            break;
4257        }
4258
4259        default:
4260        {
4261            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4262
4263            CHECK_EQ((status_t)OK,
4264                     mCodec->freeBuffer(kPortIndexOutput, index));
4265            break;
4266        }
4267    }
4268}
4269
4270////////////////////////////////////////////////////////////////////////////////
4271
4272ACodec::UninitializedState::UninitializedState(ACodec *codec)
4273    : BaseState(codec) {
4274}
4275
4276void ACodec::UninitializedState::stateEntered() {
4277    ALOGV("Now uninitialized");
4278
4279    if (mDeathNotifier != NULL) {
4280        mCodec->mOMX->asBinder()->unlinkToDeath(mDeathNotifier);
4281        mDeathNotifier.clear();
4282    }
4283
4284    mCodec->mNativeWindow.clear();
4285    mCodec->mNode = NULL;
4286    mCodec->mOMX.clear();
4287    mCodec->mQuirks = 0;
4288    mCodec->mFlags = 0;
4289    mCodec->mUseMetadataOnEncoderOutput = 0;
4290    mCodec->mComponentName.clear();
4291}
4292
4293bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
4294    bool handled = false;
4295
4296    switch (msg->what()) {
4297        case ACodec::kWhatSetup:
4298        {
4299            onSetup(msg);
4300
4301            handled = true;
4302            break;
4303        }
4304
4305        case ACodec::kWhatAllocateComponent:
4306        {
4307            onAllocateComponent(msg);
4308            handled = true;
4309            break;
4310        }
4311
4312        case ACodec::kWhatShutdown:
4313        {
4314            int32_t keepComponentAllocated;
4315            CHECK(msg->findInt32(
4316                        "keepComponentAllocated", &keepComponentAllocated));
4317            ALOGW_IF(keepComponentAllocated,
4318                     "cannot keep component allocated on shutdown in Uninitialized state");
4319
4320            sp<AMessage> notify = mCodec->mNotify->dup();
4321            notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
4322            notify->post();
4323
4324            handled = true;
4325            break;
4326        }
4327
4328        case ACodec::kWhatFlush:
4329        {
4330            sp<AMessage> notify = mCodec->mNotify->dup();
4331            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
4332            notify->post();
4333
4334            handled = true;
4335            break;
4336        }
4337
4338        default:
4339            return BaseState::onMessageReceived(msg);
4340    }
4341
4342    return handled;
4343}
4344
4345void ACodec::UninitializedState::onSetup(
4346        const sp<AMessage> &msg) {
4347    if (onAllocateComponent(msg)
4348            && mCodec->mLoadedState->onConfigureComponent(msg)) {
4349        mCodec->mLoadedState->onStart();
4350    }
4351}
4352
4353bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
4354    ALOGV("onAllocateComponent");
4355
4356    CHECK(mCodec->mNode == NULL);
4357
4358    OMXClient client;
4359    CHECK_EQ(client.connect(), (status_t)OK);
4360
4361    sp<IOMX> omx = client.interface();
4362
4363    sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec->id());
4364
4365    mDeathNotifier = new DeathNotifier(notify);
4366    if (omx->asBinder()->linkToDeath(mDeathNotifier) != OK) {
4367        // This was a local binder, if it dies so do we, we won't care
4368        // about any notifications in the afterlife.
4369        mDeathNotifier.clear();
4370    }
4371
4372    Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs;
4373
4374    AString mime;
4375
4376    AString componentName;
4377    uint32_t quirks = 0;
4378    int32_t encoder = false;
4379    if (msg->findString("componentName", &componentName)) {
4380        ssize_t index = matchingCodecs.add();
4381        OMXCodec::CodecNameAndQuirks *entry = &matchingCodecs.editItemAt(index);
4382        entry->mName = String8(componentName.c_str());
4383
4384        if (!OMXCodec::findCodecQuirks(
4385                    componentName.c_str(), &entry->mQuirks)) {
4386            entry->mQuirks = 0;
4387        }
4388    } else {
4389        CHECK(msg->findString("mime", &mime));
4390
4391        if (!msg->findInt32("encoder", &encoder)) {
4392            encoder = false;
4393        }
4394
4395        OMXCodec::findMatchingCodecs(
4396                mime.c_str(),
4397                encoder, // createEncoder
4398                NULL,  // matchComponentName
4399                0,     // flags
4400                &matchingCodecs);
4401    }
4402
4403    sp<CodecObserver> observer = new CodecObserver;
4404    IOMX::node_id node = NULL;
4405
4406    for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
4407            ++matchIndex) {
4408        componentName = matchingCodecs.itemAt(matchIndex).mName.string();
4409        quirks = matchingCodecs.itemAt(matchIndex).mQuirks;
4410
4411        pid_t tid = androidGetTid();
4412        int prevPriority = androidGetThreadPriority(tid);
4413        androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
4414        status_t err = omx->allocateNode(componentName.c_str(), observer, &node);
4415        androidSetThreadPriority(tid, prevPriority);
4416
4417        if (err == OK) {
4418            break;
4419        } else {
4420            ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str());
4421        }
4422
4423        node = NULL;
4424    }
4425
4426    if (node == NULL) {
4427        if (!mime.empty()) {
4428            ALOGE("Unable to instantiate a %scoder for type '%s'.",
4429                    encoder ? "en" : "de", mime.c_str());
4430        } else {
4431            ALOGE("Unable to instantiate codec '%s'.", componentName.c_str());
4432        }
4433
4434        mCodec->signalError(OMX_ErrorComponentNotFound);
4435        return false;
4436    }
4437
4438    notify = new AMessage(kWhatOMXMessage, mCodec->id());
4439    observer->setNotificationMessage(notify);
4440
4441    mCodec->mComponentName = componentName;
4442    mCodec->mFlags = 0;
4443
4444    if (componentName.endsWith(".secure")) {
4445        mCodec->mFlags |= kFlagIsSecure;
4446        mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
4447    }
4448
4449    mCodec->mQuirks = quirks;
4450    mCodec->mOMX = omx;
4451    mCodec->mNode = node;
4452
4453    {
4454        sp<AMessage> notify = mCodec->mNotify->dup();
4455        notify->setInt32("what", CodecBase::kWhatComponentAllocated);
4456        notify->setString("componentName", mCodec->mComponentName.c_str());
4457        notify->post();
4458    }
4459
4460    mCodec->changeState(mCodec->mLoadedState);
4461
4462    return true;
4463}
4464
4465////////////////////////////////////////////////////////////////////////////////
4466
4467ACodec::LoadedState::LoadedState(ACodec *codec)
4468    : BaseState(codec) {
4469}
4470
4471void ACodec::LoadedState::stateEntered() {
4472    ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
4473
4474    mCodec->mPortEOS[kPortIndexInput] =
4475        mCodec->mPortEOS[kPortIndexOutput] = false;
4476
4477    mCodec->mInputEOSResult = OK;
4478
4479    mCodec->mDequeueCounter = 0;
4480    mCodec->mMetaDataBuffersToSubmit = 0;
4481    mCodec->mRepeatFrameDelayUs = -1ll;
4482    mCodec->mInputFormat.clear();
4483    mCodec->mOutputFormat.clear();
4484
4485    if (mCodec->mShutdownInProgress) {
4486        bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
4487
4488        mCodec->mShutdownInProgress = false;
4489        mCodec->mKeepComponentAllocated = false;
4490
4491        onShutdown(keepComponentAllocated);
4492    }
4493    mCodec->mExplicitShutdown = false;
4494}
4495
4496void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
4497    if (!keepComponentAllocated) {
4498        CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
4499
4500        mCodec->changeState(mCodec->mUninitializedState);
4501    }
4502
4503    if (mCodec->mExplicitShutdown) {
4504        sp<AMessage> notify = mCodec->mNotify->dup();
4505        notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
4506        notify->post();
4507        mCodec->mExplicitShutdown = false;
4508    }
4509}
4510
4511bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
4512    bool handled = false;
4513
4514    switch (msg->what()) {
4515        case ACodec::kWhatConfigureComponent:
4516        {
4517            onConfigureComponent(msg);
4518            handled = true;
4519            break;
4520        }
4521
4522        case ACodec::kWhatCreateInputSurface:
4523        {
4524            onCreateInputSurface(msg);
4525            handled = true;
4526            break;
4527        }
4528
4529        case ACodec::kWhatStart:
4530        {
4531            onStart();
4532            handled = true;
4533            break;
4534        }
4535
4536        case ACodec::kWhatShutdown:
4537        {
4538            int32_t keepComponentAllocated;
4539            CHECK(msg->findInt32(
4540                        "keepComponentAllocated", &keepComponentAllocated));
4541
4542            mCodec->mExplicitShutdown = true;
4543            onShutdown(keepComponentAllocated);
4544
4545            handled = true;
4546            break;
4547        }
4548
4549        case ACodec::kWhatFlush:
4550        {
4551            sp<AMessage> notify = mCodec->mNotify->dup();
4552            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
4553            notify->post();
4554
4555            handled = true;
4556            break;
4557        }
4558
4559        default:
4560            return BaseState::onMessageReceived(msg);
4561    }
4562
4563    return handled;
4564}
4565
4566bool ACodec::LoadedState::onConfigureComponent(
4567        const sp<AMessage> &msg) {
4568    ALOGV("onConfigureComponent");
4569
4570    CHECK(mCodec->mNode != NULL);
4571
4572    AString mime;
4573    CHECK(msg->findString("mime", &mime));
4574
4575    status_t err = mCodec->configureCodec(mime.c_str(), msg);
4576
4577    if (err != OK) {
4578        ALOGE("[%s] configureCodec returning error %d",
4579              mCodec->mComponentName.c_str(), err);
4580
4581        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
4582        return false;
4583    }
4584
4585    sp<RefBase> obj;
4586    if (msg->findObject("native-window", &obj)
4587            && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) {
4588        sp<NativeWindowWrapper> nativeWindow(
4589                static_cast<NativeWindowWrapper *>(obj.get()));
4590        CHECK(nativeWindow != NULL);
4591        mCodec->mNativeWindow = nativeWindow->getNativeWindow();
4592
4593        native_window_set_scaling_mode(
4594                mCodec->mNativeWindow.get(),
4595                NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
4596    }
4597    CHECK_EQ((status_t)OK, mCodec->initNativeWindow());
4598
4599    {
4600        sp<AMessage> notify = mCodec->mNotify->dup();
4601        notify->setInt32("what", CodecBase::kWhatComponentConfigured);
4602        notify->setMessage("input-format", mCodec->mInputFormat);
4603        notify->setMessage("output-format", mCodec->mOutputFormat);
4604        notify->post();
4605    }
4606
4607    return true;
4608}
4609
4610void ACodec::LoadedState::onCreateInputSurface(
4611        const sp<AMessage> & /* msg */) {
4612    ALOGV("onCreateInputSurface");
4613
4614    sp<AMessage> notify = mCodec->mNotify->dup();
4615    notify->setInt32("what", CodecBase::kWhatInputSurfaceCreated);
4616
4617    sp<IGraphicBufferProducer> bufferProducer;
4618    status_t err;
4619
4620    err = mCodec->mOMX->createInputSurface(mCodec->mNode, kPortIndexInput,
4621            &bufferProducer);
4622
4623    if (err == OK && mCodec->mRepeatFrameDelayUs > 0ll) {
4624        err = mCodec->mOMX->setInternalOption(
4625                mCodec->mNode,
4626                kPortIndexInput,
4627                IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY,
4628                &mCodec->mRepeatFrameDelayUs,
4629                sizeof(mCodec->mRepeatFrameDelayUs));
4630
4631        if (err != OK) {
4632            ALOGE("[%s] Unable to configure option to repeat previous "
4633                  "frames (err %d)",
4634                  mCodec->mComponentName.c_str(),
4635                  err);
4636        }
4637    }
4638
4639    if (err == OK && mCodec->mMaxPtsGapUs > 0ll) {
4640        err = mCodec->mOMX->setInternalOption(
4641                mCodec->mNode,
4642                kPortIndexInput,
4643                IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP,
4644                &mCodec->mMaxPtsGapUs,
4645                sizeof(mCodec->mMaxPtsGapUs));
4646
4647        if (err != OK) {
4648            ALOGE("[%s] Unable to configure max timestamp gap (err %d)",
4649                    mCodec->mComponentName.c_str(),
4650                    err);
4651        }
4652    }
4653
4654    if (err == OK && mCodec->mTimePerCaptureUs > 0ll
4655            && mCodec->mTimePerFrameUs > 0ll) {
4656        int64_t timeLapse[2];
4657        timeLapse[0] = mCodec->mTimePerFrameUs;
4658        timeLapse[1] = mCodec->mTimePerCaptureUs;
4659        err = mCodec->mOMX->setInternalOption(
4660                mCodec->mNode,
4661                kPortIndexInput,
4662                IOMX::INTERNAL_OPTION_TIME_LAPSE,
4663                &timeLapse[0],
4664                sizeof(timeLapse));
4665
4666        if (err != OK) {
4667            ALOGE("[%s] Unable to configure time lapse (err %d)",
4668                    mCodec->mComponentName.c_str(),
4669                    err);
4670        }
4671    }
4672
4673    if (err == OK && mCodec->mCreateInputBuffersSuspended) {
4674        bool suspend = true;
4675        err = mCodec->mOMX->setInternalOption(
4676                mCodec->mNode,
4677                kPortIndexInput,
4678                IOMX::INTERNAL_OPTION_SUSPEND,
4679                &suspend,
4680                sizeof(suspend));
4681
4682        if (err != OK) {
4683            ALOGE("[%s] Unable to configure option to suspend (err %d)",
4684                  mCodec->mComponentName.c_str(),
4685                  err);
4686        }
4687    }
4688
4689    if (err == OK) {
4690        notify->setObject("input-surface",
4691                new BufferProducerWrapper(bufferProducer));
4692    } else {
4693        // Can't use mCodec->signalError() here -- MediaCodec won't forward
4694        // the error through because it's in the "configured" state.  We
4695        // send a kWhatInputSurfaceCreated with an error value instead.
4696        ALOGE("[%s] onCreateInputSurface returning error %d",
4697                mCodec->mComponentName.c_str(), err);
4698        notify->setInt32("err", err);
4699    }
4700    notify->post();
4701}
4702
4703void ACodec::LoadedState::onStart() {
4704    ALOGV("onStart");
4705
4706    CHECK_EQ(mCodec->mOMX->sendCommand(
4707                mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
4708             (status_t)OK);
4709
4710    mCodec->changeState(mCodec->mLoadedToIdleState);
4711}
4712
4713////////////////////////////////////////////////////////////////////////////////
4714
4715ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
4716    : BaseState(codec) {
4717}
4718
4719void ACodec::LoadedToIdleState::stateEntered() {
4720    ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
4721
4722    status_t err;
4723    if ((err = allocateBuffers()) != OK) {
4724        ALOGE("Failed to allocate buffers after transitioning to IDLE state "
4725             "(error 0x%08x)",
4726             err);
4727
4728        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
4729
4730        mCodec->changeState(mCodec->mLoadedState);
4731    }
4732}
4733
4734status_t ACodec::LoadedToIdleState::allocateBuffers() {
4735    status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
4736
4737    if (err != OK) {
4738        return err;
4739    }
4740
4741    return mCodec->allocateBuffersOnPort(kPortIndexOutput);
4742}
4743
4744bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
4745    switch (msg->what()) {
4746        case kWhatSetParameters:
4747        case kWhatShutdown:
4748        {
4749            mCodec->deferMessage(msg);
4750            return true;
4751        }
4752
4753        case kWhatSignalEndOfInputStream:
4754        {
4755            mCodec->onSignalEndOfInputStream();
4756            return true;
4757        }
4758
4759        case kWhatResume:
4760        {
4761            // We'll be active soon enough.
4762            return true;
4763        }
4764
4765        case kWhatFlush:
4766        {
4767            // We haven't even started yet, so we're flushed alright...
4768            sp<AMessage> notify = mCodec->mNotify->dup();
4769            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
4770            notify->post();
4771            return true;
4772        }
4773
4774        default:
4775            return BaseState::onMessageReceived(msg);
4776    }
4777}
4778
4779bool ACodec::LoadedToIdleState::onOMXEvent(
4780        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
4781    switch (event) {
4782        case OMX_EventCmdComplete:
4783        {
4784            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
4785            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
4786
4787            CHECK_EQ(mCodec->mOMX->sendCommand(
4788                        mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
4789                     (status_t)OK);
4790
4791            mCodec->changeState(mCodec->mIdleToExecutingState);
4792
4793            return true;
4794        }
4795
4796        default:
4797            return BaseState::onOMXEvent(event, data1, data2);
4798    }
4799}
4800
4801////////////////////////////////////////////////////////////////////////////////
4802
4803ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
4804    : BaseState(codec) {
4805}
4806
4807void ACodec::IdleToExecutingState::stateEntered() {
4808    ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
4809}
4810
4811bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
4812    switch (msg->what()) {
4813        case kWhatSetParameters:
4814        case kWhatShutdown:
4815        {
4816            mCodec->deferMessage(msg);
4817            return true;
4818        }
4819
4820        case kWhatResume:
4821        {
4822            // We'll be active soon enough.
4823            return true;
4824        }
4825
4826        case kWhatFlush:
4827        {
4828            // We haven't even started yet, so we're flushed alright...
4829            sp<AMessage> notify = mCodec->mNotify->dup();
4830            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
4831            notify->post();
4832
4833            return true;
4834        }
4835
4836        case kWhatSignalEndOfInputStream:
4837        {
4838            mCodec->onSignalEndOfInputStream();
4839            return true;
4840        }
4841
4842        default:
4843            return BaseState::onMessageReceived(msg);
4844    }
4845}
4846
4847bool ACodec::IdleToExecutingState::onOMXEvent(
4848        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
4849    switch (event) {
4850        case OMX_EventCmdComplete:
4851        {
4852            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
4853            CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
4854
4855            mCodec->mExecutingState->resume();
4856            mCodec->changeState(mCodec->mExecutingState);
4857
4858            return true;
4859        }
4860
4861        default:
4862            return BaseState::onOMXEvent(event, data1, data2);
4863    }
4864}
4865
4866////////////////////////////////////////////////////////////////////////////////
4867
4868ACodec::ExecutingState::ExecutingState(ACodec *codec)
4869    : BaseState(codec),
4870      mActive(false) {
4871}
4872
4873ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
4874        OMX_U32 /* portIndex */) {
4875    return RESUBMIT_BUFFERS;
4876}
4877
4878void ACodec::ExecutingState::submitOutputMetaBuffers() {
4879    // submit as many buffers as there are input buffers with the codec
4880    // in case we are in port reconfiguring
4881    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
4882        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
4883
4884        if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) {
4885            if (mCodec->submitOutputMetaDataBuffer() != OK)
4886                break;
4887        }
4888    }
4889
4890    // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
4891    mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround();
4892}
4893
4894void ACodec::ExecutingState::submitRegularOutputBuffers() {
4895    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
4896        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
4897
4898        if (mCodec->mNativeWindow != NULL) {
4899            CHECK(info->mStatus == BufferInfo::OWNED_BY_US
4900                    || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
4901
4902            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4903                continue;
4904            }
4905        } else {
4906            CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
4907        }
4908
4909        ALOGV("[%s] calling fillBuffer %p",
4910             mCodec->mComponentName.c_str(), info->mBufferID);
4911
4912        CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
4913                 (status_t)OK);
4914
4915        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4916    }
4917}
4918
4919void ACodec::ExecutingState::submitOutputBuffers() {
4920    submitRegularOutputBuffers();
4921    if (mCodec->mStoreMetaDataInOutputBuffers) {
4922        submitOutputMetaBuffers();
4923    }
4924}
4925
4926void ACodec::ExecutingState::resume() {
4927    if (mActive) {
4928        ALOGV("[%s] We're already active, no need to resume.",
4929             mCodec->mComponentName.c_str());
4930
4931        return;
4932    }
4933
4934    submitOutputBuffers();
4935
4936    // Post all available input buffers
4937    CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
4938    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) {
4939        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
4940        if (info->mStatus == BufferInfo::OWNED_BY_US) {
4941            postFillThisBuffer(info);
4942        }
4943    }
4944
4945    mActive = true;
4946}
4947
4948void ACodec::ExecutingState::stateEntered() {
4949    ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
4950
4951    mCodec->processDeferredMessages();
4952}
4953
4954bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
4955    bool handled = false;
4956
4957    switch (msg->what()) {
4958        case kWhatShutdown:
4959        {
4960            int32_t keepComponentAllocated;
4961            CHECK(msg->findInt32(
4962                        "keepComponentAllocated", &keepComponentAllocated));
4963
4964            mCodec->mShutdownInProgress = true;
4965            mCodec->mExplicitShutdown = true;
4966            mCodec->mKeepComponentAllocated = keepComponentAllocated;
4967
4968            mActive = false;
4969
4970            CHECK_EQ(mCodec->mOMX->sendCommand(
4971                        mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
4972                     (status_t)OK);
4973
4974            mCodec->changeState(mCodec->mExecutingToIdleState);
4975
4976            handled = true;
4977            break;
4978        }
4979
4980        case kWhatFlush:
4981        {
4982            ALOGV("[%s] ExecutingState flushing now "
4983                 "(codec owns %d/%d input, %d/%d output).",
4984                    mCodec->mComponentName.c_str(),
4985                    mCodec->countBuffersOwnedByComponent(kPortIndexInput),
4986                    mCodec->mBuffers[kPortIndexInput].size(),
4987                    mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
4988                    mCodec->mBuffers[kPortIndexOutput].size());
4989
4990            mActive = false;
4991
4992            CHECK_EQ(mCodec->mOMX->sendCommand(
4993                        mCodec->mNode, OMX_CommandFlush, OMX_ALL),
4994                     (status_t)OK);
4995
4996            mCodec->changeState(mCodec->mFlushingState);
4997            handled = true;
4998            break;
4999        }
5000
5001        case kWhatResume:
5002        {
5003            resume();
5004
5005            handled = true;
5006            break;
5007        }
5008
5009        case kWhatRequestIDRFrame:
5010        {
5011            status_t err = mCodec->requestIDRFrame();
5012            if (err != OK) {
5013                ALOGW("Requesting an IDR frame failed.");
5014            }
5015
5016            handled = true;
5017            break;
5018        }
5019
5020        case kWhatSetParameters:
5021        {
5022            sp<AMessage> params;
5023            CHECK(msg->findMessage("params", &params));
5024
5025            status_t err = mCodec->setParameters(params);
5026
5027            sp<AMessage> reply;
5028            if (msg->findMessage("reply", &reply)) {
5029                reply->setInt32("err", err);
5030                reply->post();
5031            }
5032
5033            handled = true;
5034            break;
5035        }
5036
5037        case ACodec::kWhatSignalEndOfInputStream:
5038        {
5039            mCodec->onSignalEndOfInputStream();
5040            handled = true;
5041            break;
5042        }
5043
5044        // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
5045        case kWhatSubmitOutputMetaDataBufferIfEOS:
5046        {
5047            if (mCodec->mPortEOS[kPortIndexInput] &&
5048                    !mCodec->mPortEOS[kPortIndexOutput]) {
5049                status_t err = mCodec->submitOutputMetaDataBuffer();
5050                if (err == OK) {
5051                    mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround();
5052                }
5053            }
5054            return true;
5055        }
5056
5057        default:
5058            handled = BaseState::onMessageReceived(msg);
5059            break;
5060    }
5061
5062    return handled;
5063}
5064
5065status_t ACodec::setParameters(const sp<AMessage> &params) {
5066    int32_t videoBitrate;
5067    if (params->findInt32("video-bitrate", &videoBitrate)) {
5068        OMX_VIDEO_CONFIG_BITRATETYPE configParams;
5069        InitOMXParams(&configParams);
5070        configParams.nPortIndex = kPortIndexOutput;
5071        configParams.nEncodeBitrate = videoBitrate;
5072
5073        status_t err = mOMX->setConfig(
5074                mNode,
5075                OMX_IndexConfigVideoBitrate,
5076                &configParams,
5077                sizeof(configParams));
5078
5079        if (err != OK) {
5080            ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d",
5081                   videoBitrate, err);
5082
5083            return err;
5084        }
5085    }
5086
5087    int64_t skipFramesBeforeUs;
5088    if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) {
5089        status_t err =
5090            mOMX->setInternalOption(
5091                     mNode,
5092                     kPortIndexInput,
5093                     IOMX::INTERNAL_OPTION_START_TIME,
5094                     &skipFramesBeforeUs,
5095                     sizeof(skipFramesBeforeUs));
5096
5097        if (err != OK) {
5098            ALOGE("Failed to set parameter 'skip-frames-before' (err %d)", err);
5099            return err;
5100        }
5101    }
5102
5103    int32_t dropInputFrames;
5104    if (params->findInt32("drop-input-frames", &dropInputFrames)) {
5105        bool suspend = dropInputFrames != 0;
5106
5107        status_t err =
5108            mOMX->setInternalOption(
5109                     mNode,
5110                     kPortIndexInput,
5111                     IOMX::INTERNAL_OPTION_SUSPEND,
5112                     &suspend,
5113                     sizeof(suspend));
5114
5115        if (err != OK) {
5116            ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err);
5117            return err;
5118        }
5119    }
5120
5121    int32_t dummy;
5122    if (params->findInt32("request-sync", &dummy)) {
5123        status_t err = requestIDRFrame();
5124
5125        if (err != OK) {
5126            ALOGE("Requesting a sync frame failed w/ err %d", err);
5127            return err;
5128        }
5129    }
5130
5131    return OK;
5132}
5133
5134void ACodec::onSignalEndOfInputStream() {
5135    sp<AMessage> notify = mNotify->dup();
5136    notify->setInt32("what", CodecBase::kWhatSignaledInputEOS);
5137
5138    status_t err = mOMX->signalEndOfInputStream(mNode);
5139    if (err != OK) {
5140        notify->setInt32("err", err);
5141    }
5142    notify->post();
5143}
5144
5145bool ACodec::ExecutingState::onOMXEvent(
5146        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5147    switch (event) {
5148        case OMX_EventPortSettingsChanged:
5149        {
5150            CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
5151
5152            if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
5153                mCodec->mMetaDataBuffersToSubmit = 0;
5154                CHECK_EQ(mCodec->mOMX->sendCommand(
5155                            mCodec->mNode,
5156                            OMX_CommandPortDisable, kPortIndexOutput),
5157                         (status_t)OK);
5158
5159                mCodec->freeOutputBuffersNotOwnedByComponent();
5160
5161                mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
5162            } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
5163                mCodec->mSentFormat = false;
5164            } else {
5165                ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
5166                     mCodec->mComponentName.c_str(), data2);
5167            }
5168
5169            return true;
5170        }
5171
5172        case OMX_EventBufferFlag:
5173        {
5174            return true;
5175        }
5176
5177        default:
5178            return BaseState::onOMXEvent(event, data1, data2);
5179    }
5180}
5181
5182////////////////////////////////////////////////////////////////////////////////
5183
5184ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
5185        ACodec *codec)
5186    : BaseState(codec) {
5187}
5188
5189ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
5190        OMX_U32 portIndex) {
5191    if (portIndex == kPortIndexOutput) {
5192        return FREE_BUFFERS;
5193    }
5194
5195    CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
5196
5197    return RESUBMIT_BUFFERS;
5198}
5199
5200bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
5201        const sp<AMessage> &msg) {
5202    bool handled = false;
5203
5204    switch (msg->what()) {
5205        case kWhatFlush:
5206        case kWhatShutdown:
5207        case kWhatResume:
5208        {
5209            if (msg->what() == kWhatResume) {
5210                ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
5211            }
5212
5213            mCodec->deferMessage(msg);
5214            handled = true;
5215            break;
5216        }
5217
5218        default:
5219            handled = BaseState::onMessageReceived(msg);
5220            break;
5221    }
5222
5223    return handled;
5224}
5225
5226void ACodec::OutputPortSettingsChangedState::stateEntered() {
5227    ALOGV("[%s] Now handling output port settings change",
5228         mCodec->mComponentName.c_str());
5229}
5230
5231bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
5232        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5233    switch (event) {
5234        case OMX_EventCmdComplete:
5235        {
5236            if (data1 == (OMX_U32)OMX_CommandPortDisable) {
5237                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
5238
5239                ALOGV("[%s] Output port now disabled.",
5240                        mCodec->mComponentName.c_str());
5241
5242                CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
5243                mCodec->mDealer[kPortIndexOutput].clear();
5244
5245                CHECK_EQ(mCodec->mOMX->sendCommand(
5246                            mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
5247                         (status_t)OK);
5248
5249                status_t err;
5250                if ((err = mCodec->allocateBuffersOnPort(
5251                                kPortIndexOutput)) != OK) {
5252                    ALOGE("Failed to allocate output port buffers after "
5253                         "port reconfiguration (error 0x%08x)",
5254                         err);
5255
5256                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5257
5258                    // This is technically not correct, but appears to be
5259                    // the only way to free the component instance.
5260                    // Controlled transitioning from excecuting->idle
5261                    // and idle->loaded seem impossible probably because
5262                    // the output port never finishes re-enabling.
5263                    mCodec->mShutdownInProgress = true;
5264                    mCodec->mKeepComponentAllocated = false;
5265                    mCodec->changeState(mCodec->mLoadedState);
5266                }
5267
5268                return true;
5269            } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
5270                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
5271
5272                mCodec->mSentFormat = false;
5273
5274                ALOGV("[%s] Output port now reenabled.",
5275                        mCodec->mComponentName.c_str());
5276
5277                if (mCodec->mExecutingState->active()) {
5278                    mCodec->mExecutingState->submitOutputBuffers();
5279                }
5280
5281                mCodec->changeState(mCodec->mExecutingState);
5282
5283                return true;
5284            }
5285
5286            return false;
5287        }
5288
5289        default:
5290            return false;
5291    }
5292}
5293
5294////////////////////////////////////////////////////////////////////////////////
5295
5296ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
5297    : BaseState(codec),
5298      mComponentNowIdle(false) {
5299}
5300
5301bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
5302    bool handled = false;
5303
5304    switch (msg->what()) {
5305        case kWhatFlush:
5306        {
5307            // Don't send me a flush request if you previously wanted me
5308            // to shutdown.
5309            TRESPASS();
5310            break;
5311        }
5312
5313        case kWhatShutdown:
5314        {
5315            // We're already doing that...
5316
5317            handled = true;
5318            break;
5319        }
5320
5321        default:
5322            handled = BaseState::onMessageReceived(msg);
5323            break;
5324    }
5325
5326    return handled;
5327}
5328
5329void ACodec::ExecutingToIdleState::stateEntered() {
5330    ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
5331
5332    mComponentNowIdle = false;
5333    mCodec->mSentFormat = false;
5334}
5335
5336bool ACodec::ExecutingToIdleState::onOMXEvent(
5337        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5338    switch (event) {
5339        case OMX_EventCmdComplete:
5340        {
5341            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
5342            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
5343
5344            mComponentNowIdle = true;
5345
5346            changeStateIfWeOwnAllBuffers();
5347
5348            return true;
5349        }
5350
5351        case OMX_EventPortSettingsChanged:
5352        case OMX_EventBufferFlag:
5353        {
5354            // We're shutting down and don't care about this anymore.
5355            return true;
5356        }
5357
5358        default:
5359            return BaseState::onOMXEvent(event, data1, data2);
5360    }
5361}
5362
5363void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
5364    if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
5365        CHECK_EQ(mCodec->mOMX->sendCommand(
5366                    mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
5367                 (status_t)OK);
5368
5369        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
5370        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
5371
5372        if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown)
5373                && mCodec->mNativeWindow != NULL) {
5374            // We push enough 1x1 blank buffers to ensure that one of
5375            // them has made it to the display.  This allows the OMX
5376            // component teardown to zero out any protected buffers
5377            // without the risk of scanning out one of those buffers.
5378            mCodec->pushBlankBuffersToNativeWindow();
5379        }
5380
5381        mCodec->changeState(mCodec->mIdleToLoadedState);
5382    }
5383}
5384
5385void ACodec::ExecutingToIdleState::onInputBufferFilled(
5386        const sp<AMessage> &msg) {
5387    BaseState::onInputBufferFilled(msg);
5388
5389    changeStateIfWeOwnAllBuffers();
5390}
5391
5392void ACodec::ExecutingToIdleState::onOutputBufferDrained(
5393        const sp<AMessage> &msg) {
5394    BaseState::onOutputBufferDrained(msg);
5395
5396    changeStateIfWeOwnAllBuffers();
5397}
5398
5399////////////////////////////////////////////////////////////////////////////////
5400
5401ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
5402    : BaseState(codec) {
5403}
5404
5405bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
5406    bool handled = false;
5407
5408    switch (msg->what()) {
5409        case kWhatShutdown:
5410        {
5411            // We're already doing that...
5412
5413            handled = true;
5414            break;
5415        }
5416
5417        case kWhatFlush:
5418        {
5419            // Don't send me a flush request if you previously wanted me
5420            // to shutdown.
5421            TRESPASS();
5422            break;
5423        }
5424
5425        default:
5426            handled = BaseState::onMessageReceived(msg);
5427            break;
5428    }
5429
5430    return handled;
5431}
5432
5433void ACodec::IdleToLoadedState::stateEntered() {
5434    ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
5435}
5436
5437bool ACodec::IdleToLoadedState::onOMXEvent(
5438        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5439    switch (event) {
5440        case OMX_EventCmdComplete:
5441        {
5442            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
5443            CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
5444
5445            mCodec->changeState(mCodec->mLoadedState);
5446
5447            return true;
5448        }
5449
5450        default:
5451            return BaseState::onOMXEvent(event, data1, data2);
5452    }
5453}
5454
5455////////////////////////////////////////////////////////////////////////////////
5456
5457ACodec::FlushingState::FlushingState(ACodec *codec)
5458    : BaseState(codec) {
5459}
5460
5461void ACodec::FlushingState::stateEntered() {
5462    ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
5463
5464    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
5465}
5466
5467bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
5468    bool handled = false;
5469
5470    switch (msg->what()) {
5471        case kWhatShutdown:
5472        {
5473            mCodec->deferMessage(msg);
5474            break;
5475        }
5476
5477        case kWhatFlush:
5478        {
5479            // We're already doing this right now.
5480            handled = true;
5481            break;
5482        }
5483
5484        default:
5485            handled = BaseState::onMessageReceived(msg);
5486            break;
5487    }
5488
5489    return handled;
5490}
5491
5492bool ACodec::FlushingState::onOMXEvent(
5493        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5494    ALOGV("[%s] FlushingState onOMXEvent(%d,%ld)",
5495            mCodec->mComponentName.c_str(), event, data1);
5496
5497    switch (event) {
5498        case OMX_EventCmdComplete:
5499        {
5500            CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
5501
5502            if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
5503                CHECK(!mFlushComplete[data2]);
5504                mFlushComplete[data2] = true;
5505
5506                if (mFlushComplete[kPortIndexInput]
5507                        && mFlushComplete[kPortIndexOutput]) {
5508                    changeStateIfWeOwnAllBuffers();
5509                }
5510            } else {
5511                CHECK_EQ(data2, OMX_ALL);
5512                CHECK(mFlushComplete[kPortIndexInput]);
5513                CHECK(mFlushComplete[kPortIndexOutput]);
5514
5515                changeStateIfWeOwnAllBuffers();
5516            }
5517
5518            return true;
5519        }
5520
5521        case OMX_EventPortSettingsChanged:
5522        {
5523            sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id());
5524            msg->setInt32("type", omx_message::EVENT);
5525            msg->setInt32("node", mCodec->mNode);
5526            msg->setInt32("event", event);
5527            msg->setInt32("data1", data1);
5528            msg->setInt32("data2", data2);
5529
5530            ALOGV("[%s] Deferring OMX_EventPortSettingsChanged",
5531                 mCodec->mComponentName.c_str());
5532
5533            mCodec->deferMessage(msg);
5534
5535            return true;
5536        }
5537
5538        default:
5539            return BaseState::onOMXEvent(event, data1, data2);
5540    }
5541
5542    return true;
5543}
5544
5545void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
5546    BaseState::onOutputBufferDrained(msg);
5547
5548    changeStateIfWeOwnAllBuffers();
5549}
5550
5551void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
5552    BaseState::onInputBufferFilled(msg);
5553
5554    changeStateIfWeOwnAllBuffers();
5555}
5556
5557void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
5558    if (mFlushComplete[kPortIndexInput]
5559            && mFlushComplete[kPortIndexOutput]
5560            && mCodec->allYourBuffersAreBelongToUs()) {
5561        // We now own all buffers except possibly those still queued with
5562        // the native window for rendering. Let's get those back as well.
5563        mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs();
5564
5565        sp<AMessage> notify = mCodec->mNotify->dup();
5566        notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5567        notify->post();
5568
5569        mCodec->mPortEOS[kPortIndexInput] =
5570            mCodec->mPortEOS[kPortIndexOutput] = false;
5571
5572        mCodec->mInputEOSResult = OK;
5573
5574        if (mCodec->mSkipCutBuffer != NULL) {
5575            mCodec->mSkipCutBuffer->clear();
5576        }
5577
5578        mCodec->changeState(mCodec->mExecutingState);
5579    }
5580}
5581
5582}  // namespace android
5583