ACodec.cpp revision 98a421bfffe6b3a1b762d11740e90787bdfeac08
1d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright/*
2d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * Copyright (C) 2010 The Android Open Source Project
3d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright *
4d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * Licensed under the Apache License, Version 2.0 (the "License");
5d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * you may not use this file except in compliance with the License.
6d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * You may obtain a copy of the License at
7d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright *
8d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright *      http://www.apache.org/licenses/LICENSE-2.0
9d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright *
10d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * Unless required by applicable law or agreed to in writing, software
11d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * distributed under the License is distributed on an "AS IS" BASIS,
12d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * See the License for the specific language governing permissions and
14d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * limitations under the License.
15d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright */
16d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
17d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright//#define LOG_NDEBUG 0
18d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#define LOG_TAG "ACodec"
19d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
20d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#ifdef __LP64__
21d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
22d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#endif
23d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
24d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#include <inttypes.h>
25d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#include <utils/Trace.h>
26d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
27d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#include <gui/Surface.h>
28d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
29d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#include <media/stagefright/ACodec.h>
30d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
31d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#include <binder/MemoryDealer.h>
32d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
33d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#include <media/stagefright/foundation/hexdump.h>
34d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#include <media/stagefright/foundation/ABuffer.h>
35d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#include <media/stagefright/foundation/ADebug.h>
36d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#include <media/stagefright/foundation/AMessage.h>
37d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#include <media/stagefright/foundation/AUtils.h>
38d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
39d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#include <media/stagefright/BufferProducerWrapper.h>
40d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#include <media/stagefright/MediaCodec.h>
41d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#include <media/stagefright/MediaCodecList.h>
42d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#include <media/stagefright/MediaDefs.h>
43d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#include <media/stagefright/OMXClient.h>
44d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#include <media/stagefright/OMXCodec.h>
45d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#include <media/stagefright/PersistentSurface.h>
46d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#include <media/stagefright/SurfaceUtils.h>
47d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#include <media/hardware/HardwareAPI.h>
48d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
49d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#include <OMX_AudioExt.h>
50d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#include <OMX_VideoExt.h>
51d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#include <OMX_Component.h>
52d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#include <OMX_IndexExt.h>
53d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#include <OMX_AsString.h>
54d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
55d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#include "include/avc_utils.h"
56d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
57d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightnamespace android {
58d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
59d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// OMX errors are directly mapped into status_t range if
60d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// there is no corresponding MediaError status code.
61d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// Use the statusFromOMXError(int32_t omxError) function.
62d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright//
63d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// Currently this is a direct map.
64d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// See frameworks/native/include/media/openmax/OMX_Core.h
65d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright//
66d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// Vendor OMX errors     from 0x90000000 - 0x9000FFFF
67d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// Extension OMX errors  from 0x8F000000 - 0x90000000
68d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// Standard OMX errors   from 0x80001000 - 0x80001024 (0x80001024 current)
69d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright//
70d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
71d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// returns true if err is a recognized OMX error code.
72d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// as OMX error is OMX_S32, this is an int32_t type
73d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatic inline bool isOMXError(int32_t err) {
74d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return (ERROR_CODEC_MIN <= err && err <= ERROR_CODEC_MAX);
75d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
76d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
77d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// converts an OMX error to a status_t
78d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatic inline status_t statusFromOMXError(int32_t omxError) {
79d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    switch (omxError) {
80d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    case OMX_ErrorInvalidComponentName:
81d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    case OMX_ErrorComponentNotFound:
82d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return NAME_NOT_FOUND; // can trigger illegal argument error for provided names.
83d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    default:
84d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return isOMXError(omxError) ? omxError : 0; // no translation required
85d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
86d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
87d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
88d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// checks and converts status_t to a non-side-effect status_t
89d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatic inline status_t makeNoSideEffectStatus(status_t err) {
90d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    switch (err) {
91d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // the following errors have side effects and may come
92d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // from other code modules. Remap for safety reasons.
93d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    case INVALID_OPERATION:
94d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    case DEAD_OBJECT:
95d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return UNKNOWN_ERROR;
96d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    default:
97d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
98d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
99d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
100d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
101d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrighttemplate<class T>
102d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatic void InitOMXParams(T *params) {
103d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    params->nSize = sizeof(T);
104d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    params->nVersion.s.nVersionMajor = 1;
105d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    params->nVersion.s.nVersionMinor = 0;
106d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    params->nVersion.s.nRevision = 0;
10739efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath    params->nVersion.s.nStep = 0;
108d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
109d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
11039efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamathstruct MessageList : public RefBase {
111d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    MessageList() {
112d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
11339efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath    virtual ~MessageList() {
114d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
115d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    std::list<sp<AMessage> > &getList() { return mList; }
11639efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamathprivate:
117d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    std::list<sp<AMessage> > mList;
118d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
119d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    DISALLOW_EVIL_CONSTRUCTORS(MessageList);
120d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright};
121d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
122d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstruct CodecObserver : public BnOMXObserver {
123d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    CodecObserver() {}
124d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
125d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    void setNotificationMessage(const sp<AMessage> &msg) {
126d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mNotify = msg;
127d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
128d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
129d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // from IOMXObserver
130489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke    virtual void onMessages(const std::list<omx_message> &messages) {
131d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (messages.empty()) {
132d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return;
133d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
134d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
135d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        sp<AMessage> notify = mNotify->dup();
136d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        bool first = true;
137d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        sp<MessageList> msgList = new MessageList();
138d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        for (std::list<omx_message>::const_iterator it = messages.cbegin();
139d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright              it != messages.cend(); ++it) {
140d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            const omx_message &omx_msg = *it;
141d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (first) {
142d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                notify->setInt32("node", omx_msg.node);
143d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                first = false;
144d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
145d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
146d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            sp<AMessage> msg = new AMessage;
147d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            msg->setInt32("type", omx_msg.type);
148d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            switch (omx_msg.type) {
149d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                case omx_message::EVENT:
150d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                {
151d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    msg->setInt32("event", omx_msg.u.event_data.event);
152d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    msg->setInt32("data1", omx_msg.u.event_data.data1);
153d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    msg->setInt32("data2", omx_msg.u.event_data.data2);
154d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    break;
155d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
156d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
157d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                case omx_message::EMPTY_BUFFER_DONE:
158d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                {
159d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    msg->setInt32("buffer", omx_msg.u.buffer_data.buffer);
160d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    msg->setInt32("fence_fd", omx_msg.fenceFd);
161d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    break;
162d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
163d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
164d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                case omx_message::FILL_BUFFER_DONE:
165d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                {
166d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    msg->setInt32(
167d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            "buffer", omx_msg.u.extended_buffer_data.buffer);
168d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    msg->setInt32(
169d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            "range_offset",
170d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            omx_msg.u.extended_buffer_data.range_offset);
171d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    msg->setInt32(
172d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            "range_length",
173d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            omx_msg.u.extended_buffer_data.range_length);
174d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    msg->setInt32(
175d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            "flags",
17671b16e81f9cbf2e288611f32c43ea7fb4a331fcfJason Gerecke                            omx_msg.u.extended_buffer_data.flags);
17771b16e81f9cbf2e288611f32c43ea7fb4a331fcfJason Gerecke                    msg->setInt64(
178489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke                            "timestamp",
179489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke                            omx_msg.u.extended_buffer_data.timestamp);
180489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke                    msg->setInt32(
181489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke                            "fence_fd", omx_msg.fenceFd);
182489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke                    break;
18312d6baa9b832f16a28f048ed5ffab75a76ed9c41Jason Gerecke                }
18412d6baa9b832f16a28f048ed5ffab75a76ed9c41Jason Gerecke
185d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                case omx_message::FRAME_RENDERED:
186d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                {
187d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    msg->setInt64(
188d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            "media_time_us", omx_msg.u.render_data.timestamp);
189d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    msg->setInt64(
190d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            "system_nano", omx_msg.u.render_data.nanoTime);
191d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    break;
192d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
193d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
194d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                default:
195d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    ALOGE("Unrecognized message type: %d", omx_msg.type);
196d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    break;
197d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
19839efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath            msgList->getList().push_back(msg);
199d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
200d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        notify->setObject("messages", msgList);
201d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        notify->post();
20239efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath    }
203d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
204d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightprotected:
205d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual ~CodecObserver() {}
206d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
207d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightprivate:
208d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    sp<AMessage> mNotify;
209d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
210d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    DISALLOW_EVIL_CONSTRUCTORS(CodecObserver);
211d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright};
212d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
213d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright////////////////////////////////////////////////////////////////////////////////
214d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
215d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstruct ACodec::BaseState : public AState {
216d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    BaseState(ACodec *codec, const sp<AState> &parentState = NULL);
217d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
218d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightprotected:
219d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    enum PortMode {
220d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        KEEP_BUFFERS,
221d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        RESUBMIT_BUFFERS,
222d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        FREE_BUFFERS,
223d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    };
224d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
225d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    ACodec *mCodec;
226d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
227d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual PortMode getPortMode(OMX_U32 portIndex);
228d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
229d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual bool onMessageReceived(const sp<AMessage> &msg);
230d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
231d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
232d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
233d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
234d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual void onInputBufferFilled(const sp<AMessage> &msg);
235d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
236d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    void postFillThisBuffer(BufferInfo *info);
237d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
238d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightprivate:
239d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // Handles an OMX message. Returns true iff message was handled.
240d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    bool onOMXMessage(const sp<AMessage> &msg);
241d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
242d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // Handles a list of messages. Returns true iff messages were handled.
243d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    bool onOMXMessageList(const sp<AMessage> &msg);
244d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
245d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // returns true iff this message is for this component and the component is alive
246d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    bool checkOMXMessage(const sp<AMessage> &msg);
247d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
248d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID, int fenceFd);
249d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
250d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    bool onOMXFillBufferDone(
251d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            IOMX::buffer_id bufferID,
252d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            size_t rangeOffset, size_t rangeLength,
253d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            OMX_U32 flags,
254d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            int64_t timeUs,
255d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            int fenceFd);
256d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
257d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual bool onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano);
258d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
259d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    void getMoreInputDataIfPossible();
260d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
261d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    DISALLOW_EVIL_CONSTRUCTORS(BaseState);
262d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright};
263d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
264d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright////////////////////////////////////////////////////////////////////////////////
265d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
266d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstruct ACodec::DeathNotifier : public IBinder::DeathRecipient {
267d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    DeathNotifier(const sp<AMessage> &notify)
268d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        : mNotify(notify) {
269d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
270d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
271d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual void binderDied(const wp<IBinder> &) {
272d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mNotify->post();
273d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
274d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
275d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightprotected:
276d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual ~DeathNotifier() {}
277d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
278d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightprivate:
279d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    sp<AMessage> mNotify;
280d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
281d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    DISALLOW_EVIL_CONSTRUCTORS(DeathNotifier);
282d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright};
283d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
284d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstruct ACodec::UninitializedState : public ACodec::BaseState {
285d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    UninitializedState(ACodec *codec);
286d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
287d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightprotected:
288d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual bool onMessageReceived(const sp<AMessage> &msg);
289d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual void stateEntered();
290d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
291d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightprivate:
292d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    void onSetup(const sp<AMessage> &msg);
293d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    bool onAllocateComponent(const sp<AMessage> &msg);
294d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
295d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    sp<DeathNotifier> mDeathNotifier;
296d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
297d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    DISALLOW_EVIL_CONSTRUCTORS(UninitializedState);
298d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright};
299d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
300d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright////////////////////////////////////////////////////////////////////////////////
301d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
302d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstruct ACodec::LoadedState : public ACodec::BaseState {
303d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    LoadedState(ACodec *codec);
304d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
305d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightprotected:
306d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual bool onMessageReceived(const sp<AMessage> &msg);
307d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual void stateEntered();
308d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
309d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightprivate:
310d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    friend struct ACodec::UninitializedState;
311d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
312d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    bool onConfigureComponent(const sp<AMessage> &msg);
313d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    void onCreateInputSurface(const sp<AMessage> &msg);
314d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    void onSetInputSurface(const sp<AMessage> &msg);
315d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    void onStart();
316d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    void onShutdown(bool keepComponentAllocated);
317d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
318d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t setupInputSurface();
319d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
320d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    DISALLOW_EVIL_CONSTRUCTORS(LoadedState);
321d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright};
322d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
323d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright////////////////////////////////////////////////////////////////////////////////
324d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
325d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstruct ACodec::LoadedToIdleState : public ACodec::BaseState {
326d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    LoadedToIdleState(ACodec *codec);
327d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3286ca70efdaef8c07e91692101c7a3ae35dc1e0cbbChih-Hung Hsiehprotected:
329d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual bool onMessageReceived(const sp<AMessage> &msg);
330d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
331d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual void stateEntered();
332d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
333d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightprivate:
334d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t allocateBuffers();
335d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
336d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState);
337d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright};
338d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
339d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright////////////////////////////////////////////////////////////////////////////////
340d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
341d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstruct ACodec::IdleToExecutingState : public ACodec::BaseState {
342d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    IdleToExecutingState(ACodec *codec);
343d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
344d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightprotected:
345d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual bool onMessageReceived(const sp<AMessage> &msg);
346d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
347d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual void stateEntered();
348d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
349d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightprivate:
350d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState);
351d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright};
352d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
353d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright////////////////////////////////////////////////////////////////////////////////
354d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
355d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstruct ACodec::ExecutingState : public ACodec::BaseState {
356d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    ExecutingState(ACodec *codec);
357d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
358d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    void submitRegularOutputBuffers();
359d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    void submitOutputMetaBuffers();
360d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    void submitOutputBuffers();
361d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
362d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // Submit output buffers to the decoder, submit input buffers to client
363d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // to fill with data.
364d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    void resume();
365d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
366d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // Returns true iff input and output buffers are in play.
367d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    bool active() const { return mActive; }
368d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
369d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightprotected:
370d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual PortMode getPortMode(OMX_U32 portIndex);
371d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual bool onMessageReceived(const sp<AMessage> &msg);
372d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual void stateEntered();
373d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
374d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
375d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual bool onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano);
376d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
377d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightprivate:
378d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    bool mActive;
379d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
380d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    DISALLOW_EVIL_CONSTRUCTORS(ExecutingState);
381d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright};
382d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
383d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright////////////////////////////////////////////////////////////////////////////////
384d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
385d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstruct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState {
386d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OutputPortSettingsChangedState(ACodec *codec);
387d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
388d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightprotected:
389d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual PortMode getPortMode(OMX_U32 portIndex);
390d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual bool onMessageReceived(const sp<AMessage> &msg);
391d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual void stateEntered();
392d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
393d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
394d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual bool onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano);
395d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
396d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightprivate:
397d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState);
398d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright};
399d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
400d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright////////////////////////////////////////////////////////////////////////////////
401d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
402d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstruct ACodec::ExecutingToIdleState : public ACodec::BaseState {
403d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    ExecutingToIdleState(ACodec *codec);
404d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
405d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightprotected:
406d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual bool onMessageReceived(const sp<AMessage> &msg);
407d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual void stateEntered();
408d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
409d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
410d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
411d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
412d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual void onInputBufferFilled(const sp<AMessage> &msg);
413d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
414d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightprivate:
415d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    void changeStateIfWeOwnAllBuffers();
416d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
417d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    bool mComponentNowIdle;
418d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
419d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState);
420d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright};
421d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
422d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright////////////////////////////////////////////////////////////////////////////////
423d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
424d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstruct ACodec::IdleToLoadedState : public ACodec::BaseState {
425d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    IdleToLoadedState(ACodec *codec);
426d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
427d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightprotected:
428d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual bool onMessageReceived(const sp<AMessage> &msg);
429d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual void stateEntered();
430d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
431d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
432d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
433d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightprivate:
434d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState);
435d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright};
436d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
437d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright////////////////////////////////////////////////////////////////////////////////
438d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
439d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstruct ACodec::FlushingState : public ACodec::BaseState {
440d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    FlushingState(ACodec *codec);
441d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
442d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightprotected:
443d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual bool onMessageReceived(const sp<AMessage> &msg);
444d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual void stateEntered();
445d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
446d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
447d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
448d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
449d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    virtual void onInputBufferFilled(const sp<AMessage> &msg);
450d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
451d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightprivate:
452d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    bool mFlushComplete[2];
453d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
454d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    void changeStateIfWeOwnAllBuffers();
455d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
456d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    DISALLOW_EVIL_CONSTRUCTORS(FlushingState);
457d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright};
458d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
459d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright////////////////////////////////////////////////////////////////////////////////
460d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
461d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::BufferInfo::setWriteFence(int fenceFd, const char *dbg) {
462d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (mFenceFd >= 0) {
463d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGW("OVERWRITE OF %s fence %d by write fence %d in %s",
464d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mIsReadFence ? "read" : "write", mFenceFd, fenceFd, dbg);
465d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
466d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mFenceFd = fenceFd;
467d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mIsReadFence = false;
468d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
469d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
470d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::BufferInfo::setReadFence(int fenceFd, const char *dbg) {
471d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (mFenceFd >= 0) {
472d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGW("OVERWRITE OF %s fence %d by read fence %d in %s",
473d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mIsReadFence ? "read" : "write", mFenceFd, fenceFd, dbg);
474d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
475d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mFenceFd = fenceFd;
476d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mIsReadFence = true;
477d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
478d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
479d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::BufferInfo::checkWriteFence(const char *dbg) {
480d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (mFenceFd >= 0 && mIsReadFence) {
481d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGD("REUSING read fence %d as write fence in %s", mFenceFd, dbg);
482d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
483d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
48439efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath
485d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::BufferInfo::checkReadFence(const char *dbg) {
486d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (mFenceFd >= 0 && !mIsReadFence) {
487d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGD("REUSING write fence %d as read fence in %s", mFenceFd, dbg);
488d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
489d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
490d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
491d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright////////////////////////////////////////////////////////////////////////////////
492d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
493d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael WrightACodec::ACodec()
494d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    : mQuirks(0),
495d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright      mNode(0),
496d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright      mNativeWindowUsageBits(0),
497d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright      mSentFormat(false),
498d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright      mIsVideo(false),
499d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright      mIsEncoder(false),
500d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright      mShutdownInProgress(false),
501d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright      mExplicitShutdown(false),
502d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright      mEncoderDelay(0),
503d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright      mEncoderPadding(0),
504d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright      mRotationDegrees(0),
505d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright      mChannelMaskPresent(false),
506d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright      mChannelMask(0),
507d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright      mDequeueCounter(0),
508d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright      mInputMetadataType(kMetadataBufferTypeInvalid),
509d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright      mOutputMetadataType(kMetadataBufferTypeInvalid),
510d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright      mLegacyAdaptiveExperiment(false),
511d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright      mMetadataBuffersToSubmit(0),
512d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright      mRepeatFrameDelayUs(-1ll),
513d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright      mMaxPtsGapUs(-1ll),
514d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright      mMaxFps(-1),
515d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright      mTimePerFrameUs(-1ll),
516d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright      mTimePerCaptureUs(-1ll),
51739efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath      mCreateInputBuffersSuspended(false),
518d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright      mTunneled(false) {
519d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mUninitializedState = new UninitializedState(this);
520d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mLoadedState = new LoadedState(this);
5210faaa0bd7aa5dadea7c365fbb1f186da6eb097efDmitry Torokhov    mLoadedToIdleState = new LoadedToIdleState(this);
5220faaa0bd7aa5dadea7c365fbb1f186da6eb097efDmitry Torokhov    mIdleToExecutingState = new IdleToExecutingState(this);
5230faaa0bd7aa5dadea7c365fbb1f186da6eb097efDmitry Torokhov    mExecutingState = new ExecutingState(this);
524d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
525d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mOutputPortSettingsChangedState =
526d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        new OutputPortSettingsChangedState(this);
527d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
528d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mExecutingToIdleState = new ExecutingToIdleState(this);
529d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mIdleToLoadedState = new IdleToLoadedState(this);
530d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mFlushingState = new FlushingState(this);
531d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
532d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false;
533d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mInputEOSResult = OK;
5340faaa0bd7aa5dadea7c365fbb1f186da6eb097efDmitry Torokhov
5350faaa0bd7aa5dadea7c365fbb1f186da6eb097efDmitry Torokhov    changeState(mUninitializedState);
5360faaa0bd7aa5dadea7c365fbb1f186da6eb097efDmitry Torokhov}
537d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
538d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael WrightACodec::~ACodec() {
539d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
540d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
541d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::setNotificationMessage(const sp<AMessage> &msg) {
542d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mNotify = msg;
543d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
544d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
545d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::initiateSetup(const sp<AMessage> &msg) {
546d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    msg->setWhat(kWhatSetup);
547d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    msg->setTarget(this);
548d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    msg->post();
549d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
550d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
551d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::signalSetParameters(const sp<AMessage> &params) {
552d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
553d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    msg->setMessage("params", params);
554d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    msg->post();
555d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
556d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
557d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::initiateAllocateComponent(const sp<AMessage> &msg) {
558d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    msg->setWhat(kWhatAllocateComponent);
55939efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath    msg->setTarget(this);
560d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    msg->post();
561d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
562d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
563d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::initiateConfigureComponent(const sp<AMessage> &msg) {
564d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    msg->setWhat(kWhatConfigureComponent);
565d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    msg->setTarget(this);
566d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    msg->post();
56739efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath}
568d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
569d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::setSurface(const sp<Surface> &surface) {
570d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    sp<AMessage> msg = new AMessage(kWhatSetSurface, this);
571d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    msg->setObject("surface", surface);
572d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
573d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    sp<AMessage> response;
574d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err = msg->postAndAwaitResponse(&response);
575d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
576d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err == OK) {
577d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        (void)response->findInt32("err", &err);
578d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
579d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return err;
580d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
581d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
582d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::initiateCreateInputSurface() {
583d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    (new AMessage(kWhatCreateInputSurface, this))->post();
584d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
585d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
586d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::initiateSetInputSurface(
587d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        const sp<PersistentSurface> &surface) {
588d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    sp<AMessage> msg = new AMessage(kWhatSetInputSurface, this);
589d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    msg->setObject("input-surface", surface);
590d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    msg->post();
591d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
592d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
593d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::signalEndOfInputStream() {
594d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    (new AMessage(kWhatSignalEndOfInputStream, this))->post();
595d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
596d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
597d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::initiateStart() {
598d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    (new AMessage(kWhatStart, this))->post();
599d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
600d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
601d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::signalFlush() {
602d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    ALOGV("[%s] signalFlush", mComponentName.c_str());
603d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    (new AMessage(kWhatFlush, this))->post();
604d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
605d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
606d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::signalResume() {
607d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    (new AMessage(kWhatResume, this))->post();
608d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
609d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
610d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::initiateShutdown(bool keepComponentAllocated) {
611d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    sp<AMessage> msg = new AMessage(kWhatShutdown, this);
612d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    msg->setInt32("keepComponentAllocated", keepComponentAllocated);
613d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    msg->post();
614d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (!keepComponentAllocated) {
615d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // ensure shutdown completes in 3 seconds
616d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        (new AMessage(kWhatReleaseCodecInstance, this))->post(3000000);
617d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
618d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
619d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
620d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::signalRequestIDRFrame() {
621d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    (new AMessage(kWhatRequestIDRFrame, this))->post();
622d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
623d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
624d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
625d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// Some codecs may return input buffers before having them processed.
626d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// This causes a halt if we already signaled an EOS on the input
627d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// port.  For now keep submitting an output buffer if there was an
628d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// EOS on the input port, but not yet on the output port.
629d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::signalSubmitOutputMetadataBufferIfEOS_workaround() {
630d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (mPortEOS[kPortIndexInput] && !mPortEOS[kPortIndexOutput] &&
631d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mMetadataBuffersToSubmit > 0) {
632d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        (new AMessage(kWhatSubmitOutputMetadataBufferIfEOS, this))->post();
633d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
634d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
635d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
636d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::handleSetSurface(const sp<Surface> &surface) {
637d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // allow keeping unset surface
638d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (surface == NULL) {
639d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (mNativeWindow != NULL) {
640d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGW("cannot unset a surface");
641d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return INVALID_OPERATION;
642d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
643d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return OK;
644d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
645d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
646d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // cannot switch from bytebuffers to surface
647d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (mNativeWindow == NULL) {
648d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGW("component was not configured with a surface");
649d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return INVALID_OPERATION;
650d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
651d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
652d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    ANativeWindow *nativeWindow = surface.get();
653d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // if we have not yet started the codec, we can simply set the native window
654d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (mBuffers[kPortIndexInput].size() == 0) {
655d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mNativeWindow = surface;
656d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return OK;
657d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
658d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
659d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // we do not support changing a tunneled surface after start
660d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (mTunneled) {
661d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGW("cannot change tunneled surface");
662d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return INVALID_OPERATION;
663d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
664d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
665d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int usageBits = 0;
666d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err = setupNativeWindowSizeFormatAndUsage(nativeWindow, &usageBits);
667d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
668d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
669d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
670d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
671d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int ignoredFlags = kVideoGrallocUsage;
672d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // New output surface is not allowed to add new usage flag except ignored ones.
673d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if ((usageBits & ~(mNativeWindowUsageBits | ignoredFlags)) != 0) {
674d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGW("cannot change usage from %#x to %#x", mNativeWindowUsageBits, usageBits);
675d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return BAD_VALUE;
676d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
677d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
678d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // get min undequeued count. We cannot switch to a surface that has a higher
679d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // undequeued count than we allocated.
680d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int minUndequeuedBuffers = 0;
681d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    err = nativeWindow->query(
682d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            nativeWindow, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
683d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            &minUndequeuedBuffers);
684d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != 0) {
68539efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath        ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
686d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                strerror(-err), -err);
687d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
688d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
68939efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath    if (minUndequeuedBuffers > (int)mNumUndequeuedBuffers) {
690d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGE("new surface holds onto more buffers (%d) than planned for (%zu)",
691d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                minUndequeuedBuffers, mNumUndequeuedBuffers);
692d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return BAD_VALUE;
69339efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath    }
694d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
695d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // we cannot change the number of output buffers while OMX is running
69639efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath    // set up surface to the same count
697d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    Vector<BufferInfo> &buffers = mBuffers[kPortIndexOutput];
698d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    ALOGV("setting up surface for %zu buffers", buffers.size());
69939efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath
700d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    err = native_window_set_buffer_count(nativeWindow, buffers.size());
701d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != 0) {
702d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
70339efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath                -err);
704d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
705d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
706d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
707d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // need to enable allocation when attaching
708d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    surface->getIGraphicBufferProducer()->allowAllocation(true);
709d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
710d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // for meta data mode, we move dequeud buffers to the new surface.
711d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // for non-meta mode, we must move all registered buffers
712d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    for (size_t i = 0; i < buffers.size(); ++i) {
713d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        const BufferInfo &info = buffers[i];
714d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // skip undequeued buffers for meta data mode
715d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (storingMetadataInDecodedBuffers()
716d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                && !mLegacyAdaptiveExperiment
717d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                && info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
718d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGV("skipping buffer %p", info.mGraphicBuffer->getNativeBuffer());
719d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            continue;
720d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
721d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGV("attaching buffer %p", info.mGraphicBuffer->getNativeBuffer());
722d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
723d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = surface->attachBuffer(info.mGraphicBuffer->getNativeBuffer());
724d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (err != OK) {
725d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGE("failed to attach buffer %p to the new surface: %s (%d)",
726d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    info.mGraphicBuffer->getNativeBuffer(),
727d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    strerror(-err), -err);
728d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return err;
729d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
730d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
731d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
732d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // cancel undequeued buffers to new surface
733d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (!storingMetadataInDecodedBuffers() || mLegacyAdaptiveExperiment) {
734d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        for (size_t i = 0; i < buffers.size(); ++i) {
735d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            BufferInfo &info = buffers.editItemAt(i);
736d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
737d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                ALOGV("canceling buffer %p", info.mGraphicBuffer->getNativeBuffer());
738d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                err = nativeWindow->cancelBuffer(
739d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        nativeWindow, info.mGraphicBuffer->getNativeBuffer(), info.mFenceFd);
740d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                info.mFenceFd = -1;
741d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                if (err != OK) {
742d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    ALOGE("failed to cancel buffer %p to the new surface: %s (%d)",
743d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            info.mGraphicBuffer->getNativeBuffer(),
744d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            strerror(-err), -err);
745d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    return err;
746d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
747d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
748d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
749d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // disallow further allocation
750d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        (void)surface->getIGraphicBufferProducer()->allowAllocation(false);
751d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
752d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
753d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // push blank buffers to previous window if requested
754d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown) {
755d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        pushBlankBuffersToNativeWindow(mNativeWindow.get());
756d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
757d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
758d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mNativeWindow = nativeWindow;
759d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mNativeWindowUsageBits = usageBits;
760d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return OK;
761d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
762d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
763d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
764d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
765d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
766d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    CHECK(mDealer[portIndex] == NULL);
767d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    CHECK(mBuffers[portIndex].isEmpty());
76839efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath
769d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err;
770d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
77139efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath        if (storingMetadataInDecodedBuffers()) {
772d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            err = allocateOutputMetadataBuffers();
773d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        } else {
774d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            err = allocateOutputBuffersFromNativeWindow();
775d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
776d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    } else {
777d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        OMX_PARAM_PORTDEFINITIONTYPE def;
77839efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath        InitOMXParams(&def);
779d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        def.nPortIndex = portIndex;
780d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
781d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = mOMX->getParameter(
782d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
783d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
784842500e146cdc0036b2a1a3e2acc7626d005128bMichael Wright        if (err == OK) {
785842500e146cdc0036b2a1a3e2acc7626d005128bMichael Wright            MetadataBufferType type =
786842500e146cdc0036b2a1a3e2acc7626d005128bMichael Wright                portIndex == kPortIndexOutput ? mOutputMetadataType : mInputMetadataType;
787842500e146cdc0036b2a1a3e2acc7626d005128bMichael Wright            int32_t bufSize = def.nBufferSize;
788842500e146cdc0036b2a1a3e2acc7626d005128bMichael Wright            if (type == kMetadataBufferTypeGrallocSource) {
789842500e146cdc0036b2a1a3e2acc7626d005128bMichael Wright                bufSize = sizeof(VideoGrallocMetadata);
790842500e146cdc0036b2a1a3e2acc7626d005128bMichael Wright            } else if (type == kMetadataBufferTypeANWBuffer) {
791842500e146cdc0036b2a1a3e2acc7626d005128bMichael Wright                bufSize = sizeof(VideoNativeMetadata);
792d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
793d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
794d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            // If using gralloc or native source input metadata buffers, allocate largest
795d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            // metadata size as we prefer to generate native source metadata, but component
796d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            // may require gralloc source. For camera source, allocate at least enough
797d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            // size for native metadata buffers.
798d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            int32_t allottedSize = bufSize;
799d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (portIndex == kPortIndexInput && type >= kMetadataBufferTypeGrallocSource) {
800d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                bufSize = max(sizeof(VideoGrallocMetadata), sizeof(VideoNativeMetadata));
801d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            } else if (portIndex == kPortIndexInput && type == kMetadataBufferTypeCameraSource) {
802d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                bufSize = max(bufSize, (int32_t)sizeof(VideoNativeMetadata));
803d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
804d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
805d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGV("[%s] Allocating %u buffers of size %d/%d (from %u using %s) on %s port",
806d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    mComponentName.c_str(),
807d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    def.nBufferCountActual, bufSize, allottedSize, def.nBufferSize, asString(type),
808d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    portIndex == kPortIndexInput ? "input" : "output");
809d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
810d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            size_t totalSize = def.nBufferCountActual * bufSize;
811d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec");
812d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
813d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            for (OMX_U32 i = 0; i < def.nBufferCountActual && err == OK; ++i) {
814d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                sp<IMemory> mem = mDealer[portIndex]->allocate(bufSize);
815d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                if (mem == NULL || mem->pointer() == NULL) {
816d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    return NO_MEMORY;
817d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
818d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
819d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                BufferInfo info;
820d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                info.mStatus = BufferInfo::OWNED_BY_US;
821d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                info.mFenceFd = -1;
822d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                info.mRenderInfo = NULL;
823d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
824d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                uint32_t requiresAllocateBufferBit =
825d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    (portIndex == kPortIndexInput)
826d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        ? OMXCodec::kRequiresAllocateBufferOnInputPorts
827d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        : OMXCodec::kRequiresAllocateBufferOnOutputPorts;
828d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
829d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                if ((portIndex == kPortIndexInput && (mFlags & kFlagIsSecure))
830d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        || (portIndex == kPortIndexOutput && usingMetadataOnEncoderOutput())) {
831d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    mem.clear();
832d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
833d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    void *ptr;
834d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    err = mOMX->allocateBuffer(
835d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            mNode, portIndex, bufSize, &info.mBufferID,
836d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            &ptr);
837d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
838d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    info.mData = new ABuffer(ptr, bufSize);
839d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                } else if (mQuirks & requiresAllocateBufferBit) {
840d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    err = mOMX->allocateBufferWithBackup(
841d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            mNode, portIndex, mem, &info.mBufferID, allottedSize);
842d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                } else {
843d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    err = mOMX->useBuffer(mNode, portIndex, mem, &info.mBufferID, allottedSize);
844d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
845d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
846d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                if (mem != NULL) {
847d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    info.mData = new ABuffer(mem->pointer(), bufSize);
848d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    if (type == kMetadataBufferTypeANWBuffer) {
849d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        ((VideoNativeMetadata *)mem->pointer())->nFenceFd = -1;
850d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    }
851d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
852d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
853d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mBuffers[portIndex].push(info);
854d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
855d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
856d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
857d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
858d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
859d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
860d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
861d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
862d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    sp<AMessage> notify = mNotify->dup();
863d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    notify->setInt32("what", CodecBase::kWhatBuffersAllocated);
864d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
865d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    notify->setInt32("portIndex", portIndex);
866d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
867d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    sp<PortDescription> desc = new PortDescription;
868d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
869d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
870d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        const BufferInfo &info = mBuffers[portIndex][i];
871d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
872d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        desc->addBuffer(info.mBufferID, info.mData);
873d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
874d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
875d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    notify->setObject("portDesc", desc);
876d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    notify->post();
877d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
878d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return OK;
87939efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath}
880d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
881d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::setupNativeWindowSizeFormatAndUsage(
882d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ANativeWindow *nativeWindow /* nonnull */, int *finalUsage /* nonnull */) {
88339efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath    OMX_PARAM_PORTDEFINITIONTYPE def;
884d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    InitOMXParams(&def);
885d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    def.nPortIndex = kPortIndexOutput;
886d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
887d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err = mOMX->getParameter(
888d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
889d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
890d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
891d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
89239efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath    }
893d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
894d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_U32 usage = 0;
895d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage);
896d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != 0) {
89739efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath        ALOGW("querying usage flags from OMX IL component failed: %d", err);
898d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // XXX: Currently this error is logged, but not fatal.
899d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        usage = 0;
900d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
901d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int omxUsage = usage;
90239efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath
903d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (mFlags & kFlagIsGrallocUsageProtected) {
904d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        usage |= GRALLOC_USAGE_PROTECTED;
905d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
906d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
90739efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath    usage |= kVideoGrallocUsage;
908d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    *finalUsage = usage;
909d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
910d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    ALOGV("gralloc usage: %#x(OMX) => %#x(ACodec)", omxUsage, usage);
911d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return setNativeWindowSizeFormatAndUsage(
912d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            nativeWindow,
913d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            def.format.video.nFrameWidth,
914d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            def.format.video.nFrameHeight,
915d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            def.format.video.eColorFormat,
916d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mRotationDegrees,
917d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            usage);
918d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
919d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
920d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::configureOutputBuffersFromNativeWindow(
921d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        OMX_U32 *bufferCount, OMX_U32 *bufferSize,
922d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        OMX_U32 *minUndequeuedBuffers) {
923d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_PARAM_PORTDEFINITIONTYPE def;
924d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    InitOMXParams(&def);
925d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    def.nPortIndex = kPortIndexOutput;
926d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
927d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err = mOMX->getParameter(
928d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
929d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
930d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err == OK) {
931d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = setupNativeWindowSizeFormatAndUsage(mNativeWindow.get(), &mNativeWindowUsageBits);
932d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
933d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
934d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mNativeWindowUsageBits = 0;
935d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
936d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
937d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
938d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // Exits here for tunneled video playback codecs -- i.e. skips native window
939d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // buffer allocation step as this is managed by the tunneled OMX omponent
940d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // itself and explicitly sets def.nBufferCountActual to 0.
941d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (mTunneled) {
942d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGV("Tunneled Playback: skipping native window buffer allocation.");
943d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        def.nBufferCountActual = 0;
944d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = mOMX->setParameter(
945d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
946d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
947d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        *minUndequeuedBuffers = 0;
948d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        *bufferCount = 0;
949d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        *bufferSize = 0;
950d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
951d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
952d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
953d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    *minUndequeuedBuffers = 0;
954d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    err = mNativeWindow->query(
955d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
956d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            (int *)minUndequeuedBuffers);
957d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
958d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != 0) {
959d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
960d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                strerror(-err), -err);
961d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
962d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
963d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
964d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // FIXME: assume that surface is controlled by app (native window
965d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // returns the number for the case when surface is not controlled by app)
966d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // FIXME2: This means that minUndeqeueudBufs can be 1 larger than reported
967d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // For now, try to allocate 1 more buffer, but don't fail if unsuccessful
968d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
969d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // Use conservative allocation while also trying to reduce starvation
970d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    //
971d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // 1. allocate at least nBufferCountMin + minUndequeuedBuffers - that is the
972d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    //    minimum needed for the consumer to be able to work
973d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // 2. try to allocate two (2) additional buffers to reduce starvation from
974d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    //    the consumer
975d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    //    plus an extra buffer to account for incorrect minUndequeuedBufs
976d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    for (OMX_U32 extraBuffers = 2 + 1; /* condition inside loop */; extraBuffers--) {
977d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        OMX_U32 newBufferCount =
978d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            def.nBufferCountMin + *minUndequeuedBuffers + extraBuffers;
979d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        def.nBufferCountActual = newBufferCount;
980d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = mOMX->setParameter(
981d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
982d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
983d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (err == OK) {
984d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            *minUndequeuedBuffers += extraBuffers;
985d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
986d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
987d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
988d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGW("[%s] setting nBufferCountActual to %u failed: %d",
989d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mComponentName.c_str(), newBufferCount, err);
990d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        /* exit condition */
991d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (extraBuffers == 0) {
992d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return err;
993d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
994d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
995d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
996d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    err = native_window_set_buffer_count(
997d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNativeWindow.get(), def.nBufferCountActual);
998d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
999d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != 0) {
1000d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
1001d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                -err);
1002d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
1003d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1004d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1005d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    *bufferCount = def.nBufferCountActual;
1006d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    *bufferSize =  def.nBufferSize;
1007d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return err;
1008d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
1009d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1010d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::allocateOutputBuffersFromNativeWindow() {
1011d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers;
1012d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err = configureOutputBuffersFromNativeWindow(
1013d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            &bufferCount, &bufferSize, &minUndequeuedBuffers);
1014d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != 0)
1015d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
1016d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mNumUndequeuedBuffers = minUndequeuedBuffers;
1017d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1018d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (!storingMetadataInDecodedBuffers()) {
1019d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        static_cast<Surface*>(mNativeWindow.get())
1020d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                ->getIGraphicBufferProducer()->allowAllocation(true);
1021d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1022d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1023d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    ALOGV("[%s] Allocating %u buffers from a native window of size %u on "
1024d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright         "output port",
1025d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright         mComponentName.c_str(), bufferCount, bufferSize);
1026d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1027d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // Dequeue buffers and send them to OMX
1028d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    for (OMX_U32 i = 0; i < bufferCount; i++) {
1029d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ANativeWindowBuffer *buf;
1030d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int fenceFd;
1031d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf, &fenceFd);
1032d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (err != 0) {
1033d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
1034d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
1035d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1036d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1037d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
1038d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        BufferInfo info;
1039d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        info.mStatus = BufferInfo::OWNED_BY_US;
1040d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        info.mFenceFd = fenceFd;
1041d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        info.mIsReadFence = false;
1042d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        info.mRenderInfo = NULL;
1043d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        info.mData = new ABuffer(NULL /* data */, bufferSize /* capacity */);
1044d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        info.mGraphicBuffer = graphicBuffer;
1045d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mBuffers[kPortIndexOutput].push(info);
1046d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1047d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        IOMX::buffer_id bufferId;
1048d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer,
1049d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                &bufferId);
1050d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (err != 0) {
1051d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGE("registering GraphicBuffer %u with OMX IL component failed: "
1052d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                 "%d", i, err);
1053d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
1054d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1055d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1056d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId;
1057d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1058d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGV("[%s] Registered graphic buffer with ID %u (pointer = %p)",
1059d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright             mComponentName.c_str(),
1060d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright             bufferId, graphicBuffer.get());
1061d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1062d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1063d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_U32 cancelStart;
1064d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_U32 cancelEnd;
1065d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1066d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != 0) {
1067d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // If an error occurred while dequeuing we need to cancel any buffers
1068d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // that were dequeued.
1069d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        cancelStart = 0;
1070d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        cancelEnd = mBuffers[kPortIndexOutput].size();
1071d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    } else {
1072d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // Return the required minimum undequeued buffers to the native window.
1073d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        cancelStart = bufferCount - minUndequeuedBuffers;
1074d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        cancelEnd = bufferCount;
1075d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1076d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1077d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
1078d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
1079d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (info->mStatus == BufferInfo::OWNED_BY_US) {
1080d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            status_t error = cancelBufferToNativeWindow(info);
1081d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (err == 0) {
1082d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                err = error;
1083d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
1084d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1085d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1086d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1087d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (!storingMetadataInDecodedBuffers()) {
1088d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        static_cast<Surface*>(mNativeWindow.get())
1089d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                ->getIGraphicBufferProducer()->allowAllocation(false);
1090d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1091d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1092d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return err;
1093d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
1094d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1095d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::allocateOutputMetadataBuffers() {
1096d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers;
1097d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err = configureOutputBuffersFromNativeWindow(
1098d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            &bufferCount, &bufferSize, &minUndequeuedBuffers);
1099d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != 0)
1100d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
1101d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mNumUndequeuedBuffers = minUndequeuedBuffers;
1102d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1103d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    ALOGV("[%s] Allocating %u meta buffers on output port",
1104d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright         mComponentName.c_str(), bufferCount);
1105d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1106d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    size_t bufSize = mOutputMetadataType == kMetadataBufferTypeANWBuffer ?
1107d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            sizeof(struct VideoNativeMetadata) : sizeof(struct VideoGrallocMetadata);
1108d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    size_t totalSize = bufferCount * bufSize;
1109d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mDealer[kPortIndexOutput] = new MemoryDealer(totalSize, "ACodec");
1110d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1111d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // Dequeue buffers and send them to OMX
1112d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    for (OMX_U32 i = 0; i < bufferCount; i++) {
1113d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        BufferInfo info;
1114d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        info.mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
1115d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        info.mFenceFd = -1;
1116d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        info.mRenderInfo = NULL;
1117d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        info.mGraphicBuffer = NULL;
1118d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        info.mDequeuedAt = mDequeueCounter;
1119d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1120d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        sp<IMemory> mem = mDealer[kPortIndexOutput]->allocate(bufSize);
1121d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (mem == NULL || mem->pointer() == NULL) {
1122d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return NO_MEMORY;
1123d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1124d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (mOutputMetadataType == kMetadataBufferTypeANWBuffer) {
1125d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ((VideoNativeMetadata *)mem->pointer())->nFenceFd = -1;
1126d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1127d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        info.mData = new ABuffer(mem->pointer(), mem->size());
1128d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1129d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // we use useBuffer for metadata regardless of quirks
1130d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = mOMX->useBuffer(
1131d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mNode, kPortIndexOutput, mem, &info.mBufferID, mem->size());
1132d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1133d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mBuffers[kPortIndexOutput].push(info);
1134d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1135d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGV("[%s] allocated meta buffer with ID %u (pointer = %p)",
1136d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright             mComponentName.c_str(), info.mBufferID, mem->pointer());
1137d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1138d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1139d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (mLegacyAdaptiveExperiment) {
1140d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // preallocate and preregister buffers
1141d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        static_cast<Surface *>(mNativeWindow.get())
1142d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                ->getIGraphicBufferProducer()->allowAllocation(true);
1143d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1144d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGV("[%s] Allocating %u buffers from a native window of size %u on "
1145d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright             "output port",
1146d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright             mComponentName.c_str(), bufferCount, bufferSize);
1147d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1148d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // Dequeue buffers then cancel them all
1149d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        for (OMX_U32 i = 0; i < bufferCount; i++) {
1150d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
1151d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1152d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ANativeWindowBuffer *buf;
1153d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            int fenceFd;
1154d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf, &fenceFd);
1155d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (err != 0) {
1156d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
1157d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                break;
1158d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
1159d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1160d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
1161d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mOMX->updateGraphicBufferInMeta(
1162d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    mNode, kPortIndexOutput, graphicBuffer, info->mBufferID);
1163d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            info->mStatus = BufferInfo::OWNED_BY_US;
1164d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            info->setWriteFence(fenceFd, "allocateOutputMetadataBuffers for legacy");
1165d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            info->mGraphicBuffer = graphicBuffer;
1166d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1167d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1168d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        for (OMX_U32 i = 0; i < mBuffers[kPortIndexOutput].size(); i++) {
1169d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
1170d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (info->mStatus == BufferInfo::OWNED_BY_US) {
1171d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                status_t error = cancelBufferToNativeWindow(info);
1172d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                if (err == OK) {
1173d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    err = error;
1174d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
1175d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
1176d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1177d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1178d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        static_cast<Surface*>(mNativeWindow.get())
1179d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                ->getIGraphicBufferProducer()->allowAllocation(false);
1180d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1181d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1182d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mMetadataBuffersToSubmit = bufferCount - minUndequeuedBuffers;
1183d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return err;
1184d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
1185d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1186d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::submitOutputMetadataBuffer() {
1187d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    CHECK(storingMetadataInDecodedBuffers());
1188d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (mMetadataBuffersToSubmit == 0)
1189d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return OK;
1190d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1191d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    BufferInfo *info = dequeueBufferFromNativeWindow();
1192d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (info == NULL) {
1193d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return ERROR_IO;
1194d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1195d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1196d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    ALOGV("[%s] submitting output meta buffer ID %u for graphic buffer %p",
1197d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright          mComponentName.c_str(), info->mBufferID, info->mGraphicBuffer.get());
1198d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1199d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    --mMetadataBuffersToSubmit;
1200d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    info->checkWriteFence("submitOutputMetadataBuffer");
1201d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err = mOMX->fillBuffer(mNode, info->mBufferID, info->mFenceFd);
1202d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    info->mFenceFd = -1;
1203d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err == OK) {
1204d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1205d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1206d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1207d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return err;
1208d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
1209d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1210d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::waitForFence(int fd, const char *dbg ) {
1211d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t res = OK;
1212d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (fd >= 0) {
1213d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        sp<Fence> fence = new Fence(fd);
1214d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        res = fence->wait(IOMX::kFenceTimeoutMs);
1215d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGW_IF(res != OK, "FENCE TIMEOUT for %d in %s", fd, dbg);
1216d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1217d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return res;
1218d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
1219d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1220d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// static
1221d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightconst char *ACodec::_asString(BufferInfo::Status s) {
1222d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    switch (s) {
1223d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case BufferInfo::OWNED_BY_US:            return "OUR";
1224d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case BufferInfo::OWNED_BY_COMPONENT:     return "COMPONENT";
1225d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case BufferInfo::OWNED_BY_UPSTREAM:      return "UPSTREAM";
1226d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case BufferInfo::OWNED_BY_DOWNSTREAM:    return "DOWNSTREAM";
1227d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case BufferInfo::OWNED_BY_NATIVE_WINDOW: return "SURFACE";
1228d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case BufferInfo::UNRECOGNIZED:           return "UNRECOGNIZED";
1229d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        default:                                 return "?";
1230d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1231d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
1232d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1233d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::dumpBuffers(OMX_U32 portIndex) {
1234d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
1235d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    ALOGI("[%s] %s port has %zu buffers:", mComponentName.c_str(),
1236d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            portIndex == kPortIndexInput ? "input" : "output", mBuffers[portIndex].size());
1237d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
1238d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        const BufferInfo &info = mBuffers[portIndex][i];
1239d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGI("  slot %2zu: #%8u %p/%p %s(%d) dequeued:%u",
1240d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                i, info.mBufferID, info.mGraphicBuffer.get(),
1241d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                info.mGraphicBuffer == NULL ? NULL : info.mGraphicBuffer->getNativeBuffer(),
1242d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                _asString(info.mStatus), info.mStatus, info.mDequeuedAt);
1243d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1244d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
1245d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1246d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) {
1247d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
1248d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1249d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    ALOGV("[%s] Calling cancelBuffer on buffer %u",
1250d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright         mComponentName.c_str(), info->mBufferID);
1251d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1252d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    info->checkWriteFence("cancelBufferToNativeWindow");
1253d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int err = mNativeWindow->cancelBuffer(
1254d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mNativeWindow.get(), info->mGraphicBuffer.get(), info->mFenceFd);
1255d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    info->mFenceFd = -1;
1256d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1257d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    ALOGW_IF(err != 0, "[%s] can not return buffer %u to native window",
1258d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mComponentName.c_str(), info->mBufferID);
1259d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // change ownership even if cancelBuffer fails
1260d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
1261d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1262d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return err;
1263d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
1264d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1265d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::updateRenderInfoForDequeuedBuffer(
1266d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ANativeWindowBuffer *buf, int fenceFd, BufferInfo *info) {
1267d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1268d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    info->mRenderInfo =
1269d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mRenderTracker.updateInfoForDequeuedBuffer(
1270d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                buf, fenceFd, info - &mBuffers[kPortIndexOutput][0]);
1271d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1272d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // check for any fences already signaled
1273d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    notifyOfRenderedFrames(false /* dropIncomplete */, info->mRenderInfo);
1274d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
1275d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1276d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::onFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) {
1277d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (mRenderTracker.onFrameRendered(mediaTimeUs, systemNano) != OK) {
1278d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mRenderTracker.dumpRenderQueue();
1279d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1280d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
1281d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1282d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::notifyOfRenderedFrames(bool dropIncomplete, FrameRenderTracker::Info *until) {
1283d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    sp<AMessage> msg = mNotify->dup();
1284d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    msg->setInt32("what", CodecBase::kWhatOutputFramesRendered);
1285d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    std::list<FrameRenderTracker::Info> done =
1286d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mRenderTracker.checkFencesAndGetRenderedFrames(until, dropIncomplete);
1287d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1288d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // unlink untracked frames
1289d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    for (std::list<FrameRenderTracker::Info>::const_iterator it = done.cbegin();
1290d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            it != done.cend(); ++it) {
1291d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ssize_t index = it->getIndex();
1292d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (index >= 0 && (size_t)index < mBuffers[kPortIndexOutput].size()) {
1293d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mBuffers[kPortIndexOutput].editItemAt(index).mRenderInfo = NULL;
1294d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        } else if (index >= 0) {
1295d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            // THIS SHOULD NEVER HAPPEN
1296d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGE("invalid index %zd in %zu", index, mBuffers[kPortIndexOutput].size());
1297d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1298d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1299d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1300d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (MediaCodec::CreateFramesRenderedMessage(done, msg)) {
1301d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        msg->post();
1302d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1303d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
1304d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1305d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael WrightACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
1306d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    ANativeWindowBuffer *buf;
1307d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    CHECK(mNativeWindow.get() != NULL);
1308d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1309d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (mTunneled) {
1310d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGW("dequeueBufferFromNativeWindow() should not be called in tunnel"
1311d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright              " video playback mode mode!");
1312d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return NULL;
1313d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1314d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1315d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int fenceFd = -1;
1316d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    do {
1317d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        status_t err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf, &fenceFd);
1318d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (err != 0) {
1319d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGE("dequeueBuffer failed: %s(%d).", asString(err), err);
1320d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return NULL;
1321d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1322d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1323d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        bool stale = false;
1324d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
1325d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
1326d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1327d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (info->mGraphicBuffer != NULL &&
1328d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    info->mGraphicBuffer->handle == buf->handle) {
1329d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                // Since consumers can attach buffers to BufferQueues, it is possible
1330d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                // that a known yet stale buffer can return from a surface that we
1331d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                // once used.  We can simply ignore this as we have already dequeued
1332d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                // this buffer properly.  NOTE: this does not eliminate all cases,
1333d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                // e.g. it is possible that we have queued the valid buffer to the
1334d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                // NW, and a stale copy of the same buffer gets dequeued - which will
1335d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                // be treated as the valid buffer by ACodec.
1336d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                if (info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1337d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    ALOGI("dequeued stale buffer %p. discarding", buf);
1338d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    stale = true;
1339d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    break;
1340d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
1341d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1342d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                ALOGV("dequeued buffer %p", info->mGraphicBuffer->getNativeBuffer());
1343d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                info->mStatus = BufferInfo::OWNED_BY_US;
1344d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                info->setWriteFence(fenceFd, "dequeueBufferFromNativeWindow");
1345d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                updateRenderInfoForDequeuedBuffer(buf, fenceFd, info);
1346d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                return info;
1347d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
1348d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1349d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1350d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // It is also possible to receive a previously unregistered buffer
1351d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // in non-meta mode. These should be treated as stale buffers. The
1352d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // same is possible in meta mode, in which case, it will be treated
1353d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // as a normal buffer, which is not desirable.
1354d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // TODO: fix this.
1355d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (!stale && (!storingMetadataInDecodedBuffers() || mLegacyAdaptiveExperiment)) {
1356d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGI("dequeued unrecognized (stale) buffer %p. discarding", buf);
1357d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            stale = true;
1358d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1359d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (stale) {
1360d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            // TODO: detach stale buffer, but there is no API yet to do it.
1361d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            buf = NULL;
1362d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1363d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    } while (buf == NULL);
1364d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1365d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // get oldest undequeued buffer
1366d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    BufferInfo *oldest = NULL;
1367d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
1368d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        BufferInfo *info =
1369d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            &mBuffers[kPortIndexOutput].editItemAt(i);
1370d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW &&
1371d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            (oldest == NULL ||
1372d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright             // avoid potential issues from counter rolling over
1373d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright             mDequeueCounter - info->mDequeuedAt >
1374d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    mDequeueCounter - oldest->mDequeuedAt)) {
1375d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            oldest = info;
1376d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1377d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1378d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1379d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // it is impossible dequeue a buffer when there are no buffers with ANW
1380d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    CHECK(oldest != NULL);
1381d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // it is impossible to dequeue an unknown buffer in non-meta mode, as the
1382d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // while loop above does not complete
1383d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    CHECK(storingMetadataInDecodedBuffers());
1384d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1385d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // discard buffer in LRU info and replace with new buffer
1386d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    oldest->mGraphicBuffer = new GraphicBuffer(buf, false);
1387d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    oldest->mStatus = BufferInfo::OWNED_BY_US;
1388d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    oldest->setWriteFence(fenceFd, "dequeueBufferFromNativeWindow for oldest");
1389d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mRenderTracker.untrackFrame(oldest->mRenderInfo);
1390d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    oldest->mRenderInfo = NULL;
1391d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1392d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mOMX->updateGraphicBufferInMeta(
1393d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, kPortIndexOutput, oldest->mGraphicBuffer,
1394d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            oldest->mBufferID);
1395d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1396d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (mOutputMetadataType == kMetadataBufferTypeGrallocSource) {
1397d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        VideoGrallocMetadata *grallocMeta =
1398d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            reinterpret_cast<VideoGrallocMetadata *>(oldest->mData->base());
1399d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)",
1400d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                (unsigned)(oldest - &mBuffers[kPortIndexOutput][0]),
1401d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mDequeueCounter - oldest->mDequeuedAt,
1402d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                (void *)(uintptr_t)grallocMeta->pHandle,
1403d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                oldest->mGraphicBuffer->handle, oldest->mData->base());
1404d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    } else if (mOutputMetadataType == kMetadataBufferTypeANWBuffer) {
1405d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        VideoNativeMetadata *nativeMeta =
1406d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            reinterpret_cast<VideoNativeMetadata *>(oldest->mData->base());
1407d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)",
1408d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                (unsigned)(oldest - &mBuffers[kPortIndexOutput][0]),
1409d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mDequeueCounter - oldest->mDequeuedAt,
1410d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                (void *)(uintptr_t)nativeMeta->pBuffer,
1411d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                oldest->mGraphicBuffer->getNativeBuffer(), oldest->mData->base());
1412d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1413d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1414d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    updateRenderInfoForDequeuedBuffer(buf, fenceFd, oldest);
1415d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return oldest;
1416d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
1417d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1418d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) {
1419d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err = OK;
1420d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    for (size_t i = mBuffers[portIndex].size(); i > 0;) {
1421d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        i--;
1422d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        status_t err2 = freeBuffer(portIndex, i);
1423d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (err == OK) {
1424d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            err = err2;
1425d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1426d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1427d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1428d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // clear mDealer even on an error
1429d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mDealer[portIndex].clear();
1430d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return err;
1431d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
1432d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1433d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::freeOutputBuffersNotOwnedByComponent() {
1434d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err = OK;
1435d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) {
1436d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        i--;
1437d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        BufferInfo *info =
1438d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            &mBuffers[kPortIndexOutput].editItemAt(i);
1439d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1440d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // At this time some buffers may still be with the component
1441d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // or being drained.
1442d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (info->mStatus != BufferInfo::OWNED_BY_COMPONENT &&
1443d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            info->mStatus != BufferInfo::OWNED_BY_DOWNSTREAM) {
1444d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            status_t err2 = freeBuffer(kPortIndexOutput, i);
1445d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (err == OK) {
1446d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                err = err2;
1447d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
1448d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1449d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1450d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1451d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return err;
1452d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
1453d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1454d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) {
1455d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
1456d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err = OK;
1457d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1458d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // there should not be any fences in the metadata
1459d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    MetadataBufferType type =
1460d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        portIndex == kPortIndexOutput ? mOutputMetadataType : mInputMetadataType;
1461d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (type == kMetadataBufferTypeANWBuffer && info->mData != NULL
1462d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            && info->mData->size() >= sizeof(VideoNativeMetadata)) {
1463d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int fenceFd = ((VideoNativeMetadata *)info->mData->data())->nFenceFd;
1464d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (fenceFd >= 0) {
1465d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGW("unreleased fence (%d) in %s metadata buffer %zu",
1466d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    fenceFd, portIndex == kPortIndexInput ? "input" : "output", i);
1467d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1468d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1469d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1470d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    switch (info->mStatus) {
1471d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case BufferInfo::OWNED_BY_US:
1472d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (portIndex == kPortIndexOutput && mNativeWindow != NULL) {
1473d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                (void)cancelBufferToNativeWindow(info);
1474d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
1475d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            // fall through
1476d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1477d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case BufferInfo::OWNED_BY_NATIVE_WINDOW:
1478d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            err = mOMX->freeBuffer(mNode, portIndex, info->mBufferID);
1479d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
1480d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1481d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        default:
1482d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGE("trying to free buffer not owned by us or ANW (%d)", info->mStatus);
1483d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            err = FAILED_TRANSACTION;
1484d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
1485d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1486d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1487d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (info->mFenceFd >= 0) {
1488d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ::close(info->mFenceFd);
1489d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1490d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1491d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (portIndex == kPortIndexOutput) {
1492d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mRenderTracker.untrackFrame(info->mRenderInfo, i);
1493d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        info->mRenderInfo = NULL;
1494d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1495d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1496d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // remove buffer even if mOMX->freeBuffer fails
1497d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mBuffers[portIndex].removeAt(i);
1498d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return err;
1499d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
1500d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1501d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael WrightACodec::BufferInfo *ACodec::findBufferByID(
1502d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        uint32_t portIndex, IOMX::buffer_id bufferID, ssize_t *index) {
1503d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
1504d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
1505d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1506d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (info->mBufferID == bufferID) {
1507d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (index != NULL) {
1508d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                *index = i;
1509d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
1510d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return info;
1511d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1512d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1513d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1514d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    ALOGE("Could not find buffer with ID %u", bufferID);
1515d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return NULL;
1516d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
1517d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1518d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::setComponentRole(
1519d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        bool isEncoder, const char *mime) {
1520d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    struct MimeToRole {
1521d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        const char *mime;
1522d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        const char *decoderRole;
1523d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        const char *encoderRole;
1524d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    };
1525d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1526d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    static const MimeToRole kMimeToRole[] = {
1527d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        { MEDIA_MIMETYPE_AUDIO_MPEG,
1528d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            "audio_decoder.mp3", "audio_encoder.mp3" },
1529d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I,
1530d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            "audio_decoder.mp1", "audio_encoder.mp1" },
15311bd2fc059c73c91f64d86b0eee59eda6ba888354Dan Albert        { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II,
15321bd2fc059c73c91f64d86b0eee59eda6ba888354Dan Albert            "audio_decoder.mp2", "audio_encoder.mp2" },
1533d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        { MEDIA_MIMETYPE_AUDIO_AMR_NB,
1534d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            "audio_decoder.amrnb", "audio_encoder.amrnb" },
1535d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        { MEDIA_MIMETYPE_AUDIO_AMR_WB,
1536d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            "audio_decoder.amrwb", "audio_encoder.amrwb" },
1537d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        { MEDIA_MIMETYPE_AUDIO_AAC,
1538d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            "audio_decoder.aac", "audio_encoder.aac" },
1539d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        { MEDIA_MIMETYPE_AUDIO_VORBIS,
1540d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            "audio_decoder.vorbis", "audio_encoder.vorbis" },
1541d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        { MEDIA_MIMETYPE_AUDIO_OPUS,
1542d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            "audio_decoder.opus", "audio_encoder.opus" },
1543d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        { MEDIA_MIMETYPE_AUDIO_G711_MLAW,
1544d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" },
1545d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        { MEDIA_MIMETYPE_AUDIO_G711_ALAW,
1546d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            "audio_decoder.g711alaw", "audio_encoder.g711alaw" },
154739efe3e5bf6282a4851e0eb3b938060c8f7790aeNarayan Kamath        { MEDIA_MIMETYPE_VIDEO_AVC,
1548d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            "video_decoder.avc", "video_encoder.avc" },
1549d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        { MEDIA_MIMETYPE_VIDEO_HEVC,
1550d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            "video_decoder.hevc", "video_encoder.hevc" },
1551d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        { MEDIA_MIMETYPE_VIDEO_MPEG4,
1552d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            "video_decoder.mpeg4", "video_encoder.mpeg4" },
1553d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        { MEDIA_MIMETYPE_VIDEO_H263,
1554d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            "video_decoder.h263", "video_encoder.h263" },
1555d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        { MEDIA_MIMETYPE_VIDEO_VP8,
1556d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            "video_decoder.vp8", "video_encoder.vp8" },
1557d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        { MEDIA_MIMETYPE_VIDEO_VP9,
1558d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            "video_decoder.vp9", "video_encoder.vp9" },
1559d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        { MEDIA_MIMETYPE_AUDIO_RAW,
1560d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            "audio_decoder.raw", "audio_encoder.raw" },
1561d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        { MEDIA_MIMETYPE_AUDIO_FLAC,
1562d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            "audio_decoder.flac", "audio_encoder.flac" },
1563d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        { MEDIA_MIMETYPE_AUDIO_MSGSM,
1564d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            "audio_decoder.gsm", "audio_encoder.gsm" },
1565d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        { MEDIA_MIMETYPE_VIDEO_MPEG2,
1566d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            "video_decoder.mpeg2", "video_encoder.mpeg2" },
1567d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        { MEDIA_MIMETYPE_AUDIO_AC3,
1568d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            "audio_decoder.ac3", "audio_encoder.ac3" },
1569d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        { MEDIA_MIMETYPE_AUDIO_EAC3,
1570d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            "audio_decoder.eac3", "audio_encoder.eac3" },
1571d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    };
1572d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1573d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    static const size_t kNumMimeToRole =
1574d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
1575d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1576d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    size_t i;
1577d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    for (i = 0; i < kNumMimeToRole; ++i) {
1578d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (!strcasecmp(mime, kMimeToRole[i].mime)) {
1579d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
1580d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1581d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1582d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1583d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (i == kNumMimeToRole) {
1584d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return ERROR_UNSUPPORTED;
1585d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1586d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1587d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    const char *role =
1588d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        isEncoder ? kMimeToRole[i].encoderRole
1589d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                  : kMimeToRole[i].decoderRole;
1590d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1591d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (role != NULL) {
1592d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        OMX_PARAM_COMPONENTROLETYPE roleParams;
1593d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        InitOMXParams(&roleParams);
1594d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1595d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        strncpy((char *)roleParams.cRole,
1596d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                role, OMX_MAX_STRINGNAME_SIZE - 1);
1597d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1598d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
1599d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1600d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        status_t err = mOMX->setParameter(
1601d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mNode, OMX_IndexParamStandardComponentRole,
1602d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                &roleParams, sizeof(roleParams));
1603d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1604d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (err != OK) {
1605d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGW("[%s] Failed to set standard component role '%s'.",
1606d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                 mComponentName.c_str(), role);
1607d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1608d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return err;
1609d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1610d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1611d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1612d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return OK;
1613d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
1614d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1615d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::configureCodec(
1616d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        const char *mime, const sp<AMessage> &msg) {
1617d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t encoder;
1618d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (!msg->findInt32("encoder", &encoder)) {
1619d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        encoder = false;
1620d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1621d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1622d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    sp<AMessage> inputFormat = new AMessage();
1623d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    sp<AMessage> outputFormat = mNotify->dup(); // will use this for kWhatOutputFormatChanged
1624d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1625d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mIsEncoder = encoder;
1626d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1627d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mInputMetadataType = kMetadataBufferTypeInvalid;
1628d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mOutputMetadataType = kMetadataBufferTypeInvalid;
1629d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1630d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err = setComponentRole(encoder /* isEncoder */, mime);
1631d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1632d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
1633d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
1634d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1635d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1636d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t bitRate = 0;
1637d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // FLAC encoder doesn't need a bitrate, other encoders do
1638d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (encoder && strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)
1639d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            && !msg->findInt32("bitrate", &bitRate)) {
1640d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return INVALID_OPERATION;
1641d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1642d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1643d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t storeMeta;
1644d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (encoder
1645d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            && msg->findInt32("store-metadata-in-buffers", &storeMeta)
1646d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            && storeMeta != 0) {
1647d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexInput, OMX_TRUE, &mInputMetadataType);
1648d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (err != OK) {
1649d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGE("[%s] storeMetaDataInBuffers (input) failed w/ err %d",
1650d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    mComponentName.c_str(), err);
1651d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1652d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return err;
1653d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1654d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // For this specific case we could be using camera source even if storeMetaDataInBuffers
1655d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // returns Gralloc source. Pretend that we are; this will force us to use nBufferSize.
1656d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (mInputMetadataType == kMetadataBufferTypeGrallocSource) {
1657d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mInputMetadataType = kMetadataBufferTypeCameraSource;
1658d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1659d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1660d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        uint32_t usageBits;
1661d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (mOMX->getParameter(
1662d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mNode, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
1663d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                &usageBits, sizeof(usageBits)) == OK) {
1664d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            inputFormat->setInt32(
1665d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    "using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN));
1666d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1667d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1668d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1669d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t prependSPSPPS = 0;
1670d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (encoder
1671d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            && msg->findInt32("prepend-sps-pps-to-idr-frames", &prependSPSPPS)
1672d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            && prependSPSPPS != 0) {
1673d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        OMX_INDEXTYPE index;
1674d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = mOMX->getExtensionIndex(
1675d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mNode,
1676d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                "OMX.google.android.index.prependSPSPPSToIDRFrames",
1677d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                &index);
1678d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1679d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (err == OK) {
1680d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            PrependSPSPPSToIDRFramesParams params;
1681d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            InitOMXParams(&params);
1682d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            params.bEnable = OMX_TRUE;
1683d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1684d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            err = mOMX->setParameter(
1685d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    mNode, index, &params, sizeof(params));
1686d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1687d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1688d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (err != OK) {
1689d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGE("Encoder could not be configured to emit SPS/PPS before "
1690d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                  "IDR frames. (err %d)", err);
1691d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1692d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return err;
1693d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1694d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1695d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1696d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // Only enable metadata mode on encoder output if encoder can prepend
1697d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // sps/pps to idr frames, since in metadata mode the bitstream is in an
1698d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // opaque handle, to which we don't have access.
1699d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t video = !strncasecmp(mime, "video/", 6);
1700d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mIsVideo = video;
1701d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (encoder && video) {
1702d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        OMX_BOOL enable = (OMX_BOOL) (prependSPSPPS
1703d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            && msg->findInt32("store-metadata-in-buffers-output", &storeMeta)
1704d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            && storeMeta != 0);
1705d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1706d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, enable, &mOutputMetadataType);
1707d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (err != OK) {
1708d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGE("[%s] storeMetaDataInBuffers (output) failed w/ err %d",
1709d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mComponentName.c_str(), err);
1710d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1711d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1712d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (!msg->findInt64(
1713d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    "repeat-previous-frame-after",
1714d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    &mRepeatFrameDelayUs)) {
1715d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mRepeatFrameDelayUs = -1ll;
1716d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1717d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1718d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (!msg->findInt64("max-pts-gap-to-encoder", &mMaxPtsGapUs)) {
1719d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mMaxPtsGapUs = -1ll;
1720d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1721d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1722d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (!msg->findFloat("max-fps-to-encoder", &mMaxFps)) {
1723d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mMaxFps = -1;
1724d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1725d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1726d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (!msg->findInt64("time-lapse", &mTimePerCaptureUs)) {
1727d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mTimePerCaptureUs = -1ll;
1728d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1729d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1730d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (!msg->findInt32(
1731d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    "create-input-buffers-suspended",
1732d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    (int32_t*)&mCreateInputBuffersSuspended)) {
1733d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mCreateInputBuffersSuspended = false;
1734d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1735d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1736d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1737d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // NOTE: we only use native window for video decoders
1738d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    sp<RefBase> obj;
1739d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    bool haveNativeWindow = msg->findObject("native-window", &obj)
1740d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            && obj != NULL && video && !encoder;
1741d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mLegacyAdaptiveExperiment = false;
1742d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (video && !encoder) {
1743d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        inputFormat->setInt32("adaptive-playback", false);
1744d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1745d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t usageProtected;
1746d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (msg->findInt32("protected", &usageProtected) && usageProtected) {
1747d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (!haveNativeWindow) {
1748d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                ALOGE("protected output buffers must be sent to an ANativeWindow");
1749d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                return PERMISSION_DENIED;
1750d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
1751d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mFlags |= kFlagIsGrallocUsageProtected;
1752d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
1753d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1754d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1755d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (haveNativeWindow) {
1756d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        sp<ANativeWindow> nativeWindow =
1757d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            static_cast<ANativeWindow *>(static_cast<Surface *>(obj.get()));
1758d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1759d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // START of temporary support for automatic FRC - THIS WILL BE REMOVED
1760d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t autoFrc;
1761d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (msg->findInt32("auto-frc", &autoFrc)) {
1762d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            bool enabled = autoFrc;
1763d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            OMX_CONFIG_BOOLEANTYPE config;
1764d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            InitOMXParams(&config);
1765d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            config.bEnabled = (OMX_BOOL)enabled;
1766d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            status_t temp = mOMX->setConfig(
1767d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    mNode, (OMX_INDEXTYPE)OMX_IndexConfigAutoFramerateConversion,
1768d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    &config, sizeof(config));
1769d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (temp == OK) {
1770d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                outputFormat->setInt32("auto-frc", enabled);
1771d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            } else if (enabled) {
1772d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                ALOGI("codec does not support requested auto-frc (err %d)", temp);
1773d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
1774d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1775d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // END of temporary support for automatic FRC
1776d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1777d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t tunneled;
1778d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (msg->findInt32("feature-tunneled-playback", &tunneled) &&
1779d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            tunneled != 0) {
1780d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGI("Configuring TUNNELED video playback.");
1781d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mTunneled = true;
1782d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1783d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            int32_t audioHwSync = 0;
1784d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (!msg->findInt32("audio-hw-sync", &audioHwSync)) {
1785d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                ALOGW("No Audio HW Sync provided for video tunnel");
1786d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
1787d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            err = configureTunneledVideoPlayback(audioHwSync, nativeWindow);
1788d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (err != OK) {
1789d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                ALOGE("configureTunneledVideoPlayback(%d,%p) failed!",
1790d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        audioHwSync, nativeWindow.get());
1791d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                return err;
1792d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
1793d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1794d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            int32_t maxWidth = 0, maxHeight = 0;
1795d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (msg->findInt32("max-width", &maxWidth) &&
1796d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    msg->findInt32("max-height", &maxHeight)) {
1797d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1798d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                err = mOMX->prepareForAdaptivePlayback(
1799d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        mNode, kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight);
1800d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                if (err != OK) {
1801d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    ALOGW("[%s] prepareForAdaptivePlayback failed w/ err %d",
1802d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            mComponentName.c_str(), err);
1803d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    // allow failure
1804d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    err = OK;
1805d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                } else {
1806d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    inputFormat->setInt32("max-width", maxWidth);
1807d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    inputFormat->setInt32("max-height", maxHeight);
1808d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    inputFormat->setInt32("adaptive-playback", true);
1809d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
1810d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
1811d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        } else {
1812d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGV("Configuring CPU controlled video playback.");
1813d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mTunneled = false;
1814d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1815d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            // Explicity reset the sideband handle of the window for
1816d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            // non-tunneled video in case the window was previously used
1817d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            // for a tunneled video playback.
1818d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            err = native_window_set_sideband_stream(nativeWindow.get(), NULL);
1819d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (err != OK) {
1820d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                ALOGE("set_sideband_stream(NULL) failed! (err %d).", err);
1821d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                return err;
1822d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
1823d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1824d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            // Always try to enable dynamic output buffers on native surface
1825d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            err = mOMX->storeMetaDataInBuffers(
1826d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    mNode, kPortIndexOutput, OMX_TRUE, &mOutputMetadataType);
1827d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (err != OK) {
1828d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                ALOGE("[%s] storeMetaDataInBuffers failed w/ err %d",
1829d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        mComponentName.c_str(), err);
1830d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1831d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                // if adaptive playback has been requested, try JB fallback
1832d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                // NOTE: THIS FALLBACK MECHANISM WILL BE REMOVED DUE TO ITS
1833d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                // LARGE MEMORY REQUIREMENT
1834d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1835d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                // we will not do adaptive playback on software accessed
1836d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                // surfaces as they never had to respond to changes in the
1837d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                // crop window, and we don't trust that they will be able to.
1838d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                int usageBits = 0;
1839d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                bool canDoAdaptivePlayback;
1840d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1841d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                if (nativeWindow->query(
1842d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        nativeWindow.get(),
1843d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        NATIVE_WINDOW_CONSUMER_USAGE_BITS,
1844d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        &usageBits) != OK) {
1845d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    canDoAdaptivePlayback = false;
1846d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                } else {
1847d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    canDoAdaptivePlayback =
1848d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        (usageBits &
1849d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                (GRALLOC_USAGE_SW_READ_MASK |
1850d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                 GRALLOC_USAGE_SW_WRITE_MASK)) == 0;
1851d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
1852d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1853d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                int32_t maxWidth = 0, maxHeight = 0;
1854d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                if (canDoAdaptivePlayback &&
1855d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        msg->findInt32("max-width", &maxWidth) &&
1856d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        msg->findInt32("max-height", &maxHeight)) {
1857d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    ALOGV("[%s] prepareForAdaptivePlayback(%dx%d)",
1858d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            mComponentName.c_str(), maxWidth, maxHeight);
1859d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1860d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    err = mOMX->prepareForAdaptivePlayback(
1861d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            mNode, kPortIndexOutput, OMX_TRUE, maxWidth,
1862d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            maxHeight);
1863d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    ALOGW_IF(err != OK,
1864d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            "[%s] prepareForAdaptivePlayback failed w/ err %d",
1865d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            mComponentName.c_str(), err);
1866d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1867d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    if (err == OK) {
1868d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        inputFormat->setInt32("max-width", maxWidth);
1869d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        inputFormat->setInt32("max-height", maxHeight);
1870d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        inputFormat->setInt32("adaptive-playback", true);
1871d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    }
1872d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
1873d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                // allow failure
1874d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                err = OK;
1875d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            } else {
1876d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                ALOGV("[%s] storeMetaDataInBuffers succeeded",
1877d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        mComponentName.c_str());
1878d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                CHECK(storingMetadataInDecodedBuffers());
1879d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mLegacyAdaptiveExperiment = ADebug::isExperimentEnabled(
1880d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        "legacy-adaptive", !msg->contains("no-experiments"));
1881d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1882d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                inputFormat->setInt32("adaptive-playback", true);
1883d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
1884d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1885d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            int32_t push;
1886d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (msg->findInt32("push-blank-buffers-on-shutdown", &push)
1887d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    && push != 0) {
1888d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
1889d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
1890d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1891d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1892d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t rotationDegrees;
1893d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (msg->findInt32("rotation-degrees", &rotationDegrees)) {
1894d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mRotationDegrees = rotationDegrees;
1895d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        } else {
1896d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mRotationDegrees = 0;
1897d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1898d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
1899d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1900d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (video) {
1901d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // determine need for software renderer
1902d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        bool usingSwRenderer = false;
1903d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (haveNativeWindow && mComponentName.startsWith("OMX.google.")) {
1904d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            usingSwRenderer = true;
1905d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            haveNativeWindow = false;
1906d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1907d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1908d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (encoder) {
1909d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            err = setupVideoEncoder(mime, msg);
1910d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        } else {
1911d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            err = setupVideoDecoder(mime, msg, haveNativeWindow);
1912d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1913d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1914d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (err != OK) {
1915d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return err;
1916d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1917d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1918d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (haveNativeWindow) {
1919d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNativeWindow = static_cast<Surface *>(obj.get());
1920d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1921d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1922d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // initialize native window now to get actual output format
1923d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // TODO: this is needed for some encoders even though they don't use native window
1924d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = initNativeWindow();
1925d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (err != OK) {
1926d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return err;
1927d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1928d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1929d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // fallback for devices that do not handle flex-YUV for native buffers
1930d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (haveNativeWindow) {
1931d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            int32_t requestedColorFormat = OMX_COLOR_FormatUnused;
1932d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (msg->findInt32("color-format", &requestedColorFormat) &&
1933d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    requestedColorFormat == OMX_COLOR_FormatYUV420Flexible) {
1934d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                status_t err = getPortFormat(kPortIndexOutput, outputFormat);
1935d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                if (err != OK) {
1936d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    return err;
1937d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
1938d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                int32_t colorFormat = OMX_COLOR_FormatUnused;
1939d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                OMX_U32 flexibleEquivalent = OMX_COLOR_FormatUnused;
1940d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                if (!outputFormat->findInt32("color-format", &colorFormat)) {
1941d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    ALOGE("ouptut port did not have a color format (wrong domain?)");
1942d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    return BAD_VALUE;
1943d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
1944d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                ALOGD("[%s] Requested output format %#x and got %#x.",
1945d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        mComponentName.c_str(), requestedColorFormat, colorFormat);
1946d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                if (!isFlexibleColorFormat(
1947d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                mOMX, mNode, colorFormat, haveNativeWindow, &flexibleEquivalent)
1948d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        || flexibleEquivalent != (OMX_U32)requestedColorFormat) {
1949d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    // device did not handle flex-YUV request for native window, fall back
1950d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    // to SW renderer
1951d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    ALOGI("[%s] Falling back to software renderer", mComponentName.c_str());
1952d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    mNativeWindow.clear();
1953d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    mNativeWindowUsageBits = 0;
1954d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    haveNativeWindow = false;
1955d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    usingSwRenderer = true;
1956d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    if (storingMetadataInDecodedBuffers()) {
1957d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        err = mOMX->storeMetaDataInBuffers(
1958d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                mNode, kPortIndexOutput, OMX_FALSE, &mOutputMetadataType);
1959d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        mOutputMetadataType = kMetadataBufferTypeInvalid; // just in case
1960d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        // TODO: implement adaptive-playback support for bytebuffer mode.
1961d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        // This is done by SW codecs, but most HW codecs don't support it.
1962d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        inputFormat->setInt32("adaptive-playback", false);
1963d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    }
1964d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    if (err == OK) {
1965d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        err = mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE);
1966d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    }
1967d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    if (mFlags & kFlagIsGrallocUsageProtected) {
1968d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        // fallback is not supported for protected playback
1969d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        err = PERMISSION_DENIED;
1970d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    } else if (err == OK) {
1971d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        err = setupVideoDecoder(mime, msg, false);
1972d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    }
1973d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
1974d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
1975d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1976d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
1977d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (usingSwRenderer) {
1978d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            outputFormat->setInt32("using-sw-renderer", 1);
1979d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1980d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
1981d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t numChannels, sampleRate;
1982d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (!msg->findInt32("channel-count", &numChannels)
1983d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                || !msg->findInt32("sample-rate", &sampleRate)) {
1984d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            // Since we did not always check for these, leave them optional
1985d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            // and have the decoder figure it all out.
1986d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            err = OK;
1987d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        } else {
1988d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            err = setupRawAudioFormat(
1989d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    encoder ? kPortIndexInput : kPortIndexOutput,
1990d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    sampleRate,
1991d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    numChannels);
1992d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
1993d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
1994d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t numChannels, sampleRate;
1995d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (!msg->findInt32("channel-count", &numChannels)
1996d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                || !msg->findInt32("sample-rate", &sampleRate)) {
1997d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            err = INVALID_OPERATION;
1998d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        } else {
1999d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            int32_t isADTS, aacProfile;
2000d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            int32_t sbrMode;
2001d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            int32_t maxOutputChannelCount;
2002d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            int32_t pcmLimiterEnable;
2003d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            drcParams_t drc;
2004d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (!msg->findInt32("is-adts", &isADTS)) {
2005d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                isADTS = 0;
2006d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
2007d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (!msg->findInt32("aac-profile", &aacProfile)) {
2008d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                aacProfile = OMX_AUDIO_AACObjectNull;
2009d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
2010d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (!msg->findInt32("aac-sbr-mode", &sbrMode)) {
2011d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                sbrMode = -1;
2012d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
2013d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2014d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (!msg->findInt32("aac-max-output-channel_count", &maxOutputChannelCount)) {
2015d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                maxOutputChannelCount = -1;
2016d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
2017d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (!msg->findInt32("aac-pcm-limiter-enable", &pcmLimiterEnable)) {
2018d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                // value is unknown
2019d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                pcmLimiterEnable = -1;
2020d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
2021d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (!msg->findInt32("aac-encoded-target-level", &drc.encodedTargetLevel)) {
2022d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                // value is unknown
2023d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                drc.encodedTargetLevel = -1;
2024d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
2025d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (!msg->findInt32("aac-drc-cut-level", &drc.drcCut)) {
2026d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                // value is unknown
2027d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                drc.drcCut = -1;
2028d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
2029d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (!msg->findInt32("aac-drc-boost-level", &drc.drcBoost)) {
2030d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                // value is unknown
2031d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                drc.drcBoost = -1;
2032d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
2033d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (!msg->findInt32("aac-drc-heavy-compression", &drc.heavyCompression)) {
2034d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                // value is unknown
2035d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                drc.heavyCompression = -1;
2036d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
2037d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (!msg->findInt32("aac-target-ref-level", &drc.targetRefLevel)) {
2038d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                // value is unknown
2039d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                drc.targetRefLevel = -1;
2040d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
2041d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2042d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            err = setupAACCodec(
2043d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    encoder, numChannels, sampleRate, bitRate, aacProfile,
2044d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    isADTS != 0, sbrMode, maxOutputChannelCount, drc,
2045d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    pcmLimiterEnable);
2046d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
2047d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
2048d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = setupAMRCodec(encoder, false /* isWAMR */, bitRate);
2049d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
2050d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = setupAMRCodec(encoder, true /* isWAMR */, bitRate);
2051d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW)
2052d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) {
2053d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // These are PCM-like formats with a fixed sample rate but
2054d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // a variable number of channels.
2055d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2056d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t numChannels;
2057d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (!msg->findInt32("channel-count", &numChannels)) {
2058d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            err = INVALID_OPERATION;
2059d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        } else {
2060d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            int32_t sampleRate;
2061d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (!msg->findInt32("sample-rate", &sampleRate)) {
2062d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                sampleRate = 8000;
2063d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
2064d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            err = setupG711Codec(encoder, sampleRate, numChannels);
2065d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
2066d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) {
2067d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t numChannels = 0, sampleRate = 0, compressionLevel = -1;
2068d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (encoder &&
2069d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                (!msg->findInt32("channel-count", &numChannels)
2070d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        || !msg->findInt32("sample-rate", &sampleRate))) {
2071d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGE("missing channel count or sample rate for FLAC encoder");
2072d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            err = INVALID_OPERATION;
2073d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        } else {
2074d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (encoder) {
2075d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                if (!msg->findInt32(
2076d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            "complexity", &compressionLevel) &&
2077d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    !msg->findInt32(
2078d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            "flac-compression-level", &compressionLevel)) {
2079d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    compressionLevel = 5; // default FLAC compression level
2080d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                } else if (compressionLevel < 0) {
2081fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                    ALOGW("compression level %d outside [0..8] range, "
2082fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                          "using 0",
2083fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                          compressionLevel);
2084fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                    compressionLevel = 0;
2085fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                } else if (compressionLevel > 8) {
2086fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                    ALOGW("compression level %d outside [0..8] range, "
2087fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                          "using 8",
2088fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                          compressionLevel);
2089fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                    compressionLevel = 8;
2090fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                }
2091fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            }
2092fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            err = setupFlacCodec(
2093fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                    encoder, numChannels, sampleRate, compressionLevel);
2094fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        }
2095fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
2096fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        int32_t numChannels, sampleRate;
2097fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        if (encoder
2098fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                || !msg->findInt32("channel-count", &numChannels)
2099fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                || !msg->findInt32("sample-rate", &sampleRate)) {
2100d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            err = INVALID_OPERATION;
2101d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        } else {
2102d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
2103d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
2104d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AC3)) {
2105d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t numChannels;
2106d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t sampleRate;
2107d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (!msg->findInt32("channel-count", &numChannels)
2108fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                || !msg->findInt32("sample-rate", &sampleRate)) {
2109fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            err = INVALID_OPERATION;
2110fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        } else {
2111fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            err = setupAC3Codec(encoder, numChannels, sampleRate);
2112fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        }
2113fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_EAC3)) {
2114fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        int32_t numChannels;
2115fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        int32_t sampleRate;
2116fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        if (!msg->findInt32("channel-count", &numChannels)
2117fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                || !msg->findInt32("sample-rate", &sampleRate)) {
2118fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            err = INVALID_OPERATION;
2119fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        } else {
2120fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            err = setupEAC3Codec(encoder, numChannels, sampleRate);
2121fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        }
2122fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    }
2123fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2124fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    if (err != OK) {
2125fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        return err;
2126fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    }
2127d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2128d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (!msg->findInt32("encoder-delay", &mEncoderDelay)) {
2129d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mEncoderDelay = 0;
2130d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2131d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2132d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (!msg->findInt32("encoder-padding", &mEncoderPadding)) {
2133d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mEncoderPadding = 0;
2134d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2135d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2136d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (msg->findInt32("channel-mask", &mChannelMask)) {
2137d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mChannelMaskPresent = true;
2138d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    } else {
2139d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mChannelMaskPresent = false;
2140d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2141d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2142d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t maxInputSize;
2143d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (msg->findInt32("max-input-size", &maxInputSize)) {
2144d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize);
2145d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) {
2146d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = setMinBufferSize(kPortIndexInput, 8192);  // XXX
2147d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2148d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2149d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t priority;
2150d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (msg->findInt32("priority", &priority)) {
2151d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = setPriority(priority);
2152d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2153d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2154d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t rateInt = -1;
2155d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    float rateFloat = -1;
2156d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (!msg->findFloat("operating-rate", &rateFloat)) {
2157d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        msg->findInt32("operating-rate", &rateInt);
2158d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        rateFloat = (float)rateInt;  // 16MHz (FLINTMAX) is OK for upper bound.
2159d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2160d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (rateFloat > 0) {
2161d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = setOperatingRate(rateFloat, video);
2162d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2163d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2164d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mBaseOutputFormat = outputFormat;
2165d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2166d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    err = getPortFormat(kPortIndexInput, inputFormat);
2167d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err == OK) {
2168d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = getPortFormat(kPortIndexOutput, outputFormat);
2169d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (err == OK) {
2170d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mInputFormat = inputFormat;
2171d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mOutputFormat = outputFormat;
2172d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
2173d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2174d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return err;
2175d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
2176d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2177d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::setPriority(int32_t priority) {
2178d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (priority < 0) {
2179d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return BAD_VALUE;
2180d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2181fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    OMX_PARAM_U32TYPE config;
2182fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    InitOMXParams(&config);
2183fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    config.nU32 = (OMX_U32)priority;
2184fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    status_t temp = mOMX->setConfig(
2185fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            mNode, (OMX_INDEXTYPE)OMX_IndexConfigPriority,
2186d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            &config, sizeof(config));
2187d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (temp != OK) {
2188d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGI("codec does not support config priority (err %d)", temp);
2189d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2190fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    return OK;
2191fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev}
2192fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2193fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheevstatus_t ACodec::setOperatingRate(float rateFloat, bool isVideo) {
2194fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    if (rateFloat < 0) {
2195d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return BAD_VALUE;
2196d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2197d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_U32 rate;
2198d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (isVideo) {
2199d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (rateFloat > 65535) {
2200d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return BAD_VALUE;
2201d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
2202d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        rate = (OMX_U32)(rateFloat * 65536.0f + 0.5f);
2203d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    } else {
2204d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (rateFloat > UINT_MAX) {
2205d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return BAD_VALUE;
2206d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
2207d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        rate = (OMX_U32)(rateFloat);
2208d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2209d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_PARAM_U32TYPE config;
2210d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    InitOMXParams(&config);
2211d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    config.nU32 = rate;
2212d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err = mOMX->setConfig(
2213d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, (OMX_INDEXTYPE)OMX_IndexConfigOperatingRate,
2214d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            &config, sizeof(config));
2215d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
2216d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGI("codec does not support config operating rate (err %d)", err);
2217d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2218fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    return OK;
2219fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev}
2220fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2221fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheevstatus_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) {
2222fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    OMX_PARAM_PORTDEFINITIONTYPE def;
2223fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    InitOMXParams(&def);
2224d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    def.nPortIndex = portIndex;
2225d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2226d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err = mOMX->getParameter(
2227d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2228d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2229d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
2230d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
2231d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2232d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2233d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (def.nBufferSize >= size) {
2234d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return OK;
2235d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2236d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2237d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    def.nBufferSize = size;
2238fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2239fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    err = mOMX->setParameter(
2240fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2241fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2242fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    if (err != OK) {
2243d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
2244d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2245d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2246d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    err = mOMX->getParameter(
2247d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2248d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2249d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
2250d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
2251d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2252d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2253d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (def.nBufferSize < size) {
2254d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGE("failed to set min buffer size to %zu (is still %u)", size, def.nBufferSize);
2255d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return FAILED_TRANSACTION;
2256d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2257d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2258d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return OK;
2259d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
2260d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2261d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::selectAudioPortFormat(
2262d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) {
2263d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_AUDIO_PARAM_PORTFORMATTYPE format;
2264d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    InitOMXParams(&format);
2265d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2266d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    format.nPortIndex = portIndex;
2267d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    for (OMX_U32 index = 0;; ++index) {
2268d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        format.nIndex = index;
2269d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2270d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        status_t err = mOMX->getParameter(
2271d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mNode, OMX_IndexParamAudioPortFormat,
2272d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                &format, sizeof(format));
2273d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2274d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (err != OK) {
2275d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return err;
2276d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
2277d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2278d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (format.eEncoding == desiredFormat) {
2279d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
2280d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
2281d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2282d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2283d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return mOMX->setParameter(
2284d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, OMX_IndexParamAudioPortFormat, &format, sizeof(format));
2285d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
2286d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2287d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::setupAACCodec(
2288d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        bool encoder, int32_t numChannels, int32_t sampleRate,
2289d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t bitRate, int32_t aacProfile, bool isADTS, int32_t sbrMode,
2290d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t maxOutputChannelCount, const drcParams_t& drc,
2291d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t pcmLimiterEnable) {
2292d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (encoder && isADTS) {
2293d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return -EINVAL;
2294d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2295d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2296d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err = setupRawAudioFormat(
2297d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            encoder ? kPortIndexInput : kPortIndexOutput,
2298d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            sampleRate,
2299d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            numChannels);
2300d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2301d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
2302d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
2303d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2304d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2305d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (encoder) {
2306d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC);
2307d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2308d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (err != OK) {
2309d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return err;
2310d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
2311d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2312d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        OMX_PARAM_PORTDEFINITIONTYPE def;
2313d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        InitOMXParams(&def);
2314d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        def.nPortIndex = kPortIndexOutput;
2315d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2316d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = mOMX->getParameter(
2317d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2318d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2319d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (err != OK) {
2320d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return err;
2321d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
2322d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2323d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        def.format.audio.bFlagErrorConcealment = OMX_TRUE;
2324d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
2325d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2326d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = mOMX->setParameter(
2327d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2328d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2329d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (err != OK) {
2330d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return err;
2331d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
2332d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2333d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        OMX_AUDIO_PARAM_AACPROFILETYPE profile;
2334d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        InitOMXParams(&profile);
2335d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        profile.nPortIndex = kPortIndexOutput;
2336d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2337d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = mOMX->getParameter(
2338d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
2339fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2340fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        if (err != OK) {
2341fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            return err;
2342fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        }
2343fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2344fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        profile.nChannels = numChannels;
2345fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2346d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        profile.eChannelMode =
2347d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            (numChannels == 1)
2348d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo;
2349fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2350d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        profile.nSampleRate = sampleRate;
2351d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        profile.nBitRate = bitRate;
2352d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        profile.nAudioBandWidth = 0;
2353d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        profile.nFrameLength = 0;
2354d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        profile.nAACtools = OMX_AUDIO_AACToolAll;
2355d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        profile.nAACERtools = OMX_AUDIO_AACERNone;
2356fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile;
2357d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
2358d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        switch (sbrMode) {
2359fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        case 0:
2360fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            // disable sbr
2361fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
2362fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
2363d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
2364fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        case 1:
2365fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            // enable single-rate sbr
2366d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
2367d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
2368d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
2369d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case 2:
2370d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            // enable dual-rate sbr
2371d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
2372d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
2373d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
2374d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case -1:
2375d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            // enable both modes -> the codec will decide which mode should be used
2376d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
2377d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
2378d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
2379d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        default:
2380d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            // unsupported sbr mode
2381d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return BAD_VALUE;
2382fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        }
2383fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2384fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2385fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        err = mOMX->setParameter(
2386fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
2387fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2388fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        if (err != OK) {
2389fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            return err;
2390fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        }
2391fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2392fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        return err;
2393fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    }
2394fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2395fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    OMX_AUDIO_PARAM_AACPROFILETYPE profile;
2396fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    InitOMXParams(&profile);
2397fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    profile.nPortIndex = kPortIndexInput;
2398fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2399d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    err = mOMX->getParameter(
2400d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
2401d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2402fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    if (err != OK) {
2403d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
2404d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2405fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2406fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    profile.nChannels = numChannels;
2407fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    profile.nSampleRate = sampleRate;
2408fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2409d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    profile.eAACStreamFormat =
2410fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        isADTS
2411fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            ? OMX_AUDIO_AACStreamFormatMP4ADTS
2412d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            : OMX_AUDIO_AACStreamFormatMP4FF;
2413d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2414d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE presentation;
2415d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    presentation.nMaxOutputChannels = maxOutputChannelCount;
2416d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    presentation.nDrcCut = drc.drcCut;
2417d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    presentation.nDrcBoost = drc.drcBoost;
2418fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    presentation.nHeavyCompression = drc.heavyCompression;
2419fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    presentation.nTargetReferenceLevel = drc.targetRefLevel;
2420fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    presentation.nEncodedTargetLevel = drc.encodedTargetLevel;
2421fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    presentation.nPCMLimiterEnable = pcmLimiterEnable;
2422fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2423fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    status_t res = mOMX->setParameter(mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
2424fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    if (res == OK) {
2425fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        // optional parameters, will not cause configuration failure
2426fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        mOMX->setParameter(mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacPresentation,
2427d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                &presentation, sizeof(presentation));
2428d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    } else {
2429d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGW("did not set AudioAndroidAacPresentation due to error %d when setting AudioAac", res);
2430d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2431d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return res;
2432fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev}
2433d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2434d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::setupAC3Codec(
2435d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        bool encoder, int32_t numChannels, int32_t sampleRate) {
2436d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err = setupRawAudioFormat(
2437d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
2438d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2439d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
2440d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
2441d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2442d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2443d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (encoder) {
2444d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGW("AC3 encoding is not supported.");
2445d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return INVALID_OPERATION;
2446fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    }
2447d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2448fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    OMX_AUDIO_PARAM_ANDROID_AC3TYPE def;
2449fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    InitOMXParams(&def);
2450fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    def.nPortIndex = kPortIndexInput;
2451fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2452fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    err = mOMX->getParameter(
2453fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            mNode,
2454fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
2455fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            &def,
2456d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            sizeof(def));
2457d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2458d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
2459d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
2460d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2461d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2462d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    def.nChannels = numChannels;
2463d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    def.nSampleRate = sampleRate;
2464fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2465d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return mOMX->setParameter(
2466d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode,
2467fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
2468fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            &def,
2469fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            sizeof(def));
2470fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev}
2471d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2472fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheevstatus_t ACodec::setupEAC3Codec(
2473fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        bool encoder, int32_t numChannels, int32_t sampleRate) {
2474fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    status_t err = setupRawAudioFormat(
2475d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
2476d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2477d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
2478d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
2479d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2480d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2481d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (encoder) {
2482d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGW("EAC3 encoding is not supported.");
2483d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return INVALID_OPERATION;
2484d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2485d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2486d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_AUDIO_PARAM_ANDROID_EAC3TYPE def;
2487fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    InitOMXParams(&def);
2488fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    def.nPortIndex = kPortIndexInput;
2489fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2490fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    err = mOMX->getParameter(
2491fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            mNode,
2492fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
2493fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            &def,
2494fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            sizeof(def));
2495d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2496fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    if (err != OK) {
2497d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
2498d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2499d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2500d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    def.nChannels = numChannels;
2501d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    def.nSampleRate = sampleRate;
2502d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2503d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return mOMX->setParameter(
2504d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode,
2505fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
2506d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            &def,
2507d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            sizeof(def));
2508fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev}
2509fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2510fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheevstatic OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(
2511fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        bool isAMRWB, int32_t bps) {
2512d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (isAMRWB) {
2513fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        if (bps <= 6600) {
2514fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            return OMX_AUDIO_AMRBandModeWB0;
2515d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        } else if (bps <= 8850) {
2516d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return OMX_AUDIO_AMRBandModeWB1;
2517fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        } else if (bps <= 12650) {
2518d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return OMX_AUDIO_AMRBandModeWB2;
2519d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        } else if (bps <= 14250) {
2520d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return OMX_AUDIO_AMRBandModeWB3;
2521d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        } else if (bps <= 15850) {
2522d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return OMX_AUDIO_AMRBandModeWB4;
2523d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        } else if (bps <= 18250) {
2524d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return OMX_AUDIO_AMRBandModeWB5;
2525d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        } else if (bps <= 19850) {
2526d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return OMX_AUDIO_AMRBandModeWB6;
2527d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        } else if (bps <= 23050) {
2528fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            return OMX_AUDIO_AMRBandModeWB7;
2529d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
2530fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2531fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        // 23850 bps
2532fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        return OMX_AUDIO_AMRBandModeWB8;
2533fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    } else {  // AMRNB
2534fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        if (bps <= 4750) {
2535fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            return OMX_AUDIO_AMRBandModeNB0;
2536fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        } else if (bps <= 5150) {
2537fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            return OMX_AUDIO_AMRBandModeNB1;
2538d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        } else if (bps <= 5900) {
2539d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return OMX_AUDIO_AMRBandModeNB2;
2540d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        } else if (bps <= 6700) {
2541d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return OMX_AUDIO_AMRBandModeNB3;
2542d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        } else if (bps <= 7400) {
2543d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return OMX_AUDIO_AMRBandModeNB4;
2544d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        } else if (bps <= 7950) {
2545d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return OMX_AUDIO_AMRBandModeNB5;
2546fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        } else if (bps <= 10200) {
2547d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return OMX_AUDIO_AMRBandModeNB6;
2548d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
2549fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2550fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        // 12200 bps
2551fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        return OMX_AUDIO_AMRBandModeNB7;
2552fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    }
2553d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
2554fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2555fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheevstatus_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) {
2556d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_AUDIO_PARAM_AMRTYPE def;
2557d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    InitOMXParams(&def);
2558fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput;
2559d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2560d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err =
2561d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
2562d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2563d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
2564d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
2565d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2566d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2567d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
2568d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate);
2569fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2570d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    err = mOMX->setParameter(
2571fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
2572fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2573fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    if (err != OK) {
2574fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        return err;
2575fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    }
2576fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2577fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    return setupRawAudioFormat(
2578fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            encoder ? kPortIndexInput : kPortIndexOutput,
2579d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            isWAMR ? 16000 : 8000 /* sampleRate */,
2580d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            1 /* numChannels */);
2581d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
2582d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2583d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::setupG711Codec(bool encoder, int32_t sampleRate, int32_t numChannels) {
2584d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (encoder) {
2585d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return INVALID_OPERATION;
2586d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2587fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2588d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return setupRawAudioFormat(
2589d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            kPortIndexInput, sampleRate, numChannels);
2590fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev}
2591fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2592fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheevstatus_t ACodec::setupFlacCodec(
2593fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel) {
2594d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2595fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    if (encoder) {
2596fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        OMX_AUDIO_PARAM_FLACTYPE def;
2597d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        InitOMXParams(&def);
2598d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        def.nPortIndex = kPortIndexOutput;
2599fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
2600d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // configure compression level
2601d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        status_t err = mOMX->getParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def));
2602d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (err != OK) {
2603d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGE("setupFlacCodec(): Error %d getting OMX_IndexParamAudioFlac parameter", err);
2604d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return err;
2605d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
2606d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        def.nCompressionLevel = compressionLevel;
2607d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = mOMX->setParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def));
2608d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (err != OK) {
2609d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGE("setupFlacCodec(): Error %d setting OMX_IndexParamAudioFlac parameter", err);
2610d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return err;
2611d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
2612d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2613d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2614d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return setupRawAudioFormat(
2615d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            encoder ? kPortIndexInput : kPortIndexOutput,
2616d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            sampleRate,
2617d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            numChannels);
2618d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
2619d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2620d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::setupRawAudioFormat(
2621d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
2622d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_PARAM_PORTDEFINITIONTYPE def;
2623d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    InitOMXParams(&def);
2624d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    def.nPortIndex = portIndex;
2625d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2626d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err = mOMX->getParameter(
2627d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2628d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2629d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
2630d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
2631d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2632d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2633d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
2634d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2635d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    err = mOMX->setParameter(
2636d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2637d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2638d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
2639d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
2640d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2641d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2642d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
2643d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    InitOMXParams(&pcmParams);
2644d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    pcmParams.nPortIndex = portIndex;
2645d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2646d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    err = mOMX->getParameter(
2647d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
2648d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2649d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
2650d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
2651d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2652d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2653d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    pcmParams.nChannels = numChannels;
2654d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    pcmParams.eNumData = OMX_NumericalDataSigned;
2655489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke    pcmParams.bInterleaved = OMX_TRUE;
2656d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    pcmParams.nBitPerSample = 16;
2657d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    pcmParams.nSamplingRate = sampleRate;
2658d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
2659d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2660d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) {
2661d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return OMX_ErrorNone;
2662d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2663d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2664d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return mOMX->setParameter(
2665d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
2666d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
2667d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2668d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::configureTunneledVideoPlayback(
2669d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t audioHwSync, const sp<ANativeWindow> &nativeWindow) {
2670d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    native_handle_t* sidebandHandle;
2671d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2672d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err = mOMX->configureVideoTunnelMode(
2673d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, kPortIndexOutput, OMX_TRUE, audioHwSync, &sidebandHandle);
2674d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
2675489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke        ALOGE("configureVideoTunnelMode failed! (err %d).", err);
2676d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
2677d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2678489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke
2679489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke    err = native_window_set_sideband_stream(nativeWindow.get(), sidebandHandle);
2680d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
2681d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGE("native_window_set_sideband_stream(%p) failed! (err %d).",
2682d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                sidebandHandle, err);
2683d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
2684d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2685d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2686d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return OK;
2687d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
2688d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2689d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::setVideoPortFormatType(
2690d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        OMX_U32 portIndex,
2691d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        OMX_VIDEO_CODINGTYPE compressionFormat,
2692d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        OMX_COLOR_FORMATTYPE colorFormat,
2693d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        bool usingNativeBuffers) {
2694d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_VIDEO_PARAM_PORTFORMATTYPE format;
2695d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    InitOMXParams(&format);
2696d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    format.nPortIndex = portIndex;
2697d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    format.nIndex = 0;
2698d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    bool found = false;
2699d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2700d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_U32 index = 0;
2701d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    for (;;) {
2702d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        format.nIndex = index;
2703d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        status_t err = mOMX->getParameter(
2704d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mNode, OMX_IndexParamVideoPortFormat,
2705d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                &format, sizeof(format));
2706489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke
2707489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke        if (err != OK) {
2708d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return err;
2709d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
2710d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2711d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // substitute back flexible color format to codec supported format
2712d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        OMX_U32 flexibleEquivalent;
2713d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (compressionFormat == OMX_VIDEO_CodingUnused
2714d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                && isFlexibleColorFormat(
2715d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        mOMX, mNode, format.eColorFormat, usingNativeBuffers, &flexibleEquivalent)
2716d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                && colorFormat == flexibleEquivalent) {
2717d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGI("[%s] using color format %#x in place of %#x",
2718d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    mComponentName.c_str(), format.eColorFormat, colorFormat);
2719d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            colorFormat = format.eColorFormat;
2720d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
2721d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2722d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // The following assertion is violated by TI's video decoder.
2723d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // CHECK_EQ(format.nIndex, index);
2724d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2725d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) {
2726d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (portIndex == kPortIndexInput
2727d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    && colorFormat == format.eColorFormat) {
2728d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                // eCompressionFormat does not seem right.
2729489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke                found = true;
2730489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke                break;
2731489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke            }
2732489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke            if (portIndex == kPortIndexOutput
2733d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    && compressionFormat == format.eCompressionFormat) {
2734d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                // eColorFormat does not seem right.
2735d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                found = true;
2736d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                break;
2737d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
2738d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
2739d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2740d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (format.eCompressionFormat == compressionFormat
2741489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke            && format.eColorFormat == colorFormat) {
2742489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke            found = true;
2743489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke            break;
2744489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke        }
2745489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke
2746489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke        ++index;
2747489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke    }
2748489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke
2749489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke    if (!found) {
2750489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke        return UNKNOWN_ERROR;
2751d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2752d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2753d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err = mOMX->setParameter(
2754d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, OMX_IndexParamVideoPortFormat,
2755d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            &format, sizeof(format));
2756d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2757d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return err;
2758d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
2759d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2760d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// Set optimal output format. OMX component lists output formats in the order
2761d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// of preference, but this got more complicated since the introduction of flexible
2762d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// YUV formats. We support a legacy behavior for applications that do not use
2763d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// surface output, do not specify an output format, but expect a "usable" standard
2764d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// OMX format. SW readable and standard formats must be flex-YUV.
2765d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright//
2766d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// Suggested preference order:
2767d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// - optimal format for texture rendering (mediaplayer behavior)
2768d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// - optimal SW readable & texture renderable format (flex-YUV support)
2769d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// - optimal SW readable non-renderable format (flex-YUV bytebuffer support)
2770d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// - legacy "usable" standard formats
2771d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright//
2772d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// For legacy support, we prefer a standard format, but will settle for a SW readable
2773d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// flex-YUV format.
2774d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::setSupportedOutputFormat(bool getLegacyFlexibleFormat) {
2775d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_VIDEO_PARAM_PORTFORMATTYPE format, legacyFormat;
2776d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    InitOMXParams(&format);
2777d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    format.nPortIndex = kPortIndexOutput;
2778d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2779d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    InitOMXParams(&legacyFormat);
2780d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // this field will change when we find a suitable legacy format
2781d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    legacyFormat.eColorFormat = OMX_COLOR_FormatUnused;
2782d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2783d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    for (OMX_U32 index = 0; ; ++index) {
2784d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        format.nIndex = index;
2785d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        status_t err = mOMX->getParameter(
2786d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mNode, OMX_IndexParamVideoPortFormat,
2787d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                &format, sizeof(format));
2788d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (err != OK) {
2789d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            // no more formats, pick legacy format if found
2790d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (legacyFormat.eColorFormat != OMX_COLOR_FormatUnused) {
2791d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                 memcpy(&format, &legacyFormat, sizeof(format));
2792d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                 break;
2793d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
2794d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return err;
2795d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
2796d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (format.eCompressionFormat != OMX_VIDEO_CodingUnused) {
2797d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return OMX_ErrorBadParameter;
2798d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
2799d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (!getLegacyFlexibleFormat) {
2800d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
2801d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
2802d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // standard formats that were exposed to users before
2803d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (format.eColorFormat == OMX_COLOR_FormatYUV420Planar
2804d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                || format.eColorFormat == OMX_COLOR_FormatYUV420PackedPlanar
2805d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
2806d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                || format.eColorFormat == OMX_COLOR_FormatYUV420PackedSemiPlanar
2807d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar) {
2808d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
2809d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
2810d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // find best legacy non-standard format
2811d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        OMX_U32 flexibleEquivalent;
2812d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (legacyFormat.eColorFormat == OMX_COLOR_FormatUnused
2813d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                && isFlexibleColorFormat(
2814d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        mOMX, mNode, format.eColorFormat, false /* usingNativeBuffers */,
2815d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        &flexibleEquivalent)
2816d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                && flexibleEquivalent == OMX_COLOR_FormatYUV420Flexible) {
2817d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            memcpy(&legacyFormat, &format, sizeof(format));
2818d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
2819d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2820d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return mOMX->setParameter(
2821d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, OMX_IndexParamVideoPortFormat,
2822d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            &format, sizeof(format));
2823d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
2824d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2825d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatic const struct VideoCodingMapEntry {
2826d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    const char *mMime;
2827d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_VIDEO_CODINGTYPE mVideoCodingType;
2828d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright} kVideoCodingMapEntry[] = {
2829d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    { MEDIA_MIMETYPE_VIDEO_AVC, OMX_VIDEO_CodingAVC },
2830d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    { MEDIA_MIMETYPE_VIDEO_HEVC, OMX_VIDEO_CodingHEVC },
2831d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    { MEDIA_MIMETYPE_VIDEO_MPEG4, OMX_VIDEO_CodingMPEG4 },
2832d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    { MEDIA_MIMETYPE_VIDEO_H263, OMX_VIDEO_CodingH263 },
2833d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    { MEDIA_MIMETYPE_VIDEO_MPEG2, OMX_VIDEO_CodingMPEG2 },
2834d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    { MEDIA_MIMETYPE_VIDEO_VP8, OMX_VIDEO_CodingVP8 },
2835d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    { MEDIA_MIMETYPE_VIDEO_VP9, OMX_VIDEO_CodingVP9 },
2836d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright};
2837d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2838d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatic status_t GetVideoCodingTypeFromMime(
2839d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        const char *mime, OMX_VIDEO_CODINGTYPE *codingType) {
2840d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    for (size_t i = 0;
2841d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright         i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
2842d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright         ++i) {
2843d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (!strcasecmp(mime, kVideoCodingMapEntry[i].mMime)) {
2844d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            *codingType = kVideoCodingMapEntry[i].mVideoCodingType;
2845d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return OK;
2846d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
2847d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2848d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2849d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    *codingType = OMX_VIDEO_CodingUnused;
2850d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2851d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return ERROR_UNSUPPORTED;
2852d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
2853d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2854d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatic status_t GetMimeTypeForVideoCoding(
2855d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        OMX_VIDEO_CODINGTYPE codingType, AString *mime) {
2856d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    for (size_t i = 0;
2857d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright         i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
2858d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright         ++i) {
2859d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (codingType == kVideoCodingMapEntry[i].mVideoCodingType) {
2860d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            *mime = kVideoCodingMapEntry[i].mMime;
2861d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return OK;
2862d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
2863d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2864d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2865d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mime->clear();
2866d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2867d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return ERROR_UNSUPPORTED;
2868d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
2869d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2870d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::setupVideoDecoder(
2871d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        const char *mime, const sp<AMessage> &msg, bool haveNativeWindow) {
2872d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t width, height;
2873d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (!msg->findInt32("width", &width)
2874d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            || !msg->findInt32("height", &height)) {
2875d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return INVALID_OPERATION;
2876d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2877d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2878d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_VIDEO_CODINGTYPE compressionFormat;
2879d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
2880d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2881d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
2882d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
2883d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2884d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2885d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    err = setVideoPortFormatType(
2886d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
2887d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2888d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
2889d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
2890d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2891d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2892d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t tmp;
2893d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (msg->findInt32("color-format", &tmp)) {
2894d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        OMX_COLOR_FORMATTYPE colorFormat =
2895d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            static_cast<OMX_COLOR_FORMATTYPE>(tmp);
2896d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = setVideoPortFormatType(
2897d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                kPortIndexOutput, OMX_VIDEO_CodingUnused, colorFormat, haveNativeWindow);
2898d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (err != OK) {
2899d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGW("[%s] does not support color format %d",
2900d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                  mComponentName.c_str(), colorFormat);
2901d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */);
2902d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
2903d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    } else {
2904d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */);
2905d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2906d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2907d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
2908d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
2909d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2910d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2911d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t frameRateInt;
2912d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    float frameRateFloat;
2913d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (!msg->findFloat("frame-rate", &frameRateFloat)) {
2914d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (!msg->findInt32("frame-rate", &frameRateInt)) {
2915d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            frameRateInt = -1;
2916d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
2917d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        frameRateFloat = (float)frameRateInt;
2918d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2919d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2920d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    err = setVideoFormatOnPort(
2921d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            kPortIndexInput, width, height, compressionFormat, frameRateFloat);
2922d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2923d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
2924d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
2925d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2926d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2927d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    err = setVideoFormatOnPort(
2928d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused);
2929d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2930d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
2931d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
2932d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2933d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2934d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return OK;
2935d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
2936d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2937d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) {
2938d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t tmp;
2939d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (!msg->findInt32("color-format", &tmp)) {
2940d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return INVALID_OPERATION;
2941d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2942d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2943d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_COLOR_FORMATTYPE colorFormat =
2944d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        static_cast<OMX_COLOR_FORMATTYPE>(tmp);
2945d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2946d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err = setVideoPortFormatType(
2947d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat);
2948d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2949d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
2950d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGE("[%s] does not support color format %d",
2951d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright              mComponentName.c_str(), colorFormat);
2952d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2953d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
2954d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2955d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2956d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    /* Input port configuration */
2957d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2958d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_PARAM_PORTDEFINITIONTYPE def;
2959d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    InitOMXParams(&def);
2960d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2961d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
2962d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2963d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    def.nPortIndex = kPortIndexInput;
2964d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2965d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    err = mOMX->getParameter(
2966d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2967d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2968d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
2969d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
2970d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2971d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2972d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t width, height, bitrate;
2973d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (!msg->findInt32("width", &width)
2974d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            || !msg->findInt32("height", &height)
2975d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            || !msg->findInt32("bitrate", &bitrate)) {
2976d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return INVALID_OPERATION;
2977d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2978d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2979d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    video_def->nFrameWidth = width;
2980d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    video_def->nFrameHeight = height;
2981d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2982d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t stride;
2983d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (!msg->findInt32("stride", &stride)) {
2984d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        stride = width;
2985d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2986d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2987d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    video_def->nStride = stride;
2988d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2989d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t sliceHeight;
2990d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (!msg->findInt32("slice-height", &sliceHeight)) {
2991d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        sliceHeight = height;
2992d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
2993d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2994d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    video_def->nSliceHeight = sliceHeight;
2995d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2996d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2;
2997d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
2998d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    float frameRate;
2999d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (!msg->findFloat("frame-rate", &frameRate)) {
3000d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t tmp;
3001d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (!msg->findInt32("frame-rate", &tmp)) {
3002d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return INVALID_OPERATION;
3003d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
3004d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        frameRate = (float)tmp;
3005d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mTimePerFrameUs = (int64_t) (1000000.0f / frameRate);
3006d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3007d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3008d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
3009d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
3010d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // this is redundant as it was already set up in setVideoPortFormatType
3011d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // FIXME for now skip this only for flexible YUV formats
3012d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (colorFormat != OMX_COLOR_FormatYUV420Flexible) {
3013d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        video_def->eColorFormat = colorFormat;
3014d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3015d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3016d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    err = mOMX->setParameter(
3017d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3018d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3019d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
3020d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGE("[%s] failed to set input port definition parameters.",
3021d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright              mComponentName.c_str());
3022d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3023d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
3024d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3025d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3026d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    /* Output port configuration */
3027d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3028d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_VIDEO_CODINGTYPE compressionFormat;
3029d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
3030d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3031d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
3032d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
3033d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3034d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3035d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    err = setVideoPortFormatType(
3036d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused);
3037d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3038d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
3039d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGE("[%s] does not support compression format %d",
3040d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright             mComponentName.c_str(), compressionFormat);
3041d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3042d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
3043d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3044d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3045d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    def.nPortIndex = kPortIndexOutput;
3046d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3047d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    err = mOMX->getParameter(
3048d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3049d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3050d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
3051d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
3052d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3053d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3054d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    video_def->nFrameWidth = width;
3055d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    video_def->nFrameHeight = height;
3056d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    video_def->xFramerate = 0;
3057d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    video_def->nBitrate = bitrate;
3058d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    video_def->eCompressionFormat = compressionFormat;
3059d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    video_def->eColorFormat = OMX_COLOR_FormatUnused;
3060d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3061d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    err = mOMX->setParameter(
3062d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3063d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3064d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
3065d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGE("[%s] failed to set output port definition parameters.",
3066d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright              mComponentName.c_str());
3067d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3068d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
3069d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3070d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3071d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    switch (compressionFormat) {
3072d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case OMX_VIDEO_CodingMPEG4:
3073d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            err = setupMPEG4EncoderParameters(msg);
3074d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
3075d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3076d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case OMX_VIDEO_CodingH263:
3077d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            err = setupH263EncoderParameters(msg);
3078d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
3079d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3080d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case OMX_VIDEO_CodingAVC:
3081d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            err = setupAVCEncoderParameters(msg);
3082d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
3083d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3084d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case OMX_VIDEO_CodingHEVC:
3085d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            err = setupHEVCEncoderParameters(msg);
3086d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
3087d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3088d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case OMX_VIDEO_CodingVP8:
3089d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case OMX_VIDEO_CodingVP9:
3090d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            err = setupVPXEncoderParameters(msg);
3091d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
3092d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3093d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        default:
3094d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
3095d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3096d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3097d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err == OK) {
3098d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGI("setupVideoEncoder succeeded");
3099d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3100d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3101d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return err;
3102d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
3103d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3104d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) {
3105d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_VIDEO_PARAM_INTRAREFRESHTYPE params;
3106d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    InitOMXParams(&params);
3107d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    params.nPortIndex = kPortIndexOutput;
3108d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3109d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode);
3110d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3111d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic ||
3112d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
3113d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t mbs;
3114d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) {
3115d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return INVALID_OPERATION;
3116d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
3117d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        params.nCirMBs = mbs;
3118d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3119d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3120d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive ||
3121d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
3122d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t mbs;
3123d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) {
3124d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return INVALID_OPERATION;
3125d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
3126d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        params.nAirMBs = mbs;
3127d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3128d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t ref;
3129d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) {
3130d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return INVALID_OPERATION;
3131d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
3132d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        params.nAirRef = ref;
3133d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3134d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3135d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err = mOMX->setParameter(
3136d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, OMX_IndexParamVideoIntraRefresh,
3137d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            &params, sizeof(params));
3138d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return err;
3139d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
3140d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3141d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatic OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) {
3142d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (iFramesInterval < 0) {
3143d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return 0xFFFFFFFF;
3144d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    } else if (iFramesInterval == 0) {
3145d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return 0;
3146d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3147d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_U32 ret = frameRate * iFramesInterval;
3148d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return ret;
3149d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
3150d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3151d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatic OMX_VIDEO_CONTROLRATETYPE getBitrateMode(const sp<AMessage> &msg) {
3152d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t tmp;
3153d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (!msg->findInt32("bitrate-mode", &tmp)) {
3154d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return OMX_Video_ControlRateVariable;
3155d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3156d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3157d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return static_cast<OMX_VIDEO_CONTROLRATETYPE>(tmp);
3158d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
3159d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3160d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) {
3161d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t bitrate, iFrameInterval;
3162d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (!msg->findInt32("bitrate", &bitrate)
3163d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
3164d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return INVALID_OPERATION;
3165d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3166d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3167d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
3168d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3169d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    float frameRate;
3170d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (!msg->findFloat("frame-rate", &frameRate)) {
3171d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t tmp;
3172d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (!msg->findInt32("frame-rate", &tmp)) {
3173d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return INVALID_OPERATION;
3174d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
3175d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        frameRate = (float)tmp;
3176d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3177d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3178d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
3179d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    InitOMXParams(&mpeg4type);
3180d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mpeg4type.nPortIndex = kPortIndexOutput;
3181d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3182d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err = mOMX->getParameter(
3183d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
3184d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3185d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
3186d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
3187d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3188d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3189d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mpeg4type.nSliceHeaderSpacing = 0;
3190d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mpeg4type.bSVH = OMX_FALSE;
3191d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mpeg4type.bGov = OMX_FALSE;
3192d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3193d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mpeg4type.nAllowedPictureTypes =
3194d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
3195d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3196d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
3197d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (mpeg4type.nPFrames == 0) {
3198d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
3199d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3200d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mpeg4type.nBFrames = 0;
3201d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mpeg4type.nIDCVLCThreshold = 0;
3202d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mpeg4type.bACPred = OMX_TRUE;
3203d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mpeg4type.nMaxPacketSize = 256;
3204d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mpeg4type.nTimeIncRes = 1000;
3205d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mpeg4type.nHeaderExtension = 0;
3206d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mpeg4type.bReversibleVLC = OMX_FALSE;
3207d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3208d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t profile;
3209d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (msg->findInt32("profile", &profile)) {
3210d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t level;
3211d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (!msg->findInt32("level", &level)) {
3212d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return INVALID_OPERATION;
3213d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
3214d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3215d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = verifySupportForProfileAndLevel(profile, level);
3216d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3217d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (err != OK) {
3218d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return err;
3219d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
3220d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3221d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile);
3222d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level);
3223d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3224d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3225d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    err = mOMX->setParameter(
3226d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
3227d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3228d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
3229d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
3230d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3231d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3232d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    err = configureBitrate(bitrate, bitrateMode);
3233d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3234d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
3235d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
3236d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3237d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3238d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return setupErrorCorrectionParameters();
3239d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
3240d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3241d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) {
3242d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t bitrate, iFrameInterval;
3243d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (!msg->findInt32("bitrate", &bitrate)
3244d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
3245d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return INVALID_OPERATION;
3246d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3247d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3248d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
3249d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3250d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    float frameRate;
3251d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (!msg->findFloat("frame-rate", &frameRate)) {
3252d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t tmp;
3253d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (!msg->findInt32("frame-rate", &tmp)) {
3254d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return INVALID_OPERATION;
3255d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
3256d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        frameRate = (float)tmp;
3257d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3258d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3259d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_VIDEO_PARAM_H263TYPE h263type;
3260d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    InitOMXParams(&h263type);
3261d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    h263type.nPortIndex = kPortIndexOutput;
3262d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3263d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err = mOMX->getParameter(
3264d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
3265d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3266d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
3267d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
3268d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3269d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3270d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    h263type.nAllowedPictureTypes =
3271d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
3272d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3273d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
3274d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (h263type.nPFrames == 0) {
3275d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
3276d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3277d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    h263type.nBFrames = 0;
3278d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3279d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t profile;
3280d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (msg->findInt32("profile", &profile)) {
3281d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t level;
3282d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (!msg->findInt32("level", &level)) {
3283d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return INVALID_OPERATION;
3284d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
3285d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3286d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = verifySupportForProfileAndLevel(profile, level);
3287d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3288d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (err != OK) {
3289d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return err;
3290d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
3291d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3292d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile);
3293d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level);
3294d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3295d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3296d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    h263type.bPLUSPTYPEAllowed = OMX_FALSE;
3297d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    h263type.bForceRoundingTypeToZero = OMX_FALSE;
3298d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    h263type.nPictureHeaderRepetition = 0;
3299d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    h263type.nGOBHeaderInterval = 0;
3300d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3301d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    err = mOMX->setParameter(
3302d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
3303d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3304d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
3305d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
3306d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3307d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3308d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    err = configureBitrate(bitrate, bitrateMode);
3309d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3310d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
3311d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
3312d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3313d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3314d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return setupErrorCorrectionParameters();
3315d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
3316d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3317d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// static
3318d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightint /* OMX_VIDEO_AVCLEVELTYPE */ ACodec::getAVCLevelFor(
3319d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int width, int height, int rate, int bitrate,
3320d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        OMX_VIDEO_AVCPROFILETYPE profile) {
3321d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // convert bitrate to main/baseline profile kbps equivalent
3322d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    switch (profile) {
3323d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case OMX_VIDEO_AVCProfileHigh10:
3324d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            bitrate = divUp(bitrate, 3000); break;
3325d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case OMX_VIDEO_AVCProfileHigh:
3326d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            bitrate = divUp(bitrate, 1250); break;
3327d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        default:
3328d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            bitrate = divUp(bitrate, 1000); break;
3329d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3330d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3331d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // convert size and rate to MBs
3332d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    width = divUp(width, 16);
3333d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    height = divUp(height, 16);
3334d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int mbs = width * height;
3335d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    rate *= mbs;
3336d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int maxDimension = max(width, height);
3337d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3338d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    static const int limits[][5] = {
3339d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        /*   MBps     MB   dim  bitrate        level */
3340d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {    1485,    99,  28,     64, OMX_VIDEO_AVCLevel1  },
3341d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {    1485,    99,  28,    128, OMX_VIDEO_AVCLevel1b },
3342d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {    3000,   396,  56,    192, OMX_VIDEO_AVCLevel11 },
3343d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {    6000,   396,  56,    384, OMX_VIDEO_AVCLevel12 },
3344d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {   11880,   396,  56,    768, OMX_VIDEO_AVCLevel13 },
3345d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {   11880,   396,  56,   2000, OMX_VIDEO_AVCLevel2  },
3346d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {   19800,   792,  79,   4000, OMX_VIDEO_AVCLevel21 },
3347d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {   20250,  1620, 113,   4000, OMX_VIDEO_AVCLevel22 },
3348d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {   40500,  1620, 113,  10000, OMX_VIDEO_AVCLevel3  },
3349d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {  108000,  3600, 169,  14000, OMX_VIDEO_AVCLevel31 },
3350d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {  216000,  5120, 202,  20000, OMX_VIDEO_AVCLevel32 },
3351d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {  245760,  8192, 256,  20000, OMX_VIDEO_AVCLevel4  },
3352d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {  245760,  8192, 256,  50000, OMX_VIDEO_AVCLevel41 },
3353d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {  522240,  8704, 263,  50000, OMX_VIDEO_AVCLevel42 },
3354d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {  589824, 22080, 420, 135000, OMX_VIDEO_AVCLevel5  },
3355d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {  983040, 36864, 543, 240000, OMX_VIDEO_AVCLevel51 },
3356d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        { 2073600, 36864, 543, 240000, OMX_VIDEO_AVCLevel52 },
3357d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    };
3358d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3359d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    for (size_t i = 0; i < ARRAY_SIZE(limits); i++) {
3360d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        const int (&limit)[5] = limits[i];
3361d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (rate <= limit[0] && mbs <= limit[1] && maxDimension <= limit[2]
3362d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                && bitrate <= limit[3]) {
3363d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return limit[4];
3364d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
3365d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3366d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return 0;
3367d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
3368d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3369d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
3370d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t bitrate, iFrameInterval;
3371d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (!msg->findInt32("bitrate", &bitrate)
3372d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
3373d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return INVALID_OPERATION;
3374d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3375d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3376d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
3377d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3378d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    float frameRate;
3379d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (!msg->findFloat("frame-rate", &frameRate)) {
3380d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t tmp;
3381d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (!msg->findInt32("frame-rate", &tmp)) {
3382d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return INVALID_OPERATION;
3383d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
3384d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        frameRate = (float)tmp;
3385d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3386d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3387d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err = OK;
3388d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t intraRefreshMode = 0;
3389d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) {
3390d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode);
3391d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (err != OK) {
3392d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x",
3393d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    err, intraRefreshMode);
3394d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return err;
3395d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
3396d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3397d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3398d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_VIDEO_PARAM_AVCTYPE h264type;
3399d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    InitOMXParams(&h264type);
3400d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    h264type.nPortIndex = kPortIndexOutput;
3401d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3402d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    err = mOMX->getParameter(
3403d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
3404d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3405d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
3406d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
3407d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3408d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3409d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    h264type.nAllowedPictureTypes =
3410d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
3411d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3412d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t profile;
3413d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (msg->findInt32("profile", &profile)) {
3414d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t level;
3415d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (!msg->findInt32("level", &level)) {
3416d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return INVALID_OPERATION;
3417d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
3418d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3419d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = verifySupportForProfileAndLevel(profile, level);
3420d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3421d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (err != OK) {
3422d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return err;
3423d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
3424d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3425d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile);
3426d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level);
3427d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3428d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3429d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // XXX
3430d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) {
3431d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGW("Use baseline profile instead of %d for AVC recording",
3432d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            h264type.eProfile);
3433d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
3434d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3435d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3436d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
3437d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        h264type.nSliceHeaderSpacing = 0;
3438489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke        h264type.bUseHadamard = OMX_TRUE;
3439489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke        h264type.nRefFrames = 1;
3440489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke        h264type.nBFrames = 0;
3441489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke        h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
3442489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke        if (h264type.nPFrames == 0) {
3443489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke            h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
3444489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke        }
3445489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke        h264type.nRefIdx10ActiveMinus1 = 0;
3446489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke        h264type.nRefIdx11ActiveMinus1 = 0;
3447489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke        h264type.bEntropyCodingCABAC = OMX_FALSE;
3448489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke        h264type.bWeightedPPrediction = OMX_FALSE;
3449489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke        h264type.bconstIpred = OMX_FALSE;
3450489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke        h264type.bDirect8x8Inference = OMX_FALSE;
3451489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke        h264type.bDirectSpatialTemporal = OMX_FALSE;
3452489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke        h264type.nCabacInitIdc = 0;
3453489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke    }
3454489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke
3455489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke    if (h264type.nBFrames != 0) {
3456489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke        h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
3457489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke    }
3458489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke
3459489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke    h264type.bEnableUEP = OMX_FALSE;
3460489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke    h264type.bEnableFMO = OMX_FALSE;
3461489fda8d476f3fc10b0251263cc69528b736257bJason Gerecke    h264type.bEnableASO = OMX_FALSE;
3462d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    h264type.bEnableRS = OMX_FALSE;
3463d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    h264type.bFrameMBsOnly = OMX_TRUE;
3464d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    h264type.bMBAFF = OMX_FALSE;
3465d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
3466d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3467d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    err = mOMX->setParameter(
3468d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
3469d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3470d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
3471d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
3472d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3473d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3474d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return configureBitrate(bitrate, bitrateMode);
3475d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
3476d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3477d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::setupHEVCEncoderParameters(const sp<AMessage> &msg) {
3478d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t bitrate, iFrameInterval;
3479d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (!msg->findInt32("bitrate", &bitrate)
3480d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
3481d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return INVALID_OPERATION;
3482d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3483d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3484d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
3485d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3486fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    float frameRate;
3487fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    if (!msg->findFloat("frame-rate", &frameRate)) {
3488fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        int32_t tmp;
3489fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        if (!msg->findInt32("frame-rate", &tmp)) {
3490d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return INVALID_OPERATION;
3491d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
3492d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        frameRate = (float)tmp;
3493fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    }
3494d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3495fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    OMX_VIDEO_PARAM_HEVCTYPE hevcType;
3496fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    InitOMXParams(&hevcType);
3497d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    hevcType.nPortIndex = kPortIndexOutput;
3498fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
3499d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err = OK;
3500d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    err = mOMX->getParameter(
3501d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
3502d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
3503d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
3504d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3505d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3506d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t profile;
3507d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (msg->findInt32("profile", &profile)) {
3508d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t level;
3509fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        if (!msg->findInt32("level", &level)) {
3510fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            return INVALID_OPERATION;
3511fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        }
3512fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
3513fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        err = verifySupportForProfileAndLevel(profile, level);
3514fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        if (err != OK) {
3515fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            return err;
3516fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        }
3517fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
3518d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        hevcType.eProfile = static_cast<OMX_VIDEO_HEVCPROFILETYPE>(profile);
3519d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        hevcType.eLevel = static_cast<OMX_VIDEO_HEVCLEVELTYPE>(level);
3520d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3521fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
3522d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // TODO: Need OMX structure definition for setting iFrameInterval
3523fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
3524fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    err = mOMX->setParameter(
3525d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
3526fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    if (err != OK) {
3527d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
3528d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3529d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3530d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return configureBitrate(bitrate, bitrateMode);
3531fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev}
3532d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3533fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheevstatus_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg) {
3534fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    int32_t bitrate;
3535d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t iFrameInterval = 0;
3536fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    size_t tsLayers = 0;
3537d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE pattern =
3538d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        OMX_VIDEO_VPXTemporalLayerPatternNone;
3539d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    static const uint32_t kVp8LayerRateAlloction
3540d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS]
3541d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] = {
3542d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {100, 100, 100},  // 1 layer
3543d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        { 60, 100, 100},  // 2 layers {60%, 40%}
3544fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        { 40,  60, 100},  // 3 layers {40%, 20%, 40%}
3545d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    };
3546d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (!msg->findInt32("bitrate", &bitrate)) {
3547fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        return INVALID_OPERATION;
3548fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    }
3549fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    msg->findInt32("i-frame-interval", &iFrameInterval);
3550fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
3551fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
3552d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3553d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    float frameRate;
3554d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (!msg->findFloat("frame-rate", &frameRate)) {
3555d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t tmp;
3556fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        if (!msg->findInt32("frame-rate", &tmp)) {
3557d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return INVALID_OPERATION;
3558fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        }
3559fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        frameRate = (float)tmp;
3560d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3561fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
3562fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    AString tsSchema;
3563d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (msg->findString("ts-schema", &tsSchema)) {
3564d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (tsSchema == "webrtc.vp8.1-layer") {
3565d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
3566d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            tsLayers = 1;
3567d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        } else if (tsSchema == "webrtc.vp8.2-layer") {
3568d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
3569d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            tsLayers = 2;
3570d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        } else if (tsSchema == "webrtc.vp8.3-layer") {
3571d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
3572d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            tsLayers = 3;
3573fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        } else {
3574d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGW("Unsupported ts-schema [%s]", tsSchema.c_str());
3575d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
3576fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    }
3577fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
3578fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
3579fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    InitOMXParams(&vp8type);
3580fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    vp8type.nPortIndex = kPortIndexOutput;
3581d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err = mOMX->getParameter(
3582d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
3583d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            &vp8type, sizeof(vp8type));
3584d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3585fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    if (err == OK) {
3586d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (iFrameInterval > 0) {
3587fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            vp8type.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate);
3588fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        }
3589d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        vp8type.eTemporalPattern = pattern;
3590fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        vp8type.nTemporalLayerCount = tsLayers;
3591fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        if (tsLayers > 0) {
3592d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            for (size_t i = 0; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) {
3593d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                vp8type.nTemporalLayerBitrateRatio[i] =
3594d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    kVp8LayerRateAlloction[tsLayers - 1][i];
3595d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
3596d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
3597d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (bitrateMode == OMX_Video_ControlRateConstant) {
3598d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            vp8type.nMinQuantizer = 2;
3599d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            vp8type.nMaxQuantizer = 63;
3600d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
3601d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3602fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        err = mOMX->setParameter(
3603d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
3604d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                &vp8type, sizeof(vp8type));
3605fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        if (err != OK) {
3606fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            ALOGW("Extended VP8 parameters set failed: %d", err);
3607fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        }
3608fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    }
3609fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
3610d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return configureBitrate(bitrate, bitrateMode);
3611d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
3612d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3613d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::verifySupportForProfileAndLevel(
3614fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        int32_t profile, int32_t level) {
3615d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
3616fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    InitOMXParams(&params);
3617fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    params.nPortIndex = kPortIndexOutput;
3618d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3619fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    for (params.nProfileIndex = 0;; ++params.nProfileIndex) {
3620fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        status_t err = mOMX->getParameter(
3621d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mNode,
3622d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                OMX_IndexParamVideoProfileLevelQuerySupported,
3623d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                &params,
3624d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                sizeof(params));
3625d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3626d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (err != OK) {
3627d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return err;
3628d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
3629d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3630d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t supportedProfile = static_cast<int32_t>(params.eProfile);
3631fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        int32_t supportedLevel = static_cast<int32_t>(params.eLevel);
3632d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3633d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (profile == supportedProfile && level <= supportedLevel) {
3634fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            return OK;
3635fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        }
3636fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    }
3637fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev}
3638fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
3639d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::configureBitrate(
3640d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode) {
3641d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
3642d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    InitOMXParams(&bitrateType);
3643fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    bitrateType.nPortIndex = kPortIndexOutput;
3644d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3645fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    status_t err = mOMX->getParameter(
3646fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            mNode, OMX_IndexParamVideoBitrate,
3647d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            &bitrateType, sizeof(bitrateType));
3648fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
3649fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    if (err != OK) {
3650d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
3651d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3652d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3653d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    bitrateType.eControlRate = bitrateMode;
3654fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    bitrateType.nTargetBitrate = bitrate;
3655fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
3656d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return mOMX->setParameter(
3657d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, OMX_IndexParamVideoBitrate,
3658d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            &bitrateType, sizeof(bitrateType));
3659d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
3660d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3661fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheevstatus_t ACodec::setupErrorCorrectionParameters() {
3662fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
3663fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    InitOMXParams(&errorCorrectionType);
3664fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    errorCorrectionType.nPortIndex = kPortIndexOutput;
3665fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
3666d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err = mOMX->getParameter(
3667d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, OMX_IndexParamVideoErrorCorrection,
3668d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            &errorCorrectionType, sizeof(errorCorrectionType));
3669d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3670fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    if (err != OK) {
3671d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return OK;  // Optional feature. Ignore this failure
3672fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    }
3673fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
3674d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    errorCorrectionType.bEnableHEC = OMX_FALSE;
3675fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    errorCorrectionType.bEnableResync = OMX_TRUE;
3676d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    errorCorrectionType.nResynchMarkerSpacing = 256;
3677d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
3678d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    errorCorrectionType.bEnableRVLC = OMX_FALSE;
3679d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3680d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return mOMX->setParameter(
3681d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, OMX_IndexParamVideoErrorCorrection,
3682fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            &errorCorrectionType, sizeof(errorCorrectionType));
3683fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev}
3684fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
3685fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheevstatus_t ACodec::setVideoFormatOnPort(
3686fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        OMX_U32 portIndex,
3687d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat,
3688d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        float frameRate) {
3689d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_PARAM_PORTDEFINITIONTYPE def;
3690d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    InitOMXParams(&def);
3691fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    def.nPortIndex = portIndex;
3692d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3693fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
3694fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
3695d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err = mOMX->getParameter(
3696fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3697d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
3698d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
3699d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3700d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3701d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (portIndex == kPortIndexInput) {
3702d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // XXX Need a (much) better heuristic to compute input buffer sizes.
3703d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        const size_t X = 64 * 1024;
3704d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (def.nBufferSize < X) {
3705d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            def.nBufferSize = X;
3706d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
3707d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3708d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3709d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (def.eDomain != OMX_PortDomainVideo) {
3710d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGE("expected video port, got %s(%d)", asString(def.eDomain), def.eDomain);
3711d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return FAILED_TRANSACTION;
3712d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3713d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3714d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    video_def->nFrameWidth = width;
3715d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    video_def->nFrameHeight = height;
3716d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3717d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (portIndex == kPortIndexInput) {
3718d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        video_def->eCompressionFormat = compressionFormat;
3719d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        video_def->eColorFormat = OMX_COLOR_FormatUnused;
3720d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (frameRate >= 0) {
3721d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
3722d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
3723d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3724d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3725d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    err = mOMX->setParameter(
3726d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3727d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3728d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return err;
3729d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
3730d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3731d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::initNativeWindow() {
3732d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (mNativeWindow != NULL) {
3733d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
3734d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3735d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3736d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE);
3737d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return OK;
3738d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
3739d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3740d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightsize_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const {
3741d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    size_t n = 0;
3742d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3743d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
3744d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        const BufferInfo &info = mBuffers[portIndex].itemAt(i);
3745d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3746d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
3747d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ++n;
3748d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
3749d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3750d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3751d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return n;
3752d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
3753d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3754d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightsize_t ACodec::countBuffersOwnedByNativeWindow() const {
3755d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    size_t n = 0;
3756d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3757d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) {
3758d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i);
3759d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3760d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
3761d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ++n;
3762d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
3763d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3764d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3765d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return n;
3766d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
3767d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3768d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() {
3769d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (mNativeWindow == NULL) {
3770d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return;
3771d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3772d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3773d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    while (countBuffersOwnedByNativeWindow() > mNumUndequeuedBuffers
3774d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            && dequeueBufferFromNativeWindow() != NULL) {
3775d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // these buffers will be submitted as regular buffers; account for this
3776d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (storingMetadataInDecodedBuffers() && mMetadataBuffersToSubmit > 0) {
3777d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            --mMetadataBuffersToSubmit;
3778d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
3779d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3780d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
3781d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3782d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightbool ACodec::allYourBuffersAreBelongToUs(
3783d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        OMX_U32 portIndex) {
3784d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
3785d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
3786d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3787d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (info->mStatus != BufferInfo::OWNED_BY_US
3788d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
3789d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGV("[%s] Buffer %u on port %u still has status %d",
3790d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    mComponentName.c_str(),
3791d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    info->mBufferID, portIndex, info->mStatus);
3792d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return false;
3793d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
3794d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3795d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3796d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return true;
3797d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
3798d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3799d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightbool ACodec::allYourBuffersAreBelongToUs() {
3800d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return allYourBuffersAreBelongToUs(kPortIndexInput)
3801d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        && allYourBuffersAreBelongToUs(kPortIndexOutput);
3802d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
3803d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3804d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::deferMessage(const sp<AMessage> &msg) {
3805d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mDeferredQueue.push_back(msg);
3806d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
3807d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3808d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::processDeferredMessages() {
3809d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    List<sp<AMessage> > queue = mDeferredQueue;
3810d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mDeferredQueue.clear();
3811d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3812d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    List<sp<AMessage> >::iterator it = queue.begin();
3813d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    while (it != queue.end()) {
3814d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        onMessageReceived(*it++);
3815d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3816d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
3817d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3818d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// static
3819d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightbool ACodec::describeDefaultColorFormat(DescribeColorFormatParams &params) {
3820d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    MediaImage &image = params.sMediaImage;
3821d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    memset(&image, 0, sizeof(image));
3822d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3823d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    image.mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
3824d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    image.mNumPlanes = 0;
3825d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3826d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    const OMX_COLOR_FORMATTYPE fmt = params.eColorFormat;
3827d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    image.mWidth = params.nFrameWidth;
3828d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    image.mHeight = params.nFrameHeight;
3829d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3830d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // only supporting YUV420
3831d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (fmt != OMX_COLOR_FormatYUV420Planar &&
3832d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        fmt != OMX_COLOR_FormatYUV420PackedPlanar &&
3833d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        fmt != OMX_COLOR_FormatYUV420SemiPlanar &&
3834d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        fmt != OMX_COLOR_FormatYUV420PackedSemiPlanar &&
3835d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        fmt != HAL_PIXEL_FORMAT_YV12) {
3836d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGW("do not know color format 0x%x = %d", fmt, fmt);
3837d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return false;
3838d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3839d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3840d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // TEMPORARY FIX for some vendors that advertise sliceHeight as 0
3841d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (params.nStride != 0 && params.nSliceHeight == 0) {
3842d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGW("using sliceHeight=%u instead of what codec advertised (=0)",
3843d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                params.nFrameHeight);
3844d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        params.nSliceHeight = params.nFrameHeight;
3845d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3846d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3847d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // we need stride and slice-height to be non-zero
3848d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (params.nStride == 0 || params.nSliceHeight == 0) {
3849d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGW("cannot describe color format 0x%x = %d with stride=%u and sliceHeight=%u",
3850d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                fmt, fmt, params.nStride, params.nSliceHeight);
3851d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return false;
3852d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3853d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3854d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // set-up YUV format
3855d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    image.mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
3856d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    image.mNumPlanes = 3;
3857d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    image.mBitDepth = 8;
3858d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    image.mPlane[image.Y].mOffset = 0;
3859d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    image.mPlane[image.Y].mColInc = 1;
3860d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    image.mPlane[image.Y].mRowInc = params.nStride;
3861d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    image.mPlane[image.Y].mHorizSubsampling = 1;
3862d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    image.mPlane[image.Y].mVertSubsampling = 1;
3863d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3864d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    switch ((int)fmt) {
3865d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case HAL_PIXEL_FORMAT_YV12:
3866d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (params.bUsingNativeBuffers) {
3867d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                size_t ystride = align(params.nStride, 16);
3868d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                size_t cstride = align(params.nStride / 2, 16);
3869d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                image.mPlane[image.Y].mRowInc = ystride;
3870d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3871d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                image.mPlane[image.V].mOffset = ystride * params.nSliceHeight;
3872d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                image.mPlane[image.V].mColInc = 1;
3873d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                image.mPlane[image.V].mRowInc = cstride;
3874d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                image.mPlane[image.V].mHorizSubsampling = 2;
3875d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                image.mPlane[image.V].mVertSubsampling = 2;
3876d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3877d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                image.mPlane[image.U].mOffset = image.mPlane[image.V].mOffset
3878d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        + (cstride * params.nSliceHeight / 2);
3879d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                image.mPlane[image.U].mColInc = 1;
3880d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                image.mPlane[image.U].mRowInc = cstride;
3881d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                image.mPlane[image.U].mHorizSubsampling = 2;
3882d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                image.mPlane[image.U].mVertSubsampling = 2;
3883d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                break;
3884d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            } else {
3885d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                // fall through as YV12 is used for YUV420Planar by some codecs
3886d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
3887d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3888d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case OMX_COLOR_FormatYUV420Planar:
3889d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case OMX_COLOR_FormatYUV420PackedPlanar:
3890d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
3891d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            image.mPlane[image.U].mColInc = 1;
3892d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            image.mPlane[image.U].mRowInc = params.nStride / 2;
3893d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            image.mPlane[image.U].mHorizSubsampling = 2;
3894d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            image.mPlane[image.U].mVertSubsampling = 2;
3895d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3896d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset
3897d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    + (params.nStride * params.nSliceHeight / 4);
3898d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            image.mPlane[image.V].mColInc = 1;
3899d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            image.mPlane[image.V].mRowInc = params.nStride / 2;
3900d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            image.mPlane[image.V].mHorizSubsampling = 2;
3901d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            image.mPlane[image.V].mVertSubsampling = 2;
3902d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
3903d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3904d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case OMX_COLOR_FormatYUV420SemiPlanar:
3905d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            // FIXME: NV21 for sw-encoder, NV12 for decoder and hw-encoder
3906d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case OMX_COLOR_FormatYUV420PackedSemiPlanar:
3907d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            // NV12
3908d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
3909d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            image.mPlane[image.U].mColInc = 2;
3910d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            image.mPlane[image.U].mRowInc = params.nStride;
3911d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            image.mPlane[image.U].mHorizSubsampling = 2;
3912d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            image.mPlane[image.U].mVertSubsampling = 2;
3913d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3914d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset + 1;
3915d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            image.mPlane[image.V].mColInc = 2;
3916d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            image.mPlane[image.V].mRowInc = params.nStride;
3917d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            image.mPlane[image.V].mHorizSubsampling = 2;
3918d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            image.mPlane[image.V].mVertSubsampling = 2;
3919d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
3920d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3921d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        default:
3922d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            TRESPASS();
3923d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3924d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return true;
3925d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
3926d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3927d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// static
3928d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightbool ACodec::describeColorFormat(
3929d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        const sp<IOMX> &omx, IOMX::node_id node,
3930d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        DescribeColorFormatParams &describeParams)
3931d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright{
3932d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_INDEXTYPE describeColorFormatIndex;
3933d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (omx->getExtensionIndex(
3934d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            node, "OMX.google.android.index.describeColorFormat",
3935d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            &describeColorFormatIndex) != OK ||
3936d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        omx->getParameter(
3937d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            node, describeColorFormatIndex,
3938d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            &describeParams, sizeof(describeParams)) != OK) {
3939d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return describeDefaultColorFormat(describeParams);
3940d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3941d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return describeParams.sMediaImage.mType !=
3942d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
3943d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
3944d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3945d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright// static
3946d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightbool ACodec::isFlexibleColorFormat(
3947d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright         const sp<IOMX> &omx, IOMX::node_id node,
3948d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright         uint32_t colorFormat, bool usingNativeBuffers, OMX_U32 *flexibleEquivalent) {
3949d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    DescribeColorFormatParams describeParams;
3950d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    InitOMXParams(&describeParams);
3951d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    describeParams.eColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat;
3952d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // reasonable dummy values
3953d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    describeParams.nFrameWidth = 128;
3954d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    describeParams.nFrameHeight = 128;
3955d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    describeParams.nStride = 128;
3956d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    describeParams.nSliceHeight = 128;
3957d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    describeParams.bUsingNativeBuffers = (OMX_BOOL)usingNativeBuffers;
3958d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3959d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    CHECK(flexibleEquivalent != NULL);
3960d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3961d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (!describeColorFormat(omx, node, describeParams)) {
3962d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return false;
3963d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3964d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3965d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    const MediaImage &img = describeParams.sMediaImage;
3966d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (img.mType == MediaImage::MEDIA_IMAGE_TYPE_YUV) {
3967d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (img.mNumPlanes != 3 ||
3968d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            img.mPlane[img.Y].mHorizSubsampling != 1 ||
3969d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            img.mPlane[img.Y].mVertSubsampling != 1) {
3970d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return false;
3971d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
3972d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3973d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // YUV 420
3974d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (img.mPlane[img.U].mHorizSubsampling == 2
3975d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                && img.mPlane[img.U].mVertSubsampling == 2
3976d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                && img.mPlane[img.V].mHorizSubsampling == 2
3977d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                && img.mPlane[img.V].mVertSubsampling == 2) {
3978d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            // possible flexible YUV420 format
3979d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (img.mBitDepth <= 8) {
3980d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright               *flexibleEquivalent = OMX_COLOR_FormatYUV420Flexible;
3981d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright               return true;
3982d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
3983d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
3984d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3985d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return false;
3986d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
3987d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3988d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
3989d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    const char *niceIndex = portIndex == kPortIndexInput ? "input" : "output";
3990d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_PARAM_PORTDEFINITIONTYPE def;
3991d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    InitOMXParams(&def);
3992d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    def.nPortIndex = portIndex;
3993d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3994d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err = mOMX->getParameter(mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3995d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (err != OK) {
3996d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return err;
3997d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
3998d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
3999d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (def.eDir != (portIndex == kPortIndexOutput ? OMX_DirOutput : OMX_DirInput)) {
4000d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGE("unexpected dir: %s(%d) on %s port", asString(def.eDir), def.eDir, niceIndex);
4001d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return BAD_VALUE;
4002d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
4003d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4004d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    switch (def.eDomain) {
4005d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case OMX_PortDomainVideo:
4006d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {
4007d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
4008d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            switch ((int)videoDef->eCompressionFormat) {
4009d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                case OMX_VIDEO_CodingUnused:
4010d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                {
4011d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    CHECK(mIsEncoder ^ (portIndex == kPortIndexOutput));
4012d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
4013d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4014d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setInt32("stride", videoDef->nStride);
4015d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setInt32("slice-height", videoDef->nSliceHeight);
4016d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setInt32("color-format", videoDef->eColorFormat);
4017d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4018d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    if (mNativeWindow == NULL) {
4019d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        DescribeColorFormatParams describeParams;
4020d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        InitOMXParams(&describeParams);
4021d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        describeParams.eColorFormat = videoDef->eColorFormat;
4022d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        describeParams.nFrameWidth = videoDef->nFrameWidth;
4023d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        describeParams.nFrameHeight = videoDef->nFrameHeight;
4024d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        describeParams.nStride = videoDef->nStride;
4025d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        describeParams.nSliceHeight = videoDef->nSliceHeight;
4026d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        describeParams.bUsingNativeBuffers = OMX_FALSE;
4027d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4028d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        if (describeColorFormat(mOMX, mNode, describeParams)) {
4029d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            notify->setBuffer(
4030d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                    "image-data",
4031d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                    ABuffer::CreateAsCopy(
4032d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                            &describeParams.sMediaImage,
4033d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                            sizeof(describeParams.sMediaImage)));
4034d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4035d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            MediaImage *img = &describeParams.sMediaImage;
4036d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            ALOGV("[%s] MediaImage { F(%ux%u) @%u+%u+%u @%u+%u+%u @%u+%u+%u }",
4037d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                    mComponentName.c_str(), img->mWidth, img->mHeight,
4038d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                    img->mPlane[0].mOffset, img->mPlane[0].mColInc, img->mPlane[0].mRowInc,
4039d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                    img->mPlane[1].mOffset, img->mPlane[1].mColInc, img->mPlane[1].mRowInc,
4040d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                    img->mPlane[2].mOffset, img->mPlane[2].mColInc, img->mPlane[2].mRowInc);
4041d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        }
4042d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    }
4043d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4044d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    if (portIndex != kPortIndexOutput) {
4045d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        // TODO: also get input crop
4046d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        break;
4047d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    }
4048d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4049d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    OMX_CONFIG_RECTTYPE rect;
4050d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    InitOMXParams(&rect);
4051d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    rect.nPortIndex = portIndex;
4052d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4053d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    if (mOMX->getConfig(
4054d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                mNode,
4055d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                (portIndex == kPortIndexOutput ?
4056d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                        OMX_IndexConfigCommonOutputCrop :
4057d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                        OMX_IndexConfigCommonInputCrop),
4058d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                &rect, sizeof(rect)) != OK) {
4059d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        rect.nLeft = 0;
4060d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        rect.nTop = 0;
4061d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        rect.nWidth = videoDef->nFrameWidth;
4062d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        rect.nHeight = videoDef->nFrameHeight;
4063d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    }
4064d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4065d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    if (rect.nLeft < 0 ||
4066d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        rect.nTop < 0 ||
4067d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        rect.nLeft + rect.nWidth > videoDef->nFrameWidth ||
4068d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        rect.nTop + rect.nHeight > videoDef->nFrameHeight) {
4069d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        ALOGE("Wrong cropped rect (%d, %d) - (%u, %u) vs. frame (%u, %u)",
4070d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                rect.nLeft, rect.nTop,
4071d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                rect.nLeft + rect.nWidth, rect.nTop + rect.nHeight,
4072d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                videoDef->nFrameWidth, videoDef->nFrameHeight);
4073d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        return BAD_VALUE;
4074d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    }
4075d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4076d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setRect(
4077d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            "crop",
4078d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            rect.nLeft,
4079d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            rect.nTop,
4080d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            rect.nLeft + rect.nWidth - 1,
4081d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            rect.nTop + rect.nHeight - 1);
4082d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4083d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    break;
4084d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
4085d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4086d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                case OMX_VIDEO_CodingVP8:
4087d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                case OMX_VIDEO_CodingVP9:
4088d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                {
4089d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
4090d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    InitOMXParams(&vp8type);
4091d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    vp8type.nPortIndex = kPortIndexOutput;
4092d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    status_t err = mOMX->getParameter(
4093d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            mNode,
4094d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
4095d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            &vp8type,
4096d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            sizeof(vp8type));
4097d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4098d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    if (err == OK) {
4099d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        AString tsSchema = "none";
4100d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        if (vp8type.eTemporalPattern
4101d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                == OMX_VIDEO_VPXTemporalLayerPatternWebRTC) {
4102d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            switch (vp8type.nTemporalLayerCount) {
4103d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                case 1:
4104d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                {
4105d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                    tsSchema = "webrtc.vp8.1-layer";
4106d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                    break;
4107d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                }
4108d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                case 2:
4109d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                {
4110d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                    tsSchema = "webrtc.vp8.2-layer";
4111d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                    break;
4112d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                }
4113d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                case 3:
4114d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                {
4115d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                    tsSchema = "webrtc.vp8.3-layer";
4116d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                    break;
4117d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                }
4118d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                default:
4119d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                {
4120d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                    break;
4121d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                }
4122d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            }
4123d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        }
4124d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        notify->setString("ts-schema", tsSchema);
4125d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    }
4126d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    // Fall through to set up mime.
4127d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
4128d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4129d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                default:
4130d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                {
4131d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    if (mIsEncoder ^ (portIndex == kPortIndexOutput)) {
4132d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        // should be CodingUnused
4133d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        ALOGE("Raw port video compression format is %s(%d)",
4134d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                asString(videoDef->eCompressionFormat),
4135d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                videoDef->eCompressionFormat);
4136d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        return BAD_VALUE;
4137d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    }
4138d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    AString mime;
4139d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    if (GetMimeTypeForVideoCoding(
4140d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        videoDef->eCompressionFormat, &mime) != OK) {
4141d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        notify->setString("mime", "application/octet-stream");
4142d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    } else {
4143d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        notify->setString("mime", mime.c_str());
4144d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    }
4145d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    break;
4146d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
4147d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
4148d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            notify->setInt32("width", videoDef->nFrameWidth);
4149d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            notify->setInt32("height", videoDef->nFrameHeight);
4150d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGV("[%s] %s format is %s", mComponentName.c_str(),
4151d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    portIndex == kPortIndexInput ? "input" : "output",
4152d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->debugString().c_str());
4153d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4154d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
4155d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
4156d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4157d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case OMX_PortDomainAudio:
4158d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {
4159d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
4160d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4161d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            switch ((int)audioDef->eEncoding) {
4162d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                case OMX_AUDIO_CodingPCM:
4163d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                {
4164d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    OMX_AUDIO_PARAM_PCMMODETYPE params;
4165d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    InitOMXParams(&params);
4166d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    params.nPortIndex = portIndex;
4167d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4168d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    err = mOMX->getParameter(
4169d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
4170d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    if (err != OK) {
4171d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        return err;
4172d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    }
4173d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4174d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    if (params.nChannels <= 0
4175d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            || (params.nChannels != 1 && !params.bInterleaved)
4176d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            || params.nBitPerSample != 16u
4177d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            || params.eNumData != OMX_NumericalDataSigned
4178d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            || params.ePCMMode != OMX_AUDIO_PCMModeLinear) {
4179d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        ALOGE("unsupported PCM port: %u channels%s, %u-bit, %s(%d), %s(%d) mode ",
4180d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                params.nChannels,
4181d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                params.bInterleaved ? " interleaved" : "",
4182d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                params.nBitPerSample,
4183d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                asString(params.eNumData), params.eNumData,
4184d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                asString(params.ePCMMode), params.ePCMMode);
4185d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        return FAILED_TRANSACTION;
4186d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    }
4187d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4188d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
4189d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setInt32("channel-count", params.nChannels);
4190d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setInt32("sample-rate", params.nSamplingRate);
4191d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4192d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    if (mChannelMaskPresent) {
4193d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        notify->setInt32("channel-mask", mChannelMask);
4194d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    }
4195d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    break;
4196d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
4197d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4198d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                case OMX_AUDIO_CodingAAC:
4199d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                {
4200d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    OMX_AUDIO_PARAM_AACPROFILETYPE params;
4201d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    InitOMXParams(&params);
4202d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    params.nPortIndex = portIndex;
4203d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4204d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    err = mOMX->getParameter(
4205d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            mNode, OMX_IndexParamAudioAac, &params, sizeof(params));
4206d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    if (err != OK) {
4207d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        return err;
4208d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    }
4209d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4210d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
4211d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setInt32("channel-count", params.nChannels);
4212d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setInt32("sample-rate", params.nSampleRate);
4213d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    break;
4214d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
4215d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4216d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                case OMX_AUDIO_CodingAMR:
4217d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                {
4218d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    OMX_AUDIO_PARAM_AMRTYPE params;
4219d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    InitOMXParams(&params);
4220d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    params.nPortIndex = portIndex;
4221d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4222d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    err = mOMX->getParameter(
4223d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            mNode, OMX_IndexParamAudioAmr, &params, sizeof(params));
4224d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    if (err != OK) {
4225d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        return err;
4226d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    }
4227d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4228d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setInt32("channel-count", 1);
4229d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) {
4230d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
4231d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        notify->setInt32("sample-rate", 16000);
4232d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    } else {
4233d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
4234d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        notify->setInt32("sample-rate", 8000);
4235d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    }
4236d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    break;
4237d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
4238d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4239d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                case OMX_AUDIO_CodingFLAC:
4240d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                {
4241d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    OMX_AUDIO_PARAM_FLACTYPE params;
4242d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    InitOMXParams(&params);
4243d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    params.nPortIndex = portIndex;
4244d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4245d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    err = mOMX->getParameter(
4246d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            mNode, OMX_IndexParamAudioFlac, &params, sizeof(params));
4247d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    if (err != OK) {
4248d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        return err;
4249d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    }
4250d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4251d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC);
4252d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setInt32("channel-count", params.nChannels);
4253d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setInt32("sample-rate", params.nSampleRate);
4254d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    break;
4255d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
4256d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4257d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                case OMX_AUDIO_CodingMP3:
4258d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                {
4259d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    OMX_AUDIO_PARAM_MP3TYPE params;
4260d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    InitOMXParams(&params);
4261d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    params.nPortIndex = portIndex;
4262d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4263d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    err = mOMX->getParameter(
4264d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            mNode, OMX_IndexParamAudioMp3, &params, sizeof(params));
4265d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    if (err != OK) {
4266d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        return err;
4267d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    }
4268d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4269d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MPEG);
4270d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setInt32("channel-count", params.nChannels);
4271d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setInt32("sample-rate", params.nSampleRate);
4272d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    break;
4273d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
4274d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4275d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                case OMX_AUDIO_CodingVORBIS:
4276d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                {
4277d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    OMX_AUDIO_PARAM_VORBISTYPE params;
4278d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    InitOMXParams(&params);
4279d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    params.nPortIndex = portIndex;
4280d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4281d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    err = mOMX->getParameter(
4282d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            mNode, OMX_IndexParamAudioVorbis, &params, sizeof(params));
4283d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    if (err != OK) {
4284d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        return err;
4285d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    }
4286d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4287d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_VORBIS);
4288d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setInt32("channel-count", params.nChannels);
4289d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setInt32("sample-rate", params.nSampleRate);
4290d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    break;
4291d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
4292d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4293d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                case OMX_AUDIO_CodingAndroidAC3:
4294d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                {
4295d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    OMX_AUDIO_PARAM_ANDROID_AC3TYPE params;
4296d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    InitOMXParams(&params);
4297d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    params.nPortIndex = portIndex;
4298d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4299d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    err = mOMX->getParameter(
4300d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
4301d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            &params, sizeof(params));
4302d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    if (err != OK) {
4303d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        return err;
4304d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    }
4305d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4306d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3);
4307d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setInt32("channel-count", params.nChannels);
4308d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setInt32("sample-rate", params.nSampleRate);
4309d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    break;
4310d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
4311d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4312d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                case OMX_AUDIO_CodingAndroidEAC3:
4313d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                {
4314d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    OMX_AUDIO_PARAM_ANDROID_EAC3TYPE params;
4315d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    InitOMXParams(&params);
4316d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    params.nPortIndex = portIndex;
4317d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4318d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    err = mOMX->getParameter(
4319d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
4320d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            &params, sizeof(params));
4321d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    if (err != OK) {
4322d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        return err;
4323d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    }
4324d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4325d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_EAC3);
4326d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setInt32("channel-count", params.nChannels);
4327d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setInt32("sample-rate", params.nSampleRate);
4328d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    break;
4329d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
4330d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4331d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                case OMX_AUDIO_CodingAndroidOPUS:
4332d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                {
4333d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    OMX_AUDIO_PARAM_ANDROID_OPUSTYPE params;
4334d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    InitOMXParams(&params);
4335d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    params.nPortIndex = portIndex;
4336d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4337d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    err = mOMX->getParameter(
4338d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
4339d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            &params, sizeof(params));
4340d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    if (err != OK) {
4341d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        return err;
4342d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    }
4343d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4344d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_OPUS);
4345d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setInt32("channel-count", params.nChannels);
4346d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setInt32("sample-rate", params.nSampleRate);
4347d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    break;
4348d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
4349d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4350d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                case OMX_AUDIO_CodingG711:
4351d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                {
4352d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    OMX_AUDIO_PARAM_PCMMODETYPE params;
4353d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    InitOMXParams(&params);
4354d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    params.nPortIndex = portIndex;
4355d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4356d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    err = mOMX->getParameter(
4357d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioPcm, &params, sizeof(params));
4358d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    if (err != OK) {
4359d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        return err;
4360d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    }
4361d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4362d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    const char *mime = NULL;
4363d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    if (params.ePCMMode == OMX_AUDIO_PCMModeMULaw) {
4364d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        mime = MEDIA_MIMETYPE_AUDIO_G711_MLAW;
4365d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    } else if (params.ePCMMode == OMX_AUDIO_PCMModeALaw) {
4366d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        mime = MEDIA_MIMETYPE_AUDIO_G711_ALAW;
4367d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    } else { // params.ePCMMode == OMX_AUDIO_PCMModeLinear
4368d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        mime = MEDIA_MIMETYPE_AUDIO_RAW;
4369d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    }
4370d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setString("mime", mime);
4371d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setInt32("channel-count", params.nChannels);
4372d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setInt32("sample-rate", params.nSamplingRate);
4373d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    break;
4374d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
4375d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4376d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                case OMX_AUDIO_CodingGSMFR:
4377d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                {
4378d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    OMX_AUDIO_PARAM_PCMMODETYPE params;
4379d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    InitOMXParams(&params);
4380d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    params.nPortIndex = portIndex;
4381d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4382d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    err = mOMX->getParameter(
4383d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
4384d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    if (err != OK) {
4385d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        return err;
4386d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    }
4387d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4388d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MSGSM);
4389d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setInt32("channel-count", params.nChannels);
4390d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    notify->setInt32("sample-rate", params.nSamplingRate);
4391d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    break;
4392d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
4393d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4394d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                default:
4395d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    ALOGE("Unsupported audio coding: %s(%d)\n",
4396d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            asString(audioDef->eEncoding), audioDef->eEncoding);
4397d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    return BAD_TYPE;
4398d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
4399d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
4400d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
4401d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4402d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        default:
4403d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGE("Unsupported domain: %s(%d)", asString(def.eDomain), def.eDomain);
4404d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return BAD_TYPE;
4405d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
4406d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4407d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return OK;
4408d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
4409d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4410d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::sendFormatChange(const sp<AMessage> &reply) {
4411d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    sp<AMessage> notify = mBaseOutputFormat->dup();
4412d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    notify->setInt32("what", kWhatOutputFormatChanged);
4413d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4414d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (getPortFormat(kPortIndexOutput, notify) != OK) {
4415d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGE("[%s] Failed to get port format to send format change", mComponentName.c_str());
4416d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return;
4417d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
4418d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4419d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    AString mime;
4420d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    CHECK(notify->findString("mime", &mime));
4421d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4422d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t left, top, right, bottom;
4423d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (mime == MEDIA_MIMETYPE_VIDEO_RAW &&
4424d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mNativeWindow != NULL &&
4425d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        notify->findRect("crop", &left, &top, &right, &bottom)) {
4426d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // notify renderer of the crop change
4427d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // NOTE: native window uses extended right-bottom coordinate
4428d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        reply->setRect("crop", left, top, right + 1, bottom + 1);
4429d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    } else if (mime == MEDIA_MIMETYPE_AUDIO_RAW &&
4430d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright               (mEncoderDelay || mEncoderPadding)) {
4431d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t channelCount;
4432d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        CHECK(notify->findInt32("channel-count", &channelCount));
4433d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        size_t frameSize = channelCount * sizeof(int16_t);
4434d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (mSkipCutBuffer != NULL) {
4435d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            size_t prevbufsize = mSkipCutBuffer->size();
4436d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (prevbufsize != 0) {
4437d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                ALOGW("Replacing SkipCutBuffer holding %zu bytes", prevbufsize);
4438d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
4439d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
4440d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mSkipCutBuffer = new SkipCutBuffer(
4441d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mEncoderDelay * frameSize,
4442d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mEncoderPadding * frameSize);
4443d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
4444d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4445d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    notify->post();
4446d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4447d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mSentFormat = true;
4448d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
4449d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4450d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) {
4451d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    sp<AMessage> notify = mNotify->dup();
4452d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    notify->setInt32("what", CodecBase::kWhatError);
4453d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    ALOGE("signalError(omxError %#x, internalError %d)", error, internalError);
4454d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4455d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (internalError == UNKNOWN_ERROR) { // find better error code
4456d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        const status_t omxStatus = statusFromOMXError(error);
4457d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (omxStatus != 0) {
4458d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            internalError = omxStatus;
4459d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        } else {
4460d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGW("Invalid OMX error %#x", error);
4461d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
4462d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
4463d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    notify->setInt32("err", internalError);
4464d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    notify->setInt32("actionCode", ACTION_CODE_FATAL); // could translate from OMX error.
4465d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    notify->post();
4466d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
4467d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4468d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright////////////////////////////////////////////////////////////////////////////////
4469d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4470d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael WrightACodec::PortDescription::PortDescription() {
4471d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
4472d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4473d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightstatus_t ACodec::requestIDRFrame() {
4474d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (!mIsEncoder) {
4475d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return ERROR_UNSUPPORTED;
4476d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
4477d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4478d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_CONFIG_INTRAREFRESHVOPTYPE params;
4479d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    InitOMXParams(&params);
4480d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4481d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    params.nPortIndex = kPortIndexOutput;
4482d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    params.IntraRefreshVOP = OMX_TRUE;
4483d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4484d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return mOMX->setConfig(
4485d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mNode,
4486d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            OMX_IndexConfigVideoIntraVOPRefresh,
4487d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            &params,
4488d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            sizeof(params));
4489d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
4490d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4491d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::PortDescription::addBuffer(
4492d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        IOMX::buffer_id id, const sp<ABuffer> &buffer) {
4493d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mBufferIDs.push_back(id);
4494d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mBuffers.push_back(buffer);
4495d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
4496d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4497d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightsize_t ACodec::PortDescription::countBuffers() {
4498d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return mBufferIDs.size();
4499d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
4500d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4501d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael WrightIOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const {
4502d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return mBufferIDs.itemAt(index);
4503d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
4504d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4505d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightsp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const {
4506d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return mBuffers.itemAt(index);
4507d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
4508d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4509d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright////////////////////////////////////////////////////////////////////////////////
4510d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4511d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael WrightACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
4512d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    : AState(parentState),
4513d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright      mCodec(codec) {
4514d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
4515d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4516d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael WrightACodec::BaseState::PortMode ACodec::BaseState::getPortMode(
4517d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        OMX_U32 /* portIndex */) {
4518d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return KEEP_BUFFERS;
4519d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
4520d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4521d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightbool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
4522d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    switch (msg->what()) {
4523d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case kWhatInputBufferFilled:
4524d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {
4525d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            onInputBufferFilled(msg);
4526d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
4527d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
4528d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4529d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case kWhatOutputBufferDrained:
4530d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {
4531d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            onOutputBufferDrained(msg);
4532d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
4533d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
4534d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4535d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case ACodec::kWhatOMXMessageList:
4536d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {
4537d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return checkOMXMessage(msg) ? onOMXMessageList(msg) : true;
4538d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
4539d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4540d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case ACodec::kWhatOMXMessageItem:
4541d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {
4542d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            // no need to check as we already did it for kWhatOMXMessageList
4543d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return onOMXMessage(msg);
4544d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
4545d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4546d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case ACodec::kWhatOMXMessage:
4547d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {
4548d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return checkOMXMessage(msg) ? onOMXMessage(msg) : true;
4549d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
4550d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4551d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case ACodec::kWhatSetSurface:
4552d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {
4553d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            sp<AReplyToken> replyID;
4554d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            CHECK(msg->senderAwaitsResponse(&replyID));
4555d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4556d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            sp<RefBase> obj;
4557d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            CHECK(msg->findObject("surface", &obj));
4558d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4559d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            status_t err = mCodec->handleSetSurface(static_cast<Surface *>(obj.get()));
4560d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4561d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            sp<AMessage> response = new AMessage;
4562d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            response->setInt32("err", err);
4563d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            response->postReply(replyID);
4564d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
4565d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
4566d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4567d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case ACodec::kWhatCreateInputSurface:
4568d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case ACodec::kWhatSetInputSurface:
4569d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case ACodec::kWhatSignalEndOfInputStream:
4570d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {
4571d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            // This may result in an app illegal state exception.
4572d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGE("Message 0x%x was not handled", msg->what());
4573d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION);
4574d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return true;
4575d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
4576d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4577d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case ACodec::kWhatOMXDied:
4578d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {
4579d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            // This will result in kFlagSawMediaServerDie handling in MediaCodec.
4580d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGE("OMX/mediaserver died, signalling error!");
4581d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT);
4582d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
4583d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
4584d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4585d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case ACodec::kWhatReleaseCodecInstance:
4586d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {
4587d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGI("[%s] forcing the release of codec",
4588d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    mCodec->mComponentName.c_str());
4589d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            status_t err = mCodec->mOMX->freeNode(mCodec->mNode);
4590d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGE_IF("[%s] failed to release codec instance: err=%d",
4591d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                       mCodec->mComponentName.c_str(), err);
4592d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            sp<AMessage> notify = mCodec->mNotify->dup();
4593d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
4594d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            notify->post();
4595d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
4596d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
4597d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4598d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        default:
4599d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return false;
4600d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
4601d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4602d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return true;
4603d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
4604d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4605d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightbool ACodec::BaseState::checkOMXMessage(const sp<AMessage> &msg) {
4606d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // there is a possibility that this is an outstanding message for a
4607d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // codec that we have already destroyed
4608d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (mCodec->mNode == 0) {
4609d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGI("ignoring message as already freed component: %s",
4610d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                msg->debugString().c_str());
4611d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return false;
4612d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
4613d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4614d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    IOMX::node_id nodeID;
4615d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    CHECK(msg->findInt32("node", (int32_t*)&nodeID));
4616d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (nodeID != mCodec->mNode) {
4617d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGE("Unexpected message for nodeID: %u, should have been %u", nodeID, mCodec->mNode);
4618d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return false;
4619d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
4620d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return true;
4621d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
4622d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4623d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightbool ACodec::BaseState::onOMXMessageList(const sp<AMessage> &msg) {
4624d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    sp<RefBase> obj;
4625d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    CHECK(msg->findObject("messages", &obj));
4626d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    sp<MessageList> msgList = static_cast<MessageList *>(obj.get());
4627d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4628d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    bool receivedRenderedEvents = false;
4629d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    for (std::list<sp<AMessage>>::const_iterator it = msgList->getList().cbegin();
4630d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright          it != msgList->getList().cend(); ++it) {
4631d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        (*it)->setWhat(ACodec::kWhatOMXMessageItem);
4632d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mCodec->handleMessage(*it);
4633d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int32_t type;
4634d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        CHECK((*it)->findInt32("type", &type));
4635d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (type == omx_message::FRAME_RENDERED) {
4636d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            receivedRenderedEvents = true;
4637d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
4638d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
4639d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4640d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (receivedRenderedEvents) {
4641d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // NOTE: all buffers are rendered in this case
4642d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mCodec->notifyOfRenderedFrames();
4643d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
4644d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return true;
4645d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
4646d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4647d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightbool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
4648d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t type;
4649d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    CHECK(msg->findInt32("type", &type));
4650d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4651d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    switch (type) {
4652d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case omx_message::EVENT:
4653d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {
4654d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            int32_t event, data1, data2;
4655d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            CHECK(msg->findInt32("event", &event));
4656d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            CHECK(msg->findInt32("data1", &data1));
4657d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            CHECK(msg->findInt32("data2", &data2));
4658d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4659d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (event == OMX_EventCmdComplete
4660d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    && data1 == OMX_CommandFlush
4661d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    && data2 == (int32_t)OMX_ALL) {
4662d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                // Use of this notification is not consistent across
4663d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                // implementations. We'll drop this notification and rely
4664d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                // on flush-complete notifications on the individual port
4665d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                // indices instead.
4666d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4667d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                return true;
4668d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
4669d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4670d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return onOMXEvent(
4671d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    static_cast<OMX_EVENTTYPE>(event),
4672d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    static_cast<OMX_U32>(data1),
4673d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    static_cast<OMX_U32>(data2));
4674d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
4675d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4676d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case omx_message::EMPTY_BUFFER_DONE:
4677d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {
4678d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            IOMX::buffer_id bufferID;
4679d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            int32_t fenceFd;
4680d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4681d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
4682d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            CHECK(msg->findInt32("fence_fd", &fenceFd));
4683d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4684d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return onOMXEmptyBufferDone(bufferID, fenceFd);
4685d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
4686d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4687d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case omx_message::FILL_BUFFER_DONE:
4688d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {
4689d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            IOMX::buffer_id bufferID;
4690d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
4691d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4692d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            int32_t rangeOffset, rangeLength, flags, fenceFd;
4693d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            int64_t timeUs;
4694d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4695d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            CHECK(msg->findInt32("range_offset", &rangeOffset));
4696d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            CHECK(msg->findInt32("range_length", &rangeLength));
4697d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            CHECK(msg->findInt32("flags", &flags));
4698d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            CHECK(msg->findInt64("timestamp", &timeUs));
4699d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            CHECK(msg->findInt32("fence_fd", &fenceFd));
4700d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4701d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return onOMXFillBufferDone(
4702d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    bufferID,
4703d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    (size_t)rangeOffset, (size_t)rangeLength,
4704d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    (OMX_U32)flags,
4705d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    timeUs,
4706d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    fenceFd);
4707d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
4708d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4709d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case omx_message::FRAME_RENDERED:
4710d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {
4711d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            int64_t mediaTimeUs, systemNano;
4712d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4713d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            CHECK(msg->findInt64("media_time_us", &mediaTimeUs));
4714d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            CHECK(msg->findInt64("system_nano", &systemNano));
4715d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4716d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return onOMXFrameRendered(
4717d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    mediaTimeUs, systemNano);
4718d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
4719d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4720d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        default:
4721d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGE("Unexpected message type: %d", type);
4722d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return false;
4723d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
4724d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
4725d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4726d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightbool ACodec::BaseState::onOMXFrameRendered(
4727d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int64_t mediaTimeUs __unused, nsecs_t systemNano __unused) {
4728d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // ignore outside of Executing and PortSettingsChanged states
4729d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return true;
4730d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
4731d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4732d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightbool ACodec::BaseState::onOMXEvent(
4733d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
4734d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (event != OMX_EventError) {
4735d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGV("[%s] EVENT(%d, 0x%08x, 0x%08x)",
4736d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright             mCodec->mComponentName.c_str(), event, data1, data2);
4737d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4738d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return false;
4739d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
4740d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4741d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    ALOGE("[%s] ERROR(0x%08x)", mCodec->mComponentName.c_str(), data1);
4742d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4743d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // verify OMX component sends back an error we expect.
4744d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMX_ERRORTYPE omxError = (OMX_ERRORTYPE)data1;
4745d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (!isOMXError(omxError)) {
4746d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGW("Invalid OMX error %#x", omxError);
4747d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        omxError = OMX_ErrorUndefined;
4748d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
4749d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mCodec->signalError(omxError);
4750d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4751d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return true;
4752d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
4753d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4754d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightbool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID, int fenceFd) {
4755d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    ALOGV("[%s] onOMXEmptyBufferDone %u",
4756d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright         mCodec->mComponentName.c_str(), bufferID);
4757d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4758d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
4759d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    BufferInfo::Status status = BufferInfo::getSafeStatus(info);
4760d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (status != BufferInfo::OWNED_BY_COMPONENT) {
4761d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGE("Wrong ownership in EBD: %s(%d) buffer #%u", _asString(status), status, bufferID);
4762d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mCodec->dumpBuffers(kPortIndexInput);
4763d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (fenceFd >= 0) {
4764d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ::close(fenceFd);
4765d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
4766d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return false;
4767d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
4768d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    info->mStatus = BufferInfo::OWNED_BY_US;
4769d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4770d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // input buffers cannot take fences, so wait for any fence now
4771d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    (void)mCodec->waitForFence(fenceFd, "onOMXEmptyBufferDone");
4772d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    fenceFd = -1;
4773d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4774d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // still save fence for completeness
4775d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    info->setWriteFence(fenceFd, "onOMXEmptyBufferDone");
4776d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4777d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // We're in "store-metadata-in-buffers" mode, the underlying
4778d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // OMX component had access to data that's implicitly refcounted
4779d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // by this "MediaBuffer" object. Now that the OMX component has
4780d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // told us that it's done with the input buffer, we can decrement
4781d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    // the mediaBuffer's reference count.
4782d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    info->mData->setMediaBufferBase(NULL);
4783d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4784d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    PortMode mode = getPortMode(kPortIndexInput);
4785d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4786d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    switch (mode) {
4787d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case KEEP_BUFFERS:
4788d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
4789d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4790d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case RESUBMIT_BUFFERS:
4791d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            postFillThisBuffer(info);
4792d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
4793d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4794d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case FREE_BUFFERS:
4795d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        default:
4796d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGE("SHOULD NOT REACH HERE: cannot free empty output buffers");
4797d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return false;
4798d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
4799d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4800d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return true;
4801d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
4802d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4803d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
4804d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (mCodec->mPortEOS[kPortIndexInput]) {
4805d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return;
4806d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
4807d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4808d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
4809d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4810d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    sp<AMessage> notify = mCodec->mNotify->dup();
4811d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    notify->setInt32("what", CodecBase::kWhatFillThisBuffer);
4812d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    notify->setInt32("buffer-id", info->mBufferID);
4813d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4814d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    info->mData->meta()->clear();
4815d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    notify->setBuffer("buffer", info->mData);
4816d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4817d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec);
4818d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    reply->setInt32("buffer-id", info->mBufferID);
4819d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4820d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    notify->setMessage("reply", reply);
4821d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4822d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    notify->post();
4823d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4824d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
4825d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
4826d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4827d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
4828d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    IOMX::buffer_id bufferID;
4829d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
4830d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    sp<ABuffer> buffer;
4831d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t err = OK;
4832d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    bool eos = false;
4833d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    PortMode mode = getPortMode(kPortIndexInput);
4834d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4835d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (!msg->findBuffer("buffer", &buffer)) {
4836d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        /* these are unfilled buffers returned by client */
4837d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        CHECK(msg->findInt32("err", &err));
4838d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4839d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (err == OK) {
4840d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            /* buffers with no errors are returned on MediaCodec.flush */
4841d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mode = KEEP_BUFFERS;
4842d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        } else {
4843d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGV("[%s] saw error %d instead of an input buffer",
4844d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                 mCodec->mComponentName.c_str(), err);
4845d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            eos = true;
4846d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
4847d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4848d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        buffer.clear();
4849d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
4850d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4851d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t tmp;
4852d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
4853d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        eos = true;
4854d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = ERROR_END_OF_STREAM;
4855d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
4856d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4857d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
4858d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    BufferInfo::Status status = BufferInfo::getSafeStatus(info);
4859d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (status != BufferInfo::OWNED_BY_UPSTREAM) {
4860d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGE("Wrong ownership in IBF: %s(%d) buffer #%u", _asString(status), status, bufferID);
4861d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mCodec->dumpBuffers(kPortIndexInput);
4862d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
4863d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return;
4864d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
4865d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4866d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    info->mStatus = BufferInfo::OWNED_BY_US;
4867d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4868d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    switch (mode) {
4869d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case KEEP_BUFFERS:
4870d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {
4871d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (eos) {
4872d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                if (!mCodec->mPortEOS[kPortIndexInput]) {
4873d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    mCodec->mPortEOS[kPortIndexInput] = true;
4874d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    mCodec->mInputEOSResult = err;
4875d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
4876d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
4877d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
4878d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
4879d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4880d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case RESUBMIT_BUFFERS:
4881d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {
4882d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) {
4883d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                // Do not send empty input buffer w/o EOS to the component.
4884d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                if (buffer->size() == 0 && !eos) {
4885d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    postFillThisBuffer(info);
4886d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    break;
4887d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
4888d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4889d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                int64_t timeUs;
4890d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
4891d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4892d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
4893d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4894d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                int32_t isCSD;
4895d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
4896d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    flags |= OMX_BUFFERFLAG_CODECCONFIG;
4897d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
4898d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4899d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                if (eos) {
4900d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    flags |= OMX_BUFFERFLAG_EOS;
4901d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
4902d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4903d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                if (buffer != info->mData) {
4904d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    ALOGV("[%s] Needs to copy input data for buffer %u. (%p != %p)",
4905d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                         mCodec->mComponentName.c_str(),
4906d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                         bufferID,
4907d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                         buffer.get(), info->mData.get());
4908d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4909d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    if (buffer->size() > info->mData->capacity()) {
4910d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        ALOGE("data size (%zu) is greated than buffer capacity (%zu)",
4911d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                buffer->size(),           // this is the data received
4912d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                                info->mData->capacity()); // this is out buffer size
4913d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
4914d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        return;
4915d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    }
4916d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    memcpy(info->mData->data(), buffer->data(), buffer->size());
4917d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
4918d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4919d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
4920d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    ALOGV("[%s] calling emptyBuffer %u w/ codec specific data",
4921d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                         mCodec->mComponentName.c_str(), bufferID);
4922d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                } else if (flags & OMX_BUFFERFLAG_EOS) {
4923d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    ALOGV("[%s] calling emptyBuffer %u w/ EOS",
4924d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                         mCodec->mComponentName.c_str(), bufferID);
4925d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                } else {
4926d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#if TRACK_BUFFER_TIMING
4927d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    ALOGI("[%s] calling emptyBuffer %u w/ time %lld us",
4928d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                         mCodec->mComponentName.c_str(), bufferID, (long long)timeUs);
4929d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#else
4930d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    ALOGV("[%s] calling emptyBuffer %u w/ time %lld us",
4931d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                         mCodec->mComponentName.c_str(), bufferID, (long long)timeUs);
4932d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#endif
4933d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
4934d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4935d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#if TRACK_BUFFER_TIMING
4936d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                ACodec::BufferStats stats;
4937d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                stats.mEmptyBufferTimeUs = ALooper::GetNowUs();
4938d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                stats.mFillBufferDoneTimeUs = -1ll;
4939d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mCodec->mBufferStats.add(timeUs, stats);
4940d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#endif
4941d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4942d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                if (mCodec->storingMetadataInDecodedBuffers()) {
4943d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    // try to submit an output buffer for each input buffer
4944d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    PortMode outputMode = getPortMode(kPortIndexOutput);
4945d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4946d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    ALOGV("MetadataBuffersToSubmit=%u portMode=%s",
4947d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            mCodec->mMetadataBuffersToSubmit,
4948d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            (outputMode == FREE_BUFFERS ? "FREE" :
4949d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                             outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT"));
4950d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    if (outputMode == RESUBMIT_BUFFERS) {
4951d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        mCodec->submitOutputMetadataBuffer();
4952d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    }
4953d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
4954d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                info->checkReadFence("onInputBufferFilled");
4955d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                status_t err2 = mCodec->mOMX->emptyBuffer(
4956d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    mCodec->mNode,
4957d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    bufferID,
4958d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    0,
4959d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    buffer->size(),
4960d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    flags,
4961d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    timeUs,
4962d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    info->mFenceFd);
4963d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                info->mFenceFd = -1;
4964d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                if (err2 != OK) {
4965d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2));
4966d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    return;
4967d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
4968d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4969d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4970d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                if (!eos && err == OK) {
4971d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    getMoreInputDataIfPossible();
4972d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                } else {
4973d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    ALOGV("[%s] Signalled EOS (%d) on the input port",
4974d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                         mCodec->mComponentName.c_str(), err);
4975d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4976d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    mCodec->mPortEOS[kPortIndexInput] = true;
4977d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    mCodec->mInputEOSResult = err;
4978d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
4979d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            } else if (!mCodec->mPortEOS[kPortIndexInput]) {
4980d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                if (err != OK && err != ERROR_END_OF_STREAM) {
4981d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    ALOGV("[%s] Signalling EOS on the input port due to error %d",
4982fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                         mCodec->mComponentName.c_str(), err);
4983fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                } else {
4984fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                    ALOGV("[%s] Signalling EOS on the input port",
4985fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                         mCodec->mComponentName.c_str());
4986d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
4987d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4988d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                ALOGV("[%s] calling emptyBuffer %u signalling EOS",
4989fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                     mCodec->mComponentName.c_str(), bufferID);
4990d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
4991fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                info->checkReadFence("onInputBufferFilled");
4992fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                status_t err2 = mCodec->mOMX->emptyBuffer(
4993d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        mCodec->mNode,
4994fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                        bufferID,
4995d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        0,
4996d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        0,
4997d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        OMX_BUFFERFLAG_EOS,
4998d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        0,
4999d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        info->mFenceFd);
5000d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                info->mFenceFd = -1;
5001d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                if (err2 != OK) {
5002d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2));
5003d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    return;
5004d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
5005fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
5006fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
5007fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                mCodec->mPortEOS[kPortIndexInput] = true;
5008fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                mCodec->mInputEOSResult = err;
5009fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            }
5010fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            break;
5011fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        }
5012fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
5013fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        case FREE_BUFFERS:
5014d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
5015d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5016d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        default:
5017fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            ALOGE("invalid port mode: %d", mode);
5018d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
5019fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    }
5020fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev}
5021d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5022fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheevvoid ACodec::BaseState::getMoreInputDataIfPossible() {
5023d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (mCodec->mPortEOS[kPortIndexInput]) {
5024d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return;
5025d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
5026d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5027fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    BufferInfo *eligible = NULL;
5028d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5029fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
5030fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
5031d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5032fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev#if 0
5033d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
5034d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            // There's already a "read" pending.
5035d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return;
5036d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
5037d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#endif
5038d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5039d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (info->mStatus == BufferInfo::OWNED_BY_US) {
5040fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            eligible = info;
5041d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
5042d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
5043fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
5044fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    if (eligible == NULL) {
5045fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        return;
5046fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    }
5047fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
5048d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    postFillThisBuffer(eligible);
5049d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
5050d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5051d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightbool ACodec::BaseState::onOMXFillBufferDone(
5052fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        IOMX::buffer_id bufferID,
5053d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        size_t rangeOffset, size_t rangeLength,
5054fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        OMX_U32 flags,
5055fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        int64_t timeUs,
5056d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int fenceFd) {
5057fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    ALOGV("[%s] onOMXFillBufferDone %u time %" PRId64 " us, flags = 0x%08x",
5058fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev         mCodec->mComponentName.c_str(), bufferID, timeUs, flags);
5059d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5060d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    ssize_t index;
5061d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err= OK;
5062d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5063d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#if TRACK_BUFFER_TIMING
5064d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    index = mCodec->mBufferStats.indexOfKey(timeUs);
5065d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (index >= 0) {
5066d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index);
5067d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        stats->mFillBufferDoneTimeUs = ALooper::GetNowUs();
5068d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5069fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        ALOGI("frame PTS %lld: %lld",
5070d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                timeUs,
5071d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs);
5072fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
5073fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        mCodec->mBufferStats.removeItemsAt(index);
5074fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        stats = NULL;
5075fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    }
5076fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev#endif
5077d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5078d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    BufferInfo *info =
5079d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
5080d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    BufferInfo::Status status = BufferInfo::getSafeStatus(info);
5081fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    if (status != BufferInfo::OWNED_BY_COMPONENT) {
5082d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGE("Wrong ownership in FBD: %s(%d) buffer #%u", _asString(status), status, bufferID);
5083fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        mCodec->dumpBuffers(kPortIndexOutput);
5084fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
5085d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (fenceFd >= 0) {
5086fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            ::close(fenceFd);
5087fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        }
5088d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return true;
5089d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
5090d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5091d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    info->mDequeuedAt = ++mCodec->mDequeueCounter;
5092d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    info->mStatus = BufferInfo::OWNED_BY_US;
5093d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5094d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (info->mRenderInfo != NULL) {
5095d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // The fence for an emptied buffer must have signaled, but there still could be queued
5096d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // or out-of-order dequeued buffers in the render queue prior to this buffer. Drop these,
5097d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // as we will soon requeue this buffer to the surface. While in theory we could still keep
5098fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        // track of buffers that are requeued to the surface, it is better to add support to the
5099d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // buffer-queue to notify us of released buffers and their fences (in the future).
5100d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mCodec->notifyOfRenderedFrames(true /* dropIncomplete */);
5101fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    }
5102fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
5103fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    // byte buffers cannot take fences, so wait for any fence now
5104fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    if (mCodec->mNativeWindow == NULL) {
5105fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        (void)mCodec->waitForFence(fenceFd, "onOMXFillBufferDone");
5106d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        fenceFd = -1;
5107d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
5108d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    info->setReadFence(fenceFd, "onOMXFillBufferDone");
5109d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5110fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    PortMode mode = getPortMode(kPortIndexOutput);
5111d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5112fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev    switch (mode) {
5113fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        case KEEP_BUFFERS:
5114d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
5115fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
5116fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev        case RESUBMIT_BUFFERS:
5117d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {
5118d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (rangeLength == 0 && (!(flags & OMX_BUFFERFLAG_EOS)
5119d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    || mCodec->mPortEOS[kPortIndexOutput])) {
5120d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                ALOGV("[%s] calling fillBuffer %u",
5121d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                     mCodec->mComponentName.c_str(), info->mBufferID);
5122d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5123d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID, info->mFenceFd);
5124d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                info->mFenceFd = -1;
5125d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                if (err != OK) {
5126d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5127fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                    return true;
5128d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
5129d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5130fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
5131fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                break;
5132fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            }
5133fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
5134fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            sp<AMessage> reply =
5135d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                new AMessage(kWhatOutputBufferDrained, mCodec);
5136d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5137d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (!mCodec->mSentFormat && rangeLength > 0) {
5138d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mCodec->sendFormatChange(reply);
5139fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            }
5140d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (mCodec->usingMetadataOnEncoderOutput()) {
5141fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                native_handle_t *handle = NULL;
5142fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                VideoGrallocMetadata &grallocMeta = *(VideoGrallocMetadata *)info->mData->data();
5143d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)info->mData->data();
5144fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                if (info->mData->size() >= sizeof(grallocMeta)
5145fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                        && grallocMeta.eType == kMetadataBufferTypeGrallocSource) {
5146d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    handle = (native_handle_t *)(uintptr_t)grallocMeta.pHandle;
5147d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                } else if (info->mData->size() >= sizeof(nativeMeta)
5148d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        && nativeMeta.eType == kMetadataBufferTypeANWBuffer) {
5149d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#ifdef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
5150fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                    // ANativeWindowBuffer is only valid on 32-bit/mediaserver process
5151fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                    handle = NULL;
5152d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#else
5153d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    handle = (native_handle_t *)nativeMeta.pBuffer->handle;
5154d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#endif
5155d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
5156d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                info->mData->meta()->setPointer("handle", handle);
5157fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                info->mData->meta()->setInt32("rangeOffset", rangeOffset);
5158fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                info->mData->meta()->setInt32("rangeLength", rangeLength);
5159fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            } else {
5160fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                info->mData->setRange(rangeOffset, rangeLength);
5161fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            }
5162d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright#if 0
5163d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (mCodec->mNativeWindow == NULL) {
5164d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                if (IsIDR(info->mData)) {
5165d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    ALOGI("IDR frame");
5166fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                }
5167d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
5168fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev#endif
5169fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
5170d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (mCodec->mSkipCutBuffer != NULL) {
5171fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                mCodec->mSkipCutBuffer->submit(info->mData);
5172d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
5173d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            info->mData->meta()->setInt64("timeUs", timeUs);
5174d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5175d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            sp<AMessage> notify = mCodec->mNotify->dup();
5176d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            notify->setInt32("what", CodecBase::kWhatDrainThisBuffer);
5177d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            notify->setInt32("buffer-id", info->mBufferID);
5178fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            notify->setBuffer("buffer", info->mData);
5179fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            notify->setInt32("flags", flags);
5180fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
5181fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            reply->setInt32("buffer-id", info->mBufferID);
5182fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev
5183d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            notify->setMessage("reply", reply);
5184d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5185d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            notify->post();
5186d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5187fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
5188d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5189fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev            if (flags & OMX_BUFFERFLAG_EOS) {
5190fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str());
5191d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5192fb7525847700ef8c328616727c747dc5e0ca8c4eVladislav Kaznacheev                sp<AMessage> notify = mCodec->mNotify->dup();
5193d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                notify->setInt32("what", CodecBase::kWhatEOS);
5194d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                notify->setInt32("err", mCodec->mInputEOSResult);
5195d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                notify->post();
5196d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5197d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mCodec->mPortEOS[kPortIndexOutput] = true;
5198d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
5199d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
5200d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
5201d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5202d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case FREE_BUFFERS:
5203d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            err = mCodec->freeBuffer(kPortIndexOutput, index);
5204d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (err != OK) {
5205d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5206d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                return true;
5207d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
5208d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
5209d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5210d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        default:
5211d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGE("Invalid port mode: %d", mode);
5212d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return false;
5213d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
5214d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5215d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return true;
5216d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
5217d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5218d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
5219d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    IOMX::buffer_id bufferID;
5220d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
5221d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    ssize_t index;
5222d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    BufferInfo *info = mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
5223d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    BufferInfo::Status status = BufferInfo::getSafeStatus(info);
5224d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (status != BufferInfo::OWNED_BY_DOWNSTREAM) {
5225d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGE("Wrong ownership in OBD: %s(%d) buffer #%u", _asString(status), status, bufferID);
5226d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mCodec->dumpBuffers(kPortIndexOutput);
5227d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
5228d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return;
5229d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
5230d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5231d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    android_native_rect_t crop;
5232d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (msg->findRect("crop", &crop.left, &crop.top, &crop.right, &crop.bottom)) {
5233d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        status_t err = native_window_set_crop(mCodec->mNativeWindow.get(), &crop);
5234d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGW_IF(err != NO_ERROR, "failed to set crop: %d", err);
5235d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
5236d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5237d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t render;
5238d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (mCodec->mNativeWindow != NULL
5239d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            && msg->findInt32("render", &render) && render != 0
5240d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            && info->mData != NULL && info->mData->size() != 0) {
5241d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ATRACE_NAME("render");
5242d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // The client wants this buffer to be rendered.
5243d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5244d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // save buffers sent to the surface so we can get render time when they return
5245d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int64_t mediaTimeUs = -1;
5246d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        info->mData->meta()->findInt64("timeUs", &mediaTimeUs);
5247d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (mediaTimeUs >= 0) {
5248d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mCodec->mRenderTracker.onFrameQueued(
5249d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    mediaTimeUs, info->mGraphicBuffer, new Fence(::dup(info->mFenceFd)));
5250d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
5251d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5252d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        int64_t timestampNs = 0;
5253d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (!msg->findInt64("timestampNs", &timestampNs)) {
5254d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            // use media timestamp if client did not request a specific render timestamp
5255d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (info->mData->meta()->findInt64("timeUs", &timestampNs)) {
5256d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                ALOGV("using buffer PTS of %lld", (long long)timestampNs);
5257d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                timestampNs *= 1000;
5258d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
5259d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
5260d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5261d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        status_t err;
5262d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs);
5263d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ALOGW_IF(err != NO_ERROR, "failed to set buffer timestamp: %d", err);
5264d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5265d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        info->checkReadFence("onOutputBufferDrained before queueBuffer");
5266d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        err = mCodec->mNativeWindow->queueBuffer(
5267d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    mCodec->mNativeWindow.get(), info->mGraphicBuffer.get(), info->mFenceFd);
5268d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        info->mFenceFd = -1;
5269d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (err == OK) {
5270d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
5271d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        } else {
5272d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGE("queueBuffer failed in onOutputBufferDrained: %d", err);
5273d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5274d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            info->mStatus = BufferInfo::OWNED_BY_US;
5275d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            // keeping read fence as write fence to avoid clobbering
5276d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            info->mIsReadFence = false;
5277d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
5278d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    } else {
5279d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (mCodec->mNativeWindow != NULL &&
5280d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            (info->mData == NULL || info->mData->size() != 0)) {
5281d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            // move read fence into write fence to avoid clobbering
5282d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            info->mIsReadFence = false;
5283d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ATRACE_NAME("frame-drop");
5284d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
5285d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        info->mStatus = BufferInfo::OWNED_BY_US;
5286d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
5287d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5288d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    PortMode mode = getPortMode(kPortIndexOutput);
5289d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5290d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    switch (mode) {
5291d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case KEEP_BUFFERS:
5292d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {
5293d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
5294d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5295d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
5296d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                // We cannot resubmit the buffer we just rendered, dequeue
5297d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                // the spare instead.
5298d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5299d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                info = mCodec->dequeueBufferFromNativeWindow();
5300d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
5301d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
5302d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
5303d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5304d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case RESUBMIT_BUFFERS:
5305d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {
5306d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (!mCodec->mPortEOS[kPortIndexOutput]) {
5307d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
5308d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    // We cannot resubmit the buffer we just rendered, dequeue
5309d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    // the spare instead.
5310d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5311d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    info = mCodec->dequeueBufferFromNativeWindow();
5312d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
5313d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5314d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                if (info != NULL) {
5315d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    ALOGV("[%s] calling fillBuffer %u",
5316d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                         mCodec->mComponentName.c_str(), info->mBufferID);
5317d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    info->checkWriteFence("onOutputBufferDrained::RESUBMIT_BUFFERS");
5318d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    status_t err = mCodec->mOMX->fillBuffer(
5319d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                            mCodec->mNode, info->mBufferID, info->mFenceFd);
5320d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    info->mFenceFd = -1;
5321d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    if (err == OK) {
5322d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
5323d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    } else {
5324d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5325d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    }
5326d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                }
5327d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
5328d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
5329d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
5330d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5331d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case FREE_BUFFERS:
5332d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {
5333d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            status_t err = mCodec->freeBuffer(kPortIndexOutput, index);
5334d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            if (err != OK) {
5335d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5336d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            }
5337d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
5338d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
5339d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5340d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        default:
5341d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGE("Invalid port mode: %d", mode);
5342d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return;
5343d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
5344d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
5345d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5346d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright////////////////////////////////////////////////////////////////////////////////
5347d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5348d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael WrightACodec::UninitializedState::UninitializedState(ACodec *codec)
5349d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    : BaseState(codec) {
5350d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
5351d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5352d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::UninitializedState::stateEntered() {
5353d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    ALOGV("Now uninitialized");
5354d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5355d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (mDeathNotifier != NULL) {
5356d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        IInterface::asBinder(mCodec->mOMX)->unlinkToDeath(mDeathNotifier);
5357d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mDeathNotifier.clear();
5358d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
5359d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5360d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mCodec->mNativeWindow.clear();
5361d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mCodec->mNativeWindowUsageBits = 0;
5362d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mCodec->mNode = 0;
5363d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mCodec->mOMX.clear();
5364d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mCodec->mQuirks = 0;
5365d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mCodec->mFlags = 0;
5366d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mCodec->mInputMetadataType = kMetadataBufferTypeInvalid;
5367d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mCodec->mOutputMetadataType = kMetadataBufferTypeInvalid;
5368d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mCodec->mComponentName.clear();
5369d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
5370d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5371d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightbool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
5372d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    bool handled = false;
5373d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5374d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    switch (msg->what()) {
5375d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case ACodec::kWhatSetup:
5376d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {
5377d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            onSetup(msg);
5378d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5379d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            handled = true;
5380d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
5381d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
5382d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5383d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case ACodec::kWhatAllocateComponent:
5384d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {
5385d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            onAllocateComponent(msg);
5386d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            handled = true;
5387d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
5388d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
5389d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5390d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case ACodec::kWhatShutdown:
5391d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {
5392d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            int32_t keepComponentAllocated;
5393d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            CHECK(msg->findInt32(
5394d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                        "keepComponentAllocated", &keepComponentAllocated));
5395d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ALOGW_IF(keepComponentAllocated,
5396d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                     "cannot keep component allocated on shutdown in Uninitialized state");
5397d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5398d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            sp<AMessage> notify = mCodec->mNotify->dup();
5399d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
5400d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            notify->post();
5401d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5402d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            handled = true;
5403d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
5404d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
5405d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5406d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case ACodec::kWhatFlush:
5407d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {
5408d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            sp<AMessage> notify = mCodec->mNotify->dup();
5409d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5410d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            notify->post();
5411d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5412d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            handled = true;
5413d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
5414d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
5415d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5416d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        case ACodec::kWhatReleaseCodecInstance:
5417d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        {
5418d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            // nothing to do, as we have already signaled shutdown
5419d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            handled = true;
5420d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            break;
5421d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
5422d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5423d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        default:
5424d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            return BaseState::onMessageReceived(msg);
5425d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
5426d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5427d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    return handled;
5428d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
5429d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5430d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightvoid ACodec::UninitializedState::onSetup(
5431d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        const sp<AMessage> &msg) {
5432d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (onAllocateComponent(msg)
5433d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            && mCodec->mLoadedState->onConfigureComponent(msg)) {
5434d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mCodec->mLoadedState->onStart();
5435d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
5436d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright}
5437d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5438d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightbool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
5439d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    ALOGV("onAllocateComponent");
5440d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5441d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    CHECK(mCodec->mNode == 0);
5442d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5443d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    OMXClient client;
5444d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (client.connect() != OK) {
5445d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
5446d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        return false;
5447d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
5448d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5449d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    sp<IOMX> omx = client.interface();
5450d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5451d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec);
5452d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5453d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    mDeathNotifier = new DeathNotifier(notify);
5454d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (IInterface::asBinder(omx)->linkToDeath(mDeathNotifier) != OK) {
5455d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // This was a local binder, if it dies so do we, we won't care
5456d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        // about any notifications in the afterlife.
5457d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        mDeathNotifier.clear();
5458d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
5459d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5460d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs;
5461d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5462d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    AString mime;
5463d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5464d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    AString componentName;
5465d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    uint32_t quirks = 0;
5466d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    int32_t encoder = false;
5467d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    if (msg->findString("componentName", &componentName)) {
5468d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        ssize_t index = matchingCodecs.add();
5469d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        OMXCodec::CodecNameAndQuirks *entry = &matchingCodecs.editItemAt(index);
5470d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        entry->mName = String8(componentName.c_str());
5471d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5472d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (!OMXCodec::findCodecQuirks(
5473d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                    componentName.c_str(), &entry->mQuirks)) {
5474d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            entry->mQuirks = 0;
5475d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
5476d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    } else {
5477d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        CHECK(msg->findString("mime", &mime));
5478d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5479d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        if (!msg->findInt32("encoder", &encoder)) {
5480d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            encoder = false;
5481d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        }
5482d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5483d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        OMXCodec::findMatchingCodecs(
5484d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                mime.c_str(),
5485d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                encoder, // createEncoder
5486d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                NULL,  // matchComponentName
5487d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                0,     // flags
5488d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright                &matchingCodecs);
5489d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    }
5490d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5491d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    sp<CodecObserver> observer = new CodecObserver;
5492d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    IOMX::node_id node = 0;
5493d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright
5494d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    status_t err = NAME_NOT_FOUND;
5495d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright    for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
5496d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright            ++matchIndex) {
5497d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        componentName = matchingCodecs.itemAt(matchIndex).mName.string();
5498d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright        quirks = matchingCodecs.itemAt(matchIndex).mQuirks;
5499
5500        pid_t tid = gettid();
5501        int prevPriority = androidGetThreadPriority(tid);
5502        androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
5503        err = omx->allocateNode(componentName.c_str(), observer, &node);
5504        androidSetThreadPriority(tid, prevPriority);
5505
5506        if (err == OK) {
5507            break;
5508        } else {
5509            ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str());
5510        }
5511
5512        node = 0;
5513    }
5514
5515    if (node == 0) {
5516        if (!mime.empty()) {
5517            ALOGE("Unable to instantiate a %scoder for type '%s' with err %#x.",
5518                    encoder ? "en" : "de", mime.c_str(), err);
5519        } else {
5520            ALOGE("Unable to instantiate codec '%s' with err %#x.", componentName.c_str(), err);
5521        }
5522
5523        mCodec->signalError((OMX_ERRORTYPE)err, makeNoSideEffectStatus(err));
5524        return false;
5525    }
5526
5527    notify = new AMessage(kWhatOMXMessageList, mCodec);
5528    observer->setNotificationMessage(notify);
5529
5530    mCodec->mComponentName = componentName;
5531    mCodec->mRenderTracker.setComponentName(componentName);
5532    mCodec->mFlags = 0;
5533
5534    if (componentName.endsWith(".secure")) {
5535        mCodec->mFlags |= kFlagIsSecure;
5536        mCodec->mFlags |= kFlagIsGrallocUsageProtected;
5537        mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
5538    }
5539
5540    mCodec->mQuirks = quirks;
5541    mCodec->mOMX = omx;
5542    mCodec->mNode = node;
5543
5544    {
5545        sp<AMessage> notify = mCodec->mNotify->dup();
5546        notify->setInt32("what", CodecBase::kWhatComponentAllocated);
5547        notify->setString("componentName", mCodec->mComponentName.c_str());
5548        notify->post();
5549    }
5550
5551    mCodec->changeState(mCodec->mLoadedState);
5552
5553    return true;
5554}
5555
5556////////////////////////////////////////////////////////////////////////////////
5557
5558ACodec::LoadedState::LoadedState(ACodec *codec)
5559    : BaseState(codec) {
5560}
5561
5562void ACodec::LoadedState::stateEntered() {
5563    ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
5564
5565    mCodec->mPortEOS[kPortIndexInput] =
5566        mCodec->mPortEOS[kPortIndexOutput] = false;
5567
5568    mCodec->mInputEOSResult = OK;
5569
5570    mCodec->mDequeueCounter = 0;
5571    mCodec->mMetadataBuffersToSubmit = 0;
5572    mCodec->mRepeatFrameDelayUs = -1ll;
5573    mCodec->mInputFormat.clear();
5574    mCodec->mOutputFormat.clear();
5575    mCodec->mBaseOutputFormat.clear();
5576
5577    if (mCodec->mShutdownInProgress) {
5578        bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
5579
5580        mCodec->mShutdownInProgress = false;
5581        mCodec->mKeepComponentAllocated = false;
5582
5583        onShutdown(keepComponentAllocated);
5584    }
5585    mCodec->mExplicitShutdown = false;
5586
5587    mCodec->processDeferredMessages();
5588}
5589
5590void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
5591    if (!keepComponentAllocated) {
5592        (void)mCodec->mOMX->freeNode(mCodec->mNode);
5593
5594        mCodec->changeState(mCodec->mUninitializedState);
5595    }
5596
5597    if (mCodec->mExplicitShutdown) {
5598        sp<AMessage> notify = mCodec->mNotify->dup();
5599        notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
5600        notify->post();
5601        mCodec->mExplicitShutdown = false;
5602    }
5603}
5604
5605bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
5606    bool handled = false;
5607
5608    switch (msg->what()) {
5609        case ACodec::kWhatConfigureComponent:
5610        {
5611            onConfigureComponent(msg);
5612            handled = true;
5613            break;
5614        }
5615
5616        case ACodec::kWhatCreateInputSurface:
5617        {
5618            onCreateInputSurface(msg);
5619            handled = true;
5620            break;
5621        }
5622
5623        case ACodec::kWhatSetInputSurface:
5624        {
5625            onSetInputSurface(msg);
5626            handled = true;
5627            break;
5628        }
5629
5630        case ACodec::kWhatStart:
5631        {
5632            onStart();
5633            handled = true;
5634            break;
5635        }
5636
5637        case ACodec::kWhatShutdown:
5638        {
5639            int32_t keepComponentAllocated;
5640            CHECK(msg->findInt32(
5641                        "keepComponentAllocated", &keepComponentAllocated));
5642
5643            mCodec->mExplicitShutdown = true;
5644            onShutdown(keepComponentAllocated);
5645
5646            handled = true;
5647            break;
5648        }
5649
5650        case ACodec::kWhatFlush:
5651        {
5652            sp<AMessage> notify = mCodec->mNotify->dup();
5653            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5654            notify->post();
5655
5656            handled = true;
5657            break;
5658        }
5659
5660        default:
5661            return BaseState::onMessageReceived(msg);
5662    }
5663
5664    return handled;
5665}
5666
5667bool ACodec::LoadedState::onConfigureComponent(
5668        const sp<AMessage> &msg) {
5669    ALOGV("onConfigureComponent");
5670
5671    CHECK(mCodec->mNode != 0);
5672
5673    status_t err = OK;
5674    AString mime;
5675    if (!msg->findString("mime", &mime)) {
5676        err = BAD_VALUE;
5677    } else {
5678        err = mCodec->configureCodec(mime.c_str(), msg);
5679    }
5680    if (err != OK) {
5681        ALOGE("[%s] configureCodec returning error %d",
5682              mCodec->mComponentName.c_str(), err);
5683
5684        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5685        return false;
5686    }
5687
5688    {
5689        sp<AMessage> notify = mCodec->mNotify->dup();
5690        notify->setInt32("what", CodecBase::kWhatComponentConfigured);
5691        notify->setMessage("input-format", mCodec->mInputFormat);
5692        notify->setMessage("output-format", mCodec->mOutputFormat);
5693        notify->post();
5694    }
5695
5696    return true;
5697}
5698
5699status_t ACodec::LoadedState::setupInputSurface() {
5700    status_t err = OK;
5701
5702    if (mCodec->mRepeatFrameDelayUs > 0ll) {
5703        err = mCodec->mOMX->setInternalOption(
5704                mCodec->mNode,
5705                kPortIndexInput,
5706                IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY,
5707                &mCodec->mRepeatFrameDelayUs,
5708                sizeof(mCodec->mRepeatFrameDelayUs));
5709
5710        if (err != OK) {
5711            ALOGE("[%s] Unable to configure option to repeat previous "
5712                  "frames (err %d)",
5713                  mCodec->mComponentName.c_str(),
5714                  err);
5715            return err;
5716        }
5717    }
5718
5719    if (mCodec->mMaxPtsGapUs > 0ll) {
5720        err = mCodec->mOMX->setInternalOption(
5721                mCodec->mNode,
5722                kPortIndexInput,
5723                IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP,
5724                &mCodec->mMaxPtsGapUs,
5725                sizeof(mCodec->mMaxPtsGapUs));
5726
5727        if (err != OK) {
5728            ALOGE("[%s] Unable to configure max timestamp gap (err %d)",
5729                    mCodec->mComponentName.c_str(),
5730                    err);
5731            return err;
5732        }
5733    }
5734
5735    if (mCodec->mMaxFps > 0) {
5736        err = mCodec->mOMX->setInternalOption(
5737                mCodec->mNode,
5738                kPortIndexInput,
5739                IOMX::INTERNAL_OPTION_MAX_FPS,
5740                &mCodec->mMaxFps,
5741                sizeof(mCodec->mMaxFps));
5742
5743        if (err != OK) {
5744            ALOGE("[%s] Unable to configure max fps (err %d)",
5745                    mCodec->mComponentName.c_str(),
5746                    err);
5747            return err;
5748        }
5749    }
5750
5751    if (mCodec->mTimePerCaptureUs > 0ll
5752            && mCodec->mTimePerFrameUs > 0ll) {
5753        int64_t timeLapse[2];
5754        timeLapse[0] = mCodec->mTimePerFrameUs;
5755        timeLapse[1] = mCodec->mTimePerCaptureUs;
5756        err = mCodec->mOMX->setInternalOption(
5757                mCodec->mNode,
5758                kPortIndexInput,
5759                IOMX::INTERNAL_OPTION_TIME_LAPSE,
5760                &timeLapse[0],
5761                sizeof(timeLapse));
5762
5763        if (err != OK) {
5764            ALOGE("[%s] Unable to configure time lapse (err %d)",
5765                    mCodec->mComponentName.c_str(),
5766                    err);
5767            return err;
5768        }
5769    }
5770
5771    if (mCodec->mCreateInputBuffersSuspended) {
5772        bool suspend = true;
5773        err = mCodec->mOMX->setInternalOption(
5774                mCodec->mNode,
5775                kPortIndexInput,
5776                IOMX::INTERNAL_OPTION_SUSPEND,
5777                &suspend,
5778                sizeof(suspend));
5779
5780        if (err != OK) {
5781            ALOGE("[%s] Unable to configure option to suspend (err %d)",
5782                  mCodec->mComponentName.c_str(),
5783                  err);
5784            return err;
5785        }
5786    }
5787
5788    uint32_t usageBits;
5789    if (mCodec->mOMX->getParameter(
5790            mCodec->mNode, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
5791            &usageBits, sizeof(usageBits)) == OK) {
5792        mCodec->mInputFormat->setInt32(
5793                "using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN));
5794    }
5795
5796    return OK;
5797}
5798
5799void ACodec::LoadedState::onCreateInputSurface(
5800        const sp<AMessage> & /* msg */) {
5801    ALOGV("onCreateInputSurface");
5802
5803    sp<AMessage> notify = mCodec->mNotify->dup();
5804    notify->setInt32("what", CodecBase::kWhatInputSurfaceCreated);
5805
5806    sp<IGraphicBufferProducer> bufferProducer;
5807    status_t err = mCodec->mOMX->createInputSurface(
5808            mCodec->mNode, kPortIndexInput, &bufferProducer, &mCodec->mInputMetadataType);
5809
5810    if (err == OK) {
5811        err = setupInputSurface();
5812    }
5813
5814    if (err == OK) {
5815        notify->setObject("input-surface",
5816                new BufferProducerWrapper(bufferProducer));
5817    } else {
5818        // Can't use mCodec->signalError() here -- MediaCodec won't forward
5819        // the error through because it's in the "configured" state.  We
5820        // send a kWhatInputSurfaceCreated with an error value instead.
5821        ALOGE("[%s] onCreateInputSurface returning error %d",
5822                mCodec->mComponentName.c_str(), err);
5823        notify->setInt32("err", err);
5824    }
5825    notify->post();
5826}
5827
5828void ACodec::LoadedState::onSetInputSurface(
5829        const sp<AMessage> &msg) {
5830    ALOGV("onSetInputSurface");
5831
5832    sp<AMessage> notify = mCodec->mNotify->dup();
5833    notify->setInt32("what", CodecBase::kWhatInputSurfaceAccepted);
5834
5835    sp<RefBase> obj;
5836    CHECK(msg->findObject("input-surface", &obj));
5837    sp<PersistentSurface> surface = static_cast<PersistentSurface *>(obj.get());
5838
5839    status_t err = mCodec->mOMX->setInputSurface(
5840            mCodec->mNode, kPortIndexInput, surface->getBufferConsumer(),
5841            &mCodec->mInputMetadataType);
5842
5843    if (err == OK) {
5844        err = setupInputSurface();
5845    }
5846
5847    if (err != OK) {
5848        // Can't use mCodec->signalError() here -- MediaCodec won't forward
5849        // the error through because it's in the "configured" state.  We
5850        // send a kWhatInputSurfaceAccepted with an error value instead.
5851        ALOGE("[%s] onSetInputSurface returning error %d",
5852                mCodec->mComponentName.c_str(), err);
5853        notify->setInt32("err", err);
5854    }
5855    notify->post();
5856}
5857
5858void ACodec::LoadedState::onStart() {
5859    ALOGV("onStart");
5860
5861    status_t err = mCodec->mOMX->sendCommand(mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle);
5862    if (err != OK) {
5863        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5864    } else {
5865        mCodec->changeState(mCodec->mLoadedToIdleState);
5866    }
5867}
5868
5869////////////////////////////////////////////////////////////////////////////////
5870
5871ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
5872    : BaseState(codec) {
5873}
5874
5875void ACodec::LoadedToIdleState::stateEntered() {
5876    ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
5877
5878    status_t err;
5879    if ((err = allocateBuffers()) != OK) {
5880        ALOGE("Failed to allocate buffers after transitioning to IDLE state "
5881             "(error 0x%08x)",
5882             err);
5883
5884        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5885
5886        mCodec->changeState(mCodec->mLoadedState);
5887    }
5888}
5889
5890status_t ACodec::LoadedToIdleState::allocateBuffers() {
5891    status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
5892
5893    if (err != OK) {
5894        return err;
5895    }
5896
5897    return mCodec->allocateBuffersOnPort(kPortIndexOutput);
5898}
5899
5900bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
5901    switch (msg->what()) {
5902        case kWhatSetParameters:
5903        case kWhatShutdown:
5904        {
5905            mCodec->deferMessage(msg);
5906            return true;
5907        }
5908
5909        case kWhatSignalEndOfInputStream:
5910        {
5911            mCodec->onSignalEndOfInputStream();
5912            return true;
5913        }
5914
5915        case kWhatResume:
5916        {
5917            // We'll be active soon enough.
5918            return true;
5919        }
5920
5921        case kWhatFlush:
5922        {
5923            // We haven't even started yet, so we're flushed alright...
5924            sp<AMessage> notify = mCodec->mNotify->dup();
5925            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5926            notify->post();
5927            return true;
5928        }
5929
5930        default:
5931            return BaseState::onMessageReceived(msg);
5932    }
5933}
5934
5935bool ACodec::LoadedToIdleState::onOMXEvent(
5936        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5937    switch (event) {
5938        case OMX_EventCmdComplete:
5939        {
5940            status_t err = OK;
5941            if (data1 != (OMX_U32)OMX_CommandStateSet
5942                    || data2 != (OMX_U32)OMX_StateIdle) {
5943                ALOGE("Unexpected command completion in LoadedToIdleState: %s(%u) %s(%u)",
5944                        asString((OMX_COMMANDTYPE)data1), data1,
5945                        asString((OMX_STATETYPE)data2), data2);
5946                err = FAILED_TRANSACTION;
5947            }
5948
5949            if (err == OK) {
5950                err = mCodec->mOMX->sendCommand(
5951                    mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting);
5952            }
5953
5954            if (err != OK) {
5955                mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5956            } else {
5957                mCodec->changeState(mCodec->mIdleToExecutingState);
5958            }
5959
5960            return true;
5961        }
5962
5963        default:
5964            return BaseState::onOMXEvent(event, data1, data2);
5965    }
5966}
5967
5968////////////////////////////////////////////////////////////////////////////////
5969
5970ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
5971    : BaseState(codec) {
5972}
5973
5974void ACodec::IdleToExecutingState::stateEntered() {
5975    ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
5976}
5977
5978bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
5979    switch (msg->what()) {
5980        case kWhatSetParameters:
5981        case kWhatShutdown:
5982        {
5983            mCodec->deferMessage(msg);
5984            return true;
5985        }
5986
5987        case kWhatResume:
5988        {
5989            // We'll be active soon enough.
5990            return true;
5991        }
5992
5993        case kWhatFlush:
5994        {
5995            // We haven't even started yet, so we're flushed alright...
5996            sp<AMessage> notify = mCodec->mNotify->dup();
5997            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5998            notify->post();
5999
6000            return true;
6001        }
6002
6003        case kWhatSignalEndOfInputStream:
6004        {
6005            mCodec->onSignalEndOfInputStream();
6006            return true;
6007        }
6008
6009        default:
6010            return BaseState::onMessageReceived(msg);
6011    }
6012}
6013
6014bool ACodec::IdleToExecutingState::onOMXEvent(
6015        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6016    switch (event) {
6017        case OMX_EventCmdComplete:
6018        {
6019            if (data1 != (OMX_U32)OMX_CommandStateSet
6020                    || data2 != (OMX_U32)OMX_StateExecuting) {
6021                ALOGE("Unexpected command completion in IdleToExecutingState: %s(%u) %s(%u)",
6022                        asString((OMX_COMMANDTYPE)data1), data1,
6023                        asString((OMX_STATETYPE)data2), data2);
6024                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6025                return true;
6026            }
6027
6028            mCodec->mExecutingState->resume();
6029            mCodec->changeState(mCodec->mExecutingState);
6030
6031            return true;
6032        }
6033
6034        default:
6035            return BaseState::onOMXEvent(event, data1, data2);
6036    }
6037}
6038
6039////////////////////////////////////////////////////////////////////////////////
6040
6041ACodec::ExecutingState::ExecutingState(ACodec *codec)
6042    : BaseState(codec),
6043      mActive(false) {
6044}
6045
6046ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
6047        OMX_U32 /* portIndex */) {
6048    return RESUBMIT_BUFFERS;
6049}
6050
6051void ACodec::ExecutingState::submitOutputMetaBuffers() {
6052    // submit as many buffers as there are input buffers with the codec
6053    // in case we are in port reconfiguring
6054    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
6055        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
6056
6057        if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) {
6058            if (mCodec->submitOutputMetadataBuffer() != OK)
6059                break;
6060        }
6061    }
6062
6063    // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
6064    mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround();
6065}
6066
6067void ACodec::ExecutingState::submitRegularOutputBuffers() {
6068    bool failed = false;
6069    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
6070        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
6071
6072        if (mCodec->mNativeWindow != NULL) {
6073            if (info->mStatus != BufferInfo::OWNED_BY_US
6074                    && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
6075                ALOGE("buffers should be owned by us or the surface");
6076                failed = true;
6077                break;
6078            }
6079
6080            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
6081                continue;
6082            }
6083        } else {
6084            if (info->mStatus != BufferInfo::OWNED_BY_US) {
6085                ALOGE("buffers should be owned by us");
6086                failed = true;
6087                break;
6088            }
6089        }
6090
6091        ALOGV("[%s] calling fillBuffer %u", mCodec->mComponentName.c_str(), info->mBufferID);
6092
6093        info->checkWriteFence("submitRegularOutputBuffers");
6094        status_t err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID, info->mFenceFd);
6095        info->mFenceFd = -1;
6096        if (err != OK) {
6097            failed = true;
6098            break;
6099        }
6100
6101        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
6102    }
6103
6104    if (failed) {
6105        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6106    }
6107}
6108
6109void ACodec::ExecutingState::submitOutputBuffers() {
6110    submitRegularOutputBuffers();
6111    if (mCodec->storingMetadataInDecodedBuffers()) {
6112        submitOutputMetaBuffers();
6113    }
6114}
6115
6116void ACodec::ExecutingState::resume() {
6117    if (mActive) {
6118        ALOGV("[%s] We're already active, no need to resume.", mCodec->mComponentName.c_str());
6119        return;
6120    }
6121
6122    submitOutputBuffers();
6123
6124    // Post all available input buffers
6125    if (mCodec->mBuffers[kPortIndexInput].size() == 0u) {
6126        ALOGW("[%s] we don't have any input buffers to resume", mCodec->mComponentName.c_str());
6127    }
6128
6129    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) {
6130        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
6131        if (info->mStatus == BufferInfo::OWNED_BY_US) {
6132            postFillThisBuffer(info);
6133        }
6134    }
6135
6136    mActive = true;
6137}
6138
6139void ACodec::ExecutingState::stateEntered() {
6140    ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
6141
6142    mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC));
6143    mCodec->processDeferredMessages();
6144}
6145
6146bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
6147    bool handled = false;
6148
6149    switch (msg->what()) {
6150        case kWhatShutdown:
6151        {
6152            int32_t keepComponentAllocated;
6153            CHECK(msg->findInt32(
6154                        "keepComponentAllocated", &keepComponentAllocated));
6155
6156            mCodec->mShutdownInProgress = true;
6157            mCodec->mExplicitShutdown = true;
6158            mCodec->mKeepComponentAllocated = keepComponentAllocated;
6159
6160            mActive = false;
6161
6162            status_t err = mCodec->mOMX->sendCommand(
6163                    mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle);
6164            if (err != OK) {
6165                if (keepComponentAllocated) {
6166                    mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6167                }
6168                // TODO: do some recovery here.
6169            } else {
6170                mCodec->changeState(mCodec->mExecutingToIdleState);
6171            }
6172
6173            handled = true;
6174            break;
6175        }
6176
6177        case kWhatFlush:
6178        {
6179            ALOGV("[%s] ExecutingState flushing now "
6180                 "(codec owns %zu/%zu input, %zu/%zu output).",
6181                    mCodec->mComponentName.c_str(),
6182                    mCodec->countBuffersOwnedByComponent(kPortIndexInput),
6183                    mCodec->mBuffers[kPortIndexInput].size(),
6184                    mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
6185                    mCodec->mBuffers[kPortIndexOutput].size());
6186
6187            mActive = false;
6188
6189            status_t err = mCodec->mOMX->sendCommand(mCodec->mNode, OMX_CommandFlush, OMX_ALL);
6190            if (err != OK) {
6191                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6192            } else {
6193                mCodec->changeState(mCodec->mFlushingState);
6194            }
6195
6196            handled = true;
6197            break;
6198        }
6199
6200        case kWhatResume:
6201        {
6202            resume();
6203
6204            handled = true;
6205            break;
6206        }
6207
6208        case kWhatRequestIDRFrame:
6209        {
6210            status_t err = mCodec->requestIDRFrame();
6211            if (err != OK) {
6212                ALOGW("Requesting an IDR frame failed.");
6213            }
6214
6215            handled = true;
6216            break;
6217        }
6218
6219        case kWhatSetParameters:
6220        {
6221            sp<AMessage> params;
6222            CHECK(msg->findMessage("params", &params));
6223
6224            status_t err = mCodec->setParameters(params);
6225
6226            sp<AMessage> reply;
6227            if (msg->findMessage("reply", &reply)) {
6228                reply->setInt32("err", err);
6229                reply->post();
6230            }
6231
6232            handled = true;
6233            break;
6234        }
6235
6236        case ACodec::kWhatSignalEndOfInputStream:
6237        {
6238            mCodec->onSignalEndOfInputStream();
6239            handled = true;
6240            break;
6241        }
6242
6243        // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
6244        case kWhatSubmitOutputMetadataBufferIfEOS:
6245        {
6246            if (mCodec->mPortEOS[kPortIndexInput] &&
6247                    !mCodec->mPortEOS[kPortIndexOutput]) {
6248                status_t err = mCodec->submitOutputMetadataBuffer();
6249                if (err == OK) {
6250                    mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround();
6251                }
6252            }
6253            return true;
6254        }
6255
6256        default:
6257            handled = BaseState::onMessageReceived(msg);
6258            break;
6259    }
6260
6261    return handled;
6262}
6263
6264status_t ACodec::setParameters(const sp<AMessage> &params) {
6265    int32_t videoBitrate;
6266    if (params->findInt32("video-bitrate", &videoBitrate)) {
6267        OMX_VIDEO_CONFIG_BITRATETYPE configParams;
6268        InitOMXParams(&configParams);
6269        configParams.nPortIndex = kPortIndexOutput;
6270        configParams.nEncodeBitrate = videoBitrate;
6271
6272        status_t err = mOMX->setConfig(
6273                mNode,
6274                OMX_IndexConfigVideoBitrate,
6275                &configParams,
6276                sizeof(configParams));
6277
6278        if (err != OK) {
6279            ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d",
6280                   videoBitrate, err);
6281
6282            return err;
6283        }
6284    }
6285
6286    int64_t skipFramesBeforeUs;
6287    if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) {
6288        status_t err =
6289            mOMX->setInternalOption(
6290                     mNode,
6291                     kPortIndexInput,
6292                     IOMX::INTERNAL_OPTION_START_TIME,
6293                     &skipFramesBeforeUs,
6294                     sizeof(skipFramesBeforeUs));
6295
6296        if (err != OK) {
6297            ALOGE("Failed to set parameter 'skip-frames-before' (err %d)", err);
6298            return err;
6299        }
6300    }
6301
6302    int32_t dropInputFrames;
6303    if (params->findInt32("drop-input-frames", &dropInputFrames)) {
6304        bool suspend = dropInputFrames != 0;
6305
6306        status_t err =
6307            mOMX->setInternalOption(
6308                     mNode,
6309                     kPortIndexInput,
6310                     IOMX::INTERNAL_OPTION_SUSPEND,
6311                     &suspend,
6312                     sizeof(suspend));
6313
6314        if (err != OK) {
6315            ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err);
6316            return err;
6317        }
6318    }
6319
6320    int32_t dummy;
6321    if (params->findInt32("request-sync", &dummy)) {
6322        status_t err = requestIDRFrame();
6323
6324        if (err != OK) {
6325            ALOGE("Requesting a sync frame failed w/ err %d", err);
6326            return err;
6327        }
6328    }
6329
6330    float rate;
6331    if (params->findFloat("operating-rate", &rate) && rate > 0) {
6332        status_t err = setOperatingRate(rate, mIsVideo);
6333        if (err != OK) {
6334            ALOGE("Failed to set parameter 'operating-rate' (err %d)", err);
6335            return err;
6336        }
6337    }
6338
6339    return OK;
6340}
6341
6342void ACodec::onSignalEndOfInputStream() {
6343    sp<AMessage> notify = mNotify->dup();
6344    notify->setInt32("what", CodecBase::kWhatSignaledInputEOS);
6345
6346    status_t err = mOMX->signalEndOfInputStream(mNode);
6347    if (err != OK) {
6348        notify->setInt32("err", err);
6349    }
6350    notify->post();
6351}
6352
6353bool ACodec::ExecutingState::onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) {
6354    mCodec->onFrameRendered(mediaTimeUs, systemNano);
6355    return true;
6356}
6357
6358bool ACodec::ExecutingState::onOMXEvent(
6359        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6360    switch (event) {
6361        case OMX_EventPortSettingsChanged:
6362        {
6363            CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
6364
6365            if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
6366                mCodec->mMetadataBuffersToSubmit = 0;
6367                CHECK_EQ(mCodec->mOMX->sendCommand(
6368                            mCodec->mNode,
6369                            OMX_CommandPortDisable, kPortIndexOutput),
6370                         (status_t)OK);
6371
6372                mCodec->freeOutputBuffersNotOwnedByComponent();
6373
6374                mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
6375            } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
6376                mCodec->mSentFormat = false;
6377
6378                if (mCodec->mTunneled) {
6379                    sp<AMessage> dummy = new AMessage(kWhatOutputBufferDrained, mCodec);
6380                    mCodec->sendFormatChange(dummy);
6381                }
6382            } else {
6383                ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08x",
6384                     mCodec->mComponentName.c_str(), data2);
6385            }
6386
6387            return true;
6388        }
6389
6390        case OMX_EventBufferFlag:
6391        {
6392            return true;
6393        }
6394
6395        default:
6396            return BaseState::onOMXEvent(event, data1, data2);
6397    }
6398}
6399
6400////////////////////////////////////////////////////////////////////////////////
6401
6402ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
6403        ACodec *codec)
6404    : BaseState(codec) {
6405}
6406
6407ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
6408        OMX_U32 portIndex) {
6409    if (portIndex == kPortIndexOutput) {
6410        return FREE_BUFFERS;
6411    }
6412
6413    CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
6414
6415    return RESUBMIT_BUFFERS;
6416}
6417
6418bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
6419        const sp<AMessage> &msg) {
6420    bool handled = false;
6421
6422    switch (msg->what()) {
6423        case kWhatFlush:
6424        case kWhatShutdown:
6425        case kWhatResume:
6426        case kWhatSetParameters:
6427        {
6428            if (msg->what() == kWhatResume) {
6429                ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
6430            }
6431
6432            mCodec->deferMessage(msg);
6433            handled = true;
6434            break;
6435        }
6436
6437        default:
6438            handled = BaseState::onMessageReceived(msg);
6439            break;
6440    }
6441
6442    return handled;
6443}
6444
6445void ACodec::OutputPortSettingsChangedState::stateEntered() {
6446    ALOGV("[%s] Now handling output port settings change",
6447         mCodec->mComponentName.c_str());
6448}
6449
6450bool ACodec::OutputPortSettingsChangedState::onOMXFrameRendered(
6451        int64_t mediaTimeUs, nsecs_t systemNano) {
6452    mCodec->onFrameRendered(mediaTimeUs, systemNano);
6453    return true;
6454}
6455
6456bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
6457        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6458    switch (event) {
6459        case OMX_EventCmdComplete:
6460        {
6461            if (data1 == (OMX_U32)OMX_CommandPortDisable) {
6462                if (data2 != (OMX_U32)kPortIndexOutput) {
6463                    ALOGW("ignoring EventCmdComplete CommandPortDisable for port %u", data2);
6464                    return false;
6465                }
6466
6467                ALOGV("[%s] Output port now disabled.", mCodec->mComponentName.c_str());
6468
6469                status_t err = OK;
6470                if (!mCodec->mBuffers[kPortIndexOutput].isEmpty()) {
6471                    ALOGE("disabled port should be empty, but has %zu buffers",
6472                            mCodec->mBuffers[kPortIndexOutput].size());
6473                    err = FAILED_TRANSACTION;
6474                } else {
6475                    mCodec->mDealer[kPortIndexOutput].clear();
6476                }
6477
6478                if (err == OK) {
6479                    err = mCodec->mOMX->sendCommand(
6480                            mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput);
6481                }
6482
6483                if (err == OK) {
6484                    err = mCodec->allocateBuffersOnPort(kPortIndexOutput);
6485                    ALOGE_IF(err != OK, "Failed to allocate output port buffers after port "
6486                            "reconfiguration: (%d)", err);
6487                }
6488
6489                if (err != OK) {
6490                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6491
6492                    // This is technically not correct, but appears to be
6493                    // the only way to free the component instance.
6494                    // Controlled transitioning from excecuting->idle
6495                    // and idle->loaded seem impossible probably because
6496                    // the output port never finishes re-enabling.
6497                    mCodec->mShutdownInProgress = true;
6498                    mCodec->mKeepComponentAllocated = false;
6499                    mCodec->changeState(mCodec->mLoadedState);
6500                }
6501
6502                return true;
6503            } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
6504                if (data2 != (OMX_U32)kPortIndexOutput) {
6505                    ALOGW("ignoring EventCmdComplete OMX_CommandPortEnable for port %u", data2);
6506                    return false;
6507                }
6508
6509                mCodec->mSentFormat = false;
6510
6511                if (mCodec->mTunneled) {
6512                    sp<AMessage> dummy = new AMessage(kWhatOutputBufferDrained, mCodec);
6513                    mCodec->sendFormatChange(dummy);
6514                }
6515
6516                ALOGV("[%s] Output port now reenabled.", mCodec->mComponentName.c_str());
6517
6518                if (mCodec->mExecutingState->active()) {
6519                    mCodec->mExecutingState->submitOutputBuffers();
6520                }
6521
6522                mCodec->changeState(mCodec->mExecutingState);
6523
6524                return true;
6525            }
6526
6527            return false;
6528        }
6529
6530        default:
6531            return false;
6532    }
6533}
6534
6535////////////////////////////////////////////////////////////////////////////////
6536
6537ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
6538    : BaseState(codec),
6539      mComponentNowIdle(false) {
6540}
6541
6542bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
6543    bool handled = false;
6544
6545    switch (msg->what()) {
6546        case kWhatFlush:
6547        {
6548            // Don't send me a flush request if you previously wanted me
6549            // to shutdown.
6550            ALOGW("Ignoring flush request in ExecutingToIdleState");
6551            break;
6552        }
6553
6554        case kWhatShutdown:
6555        {
6556            // We're already doing that...
6557
6558            handled = true;
6559            break;
6560        }
6561
6562        default:
6563            handled = BaseState::onMessageReceived(msg);
6564            break;
6565    }
6566
6567    return handled;
6568}
6569
6570void ACodec::ExecutingToIdleState::stateEntered() {
6571    ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
6572
6573    mComponentNowIdle = false;
6574    mCodec->mSentFormat = false;
6575}
6576
6577bool ACodec::ExecutingToIdleState::onOMXEvent(
6578        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6579    switch (event) {
6580        case OMX_EventCmdComplete:
6581        {
6582            if (data1 != (OMX_U32)OMX_CommandStateSet
6583                    || data2 != (OMX_U32)OMX_StateIdle) {
6584                ALOGE("Unexpected command completion in ExecutingToIdleState: %s(%u) %s(%u)",
6585                        asString((OMX_COMMANDTYPE)data1), data1,
6586                        asString((OMX_STATETYPE)data2), data2);
6587                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6588                return true;
6589            }
6590
6591            mComponentNowIdle = true;
6592
6593            changeStateIfWeOwnAllBuffers();
6594
6595            return true;
6596        }
6597
6598        case OMX_EventPortSettingsChanged:
6599        case OMX_EventBufferFlag:
6600        {
6601            // We're shutting down and don't care about this anymore.
6602            return true;
6603        }
6604
6605        default:
6606            return BaseState::onOMXEvent(event, data1, data2);
6607    }
6608}
6609
6610void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
6611    if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
6612        status_t err = mCodec->mOMX->sendCommand(
6613                mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded);
6614        if (err == OK) {
6615            err = mCodec->freeBuffersOnPort(kPortIndexInput);
6616            status_t err2 = mCodec->freeBuffersOnPort(kPortIndexOutput);
6617            if (err == OK) {
6618                err = err2;
6619            }
6620        }
6621
6622        if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown)
6623                && mCodec->mNativeWindow != NULL) {
6624            // We push enough 1x1 blank buffers to ensure that one of
6625            // them has made it to the display.  This allows the OMX
6626            // component teardown to zero out any protected buffers
6627            // without the risk of scanning out one of those buffers.
6628            pushBlankBuffersToNativeWindow(mCodec->mNativeWindow.get());
6629        }
6630
6631        if (err != OK) {
6632            mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6633            return;
6634        }
6635
6636        mCodec->changeState(mCodec->mIdleToLoadedState);
6637    }
6638}
6639
6640void ACodec::ExecutingToIdleState::onInputBufferFilled(
6641        const sp<AMessage> &msg) {
6642    BaseState::onInputBufferFilled(msg);
6643
6644    changeStateIfWeOwnAllBuffers();
6645}
6646
6647void ACodec::ExecutingToIdleState::onOutputBufferDrained(
6648        const sp<AMessage> &msg) {
6649    BaseState::onOutputBufferDrained(msg);
6650
6651    changeStateIfWeOwnAllBuffers();
6652}
6653
6654////////////////////////////////////////////////////////////////////////////////
6655
6656ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
6657    : BaseState(codec) {
6658}
6659
6660bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
6661    bool handled = false;
6662
6663    switch (msg->what()) {
6664        case kWhatShutdown:
6665        {
6666            // We're already doing that...
6667
6668            handled = true;
6669            break;
6670        }
6671
6672        case kWhatFlush:
6673        {
6674            // Don't send me a flush request if you previously wanted me
6675            // to shutdown.
6676            ALOGE("Got flush request in IdleToLoadedState");
6677            break;
6678        }
6679
6680        default:
6681            handled = BaseState::onMessageReceived(msg);
6682            break;
6683    }
6684
6685    return handled;
6686}
6687
6688void ACodec::IdleToLoadedState::stateEntered() {
6689    ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
6690}
6691
6692bool ACodec::IdleToLoadedState::onOMXEvent(
6693        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6694    switch (event) {
6695        case OMX_EventCmdComplete:
6696        {
6697            if (data1 != (OMX_U32)OMX_CommandStateSet
6698                    || data2 != (OMX_U32)OMX_StateLoaded) {
6699                ALOGE("Unexpected command completion in IdleToLoadedState: %s(%u) %s(%u)",
6700                        asString((OMX_COMMANDTYPE)data1), data1,
6701                        asString((OMX_STATETYPE)data2), data2);
6702                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6703                return true;
6704            }
6705
6706            mCodec->changeState(mCodec->mLoadedState);
6707
6708            return true;
6709        }
6710
6711        default:
6712            return BaseState::onOMXEvent(event, data1, data2);
6713    }
6714}
6715
6716////////////////////////////////////////////////////////////////////////////////
6717
6718ACodec::FlushingState::FlushingState(ACodec *codec)
6719    : BaseState(codec) {
6720}
6721
6722void ACodec::FlushingState::stateEntered() {
6723    ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
6724
6725    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
6726}
6727
6728bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
6729    bool handled = false;
6730
6731    switch (msg->what()) {
6732        case kWhatShutdown:
6733        {
6734            mCodec->deferMessage(msg);
6735            break;
6736        }
6737
6738        case kWhatFlush:
6739        {
6740            // We're already doing this right now.
6741            handled = true;
6742            break;
6743        }
6744
6745        default:
6746            handled = BaseState::onMessageReceived(msg);
6747            break;
6748    }
6749
6750    return handled;
6751}
6752
6753bool ACodec::FlushingState::onOMXEvent(
6754        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6755    ALOGV("[%s] FlushingState onOMXEvent(%u,%d)",
6756            mCodec->mComponentName.c_str(), event, (OMX_S32)data1);
6757
6758    switch (event) {
6759        case OMX_EventCmdComplete:
6760        {
6761            if (data1 != (OMX_U32)OMX_CommandFlush) {
6762                ALOGE("unexpected EventCmdComplete %s(%d) data2:%d in FlushingState",
6763                        asString((OMX_COMMANDTYPE)data1), data1, data2);
6764                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6765                return true;
6766            }
6767
6768            if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
6769                if (mFlushComplete[data2]) {
6770                    ALOGW("Flush already completed for %s port",
6771                            data2 == kPortIndexInput ? "input" : "output");
6772                    return true;
6773                }
6774                mFlushComplete[data2] = true;
6775
6776                if (mFlushComplete[kPortIndexInput] && mFlushComplete[kPortIndexOutput]) {
6777                    changeStateIfWeOwnAllBuffers();
6778                }
6779            } else if (data2 == OMX_ALL) {
6780                if (!mFlushComplete[kPortIndexInput] || !mFlushComplete[kPortIndexOutput]) {
6781                    ALOGW("received flush complete event for OMX_ALL before ports have been"
6782                            "flushed (%d/%d)",
6783                            mFlushComplete[kPortIndexInput], mFlushComplete[kPortIndexOutput]);
6784                    return false;
6785                }
6786
6787                changeStateIfWeOwnAllBuffers();
6788            } else {
6789                ALOGW("data2 not OMX_ALL but %u in EventCmdComplete CommandFlush", data2);
6790            }
6791
6792            return true;
6793        }
6794
6795        case OMX_EventPortSettingsChanged:
6796        {
6797            sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec);
6798            msg->setInt32("type", omx_message::EVENT);
6799            msg->setInt32("node", mCodec->mNode);
6800            msg->setInt32("event", event);
6801            msg->setInt32("data1", data1);
6802            msg->setInt32("data2", data2);
6803
6804            ALOGV("[%s] Deferring OMX_EventPortSettingsChanged",
6805                 mCodec->mComponentName.c_str());
6806
6807            mCodec->deferMessage(msg);
6808
6809            return true;
6810        }
6811
6812        default:
6813            return BaseState::onOMXEvent(event, data1, data2);
6814    }
6815
6816    return true;
6817}
6818
6819void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
6820    BaseState::onOutputBufferDrained(msg);
6821
6822    changeStateIfWeOwnAllBuffers();
6823}
6824
6825void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
6826    BaseState::onInputBufferFilled(msg);
6827
6828    changeStateIfWeOwnAllBuffers();
6829}
6830
6831void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
6832    if (mFlushComplete[kPortIndexInput]
6833            && mFlushComplete[kPortIndexOutput]
6834            && mCodec->allYourBuffersAreBelongToUs()) {
6835        // We now own all buffers except possibly those still queued with
6836        // the native window for rendering. Let's get those back as well.
6837        mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs();
6838
6839        mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC));
6840
6841        sp<AMessage> notify = mCodec->mNotify->dup();
6842        notify->setInt32("what", CodecBase::kWhatFlushCompleted);
6843        notify->post();
6844
6845        mCodec->mPortEOS[kPortIndexInput] =
6846            mCodec->mPortEOS[kPortIndexOutput] = false;
6847
6848        mCodec->mInputEOSResult = OK;
6849
6850        if (mCodec->mSkipCutBuffer != NULL) {
6851            mCodec->mSkipCutBuffer->clear();
6852        }
6853
6854        mCodec->changeState(mCodec->mExecutingState);
6855    }
6856}
6857
6858}  // namespace android
6859