ACodec.cpp revision b0a4b9e917bd26bf366fb20c48315f51285c18f9
14f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber/*
24f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber * Copyright (C) 2010 The Android Open Source Project
34f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber *
44f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
54f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber * you may not use this file except in compliance with the License.
64f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber * You may obtain a copy of the License at
74f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber *
84f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
94f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber *
104f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber * Unless required by applicable law or agreed to in writing, software
114f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
124f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber * See the License for the specific language governing permissions and
144f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber * limitations under the License.
154f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber */
164f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
174f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber//#define LOG_NDEBUG 0
184f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber#define LOG_TAG "ACodec"
194f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
204f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber#ifdef __LP64__
214f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber#define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
224f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber#endif
234f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
244f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber#include <inttypes.h>
254f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber#include <utils/Trace.h>
264f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
274f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber#include <gui/Surface.h>
284f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
294f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber#include <media/stagefright/ACodec.h>
304f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
314f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber#include <binder/MemoryDealer.h>
324f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
334f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber#include <media/stagefright/foundation/hexdump.h>
344f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
354f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber#include <media/stagefright/foundation/ADebug.h>
364f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber#include <media/stagefright/foundation/AMessage.h>
374f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber#include <media/stagefright/foundation/AUtils.h>
384f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
394f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber#include <media/stagefright/BufferProducerWrapper.h>
404f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber#include <media/stagefright/MediaCodec.h>
414f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber#include <media/stagefright/MediaCodecList.h>
424f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber#include <media/stagefright/MediaDefs.h>
434f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber#include <media/stagefright/OMXClient.h>
444f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber#include <media/stagefright/PersistentSurface.h>
454f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber#include <media/stagefright/SurfaceUtils.h>
464f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber#include <media/hardware/HardwareAPI.h>
474f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
484f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber#include <OMX_AudioExt.h>
494f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber#include <OMX_VideoExt.h>
504f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber#include <OMX_Component.h>
514f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber#include <OMX_IndexExt.h>
524f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber#include <OMX_AsString.h>
534f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
544f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber#include "include/avc_utils.h"
554f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber#include "omx/OMXUtils.h"
564f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
574f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Hubernamespace android {
584f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
594f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberenum {
604f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    kMaxIndicesToCheck = 32, // used when enumerating supported formats and profiles
614f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber};
624f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
634f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber// OMX errors are directly mapped into status_t range if
644f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber// there is no corresponding MediaError status code.
654f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber// Use the statusFromOMXError(int32_t omxError) function.
664f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber//
674f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber// Currently this is a direct map.
684f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber// See frameworks/native/include/media/openmax/OMX_Core.h
694f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber//
704f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber// Vendor OMX errors     from 0x90000000 - 0x9000FFFF
714f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber// Extension OMX errors  from 0x8F000000 - 0x90000000
724f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber// Standard OMX errors   from 0x80001000 - 0x80001024 (0x80001024 current)
734f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber//
744f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
754f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber// returns true if err is a recognized OMX error code.
764f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber// as OMX error is OMX_S32, this is an int32_t type
774f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberstatic inline bool isOMXError(int32_t err) {
784f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    return (ERROR_CODEC_MIN <= err && err <= ERROR_CODEC_MAX);
794f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber}
804f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
814f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber// converts an OMX error to a status_t
824f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberstatic inline status_t statusFromOMXError(int32_t omxError) {
834f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    switch (omxError) {
844f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    case OMX_ErrorInvalidComponentName:
854f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    case OMX_ErrorComponentNotFound:
864f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        return NAME_NOT_FOUND; // can trigger illegal argument error for provided names.
874f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    default:
884f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        return isOMXError(omxError) ? omxError : 0; // no translation required
894f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
904f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber}
914f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
924f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber// checks and converts status_t to a non-side-effect status_t
934f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberstatic inline status_t makeNoSideEffectStatus(status_t err) {
944f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    switch (err) {
954f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // the following errors have side effects and may come
964f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // from other code modules. Remap for safety reasons.
974f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    case INVALID_OPERATION:
984f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    case DEAD_OBJECT:
994f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        return UNKNOWN_ERROR;
1004f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    default:
1014f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        return err;
1024f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
1034f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber}
1044f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
1054f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberstruct MessageList : public RefBase {
1064f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    MessageList() {
1074f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
1084f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual ~MessageList() {
1094f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
1104f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    std::list<sp<AMessage> > &getList() { return mList; }
1114f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberprivate:
1124f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    std::list<sp<AMessage> > mList;
1134f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
1144f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(MessageList);
1154f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber};
1164f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
1174f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberstruct CodecObserver : public BnOMXObserver {
1184f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    CodecObserver() {}
1194f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
1204f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    void setNotificationMessage(const sp<AMessage> &msg) {
1214f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        mNotify = msg;
1224f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
1234f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
1244f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // from IOMXObserver
1254f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual void onMessages(const std::list<omx_message> &messages) {
1264f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        if (messages.empty()) {
1274f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            return;
1284f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        }
1294f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
1304f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        sp<AMessage> notify = mNotify->dup();
1314f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        bool first = true;
1324f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        sp<MessageList> msgList = new MessageList();
1334f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        for (std::list<omx_message>::const_iterator it = messages.cbegin();
1344f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber              it != messages.cend(); ++it) {
1354f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            const omx_message &omx_msg = *it;
1364f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            if (first) {
1374f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                notify->setInt32("node", omx_msg.node);
1384f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                first = false;
1394f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            }
1404f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
1414f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            sp<AMessage> msg = new AMessage;
1424f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            msg->setInt32("type", omx_msg.type);
1434f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            switch (omx_msg.type) {
1444f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                case omx_message::EVENT:
1454f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                {
1464f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    msg->setInt32("event", omx_msg.u.event_data.event);
1474f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    msg->setInt32("data1", omx_msg.u.event_data.data1);
1484f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    msg->setInt32("data2", omx_msg.u.event_data.data2);
1494f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    break;
1504f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                }
1514f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
1524f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                case omx_message::EMPTY_BUFFER_DONE:
1534f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                {
1544f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    msg->setInt32("buffer", omx_msg.u.buffer_data.buffer);
1554f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    msg->setInt32("fence_fd", omx_msg.fenceFd);
1564f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    break;
1574f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                }
1584f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
1594f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                case omx_message::FILL_BUFFER_DONE:
1604f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                {
1614f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    msg->setInt32(
1624f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                            "buffer", omx_msg.u.extended_buffer_data.buffer);
1634f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    msg->setInt32(
1644f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                            "range_offset",
1654f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                            omx_msg.u.extended_buffer_data.range_offset);
1664f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    msg->setInt32(
1674f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                            "range_length",
1684f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                            omx_msg.u.extended_buffer_data.range_length);
1694f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    msg->setInt32(
1704f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                            "flags",
1714f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                            omx_msg.u.extended_buffer_data.flags);
1724f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    msg->setInt64(
1734f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                            "timestamp",
1744f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                            omx_msg.u.extended_buffer_data.timestamp);
1754f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    msg->setInt32(
1764f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                            "fence_fd", omx_msg.fenceFd);
1774f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    break;
1784f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                }
1794f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
1804f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                case omx_message::FRAME_RENDERED:
1814f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                {
1824f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    msg->setInt64(
1834f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                            "media_time_us", omx_msg.u.render_data.timestamp);
1844f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    msg->setInt64(
1854f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                            "system_nano", omx_msg.u.render_data.nanoTime);
1864f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    break;
1874f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                }
1884f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
1894f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                default:
1904f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    ALOGE("Unrecognized message type: %d", omx_msg.type);
1914f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    break;
1924f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            }
1934f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            msgList->getList().push_back(msg);
1944f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        }
1954f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        notify->setObject("messages", msgList);
1964f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        notify->post();
1974f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
1984f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
1994f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberprotected:
2004f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual ~CodecObserver() {}
2014f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2024f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberprivate:
2034f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    sp<AMessage> mNotify;
2044f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2054f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(CodecObserver);
2064f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber};
2074f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2084f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber////////////////////////////////////////////////////////////////////////////////
2094f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2104f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberstruct ACodec::BaseState : public AState {
2114f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    BaseState(ACodec *codec, const sp<AState> &parentState = NULL);
2124f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2134f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberprotected:
2144f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    enum PortMode {
2154f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        KEEP_BUFFERS,
2164f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        RESUBMIT_BUFFERS,
2174f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        FREE_BUFFERS,
2184f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    };
2194f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2204f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    ACodec *mCodec;
2214f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2224f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual PortMode getPortMode(OMX_U32 portIndex);
2234f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2244f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual bool onMessageReceived(const sp<AMessage> &msg);
2254f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2264f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
2274f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2284f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
2294f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual void onInputBufferFilled(const sp<AMessage> &msg);
2304f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2314f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    void postFillThisBuffer(BufferInfo *info);
2324f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2334f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberprivate:
2344f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // Handles an OMX message. Returns true iff message was handled.
2354f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    bool onOMXMessage(const sp<AMessage> &msg);
2364f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2374f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // Handles a list of messages. Returns true iff messages were handled.
2384f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    bool onOMXMessageList(const sp<AMessage> &msg);
2394f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2404f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // returns true iff this message is for this component and the component is alive
2414f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    bool checkOMXMessage(const sp<AMessage> &msg);
2424f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2434f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID, int fenceFd);
2444f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2454f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    bool onOMXFillBufferDone(
2464f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            IOMX::buffer_id bufferID,
2474f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            size_t rangeOffset, size_t rangeLength,
2484f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            OMX_U32 flags,
2494f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            int64_t timeUs,
2504f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            int fenceFd);
2514f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2524f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual bool onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano);
2534f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2544f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    void getMoreInputDataIfPossible();
2554f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2564f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(BaseState);
2574f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber};
2584f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2594f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber////////////////////////////////////////////////////////////////////////////////
2604f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2614f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberstruct ACodec::DeathNotifier : public IBinder::DeathRecipient {
2624f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    DeathNotifier(const sp<AMessage> &notify)
2634f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        : mNotify(notify) {
2644f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
2654f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2664f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual void binderDied(const wp<IBinder> &) {
2674f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        mNotify->post();
2684f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
2694f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2704f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberprotected:
2714f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual ~DeathNotifier() {}
2724f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2734f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberprivate:
2744f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    sp<AMessage> mNotify;
2754f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2764f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(DeathNotifier);
2774f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber};
2784f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2794f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberstruct ACodec::UninitializedState : public ACodec::BaseState {
2804f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    UninitializedState(ACodec *codec);
2814f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2824f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberprotected:
2834f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual bool onMessageReceived(const sp<AMessage> &msg);
2844f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual void stateEntered();
2854f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2864f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberprivate:
2874f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    void onSetup(const sp<AMessage> &msg);
2884f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    bool onAllocateComponent(const sp<AMessage> &msg);
2894f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2904f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    sp<DeathNotifier> mDeathNotifier;
2914f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2924f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(UninitializedState);
2934f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber};
2944f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2954f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber////////////////////////////////////////////////////////////////////////////////
2964f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
2974f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberstruct ACodec::LoadedState : public ACodec::BaseState {
2984f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    LoadedState(ACodec *codec);
2994f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
3004f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberprotected:
3014f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual bool onMessageReceived(const sp<AMessage> &msg);
3024f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual void stateEntered();
3034f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
3044f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberprivate:
3054f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    friend struct ACodec::UninitializedState;
3064f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
3074f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    bool onConfigureComponent(const sp<AMessage> &msg);
3084f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    void onCreateInputSurface(const sp<AMessage> &msg);
3094f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    void onSetInputSurface(const sp<AMessage> &msg);
3104f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    void onStart();
3114f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    void onShutdown(bool keepComponentAllocated);
3124f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
3134f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    status_t setupInputSurface();
3144f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
3154f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(LoadedState);
3164f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber};
3174f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
3184f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber////////////////////////////////////////////////////////////////////////////////
3194f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
3204f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberstruct ACodec::LoadedToIdleState : public ACodec::BaseState {
3214f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    LoadedToIdleState(ACodec *codec);
3224f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
3234f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberprotected:
3244f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual bool onMessageReceived(const sp<AMessage> &msg);
3254f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
3264f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual void stateEntered();
3274f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
3284f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberprivate:
3294f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    status_t allocateBuffers();
3304f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
3314f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState);
3324f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber};
3334f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
3344f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber////////////////////////////////////////////////////////////////////////////////
3354f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
3364f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberstruct ACodec::IdleToExecutingState : public ACodec::BaseState {
3374f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    IdleToExecutingState(ACodec *codec);
3384f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
3394f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberprotected:
3404f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual bool onMessageReceived(const sp<AMessage> &msg);
3414f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
3424f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual void stateEntered();
3434f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
3444f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberprivate:
3454f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState);
3464f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber};
3474f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
3484f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber////////////////////////////////////////////////////////////////////////////////
3494f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
3504f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberstruct ACodec::ExecutingState : public ACodec::BaseState {
3514f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    ExecutingState(ACodec *codec);
3524f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
3534f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    void submitRegularOutputBuffers();
3544f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    void submitOutputMetaBuffers();
3554f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    void submitOutputBuffers();
3564f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
3574f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // Submit output buffers to the decoder, submit input buffers to client
3584f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // to fill with data.
3594f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    void resume();
3604f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
3614f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // Returns true iff input and output buffers are in play.
3624f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    bool active() const { return mActive; }
3634f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
3644f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberprotected:
3654f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual PortMode getPortMode(OMX_U32 portIndex);
3664f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual bool onMessageReceived(const sp<AMessage> &msg);
3674f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual void stateEntered();
3684f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
3694f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
3704f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual bool onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano);
3714f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
3724f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberprivate:
3734f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    bool mActive;
3744f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
3754f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(ExecutingState);
3764f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber};
3774f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
3784f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber////////////////////////////////////////////////////////////////////////////////
3794f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
3804f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberstruct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState {
3814f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    OutputPortSettingsChangedState(ACodec *codec);
3824f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
3834f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberprotected:
3844f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual PortMode getPortMode(OMX_U32 portIndex);
3854f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual bool onMessageReceived(const sp<AMessage> &msg);
3864f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual void stateEntered();
3874f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
3884f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
3894f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual bool onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano);
3904f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
3914f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberprivate:
3924f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState);
3934f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber};
3944f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
3954f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber////////////////////////////////////////////////////////////////////////////////
3964f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
3974f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberstruct ACodec::ExecutingToIdleState : public ACodec::BaseState {
3984f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    ExecutingToIdleState(ACodec *codec);
3994f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
4004f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberprotected:
4014f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual bool onMessageReceived(const sp<AMessage> &msg);
4024f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual void stateEntered();
4034f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
4044f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
4054f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
4064f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
4074f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual void onInputBufferFilled(const sp<AMessage> &msg);
4084f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
4094f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberprivate:
4104f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    void changeStateIfWeOwnAllBuffers();
4114f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
4124f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    bool mComponentNowIdle;
4134f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
4144f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState);
4154f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber};
4164f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
4174f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber////////////////////////////////////////////////////////////////////////////////
4184f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
4194f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberstruct ACodec::IdleToLoadedState : public ACodec::BaseState {
4204f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    IdleToLoadedState(ACodec *codec);
4214f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
4224f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberprotected:
4234f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual bool onMessageReceived(const sp<AMessage> &msg);
4244f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual void stateEntered();
4254f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
4264f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
4274f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
4284f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberprivate:
4294f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState);
4304f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber};
4314f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
4324f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber////////////////////////////////////////////////////////////////////////////////
4334f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
4344f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberstruct ACodec::FlushingState : public ACodec::BaseState {
4354f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    FlushingState(ACodec *codec);
4364f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
4374f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberprotected:
4384f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual bool onMessageReceived(const sp<AMessage> &msg);
4394f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual void stateEntered();
4404f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
4414f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
4424f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
4434f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
4444f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    virtual void onInputBufferFilled(const sp<AMessage> &msg);
4454f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
4464f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberprivate:
4474f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    bool mFlushComplete[2];
4484f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
4494f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    void changeStateIfWeOwnAllBuffers();
4504f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
4514f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(FlushingState);
4524f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber};
4534f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
4544f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber////////////////////////////////////////////////////////////////////////////////
4554f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
4564f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Hubervoid ACodec::BufferInfo::setWriteFence(int fenceFd, const char *dbg) {
4574f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    if (mFenceFd >= 0) {
4584f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        ALOGW("OVERWRITE OF %s fence %d by write fence %d in %s",
4594f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                mIsReadFence ? "read" : "write", mFenceFd, fenceFd, dbg);
4604f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
4614f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    mFenceFd = fenceFd;
4624f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    mIsReadFence = false;
4634f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber}
4644f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
4654f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Hubervoid ACodec::BufferInfo::setReadFence(int fenceFd, const char *dbg) {
4664f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    if (mFenceFd >= 0) {
4674f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        ALOGW("OVERWRITE OF %s fence %d by read fence %d in %s",
4684f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                mIsReadFence ? "read" : "write", mFenceFd, fenceFd, dbg);
4694f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
4704f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    mFenceFd = fenceFd;
4714f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    mIsReadFence = true;
4724f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber}
4734f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
4744f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Hubervoid ACodec::BufferInfo::checkWriteFence(const char *dbg) {
4754f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    if (mFenceFd >= 0 && mIsReadFence) {
4764f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        ALOGD("REUSING read fence %d as write fence in %s", mFenceFd, dbg);
4774f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
4784f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber}
4794f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
4802d0ac425564ff9882ebaac5267d1a04d4af67d00Bernhard Rosenkränzervoid ACodec::BufferInfo::checkReadFence(const char *dbg) {
4812d0ac425564ff9882ebaac5267d1a04d4af67d00Bernhard Rosenkränzer    if (mFenceFd >= 0 && !mIsReadFence) {
4822d0ac425564ff9882ebaac5267d1a04d4af67d00Bernhard Rosenkränzer        ALOGD("REUSING write fence %d as read fence in %s", mFenceFd, dbg);
4834f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
4844f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber}
4854f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
4864f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber////////////////////////////////////////////////////////////////////////////////
4874f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
4884f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas HuberACodec::ACodec()
4894f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    : mQuirks(0),
4904f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber      mNode(0),
4914f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber      mNativeWindowUsageBits(0),
4924f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber      mIsVideo(false),
4934f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber      mIsEncoder(false),
4944f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber      mFatalError(false),
4954f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber      mShutdownInProgress(false),
4964f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber      mExplicitShutdown(false),
4974f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber      mEncoderDelay(0),
4984f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber      mEncoderPadding(0),
4994f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber      mRotationDegrees(0),
5004f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber      mChannelMaskPresent(false),
5014f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber      mChannelMask(0),
5024f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber      mDequeueCounter(0),
5034f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber      mInputMetadataType(kMetadataBufferTypeInvalid),
5044f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber      mOutputMetadataType(kMetadataBufferTypeInvalid),
5054f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber      mLegacyAdaptiveExperiment(false),
5064f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber      mMetadataBuffersToSubmit(0),
5074f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber      mRepeatFrameDelayUs(-1ll),
5084f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber      mMaxPtsGapUs(-1ll),
5094f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber      mMaxFps(-1),
5104f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber      mTimePerFrameUs(-1ll),
5114f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber      mTimePerCaptureUs(-1ll),
5124f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber      mCreateInputBuffersSuspended(false),
5134f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber      mTunneled(false),
5144f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber      mDescribeColorAspectsIndex((OMX_INDEXTYPE)0) {
5154f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    mUninitializedState = new UninitializedState(this);
5164f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    mLoadedState = new LoadedState(this);
5174f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    mLoadedToIdleState = new LoadedToIdleState(this);
5184f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    mIdleToExecutingState = new IdleToExecutingState(this);
5194f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    mExecutingState = new ExecutingState(this);
5204f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
5214f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    mOutputPortSettingsChangedState =
5224f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        new OutputPortSettingsChangedState(this);
5234f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
5244f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    mExecutingToIdleState = new ExecutingToIdleState(this);
5254f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    mIdleToLoadedState = new IdleToLoadedState(this);
5264f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    mFlushingState = new FlushingState(this);
5274f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
5284f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false;
5294f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    mInputEOSResult = OK;
5304f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
5314f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    changeState(mUninitializedState);
5324f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber}
5334f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
5344f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas HuberACodec::~ACodec() {
5354f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber}
5364f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
5374f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Hubervoid ACodec::setNotificationMessage(const sp<AMessage> &msg) {
5384f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    mNotify = msg;
5394f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber}
5404f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
5414f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Hubervoid ACodec::initiateSetup(const sp<AMessage> &msg) {
5424f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    msg->setWhat(kWhatSetup);
5434f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    msg->setTarget(this);
5444f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    msg->post();
5454f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber}
5464f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
5474f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Hubervoid ACodec::signalSetParameters(const sp<AMessage> &params) {
5484f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
5494f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    msg->setMessage("params", params);
5504f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    msg->post();
5514f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber}
5524f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
5534f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Hubervoid ACodec::initiateAllocateComponent(const sp<AMessage> &msg) {
5544f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    msg->setWhat(kWhatAllocateComponent);
5554f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    msg->setTarget(this);
5564f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    msg->post();
5574f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber}
5584f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
5594f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Hubervoid ACodec::initiateConfigureComponent(const sp<AMessage> &msg) {
5604f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    msg->setWhat(kWhatConfigureComponent);
5614f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    msg->setTarget(this);
5624f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    msg->post();
5634f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber}
5644f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
5654f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberstatus_t ACodec::setSurface(const sp<Surface> &surface) {
5664f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    sp<AMessage> msg = new AMessage(kWhatSetSurface, this);
5674f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    msg->setObject("surface", surface);
5684f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
5694f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    sp<AMessage> response;
5704f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    status_t err = msg->postAndAwaitResponse(&response);
5714f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
5724f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    if (err == OK) {
5734f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        (void)response->findInt32("err", &err);
5744f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
5754f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    return err;
5764f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber}
5774f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
5784f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Hubervoid ACodec::initiateCreateInputSurface() {
5794f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    (new AMessage(kWhatCreateInputSurface, this))->post();
5804f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber}
5814f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
5824f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Hubervoid ACodec::initiateSetInputSurface(
5834f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        const sp<PersistentSurface> &surface) {
5844f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    sp<AMessage> msg = new AMessage(kWhatSetInputSurface, this);
5854f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    msg->setObject("input-surface", surface);
5864f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    msg->post();
5874f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber}
5884f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
5894f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Hubervoid ACodec::signalEndOfInputStream() {
5904f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    (new AMessage(kWhatSignalEndOfInputStream, this))->post();
5914f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber}
5924f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
5934f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Hubervoid ACodec::initiateStart() {
5944f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    (new AMessage(kWhatStart, this))->post();
5954f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber}
5964f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
5974f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Hubervoid ACodec::signalFlush() {
5984f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    ALOGV("[%s] signalFlush", mComponentName.c_str());
5994f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    (new AMessage(kWhatFlush, this))->post();
6004f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber}
6014f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
6024f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Hubervoid ACodec::signalResume() {
6034f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    (new AMessage(kWhatResume, this))->post();
6044f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber}
6054f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
6064f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Hubervoid ACodec::initiateShutdown(bool keepComponentAllocated) {
6074f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    sp<AMessage> msg = new AMessage(kWhatShutdown, this);
6084f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    msg->setInt32("keepComponentAllocated", keepComponentAllocated);
6094f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    msg->post();
6104f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    if (!keepComponentAllocated) {
6114f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        // ensure shutdown completes in 3 seconds
6124f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        (new AMessage(kWhatReleaseCodecInstance, this))->post(3000000);
6134f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
6144f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber}
6154f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
6164f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Hubervoid ACodec::signalRequestIDRFrame() {
6174f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    (new AMessage(kWhatRequestIDRFrame, this))->post();
6184f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber}
6194f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
6204f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber// *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
6214f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber// Some codecs may return input buffers before having them processed.
6224f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber// This causes a halt if we already signaled an EOS on the input
6234f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber// port.  For now keep submitting an output buffer if there was an
6244f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber// EOS on the input port, but not yet on the output port.
6254f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Hubervoid ACodec::signalSubmitOutputMetadataBufferIfEOS_workaround() {
6264f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    if (mPortEOS[kPortIndexInput] && !mPortEOS[kPortIndexOutput] &&
6274f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            mMetadataBuffersToSubmit > 0) {
6284f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        (new AMessage(kWhatSubmitOutputMetadataBufferIfEOS, this))->post();
6294f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
6304f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber}
6314f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
6324f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberstatus_t ACodec::handleSetSurface(const sp<Surface> &surface) {
6334f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // allow keeping unset surface
6344f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    if (surface == NULL) {
6354f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        if (mNativeWindow != NULL) {
6364f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            ALOGW("cannot unset a surface");
6374f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            return INVALID_OPERATION;
6384f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        }
6394f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        return OK;
6404f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
6414f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
6424f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // cannot switch from bytebuffers to surface
6434f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    if (mNativeWindow == NULL) {
6444f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        ALOGW("component was not configured with a surface");
6454f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        return INVALID_OPERATION;
6464f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
6474f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
6484f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    ANativeWindow *nativeWindow = surface.get();
6494f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // if we have not yet started the codec, we can simply set the native window
6504f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    if (mBuffers[kPortIndexInput].size() == 0) {
6514f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        mNativeWindow = surface;
6524f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        return OK;
6534f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
6544f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
6554f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // we do not support changing a tunneled surface after start
6564f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    if (mTunneled) {
6574f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        ALOGW("cannot change tunneled surface");
6584f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        return INVALID_OPERATION;
6594f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
6604f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
6614f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    int usageBits = 0;
6624f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    status_t err = setupNativeWindowSizeFormatAndUsage(nativeWindow, &usageBits);
6634f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    if (err != OK) {
6644f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        return err;
6654f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
6664f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
6674f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    int ignoredFlags = kVideoGrallocUsage;
6684f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // New output surface is not allowed to add new usage flag except ignored ones.
6694f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    if ((usageBits & ~(mNativeWindowUsageBits | ignoredFlags)) != 0) {
6704f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        ALOGW("cannot change usage from %#x to %#x", mNativeWindowUsageBits, usageBits);
6714f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        return BAD_VALUE;
6724f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
6734f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
6744f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // get min undequeued count. We cannot switch to a surface that has a higher
6754f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // undequeued count than we allocated.
6764f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    int minUndequeuedBuffers = 0;
6774f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    err = nativeWindow->query(
6784f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            nativeWindow, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
6794f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            &minUndequeuedBuffers);
6804f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    if (err != 0) {
6814f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
6824f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                strerror(-err), -err);
6834f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        return err;
6844f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
6854f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    if (minUndequeuedBuffers > (int)mNumUndequeuedBuffers) {
6864f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        ALOGE("new surface holds onto more buffers (%d) than planned for (%zu)",
6874f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                minUndequeuedBuffers, mNumUndequeuedBuffers);
6884f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        return BAD_VALUE;
6894f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
6904f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
6914f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // we cannot change the number of output buffers while OMX is running
6924f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // set up surface to the same count
6934f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    Vector<BufferInfo> &buffers = mBuffers[kPortIndexOutput];
6944f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    ALOGV("setting up surface for %zu buffers", buffers.size());
6954f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
6964f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    err = native_window_set_buffer_count(nativeWindow, buffers.size());
6974f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    if (err != 0) {
6984f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
6994f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                -err);
7004f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        return err;
7014f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
7024f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
7034f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // need to enable allocation when attaching
7044f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    surface->getIGraphicBufferProducer()->allowAllocation(true);
7054f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
7064f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // for meta data mode, we move dequeud buffers to the new surface.
7074f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // for non-meta mode, we must move all registered buffers
7084f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    for (size_t i = 0; i < buffers.size(); ++i) {
7094f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        const BufferInfo &info = buffers[i];
7104f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        // skip undequeued buffers for meta data mode
7114f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        if (storingMetadataInDecodedBuffers()
7124f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                && !mLegacyAdaptiveExperiment
7134f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                && info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
7144f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            ALOGV("skipping buffer %p", info.mGraphicBuffer->getNativeBuffer());
7154f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            continue;
7164f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        }
7174f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        ALOGV("attaching buffer %p", info.mGraphicBuffer->getNativeBuffer());
7184f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
7194f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        err = surface->attachBuffer(info.mGraphicBuffer->getNativeBuffer());
7204f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        if (err != OK) {
7214f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            ALOGE("failed to attach buffer %p to the new surface: %s (%d)",
7224f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    info.mGraphicBuffer->getNativeBuffer(),
7234f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    strerror(-err), -err);
7244f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            return err;
7254f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        }
7264f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
7274f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
7284f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // cancel undequeued buffers to new surface
7294f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    if (!storingMetadataInDecodedBuffers() || mLegacyAdaptiveExperiment) {
7304f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        for (size_t i = 0; i < buffers.size(); ++i) {
7314f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            BufferInfo &info = buffers.editItemAt(i);
7324f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
7334f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                ALOGV("canceling buffer %p", info.mGraphicBuffer->getNativeBuffer());
7344f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                err = nativeWindow->cancelBuffer(
7354f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                        nativeWindow, info.mGraphicBuffer->getNativeBuffer(), info.mFenceFd);
7364f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                info.mFenceFd = -1;
7374f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                if (err != OK) {
7384f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    ALOGE("failed to cancel buffer %p to the new surface: %s (%d)",
7394f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                            info.mGraphicBuffer->getNativeBuffer(),
7404f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                            strerror(-err), -err);
7414f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    return err;
7424f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                }
7434f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            }
7444f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        }
7454f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        // disallow further allocation
7464f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        (void)surface->getIGraphicBufferProducer()->allowAllocation(false);
7474f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
7484f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
7494f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // push blank buffers to previous window if requested
7504f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    if (mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown) {
7514f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        pushBlankBuffersToNativeWindow(mNativeWindow.get());
7524f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
7534f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
7544f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    mNativeWindow = nativeWindow;
7554f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    mNativeWindowUsageBits = usageBits;
7564f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    return OK;
7574f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber}
7584f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
7594f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberstatus_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
7604f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
7614f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
7624f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    CHECK(mDealer[portIndex] == NULL);
7634f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    CHECK(mBuffers[portIndex].isEmpty());
7644f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
7654f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    status_t err;
7664f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
7674f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        if (storingMetadataInDecodedBuffers()) {
7684f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            err = allocateOutputMetadataBuffers();
7694f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        } else {
7704f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            err = allocateOutputBuffersFromNativeWindow();
7714f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        }
7724f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    } else {
7734f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        OMX_PARAM_PORTDEFINITIONTYPE def;
7744f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        InitOMXParams(&def);
7754f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        def.nPortIndex = portIndex;
7764f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
7774f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        err = mOMX->getParameter(
7784f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
7794f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
7804f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        if (err == OK) {
7814f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            MetadataBufferType type =
7824f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                portIndex == kPortIndexOutput ? mOutputMetadataType : mInputMetadataType;
7834f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            int32_t bufSize = def.nBufferSize;
7844f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            if (type == kMetadataBufferTypeGrallocSource) {
7854f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                bufSize = sizeof(VideoGrallocMetadata);
7864f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            } else if (type == kMetadataBufferTypeANWBuffer) {
7874f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                bufSize = sizeof(VideoNativeMetadata);
7884f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            }
7894f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
7904f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            // If using gralloc or native source input metadata buffers, allocate largest
7914f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            // metadata size as we prefer to generate native source metadata, but component
7924f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            // may require gralloc source. For camera source, allocate at least enough
7934f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            // size for native metadata buffers.
7944f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            int32_t allottedSize = bufSize;
7954f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            if (portIndex == kPortIndexInput && type >= kMetadataBufferTypeGrallocSource) {
7964f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                bufSize = max(sizeof(VideoGrallocMetadata), sizeof(VideoNativeMetadata));
7974f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            } else if (portIndex == kPortIndexInput && type == kMetadataBufferTypeCameraSource) {
7984f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                bufSize = max(bufSize, (int32_t)sizeof(VideoNativeMetadata));
7994f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            }
8004f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
8014f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            ALOGV("[%s] Allocating %u buffers of size %d/%d (from %u using %s) on %s port",
8024f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    mComponentName.c_str(),
8034f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    def.nBufferCountActual, bufSize, allottedSize, def.nBufferSize, asString(type),
8044f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    portIndex == kPortIndexInput ? "input" : "output");
8054f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
8064f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            if (bufSize == 0 || def.nBufferCountActual > SIZE_MAX / bufSize) {
8074f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                ALOGE("b/22885421");
8084f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                return NO_MEMORY;
8094f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            }
8104f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            size_t totalSize = def.nBufferCountActual * bufSize;
8114f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec");
8124f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
8134f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            for (OMX_U32 i = 0; i < def.nBufferCountActual && err == OK; ++i) {
8144f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                sp<IMemory> mem = mDealer[portIndex]->allocate(bufSize);
8154f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                if (mem == NULL || mem->pointer() == NULL) {
8164f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    return NO_MEMORY;
8174f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                }
8184f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
8194f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                BufferInfo info;
8204f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                info.mStatus = BufferInfo::OWNED_BY_US;
8214f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                info.mFenceFd = -1;
8224f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                info.mRenderInfo = NULL;
8234f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                info.mNativeHandle = NULL;
8244f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
8254f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                uint32_t requiresAllocateBufferBit =
8264f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    (portIndex == kPortIndexInput)
8274f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                        ? kRequiresAllocateBufferOnInputPorts
8284f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                        : kRequiresAllocateBufferOnOutputPorts;
8294f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
8304f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                if (portIndex == kPortIndexInput && (mFlags & kFlagIsSecure)) {
8314f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    mem.clear();
8324f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
8334f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    void *ptr = NULL;
8344f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    native_handle_t *native_handle = NULL;
8354f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    err = mOMX->allocateSecureBuffer(
8364f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                            mNode, portIndex, bufSize, &info.mBufferID,
8374f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                            &ptr, &native_handle);
8384f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
8394f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    // TRICKY: this representation is unorthodox, but ACodec requires
8404f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    // an ABuffer with a proper size to validate range offsets and lengths.
8414f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    // Since mData is never referenced for secure input, it is used to store
8424f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    // either the pointer to the secure buffer, or the opaque handle as on
8434f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    // some devices ptr is actually an opaque handle, not a pointer.
8444f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
8454f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    // TRICKY2: use native handle as the base of the ABuffer if received one,
8464f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    // because Widevine source only receives these base addresses.
8474f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    info.mData = new ABuffer(ptr != NULL ? ptr : (void *)native_handle, bufSize);
8484f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    info.mNativeHandle = NativeHandle::create(native_handle, true /* ownsHandle */);
8494f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                } else if (mQuirks & requiresAllocateBufferBit) {
8504f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    err = mOMX->allocateBufferWithBackup(
8514f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                            mNode, portIndex, mem, &info.mBufferID, allottedSize);
8524f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                } else {
8534f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    err = mOMX->useBuffer(mNode, portIndex, mem, &info.mBufferID, allottedSize);
8544f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                }
8554f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
8564f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                if (mem != NULL) {
8574f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    info.mData = new ABuffer(mem->pointer(), bufSize);
8584f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    if (type == kMetadataBufferTypeANWBuffer) {
8594f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                        ((VideoNativeMetadata *)mem->pointer())->nFenceFd = -1;
8604f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    }
8614f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                    info.mMemRef = mem;
8624f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                }
8634f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
8644f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                mBuffers[portIndex].push(info);
8654f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            }
8664f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        }
8674f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
8684f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
8694f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    if (err != OK) {
8704f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        return err;
8714f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
8724f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
8734f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    sp<AMessage> notify = mNotify->dup();
8744f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    notify->setInt32("what", CodecBase::kWhatBuffersAllocated);
8754f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
8764f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    notify->setInt32("portIndex", portIndex);
8774f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
8784f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    sp<PortDescription> desc = new PortDescription;
8794f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
8804f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
8814f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        const BufferInfo &info = mBuffers[portIndex][i];
8824f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        desc->addBuffer(info.mBufferID, info.mData, info.mNativeHandle, info.mMemRef);
8834f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
8844f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
8854f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    notify->setObject("portDesc", desc);
8864f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    notify->post();
8874f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
8884f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    return OK;
8894f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber}
8904f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
8914f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberstatus_t ACodec::setupNativeWindowSizeFormatAndUsage(
8924f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        ANativeWindow *nativeWindow /* nonnull */, int *finalUsage /* nonnull */) {
8934f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    OMX_PARAM_PORTDEFINITIONTYPE def;
8944f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    InitOMXParams(&def);
8954f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    def.nPortIndex = kPortIndexOutput;
8964f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
8974f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    status_t err = mOMX->getParameter(
8984f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
8994f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
9004f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    if (err != OK) {
9014f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        return err;
9024f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
9034f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
9044f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    OMX_U32 usage = 0;
9054f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage);
9064f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    if (err != 0) {
9074f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        ALOGW("querying usage flags from OMX IL component failed: %d", err);
9084f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        // XXX: Currently this error is logged, but not fatal.
9094f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        usage = 0;
9104f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
9114f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    int omxUsage = usage;
9124f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
9134f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    if (mFlags & kFlagIsGrallocUsageProtected) {
9144f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        usage |= GRALLOC_USAGE_PROTECTED;
9154f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
9164f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
9174f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    usage |= kVideoGrallocUsage;
9184f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    *finalUsage = usage;
9194f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
9204f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    ALOGV("gralloc usage: %#x(OMX) => %#x(ACodec)", omxUsage, usage);
9214f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    return setNativeWindowSizeFormatAndUsage(
9224f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            nativeWindow,
9234f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            def.format.video.nFrameWidth,
9244f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            def.format.video.nFrameHeight,
9254f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            def.format.video.eColorFormat,
9264f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            mRotationDegrees,
9274f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            usage);
9284f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber}
9294f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
9304f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberstatus_t ACodec::configureOutputBuffersFromNativeWindow(
9314f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        OMX_U32 *bufferCount, OMX_U32 *bufferSize,
9324f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        OMX_U32 *minUndequeuedBuffers) {
9334f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    OMX_PARAM_PORTDEFINITIONTYPE def;
9344f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    InitOMXParams(&def);
9354f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    def.nPortIndex = kPortIndexOutput;
9364f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
9374f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    status_t err = mOMX->getParameter(
9384f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
9394f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
9404f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    if (err == OK) {
9414f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        err = setupNativeWindowSizeFormatAndUsage(mNativeWindow.get(), &mNativeWindowUsageBits);
9424f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
9434f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    if (err != OK) {
9444f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        mNativeWindowUsageBits = 0;
9454f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        return err;
9464f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
9474f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
9484f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // Exits here for tunneled video playback codecs -- i.e. skips native window
9494f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // buffer allocation step as this is managed by the tunneled OMX omponent
9504f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // itself and explicitly sets def.nBufferCountActual to 0.
9514f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    if (mTunneled) {
9524f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        ALOGV("Tunneled Playback: skipping native window buffer allocation.");
9534f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        def.nBufferCountActual = 0;
9544f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        err = mOMX->setParameter(
9554f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
9564f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
9574f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        *minUndequeuedBuffers = 0;
9584f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        *bufferCount = 0;
9594f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        *bufferSize = 0;
9604f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        return err;
9614f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
9624f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
9634f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    *minUndequeuedBuffers = 0;
9644f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    err = mNativeWindow->query(
9654f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
9664f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            (int *)minUndequeuedBuffers);
9674f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
9684f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    if (err != 0) {
9694f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
9704f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                strerror(-err), -err);
9714f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        return err;
9724f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
9734f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
9744f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // FIXME: assume that surface is controlled by app (native window
9754f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // returns the number for the case when surface is not controlled by app)
9764f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // FIXME2: This means that minUndeqeueudBufs can be 1 larger than reported
9774f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // For now, try to allocate 1 more buffer, but don't fail if unsuccessful
9784f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
9794f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // Use conservative allocation while also trying to reduce starvation
9804f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    //
9814f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // 1. allocate at least nBufferCountMin + minUndequeuedBuffers - that is the
9824f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    //    minimum needed for the consumer to be able to work
9834f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // 2. try to allocate two (2) additional buffers to reduce starvation from
9844f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    //    the consumer
9854f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    //    plus an extra buffer to account for incorrect minUndequeuedBufs
9864f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    for (OMX_U32 extraBuffers = 2 + 1; /* condition inside loop */; extraBuffers--) {
9874f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        OMX_U32 newBufferCount =
9884f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            def.nBufferCountMin + *minUndequeuedBuffers + extraBuffers;
9894f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        def.nBufferCountActual = newBufferCount;
9904f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        err = mOMX->setParameter(
9914f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
9924f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
9934f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        if (err == OK) {
9944f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            *minUndequeuedBuffers += extraBuffers;
9954f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            break;
9962d0ac425564ff9882ebaac5267d1a04d4af67d00Bernhard Rosenkränzer        }
9974f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
9984f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        ALOGW("[%s] setting nBufferCountActual to %u failed: %d",
9994f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                mComponentName.c_str(), newBufferCount, err);
10004f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        /* exit condition */
10014f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        if (extraBuffers == 0) {
10024f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            return err;
10034f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        }
10044f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
10054f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
10064f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    err = native_window_set_buffer_count(
10074f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            mNativeWindow.get(), def.nBufferCountActual);
10084f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
10094f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    if (err != 0) {
10104f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
10114f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                -err);
10124f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        return err;
10134f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
10144f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
10154f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    *bufferCount = def.nBufferCountActual;
10164f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    *bufferSize =  def.nBufferSize;
10174f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    return err;
10184f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber}
10194f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
10204f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huberstatus_t ACodec::allocateOutputBuffersFromNativeWindow() {
10214f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers;
10224f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    status_t err = configureOutputBuffersFromNativeWindow(
10234f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            &bufferCount, &bufferSize, &minUndequeuedBuffers);
10244f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    if (err != 0)
10254f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        return err;
10264f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    mNumUndequeuedBuffers = minUndequeuedBuffers;
10274f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
10284f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    if (!storingMetadataInDecodedBuffers()) {
10294f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        static_cast<Surface*>(mNativeWindow.get())
10304f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber                ->getIGraphicBufferProducer()->allowAllocation(true);
10314f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    }
10324f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
10334f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    ALOGV("[%s] Allocating %u buffers from a native window of size %u on "
10344f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber         "output port",
10354f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber         mComponentName.c_str(), bufferCount, bufferSize);
10364f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
10374f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    // Dequeue buffers and send them to OMX
10384f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber    for (OMX_U32 i = 0; i < bufferCount; i++) {
10394f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        ANativeWindowBuffer *buf;
10404f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        int fenceFd;
10414f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf, &fenceFd);
10424f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        if (err != 0) {
10434f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
10444f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber            break;
10454f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber        }
10464f1efc098cb5791c3e9f483f2af84aef70d2d0a0Andreas Huber
1047        sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
1048        BufferInfo info;
1049        info.mStatus = BufferInfo::OWNED_BY_US;
1050        info.mFenceFd = fenceFd;
1051        info.mIsReadFence = false;
1052        info.mRenderInfo = NULL;
1053        info.mData = new ABuffer(NULL /* data */, bufferSize /* capacity */);
1054        info.mGraphicBuffer = graphicBuffer;
1055        mBuffers[kPortIndexOutput].push(info);
1056
1057        IOMX::buffer_id bufferId;
1058        err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer,
1059                &bufferId);
1060        if (err != 0) {
1061            ALOGE("registering GraphicBuffer %u with OMX IL component failed: "
1062                 "%d", i, err);
1063            break;
1064        }
1065
1066        mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId;
1067
1068        ALOGV("[%s] Registered graphic buffer with ID %u (pointer = %p)",
1069             mComponentName.c_str(),
1070             bufferId, graphicBuffer.get());
1071    }
1072
1073    OMX_U32 cancelStart;
1074    OMX_U32 cancelEnd;
1075
1076    if (err != 0) {
1077        // If an error occurred while dequeuing we need to cancel any buffers
1078        // that were dequeued.
1079        cancelStart = 0;
1080        cancelEnd = mBuffers[kPortIndexOutput].size();
1081    } else {
1082        // Return the required minimum undequeued buffers to the native window.
1083        cancelStart = bufferCount - minUndequeuedBuffers;
1084        cancelEnd = bufferCount;
1085    }
1086
1087    for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
1088        BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
1089        if (info->mStatus == BufferInfo::OWNED_BY_US) {
1090            status_t error = cancelBufferToNativeWindow(info);
1091            if (err == 0) {
1092                err = error;
1093            }
1094        }
1095    }
1096
1097    if (!storingMetadataInDecodedBuffers()) {
1098        static_cast<Surface*>(mNativeWindow.get())
1099                ->getIGraphicBufferProducer()->allowAllocation(false);
1100    }
1101
1102    return err;
1103}
1104
1105status_t ACodec::allocateOutputMetadataBuffers() {
1106    OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers;
1107    status_t err = configureOutputBuffersFromNativeWindow(
1108            &bufferCount, &bufferSize, &minUndequeuedBuffers);
1109    if (err != 0)
1110        return err;
1111    mNumUndequeuedBuffers = minUndequeuedBuffers;
1112
1113    ALOGV("[%s] Allocating %u meta buffers on output port",
1114         mComponentName.c_str(), bufferCount);
1115
1116    size_t bufSize = mOutputMetadataType == kMetadataBufferTypeANWBuffer ?
1117            sizeof(struct VideoNativeMetadata) : sizeof(struct VideoGrallocMetadata);
1118    size_t totalSize = bufferCount * bufSize;
1119    mDealer[kPortIndexOutput] = new MemoryDealer(totalSize, "ACodec");
1120
1121    // Dequeue buffers and send them to OMX
1122    for (OMX_U32 i = 0; i < bufferCount; i++) {
1123        BufferInfo info;
1124        info.mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
1125        info.mFenceFd = -1;
1126        info.mRenderInfo = NULL;
1127        info.mGraphicBuffer = NULL;
1128        info.mDequeuedAt = mDequeueCounter;
1129
1130        sp<IMemory> mem = mDealer[kPortIndexOutput]->allocate(bufSize);
1131        if (mem == NULL || mem->pointer() == NULL) {
1132            return NO_MEMORY;
1133        }
1134        if (mOutputMetadataType == kMetadataBufferTypeANWBuffer) {
1135            ((VideoNativeMetadata *)mem->pointer())->nFenceFd = -1;
1136        }
1137        info.mData = new ABuffer(mem->pointer(), mem->size());
1138
1139        // we use useBuffer for metadata regardless of quirks
1140        err = mOMX->useBuffer(
1141                mNode, kPortIndexOutput, mem, &info.mBufferID, mem->size());
1142        info.mMemRef = mem;
1143        mBuffers[kPortIndexOutput].push(info);
1144
1145        ALOGV("[%s] allocated meta buffer with ID %u (pointer = %p)",
1146             mComponentName.c_str(), info.mBufferID, mem->pointer());
1147    }
1148
1149    if (mLegacyAdaptiveExperiment) {
1150        // preallocate and preregister buffers
1151        static_cast<Surface *>(mNativeWindow.get())
1152                ->getIGraphicBufferProducer()->allowAllocation(true);
1153
1154        ALOGV("[%s] Allocating %u buffers from a native window of size %u on "
1155             "output port",
1156             mComponentName.c_str(), bufferCount, bufferSize);
1157
1158        // Dequeue buffers then cancel them all
1159        for (OMX_U32 i = 0; i < bufferCount; i++) {
1160            BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
1161
1162            ANativeWindowBuffer *buf;
1163            int fenceFd;
1164            err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf, &fenceFd);
1165            if (err != 0) {
1166                ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
1167                break;
1168            }
1169
1170            sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
1171            mOMX->updateGraphicBufferInMeta(
1172                    mNode, kPortIndexOutput, graphicBuffer, info->mBufferID);
1173            info->mStatus = BufferInfo::OWNED_BY_US;
1174            info->setWriteFence(fenceFd, "allocateOutputMetadataBuffers for legacy");
1175            info->mGraphicBuffer = graphicBuffer;
1176        }
1177
1178        for (OMX_U32 i = 0; i < mBuffers[kPortIndexOutput].size(); i++) {
1179            BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
1180            if (info->mStatus == BufferInfo::OWNED_BY_US) {
1181                status_t error = cancelBufferToNativeWindow(info);
1182                if (err == OK) {
1183                    err = error;
1184                }
1185            }
1186        }
1187
1188        static_cast<Surface*>(mNativeWindow.get())
1189                ->getIGraphicBufferProducer()->allowAllocation(false);
1190    }
1191
1192    mMetadataBuffersToSubmit = bufferCount - minUndequeuedBuffers;
1193    return err;
1194}
1195
1196status_t ACodec::submitOutputMetadataBuffer() {
1197    CHECK(storingMetadataInDecodedBuffers());
1198    if (mMetadataBuffersToSubmit == 0)
1199        return OK;
1200
1201    BufferInfo *info = dequeueBufferFromNativeWindow();
1202    if (info == NULL) {
1203        return ERROR_IO;
1204    }
1205
1206    ALOGV("[%s] submitting output meta buffer ID %u for graphic buffer %p",
1207          mComponentName.c_str(), info->mBufferID, info->mGraphicBuffer.get());
1208
1209    --mMetadataBuffersToSubmit;
1210    info->checkWriteFence("submitOutputMetadataBuffer");
1211    status_t err = mOMX->fillBuffer(mNode, info->mBufferID, info->mFenceFd);
1212    info->mFenceFd = -1;
1213    if (err == OK) {
1214        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
1215    }
1216
1217    return err;
1218}
1219
1220status_t ACodec::waitForFence(int fd, const char *dbg ) {
1221    status_t res = OK;
1222    if (fd >= 0) {
1223        sp<Fence> fence = new Fence(fd);
1224        res = fence->wait(IOMX::kFenceTimeoutMs);
1225        ALOGW_IF(res != OK, "FENCE TIMEOUT for %d in %s", fd, dbg);
1226    }
1227    return res;
1228}
1229
1230// static
1231const char *ACodec::_asString(BufferInfo::Status s) {
1232    switch (s) {
1233        case BufferInfo::OWNED_BY_US:            return "OUR";
1234        case BufferInfo::OWNED_BY_COMPONENT:     return "COMPONENT";
1235        case BufferInfo::OWNED_BY_UPSTREAM:      return "UPSTREAM";
1236        case BufferInfo::OWNED_BY_DOWNSTREAM:    return "DOWNSTREAM";
1237        case BufferInfo::OWNED_BY_NATIVE_WINDOW: return "SURFACE";
1238        case BufferInfo::UNRECOGNIZED:           return "UNRECOGNIZED";
1239        default:                                 return "?";
1240    }
1241}
1242
1243void ACodec::dumpBuffers(OMX_U32 portIndex) {
1244    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
1245    ALOGI("[%s] %s port has %zu buffers:", mComponentName.c_str(),
1246            portIndex == kPortIndexInput ? "input" : "output", mBuffers[portIndex].size());
1247    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
1248        const BufferInfo &info = mBuffers[portIndex][i];
1249        ALOGI("  slot %2zu: #%8u %p/%p %s(%d) dequeued:%u",
1250                i, info.mBufferID, info.mGraphicBuffer.get(),
1251                info.mGraphicBuffer == NULL ? NULL : info.mGraphicBuffer->getNativeBuffer(),
1252                _asString(info.mStatus), info.mStatus, info.mDequeuedAt);
1253    }
1254}
1255
1256status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) {
1257    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
1258
1259    ALOGV("[%s] Calling cancelBuffer on buffer %u",
1260         mComponentName.c_str(), info->mBufferID);
1261
1262    info->checkWriteFence("cancelBufferToNativeWindow");
1263    int err = mNativeWindow->cancelBuffer(
1264        mNativeWindow.get(), info->mGraphicBuffer.get(), info->mFenceFd);
1265    info->mFenceFd = -1;
1266
1267    ALOGW_IF(err != 0, "[%s] can not return buffer %u to native window",
1268            mComponentName.c_str(), info->mBufferID);
1269    // change ownership even if cancelBuffer fails
1270    info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
1271
1272    return err;
1273}
1274
1275void ACodec::updateRenderInfoForDequeuedBuffer(
1276        ANativeWindowBuffer *buf, int fenceFd, BufferInfo *info) {
1277
1278    info->mRenderInfo =
1279        mRenderTracker.updateInfoForDequeuedBuffer(
1280                buf, fenceFd, info - &mBuffers[kPortIndexOutput][0]);
1281
1282    // check for any fences already signaled
1283    notifyOfRenderedFrames(false /* dropIncomplete */, info->mRenderInfo);
1284}
1285
1286void ACodec::onFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) {
1287    if (mRenderTracker.onFrameRendered(mediaTimeUs, systemNano) != OK) {
1288        mRenderTracker.dumpRenderQueue();
1289    }
1290}
1291
1292void ACodec::notifyOfRenderedFrames(bool dropIncomplete, FrameRenderTracker::Info *until) {
1293    sp<AMessage> msg = mNotify->dup();
1294    msg->setInt32("what", CodecBase::kWhatOutputFramesRendered);
1295    std::list<FrameRenderTracker::Info> done =
1296        mRenderTracker.checkFencesAndGetRenderedFrames(until, dropIncomplete);
1297
1298    // unlink untracked frames
1299    for (std::list<FrameRenderTracker::Info>::const_iterator it = done.cbegin();
1300            it != done.cend(); ++it) {
1301        ssize_t index = it->getIndex();
1302        if (index >= 0 && (size_t)index < mBuffers[kPortIndexOutput].size()) {
1303            mBuffers[kPortIndexOutput].editItemAt(index).mRenderInfo = NULL;
1304        } else if (index >= 0) {
1305            // THIS SHOULD NEVER HAPPEN
1306            ALOGE("invalid index %zd in %zu", index, mBuffers[kPortIndexOutput].size());
1307        }
1308    }
1309
1310    if (MediaCodec::CreateFramesRenderedMessage(done, msg)) {
1311        msg->post();
1312    }
1313}
1314
1315ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
1316    ANativeWindowBuffer *buf;
1317    CHECK(mNativeWindow.get() != NULL);
1318
1319    if (mTunneled) {
1320        ALOGW("dequeueBufferFromNativeWindow() should not be called in tunnel"
1321              " video playback mode mode!");
1322        return NULL;
1323    }
1324
1325    if (mFatalError) {
1326        ALOGW("not dequeuing from native window due to fatal error");
1327        return NULL;
1328    }
1329
1330    int fenceFd = -1;
1331    do {
1332        status_t err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf, &fenceFd);
1333        if (err != 0) {
1334            ALOGE("dequeueBuffer failed: %s(%d).", asString(err), err);
1335            return NULL;
1336        }
1337
1338        bool stale = false;
1339        for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) {
1340            i--;
1341            BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
1342
1343            if (info->mGraphicBuffer != NULL &&
1344                    info->mGraphicBuffer->handle == buf->handle) {
1345                // Since consumers can attach buffers to BufferQueues, it is possible
1346                // that a known yet stale buffer can return from a surface that we
1347                // once used.  We can simply ignore this as we have already dequeued
1348                // this buffer properly.  NOTE: this does not eliminate all cases,
1349                // e.g. it is possible that we have queued the valid buffer to the
1350                // NW, and a stale copy of the same buffer gets dequeued - which will
1351                // be treated as the valid buffer by ACodec.
1352                if (info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
1353                    ALOGI("dequeued stale buffer %p. discarding", buf);
1354                    stale = true;
1355                    break;
1356                }
1357
1358                ALOGV("dequeued buffer %p", info->mGraphicBuffer->getNativeBuffer());
1359                info->mStatus = BufferInfo::OWNED_BY_US;
1360                info->setWriteFence(fenceFd, "dequeueBufferFromNativeWindow");
1361                updateRenderInfoForDequeuedBuffer(buf, fenceFd, info);
1362                return info;
1363            }
1364        }
1365
1366        // It is also possible to receive a previously unregistered buffer
1367        // in non-meta mode. These should be treated as stale buffers. The
1368        // same is possible in meta mode, in which case, it will be treated
1369        // as a normal buffer, which is not desirable.
1370        // TODO: fix this.
1371        if (!stale && (!storingMetadataInDecodedBuffers() || mLegacyAdaptiveExperiment)) {
1372            ALOGI("dequeued unrecognized (stale) buffer %p. discarding", buf);
1373            stale = true;
1374        }
1375        if (stale) {
1376            // TODO: detach stale buffer, but there is no API yet to do it.
1377            buf = NULL;
1378        }
1379    } while (buf == NULL);
1380
1381    // get oldest undequeued buffer
1382    BufferInfo *oldest = NULL;
1383    for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) {
1384        i--;
1385        BufferInfo *info =
1386            &mBuffers[kPortIndexOutput].editItemAt(i);
1387        if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW &&
1388            (oldest == NULL ||
1389             // avoid potential issues from counter rolling over
1390             mDequeueCounter - info->mDequeuedAt >
1391                    mDequeueCounter - oldest->mDequeuedAt)) {
1392            oldest = info;
1393        }
1394    }
1395
1396    // it is impossible dequeue a buffer when there are no buffers with ANW
1397    CHECK(oldest != NULL);
1398    // it is impossible to dequeue an unknown buffer in non-meta mode, as the
1399    // while loop above does not complete
1400    CHECK(storingMetadataInDecodedBuffers());
1401
1402    // discard buffer in LRU info and replace with new buffer
1403    oldest->mGraphicBuffer = new GraphicBuffer(buf, false);
1404    oldest->mStatus = BufferInfo::OWNED_BY_US;
1405    oldest->setWriteFence(fenceFd, "dequeueBufferFromNativeWindow for oldest");
1406    mRenderTracker.untrackFrame(oldest->mRenderInfo);
1407    oldest->mRenderInfo = NULL;
1408
1409    mOMX->updateGraphicBufferInMeta(
1410            mNode, kPortIndexOutput, oldest->mGraphicBuffer,
1411            oldest->mBufferID);
1412
1413    if (mOutputMetadataType == kMetadataBufferTypeGrallocSource) {
1414        VideoGrallocMetadata *grallocMeta =
1415            reinterpret_cast<VideoGrallocMetadata *>(oldest->mData->base());
1416        ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)",
1417                (unsigned)(oldest - &mBuffers[kPortIndexOutput][0]),
1418                mDequeueCounter - oldest->mDequeuedAt,
1419                (void *)(uintptr_t)grallocMeta->pHandle,
1420                oldest->mGraphicBuffer->handle, oldest->mData->base());
1421    } else if (mOutputMetadataType == kMetadataBufferTypeANWBuffer) {
1422        VideoNativeMetadata *nativeMeta =
1423            reinterpret_cast<VideoNativeMetadata *>(oldest->mData->base());
1424        ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)",
1425                (unsigned)(oldest - &mBuffers[kPortIndexOutput][0]),
1426                mDequeueCounter - oldest->mDequeuedAt,
1427                (void *)(uintptr_t)nativeMeta->pBuffer,
1428                oldest->mGraphicBuffer->getNativeBuffer(), oldest->mData->base());
1429    }
1430
1431    updateRenderInfoForDequeuedBuffer(buf, fenceFd, oldest);
1432    return oldest;
1433}
1434
1435status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) {
1436    status_t err = OK;
1437    for (size_t i = mBuffers[portIndex].size(); i > 0;) {
1438        i--;
1439        status_t err2 = freeBuffer(portIndex, i);
1440        if (err == OK) {
1441            err = err2;
1442        }
1443    }
1444
1445    // clear mDealer even on an error
1446    mDealer[portIndex].clear();
1447    return err;
1448}
1449
1450status_t ACodec::freeOutputBuffersNotOwnedByComponent() {
1451    status_t err = OK;
1452    for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) {
1453        i--;
1454        BufferInfo *info =
1455            &mBuffers[kPortIndexOutput].editItemAt(i);
1456
1457        // At this time some buffers may still be with the component
1458        // or being drained.
1459        if (info->mStatus != BufferInfo::OWNED_BY_COMPONENT &&
1460            info->mStatus != BufferInfo::OWNED_BY_DOWNSTREAM) {
1461            status_t err2 = freeBuffer(kPortIndexOutput, i);
1462            if (err == OK) {
1463                err = err2;
1464            }
1465        }
1466    }
1467
1468    return err;
1469}
1470
1471status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) {
1472    BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
1473    status_t err = OK;
1474
1475    // there should not be any fences in the metadata
1476    MetadataBufferType type =
1477        portIndex == kPortIndexOutput ? mOutputMetadataType : mInputMetadataType;
1478    if (type == kMetadataBufferTypeANWBuffer && info->mData != NULL
1479            && info->mData->size() >= sizeof(VideoNativeMetadata)) {
1480        int fenceFd = ((VideoNativeMetadata *)info->mData->data())->nFenceFd;
1481        if (fenceFd >= 0) {
1482            ALOGW("unreleased fence (%d) in %s metadata buffer %zu",
1483                    fenceFd, portIndex == kPortIndexInput ? "input" : "output", i);
1484        }
1485    }
1486
1487    switch (info->mStatus) {
1488        case BufferInfo::OWNED_BY_US:
1489            if (portIndex == kPortIndexOutput && mNativeWindow != NULL) {
1490                (void)cancelBufferToNativeWindow(info);
1491            }
1492            // fall through
1493
1494        case BufferInfo::OWNED_BY_NATIVE_WINDOW:
1495            err = mOMX->freeBuffer(mNode, portIndex, info->mBufferID);
1496            break;
1497
1498        default:
1499            ALOGE("trying to free buffer not owned by us or ANW (%d)", info->mStatus);
1500            err = FAILED_TRANSACTION;
1501            break;
1502    }
1503
1504    if (info->mFenceFd >= 0) {
1505        ::close(info->mFenceFd);
1506    }
1507
1508    if (portIndex == kPortIndexOutput) {
1509        mRenderTracker.untrackFrame(info->mRenderInfo, i);
1510        info->mRenderInfo = NULL;
1511    }
1512
1513    // remove buffer even if mOMX->freeBuffer fails
1514    mBuffers[portIndex].removeAt(i);
1515    return err;
1516}
1517
1518ACodec::BufferInfo *ACodec::findBufferByID(
1519        uint32_t portIndex, IOMX::buffer_id bufferID, ssize_t *index) {
1520    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
1521        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
1522
1523        if (info->mBufferID == bufferID) {
1524            if (index != NULL) {
1525                *index = i;
1526            }
1527            return info;
1528        }
1529    }
1530
1531    ALOGE("Could not find buffer with ID %u", bufferID);
1532    return NULL;
1533}
1534
1535status_t ACodec::setComponentRole(
1536        bool isEncoder, const char *mime) {
1537    const char *role = getComponentRole(isEncoder, mime);
1538    if (role == NULL) {
1539        return BAD_VALUE;
1540    }
1541    status_t err = setComponentRole(mOMX, mNode, role);
1542    if (err != OK) {
1543        ALOGW("[%s] Failed to set standard component role '%s'.",
1544             mComponentName.c_str(), role);
1545    }
1546    return err;
1547}
1548
1549//static
1550const char *ACodec::getComponentRole(
1551        bool isEncoder, const char *mime) {
1552    struct MimeToRole {
1553        const char *mime;
1554        const char *decoderRole;
1555        const char *encoderRole;
1556    };
1557
1558    static const MimeToRole kMimeToRole[] = {
1559        { MEDIA_MIMETYPE_AUDIO_MPEG,
1560            "audio_decoder.mp3", "audio_encoder.mp3" },
1561        { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I,
1562            "audio_decoder.mp1", "audio_encoder.mp1" },
1563        { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II,
1564            "audio_decoder.mp2", "audio_encoder.mp2" },
1565        { MEDIA_MIMETYPE_AUDIO_AMR_NB,
1566            "audio_decoder.amrnb", "audio_encoder.amrnb" },
1567        { MEDIA_MIMETYPE_AUDIO_AMR_WB,
1568            "audio_decoder.amrwb", "audio_encoder.amrwb" },
1569        { MEDIA_MIMETYPE_AUDIO_AAC,
1570            "audio_decoder.aac", "audio_encoder.aac" },
1571        { MEDIA_MIMETYPE_AUDIO_VORBIS,
1572            "audio_decoder.vorbis", "audio_encoder.vorbis" },
1573        { MEDIA_MIMETYPE_AUDIO_OPUS,
1574            "audio_decoder.opus", "audio_encoder.opus" },
1575        { MEDIA_MIMETYPE_AUDIO_G711_MLAW,
1576            "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" },
1577        { MEDIA_MIMETYPE_AUDIO_G711_ALAW,
1578            "audio_decoder.g711alaw", "audio_encoder.g711alaw" },
1579        { MEDIA_MIMETYPE_VIDEO_AVC,
1580            "video_decoder.avc", "video_encoder.avc" },
1581        { MEDIA_MIMETYPE_VIDEO_HEVC,
1582            "video_decoder.hevc", "video_encoder.hevc" },
1583        { MEDIA_MIMETYPE_VIDEO_MPEG4,
1584            "video_decoder.mpeg4", "video_encoder.mpeg4" },
1585        { MEDIA_MIMETYPE_VIDEO_H263,
1586            "video_decoder.h263", "video_encoder.h263" },
1587        { MEDIA_MIMETYPE_VIDEO_VP8,
1588            "video_decoder.vp8", "video_encoder.vp8" },
1589        { MEDIA_MIMETYPE_VIDEO_VP9,
1590            "video_decoder.vp9", "video_encoder.vp9" },
1591        { MEDIA_MIMETYPE_AUDIO_RAW,
1592            "audio_decoder.raw", "audio_encoder.raw" },
1593        { MEDIA_MIMETYPE_VIDEO_DOLBY_VISION,
1594            "video_decoder.dolby-vision", "video_encoder.dolby-vision" },
1595        { MEDIA_MIMETYPE_AUDIO_FLAC,
1596            "audio_decoder.flac", "audio_encoder.flac" },
1597        { MEDIA_MIMETYPE_AUDIO_MSGSM,
1598            "audio_decoder.gsm", "audio_encoder.gsm" },
1599        { MEDIA_MIMETYPE_VIDEO_MPEG2,
1600            "video_decoder.mpeg2", "video_encoder.mpeg2" },
1601        { MEDIA_MIMETYPE_AUDIO_AC3,
1602            "audio_decoder.ac3", "audio_encoder.ac3" },
1603        { MEDIA_MIMETYPE_AUDIO_EAC3,
1604            "audio_decoder.eac3", "audio_encoder.eac3" },
1605    };
1606
1607    static const size_t kNumMimeToRole =
1608        sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
1609
1610    size_t i;
1611    for (i = 0; i < kNumMimeToRole; ++i) {
1612        if (!strcasecmp(mime, kMimeToRole[i].mime)) {
1613            break;
1614        }
1615    }
1616
1617    if (i == kNumMimeToRole) {
1618        return NULL;
1619    }
1620
1621    return isEncoder ? kMimeToRole[i].encoderRole
1622                  : kMimeToRole[i].decoderRole;
1623}
1624
1625//static
1626status_t ACodec::setComponentRole(
1627        const sp<IOMX> &omx, IOMX::node_id node, const char *role) {
1628    OMX_PARAM_COMPONENTROLETYPE roleParams;
1629    InitOMXParams(&roleParams);
1630
1631    strncpy((char *)roleParams.cRole,
1632            role, OMX_MAX_STRINGNAME_SIZE - 1);
1633
1634    roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
1635
1636    return omx->setParameter(
1637            node, OMX_IndexParamStandardComponentRole,
1638            &roleParams, sizeof(roleParams));
1639}
1640
1641status_t ACodec::configureCodec(
1642        const char *mime, const sp<AMessage> &msg) {
1643    int32_t encoder;
1644    if (!msg->findInt32("encoder", &encoder)) {
1645        encoder = false;
1646    }
1647
1648    sp<AMessage> inputFormat = new AMessage;
1649    sp<AMessage> outputFormat = new AMessage;
1650
1651    mIsEncoder = encoder;
1652
1653    mInputMetadataType = kMetadataBufferTypeInvalid;
1654    mOutputMetadataType = kMetadataBufferTypeInvalid;
1655
1656    status_t err = setComponentRole(encoder /* isEncoder */, mime);
1657
1658    if (err != OK) {
1659        return err;
1660    }
1661
1662    int32_t bitRate = 0;
1663    // FLAC encoder doesn't need a bitrate, other encoders do
1664    if (encoder && strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)
1665            && !msg->findInt32("bitrate", &bitRate)) {
1666        return INVALID_OPERATION;
1667    }
1668
1669    int32_t storeMeta;
1670    if (encoder
1671            && msg->findInt32("store-metadata-in-buffers", &storeMeta)
1672            && storeMeta != 0) {
1673        err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexInput, OMX_TRUE, &mInputMetadataType);
1674        if (err != OK) {
1675            ALOGE("[%s] storeMetaDataInBuffers (input) failed w/ err %d",
1676                    mComponentName.c_str(), err);
1677
1678            return err;
1679        }
1680        // For this specific case we could be using camera source even if storeMetaDataInBuffers
1681        // returns Gralloc source. Pretend that we are; this will force us to use nBufferSize.
1682        if (mInputMetadataType == kMetadataBufferTypeGrallocSource) {
1683            mInputMetadataType = kMetadataBufferTypeCameraSource;
1684        }
1685
1686        uint32_t usageBits;
1687        if (mOMX->getParameter(
1688                mNode, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
1689                &usageBits, sizeof(usageBits)) == OK) {
1690            inputFormat->setInt32(
1691                    "using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN));
1692        }
1693    }
1694
1695    int32_t prependSPSPPS = 0;
1696    if (encoder
1697            && msg->findInt32("prepend-sps-pps-to-idr-frames", &prependSPSPPS)
1698            && prependSPSPPS != 0) {
1699        OMX_INDEXTYPE index;
1700        err = mOMX->getExtensionIndex(
1701                mNode,
1702                "OMX.google.android.index.prependSPSPPSToIDRFrames",
1703                &index);
1704
1705        if (err == OK) {
1706            PrependSPSPPSToIDRFramesParams params;
1707            InitOMXParams(&params);
1708            params.bEnable = OMX_TRUE;
1709
1710            err = mOMX->setParameter(
1711                    mNode, index, &params, sizeof(params));
1712        }
1713
1714        if (err != OK) {
1715            ALOGE("Encoder could not be configured to emit SPS/PPS before "
1716                  "IDR frames. (err %d)", err);
1717
1718            return err;
1719        }
1720    }
1721
1722    // Only enable metadata mode on encoder output if encoder can prepend
1723    // sps/pps to idr frames, since in metadata mode the bitstream is in an
1724    // opaque handle, to which we don't have access.
1725    int32_t video = !strncasecmp(mime, "video/", 6);
1726    mIsVideo = video;
1727    if (encoder && video) {
1728        OMX_BOOL enable = (OMX_BOOL) (prependSPSPPS
1729            && msg->findInt32("store-metadata-in-buffers-output", &storeMeta)
1730            && storeMeta != 0);
1731
1732        err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, enable, &mOutputMetadataType);
1733        if (err != OK) {
1734            ALOGE("[%s] storeMetaDataInBuffers (output) failed w/ err %d",
1735                mComponentName.c_str(), err);
1736        }
1737
1738        if (!msg->findInt64(
1739                    "repeat-previous-frame-after",
1740                    &mRepeatFrameDelayUs)) {
1741            mRepeatFrameDelayUs = -1ll;
1742        }
1743
1744        if (!msg->findInt64("max-pts-gap-to-encoder", &mMaxPtsGapUs)) {
1745            mMaxPtsGapUs = -1ll;
1746        }
1747
1748        if (!msg->findFloat("max-fps-to-encoder", &mMaxFps)) {
1749            mMaxFps = -1;
1750        }
1751
1752        if (!msg->findInt64("time-lapse", &mTimePerCaptureUs)) {
1753            mTimePerCaptureUs = -1ll;
1754        }
1755
1756        if (!msg->findInt32(
1757                    "create-input-buffers-suspended",
1758                    (int32_t*)&mCreateInputBuffersSuspended)) {
1759            mCreateInputBuffersSuspended = false;
1760        }
1761    }
1762
1763    // NOTE: we only use native window for video decoders
1764    sp<RefBase> obj;
1765    bool haveNativeWindow = msg->findObject("native-window", &obj)
1766            && obj != NULL && video && !encoder;
1767    mLegacyAdaptiveExperiment = false;
1768    if (video && !encoder) {
1769        inputFormat->setInt32("adaptive-playback", false);
1770
1771        int32_t usageProtected;
1772        if (msg->findInt32("protected", &usageProtected) && usageProtected) {
1773            if (!haveNativeWindow) {
1774                ALOGE("protected output buffers must be sent to an ANativeWindow");
1775                return PERMISSION_DENIED;
1776            }
1777            mFlags |= kFlagIsGrallocUsageProtected;
1778            mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
1779        }
1780
1781        if (mFlags & kFlagIsSecure) {
1782            // use native_handles for secure input buffers
1783            err = mOMX->enableNativeBuffers(
1784                    mNode, kPortIndexInput, OMX_FALSE /* graphic */, OMX_TRUE);
1785            ALOGI_IF(err != OK, "falling back to non-native_handles");
1786            err = OK; // ignore error for now
1787        }
1788    }
1789    if (haveNativeWindow) {
1790        sp<ANativeWindow> nativeWindow =
1791            static_cast<ANativeWindow *>(static_cast<Surface *>(obj.get()));
1792
1793        // START of temporary support for automatic FRC - THIS WILL BE REMOVED
1794        int32_t autoFrc;
1795        if (msg->findInt32("auto-frc", &autoFrc)) {
1796            bool enabled = autoFrc;
1797            OMX_CONFIG_BOOLEANTYPE config;
1798            InitOMXParams(&config);
1799            config.bEnabled = (OMX_BOOL)enabled;
1800            status_t temp = mOMX->setConfig(
1801                    mNode, (OMX_INDEXTYPE)OMX_IndexConfigAutoFramerateConversion,
1802                    &config, sizeof(config));
1803            if (temp == OK) {
1804                outputFormat->setInt32("auto-frc", enabled);
1805            } else if (enabled) {
1806                ALOGI("codec does not support requested auto-frc (err %d)", temp);
1807            }
1808        }
1809        // END of temporary support for automatic FRC
1810
1811        int32_t tunneled;
1812        if (msg->findInt32("feature-tunneled-playback", &tunneled) &&
1813            tunneled != 0) {
1814            ALOGI("Configuring TUNNELED video playback.");
1815            mTunneled = true;
1816
1817            int32_t audioHwSync = 0;
1818            if (!msg->findInt32("audio-hw-sync", &audioHwSync)) {
1819                ALOGW("No Audio HW Sync provided for video tunnel");
1820            }
1821            err = configureTunneledVideoPlayback(audioHwSync, nativeWindow);
1822            if (err != OK) {
1823                ALOGE("configureTunneledVideoPlayback(%d,%p) failed!",
1824                        audioHwSync, nativeWindow.get());
1825                return err;
1826            }
1827
1828            int32_t maxWidth = 0, maxHeight = 0;
1829            if (msg->findInt32("max-width", &maxWidth) &&
1830                    msg->findInt32("max-height", &maxHeight)) {
1831
1832                err = mOMX->prepareForAdaptivePlayback(
1833                        mNode, kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight);
1834                if (err != OK) {
1835                    ALOGW("[%s] prepareForAdaptivePlayback failed w/ err %d",
1836                            mComponentName.c_str(), err);
1837                    // allow failure
1838                    err = OK;
1839                } else {
1840                    inputFormat->setInt32("max-width", maxWidth);
1841                    inputFormat->setInt32("max-height", maxHeight);
1842                    inputFormat->setInt32("adaptive-playback", true);
1843                }
1844            }
1845        } else {
1846            ALOGV("Configuring CPU controlled video playback.");
1847            mTunneled = false;
1848
1849            // Explicity reset the sideband handle of the window for
1850            // non-tunneled video in case the window was previously used
1851            // for a tunneled video playback.
1852            err = native_window_set_sideband_stream(nativeWindow.get(), NULL);
1853            if (err != OK) {
1854                ALOGE("set_sideband_stream(NULL) failed! (err %d).", err);
1855                return err;
1856            }
1857
1858            // Always try to enable dynamic output buffers on native surface
1859            err = mOMX->storeMetaDataInBuffers(
1860                    mNode, kPortIndexOutput, OMX_TRUE, &mOutputMetadataType);
1861            if (err != OK) {
1862                ALOGE("[%s] storeMetaDataInBuffers failed w/ err %d",
1863                        mComponentName.c_str(), err);
1864
1865                // if adaptive playback has been requested, try JB fallback
1866                // NOTE: THIS FALLBACK MECHANISM WILL BE REMOVED DUE TO ITS
1867                // LARGE MEMORY REQUIREMENT
1868
1869                // we will not do adaptive playback on software accessed
1870                // surfaces as they never had to respond to changes in the
1871                // crop window, and we don't trust that they will be able to.
1872                int usageBits = 0;
1873                bool canDoAdaptivePlayback;
1874
1875                if (nativeWindow->query(
1876                        nativeWindow.get(),
1877                        NATIVE_WINDOW_CONSUMER_USAGE_BITS,
1878                        &usageBits) != OK) {
1879                    canDoAdaptivePlayback = false;
1880                } else {
1881                    canDoAdaptivePlayback =
1882                        (usageBits &
1883                                (GRALLOC_USAGE_SW_READ_MASK |
1884                                 GRALLOC_USAGE_SW_WRITE_MASK)) == 0;
1885                }
1886
1887                int32_t maxWidth = 0, maxHeight = 0;
1888                if (canDoAdaptivePlayback &&
1889                        msg->findInt32("max-width", &maxWidth) &&
1890                        msg->findInt32("max-height", &maxHeight)) {
1891                    ALOGV("[%s] prepareForAdaptivePlayback(%dx%d)",
1892                            mComponentName.c_str(), maxWidth, maxHeight);
1893
1894                    err = mOMX->prepareForAdaptivePlayback(
1895                            mNode, kPortIndexOutput, OMX_TRUE, maxWidth,
1896                            maxHeight);
1897                    ALOGW_IF(err != OK,
1898                            "[%s] prepareForAdaptivePlayback failed w/ err %d",
1899                            mComponentName.c_str(), err);
1900
1901                    if (err == OK) {
1902                        inputFormat->setInt32("max-width", maxWidth);
1903                        inputFormat->setInt32("max-height", maxHeight);
1904                        inputFormat->setInt32("adaptive-playback", true);
1905                    }
1906                }
1907                // allow failure
1908                err = OK;
1909            } else {
1910                ALOGV("[%s] storeMetaDataInBuffers succeeded",
1911                        mComponentName.c_str());
1912                CHECK(storingMetadataInDecodedBuffers());
1913                mLegacyAdaptiveExperiment = ADebug::isExperimentEnabled(
1914                        "legacy-adaptive", !msg->contains("no-experiments"));
1915
1916                inputFormat->setInt32("adaptive-playback", true);
1917            }
1918
1919            int32_t push;
1920            if (msg->findInt32("push-blank-buffers-on-shutdown", &push)
1921                    && push != 0) {
1922                mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
1923            }
1924        }
1925
1926        int32_t rotationDegrees;
1927        if (msg->findInt32("rotation-degrees", &rotationDegrees)) {
1928            mRotationDegrees = rotationDegrees;
1929        } else {
1930            mRotationDegrees = 0;
1931        }
1932    }
1933
1934    if (video) {
1935        // determine need for software renderer
1936        bool usingSwRenderer = false;
1937        if (haveNativeWindow && mComponentName.startsWith("OMX.google.")) {
1938            usingSwRenderer = true;
1939            haveNativeWindow = false;
1940        }
1941
1942        if (encoder) {
1943            err = setupVideoEncoder(mime, msg, outputFormat);
1944        } else {
1945            err = setupVideoDecoder(mime, msg, haveNativeWindow, outputFormat);
1946        }
1947
1948        if (err != OK) {
1949            return err;
1950        }
1951
1952        if (haveNativeWindow) {
1953            mNativeWindow = static_cast<Surface *>(obj.get());
1954        }
1955
1956        // initialize native window now to get actual output format
1957        // TODO: this is needed for some encoders even though they don't use native window
1958        err = initNativeWindow();
1959        if (err != OK) {
1960            return err;
1961        }
1962
1963        // fallback for devices that do not handle flex-YUV for native buffers
1964        if (haveNativeWindow) {
1965            int32_t requestedColorFormat = OMX_COLOR_FormatUnused;
1966            if (msg->findInt32("color-format", &requestedColorFormat) &&
1967                    requestedColorFormat == OMX_COLOR_FormatYUV420Flexible) {
1968                status_t err = getPortFormat(kPortIndexOutput, outputFormat);
1969                if (err != OK) {
1970                    return err;
1971                }
1972                int32_t colorFormat = OMX_COLOR_FormatUnused;
1973                OMX_U32 flexibleEquivalent = OMX_COLOR_FormatUnused;
1974                if (!outputFormat->findInt32("color-format", &colorFormat)) {
1975                    ALOGE("ouptut port did not have a color format (wrong domain?)");
1976                    return BAD_VALUE;
1977                }
1978                ALOGD("[%s] Requested output format %#x and got %#x.",
1979                        mComponentName.c_str(), requestedColorFormat, colorFormat);
1980                if (!isFlexibleColorFormat(
1981                                mOMX, mNode, colorFormat, haveNativeWindow, &flexibleEquivalent)
1982                        || flexibleEquivalent != (OMX_U32)requestedColorFormat) {
1983                    // device did not handle flex-YUV request for native window, fall back
1984                    // to SW renderer
1985                    ALOGI("[%s] Falling back to software renderer", mComponentName.c_str());
1986                    mNativeWindow.clear();
1987                    mNativeWindowUsageBits = 0;
1988                    haveNativeWindow = false;
1989                    usingSwRenderer = true;
1990                    if (storingMetadataInDecodedBuffers()) {
1991                        err = mOMX->storeMetaDataInBuffers(
1992                                mNode, kPortIndexOutput, OMX_FALSE, &mOutputMetadataType);
1993                        mOutputMetadataType = kMetadataBufferTypeInvalid; // just in case
1994                        // TODO: implement adaptive-playback support for bytebuffer mode.
1995                        // This is done by SW codecs, but most HW codecs don't support it.
1996                        inputFormat->setInt32("adaptive-playback", false);
1997                    }
1998                    if (err == OK) {
1999                        err = mOMX->enableNativeBuffers(
2000                                mNode, kPortIndexOutput, OMX_TRUE /* graphic */, OMX_FALSE);
2001                    }
2002                    if (mFlags & kFlagIsGrallocUsageProtected) {
2003                        // fallback is not supported for protected playback
2004                        err = PERMISSION_DENIED;
2005                    } else if (err == OK) {
2006                        err = setupVideoDecoder(mime, msg, false, outputFormat);
2007                    }
2008                }
2009            }
2010        }
2011
2012        if (usingSwRenderer) {
2013            outputFormat->setInt32("using-sw-renderer", 1);
2014        }
2015    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
2016        int32_t numChannels, sampleRate;
2017        if (!msg->findInt32("channel-count", &numChannels)
2018                || !msg->findInt32("sample-rate", &sampleRate)) {
2019            // Since we did not always check for these, leave them optional
2020            // and have the decoder figure it all out.
2021            err = OK;
2022        } else {
2023            err = setupRawAudioFormat(
2024                    encoder ? kPortIndexInput : kPortIndexOutput,
2025                    sampleRate,
2026                    numChannels);
2027        }
2028    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
2029        int32_t numChannels, sampleRate;
2030        if (!msg->findInt32("channel-count", &numChannels)
2031                || !msg->findInt32("sample-rate", &sampleRate)) {
2032            err = INVALID_OPERATION;
2033        } else {
2034            int32_t isADTS, aacProfile;
2035            int32_t sbrMode;
2036            int32_t maxOutputChannelCount;
2037            int32_t pcmLimiterEnable;
2038            drcParams_t drc;
2039            if (!msg->findInt32("is-adts", &isADTS)) {
2040                isADTS = 0;
2041            }
2042            if (!msg->findInt32("aac-profile", &aacProfile)) {
2043                aacProfile = OMX_AUDIO_AACObjectNull;
2044            }
2045            if (!msg->findInt32("aac-sbr-mode", &sbrMode)) {
2046                sbrMode = -1;
2047            }
2048
2049            if (!msg->findInt32("aac-max-output-channel_count", &maxOutputChannelCount)) {
2050                maxOutputChannelCount = -1;
2051            }
2052            if (!msg->findInt32("aac-pcm-limiter-enable", &pcmLimiterEnable)) {
2053                // value is unknown
2054                pcmLimiterEnable = -1;
2055            }
2056            if (!msg->findInt32("aac-encoded-target-level", &drc.encodedTargetLevel)) {
2057                // value is unknown
2058                drc.encodedTargetLevel = -1;
2059            }
2060            if (!msg->findInt32("aac-drc-cut-level", &drc.drcCut)) {
2061                // value is unknown
2062                drc.drcCut = -1;
2063            }
2064            if (!msg->findInt32("aac-drc-boost-level", &drc.drcBoost)) {
2065                // value is unknown
2066                drc.drcBoost = -1;
2067            }
2068            if (!msg->findInt32("aac-drc-heavy-compression", &drc.heavyCompression)) {
2069                // value is unknown
2070                drc.heavyCompression = -1;
2071            }
2072            if (!msg->findInt32("aac-target-ref-level", &drc.targetRefLevel)) {
2073                // value is unknown
2074                drc.targetRefLevel = -1;
2075            }
2076
2077            err = setupAACCodec(
2078                    encoder, numChannels, sampleRate, bitRate, aacProfile,
2079                    isADTS != 0, sbrMode, maxOutputChannelCount, drc,
2080                    pcmLimiterEnable);
2081        }
2082    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
2083        err = setupAMRCodec(encoder, false /* isWAMR */, bitRate);
2084    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
2085        err = setupAMRCodec(encoder, true /* isWAMR */, bitRate);
2086    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW)
2087            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) {
2088        // These are PCM-like formats with a fixed sample rate but
2089        // a variable number of channels.
2090
2091        int32_t numChannels;
2092        if (!msg->findInt32("channel-count", &numChannels)) {
2093            err = INVALID_OPERATION;
2094        } else {
2095            int32_t sampleRate;
2096            if (!msg->findInt32("sample-rate", &sampleRate)) {
2097                sampleRate = 8000;
2098            }
2099            err = setupG711Codec(encoder, sampleRate, numChannels);
2100        }
2101    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) {
2102        int32_t numChannels = 0, sampleRate = 0, compressionLevel = -1;
2103        if (encoder &&
2104                (!msg->findInt32("channel-count", &numChannels)
2105                        || !msg->findInt32("sample-rate", &sampleRate))) {
2106            ALOGE("missing channel count or sample rate for FLAC encoder");
2107            err = INVALID_OPERATION;
2108        } else {
2109            if (encoder) {
2110                if (!msg->findInt32(
2111                            "complexity", &compressionLevel) &&
2112                    !msg->findInt32(
2113                            "flac-compression-level", &compressionLevel)) {
2114                    compressionLevel = 5; // default FLAC compression level
2115                } else if (compressionLevel < 0) {
2116                    ALOGW("compression level %d outside [0..8] range, "
2117                          "using 0",
2118                          compressionLevel);
2119                    compressionLevel = 0;
2120                } else if (compressionLevel > 8) {
2121                    ALOGW("compression level %d outside [0..8] range, "
2122                          "using 8",
2123                          compressionLevel);
2124                    compressionLevel = 8;
2125                }
2126            }
2127            err = setupFlacCodec(
2128                    encoder, numChannels, sampleRate, compressionLevel);
2129        }
2130    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
2131        int32_t numChannels, sampleRate;
2132        if (encoder
2133                || !msg->findInt32("channel-count", &numChannels)
2134                || !msg->findInt32("sample-rate", &sampleRate)) {
2135            err = INVALID_OPERATION;
2136        } else {
2137            err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
2138        }
2139    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AC3)) {
2140        int32_t numChannels;
2141        int32_t sampleRate;
2142        if (!msg->findInt32("channel-count", &numChannels)
2143                || !msg->findInt32("sample-rate", &sampleRate)) {
2144            err = INVALID_OPERATION;
2145        } else {
2146            err = setupAC3Codec(encoder, numChannels, sampleRate);
2147        }
2148    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_EAC3)) {
2149        int32_t numChannels;
2150        int32_t sampleRate;
2151        if (!msg->findInt32("channel-count", &numChannels)
2152                || !msg->findInt32("sample-rate", &sampleRate)) {
2153            err = INVALID_OPERATION;
2154        } else {
2155            err = setupEAC3Codec(encoder, numChannels, sampleRate);
2156        }
2157    }
2158
2159    if (err != OK) {
2160        return err;
2161    }
2162
2163    if (!msg->findInt32("encoder-delay", &mEncoderDelay)) {
2164        mEncoderDelay = 0;
2165    }
2166
2167    if (!msg->findInt32("encoder-padding", &mEncoderPadding)) {
2168        mEncoderPadding = 0;
2169    }
2170
2171    if (msg->findInt32("channel-mask", &mChannelMask)) {
2172        mChannelMaskPresent = true;
2173    } else {
2174        mChannelMaskPresent = false;
2175    }
2176
2177    int32_t maxInputSize;
2178    if (msg->findInt32("max-input-size", &maxInputSize)) {
2179        err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize);
2180    } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) {
2181        err = setMinBufferSize(kPortIndexInput, 8192);  // XXX
2182    }
2183
2184    int32_t priority;
2185    if (msg->findInt32("priority", &priority)) {
2186        err = setPriority(priority);
2187    }
2188
2189    int32_t rateInt = -1;
2190    float rateFloat = -1;
2191    if (!msg->findFloat("operating-rate", &rateFloat)) {
2192        msg->findInt32("operating-rate", &rateInt);
2193        rateFloat = (float)rateInt;  // 16MHz (FLINTMAX) is OK for upper bound.
2194    }
2195    if (rateFloat > 0) {
2196        err = setOperatingRate(rateFloat, video);
2197    }
2198
2199    mBaseOutputFormat = outputFormat;
2200    // trigger a kWhatOutputFormatChanged msg on first buffer
2201    mLastOutputFormat.clear();
2202
2203    err = getPortFormat(kPortIndexInput, inputFormat);
2204    if (err == OK) {
2205        err = getPortFormat(kPortIndexOutput, outputFormat);
2206        if (err == OK) {
2207            mInputFormat = inputFormat;
2208            mOutputFormat = outputFormat;
2209        }
2210    }
2211    return err;
2212}
2213
2214status_t ACodec::setPriority(int32_t priority) {
2215    if (priority < 0) {
2216        return BAD_VALUE;
2217    }
2218    OMX_PARAM_U32TYPE config;
2219    InitOMXParams(&config);
2220    config.nU32 = (OMX_U32)priority;
2221    status_t temp = mOMX->setConfig(
2222            mNode, (OMX_INDEXTYPE)OMX_IndexConfigPriority,
2223            &config, sizeof(config));
2224    if (temp != OK) {
2225        ALOGI("codec does not support config priority (err %d)", temp);
2226    }
2227    return OK;
2228}
2229
2230status_t ACodec::setOperatingRate(float rateFloat, bool isVideo) {
2231    if (rateFloat < 0) {
2232        return BAD_VALUE;
2233    }
2234    OMX_U32 rate;
2235    if (isVideo) {
2236        if (rateFloat > 65535) {
2237            return BAD_VALUE;
2238        }
2239        rate = (OMX_U32)(rateFloat * 65536.0f + 0.5f);
2240    } else {
2241        if (rateFloat > UINT_MAX) {
2242            return BAD_VALUE;
2243        }
2244        rate = (OMX_U32)(rateFloat);
2245    }
2246    OMX_PARAM_U32TYPE config;
2247    InitOMXParams(&config);
2248    config.nU32 = rate;
2249    status_t err = mOMX->setConfig(
2250            mNode, (OMX_INDEXTYPE)OMX_IndexConfigOperatingRate,
2251            &config, sizeof(config));
2252    if (err != OK) {
2253        ALOGI("codec does not support config operating rate (err %d)", err);
2254    }
2255    return OK;
2256}
2257
2258status_t ACodec::getIntraRefreshPeriod(uint32_t *intraRefreshPeriod) {
2259    OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params;
2260    InitOMXParams(&params);
2261    params.nPortIndex = kPortIndexOutput;
2262    status_t err = mOMX->getConfig(
2263            mNode, (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, &params, sizeof(params));
2264    if (err == OK) {
2265        *intraRefreshPeriod = params.nRefreshPeriod;
2266        return OK;
2267    }
2268
2269    // Fallback to query through standard OMX index.
2270    OMX_VIDEO_PARAM_INTRAREFRESHTYPE refreshParams;
2271    InitOMXParams(&refreshParams);
2272    refreshParams.nPortIndex = kPortIndexOutput;
2273    refreshParams.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic;
2274    err = mOMX->getParameter(
2275            mNode, OMX_IndexParamVideoIntraRefresh, &refreshParams, sizeof(refreshParams));
2276    if (err != OK || refreshParams.nCirMBs == 0) {
2277        *intraRefreshPeriod = 0;
2278        return OK;
2279    }
2280
2281    // Calculate period based on width and height
2282    uint32_t width, height;
2283    OMX_PARAM_PORTDEFINITIONTYPE def;
2284    InitOMXParams(&def);
2285    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
2286    def.nPortIndex = kPortIndexOutput;
2287    err = mOMX->getParameter(
2288            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2289    if (err != OK) {
2290        *intraRefreshPeriod = 0;
2291        return err;
2292    }
2293    width = video_def->nFrameWidth;
2294    height = video_def->nFrameHeight;
2295    // Use H.264/AVC MacroBlock size 16x16
2296    *intraRefreshPeriod = divUp((divUp(width, 16u) * divUp(height, 16u)), refreshParams.nCirMBs);
2297
2298    return OK;
2299}
2300
2301status_t ACodec::setIntraRefreshPeriod(uint32_t intraRefreshPeriod, bool inConfigure) {
2302    OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params;
2303    InitOMXParams(&params);
2304    params.nPortIndex = kPortIndexOutput;
2305    params.nRefreshPeriod = intraRefreshPeriod;
2306    status_t err = mOMX->setConfig(
2307            mNode, (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, &params, sizeof(params));
2308    if (err == OK) {
2309        return OK;
2310    }
2311
2312    // Only in configure state, a component could invoke setParameter.
2313    if (!inConfigure) {
2314        return INVALID_OPERATION;
2315    } else {
2316        ALOGI("[%s] try falling back to Cyclic", mComponentName.c_str());
2317    }
2318
2319    OMX_VIDEO_PARAM_INTRAREFRESHTYPE refreshParams;
2320    InitOMXParams(&refreshParams);
2321    refreshParams.nPortIndex = kPortIndexOutput;
2322    refreshParams.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic;
2323
2324    if (intraRefreshPeriod == 0) {
2325        // 0 means disable intra refresh.
2326        refreshParams.nCirMBs = 0;
2327    } else {
2328        // Calculate macroblocks that need to be intra coded base on width and height
2329        uint32_t width, height;
2330        OMX_PARAM_PORTDEFINITIONTYPE def;
2331        InitOMXParams(&def);
2332        OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
2333        def.nPortIndex = kPortIndexOutput;
2334        err = mOMX->getParameter(
2335                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2336        if (err != OK) {
2337            return err;
2338        }
2339        width = video_def->nFrameWidth;
2340        height = video_def->nFrameHeight;
2341        // Use H.264/AVC MacroBlock size 16x16
2342        refreshParams.nCirMBs = divUp((divUp(width, 16u) * divUp(height, 16u)), intraRefreshPeriod);
2343    }
2344
2345    err = mOMX->setParameter(mNode, OMX_IndexParamVideoIntraRefresh,
2346                             &refreshParams, sizeof(refreshParams));
2347    if (err != OK) {
2348        return err;
2349    }
2350
2351    return OK;
2352}
2353
2354status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) {
2355    OMX_PARAM_PORTDEFINITIONTYPE def;
2356    InitOMXParams(&def);
2357    def.nPortIndex = portIndex;
2358
2359    status_t err = mOMX->getParameter(
2360            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2361
2362    if (err != OK) {
2363        return err;
2364    }
2365
2366    if (def.nBufferSize >= size) {
2367        return OK;
2368    }
2369
2370    def.nBufferSize = size;
2371
2372    err = mOMX->setParameter(
2373            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2374
2375    if (err != OK) {
2376        return err;
2377    }
2378
2379    err = mOMX->getParameter(
2380            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2381
2382    if (err != OK) {
2383        return err;
2384    }
2385
2386    if (def.nBufferSize < size) {
2387        ALOGE("failed to set min buffer size to %zu (is still %u)", size, def.nBufferSize);
2388        return FAILED_TRANSACTION;
2389    }
2390
2391    return OK;
2392}
2393
2394status_t ACodec::selectAudioPortFormat(
2395        OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) {
2396    OMX_AUDIO_PARAM_PORTFORMATTYPE format;
2397    InitOMXParams(&format);
2398
2399    format.nPortIndex = portIndex;
2400    for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
2401        format.nIndex = index;
2402        status_t err = mOMX->getParameter(
2403                mNode, OMX_IndexParamAudioPortFormat,
2404                &format, sizeof(format));
2405
2406        if (err != OK) {
2407            return err;
2408        }
2409
2410        if (format.eEncoding == desiredFormat) {
2411            break;
2412        }
2413
2414        if (index == kMaxIndicesToCheck) {
2415            ALOGW("[%s] stopping checking formats after %u: %s(%x)",
2416                    mComponentName.c_str(), index,
2417                    asString(format.eEncoding), format.eEncoding);
2418            return ERROR_UNSUPPORTED;
2419        }
2420    }
2421
2422    return mOMX->setParameter(
2423            mNode, OMX_IndexParamAudioPortFormat, &format, sizeof(format));
2424}
2425
2426status_t ACodec::setupAACCodec(
2427        bool encoder, int32_t numChannels, int32_t sampleRate,
2428        int32_t bitRate, int32_t aacProfile, bool isADTS, int32_t sbrMode,
2429        int32_t maxOutputChannelCount, const drcParams_t& drc,
2430        int32_t pcmLimiterEnable) {
2431    if (encoder && isADTS) {
2432        return -EINVAL;
2433    }
2434
2435    status_t err = setupRawAudioFormat(
2436            encoder ? kPortIndexInput : kPortIndexOutput,
2437            sampleRate,
2438            numChannels);
2439
2440    if (err != OK) {
2441        return err;
2442    }
2443
2444    if (encoder) {
2445        err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC);
2446
2447        if (err != OK) {
2448            return err;
2449        }
2450
2451        OMX_PARAM_PORTDEFINITIONTYPE def;
2452        InitOMXParams(&def);
2453        def.nPortIndex = kPortIndexOutput;
2454
2455        err = mOMX->getParameter(
2456                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2457
2458        if (err != OK) {
2459            return err;
2460        }
2461
2462        def.format.audio.bFlagErrorConcealment = OMX_TRUE;
2463        def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
2464
2465        err = mOMX->setParameter(
2466                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2467
2468        if (err != OK) {
2469            return err;
2470        }
2471
2472        OMX_AUDIO_PARAM_AACPROFILETYPE profile;
2473        InitOMXParams(&profile);
2474        profile.nPortIndex = kPortIndexOutput;
2475
2476        err = mOMX->getParameter(
2477                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
2478
2479        if (err != OK) {
2480            return err;
2481        }
2482
2483        profile.nChannels = numChannels;
2484
2485        profile.eChannelMode =
2486            (numChannels == 1)
2487                ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo;
2488
2489        profile.nSampleRate = sampleRate;
2490        profile.nBitRate = bitRate;
2491        profile.nAudioBandWidth = 0;
2492        profile.nFrameLength = 0;
2493        profile.nAACtools = OMX_AUDIO_AACToolAll;
2494        profile.nAACERtools = OMX_AUDIO_AACERNone;
2495        profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile;
2496        profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
2497        switch (sbrMode) {
2498        case 0:
2499            // disable sbr
2500            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
2501            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
2502            break;
2503        case 1:
2504            // enable single-rate sbr
2505            profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
2506            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
2507            break;
2508        case 2:
2509            // enable dual-rate sbr
2510            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
2511            profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
2512            break;
2513        case -1:
2514            // enable both modes -> the codec will decide which mode should be used
2515            profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
2516            profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
2517            break;
2518        default:
2519            // unsupported sbr mode
2520            return BAD_VALUE;
2521        }
2522
2523
2524        err = mOMX->setParameter(
2525                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
2526
2527        if (err != OK) {
2528            return err;
2529        }
2530
2531        return err;
2532    }
2533
2534    OMX_AUDIO_PARAM_AACPROFILETYPE profile;
2535    InitOMXParams(&profile);
2536    profile.nPortIndex = kPortIndexInput;
2537
2538    err = mOMX->getParameter(
2539            mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
2540
2541    if (err != OK) {
2542        return err;
2543    }
2544
2545    profile.nChannels = numChannels;
2546    profile.nSampleRate = sampleRate;
2547
2548    profile.eAACStreamFormat =
2549        isADTS
2550            ? OMX_AUDIO_AACStreamFormatMP4ADTS
2551            : OMX_AUDIO_AACStreamFormatMP4FF;
2552
2553    OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE presentation;
2554    presentation.nMaxOutputChannels = maxOutputChannelCount;
2555    presentation.nDrcCut = drc.drcCut;
2556    presentation.nDrcBoost = drc.drcBoost;
2557    presentation.nHeavyCompression = drc.heavyCompression;
2558    presentation.nTargetReferenceLevel = drc.targetRefLevel;
2559    presentation.nEncodedTargetLevel = drc.encodedTargetLevel;
2560    presentation.nPCMLimiterEnable = pcmLimiterEnable;
2561
2562    status_t res = mOMX->setParameter(mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
2563    if (res == OK) {
2564        // optional parameters, will not cause configuration failure
2565        mOMX->setParameter(mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacPresentation,
2566                &presentation, sizeof(presentation));
2567    } else {
2568        ALOGW("did not set AudioAndroidAacPresentation due to error %d when setting AudioAac", res);
2569    }
2570    return res;
2571}
2572
2573status_t ACodec::setupAC3Codec(
2574        bool encoder, int32_t numChannels, int32_t sampleRate) {
2575    status_t err = setupRawAudioFormat(
2576            encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
2577
2578    if (err != OK) {
2579        return err;
2580    }
2581
2582    if (encoder) {
2583        ALOGW("AC3 encoding is not supported.");
2584        return INVALID_OPERATION;
2585    }
2586
2587    OMX_AUDIO_PARAM_ANDROID_AC3TYPE def;
2588    InitOMXParams(&def);
2589    def.nPortIndex = kPortIndexInput;
2590
2591    err = mOMX->getParameter(
2592            mNode,
2593            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
2594            &def,
2595            sizeof(def));
2596
2597    if (err != OK) {
2598        return err;
2599    }
2600
2601    def.nChannels = numChannels;
2602    def.nSampleRate = sampleRate;
2603
2604    return mOMX->setParameter(
2605            mNode,
2606            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
2607            &def,
2608            sizeof(def));
2609}
2610
2611status_t ACodec::setupEAC3Codec(
2612        bool encoder, int32_t numChannels, int32_t sampleRate) {
2613    status_t err = setupRawAudioFormat(
2614            encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
2615
2616    if (err != OK) {
2617        return err;
2618    }
2619
2620    if (encoder) {
2621        ALOGW("EAC3 encoding is not supported.");
2622        return INVALID_OPERATION;
2623    }
2624
2625    OMX_AUDIO_PARAM_ANDROID_EAC3TYPE def;
2626    InitOMXParams(&def);
2627    def.nPortIndex = kPortIndexInput;
2628
2629    err = mOMX->getParameter(
2630            mNode,
2631            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
2632            &def,
2633            sizeof(def));
2634
2635    if (err != OK) {
2636        return err;
2637    }
2638
2639    def.nChannels = numChannels;
2640    def.nSampleRate = sampleRate;
2641
2642    return mOMX->setParameter(
2643            mNode,
2644            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
2645            &def,
2646            sizeof(def));
2647}
2648
2649static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(
2650        bool isAMRWB, int32_t bps) {
2651    if (isAMRWB) {
2652        if (bps <= 6600) {
2653            return OMX_AUDIO_AMRBandModeWB0;
2654        } else if (bps <= 8850) {
2655            return OMX_AUDIO_AMRBandModeWB1;
2656        } else if (bps <= 12650) {
2657            return OMX_AUDIO_AMRBandModeWB2;
2658        } else if (bps <= 14250) {
2659            return OMX_AUDIO_AMRBandModeWB3;
2660        } else if (bps <= 15850) {
2661            return OMX_AUDIO_AMRBandModeWB4;
2662        } else if (bps <= 18250) {
2663            return OMX_AUDIO_AMRBandModeWB5;
2664        } else if (bps <= 19850) {
2665            return OMX_AUDIO_AMRBandModeWB6;
2666        } else if (bps <= 23050) {
2667            return OMX_AUDIO_AMRBandModeWB7;
2668        }
2669
2670        // 23850 bps
2671        return OMX_AUDIO_AMRBandModeWB8;
2672    } else {  // AMRNB
2673        if (bps <= 4750) {
2674            return OMX_AUDIO_AMRBandModeNB0;
2675        } else if (bps <= 5150) {
2676            return OMX_AUDIO_AMRBandModeNB1;
2677        } else if (bps <= 5900) {
2678            return OMX_AUDIO_AMRBandModeNB2;
2679        } else if (bps <= 6700) {
2680            return OMX_AUDIO_AMRBandModeNB3;
2681        } else if (bps <= 7400) {
2682            return OMX_AUDIO_AMRBandModeNB4;
2683        } else if (bps <= 7950) {
2684            return OMX_AUDIO_AMRBandModeNB5;
2685        } else if (bps <= 10200) {
2686            return OMX_AUDIO_AMRBandModeNB6;
2687        }
2688
2689        // 12200 bps
2690        return OMX_AUDIO_AMRBandModeNB7;
2691    }
2692}
2693
2694status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) {
2695    OMX_AUDIO_PARAM_AMRTYPE def;
2696    InitOMXParams(&def);
2697    def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput;
2698
2699    status_t err =
2700        mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
2701
2702    if (err != OK) {
2703        return err;
2704    }
2705
2706    def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
2707    def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate);
2708
2709    err = mOMX->setParameter(
2710            mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
2711
2712    if (err != OK) {
2713        return err;
2714    }
2715
2716    return setupRawAudioFormat(
2717            encoder ? kPortIndexInput : kPortIndexOutput,
2718            isWAMR ? 16000 : 8000 /* sampleRate */,
2719            1 /* numChannels */);
2720}
2721
2722status_t ACodec::setupG711Codec(bool encoder, int32_t sampleRate, int32_t numChannels) {
2723    if (encoder) {
2724        return INVALID_OPERATION;
2725    }
2726
2727    return setupRawAudioFormat(
2728            kPortIndexInput, sampleRate, numChannels);
2729}
2730
2731status_t ACodec::setupFlacCodec(
2732        bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel) {
2733
2734    if (encoder) {
2735        OMX_AUDIO_PARAM_FLACTYPE def;
2736        InitOMXParams(&def);
2737        def.nPortIndex = kPortIndexOutput;
2738
2739        // configure compression level
2740        status_t err = mOMX->getParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def));
2741        if (err != OK) {
2742            ALOGE("setupFlacCodec(): Error %d getting OMX_IndexParamAudioFlac parameter", err);
2743            return err;
2744        }
2745        def.nCompressionLevel = compressionLevel;
2746        err = mOMX->setParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def));
2747        if (err != OK) {
2748            ALOGE("setupFlacCodec(): Error %d setting OMX_IndexParamAudioFlac parameter", err);
2749            return err;
2750        }
2751    }
2752
2753    return setupRawAudioFormat(
2754            encoder ? kPortIndexInput : kPortIndexOutput,
2755            sampleRate,
2756            numChannels);
2757}
2758
2759status_t ACodec::setupRawAudioFormat(
2760        OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
2761    OMX_PARAM_PORTDEFINITIONTYPE def;
2762    InitOMXParams(&def);
2763    def.nPortIndex = portIndex;
2764
2765    status_t err = mOMX->getParameter(
2766            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2767
2768    if (err != OK) {
2769        return err;
2770    }
2771
2772    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
2773
2774    err = mOMX->setParameter(
2775            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2776
2777    if (err != OK) {
2778        return err;
2779    }
2780
2781    OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
2782    InitOMXParams(&pcmParams);
2783    pcmParams.nPortIndex = portIndex;
2784
2785    err = mOMX->getParameter(
2786            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
2787
2788    if (err != OK) {
2789        return err;
2790    }
2791
2792    pcmParams.nChannels = numChannels;
2793    pcmParams.eNumData = OMX_NumericalDataSigned;
2794    pcmParams.bInterleaved = OMX_TRUE;
2795    pcmParams.nBitPerSample = 16;
2796    pcmParams.nSamplingRate = sampleRate;
2797    pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
2798
2799    if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) {
2800        return OMX_ErrorNone;
2801    }
2802
2803    return mOMX->setParameter(
2804            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
2805}
2806
2807status_t ACodec::configureTunneledVideoPlayback(
2808        int32_t audioHwSync, const sp<ANativeWindow> &nativeWindow) {
2809    native_handle_t* sidebandHandle;
2810
2811    status_t err = mOMX->configureVideoTunnelMode(
2812            mNode, kPortIndexOutput, OMX_TRUE, audioHwSync, &sidebandHandle);
2813    if (err != OK) {
2814        ALOGE("configureVideoTunnelMode failed! (err %d).", err);
2815        return err;
2816    }
2817
2818    err = native_window_set_sideband_stream(nativeWindow.get(), sidebandHandle);
2819    if (err != OK) {
2820        ALOGE("native_window_set_sideband_stream(%p) failed! (err %d).",
2821                sidebandHandle, err);
2822        return err;
2823    }
2824
2825    return OK;
2826}
2827
2828status_t ACodec::setVideoPortFormatType(
2829        OMX_U32 portIndex,
2830        OMX_VIDEO_CODINGTYPE compressionFormat,
2831        OMX_COLOR_FORMATTYPE colorFormat,
2832        bool usingNativeBuffers) {
2833    OMX_VIDEO_PARAM_PORTFORMATTYPE format;
2834    InitOMXParams(&format);
2835    format.nPortIndex = portIndex;
2836    format.nIndex = 0;
2837    bool found = false;
2838
2839    for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
2840        format.nIndex = index;
2841        status_t err = mOMX->getParameter(
2842                mNode, OMX_IndexParamVideoPortFormat,
2843                &format, sizeof(format));
2844
2845        if (err != OK) {
2846            return err;
2847        }
2848
2849        // substitute back flexible color format to codec supported format
2850        OMX_U32 flexibleEquivalent;
2851        if (compressionFormat == OMX_VIDEO_CodingUnused
2852                && isFlexibleColorFormat(
2853                        mOMX, mNode, format.eColorFormat, usingNativeBuffers, &flexibleEquivalent)
2854                && colorFormat == flexibleEquivalent) {
2855            ALOGI("[%s] using color format %#x in place of %#x",
2856                    mComponentName.c_str(), format.eColorFormat, colorFormat);
2857            colorFormat = format.eColorFormat;
2858        }
2859
2860        // The following assertion is violated by TI's video decoder.
2861        // CHECK_EQ(format.nIndex, index);
2862
2863        if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) {
2864            if (portIndex == kPortIndexInput
2865                    && colorFormat == format.eColorFormat) {
2866                // eCompressionFormat does not seem right.
2867                found = true;
2868                break;
2869            }
2870            if (portIndex == kPortIndexOutput
2871                    && compressionFormat == format.eCompressionFormat) {
2872                // eColorFormat does not seem right.
2873                found = true;
2874                break;
2875            }
2876        }
2877
2878        if (format.eCompressionFormat == compressionFormat
2879            && format.eColorFormat == colorFormat) {
2880            found = true;
2881            break;
2882        }
2883
2884        if (index == kMaxIndicesToCheck) {
2885            ALOGW("[%s] stopping checking formats after %u: %s(%x)/%s(%x)",
2886                    mComponentName.c_str(), index,
2887                    asString(format.eCompressionFormat), format.eCompressionFormat,
2888                    asString(format.eColorFormat), format.eColorFormat);
2889        }
2890    }
2891
2892    if (!found) {
2893        return UNKNOWN_ERROR;
2894    }
2895
2896    status_t err = mOMX->setParameter(
2897            mNode, OMX_IndexParamVideoPortFormat,
2898            &format, sizeof(format));
2899
2900    return err;
2901}
2902
2903// Set optimal output format. OMX component lists output formats in the order
2904// of preference, but this got more complicated since the introduction of flexible
2905// YUV formats. We support a legacy behavior for applications that do not use
2906// surface output, do not specify an output format, but expect a "usable" standard
2907// OMX format. SW readable and standard formats must be flex-YUV.
2908//
2909// Suggested preference order:
2910// - optimal format for texture rendering (mediaplayer behavior)
2911// - optimal SW readable & texture renderable format (flex-YUV support)
2912// - optimal SW readable non-renderable format (flex-YUV bytebuffer support)
2913// - legacy "usable" standard formats
2914//
2915// For legacy support, we prefer a standard format, but will settle for a SW readable
2916// flex-YUV format.
2917status_t ACodec::setSupportedOutputFormat(bool getLegacyFlexibleFormat) {
2918    OMX_VIDEO_PARAM_PORTFORMATTYPE format, legacyFormat;
2919    InitOMXParams(&format);
2920    format.nPortIndex = kPortIndexOutput;
2921
2922    InitOMXParams(&legacyFormat);
2923    // this field will change when we find a suitable legacy format
2924    legacyFormat.eColorFormat = OMX_COLOR_FormatUnused;
2925
2926    for (OMX_U32 index = 0; ; ++index) {
2927        format.nIndex = index;
2928        status_t err = mOMX->getParameter(
2929                mNode, OMX_IndexParamVideoPortFormat,
2930                &format, sizeof(format));
2931        if (err != OK) {
2932            // no more formats, pick legacy format if found
2933            if (legacyFormat.eColorFormat != OMX_COLOR_FormatUnused) {
2934                 memcpy(&format, &legacyFormat, sizeof(format));
2935                 break;
2936            }
2937            return err;
2938        }
2939        if (format.eCompressionFormat != OMX_VIDEO_CodingUnused) {
2940            return OMX_ErrorBadParameter;
2941        }
2942        if (!getLegacyFlexibleFormat) {
2943            break;
2944        }
2945        // standard formats that were exposed to users before
2946        if (format.eColorFormat == OMX_COLOR_FormatYUV420Planar
2947                || format.eColorFormat == OMX_COLOR_FormatYUV420PackedPlanar
2948                || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
2949                || format.eColorFormat == OMX_COLOR_FormatYUV420PackedSemiPlanar
2950                || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar) {
2951            break;
2952        }
2953        // find best legacy non-standard format
2954        OMX_U32 flexibleEquivalent;
2955        if (legacyFormat.eColorFormat == OMX_COLOR_FormatUnused
2956                && isFlexibleColorFormat(
2957                        mOMX, mNode, format.eColorFormat, false /* usingNativeBuffers */,
2958                        &flexibleEquivalent)
2959                && flexibleEquivalent == OMX_COLOR_FormatYUV420Flexible) {
2960            memcpy(&legacyFormat, &format, sizeof(format));
2961        }
2962    }
2963    return mOMX->setParameter(
2964            mNode, OMX_IndexParamVideoPortFormat,
2965            &format, sizeof(format));
2966}
2967
2968static const struct VideoCodingMapEntry {
2969    const char *mMime;
2970    OMX_VIDEO_CODINGTYPE mVideoCodingType;
2971} kVideoCodingMapEntry[] = {
2972    { MEDIA_MIMETYPE_VIDEO_AVC, OMX_VIDEO_CodingAVC },
2973    { MEDIA_MIMETYPE_VIDEO_HEVC, OMX_VIDEO_CodingHEVC },
2974    { MEDIA_MIMETYPE_VIDEO_MPEG4, OMX_VIDEO_CodingMPEG4 },
2975    { MEDIA_MIMETYPE_VIDEO_H263, OMX_VIDEO_CodingH263 },
2976    { MEDIA_MIMETYPE_VIDEO_MPEG2, OMX_VIDEO_CodingMPEG2 },
2977    { MEDIA_MIMETYPE_VIDEO_VP8, OMX_VIDEO_CodingVP8 },
2978    { MEDIA_MIMETYPE_VIDEO_VP9, OMX_VIDEO_CodingVP9 },
2979    { MEDIA_MIMETYPE_VIDEO_DOLBY_VISION, OMX_VIDEO_CodingDolbyVision },
2980};
2981
2982static status_t GetVideoCodingTypeFromMime(
2983        const char *mime, OMX_VIDEO_CODINGTYPE *codingType) {
2984    for (size_t i = 0;
2985         i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
2986         ++i) {
2987        if (!strcasecmp(mime, kVideoCodingMapEntry[i].mMime)) {
2988            *codingType = kVideoCodingMapEntry[i].mVideoCodingType;
2989            return OK;
2990        }
2991    }
2992
2993    *codingType = OMX_VIDEO_CodingUnused;
2994
2995    return ERROR_UNSUPPORTED;
2996}
2997
2998static status_t GetMimeTypeForVideoCoding(
2999        OMX_VIDEO_CODINGTYPE codingType, AString *mime) {
3000    for (size_t i = 0;
3001         i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
3002         ++i) {
3003        if (codingType == kVideoCodingMapEntry[i].mVideoCodingType) {
3004            *mime = kVideoCodingMapEntry[i].mMime;
3005            return OK;
3006        }
3007    }
3008
3009    mime->clear();
3010
3011    return ERROR_UNSUPPORTED;
3012}
3013
3014status_t ACodec::setupVideoDecoder(
3015        const char *mime, const sp<AMessage> &msg, bool haveNativeWindow,
3016        sp<AMessage> &outputFormat) {
3017    int32_t width, height;
3018    if (!msg->findInt32("width", &width)
3019            || !msg->findInt32("height", &height)) {
3020        return INVALID_OPERATION;
3021    }
3022
3023    OMX_VIDEO_CODINGTYPE compressionFormat;
3024    status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
3025
3026    if (err != OK) {
3027        return err;
3028    }
3029
3030    err = setVideoPortFormatType(
3031            kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
3032
3033    if (err != OK) {
3034        return err;
3035    }
3036
3037    int32_t tmp;
3038    if (msg->findInt32("color-format", &tmp)) {
3039        OMX_COLOR_FORMATTYPE colorFormat =
3040            static_cast<OMX_COLOR_FORMATTYPE>(tmp);
3041        err = setVideoPortFormatType(
3042                kPortIndexOutput, OMX_VIDEO_CodingUnused, colorFormat, haveNativeWindow);
3043        if (err != OK) {
3044            ALOGW("[%s] does not support color format %d",
3045                  mComponentName.c_str(), colorFormat);
3046            err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */);
3047        }
3048    } else {
3049        err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */);
3050    }
3051
3052    if (err != OK) {
3053        return err;
3054    }
3055
3056    int32_t frameRateInt;
3057    float frameRateFloat;
3058    if (!msg->findFloat("frame-rate", &frameRateFloat)) {
3059        if (!msg->findInt32("frame-rate", &frameRateInt)) {
3060            frameRateInt = -1;
3061        }
3062        frameRateFloat = (float)frameRateInt;
3063    }
3064
3065    err = setVideoFormatOnPort(
3066            kPortIndexInput, width, height, compressionFormat, frameRateFloat);
3067
3068    if (err != OK) {
3069        return err;
3070    }
3071
3072    err = setVideoFormatOnPort(
3073            kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused);
3074
3075    if (err != OK) {
3076        return err;
3077    }
3078
3079    err = setColorAspects(
3080            kPortIndexOutput, width, height, msg, outputFormat);
3081    if (err != OK) {
3082        ALOGI("Falling back to presets as component does not describe color aspects.");
3083        err = OK;
3084    }
3085
3086    return err;
3087}
3088
3089status_t ACodec::setColorAspects(
3090        OMX_U32 portIndex, int32_t width, int32_t height, const sp<AMessage> &msg,
3091        sp<AMessage> &format) {
3092    DescribeColorAspectsParams params;
3093    InitOMXParams(&params);
3094    params.nPortIndex = portIndex;
3095
3096    // 0 values are unspecified
3097    int32_t range = 0, standard = 0, transfer = 0;
3098    if (portIndex == kPortIndexInput) {
3099        // Encoders allow overriding default aspects with 0 if specified by format. Decoders do not.
3100        setDefaultPlatformColorAspectsIfNeeded(range, standard, transfer, width, height);
3101    }
3102    (void)msg->findInt32("color-range", &range);
3103    (void)msg->findInt32("color-standard", &standard);
3104    (void)msg->findInt32("color-transfer", &transfer);
3105
3106    if (convertPlatformColorAspectsToCodecAspects(
3107            range, standard, transfer, params.sAspects) != OK) {
3108        ALOGW("[%s] Ignoring illegal color aspects(range=%d, standard=%d, transfer=%d)",
3109                mComponentName.c_str(), range, standard, transfer);
3110        // Invalid values were converted to unspecified !params!, but otherwise were not changed
3111        // For encoders, we leave these as is. For decoders, we will use default values.
3112    }
3113
3114    // set defaults for decoders.
3115    if (portIndex != kPortIndexInput) {
3116        setDefaultCodecColorAspectsIfNeeded(params.sAspects, width, height);
3117        convertCodecColorAspectsToPlatformAspects(params.sAspects, &range, &standard, &transfer);
3118    }
3119
3120    // save updated values to base output format (encoder input format will read back actually
3121    // supported values by the codec)
3122    if (range != 0) {
3123        format->setInt32("color-range", range);
3124    }
3125    if (standard != 0) {
3126        format->setInt32("color-standard", standard);
3127    }
3128    if (transfer != 0) {
3129        format->setInt32("color-transfer", transfer);
3130    }
3131
3132    // communicate color aspects to codec
3133    status_t err = mOMX->getExtensionIndex(
3134            mNode, "OMX.google.android.index.describeColorAspects", &mDescribeColorAspectsIndex);
3135    if (err != OK) {
3136        mDescribeColorAspectsIndex = (OMX_INDEXTYPE)0;
3137        return err;
3138    }
3139
3140    return mOMX->setConfig(mNode, mDescribeColorAspectsIndex, &params, sizeof(params));
3141}
3142
3143status_t ACodec::getColorAspects(OMX_U32 portIndex, sp<AMessage> &format) {
3144    if (!mDescribeColorAspectsIndex) {
3145        return ERROR_UNSUPPORTED;
3146    }
3147
3148    DescribeColorAspectsParams params;
3149    InitOMXParams(&params);
3150    params.nPortIndex = portIndex;
3151    ColorAspects &aspects = params.sAspects;
3152    aspects.mRange = ColorAspects::RangeUnspecified;
3153    aspects.mPrimaries = ColorAspects::PrimariesUnspecified;
3154    aspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
3155    aspects.mTransfer = ColorAspects::TransferUnspecified;
3156
3157    status_t err = mOMX->getConfig(mNode, mDescribeColorAspectsIndex, &params, sizeof(params));
3158    if (err != OK) {
3159        return err;
3160    }
3161
3162    // keep non-standard codec values in extension ranges
3163    int32_t range, standard, transfer;
3164    if (convertCodecColorAspectsToPlatformAspects(
3165            params.sAspects, &range, &standard, &transfer) != OK) {
3166        ALOGW("[%s] Ignoring invalid color aspects(range=%u, primaries=%u, coeffs=%u, transfer=%u)",
3167                mComponentName.c_str(),
3168                aspects.mRange, aspects.mPrimaries, aspects.mMatrixCoeffs, aspects.mTransfer);
3169    }
3170
3171    // save specified values to format
3172    if (range != 0) {
3173        format->setInt32("color-range", range);
3174    }
3175    if (standard != 0) {
3176        format->setInt32("color-standard", standard);
3177    }
3178    if (transfer != 0) {
3179        format->setInt32("color-transfer", transfer);
3180    }
3181    return OK;
3182}
3183
3184status_t ACodec::setupVideoEncoder(
3185        const char *mime, const sp<AMessage> &msg, sp<AMessage> &outputFormat) {
3186    int32_t tmp;
3187    if (!msg->findInt32("color-format", &tmp)) {
3188        return INVALID_OPERATION;
3189    }
3190
3191    OMX_COLOR_FORMATTYPE colorFormat =
3192        static_cast<OMX_COLOR_FORMATTYPE>(tmp);
3193
3194    status_t err = setVideoPortFormatType(
3195            kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat);
3196
3197    if (err != OK) {
3198        ALOGE("[%s] does not support color format %d",
3199              mComponentName.c_str(), colorFormat);
3200
3201        return err;
3202    }
3203
3204    /* Input port configuration */
3205
3206    OMX_PARAM_PORTDEFINITIONTYPE def;
3207    InitOMXParams(&def);
3208
3209    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
3210
3211    def.nPortIndex = kPortIndexInput;
3212
3213    err = mOMX->getParameter(
3214            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3215
3216    if (err != OK) {
3217        return err;
3218    }
3219
3220    int32_t width, height, bitrate;
3221    if (!msg->findInt32("width", &width)
3222            || !msg->findInt32("height", &height)
3223            || !msg->findInt32("bitrate", &bitrate)) {
3224        return INVALID_OPERATION;
3225    }
3226
3227    video_def->nFrameWidth = width;
3228    video_def->nFrameHeight = height;
3229
3230    int32_t stride;
3231    if (!msg->findInt32("stride", &stride)) {
3232        stride = width;
3233    }
3234
3235    video_def->nStride = stride;
3236
3237    int32_t sliceHeight;
3238    if (!msg->findInt32("slice-height", &sliceHeight)) {
3239        sliceHeight = height;
3240    }
3241
3242    video_def->nSliceHeight = sliceHeight;
3243
3244    def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2;
3245
3246    float frameRate;
3247    if (!msg->findFloat("frame-rate", &frameRate)) {
3248        int32_t tmp;
3249        if (!msg->findInt32("frame-rate", &tmp)) {
3250            return INVALID_OPERATION;
3251        }
3252        frameRate = (float)tmp;
3253        mTimePerFrameUs = (int64_t) (1000000.0f / frameRate);
3254    }
3255
3256    video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
3257    video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
3258    // this is redundant as it was already set up in setVideoPortFormatType
3259    // FIXME for now skip this only for flexible YUV formats
3260    if (colorFormat != OMX_COLOR_FormatYUV420Flexible) {
3261        video_def->eColorFormat = colorFormat;
3262    }
3263
3264    err = mOMX->setParameter(
3265            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3266
3267    if (err != OK) {
3268        ALOGE("[%s] failed to set input port definition parameters.",
3269              mComponentName.c_str());
3270
3271        return err;
3272    }
3273
3274    /* Output port configuration */
3275
3276    OMX_VIDEO_CODINGTYPE compressionFormat;
3277    err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
3278
3279    if (err != OK) {
3280        return err;
3281    }
3282
3283    err = setVideoPortFormatType(
3284            kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused);
3285
3286    if (err != OK) {
3287        ALOGE("[%s] does not support compression format %d",
3288             mComponentName.c_str(), compressionFormat);
3289
3290        return err;
3291    }
3292
3293    def.nPortIndex = kPortIndexOutput;
3294
3295    err = mOMX->getParameter(
3296            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3297
3298    if (err != OK) {
3299        return err;
3300    }
3301
3302    video_def->nFrameWidth = width;
3303    video_def->nFrameHeight = height;
3304    video_def->xFramerate = 0;
3305    video_def->nBitrate = bitrate;
3306    video_def->eCompressionFormat = compressionFormat;
3307    video_def->eColorFormat = OMX_COLOR_FormatUnused;
3308
3309    err = mOMX->setParameter(
3310            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3311
3312    if (err != OK) {
3313        ALOGE("[%s] failed to set output port definition parameters.",
3314              mComponentName.c_str());
3315
3316        return err;
3317    }
3318
3319    int32_t intraRefreshPeriod = 0;
3320    if (msg->findInt32("intra-refresh-period", &intraRefreshPeriod)
3321            && intraRefreshPeriod >= 0) {
3322        err = setIntraRefreshPeriod((uint32_t)intraRefreshPeriod, true);
3323        if (err != OK) {
3324            ALOGI("[%s] failed setIntraRefreshPeriod. Failure is fine since this key is optional",
3325                    mComponentName.c_str());
3326            err = OK;
3327        }
3328    }
3329
3330    switch (compressionFormat) {
3331        case OMX_VIDEO_CodingMPEG4:
3332            err = setupMPEG4EncoderParameters(msg);
3333            break;
3334
3335        case OMX_VIDEO_CodingH263:
3336            err = setupH263EncoderParameters(msg);
3337            break;
3338
3339        case OMX_VIDEO_CodingAVC:
3340            err = setupAVCEncoderParameters(msg);
3341            break;
3342
3343        case OMX_VIDEO_CodingHEVC:
3344            err = setupHEVCEncoderParameters(msg);
3345            break;
3346
3347        case OMX_VIDEO_CodingVP8:
3348        case OMX_VIDEO_CodingVP9:
3349            err = setupVPXEncoderParameters(msg);
3350            break;
3351
3352        default:
3353            break;
3354    }
3355
3356    // Set up color aspects on input, but propagate them to the output format, as they will
3357    // not be read back from encoder.
3358    err = setColorAspects(
3359            kPortIndexInput, width, height, msg, outputFormat);
3360    if (err != OK) {
3361        ALOGI("[%s] cannot encode color aspects. Ignoring.", mComponentName.c_str());
3362        err = OK;
3363    }
3364
3365    if (err == OK) {
3366        ALOGI("setupVideoEncoder succeeded");
3367    }
3368
3369    return err;
3370}
3371
3372status_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) {
3373    OMX_VIDEO_PARAM_INTRAREFRESHTYPE params;
3374    InitOMXParams(&params);
3375    params.nPortIndex = kPortIndexOutput;
3376
3377    params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode);
3378
3379    if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic ||
3380            params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
3381        int32_t mbs;
3382        if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) {
3383            return INVALID_OPERATION;
3384        }
3385        params.nCirMBs = mbs;
3386    }
3387
3388    if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive ||
3389            params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
3390        int32_t mbs;
3391        if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) {
3392            return INVALID_OPERATION;
3393        }
3394        params.nAirMBs = mbs;
3395
3396        int32_t ref;
3397        if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) {
3398            return INVALID_OPERATION;
3399        }
3400        params.nAirRef = ref;
3401    }
3402
3403    status_t err = mOMX->setParameter(
3404            mNode, OMX_IndexParamVideoIntraRefresh,
3405            &params, sizeof(params));
3406    return err;
3407}
3408
3409static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) {
3410    if (iFramesInterval < 0) {
3411        return 0xFFFFFFFF;
3412    } else if (iFramesInterval == 0) {
3413        return 0;
3414    }
3415    OMX_U32 ret = frameRate * iFramesInterval;
3416    return ret;
3417}
3418
3419static OMX_VIDEO_CONTROLRATETYPE getBitrateMode(const sp<AMessage> &msg) {
3420    int32_t tmp;
3421    if (!msg->findInt32("bitrate-mode", &tmp)) {
3422        return OMX_Video_ControlRateVariable;
3423    }
3424
3425    return static_cast<OMX_VIDEO_CONTROLRATETYPE>(tmp);
3426}
3427
3428status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) {
3429    int32_t bitrate, iFrameInterval;
3430    if (!msg->findInt32("bitrate", &bitrate)
3431            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
3432        return INVALID_OPERATION;
3433    }
3434
3435    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
3436
3437    float frameRate;
3438    if (!msg->findFloat("frame-rate", &frameRate)) {
3439        int32_t tmp;
3440        if (!msg->findInt32("frame-rate", &tmp)) {
3441            return INVALID_OPERATION;
3442        }
3443        frameRate = (float)tmp;
3444    }
3445
3446    OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
3447    InitOMXParams(&mpeg4type);
3448    mpeg4type.nPortIndex = kPortIndexOutput;
3449
3450    status_t err = mOMX->getParameter(
3451            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
3452
3453    if (err != OK) {
3454        return err;
3455    }
3456
3457    mpeg4type.nSliceHeaderSpacing = 0;
3458    mpeg4type.bSVH = OMX_FALSE;
3459    mpeg4type.bGov = OMX_FALSE;
3460
3461    mpeg4type.nAllowedPictureTypes =
3462        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
3463
3464    mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
3465    if (mpeg4type.nPFrames == 0) {
3466        mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
3467    }
3468    mpeg4type.nBFrames = 0;
3469    mpeg4type.nIDCVLCThreshold = 0;
3470    mpeg4type.bACPred = OMX_TRUE;
3471    mpeg4type.nMaxPacketSize = 256;
3472    mpeg4type.nTimeIncRes = 1000;
3473    mpeg4type.nHeaderExtension = 0;
3474    mpeg4type.bReversibleVLC = OMX_FALSE;
3475
3476    int32_t profile;
3477    if (msg->findInt32("profile", &profile)) {
3478        int32_t level;
3479        if (!msg->findInt32("level", &level)) {
3480            return INVALID_OPERATION;
3481        }
3482
3483        err = verifySupportForProfileAndLevel(profile, level);
3484
3485        if (err != OK) {
3486            return err;
3487        }
3488
3489        mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile);
3490        mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level);
3491    }
3492
3493    err = mOMX->setParameter(
3494            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
3495
3496    if (err != OK) {
3497        return err;
3498    }
3499
3500    err = configureBitrate(bitrate, bitrateMode);
3501
3502    if (err != OK) {
3503        return err;
3504    }
3505
3506    return setupErrorCorrectionParameters();
3507}
3508
3509status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) {
3510    int32_t bitrate, iFrameInterval;
3511    if (!msg->findInt32("bitrate", &bitrate)
3512            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
3513        return INVALID_OPERATION;
3514    }
3515
3516    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
3517
3518    float frameRate;
3519    if (!msg->findFloat("frame-rate", &frameRate)) {
3520        int32_t tmp;
3521        if (!msg->findInt32("frame-rate", &tmp)) {
3522            return INVALID_OPERATION;
3523        }
3524        frameRate = (float)tmp;
3525    }
3526
3527    OMX_VIDEO_PARAM_H263TYPE h263type;
3528    InitOMXParams(&h263type);
3529    h263type.nPortIndex = kPortIndexOutput;
3530
3531    status_t err = mOMX->getParameter(
3532            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
3533
3534    if (err != OK) {
3535        return err;
3536    }
3537
3538    h263type.nAllowedPictureTypes =
3539        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
3540
3541    h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
3542    if (h263type.nPFrames == 0) {
3543        h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
3544    }
3545    h263type.nBFrames = 0;
3546
3547    int32_t profile;
3548    if (msg->findInt32("profile", &profile)) {
3549        int32_t level;
3550        if (!msg->findInt32("level", &level)) {
3551            return INVALID_OPERATION;
3552        }
3553
3554        err = verifySupportForProfileAndLevel(profile, level);
3555
3556        if (err != OK) {
3557            return err;
3558        }
3559
3560        h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile);
3561        h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level);
3562    }
3563
3564    h263type.bPLUSPTYPEAllowed = OMX_FALSE;
3565    h263type.bForceRoundingTypeToZero = OMX_FALSE;
3566    h263type.nPictureHeaderRepetition = 0;
3567    h263type.nGOBHeaderInterval = 0;
3568
3569    err = mOMX->setParameter(
3570            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
3571
3572    if (err != OK) {
3573        return err;
3574    }
3575
3576    err = configureBitrate(bitrate, bitrateMode);
3577
3578    if (err != OK) {
3579        return err;
3580    }
3581
3582    return setupErrorCorrectionParameters();
3583}
3584
3585// static
3586int /* OMX_VIDEO_AVCLEVELTYPE */ ACodec::getAVCLevelFor(
3587        int width, int height, int rate, int bitrate,
3588        OMX_VIDEO_AVCPROFILETYPE profile) {
3589    // convert bitrate to main/baseline profile kbps equivalent
3590    switch (profile) {
3591        case OMX_VIDEO_AVCProfileHigh10:
3592            bitrate = divUp(bitrate, 3000); break;
3593        case OMX_VIDEO_AVCProfileHigh:
3594            bitrate = divUp(bitrate, 1250); break;
3595        default:
3596            bitrate = divUp(bitrate, 1000); break;
3597    }
3598
3599    // convert size and rate to MBs
3600    width = divUp(width, 16);
3601    height = divUp(height, 16);
3602    int mbs = width * height;
3603    rate *= mbs;
3604    int maxDimension = max(width, height);
3605
3606    static const int limits[][5] = {
3607        /*   MBps     MB   dim  bitrate        level */
3608        {    1485,    99,  28,     64, OMX_VIDEO_AVCLevel1  },
3609        {    1485,    99,  28,    128, OMX_VIDEO_AVCLevel1b },
3610        {    3000,   396,  56,    192, OMX_VIDEO_AVCLevel11 },
3611        {    6000,   396,  56,    384, OMX_VIDEO_AVCLevel12 },
3612        {   11880,   396,  56,    768, OMX_VIDEO_AVCLevel13 },
3613        {   11880,   396,  56,   2000, OMX_VIDEO_AVCLevel2  },
3614        {   19800,   792,  79,   4000, OMX_VIDEO_AVCLevel21 },
3615        {   20250,  1620, 113,   4000, OMX_VIDEO_AVCLevel22 },
3616        {   40500,  1620, 113,  10000, OMX_VIDEO_AVCLevel3  },
3617        {  108000,  3600, 169,  14000, OMX_VIDEO_AVCLevel31 },
3618        {  216000,  5120, 202,  20000, OMX_VIDEO_AVCLevel32 },
3619        {  245760,  8192, 256,  20000, OMX_VIDEO_AVCLevel4  },
3620        {  245760,  8192, 256,  50000, OMX_VIDEO_AVCLevel41 },
3621        {  522240,  8704, 263,  50000, OMX_VIDEO_AVCLevel42 },
3622        {  589824, 22080, 420, 135000, OMX_VIDEO_AVCLevel5  },
3623        {  983040, 36864, 543, 240000, OMX_VIDEO_AVCLevel51 },
3624        { 2073600, 36864, 543, 240000, OMX_VIDEO_AVCLevel52 },
3625    };
3626
3627    for (size_t i = 0; i < ARRAY_SIZE(limits); i++) {
3628        const int (&limit)[5] = limits[i];
3629        if (rate <= limit[0] && mbs <= limit[1] && maxDimension <= limit[2]
3630                && bitrate <= limit[3]) {
3631            return limit[4];
3632        }
3633    }
3634    return 0;
3635}
3636
3637status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
3638    int32_t bitrate, iFrameInterval;
3639    if (!msg->findInt32("bitrate", &bitrate)
3640            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
3641        return INVALID_OPERATION;
3642    }
3643
3644    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
3645
3646    float frameRate;
3647    if (!msg->findFloat("frame-rate", &frameRate)) {
3648        int32_t tmp;
3649        if (!msg->findInt32("frame-rate", &tmp)) {
3650            return INVALID_OPERATION;
3651        }
3652        frameRate = (float)tmp;
3653    }
3654
3655    status_t err = OK;
3656    int32_t intraRefreshMode = 0;
3657    if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) {
3658        err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode);
3659        if (err != OK) {
3660            ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x",
3661                    err, intraRefreshMode);
3662            return err;
3663        }
3664    }
3665
3666    OMX_VIDEO_PARAM_AVCTYPE h264type;
3667    InitOMXParams(&h264type);
3668    h264type.nPortIndex = kPortIndexOutput;
3669
3670    err = mOMX->getParameter(
3671            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
3672
3673    if (err != OK) {
3674        return err;
3675    }
3676
3677    h264type.nAllowedPictureTypes =
3678        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
3679
3680    int32_t profile;
3681    if (msg->findInt32("profile", &profile)) {
3682        int32_t level;
3683        if (!msg->findInt32("level", &level)) {
3684            return INVALID_OPERATION;
3685        }
3686
3687        err = verifySupportForProfileAndLevel(profile, level);
3688
3689        if (err != OK) {
3690            return err;
3691        }
3692
3693        h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile);
3694        h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level);
3695    }
3696
3697    // XXX
3698    if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) {
3699        ALOGW("Use baseline profile instead of %d for AVC recording",
3700            h264type.eProfile);
3701        h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
3702    }
3703
3704    if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
3705        h264type.nSliceHeaderSpacing = 0;
3706        h264type.bUseHadamard = OMX_TRUE;
3707        h264type.nRefFrames = 1;
3708        h264type.nBFrames = 0;
3709        h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
3710        if (h264type.nPFrames == 0) {
3711            h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
3712        }
3713        h264type.nRefIdx10ActiveMinus1 = 0;
3714        h264type.nRefIdx11ActiveMinus1 = 0;
3715        h264type.bEntropyCodingCABAC = OMX_FALSE;
3716        h264type.bWeightedPPrediction = OMX_FALSE;
3717        h264type.bconstIpred = OMX_FALSE;
3718        h264type.bDirect8x8Inference = OMX_FALSE;
3719        h264type.bDirectSpatialTemporal = OMX_FALSE;
3720        h264type.nCabacInitIdc = 0;
3721    }
3722
3723    if (h264type.nBFrames != 0) {
3724        h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
3725    }
3726
3727    h264type.bEnableUEP = OMX_FALSE;
3728    h264type.bEnableFMO = OMX_FALSE;
3729    h264type.bEnableASO = OMX_FALSE;
3730    h264type.bEnableRS = OMX_FALSE;
3731    h264type.bFrameMBsOnly = OMX_TRUE;
3732    h264type.bMBAFF = OMX_FALSE;
3733    h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
3734
3735    err = mOMX->setParameter(
3736            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
3737
3738    if (err != OK) {
3739        return err;
3740    }
3741
3742    return configureBitrate(bitrate, bitrateMode);
3743}
3744
3745status_t ACodec::setupHEVCEncoderParameters(const sp<AMessage> &msg) {
3746    int32_t bitrate, iFrameInterval;
3747    if (!msg->findInt32("bitrate", &bitrate)
3748            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
3749        return INVALID_OPERATION;
3750    }
3751
3752    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
3753
3754    float frameRate;
3755    if (!msg->findFloat("frame-rate", &frameRate)) {
3756        int32_t tmp;
3757        if (!msg->findInt32("frame-rate", &tmp)) {
3758            return INVALID_OPERATION;
3759        }
3760        frameRate = (float)tmp;
3761    }
3762
3763    OMX_VIDEO_PARAM_HEVCTYPE hevcType;
3764    InitOMXParams(&hevcType);
3765    hevcType.nPortIndex = kPortIndexOutput;
3766
3767    status_t err = OK;
3768    err = mOMX->getParameter(
3769            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
3770    if (err != OK) {
3771        return err;
3772    }
3773
3774    int32_t profile;
3775    if (msg->findInt32("profile", &profile)) {
3776        int32_t level;
3777        if (!msg->findInt32("level", &level)) {
3778            return INVALID_OPERATION;
3779        }
3780
3781        err = verifySupportForProfileAndLevel(profile, level);
3782        if (err != OK) {
3783            return err;
3784        }
3785
3786        hevcType.eProfile = static_cast<OMX_VIDEO_HEVCPROFILETYPE>(profile);
3787        hevcType.eLevel = static_cast<OMX_VIDEO_HEVCLEVELTYPE>(level);
3788    }
3789    // TODO: finer control?
3790    hevcType.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate);
3791
3792    err = mOMX->setParameter(
3793            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
3794    if (err != OK) {
3795        return err;
3796    }
3797
3798    return configureBitrate(bitrate, bitrateMode);
3799}
3800
3801status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg) {
3802    int32_t bitrate;
3803    int32_t iFrameInterval = 0;
3804    size_t tsLayers = 0;
3805    OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE pattern =
3806        OMX_VIDEO_VPXTemporalLayerPatternNone;
3807    static const uint32_t kVp8LayerRateAlloction
3808        [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS]
3809        [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] = {
3810        {100, 100, 100},  // 1 layer
3811        { 60, 100, 100},  // 2 layers {60%, 40%}
3812        { 40,  60, 100},  // 3 layers {40%, 20%, 40%}
3813    };
3814    if (!msg->findInt32("bitrate", &bitrate)) {
3815        return INVALID_OPERATION;
3816    }
3817    msg->findInt32("i-frame-interval", &iFrameInterval);
3818
3819    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
3820
3821    float frameRate;
3822    if (!msg->findFloat("frame-rate", &frameRate)) {
3823        int32_t tmp;
3824        if (!msg->findInt32("frame-rate", &tmp)) {
3825            return INVALID_OPERATION;
3826        }
3827        frameRate = (float)tmp;
3828    }
3829
3830    AString tsSchema;
3831    if (msg->findString("ts-schema", &tsSchema)) {
3832        if (tsSchema == "webrtc.vp8.1-layer") {
3833            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
3834            tsLayers = 1;
3835        } else if (tsSchema == "webrtc.vp8.2-layer") {
3836            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
3837            tsLayers = 2;
3838        } else if (tsSchema == "webrtc.vp8.3-layer") {
3839            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
3840            tsLayers = 3;
3841        } else {
3842            ALOGW("Unsupported ts-schema [%s]", tsSchema.c_str());
3843        }
3844    }
3845
3846    OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
3847    InitOMXParams(&vp8type);
3848    vp8type.nPortIndex = kPortIndexOutput;
3849    status_t err = mOMX->getParameter(
3850            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
3851            &vp8type, sizeof(vp8type));
3852
3853    if (err == OK) {
3854        if (iFrameInterval > 0) {
3855            vp8type.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate);
3856        }
3857        vp8type.eTemporalPattern = pattern;
3858        vp8type.nTemporalLayerCount = tsLayers;
3859        if (tsLayers > 0) {
3860            for (size_t i = 0; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) {
3861                vp8type.nTemporalLayerBitrateRatio[i] =
3862                    kVp8LayerRateAlloction[tsLayers - 1][i];
3863            }
3864        }
3865        if (bitrateMode == OMX_Video_ControlRateConstant) {
3866            vp8type.nMinQuantizer = 2;
3867            vp8type.nMaxQuantizer = 63;
3868        }
3869
3870        err = mOMX->setParameter(
3871                mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
3872                &vp8type, sizeof(vp8type));
3873        if (err != OK) {
3874            ALOGW("Extended VP8 parameters set failed: %d", err);
3875        }
3876    }
3877
3878    return configureBitrate(bitrate, bitrateMode);
3879}
3880
3881status_t ACodec::verifySupportForProfileAndLevel(
3882        int32_t profile, int32_t level) {
3883    OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
3884    InitOMXParams(&params);
3885    params.nPortIndex = kPortIndexOutput;
3886
3887    for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
3888        params.nProfileIndex = index;
3889        status_t err = mOMX->getParameter(
3890                mNode,
3891                OMX_IndexParamVideoProfileLevelQuerySupported,
3892                &params,
3893                sizeof(params));
3894
3895        if (err != OK) {
3896            return err;
3897        }
3898
3899        int32_t supportedProfile = static_cast<int32_t>(params.eProfile);
3900        int32_t supportedLevel = static_cast<int32_t>(params.eLevel);
3901
3902        if (profile == supportedProfile && level <= supportedLevel) {
3903            return OK;
3904        }
3905
3906        if (index == kMaxIndicesToCheck) {
3907            ALOGW("[%s] stopping checking profiles after %u: %x/%x",
3908                    mComponentName.c_str(), index,
3909                    params.eProfile, params.eLevel);
3910        }
3911    }
3912    return ERROR_UNSUPPORTED;
3913}
3914
3915status_t ACodec::configureBitrate(
3916        int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode) {
3917    OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
3918    InitOMXParams(&bitrateType);
3919    bitrateType.nPortIndex = kPortIndexOutput;
3920
3921    status_t err = mOMX->getParameter(
3922            mNode, OMX_IndexParamVideoBitrate,
3923            &bitrateType, sizeof(bitrateType));
3924
3925    if (err != OK) {
3926        return err;
3927    }
3928
3929    bitrateType.eControlRate = bitrateMode;
3930    bitrateType.nTargetBitrate = bitrate;
3931
3932    return mOMX->setParameter(
3933            mNode, OMX_IndexParamVideoBitrate,
3934            &bitrateType, sizeof(bitrateType));
3935}
3936
3937status_t ACodec::setupErrorCorrectionParameters() {
3938    OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
3939    InitOMXParams(&errorCorrectionType);
3940    errorCorrectionType.nPortIndex = kPortIndexOutput;
3941
3942    status_t err = mOMX->getParameter(
3943            mNode, OMX_IndexParamVideoErrorCorrection,
3944            &errorCorrectionType, sizeof(errorCorrectionType));
3945
3946    if (err != OK) {
3947        return OK;  // Optional feature. Ignore this failure
3948    }
3949
3950    errorCorrectionType.bEnableHEC = OMX_FALSE;
3951    errorCorrectionType.bEnableResync = OMX_TRUE;
3952    errorCorrectionType.nResynchMarkerSpacing = 256;
3953    errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
3954    errorCorrectionType.bEnableRVLC = OMX_FALSE;
3955
3956    return mOMX->setParameter(
3957            mNode, OMX_IndexParamVideoErrorCorrection,
3958            &errorCorrectionType, sizeof(errorCorrectionType));
3959}
3960
3961status_t ACodec::setVideoFormatOnPort(
3962        OMX_U32 portIndex,
3963        int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat,
3964        float frameRate) {
3965    OMX_PARAM_PORTDEFINITIONTYPE def;
3966    InitOMXParams(&def);
3967    def.nPortIndex = portIndex;
3968
3969    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
3970
3971    status_t err = mOMX->getParameter(
3972            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3973    if (err != OK) {
3974        return err;
3975    }
3976
3977    if (portIndex == kPortIndexInput) {
3978        // XXX Need a (much) better heuristic to compute input buffer sizes.
3979        const size_t X = 64 * 1024;
3980        if (def.nBufferSize < X) {
3981            def.nBufferSize = X;
3982        }
3983    }
3984
3985    if (def.eDomain != OMX_PortDomainVideo) {
3986        ALOGE("expected video port, got %s(%d)", asString(def.eDomain), def.eDomain);
3987        return FAILED_TRANSACTION;
3988    }
3989
3990    video_def->nFrameWidth = width;
3991    video_def->nFrameHeight = height;
3992
3993    if (portIndex == kPortIndexInput) {
3994        video_def->eCompressionFormat = compressionFormat;
3995        video_def->eColorFormat = OMX_COLOR_FormatUnused;
3996        if (frameRate >= 0) {
3997            video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
3998        }
3999    }
4000
4001    err = mOMX->setParameter(
4002            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
4003
4004    return err;
4005}
4006
4007status_t ACodec::initNativeWindow() {
4008    if (mNativeWindow != NULL) {
4009        return mOMX->enableNativeBuffers(mNode, kPortIndexOutput, OMX_TRUE /* graphic */, OMX_TRUE);
4010    }
4011
4012    mOMX->enableNativeBuffers(mNode, kPortIndexOutput, OMX_TRUE /* graphic */, OMX_FALSE);
4013    return OK;
4014}
4015
4016size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const {
4017    size_t n = 0;
4018
4019    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
4020        const BufferInfo &info = mBuffers[portIndex].itemAt(i);
4021
4022        if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
4023            ++n;
4024        }
4025    }
4026
4027    return n;
4028}
4029
4030size_t ACodec::countBuffersOwnedByNativeWindow() const {
4031    size_t n = 0;
4032
4033    for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) {
4034        const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i);
4035
4036        if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4037            ++n;
4038        }
4039    }
4040
4041    return n;
4042}
4043
4044void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() {
4045    if (mNativeWindow == NULL) {
4046        return;
4047    }
4048
4049    while (countBuffersOwnedByNativeWindow() > mNumUndequeuedBuffers
4050            && dequeueBufferFromNativeWindow() != NULL) {
4051        // these buffers will be submitted as regular buffers; account for this
4052        if (storingMetadataInDecodedBuffers() && mMetadataBuffersToSubmit > 0) {
4053            --mMetadataBuffersToSubmit;
4054        }
4055    }
4056}
4057
4058bool ACodec::allYourBuffersAreBelongToUs(
4059        OMX_U32 portIndex) {
4060    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
4061        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
4062
4063        if (info->mStatus != BufferInfo::OWNED_BY_US
4064                && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4065            ALOGV("[%s] Buffer %u on port %u still has status %d",
4066                    mComponentName.c_str(),
4067                    info->mBufferID, portIndex, info->mStatus);
4068            return false;
4069        }
4070    }
4071
4072    return true;
4073}
4074
4075bool ACodec::allYourBuffersAreBelongToUs() {
4076    return allYourBuffersAreBelongToUs(kPortIndexInput)
4077        && allYourBuffersAreBelongToUs(kPortIndexOutput);
4078}
4079
4080void ACodec::deferMessage(const sp<AMessage> &msg) {
4081    mDeferredQueue.push_back(msg);
4082}
4083
4084void ACodec::processDeferredMessages() {
4085    List<sp<AMessage> > queue = mDeferredQueue;
4086    mDeferredQueue.clear();
4087
4088    List<sp<AMessage> >::iterator it = queue.begin();
4089    while (it != queue.end()) {
4090        onMessageReceived(*it++);
4091    }
4092}
4093
4094// static
4095bool ACodec::describeDefaultColorFormat(DescribeColorFormat2Params &params) {
4096    MediaImage2 &image = params.sMediaImage;
4097    memset(&image, 0, sizeof(image));
4098
4099    image.mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
4100    image.mNumPlanes = 0;
4101
4102    const OMX_COLOR_FORMATTYPE fmt = params.eColorFormat;
4103    image.mWidth = params.nFrameWidth;
4104    image.mHeight = params.nFrameHeight;
4105
4106    // only supporting YUV420
4107    if (fmt != OMX_COLOR_FormatYUV420Planar &&
4108        fmt != OMX_COLOR_FormatYUV420PackedPlanar &&
4109        fmt != OMX_COLOR_FormatYUV420SemiPlanar &&
4110        fmt != OMX_COLOR_FormatYUV420PackedSemiPlanar &&
4111        fmt != (OMX_COLOR_FORMATTYPE)HAL_PIXEL_FORMAT_YV12) {
4112        ALOGW("do not know color format 0x%x = %d", fmt, fmt);
4113        return false;
4114    }
4115
4116    // TEMPORARY FIX for some vendors that advertise sliceHeight as 0
4117    if (params.nStride != 0 && params.nSliceHeight == 0) {
4118        ALOGW("using sliceHeight=%u instead of what codec advertised (=0)",
4119                params.nFrameHeight);
4120        params.nSliceHeight = params.nFrameHeight;
4121    }
4122
4123    // we need stride and slice-height to be non-zero and sensible. These values were chosen to
4124    // prevent integer overflows further down the line, and do not indicate support for
4125    // 32kx32k video.
4126    if (params.nStride == 0 || params.nSliceHeight == 0
4127            || params.nStride > 32768 || params.nSliceHeight > 32768) {
4128        ALOGW("cannot describe color format 0x%x = %d with stride=%u and sliceHeight=%u",
4129                fmt, fmt, params.nStride, params.nSliceHeight);
4130        return false;
4131    }
4132
4133    // set-up YUV format
4134    image.mType = MediaImage2::MEDIA_IMAGE_TYPE_YUV;
4135    image.mNumPlanes = 3;
4136    image.mBitDepth = 8;
4137    image.mBitDepthAllocated = 8;
4138    image.mPlane[image.Y].mOffset = 0;
4139    image.mPlane[image.Y].mColInc = 1;
4140    image.mPlane[image.Y].mRowInc = params.nStride;
4141    image.mPlane[image.Y].mHorizSubsampling = 1;
4142    image.mPlane[image.Y].mVertSubsampling = 1;
4143
4144    switch ((int)fmt) {
4145        case HAL_PIXEL_FORMAT_YV12:
4146            if (params.bUsingNativeBuffers) {
4147                size_t ystride = align(params.nStride, 16);
4148                size_t cstride = align(params.nStride / 2, 16);
4149                image.mPlane[image.Y].mRowInc = ystride;
4150
4151                image.mPlane[image.V].mOffset = ystride * params.nSliceHeight;
4152                image.mPlane[image.V].mColInc = 1;
4153                image.mPlane[image.V].mRowInc = cstride;
4154                image.mPlane[image.V].mHorizSubsampling = 2;
4155                image.mPlane[image.V].mVertSubsampling = 2;
4156
4157                image.mPlane[image.U].mOffset = image.mPlane[image.V].mOffset
4158                        + (cstride * params.nSliceHeight / 2);
4159                image.mPlane[image.U].mColInc = 1;
4160                image.mPlane[image.U].mRowInc = cstride;
4161                image.mPlane[image.U].mHorizSubsampling = 2;
4162                image.mPlane[image.U].mVertSubsampling = 2;
4163                break;
4164            } else {
4165                // fall through as YV12 is used for YUV420Planar by some codecs
4166            }
4167
4168        case OMX_COLOR_FormatYUV420Planar:
4169        case OMX_COLOR_FormatYUV420PackedPlanar:
4170            image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
4171            image.mPlane[image.U].mColInc = 1;
4172            image.mPlane[image.U].mRowInc = params.nStride / 2;
4173            image.mPlane[image.U].mHorizSubsampling = 2;
4174            image.mPlane[image.U].mVertSubsampling = 2;
4175
4176            image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset
4177                    + (params.nStride * params.nSliceHeight / 4);
4178            image.mPlane[image.V].mColInc = 1;
4179            image.mPlane[image.V].mRowInc = params.nStride / 2;
4180            image.mPlane[image.V].mHorizSubsampling = 2;
4181            image.mPlane[image.V].mVertSubsampling = 2;
4182            break;
4183
4184        case OMX_COLOR_FormatYUV420SemiPlanar:
4185            // FIXME: NV21 for sw-encoder, NV12 for decoder and hw-encoder
4186        case OMX_COLOR_FormatYUV420PackedSemiPlanar:
4187            // NV12
4188            image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
4189            image.mPlane[image.U].mColInc = 2;
4190            image.mPlane[image.U].mRowInc = params.nStride;
4191            image.mPlane[image.U].mHorizSubsampling = 2;
4192            image.mPlane[image.U].mVertSubsampling = 2;
4193
4194            image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset + 1;
4195            image.mPlane[image.V].mColInc = 2;
4196            image.mPlane[image.V].mRowInc = params.nStride;
4197            image.mPlane[image.V].mHorizSubsampling = 2;
4198            image.mPlane[image.V].mVertSubsampling = 2;
4199            break;
4200
4201        default:
4202            TRESPASS();
4203    }
4204    return true;
4205}
4206
4207// static
4208bool ACodec::describeColorFormat(
4209        const sp<IOMX> &omx, IOMX::node_id node,
4210        DescribeColorFormat2Params &describeParams)
4211{
4212    OMX_INDEXTYPE describeColorFormatIndex;
4213    if (omx->getExtensionIndex(
4214            node, "OMX.google.android.index.describeColorFormat",
4215            &describeColorFormatIndex) == OK) {
4216        DescribeColorFormatParams describeParamsV1(describeParams);
4217        if (omx->getParameter(
4218                node, describeColorFormatIndex,
4219                &describeParamsV1, sizeof(describeParamsV1)) == OK) {
4220            describeParams.initFromV1(describeParamsV1);
4221            return describeParams.sMediaImage.mType != MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
4222        }
4223    } else if (omx->getExtensionIndex(
4224            node, "OMX.google.android.index.describeColorFormat2", &describeColorFormatIndex) == OK
4225               && omx->getParameter(
4226            node, describeColorFormatIndex, &describeParams, sizeof(describeParams)) == OK) {
4227        return describeParams.sMediaImage.mType != MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
4228    }
4229
4230    return describeDefaultColorFormat(describeParams);
4231}
4232
4233// static
4234bool ACodec::isFlexibleColorFormat(
4235         const sp<IOMX> &omx, IOMX::node_id node,
4236         uint32_t colorFormat, bool usingNativeBuffers, OMX_U32 *flexibleEquivalent) {
4237    DescribeColorFormat2Params describeParams;
4238    InitOMXParams(&describeParams);
4239    describeParams.eColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat;
4240    // reasonable dummy values
4241    describeParams.nFrameWidth = 128;
4242    describeParams.nFrameHeight = 128;
4243    describeParams.nStride = 128;
4244    describeParams.nSliceHeight = 128;
4245    describeParams.bUsingNativeBuffers = (OMX_BOOL)usingNativeBuffers;
4246
4247    CHECK(flexibleEquivalent != NULL);
4248
4249    if (!describeColorFormat(omx, node, describeParams)) {
4250        return false;
4251    }
4252
4253    const MediaImage2 &img = describeParams.sMediaImage;
4254    if (img.mType == MediaImage2::MEDIA_IMAGE_TYPE_YUV) {
4255        if (img.mNumPlanes != 3
4256                || img.mPlane[img.Y].mHorizSubsampling != 1
4257                || img.mPlane[img.Y].mVertSubsampling != 1) {
4258            return false;
4259        }
4260
4261        // YUV 420
4262        if (img.mPlane[img.U].mHorizSubsampling == 2
4263                && img.mPlane[img.U].mVertSubsampling == 2
4264                && img.mPlane[img.V].mHorizSubsampling == 2
4265                && img.mPlane[img.V].mVertSubsampling == 2) {
4266            // possible flexible YUV420 format
4267            if (img.mBitDepth <= 8) {
4268               *flexibleEquivalent = OMX_COLOR_FormatYUV420Flexible;
4269               return true;
4270            }
4271        }
4272    }
4273    return false;
4274}
4275
4276status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
4277    const char *niceIndex = portIndex == kPortIndexInput ? "input" : "output";
4278    OMX_PARAM_PORTDEFINITIONTYPE def;
4279    InitOMXParams(&def);
4280    def.nPortIndex = portIndex;
4281
4282    status_t err = mOMX->getParameter(mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
4283    if (err != OK) {
4284        return err;
4285    }
4286
4287    if (def.eDir != (portIndex == kPortIndexOutput ? OMX_DirOutput : OMX_DirInput)) {
4288        ALOGE("unexpected dir: %s(%d) on %s port", asString(def.eDir), def.eDir, niceIndex);
4289        return BAD_VALUE;
4290    }
4291
4292    switch (def.eDomain) {
4293        case OMX_PortDomainVideo:
4294        {
4295            OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
4296            switch ((int)videoDef->eCompressionFormat) {
4297                case OMX_VIDEO_CodingUnused:
4298                {
4299                    CHECK(mIsEncoder ^ (portIndex == kPortIndexOutput));
4300                    notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
4301
4302                    notify->setInt32("stride", videoDef->nStride);
4303                    notify->setInt32("slice-height", videoDef->nSliceHeight);
4304                    notify->setInt32("color-format", videoDef->eColorFormat);
4305
4306                    if (mNativeWindow == NULL) {
4307                        DescribeColorFormat2Params describeParams;
4308                        InitOMXParams(&describeParams);
4309                        describeParams.eColorFormat = videoDef->eColorFormat;
4310                        describeParams.nFrameWidth = videoDef->nFrameWidth;
4311                        describeParams.nFrameHeight = videoDef->nFrameHeight;
4312                        describeParams.nStride = videoDef->nStride;
4313                        describeParams.nSliceHeight = videoDef->nSliceHeight;
4314                        describeParams.bUsingNativeBuffers = OMX_FALSE;
4315
4316                        if (describeColorFormat(mOMX, mNode, describeParams)) {
4317                            notify->setBuffer(
4318                                    "image-data",
4319                                    ABuffer::CreateAsCopy(
4320                                            &describeParams.sMediaImage,
4321                                            sizeof(describeParams.sMediaImage)));
4322
4323                            MediaImage2 &img = describeParams.sMediaImage;
4324                            MediaImage2::PlaneInfo *plane = img.mPlane;
4325                            ALOGV("[%s] MediaImage { F(%ux%u) @%u+%d+%d @%u+%d+%d @%u+%d+%d }",
4326                                    mComponentName.c_str(), img.mWidth, img.mHeight,
4327                                    plane[0].mOffset, plane[0].mColInc, plane[0].mRowInc,
4328                                    plane[1].mOffset, plane[1].mColInc, plane[1].mRowInc,
4329                                    plane[2].mOffset, plane[2].mColInc, plane[2].mRowInc);
4330                        }
4331                    }
4332
4333                    if (portIndex != kPortIndexOutput) {
4334                        // TODO: also get input crop
4335                        break;
4336                    }
4337
4338                    (void)getColorAspects(portIndex, notify);
4339
4340                    OMX_CONFIG_RECTTYPE rect;
4341                    InitOMXParams(&rect);
4342                    rect.nPortIndex = portIndex;
4343
4344                    if (mOMX->getConfig(
4345                                mNode,
4346                                (portIndex == kPortIndexOutput ?
4347                                        OMX_IndexConfigCommonOutputCrop :
4348                                        OMX_IndexConfigCommonInputCrop),
4349                                &rect, sizeof(rect)) != OK) {
4350                        rect.nLeft = 0;
4351                        rect.nTop = 0;
4352                        rect.nWidth = videoDef->nFrameWidth;
4353                        rect.nHeight = videoDef->nFrameHeight;
4354                    }
4355
4356                    if (rect.nLeft < 0 ||
4357                        rect.nTop < 0 ||
4358                        rect.nLeft + rect.nWidth > videoDef->nFrameWidth ||
4359                        rect.nTop + rect.nHeight > videoDef->nFrameHeight) {
4360                        ALOGE("Wrong cropped rect (%d, %d) - (%u, %u) vs. frame (%u, %u)",
4361                                rect.nLeft, rect.nTop,
4362                                rect.nLeft + rect.nWidth, rect.nTop + rect.nHeight,
4363                                videoDef->nFrameWidth, videoDef->nFrameHeight);
4364                        return BAD_VALUE;
4365                    }
4366
4367                    notify->setRect(
4368                            "crop",
4369                            rect.nLeft,
4370                            rect.nTop,
4371                            rect.nLeft + rect.nWidth - 1,
4372                            rect.nTop + rect.nHeight - 1);
4373
4374                    break;
4375                }
4376
4377                case OMX_VIDEO_CodingVP8:
4378                case OMX_VIDEO_CodingVP9:
4379                {
4380                    OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
4381                    InitOMXParams(&vp8type);
4382                    vp8type.nPortIndex = kPortIndexOutput;
4383                    status_t err = mOMX->getParameter(
4384                            mNode,
4385                            (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
4386                            &vp8type,
4387                            sizeof(vp8type));
4388
4389                    if (err == OK) {
4390                        AString tsSchema = "none";
4391                        if (vp8type.eTemporalPattern
4392                                == OMX_VIDEO_VPXTemporalLayerPatternWebRTC) {
4393                            switch (vp8type.nTemporalLayerCount) {
4394                                case 1:
4395                                {
4396                                    tsSchema = "webrtc.vp8.1-layer";
4397                                    break;
4398                                }
4399                                case 2:
4400                                {
4401                                    tsSchema = "webrtc.vp8.2-layer";
4402                                    break;
4403                                }
4404                                case 3:
4405                                {
4406                                    tsSchema = "webrtc.vp8.3-layer";
4407                                    break;
4408                                }
4409                                default:
4410                                {
4411                                    break;
4412                                }
4413                            }
4414                        }
4415                        notify->setString("ts-schema", tsSchema);
4416                    }
4417                    // Fall through to set up mime.
4418                }
4419
4420                default:
4421                {
4422                    if (mIsEncoder ^ (portIndex == kPortIndexOutput)) {
4423                        // should be CodingUnused
4424                        ALOGE("Raw port video compression format is %s(%d)",
4425                                asString(videoDef->eCompressionFormat),
4426                                videoDef->eCompressionFormat);
4427                        return BAD_VALUE;
4428                    }
4429                    AString mime;
4430                    if (GetMimeTypeForVideoCoding(
4431                        videoDef->eCompressionFormat, &mime) != OK) {
4432                        notify->setString("mime", "application/octet-stream");
4433                    } else {
4434                        notify->setString("mime", mime.c_str());
4435                    }
4436                    uint32_t intraRefreshPeriod = 0;
4437                    if (mIsEncoder && getIntraRefreshPeriod(&intraRefreshPeriod) == OK
4438                            && intraRefreshPeriod > 0) {
4439                        notify->setInt32("intra-refresh-period", intraRefreshPeriod);
4440                    }
4441                    break;
4442                }
4443            }
4444            notify->setInt32("width", videoDef->nFrameWidth);
4445            notify->setInt32("height", videoDef->nFrameHeight);
4446            ALOGV("[%s] %s format is %s", mComponentName.c_str(),
4447                    portIndex == kPortIndexInput ? "input" : "output",
4448                    notify->debugString().c_str());
4449
4450            break;
4451        }
4452
4453        case OMX_PortDomainAudio:
4454        {
4455            OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
4456
4457            switch ((int)audioDef->eEncoding) {
4458                case OMX_AUDIO_CodingPCM:
4459                {
4460                    OMX_AUDIO_PARAM_PCMMODETYPE params;
4461                    InitOMXParams(&params);
4462                    params.nPortIndex = portIndex;
4463
4464                    err = mOMX->getParameter(
4465                            mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
4466                    if (err != OK) {
4467                        return err;
4468                    }
4469
4470                    if (params.nChannels <= 0
4471                            || (params.nChannels != 1 && !params.bInterleaved)
4472                            || params.nBitPerSample != 16u
4473                            || params.eNumData != OMX_NumericalDataSigned
4474                            || params.ePCMMode != OMX_AUDIO_PCMModeLinear) {
4475                        ALOGE("unsupported PCM port: %u channels%s, %u-bit, %s(%d), %s(%d) mode ",
4476                                params.nChannels,
4477                                params.bInterleaved ? " interleaved" : "",
4478                                params.nBitPerSample,
4479                                asString(params.eNumData), params.eNumData,
4480                                asString(params.ePCMMode), params.ePCMMode);
4481                        return FAILED_TRANSACTION;
4482                    }
4483
4484                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
4485                    notify->setInt32("channel-count", params.nChannels);
4486                    notify->setInt32("sample-rate", params.nSamplingRate);
4487
4488                    if (mChannelMaskPresent) {
4489                        notify->setInt32("channel-mask", mChannelMask);
4490                    }
4491                    break;
4492                }
4493
4494                case OMX_AUDIO_CodingAAC:
4495                {
4496                    OMX_AUDIO_PARAM_AACPROFILETYPE params;
4497                    InitOMXParams(&params);
4498                    params.nPortIndex = portIndex;
4499
4500                    err = mOMX->getParameter(
4501                            mNode, OMX_IndexParamAudioAac, &params, sizeof(params));
4502                    if (err != OK) {
4503                        return err;
4504                    }
4505
4506                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
4507                    notify->setInt32("channel-count", params.nChannels);
4508                    notify->setInt32("sample-rate", params.nSampleRate);
4509                    break;
4510                }
4511
4512                case OMX_AUDIO_CodingAMR:
4513                {
4514                    OMX_AUDIO_PARAM_AMRTYPE params;
4515                    InitOMXParams(&params);
4516                    params.nPortIndex = portIndex;
4517
4518                    err = mOMX->getParameter(
4519                            mNode, OMX_IndexParamAudioAmr, &params, sizeof(params));
4520                    if (err != OK) {
4521                        return err;
4522                    }
4523
4524                    notify->setInt32("channel-count", 1);
4525                    if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) {
4526                        notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
4527                        notify->setInt32("sample-rate", 16000);
4528                    } else {
4529                        notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
4530                        notify->setInt32("sample-rate", 8000);
4531                    }
4532                    break;
4533                }
4534
4535                case OMX_AUDIO_CodingFLAC:
4536                {
4537                    OMX_AUDIO_PARAM_FLACTYPE params;
4538                    InitOMXParams(&params);
4539                    params.nPortIndex = portIndex;
4540
4541                    err = mOMX->getParameter(
4542                            mNode, OMX_IndexParamAudioFlac, &params, sizeof(params));
4543                    if (err != OK) {
4544                        return err;
4545                    }
4546
4547                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC);
4548                    notify->setInt32("channel-count", params.nChannels);
4549                    notify->setInt32("sample-rate", params.nSampleRate);
4550                    break;
4551                }
4552
4553                case OMX_AUDIO_CodingMP3:
4554                {
4555                    OMX_AUDIO_PARAM_MP3TYPE params;
4556                    InitOMXParams(&params);
4557                    params.nPortIndex = portIndex;
4558
4559                    err = mOMX->getParameter(
4560                            mNode, OMX_IndexParamAudioMp3, &params, sizeof(params));
4561                    if (err != OK) {
4562                        return err;
4563                    }
4564
4565                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MPEG);
4566                    notify->setInt32("channel-count", params.nChannels);
4567                    notify->setInt32("sample-rate", params.nSampleRate);
4568                    break;
4569                }
4570
4571                case OMX_AUDIO_CodingVORBIS:
4572                {
4573                    OMX_AUDIO_PARAM_VORBISTYPE params;
4574                    InitOMXParams(&params);
4575                    params.nPortIndex = portIndex;
4576
4577                    err = mOMX->getParameter(
4578                            mNode, OMX_IndexParamAudioVorbis, &params, sizeof(params));
4579                    if (err != OK) {
4580                        return err;
4581                    }
4582
4583                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_VORBIS);
4584                    notify->setInt32("channel-count", params.nChannels);
4585                    notify->setInt32("sample-rate", params.nSampleRate);
4586                    break;
4587                }
4588
4589                case OMX_AUDIO_CodingAndroidAC3:
4590                {
4591                    OMX_AUDIO_PARAM_ANDROID_AC3TYPE params;
4592                    InitOMXParams(&params);
4593                    params.nPortIndex = portIndex;
4594
4595                    err = mOMX->getParameter(
4596                            mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
4597                            &params, sizeof(params));
4598                    if (err != OK) {
4599                        return err;
4600                    }
4601
4602                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3);
4603                    notify->setInt32("channel-count", params.nChannels);
4604                    notify->setInt32("sample-rate", params.nSampleRate);
4605                    break;
4606                }
4607
4608                case OMX_AUDIO_CodingAndroidEAC3:
4609                {
4610                    OMX_AUDIO_PARAM_ANDROID_EAC3TYPE params;
4611                    InitOMXParams(&params);
4612                    params.nPortIndex = portIndex;
4613
4614                    err = mOMX->getParameter(
4615                            mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
4616                            &params, sizeof(params));
4617                    if (err != OK) {
4618                        return err;
4619                    }
4620
4621                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_EAC3);
4622                    notify->setInt32("channel-count", params.nChannels);
4623                    notify->setInt32("sample-rate", params.nSampleRate);
4624                    break;
4625                }
4626
4627                case OMX_AUDIO_CodingAndroidOPUS:
4628                {
4629                    OMX_AUDIO_PARAM_ANDROID_OPUSTYPE params;
4630                    InitOMXParams(&params);
4631                    params.nPortIndex = portIndex;
4632
4633                    err = mOMX->getParameter(
4634                            mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
4635                            &params, sizeof(params));
4636                    if (err != OK) {
4637                        return err;
4638                    }
4639
4640                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_OPUS);
4641                    notify->setInt32("channel-count", params.nChannels);
4642                    notify->setInt32("sample-rate", params.nSampleRate);
4643                    break;
4644                }
4645
4646                case OMX_AUDIO_CodingG711:
4647                {
4648                    OMX_AUDIO_PARAM_PCMMODETYPE params;
4649                    InitOMXParams(&params);
4650                    params.nPortIndex = portIndex;
4651
4652                    err = mOMX->getParameter(
4653                            mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioPcm, &params, sizeof(params));
4654                    if (err != OK) {
4655                        return err;
4656                    }
4657
4658                    const char *mime = NULL;
4659                    if (params.ePCMMode == OMX_AUDIO_PCMModeMULaw) {
4660                        mime = MEDIA_MIMETYPE_AUDIO_G711_MLAW;
4661                    } else if (params.ePCMMode == OMX_AUDIO_PCMModeALaw) {
4662                        mime = MEDIA_MIMETYPE_AUDIO_G711_ALAW;
4663                    } else { // params.ePCMMode == OMX_AUDIO_PCMModeLinear
4664                        mime = MEDIA_MIMETYPE_AUDIO_RAW;
4665                    }
4666                    notify->setString("mime", mime);
4667                    notify->setInt32("channel-count", params.nChannels);
4668                    notify->setInt32("sample-rate", params.nSamplingRate);
4669                    break;
4670                }
4671
4672                case OMX_AUDIO_CodingGSMFR:
4673                {
4674                    OMX_AUDIO_PARAM_PCMMODETYPE params;
4675                    InitOMXParams(&params);
4676                    params.nPortIndex = portIndex;
4677
4678                    err = mOMX->getParameter(
4679                                mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
4680                    if (err != OK) {
4681                        return err;
4682                    }
4683
4684                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MSGSM);
4685                    notify->setInt32("channel-count", params.nChannels);
4686                    notify->setInt32("sample-rate", params.nSamplingRate);
4687                    break;
4688                }
4689
4690                default:
4691                    ALOGE("Unsupported audio coding: %s(%d)\n",
4692                            asString(audioDef->eEncoding), audioDef->eEncoding);
4693                    return BAD_TYPE;
4694            }
4695            break;
4696        }
4697
4698        default:
4699            ALOGE("Unsupported domain: %s(%d)", asString(def.eDomain), def.eDomain);
4700            return BAD_TYPE;
4701    }
4702
4703    return OK;
4704}
4705
4706void ACodec::onOutputFormatChanged() {
4707    // store new output format
4708    mOutputFormat = mBaseOutputFormat->dup();
4709
4710    if (getPortFormat(kPortIndexOutput, mOutputFormat) != OK) {
4711        ALOGE("[%s] Failed to get port format to send format change", mComponentName.c_str());
4712        return;
4713    }
4714
4715    if (mTunneled) {
4716        sendFormatChange();
4717    }
4718}
4719
4720void ACodec::addKeyFormatChangesToRenderBufferNotification(sp<AMessage> &reply) {
4721    AString mime;
4722    CHECK(mOutputFormat->findString("mime", &mime));
4723
4724    int32_t left, top, right, bottom;
4725    if (mime == MEDIA_MIMETYPE_VIDEO_RAW &&
4726        mNativeWindow != NULL &&
4727        mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) {
4728        // notify renderer of the crop change
4729        // NOTE: native window uses extended right-bottom coordinate
4730        reply->setRect("crop", left, top, right + 1, bottom + 1);
4731    }
4732}
4733
4734void ACodec::sendFormatChange() {
4735    AString mime;
4736    CHECK(mOutputFormat->findString("mime", &mime));
4737
4738    if (mime == MEDIA_MIMETYPE_AUDIO_RAW && (mEncoderDelay || mEncoderPadding)) {
4739        int32_t channelCount;
4740        CHECK(mOutputFormat->findInt32("channel-count", &channelCount));
4741        if (mSkipCutBuffer != NULL) {
4742            size_t prevbufsize = mSkipCutBuffer->size();
4743            if (prevbufsize != 0) {
4744                ALOGW("Replacing SkipCutBuffer holding %zu bytes", prevbufsize);
4745            }
4746        }
4747        mSkipCutBuffer = new SkipCutBuffer(mEncoderDelay, mEncoderPadding, channelCount);
4748    }
4749
4750    sp<AMessage> notify = mNotify->dup();
4751    notify->setInt32("what", kWhatOutputFormatChanged);
4752    notify->setMessage("format", mOutputFormat);
4753    notify->post();
4754
4755    // mLastOutputFormat is not used when tunneled; doing this just to stay consistent
4756    mLastOutputFormat = mOutputFormat;
4757}
4758
4759void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) {
4760    sp<AMessage> notify = mNotify->dup();
4761    notify->setInt32("what", CodecBase::kWhatError);
4762    ALOGE("signalError(omxError %#x, internalError %d)", error, internalError);
4763
4764    if (internalError == UNKNOWN_ERROR) { // find better error code
4765        const status_t omxStatus = statusFromOMXError(error);
4766        if (omxStatus != 0) {
4767            internalError = omxStatus;
4768        } else {
4769            ALOGW("Invalid OMX error %#x", error);
4770        }
4771    }
4772
4773    mFatalError = true;
4774
4775    notify->setInt32("err", internalError);
4776    notify->setInt32("actionCode", ACTION_CODE_FATAL); // could translate from OMX error.
4777    notify->post();
4778}
4779
4780////////////////////////////////////////////////////////////////////////////////
4781
4782ACodec::PortDescription::PortDescription() {
4783}
4784
4785status_t ACodec::requestIDRFrame() {
4786    if (!mIsEncoder) {
4787        return ERROR_UNSUPPORTED;
4788    }
4789
4790    OMX_CONFIG_INTRAREFRESHVOPTYPE params;
4791    InitOMXParams(&params);
4792
4793    params.nPortIndex = kPortIndexOutput;
4794    params.IntraRefreshVOP = OMX_TRUE;
4795
4796    return mOMX->setConfig(
4797            mNode,
4798            OMX_IndexConfigVideoIntraVOPRefresh,
4799            &params,
4800            sizeof(params));
4801}
4802
4803void ACodec::PortDescription::addBuffer(
4804        IOMX::buffer_id id, const sp<ABuffer> &buffer,
4805        const sp<NativeHandle> &handle, const sp<RefBase> &memRef) {
4806    mBufferIDs.push_back(id);
4807    mBuffers.push_back(buffer);
4808    mHandles.push_back(handle);
4809    mMemRefs.push_back(memRef);
4810}
4811
4812size_t ACodec::PortDescription::countBuffers() {
4813    return mBufferIDs.size();
4814}
4815
4816IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const {
4817    return mBufferIDs.itemAt(index);
4818}
4819
4820sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const {
4821    return mBuffers.itemAt(index);
4822}
4823
4824sp<NativeHandle> ACodec::PortDescription::handleAt(size_t index) const {
4825    return mHandles.itemAt(index);
4826}
4827
4828sp<RefBase> ACodec::PortDescription::memRefAt(size_t index) const {
4829    return mMemRefs.itemAt(index);
4830}
4831
4832////////////////////////////////////////////////////////////////////////////////
4833
4834ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
4835    : AState(parentState),
4836      mCodec(codec) {
4837}
4838
4839ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(
4840        OMX_U32 /* portIndex */) {
4841    return KEEP_BUFFERS;
4842}
4843
4844bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
4845    switch (msg->what()) {
4846        case kWhatInputBufferFilled:
4847        {
4848            onInputBufferFilled(msg);
4849            break;
4850        }
4851
4852        case kWhatOutputBufferDrained:
4853        {
4854            onOutputBufferDrained(msg);
4855            break;
4856        }
4857
4858        case ACodec::kWhatOMXMessageList:
4859        {
4860            return checkOMXMessage(msg) ? onOMXMessageList(msg) : true;
4861        }
4862
4863        case ACodec::kWhatOMXMessageItem:
4864        {
4865            // no need to check as we already did it for kWhatOMXMessageList
4866            return onOMXMessage(msg);
4867        }
4868
4869        case ACodec::kWhatOMXMessage:
4870        {
4871            return checkOMXMessage(msg) ? onOMXMessage(msg) : true;
4872        }
4873
4874        case ACodec::kWhatSetSurface:
4875        {
4876            sp<AReplyToken> replyID;
4877            CHECK(msg->senderAwaitsResponse(&replyID));
4878
4879            sp<RefBase> obj;
4880            CHECK(msg->findObject("surface", &obj));
4881
4882            status_t err = mCodec->handleSetSurface(static_cast<Surface *>(obj.get()));
4883
4884            sp<AMessage> response = new AMessage;
4885            response->setInt32("err", err);
4886            response->postReply(replyID);
4887            break;
4888        }
4889
4890        case ACodec::kWhatCreateInputSurface:
4891        case ACodec::kWhatSetInputSurface:
4892        case ACodec::kWhatSignalEndOfInputStream:
4893        {
4894            // This may result in an app illegal state exception.
4895            ALOGE("Message 0x%x was not handled", msg->what());
4896            mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION);
4897            return true;
4898        }
4899
4900        case ACodec::kWhatOMXDied:
4901        {
4902            // This will result in kFlagSawMediaServerDie handling in MediaCodec.
4903            ALOGE("OMX/mediaserver died, signalling error!");
4904            mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT);
4905            break;
4906        }
4907
4908        case ACodec::kWhatReleaseCodecInstance:
4909        {
4910            ALOGI("[%s] forcing the release of codec",
4911                    mCodec->mComponentName.c_str());
4912            status_t err = mCodec->mOMX->freeNode(mCodec->mNode);
4913            ALOGE_IF("[%s] failed to release codec instance: err=%d",
4914                       mCodec->mComponentName.c_str(), err);
4915            sp<AMessage> notify = mCodec->mNotify->dup();
4916            notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
4917            notify->post();
4918            break;
4919        }
4920
4921        default:
4922            return false;
4923    }
4924
4925    return true;
4926}
4927
4928bool ACodec::BaseState::checkOMXMessage(const sp<AMessage> &msg) {
4929    // there is a possibility that this is an outstanding message for a
4930    // codec that we have already destroyed
4931    if (mCodec->mNode == 0) {
4932        ALOGI("ignoring message as already freed component: %s",
4933                msg->debugString().c_str());
4934        return false;
4935    }
4936
4937    IOMX::node_id nodeID;
4938    CHECK(msg->findInt32("node", (int32_t*)&nodeID));
4939    if (nodeID != mCodec->mNode) {
4940        ALOGE("Unexpected message for nodeID: %u, should have been %u", nodeID, mCodec->mNode);
4941        return false;
4942    }
4943    return true;
4944}
4945
4946bool ACodec::BaseState::onOMXMessageList(const sp<AMessage> &msg) {
4947    sp<RefBase> obj;
4948    CHECK(msg->findObject("messages", &obj));
4949    sp<MessageList> msgList = static_cast<MessageList *>(obj.get());
4950
4951    bool receivedRenderedEvents = false;
4952    for (std::list<sp<AMessage>>::const_iterator it = msgList->getList().cbegin();
4953          it != msgList->getList().cend(); ++it) {
4954        (*it)->setWhat(ACodec::kWhatOMXMessageItem);
4955        mCodec->handleMessage(*it);
4956        int32_t type;
4957        CHECK((*it)->findInt32("type", &type));
4958        if (type == omx_message::FRAME_RENDERED) {
4959            receivedRenderedEvents = true;
4960        }
4961    }
4962
4963    if (receivedRenderedEvents) {
4964        // NOTE: all buffers are rendered in this case
4965        mCodec->notifyOfRenderedFrames();
4966    }
4967    return true;
4968}
4969
4970bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
4971    int32_t type;
4972    CHECK(msg->findInt32("type", &type));
4973
4974    switch (type) {
4975        case omx_message::EVENT:
4976        {
4977            int32_t event, data1, data2;
4978            CHECK(msg->findInt32("event", &event));
4979            CHECK(msg->findInt32("data1", &data1));
4980            CHECK(msg->findInt32("data2", &data2));
4981
4982            if (event == OMX_EventCmdComplete
4983                    && data1 == OMX_CommandFlush
4984                    && data2 == (int32_t)OMX_ALL) {
4985                // Use of this notification is not consistent across
4986                // implementations. We'll drop this notification and rely
4987                // on flush-complete notifications on the individual port
4988                // indices instead.
4989
4990                return true;
4991            }
4992
4993            return onOMXEvent(
4994                    static_cast<OMX_EVENTTYPE>(event),
4995                    static_cast<OMX_U32>(data1),
4996                    static_cast<OMX_U32>(data2));
4997        }
4998
4999        case omx_message::EMPTY_BUFFER_DONE:
5000        {
5001            IOMX::buffer_id bufferID;
5002            int32_t fenceFd;
5003
5004            CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
5005            CHECK(msg->findInt32("fence_fd", &fenceFd));
5006
5007            return onOMXEmptyBufferDone(bufferID, fenceFd);
5008        }
5009
5010        case omx_message::FILL_BUFFER_DONE:
5011        {
5012            IOMX::buffer_id bufferID;
5013            CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
5014
5015            int32_t rangeOffset, rangeLength, flags, fenceFd;
5016            int64_t timeUs;
5017
5018            CHECK(msg->findInt32("range_offset", &rangeOffset));
5019            CHECK(msg->findInt32("range_length", &rangeLength));
5020            CHECK(msg->findInt32("flags", &flags));
5021            CHECK(msg->findInt64("timestamp", &timeUs));
5022            CHECK(msg->findInt32("fence_fd", &fenceFd));
5023
5024            return onOMXFillBufferDone(
5025                    bufferID,
5026                    (size_t)rangeOffset, (size_t)rangeLength,
5027                    (OMX_U32)flags,
5028                    timeUs,
5029                    fenceFd);
5030        }
5031
5032        case omx_message::FRAME_RENDERED:
5033        {
5034            int64_t mediaTimeUs, systemNano;
5035
5036            CHECK(msg->findInt64("media_time_us", &mediaTimeUs));
5037            CHECK(msg->findInt64("system_nano", &systemNano));
5038
5039            return onOMXFrameRendered(
5040                    mediaTimeUs, systemNano);
5041        }
5042
5043        default:
5044            ALOGE("Unexpected message type: %d", type);
5045            return false;
5046    }
5047}
5048
5049bool ACodec::BaseState::onOMXFrameRendered(
5050        int64_t mediaTimeUs __unused, nsecs_t systemNano __unused) {
5051    // ignore outside of Executing and PortSettingsChanged states
5052    return true;
5053}
5054
5055bool ACodec::BaseState::onOMXEvent(
5056        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5057    if (event != OMX_EventError) {
5058        ALOGV("[%s] EVENT(%d, 0x%08x, 0x%08x)",
5059             mCodec->mComponentName.c_str(), event, data1, data2);
5060
5061        return false;
5062    }
5063
5064    ALOGE("[%s] ERROR(0x%08x)", mCodec->mComponentName.c_str(), data1);
5065
5066    // verify OMX component sends back an error we expect.
5067    OMX_ERRORTYPE omxError = (OMX_ERRORTYPE)data1;
5068    if (!isOMXError(omxError)) {
5069        ALOGW("Invalid OMX error %#x", omxError);
5070        omxError = OMX_ErrorUndefined;
5071    }
5072    mCodec->signalError(omxError);
5073
5074    return true;
5075}
5076
5077bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID, int fenceFd) {
5078    ALOGV("[%s] onOMXEmptyBufferDone %u",
5079         mCodec->mComponentName.c_str(), bufferID);
5080
5081    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
5082    BufferInfo::Status status = BufferInfo::getSafeStatus(info);
5083    if (status != BufferInfo::OWNED_BY_COMPONENT) {
5084        ALOGE("Wrong ownership in EBD: %s(%d) buffer #%u", _asString(status), status, bufferID);
5085        mCodec->dumpBuffers(kPortIndexInput);
5086        if (fenceFd >= 0) {
5087            ::close(fenceFd);
5088        }
5089        return false;
5090    }
5091    info->mStatus = BufferInfo::OWNED_BY_US;
5092
5093    // input buffers cannot take fences, so wait for any fence now
5094    (void)mCodec->waitForFence(fenceFd, "onOMXEmptyBufferDone");
5095    fenceFd = -1;
5096
5097    // still save fence for completeness
5098    info->setWriteFence(fenceFd, "onOMXEmptyBufferDone");
5099
5100    // We're in "store-metadata-in-buffers" mode, the underlying
5101    // OMX component had access to data that's implicitly refcounted
5102    // by this "MediaBuffer" object. Now that the OMX component has
5103    // told us that it's done with the input buffer, we can decrement
5104    // the mediaBuffer's reference count.
5105    info->mData->setMediaBufferBase(NULL);
5106
5107    PortMode mode = getPortMode(kPortIndexInput);
5108
5109    switch (mode) {
5110        case KEEP_BUFFERS:
5111            break;
5112
5113        case RESUBMIT_BUFFERS:
5114            postFillThisBuffer(info);
5115            break;
5116
5117        case FREE_BUFFERS:
5118        default:
5119            ALOGE("SHOULD NOT REACH HERE: cannot free empty output buffers");
5120            return false;
5121    }
5122
5123    return true;
5124}
5125
5126void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
5127    if (mCodec->mPortEOS[kPortIndexInput]) {
5128        return;
5129    }
5130
5131    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
5132
5133    sp<AMessage> notify = mCodec->mNotify->dup();
5134    notify->setInt32("what", CodecBase::kWhatFillThisBuffer);
5135    notify->setInt32("buffer-id", info->mBufferID);
5136
5137    info->mData->meta()->clear();
5138    notify->setBuffer("buffer", info->mData);
5139
5140    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec);
5141    reply->setInt32("buffer-id", info->mBufferID);
5142
5143    notify->setMessage("reply", reply);
5144
5145    notify->post();
5146
5147    info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
5148}
5149
5150void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
5151    IOMX::buffer_id bufferID;
5152    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
5153    sp<ABuffer> buffer;
5154    int32_t err = OK;
5155    bool eos = false;
5156    PortMode mode = getPortMode(kPortIndexInput);
5157
5158    if (!msg->findBuffer("buffer", &buffer)) {
5159        /* these are unfilled buffers returned by client */
5160        CHECK(msg->findInt32("err", &err));
5161
5162        if (err == OK) {
5163            /* buffers with no errors are returned on MediaCodec.flush */
5164            mode = KEEP_BUFFERS;
5165        } else {
5166            ALOGV("[%s] saw error %d instead of an input buffer",
5167                 mCodec->mComponentName.c_str(), err);
5168            eos = true;
5169        }
5170
5171        buffer.clear();
5172    }
5173
5174    int32_t tmp;
5175    if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
5176        eos = true;
5177        err = ERROR_END_OF_STREAM;
5178    }
5179
5180    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
5181    BufferInfo::Status status = BufferInfo::getSafeStatus(info);
5182    if (status != BufferInfo::OWNED_BY_UPSTREAM) {
5183        ALOGE("Wrong ownership in IBF: %s(%d) buffer #%u", _asString(status), status, bufferID);
5184        mCodec->dumpBuffers(kPortIndexInput);
5185        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
5186        return;
5187    }
5188
5189    info->mStatus = BufferInfo::OWNED_BY_US;
5190
5191    switch (mode) {
5192        case KEEP_BUFFERS:
5193        {
5194            if (eos) {
5195                if (!mCodec->mPortEOS[kPortIndexInput]) {
5196                    mCodec->mPortEOS[kPortIndexInput] = true;
5197                    mCodec->mInputEOSResult = err;
5198                }
5199            }
5200            break;
5201        }
5202
5203        case RESUBMIT_BUFFERS:
5204        {
5205            if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) {
5206                // Do not send empty input buffer w/o EOS to the component.
5207                if (buffer->size() == 0 && !eos) {
5208                    postFillThisBuffer(info);
5209                    break;
5210                }
5211
5212                int64_t timeUs;
5213                CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
5214
5215                OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
5216
5217                int32_t isCSD;
5218                if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
5219                    flags |= OMX_BUFFERFLAG_CODECCONFIG;
5220                }
5221
5222                if (eos) {
5223                    flags |= OMX_BUFFERFLAG_EOS;
5224                }
5225
5226                if (buffer != info->mData) {
5227                    ALOGV("[%s] Needs to copy input data for buffer %u. (%p != %p)",
5228                         mCodec->mComponentName.c_str(),
5229                         bufferID,
5230                         buffer.get(), info->mData.get());
5231
5232                    if (buffer->size() > info->mData->capacity()) {
5233                        ALOGE("data size (%zu) is greated than buffer capacity (%zu)",
5234                                buffer->size(),           // this is the data received
5235                                info->mData->capacity()); // this is out buffer size
5236                        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
5237                        return;
5238                    }
5239                    memcpy(info->mData->data(), buffer->data(), buffer->size());
5240                }
5241
5242                if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
5243                    ALOGV("[%s] calling emptyBuffer %u w/ codec specific data",
5244                         mCodec->mComponentName.c_str(), bufferID);
5245                } else if (flags & OMX_BUFFERFLAG_EOS) {
5246                    ALOGV("[%s] calling emptyBuffer %u w/ EOS",
5247                         mCodec->mComponentName.c_str(), bufferID);
5248                } else {
5249#if TRACK_BUFFER_TIMING
5250                    ALOGI("[%s] calling emptyBuffer %u w/ time %lld us",
5251                         mCodec->mComponentName.c_str(), bufferID, (long long)timeUs);
5252#else
5253                    ALOGV("[%s] calling emptyBuffer %u w/ time %lld us",
5254                         mCodec->mComponentName.c_str(), bufferID, (long long)timeUs);
5255#endif
5256                }
5257
5258#if TRACK_BUFFER_TIMING
5259                ACodec::BufferStats stats;
5260                stats.mEmptyBufferTimeUs = ALooper::GetNowUs();
5261                stats.mFillBufferDoneTimeUs = -1ll;
5262                mCodec->mBufferStats.add(timeUs, stats);
5263#endif
5264
5265                if (mCodec->storingMetadataInDecodedBuffers()) {
5266                    // try to submit an output buffer for each input buffer
5267                    PortMode outputMode = getPortMode(kPortIndexOutput);
5268
5269                    ALOGV("MetadataBuffersToSubmit=%u portMode=%s",
5270                            mCodec->mMetadataBuffersToSubmit,
5271                            (outputMode == FREE_BUFFERS ? "FREE" :
5272                             outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT"));
5273                    if (outputMode == RESUBMIT_BUFFERS) {
5274                        mCodec->submitOutputMetadataBuffer();
5275                    }
5276                }
5277                info->checkReadFence("onInputBufferFilled");
5278                status_t err2 = mCodec->mOMX->emptyBuffer(
5279                    mCodec->mNode,
5280                    bufferID,
5281                    0,
5282                    buffer->size(),
5283                    flags,
5284                    timeUs,
5285                    info->mFenceFd);
5286                info->mFenceFd = -1;
5287                if (err2 != OK) {
5288                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2));
5289                    return;
5290                }
5291                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
5292
5293                if (!eos && err == OK) {
5294                    getMoreInputDataIfPossible();
5295                } else {
5296                    ALOGV("[%s] Signalled EOS (%d) on the input port",
5297                         mCodec->mComponentName.c_str(), err);
5298
5299                    mCodec->mPortEOS[kPortIndexInput] = true;
5300                    mCodec->mInputEOSResult = err;
5301                }
5302            } else if (!mCodec->mPortEOS[kPortIndexInput]) {
5303                if (err != OK && err != ERROR_END_OF_STREAM) {
5304                    ALOGV("[%s] Signalling EOS on the input port due to error %d",
5305                         mCodec->mComponentName.c_str(), err);
5306                } else {
5307                    ALOGV("[%s] Signalling EOS on the input port",
5308                         mCodec->mComponentName.c_str());
5309                }
5310
5311                ALOGV("[%s] calling emptyBuffer %u signalling EOS",
5312                     mCodec->mComponentName.c_str(), bufferID);
5313
5314                info->checkReadFence("onInputBufferFilled");
5315                status_t err2 = mCodec->mOMX->emptyBuffer(
5316                        mCodec->mNode,
5317                        bufferID,
5318                        0,
5319                        0,
5320                        OMX_BUFFERFLAG_EOS,
5321                        0,
5322                        info->mFenceFd);
5323                info->mFenceFd = -1;
5324                if (err2 != OK) {
5325                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2));
5326                    return;
5327                }
5328                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
5329
5330                mCodec->mPortEOS[kPortIndexInput] = true;
5331                mCodec->mInputEOSResult = err;
5332            }
5333            break;
5334        }
5335
5336        case FREE_BUFFERS:
5337            break;
5338
5339        default:
5340            ALOGE("invalid port mode: %d", mode);
5341            break;
5342    }
5343}
5344
5345void ACodec::BaseState::getMoreInputDataIfPossible() {
5346    if (mCodec->mPortEOS[kPortIndexInput]) {
5347        return;
5348    }
5349
5350    BufferInfo *eligible = NULL;
5351
5352    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
5353        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
5354
5355#if 0
5356        if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
5357            // There's already a "read" pending.
5358            return;
5359        }
5360#endif
5361
5362        if (info->mStatus == BufferInfo::OWNED_BY_US) {
5363            eligible = info;
5364        }
5365    }
5366
5367    if (eligible == NULL) {
5368        return;
5369    }
5370
5371    postFillThisBuffer(eligible);
5372}
5373
5374bool ACodec::BaseState::onOMXFillBufferDone(
5375        IOMX::buffer_id bufferID,
5376        size_t rangeOffset, size_t rangeLength,
5377        OMX_U32 flags,
5378        int64_t timeUs,
5379        int fenceFd) {
5380    ALOGV("[%s] onOMXFillBufferDone %u time %" PRId64 " us, flags = 0x%08x",
5381         mCodec->mComponentName.c_str(), bufferID, timeUs, flags);
5382
5383    ssize_t index;
5384    status_t err= OK;
5385
5386#if TRACK_BUFFER_TIMING
5387    index = mCodec->mBufferStats.indexOfKey(timeUs);
5388    if (index >= 0) {
5389        ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index);
5390        stats->mFillBufferDoneTimeUs = ALooper::GetNowUs();
5391
5392        ALOGI("frame PTS %lld: %lld",
5393                timeUs,
5394                stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs);
5395
5396        mCodec->mBufferStats.removeItemsAt(index);
5397        stats = NULL;
5398    }
5399#endif
5400
5401    BufferInfo *info =
5402        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
5403    BufferInfo::Status status = BufferInfo::getSafeStatus(info);
5404    if (status != BufferInfo::OWNED_BY_COMPONENT) {
5405        ALOGE("Wrong ownership in FBD: %s(%d) buffer #%u", _asString(status), status, bufferID);
5406        mCodec->dumpBuffers(kPortIndexOutput);
5407        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
5408        if (fenceFd >= 0) {
5409            ::close(fenceFd);
5410        }
5411        return true;
5412    }
5413
5414    info->mDequeuedAt = ++mCodec->mDequeueCounter;
5415    info->mStatus = BufferInfo::OWNED_BY_US;
5416
5417    if (info->mRenderInfo != NULL) {
5418        // The fence for an emptied buffer must have signaled, but there still could be queued
5419        // or out-of-order dequeued buffers in the render queue prior to this buffer. Drop these,
5420        // as we will soon requeue this buffer to the surface. While in theory we could still keep
5421        // track of buffers that are requeued to the surface, it is better to add support to the
5422        // buffer-queue to notify us of released buffers and their fences (in the future).
5423        mCodec->notifyOfRenderedFrames(true /* dropIncomplete */);
5424    }
5425
5426    // byte buffers cannot take fences, so wait for any fence now
5427    if (mCodec->mNativeWindow == NULL) {
5428        (void)mCodec->waitForFence(fenceFd, "onOMXFillBufferDone");
5429        fenceFd = -1;
5430    }
5431    info->setReadFence(fenceFd, "onOMXFillBufferDone");
5432
5433    PortMode mode = getPortMode(kPortIndexOutput);
5434
5435    switch (mode) {
5436        case KEEP_BUFFERS:
5437            break;
5438
5439        case RESUBMIT_BUFFERS:
5440        {
5441            if (rangeLength == 0 && (!(flags & OMX_BUFFERFLAG_EOS)
5442                    || mCodec->mPortEOS[kPortIndexOutput])) {
5443                ALOGV("[%s] calling fillBuffer %u",
5444                     mCodec->mComponentName.c_str(), info->mBufferID);
5445
5446                err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID, info->mFenceFd);
5447                info->mFenceFd = -1;
5448                if (err != OK) {
5449                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5450                    return true;
5451                }
5452
5453                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
5454                break;
5455            }
5456
5457            sp<AMessage> reply =
5458                new AMessage(kWhatOutputBufferDrained, mCodec);
5459
5460            if (mCodec->mOutputFormat != mCodec->mLastOutputFormat && rangeLength > 0) {
5461                mCodec->addKeyFormatChangesToRenderBufferNotification(reply);
5462                mCodec->sendFormatChange();
5463            }
5464
5465            if (mCodec->usingMetadataOnEncoderOutput()) {
5466                native_handle_t *handle = NULL;
5467                VideoGrallocMetadata &grallocMeta = *(VideoGrallocMetadata *)info->mData->data();
5468                VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)info->mData->data();
5469                if (info->mData->size() >= sizeof(grallocMeta)
5470                        && grallocMeta.eType == kMetadataBufferTypeGrallocSource) {
5471                    handle = (native_handle_t *)(uintptr_t)grallocMeta.pHandle;
5472                } else if (info->mData->size() >= sizeof(nativeMeta)
5473                        && nativeMeta.eType == kMetadataBufferTypeANWBuffer) {
5474#ifdef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
5475                    // ANativeWindowBuffer is only valid on 32-bit/mediaserver process
5476                    handle = NULL;
5477#else
5478                    handle = (native_handle_t *)nativeMeta.pBuffer->handle;
5479#endif
5480                }
5481                info->mData->meta()->setPointer("handle", handle);
5482                info->mData->meta()->setInt32("rangeOffset", rangeOffset);
5483                info->mData->meta()->setInt32("rangeLength", rangeLength);
5484            } else {
5485                info->mData->setRange(rangeOffset, rangeLength);
5486            }
5487#if 0
5488            if (mCodec->mNativeWindow == NULL) {
5489                if (IsIDR(info->mData)) {
5490                    ALOGI("IDR frame");
5491                }
5492            }
5493#endif
5494
5495            if (mCodec->mSkipCutBuffer != NULL) {
5496                mCodec->mSkipCutBuffer->submit(info->mData);
5497            }
5498            info->mData->meta()->setInt64("timeUs", timeUs);
5499
5500            sp<AMessage> notify = mCodec->mNotify->dup();
5501            notify->setInt32("what", CodecBase::kWhatDrainThisBuffer);
5502            notify->setInt32("buffer-id", info->mBufferID);
5503            notify->setBuffer("buffer", info->mData);
5504            notify->setInt32("flags", flags);
5505
5506            reply->setInt32("buffer-id", info->mBufferID);
5507
5508            notify->setMessage("reply", reply);
5509
5510            notify->post();
5511
5512            info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
5513
5514            if (flags & OMX_BUFFERFLAG_EOS) {
5515                ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str());
5516
5517                sp<AMessage> notify = mCodec->mNotify->dup();
5518                notify->setInt32("what", CodecBase::kWhatEOS);
5519                notify->setInt32("err", mCodec->mInputEOSResult);
5520                notify->post();
5521
5522                mCodec->mPortEOS[kPortIndexOutput] = true;
5523            }
5524            break;
5525        }
5526
5527        case FREE_BUFFERS:
5528            err = mCodec->freeBuffer(kPortIndexOutput, index);
5529            if (err != OK) {
5530                mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5531                return true;
5532            }
5533            break;
5534
5535        default:
5536            ALOGE("Invalid port mode: %d", mode);
5537            return false;
5538    }
5539
5540    return true;
5541}
5542
5543void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
5544    IOMX::buffer_id bufferID;
5545    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
5546    ssize_t index;
5547    BufferInfo *info = mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
5548    BufferInfo::Status status = BufferInfo::getSafeStatus(info);
5549    if (status != BufferInfo::OWNED_BY_DOWNSTREAM) {
5550        ALOGE("Wrong ownership in OBD: %s(%d) buffer #%u", _asString(status), status, bufferID);
5551        mCodec->dumpBuffers(kPortIndexOutput);
5552        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
5553        return;
5554    }
5555
5556    android_native_rect_t crop;
5557    if (msg->findRect("crop", &crop.left, &crop.top, &crop.right, &crop.bottom)) {
5558        status_t err = native_window_set_crop(mCodec->mNativeWindow.get(), &crop);
5559        ALOGW_IF(err != NO_ERROR, "failed to set crop: %d", err);
5560    }
5561
5562    int32_t render;
5563    if (mCodec->mNativeWindow != NULL
5564            && msg->findInt32("render", &render) && render != 0
5565            && info->mData != NULL && info->mData->size() != 0) {
5566        ATRACE_NAME("render");
5567        // The client wants this buffer to be rendered.
5568
5569        // save buffers sent to the surface so we can get render time when they return
5570        int64_t mediaTimeUs = -1;
5571        info->mData->meta()->findInt64("timeUs", &mediaTimeUs);
5572        if (mediaTimeUs >= 0) {
5573            mCodec->mRenderTracker.onFrameQueued(
5574                    mediaTimeUs, info->mGraphicBuffer, new Fence(::dup(info->mFenceFd)));
5575        }
5576
5577        int64_t timestampNs = 0;
5578        if (!msg->findInt64("timestampNs", &timestampNs)) {
5579            // use media timestamp if client did not request a specific render timestamp
5580            if (info->mData->meta()->findInt64("timeUs", &timestampNs)) {
5581                ALOGV("using buffer PTS of %lld", (long long)timestampNs);
5582                timestampNs *= 1000;
5583            }
5584        }
5585
5586        status_t err;
5587        err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs);
5588        ALOGW_IF(err != NO_ERROR, "failed to set buffer timestamp: %d", err);
5589
5590        info->checkReadFence("onOutputBufferDrained before queueBuffer");
5591        err = mCodec->mNativeWindow->queueBuffer(
5592                    mCodec->mNativeWindow.get(), info->mGraphicBuffer.get(), info->mFenceFd);
5593        info->mFenceFd = -1;
5594        if (err == OK) {
5595            info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
5596        } else {
5597            ALOGE("queueBuffer failed in onOutputBufferDrained: %d", err);
5598            mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5599            info->mStatus = BufferInfo::OWNED_BY_US;
5600            // keeping read fence as write fence to avoid clobbering
5601            info->mIsReadFence = false;
5602        }
5603    } else {
5604        if (mCodec->mNativeWindow != NULL &&
5605            (info->mData == NULL || info->mData->size() != 0)) {
5606            // move read fence into write fence to avoid clobbering
5607            info->mIsReadFence = false;
5608            ATRACE_NAME("frame-drop");
5609        }
5610        info->mStatus = BufferInfo::OWNED_BY_US;
5611    }
5612
5613    PortMode mode = getPortMode(kPortIndexOutput);
5614
5615    switch (mode) {
5616        case KEEP_BUFFERS:
5617        {
5618            // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
5619
5620            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
5621                // We cannot resubmit the buffer we just rendered, dequeue
5622                // the spare instead.
5623
5624                info = mCodec->dequeueBufferFromNativeWindow();
5625            }
5626            break;
5627        }
5628
5629        case RESUBMIT_BUFFERS:
5630        {
5631            if (!mCodec->mPortEOS[kPortIndexOutput]) {
5632                if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
5633                    // We cannot resubmit the buffer we just rendered, dequeue
5634                    // the spare instead.
5635
5636                    info = mCodec->dequeueBufferFromNativeWindow();
5637                }
5638
5639                if (info != NULL) {
5640                    ALOGV("[%s] calling fillBuffer %u",
5641                         mCodec->mComponentName.c_str(), info->mBufferID);
5642                    info->checkWriteFence("onOutputBufferDrained::RESUBMIT_BUFFERS");
5643                    status_t err = mCodec->mOMX->fillBuffer(
5644                            mCodec->mNode, info->mBufferID, info->mFenceFd);
5645                    info->mFenceFd = -1;
5646                    if (err == OK) {
5647                        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
5648                    } else {
5649                        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5650                    }
5651                }
5652            }
5653            break;
5654        }
5655
5656        case FREE_BUFFERS:
5657        {
5658            status_t err = mCodec->freeBuffer(kPortIndexOutput, index);
5659            if (err != OK) {
5660                mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5661            }
5662            break;
5663        }
5664
5665        default:
5666            ALOGE("Invalid port mode: %d", mode);
5667            return;
5668    }
5669}
5670
5671////////////////////////////////////////////////////////////////////////////////
5672
5673ACodec::UninitializedState::UninitializedState(ACodec *codec)
5674    : BaseState(codec) {
5675}
5676
5677void ACodec::UninitializedState::stateEntered() {
5678    ALOGV("Now uninitialized");
5679
5680    if (mDeathNotifier != NULL) {
5681        mCodec->mNodeBinder->unlinkToDeath(mDeathNotifier);
5682        mDeathNotifier.clear();
5683    }
5684
5685    mCodec->mNativeWindow.clear();
5686    mCodec->mNativeWindowUsageBits = 0;
5687    mCodec->mNode = 0;
5688    mCodec->mOMX.clear();
5689    mCodec->mQuirks = 0;
5690    mCodec->mFlags = 0;
5691    mCodec->mInputMetadataType = kMetadataBufferTypeInvalid;
5692    mCodec->mOutputMetadataType = kMetadataBufferTypeInvalid;
5693    mCodec->mComponentName.clear();
5694}
5695
5696bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
5697    bool handled = false;
5698
5699    switch (msg->what()) {
5700        case ACodec::kWhatSetup:
5701        {
5702            onSetup(msg);
5703
5704            handled = true;
5705            break;
5706        }
5707
5708        case ACodec::kWhatAllocateComponent:
5709        {
5710            onAllocateComponent(msg);
5711            handled = true;
5712            break;
5713        }
5714
5715        case ACodec::kWhatShutdown:
5716        {
5717            int32_t keepComponentAllocated;
5718            CHECK(msg->findInt32(
5719                        "keepComponentAllocated", &keepComponentAllocated));
5720            ALOGW_IF(keepComponentAllocated,
5721                     "cannot keep component allocated on shutdown in Uninitialized state");
5722
5723            sp<AMessage> notify = mCodec->mNotify->dup();
5724            notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
5725            notify->post();
5726
5727            handled = true;
5728            break;
5729        }
5730
5731        case ACodec::kWhatFlush:
5732        {
5733            sp<AMessage> notify = mCodec->mNotify->dup();
5734            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5735            notify->post();
5736
5737            handled = true;
5738            break;
5739        }
5740
5741        case ACodec::kWhatReleaseCodecInstance:
5742        {
5743            // nothing to do, as we have already signaled shutdown
5744            handled = true;
5745            break;
5746        }
5747
5748        default:
5749            return BaseState::onMessageReceived(msg);
5750    }
5751
5752    return handled;
5753}
5754
5755void ACodec::UninitializedState::onSetup(
5756        const sp<AMessage> &msg) {
5757    if (onAllocateComponent(msg)
5758            && mCodec->mLoadedState->onConfigureComponent(msg)) {
5759        mCodec->mLoadedState->onStart();
5760    }
5761}
5762
5763bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
5764    ALOGV("onAllocateComponent");
5765
5766    CHECK(mCodec->mNode == 0);
5767
5768    OMXClient client;
5769    if (client.connect() != OK) {
5770        mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
5771        return false;
5772    }
5773
5774    sp<IOMX> omx = client.interface();
5775
5776    sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec);
5777
5778    Vector<AString> matchingCodecs;
5779
5780    AString mime;
5781
5782    AString componentName;
5783    uint32_t quirks = 0;
5784    int32_t encoder = false;
5785    if (msg->findString("componentName", &componentName)) {
5786        sp<IMediaCodecList> list = MediaCodecList::getInstance();
5787        if (list != NULL && list->findCodecByName(componentName.c_str()) >= 0) {
5788            matchingCodecs.add(componentName);
5789        }
5790    } else {
5791        CHECK(msg->findString("mime", &mime));
5792
5793        if (!msg->findInt32("encoder", &encoder)) {
5794            encoder = false;
5795        }
5796
5797        MediaCodecList::findMatchingCodecs(
5798                mime.c_str(),
5799                encoder, // createEncoder
5800                0,       // flags
5801                &matchingCodecs);
5802    }
5803
5804    sp<CodecObserver> observer = new CodecObserver;
5805    IOMX::node_id node = 0;
5806
5807    status_t err = NAME_NOT_FOUND;
5808    for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
5809            ++matchIndex) {
5810        componentName = matchingCodecs[matchIndex];
5811        quirks = MediaCodecList::getQuirksFor(componentName.c_str());
5812
5813        pid_t tid = gettid();
5814        int prevPriority = androidGetThreadPriority(tid);
5815        androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
5816        err = omx->allocateNode(componentName.c_str(), observer, &mCodec->mNodeBinder, &node);
5817        androidSetThreadPriority(tid, prevPriority);
5818
5819        if (err == OK) {
5820            break;
5821        } else {
5822            ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str());
5823        }
5824
5825        node = 0;
5826    }
5827
5828    if (node == 0) {
5829        if (!mime.empty()) {
5830            ALOGE("Unable to instantiate a %scoder for type '%s' with err %#x.",
5831                    encoder ? "en" : "de", mime.c_str(), err);
5832        } else {
5833            ALOGE("Unable to instantiate codec '%s' with err %#x.", componentName.c_str(), err);
5834        }
5835
5836        mCodec->signalError((OMX_ERRORTYPE)err, makeNoSideEffectStatus(err));
5837        return false;
5838    }
5839
5840    mDeathNotifier = new DeathNotifier(notify);
5841    if (mCodec->mNodeBinder == NULL ||
5842            mCodec->mNodeBinder->linkToDeath(mDeathNotifier) != OK) {
5843        // This was a local binder, if it dies so do we, we won't care
5844        // about any notifications in the afterlife.
5845        mDeathNotifier.clear();
5846    }
5847
5848    notify = new AMessage(kWhatOMXMessageList, mCodec);
5849    observer->setNotificationMessage(notify);
5850
5851    mCodec->mComponentName = componentName;
5852    mCodec->mRenderTracker.setComponentName(componentName);
5853    mCodec->mFlags = 0;
5854
5855    if (componentName.endsWith(".secure")) {
5856        mCodec->mFlags |= kFlagIsSecure;
5857        mCodec->mFlags |= kFlagIsGrallocUsageProtected;
5858        mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
5859    }
5860
5861    mCodec->mQuirks = quirks;
5862    mCodec->mOMX = omx;
5863    mCodec->mNode = node;
5864
5865    {
5866        sp<AMessage> notify = mCodec->mNotify->dup();
5867        notify->setInt32("what", CodecBase::kWhatComponentAllocated);
5868        notify->setString("componentName", mCodec->mComponentName.c_str());
5869        notify->post();
5870    }
5871
5872    mCodec->changeState(mCodec->mLoadedState);
5873
5874    return true;
5875}
5876
5877////////////////////////////////////////////////////////////////////////////////
5878
5879ACodec::LoadedState::LoadedState(ACodec *codec)
5880    : BaseState(codec) {
5881}
5882
5883void ACodec::LoadedState::stateEntered() {
5884    ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
5885
5886    mCodec->mPortEOS[kPortIndexInput] =
5887        mCodec->mPortEOS[kPortIndexOutput] = false;
5888
5889    mCodec->mInputEOSResult = OK;
5890
5891    mCodec->mDequeueCounter = 0;
5892    mCodec->mMetadataBuffersToSubmit = 0;
5893    mCodec->mRepeatFrameDelayUs = -1ll;
5894    mCodec->mInputFormat.clear();
5895    mCodec->mOutputFormat.clear();
5896    mCodec->mBaseOutputFormat.clear();
5897
5898    if (mCodec->mShutdownInProgress) {
5899        bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
5900
5901        mCodec->mShutdownInProgress = false;
5902        mCodec->mKeepComponentAllocated = false;
5903
5904        onShutdown(keepComponentAllocated);
5905    }
5906    mCodec->mExplicitShutdown = false;
5907
5908    mCodec->processDeferredMessages();
5909}
5910
5911void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
5912    if (!keepComponentAllocated) {
5913        (void)mCodec->mOMX->freeNode(mCodec->mNode);
5914
5915        mCodec->changeState(mCodec->mUninitializedState);
5916    }
5917
5918    if (mCodec->mExplicitShutdown) {
5919        sp<AMessage> notify = mCodec->mNotify->dup();
5920        notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
5921        notify->post();
5922        mCodec->mExplicitShutdown = false;
5923    }
5924}
5925
5926bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
5927    bool handled = false;
5928
5929    switch (msg->what()) {
5930        case ACodec::kWhatConfigureComponent:
5931        {
5932            onConfigureComponent(msg);
5933            handled = true;
5934            break;
5935        }
5936
5937        case ACodec::kWhatCreateInputSurface:
5938        {
5939            onCreateInputSurface(msg);
5940            handled = true;
5941            break;
5942        }
5943
5944        case ACodec::kWhatSetInputSurface:
5945        {
5946            onSetInputSurface(msg);
5947            handled = true;
5948            break;
5949        }
5950
5951        case ACodec::kWhatStart:
5952        {
5953            onStart();
5954            handled = true;
5955            break;
5956        }
5957
5958        case ACodec::kWhatShutdown:
5959        {
5960            int32_t keepComponentAllocated;
5961            CHECK(msg->findInt32(
5962                        "keepComponentAllocated", &keepComponentAllocated));
5963
5964            mCodec->mExplicitShutdown = true;
5965            onShutdown(keepComponentAllocated);
5966
5967            handled = true;
5968            break;
5969        }
5970
5971        case ACodec::kWhatFlush:
5972        {
5973            sp<AMessage> notify = mCodec->mNotify->dup();
5974            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5975            notify->post();
5976
5977            handled = true;
5978            break;
5979        }
5980
5981        default:
5982            return BaseState::onMessageReceived(msg);
5983    }
5984
5985    return handled;
5986}
5987
5988bool ACodec::LoadedState::onConfigureComponent(
5989        const sp<AMessage> &msg) {
5990    ALOGV("onConfigureComponent");
5991
5992    CHECK(mCodec->mNode != 0);
5993
5994    status_t err = OK;
5995    AString mime;
5996    if (!msg->findString("mime", &mime)) {
5997        err = BAD_VALUE;
5998    } else {
5999        err = mCodec->configureCodec(mime.c_str(), msg);
6000    }
6001    if (err != OK) {
6002        ALOGE("[%s] configureCodec returning error %d",
6003              mCodec->mComponentName.c_str(), err);
6004
6005        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6006        return false;
6007    }
6008
6009    {
6010        sp<AMessage> notify = mCodec->mNotify->dup();
6011        notify->setInt32("what", CodecBase::kWhatComponentConfigured);
6012        notify->setMessage("input-format", mCodec->mInputFormat);
6013        notify->setMessage("output-format", mCodec->mOutputFormat);
6014        notify->post();
6015    }
6016
6017    return true;
6018}
6019
6020status_t ACodec::LoadedState::setupInputSurface() {
6021    status_t err = OK;
6022
6023    if (mCodec->mRepeatFrameDelayUs > 0ll) {
6024        err = mCodec->mOMX->setInternalOption(
6025                mCodec->mNode,
6026                kPortIndexInput,
6027                IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY,
6028                &mCodec->mRepeatFrameDelayUs,
6029                sizeof(mCodec->mRepeatFrameDelayUs));
6030
6031        if (err != OK) {
6032            ALOGE("[%s] Unable to configure option to repeat previous "
6033                  "frames (err %d)",
6034                  mCodec->mComponentName.c_str(),
6035                  err);
6036            return err;
6037        }
6038    }
6039
6040    if (mCodec->mMaxPtsGapUs > 0ll) {
6041        err = mCodec->mOMX->setInternalOption(
6042                mCodec->mNode,
6043                kPortIndexInput,
6044                IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP,
6045                &mCodec->mMaxPtsGapUs,
6046                sizeof(mCodec->mMaxPtsGapUs));
6047
6048        if (err != OK) {
6049            ALOGE("[%s] Unable to configure max timestamp gap (err %d)",
6050                    mCodec->mComponentName.c_str(),
6051                    err);
6052            return err;
6053        }
6054    }
6055
6056    if (mCodec->mMaxFps > 0) {
6057        err = mCodec->mOMX->setInternalOption(
6058                mCodec->mNode,
6059                kPortIndexInput,
6060                IOMX::INTERNAL_OPTION_MAX_FPS,
6061                &mCodec->mMaxFps,
6062                sizeof(mCodec->mMaxFps));
6063
6064        if (err != OK) {
6065            ALOGE("[%s] Unable to configure max fps (err %d)",
6066                    mCodec->mComponentName.c_str(),
6067                    err);
6068            return err;
6069        }
6070    }
6071
6072    if (mCodec->mTimePerCaptureUs > 0ll
6073            && mCodec->mTimePerFrameUs > 0ll) {
6074        int64_t timeLapse[2];
6075        timeLapse[0] = mCodec->mTimePerFrameUs;
6076        timeLapse[1] = mCodec->mTimePerCaptureUs;
6077        err = mCodec->mOMX->setInternalOption(
6078                mCodec->mNode,
6079                kPortIndexInput,
6080                IOMX::INTERNAL_OPTION_TIME_LAPSE,
6081                &timeLapse[0],
6082                sizeof(timeLapse));
6083
6084        if (err != OK) {
6085            ALOGE("[%s] Unable to configure time lapse (err %d)",
6086                    mCodec->mComponentName.c_str(),
6087                    err);
6088            return err;
6089        }
6090    }
6091
6092    if (mCodec->mCreateInputBuffersSuspended) {
6093        bool suspend = true;
6094        err = mCodec->mOMX->setInternalOption(
6095                mCodec->mNode,
6096                kPortIndexInput,
6097                IOMX::INTERNAL_OPTION_SUSPEND,
6098                &suspend,
6099                sizeof(suspend));
6100
6101        if (err != OK) {
6102            ALOGE("[%s] Unable to configure option to suspend (err %d)",
6103                  mCodec->mComponentName.c_str(),
6104                  err);
6105            return err;
6106        }
6107    }
6108
6109    uint32_t usageBits;
6110    if (mCodec->mOMX->getParameter(
6111            mCodec->mNode, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
6112            &usageBits, sizeof(usageBits)) == OK) {
6113        mCodec->mInputFormat->setInt32(
6114                "using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN));
6115    }
6116
6117    return OK;
6118}
6119
6120void ACodec::LoadedState::onCreateInputSurface(
6121        const sp<AMessage> & /* msg */) {
6122    ALOGV("onCreateInputSurface");
6123
6124    sp<AMessage> notify = mCodec->mNotify->dup();
6125    notify->setInt32("what", CodecBase::kWhatInputSurfaceCreated);
6126
6127    sp<IGraphicBufferProducer> bufferProducer;
6128    status_t err = mCodec->mOMX->createInputSurface(
6129            mCodec->mNode, kPortIndexInput, &bufferProducer, &mCodec->mInputMetadataType);
6130
6131    if (err == OK) {
6132        err = setupInputSurface();
6133    }
6134
6135    if (err == OK) {
6136        notify->setObject("input-surface",
6137                new BufferProducerWrapper(bufferProducer));
6138    } else {
6139        // Can't use mCodec->signalError() here -- MediaCodec won't forward
6140        // the error through because it's in the "configured" state.  We
6141        // send a kWhatInputSurfaceCreated with an error value instead.
6142        ALOGE("[%s] onCreateInputSurface returning error %d",
6143                mCodec->mComponentName.c_str(), err);
6144        notify->setInt32("err", err);
6145    }
6146    notify->post();
6147}
6148
6149void ACodec::LoadedState::onSetInputSurface(
6150        const sp<AMessage> &msg) {
6151    ALOGV("onSetInputSurface");
6152
6153    sp<AMessage> notify = mCodec->mNotify->dup();
6154    notify->setInt32("what", CodecBase::kWhatInputSurfaceAccepted);
6155
6156    sp<RefBase> obj;
6157    CHECK(msg->findObject("input-surface", &obj));
6158    sp<PersistentSurface> surface = static_cast<PersistentSurface *>(obj.get());
6159
6160    status_t err = mCodec->mOMX->setInputSurface(
6161            mCodec->mNode, kPortIndexInput, surface->getBufferConsumer(),
6162            &mCodec->mInputMetadataType);
6163
6164    if (err == OK) {
6165        err = setupInputSurface();
6166    }
6167
6168    if (err != OK) {
6169        // Can't use mCodec->signalError() here -- MediaCodec won't forward
6170        // the error through because it's in the "configured" state.  We
6171        // send a kWhatInputSurfaceAccepted with an error value instead.
6172        ALOGE("[%s] onSetInputSurface returning error %d",
6173                mCodec->mComponentName.c_str(), err);
6174        notify->setInt32("err", err);
6175    }
6176    notify->post();
6177}
6178
6179void ACodec::LoadedState::onStart() {
6180    ALOGV("onStart");
6181
6182    status_t err = mCodec->mOMX->sendCommand(mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle);
6183    if (err != OK) {
6184        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6185    } else {
6186        mCodec->changeState(mCodec->mLoadedToIdleState);
6187    }
6188}
6189
6190////////////////////////////////////////////////////////////////////////////////
6191
6192ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
6193    : BaseState(codec) {
6194}
6195
6196void ACodec::LoadedToIdleState::stateEntered() {
6197    ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
6198
6199    status_t err;
6200    if ((err = allocateBuffers()) != OK) {
6201        ALOGE("Failed to allocate buffers after transitioning to IDLE state "
6202             "(error 0x%08x)",
6203             err);
6204
6205        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6206
6207        mCodec->mOMX->sendCommand(
6208                mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded);
6209        if (mCodec->allYourBuffersAreBelongToUs(kPortIndexInput)) {
6210            mCodec->freeBuffersOnPort(kPortIndexInput);
6211        }
6212        if (mCodec->allYourBuffersAreBelongToUs(kPortIndexOutput)) {
6213            mCodec->freeBuffersOnPort(kPortIndexOutput);
6214        }
6215
6216        mCodec->changeState(mCodec->mLoadedState);
6217    }
6218}
6219
6220status_t ACodec::LoadedToIdleState::allocateBuffers() {
6221    status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
6222
6223    if (err != OK) {
6224        return err;
6225    }
6226
6227    return mCodec->allocateBuffersOnPort(kPortIndexOutput);
6228}
6229
6230bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
6231    switch (msg->what()) {
6232        case kWhatSetParameters:
6233        case kWhatShutdown:
6234        {
6235            mCodec->deferMessage(msg);
6236            return true;
6237        }
6238
6239        case kWhatSignalEndOfInputStream:
6240        {
6241            mCodec->onSignalEndOfInputStream();
6242            return true;
6243        }
6244
6245        case kWhatResume:
6246        {
6247            // We'll be active soon enough.
6248            return true;
6249        }
6250
6251        case kWhatFlush:
6252        {
6253            // We haven't even started yet, so we're flushed alright...
6254            sp<AMessage> notify = mCodec->mNotify->dup();
6255            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
6256            notify->post();
6257            return true;
6258        }
6259
6260        default:
6261            return BaseState::onMessageReceived(msg);
6262    }
6263}
6264
6265bool ACodec::LoadedToIdleState::onOMXEvent(
6266        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6267    switch (event) {
6268        case OMX_EventCmdComplete:
6269        {
6270            status_t err = OK;
6271            if (data1 != (OMX_U32)OMX_CommandStateSet
6272                    || data2 != (OMX_U32)OMX_StateIdle) {
6273                ALOGE("Unexpected command completion in LoadedToIdleState: %s(%u) %s(%u)",
6274                        asString((OMX_COMMANDTYPE)data1), data1,
6275                        asString((OMX_STATETYPE)data2), data2);
6276                err = FAILED_TRANSACTION;
6277            }
6278
6279            if (err == OK) {
6280                err = mCodec->mOMX->sendCommand(
6281                    mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting);
6282            }
6283
6284            if (err != OK) {
6285                mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6286            } else {
6287                mCodec->changeState(mCodec->mIdleToExecutingState);
6288            }
6289
6290            return true;
6291        }
6292
6293        default:
6294            return BaseState::onOMXEvent(event, data1, data2);
6295    }
6296}
6297
6298////////////////////////////////////////////////////////////////////////////////
6299
6300ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
6301    : BaseState(codec) {
6302}
6303
6304void ACodec::IdleToExecutingState::stateEntered() {
6305    ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
6306}
6307
6308bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
6309    switch (msg->what()) {
6310        case kWhatSetParameters:
6311        case kWhatShutdown:
6312        {
6313            mCodec->deferMessage(msg);
6314            return true;
6315        }
6316
6317        case kWhatResume:
6318        {
6319            // We'll be active soon enough.
6320            return true;
6321        }
6322
6323        case kWhatFlush:
6324        {
6325            // We haven't even started yet, so we're flushed alright...
6326            sp<AMessage> notify = mCodec->mNotify->dup();
6327            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
6328            notify->post();
6329
6330            return true;
6331        }
6332
6333        case kWhatSignalEndOfInputStream:
6334        {
6335            mCodec->onSignalEndOfInputStream();
6336            return true;
6337        }
6338
6339        default:
6340            return BaseState::onMessageReceived(msg);
6341    }
6342}
6343
6344bool ACodec::IdleToExecutingState::onOMXEvent(
6345        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6346    switch (event) {
6347        case OMX_EventCmdComplete:
6348        {
6349            if (data1 != (OMX_U32)OMX_CommandStateSet
6350                    || data2 != (OMX_U32)OMX_StateExecuting) {
6351                ALOGE("Unexpected command completion in IdleToExecutingState: %s(%u) %s(%u)",
6352                        asString((OMX_COMMANDTYPE)data1), data1,
6353                        asString((OMX_STATETYPE)data2), data2);
6354                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6355                return true;
6356            }
6357
6358            mCodec->mExecutingState->resume();
6359            mCodec->changeState(mCodec->mExecutingState);
6360
6361            return true;
6362        }
6363
6364        default:
6365            return BaseState::onOMXEvent(event, data1, data2);
6366    }
6367}
6368
6369////////////////////////////////////////////////////////////////////////////////
6370
6371ACodec::ExecutingState::ExecutingState(ACodec *codec)
6372    : BaseState(codec),
6373      mActive(false) {
6374}
6375
6376ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
6377        OMX_U32 /* portIndex */) {
6378    return RESUBMIT_BUFFERS;
6379}
6380
6381void ACodec::ExecutingState::submitOutputMetaBuffers() {
6382    // submit as many buffers as there are input buffers with the codec
6383    // in case we are in port reconfiguring
6384    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
6385        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
6386
6387        if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) {
6388            if (mCodec->submitOutputMetadataBuffer() != OK)
6389                break;
6390        }
6391    }
6392
6393    // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
6394    mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround();
6395}
6396
6397void ACodec::ExecutingState::submitRegularOutputBuffers() {
6398    bool failed = false;
6399    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
6400        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
6401
6402        if (mCodec->mNativeWindow != NULL) {
6403            if (info->mStatus != BufferInfo::OWNED_BY_US
6404                    && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
6405                ALOGE("buffers should be owned by us or the surface");
6406                failed = true;
6407                break;
6408            }
6409
6410            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
6411                continue;
6412            }
6413        } else {
6414            if (info->mStatus != BufferInfo::OWNED_BY_US) {
6415                ALOGE("buffers should be owned by us");
6416                failed = true;
6417                break;
6418            }
6419        }
6420
6421        ALOGV("[%s] calling fillBuffer %u", mCodec->mComponentName.c_str(), info->mBufferID);
6422
6423        info->checkWriteFence("submitRegularOutputBuffers");
6424        status_t err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID, info->mFenceFd);
6425        info->mFenceFd = -1;
6426        if (err != OK) {
6427            failed = true;
6428            break;
6429        }
6430
6431        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
6432    }
6433
6434    if (failed) {
6435        mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6436    }
6437}
6438
6439void ACodec::ExecutingState::submitOutputBuffers() {
6440    submitRegularOutputBuffers();
6441    if (mCodec->storingMetadataInDecodedBuffers()) {
6442        submitOutputMetaBuffers();
6443    }
6444}
6445
6446void ACodec::ExecutingState::resume() {
6447    if (mActive) {
6448        ALOGV("[%s] We're already active, no need to resume.", mCodec->mComponentName.c_str());
6449        return;
6450    }
6451
6452    submitOutputBuffers();
6453
6454    // Post all available input buffers
6455    if (mCodec->mBuffers[kPortIndexInput].size() == 0u) {
6456        ALOGW("[%s] we don't have any input buffers to resume", mCodec->mComponentName.c_str());
6457    }
6458
6459    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) {
6460        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
6461        if (info->mStatus == BufferInfo::OWNED_BY_US) {
6462            postFillThisBuffer(info);
6463        }
6464    }
6465
6466    mActive = true;
6467}
6468
6469void ACodec::ExecutingState::stateEntered() {
6470    ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
6471
6472    mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC));
6473    mCodec->processDeferredMessages();
6474}
6475
6476bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
6477    bool handled = false;
6478
6479    switch (msg->what()) {
6480        case kWhatShutdown:
6481        {
6482            int32_t keepComponentAllocated;
6483            CHECK(msg->findInt32(
6484                        "keepComponentAllocated", &keepComponentAllocated));
6485
6486            mCodec->mShutdownInProgress = true;
6487            mCodec->mExplicitShutdown = true;
6488            mCodec->mKeepComponentAllocated = keepComponentAllocated;
6489
6490            mActive = false;
6491
6492            status_t err = mCodec->mOMX->sendCommand(
6493                    mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle);
6494            if (err != OK) {
6495                if (keepComponentAllocated) {
6496                    mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6497                }
6498                // TODO: do some recovery here.
6499            } else {
6500                mCodec->changeState(mCodec->mExecutingToIdleState);
6501            }
6502
6503            handled = true;
6504            break;
6505        }
6506
6507        case kWhatFlush:
6508        {
6509            ALOGV("[%s] ExecutingState flushing now "
6510                 "(codec owns %zu/%zu input, %zu/%zu output).",
6511                    mCodec->mComponentName.c_str(),
6512                    mCodec->countBuffersOwnedByComponent(kPortIndexInput),
6513                    mCodec->mBuffers[kPortIndexInput].size(),
6514                    mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
6515                    mCodec->mBuffers[kPortIndexOutput].size());
6516
6517            mActive = false;
6518
6519            status_t err = mCodec->mOMX->sendCommand(mCodec->mNode, OMX_CommandFlush, OMX_ALL);
6520            if (err != OK) {
6521                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6522            } else {
6523                mCodec->changeState(mCodec->mFlushingState);
6524            }
6525
6526            handled = true;
6527            break;
6528        }
6529
6530        case kWhatResume:
6531        {
6532            resume();
6533
6534            handled = true;
6535            break;
6536        }
6537
6538        case kWhatRequestIDRFrame:
6539        {
6540            status_t err = mCodec->requestIDRFrame();
6541            if (err != OK) {
6542                ALOGW("Requesting an IDR frame failed.");
6543            }
6544
6545            handled = true;
6546            break;
6547        }
6548
6549        case kWhatSetParameters:
6550        {
6551            sp<AMessage> params;
6552            CHECK(msg->findMessage("params", &params));
6553
6554            status_t err = mCodec->setParameters(params);
6555
6556            sp<AMessage> reply;
6557            if (msg->findMessage("reply", &reply)) {
6558                reply->setInt32("err", err);
6559                reply->post();
6560            }
6561
6562            handled = true;
6563            break;
6564        }
6565
6566        case ACodec::kWhatSignalEndOfInputStream:
6567        {
6568            mCodec->onSignalEndOfInputStream();
6569            handled = true;
6570            break;
6571        }
6572
6573        // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
6574        case kWhatSubmitOutputMetadataBufferIfEOS:
6575        {
6576            if (mCodec->mPortEOS[kPortIndexInput] &&
6577                    !mCodec->mPortEOS[kPortIndexOutput]) {
6578                status_t err = mCodec->submitOutputMetadataBuffer();
6579                if (err == OK) {
6580                    mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround();
6581                }
6582            }
6583            return true;
6584        }
6585
6586        default:
6587            handled = BaseState::onMessageReceived(msg);
6588            break;
6589    }
6590
6591    return handled;
6592}
6593
6594status_t ACodec::setParameters(const sp<AMessage> &params) {
6595    int32_t videoBitrate;
6596    if (params->findInt32("video-bitrate", &videoBitrate)) {
6597        OMX_VIDEO_CONFIG_BITRATETYPE configParams;
6598        InitOMXParams(&configParams);
6599        configParams.nPortIndex = kPortIndexOutput;
6600        configParams.nEncodeBitrate = videoBitrate;
6601
6602        status_t err = mOMX->setConfig(
6603                mNode,
6604                OMX_IndexConfigVideoBitrate,
6605                &configParams,
6606                sizeof(configParams));
6607
6608        if (err != OK) {
6609            ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d",
6610                   videoBitrate, err);
6611
6612            return err;
6613        }
6614    }
6615
6616    int64_t skipFramesBeforeUs;
6617    if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) {
6618        status_t err =
6619            mOMX->setInternalOption(
6620                     mNode,
6621                     kPortIndexInput,
6622                     IOMX::INTERNAL_OPTION_START_TIME,
6623                     &skipFramesBeforeUs,
6624                     sizeof(skipFramesBeforeUs));
6625
6626        if (err != OK) {
6627            ALOGE("Failed to set parameter 'skip-frames-before' (err %d)", err);
6628            return err;
6629        }
6630    }
6631
6632    int32_t dropInputFrames;
6633    if (params->findInt32("drop-input-frames", &dropInputFrames)) {
6634        bool suspend = dropInputFrames != 0;
6635
6636        status_t err =
6637            mOMX->setInternalOption(
6638                     mNode,
6639                     kPortIndexInput,
6640                     IOMX::INTERNAL_OPTION_SUSPEND,
6641                     &suspend,
6642                     sizeof(suspend));
6643
6644        if (err != OK) {
6645            ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err);
6646            return err;
6647        }
6648    }
6649
6650    int32_t dummy;
6651    if (params->findInt32("request-sync", &dummy)) {
6652        status_t err = requestIDRFrame();
6653
6654        if (err != OK) {
6655            ALOGE("Requesting a sync frame failed w/ err %d", err);
6656            return err;
6657        }
6658    }
6659
6660    float rate;
6661    if (params->findFloat("operating-rate", &rate) && rate > 0) {
6662        status_t err = setOperatingRate(rate, mIsVideo);
6663        if (err != OK) {
6664            ALOGE("Failed to set parameter 'operating-rate' (err %d)", err);
6665            return err;
6666        }
6667    }
6668
6669    int32_t intraRefreshPeriod = 0;
6670    if (params->findInt32("intra-refresh-period", &intraRefreshPeriod)
6671            && intraRefreshPeriod > 0) {
6672        status_t err = setIntraRefreshPeriod(intraRefreshPeriod, false);
6673        if (err != OK) {
6674            ALOGI("[%s] failed setIntraRefreshPeriod. Failure is fine since this key is optional",
6675                    mComponentName.c_str());
6676            err = OK;
6677        }
6678    }
6679
6680    return OK;
6681}
6682
6683void ACodec::onSignalEndOfInputStream() {
6684    sp<AMessage> notify = mNotify->dup();
6685    notify->setInt32("what", CodecBase::kWhatSignaledInputEOS);
6686
6687    status_t err = mOMX->signalEndOfInputStream(mNode);
6688    if (err != OK) {
6689        notify->setInt32("err", err);
6690    }
6691    notify->post();
6692}
6693
6694bool ACodec::ExecutingState::onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) {
6695    mCodec->onFrameRendered(mediaTimeUs, systemNano);
6696    return true;
6697}
6698
6699bool ACodec::ExecutingState::onOMXEvent(
6700        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6701    switch (event) {
6702        case OMX_EventPortSettingsChanged:
6703        {
6704            CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
6705
6706            mCodec->onOutputFormatChanged();
6707
6708            if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
6709                mCodec->mMetadataBuffersToSubmit = 0;
6710                CHECK_EQ(mCodec->mOMX->sendCommand(
6711                            mCodec->mNode,
6712                            OMX_CommandPortDisable, kPortIndexOutput),
6713                         (status_t)OK);
6714
6715                mCodec->freeOutputBuffersNotOwnedByComponent();
6716
6717                mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
6718            } else if (data2 != OMX_IndexConfigCommonOutputCrop
6719                    && data2 != OMX_IndexConfigAndroidIntraRefresh) {
6720                ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08x",
6721                     mCodec->mComponentName.c_str(), data2);
6722            }
6723
6724            return true;
6725        }
6726
6727        case OMX_EventBufferFlag:
6728        {
6729            return true;
6730        }
6731
6732        default:
6733            return BaseState::onOMXEvent(event, data1, data2);
6734    }
6735}
6736
6737////////////////////////////////////////////////////////////////////////////////
6738
6739ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
6740        ACodec *codec)
6741    : BaseState(codec) {
6742}
6743
6744ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
6745        OMX_U32 portIndex) {
6746    if (portIndex == kPortIndexOutput) {
6747        return FREE_BUFFERS;
6748    }
6749
6750    CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
6751
6752    return RESUBMIT_BUFFERS;
6753}
6754
6755bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
6756        const sp<AMessage> &msg) {
6757    bool handled = false;
6758
6759    switch (msg->what()) {
6760        case kWhatFlush:
6761        case kWhatShutdown:
6762        case kWhatResume:
6763        case kWhatSetParameters:
6764        {
6765            if (msg->what() == kWhatResume) {
6766                ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
6767            }
6768
6769            mCodec->deferMessage(msg);
6770            handled = true;
6771            break;
6772        }
6773
6774        default:
6775            handled = BaseState::onMessageReceived(msg);
6776            break;
6777    }
6778
6779    return handled;
6780}
6781
6782void ACodec::OutputPortSettingsChangedState::stateEntered() {
6783    ALOGV("[%s] Now handling output port settings change",
6784         mCodec->mComponentName.c_str());
6785}
6786
6787bool ACodec::OutputPortSettingsChangedState::onOMXFrameRendered(
6788        int64_t mediaTimeUs, nsecs_t systemNano) {
6789    mCodec->onFrameRendered(mediaTimeUs, systemNano);
6790    return true;
6791}
6792
6793bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
6794        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6795    switch (event) {
6796        case OMX_EventCmdComplete:
6797        {
6798            if (data1 == (OMX_U32)OMX_CommandPortDisable) {
6799                if (data2 != (OMX_U32)kPortIndexOutput) {
6800                    ALOGW("ignoring EventCmdComplete CommandPortDisable for port %u", data2);
6801                    return false;
6802                }
6803
6804                ALOGV("[%s] Output port now disabled.", mCodec->mComponentName.c_str());
6805
6806                status_t err = OK;
6807                if (!mCodec->mBuffers[kPortIndexOutput].isEmpty()) {
6808                    ALOGE("disabled port should be empty, but has %zu buffers",
6809                            mCodec->mBuffers[kPortIndexOutput].size());
6810                    err = FAILED_TRANSACTION;
6811                } else {
6812                    mCodec->mDealer[kPortIndexOutput].clear();
6813                }
6814
6815                if (err == OK) {
6816                    err = mCodec->mOMX->sendCommand(
6817                            mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput);
6818                }
6819
6820                if (err == OK) {
6821                    err = mCodec->allocateBuffersOnPort(kPortIndexOutput);
6822                    ALOGE_IF(err != OK, "Failed to allocate output port buffers after port "
6823                            "reconfiguration: (%d)", err);
6824                }
6825
6826                if (err != OK) {
6827                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
6828
6829                    // This is technically not correct, but appears to be
6830                    // the only way to free the component instance.
6831                    // Controlled transitioning from excecuting->idle
6832                    // and idle->loaded seem impossible probably because
6833                    // the output port never finishes re-enabling.
6834                    mCodec->mShutdownInProgress = true;
6835                    mCodec->mKeepComponentAllocated = false;
6836                    mCodec->changeState(mCodec->mLoadedState);
6837                }
6838
6839                return true;
6840            } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
6841                if (data2 != (OMX_U32)kPortIndexOutput) {
6842                    ALOGW("ignoring EventCmdComplete OMX_CommandPortEnable for port %u", data2);
6843                    return false;
6844                }
6845
6846                ALOGV("[%s] Output port now reenabled.", mCodec->mComponentName.c_str());
6847
6848                if (mCodec->mExecutingState->active()) {
6849                    mCodec->mExecutingState->submitOutputBuffers();
6850                }
6851
6852                mCodec->changeState(mCodec->mExecutingState);
6853
6854                return true;
6855            }
6856
6857            return false;
6858        }
6859
6860        default:
6861            return false;
6862    }
6863}
6864
6865////////////////////////////////////////////////////////////////////////////////
6866
6867ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
6868    : BaseState(codec),
6869      mComponentNowIdle(false) {
6870}
6871
6872bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
6873    bool handled = false;
6874
6875    switch (msg->what()) {
6876        case kWhatFlush:
6877        {
6878            // Don't send me a flush request if you previously wanted me
6879            // to shutdown.
6880            ALOGW("Ignoring flush request in ExecutingToIdleState");
6881            break;
6882        }
6883
6884        case kWhatShutdown:
6885        {
6886            // We're already doing that...
6887
6888            handled = true;
6889            break;
6890        }
6891
6892        default:
6893            handled = BaseState::onMessageReceived(msg);
6894            break;
6895    }
6896
6897    return handled;
6898}
6899
6900void ACodec::ExecutingToIdleState::stateEntered() {
6901    ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
6902
6903    mComponentNowIdle = false;
6904    mCodec->mLastOutputFormat.clear();
6905}
6906
6907bool ACodec::ExecutingToIdleState::onOMXEvent(
6908        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
6909    switch (event) {
6910        case OMX_EventCmdComplete:
6911        {
6912            if (data1 != (OMX_U32)OMX_CommandStateSet
6913                    || data2 != (OMX_U32)OMX_StateIdle) {
6914                ALOGE("Unexpected command completion in ExecutingToIdleState: %s(%u) %s(%u)",
6915                        asString((OMX_COMMANDTYPE)data1), data1,
6916                        asString((OMX_STATETYPE)data2), data2);
6917                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6918                return true;
6919            }
6920
6921            mComponentNowIdle = true;
6922
6923            changeStateIfWeOwnAllBuffers();
6924
6925            return true;
6926        }
6927
6928        case OMX_EventPortSettingsChanged:
6929        case OMX_EventBufferFlag:
6930        {
6931            // We're shutting down and don't care about this anymore.
6932            return true;
6933        }
6934
6935        default:
6936            return BaseState::onOMXEvent(event, data1, data2);
6937    }
6938}
6939
6940void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
6941    if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
6942        status_t err = mCodec->mOMX->sendCommand(
6943                mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded);
6944        if (err == OK) {
6945            err = mCodec->freeBuffersOnPort(kPortIndexInput);
6946            status_t err2 = mCodec->freeBuffersOnPort(kPortIndexOutput);
6947            if (err == OK) {
6948                err = err2;
6949            }
6950        }
6951
6952        if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown)
6953                && mCodec->mNativeWindow != NULL) {
6954            // We push enough 1x1 blank buffers to ensure that one of
6955            // them has made it to the display.  This allows the OMX
6956            // component teardown to zero out any protected buffers
6957            // without the risk of scanning out one of those buffers.
6958            pushBlankBuffersToNativeWindow(mCodec->mNativeWindow.get());
6959        }
6960
6961        if (err != OK) {
6962            mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
6963            return;
6964        }
6965
6966        mCodec->changeState(mCodec->mIdleToLoadedState);
6967    }
6968}
6969
6970void ACodec::ExecutingToIdleState::onInputBufferFilled(
6971        const sp<AMessage> &msg) {
6972    BaseState::onInputBufferFilled(msg);
6973
6974    changeStateIfWeOwnAllBuffers();
6975}
6976
6977void ACodec::ExecutingToIdleState::onOutputBufferDrained(
6978        const sp<AMessage> &msg) {
6979    BaseState::onOutputBufferDrained(msg);
6980
6981    changeStateIfWeOwnAllBuffers();
6982}
6983
6984////////////////////////////////////////////////////////////////////////////////
6985
6986ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
6987    : BaseState(codec) {
6988}
6989
6990bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
6991    bool handled = false;
6992
6993    switch (msg->what()) {
6994        case kWhatShutdown:
6995        {
6996            // We're already doing that...
6997
6998            handled = true;
6999            break;
7000        }
7001
7002        case kWhatFlush:
7003        {
7004            // Don't send me a flush request if you previously wanted me
7005            // to shutdown.
7006            ALOGE("Got flush request in IdleToLoadedState");
7007            break;
7008        }
7009
7010        default:
7011            handled = BaseState::onMessageReceived(msg);
7012            break;
7013    }
7014
7015    return handled;
7016}
7017
7018void ACodec::IdleToLoadedState::stateEntered() {
7019    ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
7020}
7021
7022bool ACodec::IdleToLoadedState::onOMXEvent(
7023        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
7024    switch (event) {
7025        case OMX_EventCmdComplete:
7026        {
7027            if (data1 != (OMX_U32)OMX_CommandStateSet
7028                    || data2 != (OMX_U32)OMX_StateLoaded) {
7029                ALOGE("Unexpected command completion in IdleToLoadedState: %s(%u) %s(%u)",
7030                        asString((OMX_COMMANDTYPE)data1), data1,
7031                        asString((OMX_STATETYPE)data2), data2);
7032                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
7033                return true;
7034            }
7035
7036            mCodec->changeState(mCodec->mLoadedState);
7037
7038            return true;
7039        }
7040
7041        default:
7042            return BaseState::onOMXEvent(event, data1, data2);
7043    }
7044}
7045
7046////////////////////////////////////////////////////////////////////////////////
7047
7048ACodec::FlushingState::FlushingState(ACodec *codec)
7049    : BaseState(codec) {
7050}
7051
7052void ACodec::FlushingState::stateEntered() {
7053    ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
7054
7055    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
7056}
7057
7058bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
7059    bool handled = false;
7060
7061    switch (msg->what()) {
7062        case kWhatShutdown:
7063        {
7064            mCodec->deferMessage(msg);
7065            break;
7066        }
7067
7068        case kWhatFlush:
7069        {
7070            // We're already doing this right now.
7071            handled = true;
7072            break;
7073        }
7074
7075        default:
7076            handled = BaseState::onMessageReceived(msg);
7077            break;
7078    }
7079
7080    return handled;
7081}
7082
7083bool ACodec::FlushingState::onOMXEvent(
7084        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
7085    ALOGV("[%s] FlushingState onOMXEvent(%u,%d)",
7086            mCodec->mComponentName.c_str(), event, (OMX_S32)data1);
7087
7088    switch (event) {
7089        case OMX_EventCmdComplete:
7090        {
7091            if (data1 != (OMX_U32)OMX_CommandFlush) {
7092                ALOGE("unexpected EventCmdComplete %s(%d) data2:%d in FlushingState",
7093                        asString((OMX_COMMANDTYPE)data1), data1, data2);
7094                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
7095                return true;
7096            }
7097
7098            if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
7099                if (mFlushComplete[data2]) {
7100                    ALOGW("Flush already completed for %s port",
7101                            data2 == kPortIndexInput ? "input" : "output");
7102                    return true;
7103                }
7104                mFlushComplete[data2] = true;
7105
7106                if (mFlushComplete[kPortIndexInput] && mFlushComplete[kPortIndexOutput]) {
7107                    changeStateIfWeOwnAllBuffers();
7108                }
7109            } else if (data2 == OMX_ALL) {
7110                if (!mFlushComplete[kPortIndexInput] || !mFlushComplete[kPortIndexOutput]) {
7111                    ALOGW("received flush complete event for OMX_ALL before ports have been"
7112                            "flushed (%d/%d)",
7113                            mFlushComplete[kPortIndexInput], mFlushComplete[kPortIndexOutput]);
7114                    return false;
7115                }
7116
7117                changeStateIfWeOwnAllBuffers();
7118            } else {
7119                ALOGW("data2 not OMX_ALL but %u in EventCmdComplete CommandFlush", data2);
7120            }
7121
7122            return true;
7123        }
7124
7125        case OMX_EventPortSettingsChanged:
7126        {
7127            sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec);
7128            msg->setInt32("type", omx_message::EVENT);
7129            msg->setInt32("node", mCodec->mNode);
7130            msg->setInt32("event", event);
7131            msg->setInt32("data1", data1);
7132            msg->setInt32("data2", data2);
7133
7134            ALOGV("[%s] Deferring OMX_EventPortSettingsChanged",
7135                 mCodec->mComponentName.c_str());
7136
7137            mCodec->deferMessage(msg);
7138
7139            return true;
7140        }
7141
7142        default:
7143            return BaseState::onOMXEvent(event, data1, data2);
7144    }
7145
7146    return true;
7147}
7148
7149void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
7150    BaseState::onOutputBufferDrained(msg);
7151
7152    changeStateIfWeOwnAllBuffers();
7153}
7154
7155void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
7156    BaseState::onInputBufferFilled(msg);
7157
7158    changeStateIfWeOwnAllBuffers();
7159}
7160
7161void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
7162    if (mFlushComplete[kPortIndexInput]
7163            && mFlushComplete[kPortIndexOutput]
7164            && mCodec->allYourBuffersAreBelongToUs()) {
7165        // We now own all buffers except possibly those still queued with
7166        // the native window for rendering. Let's get those back as well.
7167        mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs();
7168
7169        mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC));
7170
7171        sp<AMessage> notify = mCodec->mNotify->dup();
7172        notify->setInt32("what", CodecBase::kWhatFlushCompleted);
7173        notify->post();
7174
7175        mCodec->mPortEOS[kPortIndexInput] =
7176            mCodec->mPortEOS[kPortIndexOutput] = false;
7177
7178        mCodec->mInputEOSResult = OK;
7179
7180        if (mCodec->mSkipCutBuffer != NULL) {
7181            mCodec->mSkipCutBuffer->clear();
7182        }
7183
7184        mCodec->changeState(mCodec->mExecutingState);
7185    }
7186}
7187
7188status_t ACodec::queryCapabilities(
7189        const AString &name, const AString &mime, bool isEncoder,
7190        sp<MediaCodecInfo::Capabilities> *caps) {
7191    (*caps).clear();
7192    const char *role = getComponentRole(isEncoder, mime.c_str());
7193    if (role == NULL) {
7194        return BAD_VALUE;
7195    }
7196
7197    OMXClient client;
7198    status_t err = client.connect();
7199    if (err != OK) {
7200        return err;
7201    }
7202
7203    sp<IOMX> omx = client.interface();
7204    sp<CodecObserver> observer = new CodecObserver;
7205    IOMX::node_id node = 0;
7206
7207    err = omx->allocateNode(name.c_str(), observer, NULL, &node);
7208    if (err != OK) {
7209        client.disconnect();
7210        return err;
7211    }
7212
7213    err = setComponentRole(omx, node, role);
7214    if (err != OK) {
7215        omx->freeNode(node);
7216        client.disconnect();
7217        return err;
7218    }
7219
7220    sp<MediaCodecInfo::CapabilitiesBuilder> builder = new MediaCodecInfo::CapabilitiesBuilder();
7221    bool isVideo = mime.startsWithIgnoreCase("video/");
7222
7223    if (isVideo) {
7224        OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
7225        InitOMXParams(&param);
7226        param.nPortIndex = isEncoder ? kPortIndexOutput : kPortIndexInput;
7227
7228        for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
7229            param.nProfileIndex = index;
7230            status_t err = omx->getParameter(
7231                    node, OMX_IndexParamVideoProfileLevelQuerySupported,
7232                    &param, sizeof(param));
7233            if (err != OK) {
7234                break;
7235            }
7236            builder->addProfileLevel(param.eProfile, param.eLevel);
7237
7238            if (index == kMaxIndicesToCheck) {
7239                ALOGW("[%s] stopping checking profiles after %u: %x/%x",
7240                        name.c_str(), index,
7241                        param.eProfile, param.eLevel);
7242            }
7243        }
7244
7245        // Color format query
7246        // return colors in the order reported by the OMX component
7247        // prefix "flexible" standard ones with the flexible equivalent
7248        OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
7249        InitOMXParams(&portFormat);
7250        portFormat.nPortIndex = isEncoder ? kPortIndexInput : kPortIndexOutput;
7251        Vector<uint32_t> supportedColors; // shadow copy to check for duplicates
7252        for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
7253            portFormat.nIndex = index;
7254            status_t err = omx->getParameter(
7255                    node, OMX_IndexParamVideoPortFormat,
7256                    &portFormat, sizeof(portFormat));
7257            if (err != OK) {
7258                break;
7259            }
7260
7261            OMX_U32 flexibleEquivalent;
7262            if (isFlexibleColorFormat(
7263                    omx, node, portFormat.eColorFormat, false /* usingNativeWindow */,
7264                    &flexibleEquivalent)) {
7265                bool marked = false;
7266                for (size_t i = 0; i < supportedColors.size(); ++i) {
7267                    if (supportedColors[i] == flexibleEquivalent) {
7268                        marked = true;
7269                        break;
7270                    }
7271                }
7272                if (!marked) {
7273                    supportedColors.push(flexibleEquivalent);
7274                    builder->addColorFormat(flexibleEquivalent);
7275                }
7276            }
7277            supportedColors.push(portFormat.eColorFormat);
7278            builder->addColorFormat(portFormat.eColorFormat);
7279
7280            if (index == kMaxIndicesToCheck) {
7281                ALOGW("[%s] stopping checking formats after %u: %s(%x)",
7282                        name.c_str(), index,
7283                        asString(portFormat.eColorFormat), portFormat.eColorFormat);
7284            }
7285        }
7286    } else if (mime.equalsIgnoreCase(MEDIA_MIMETYPE_AUDIO_AAC)) {
7287        // More audio codecs if they have profiles.
7288        OMX_AUDIO_PARAM_ANDROID_PROFILETYPE param;
7289        InitOMXParams(&param);
7290        param.nPortIndex = isEncoder ? kPortIndexOutput : kPortIndexInput;
7291        for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) {
7292            param.nProfileIndex = index;
7293            status_t err = omx->getParameter(
7294                    node, (OMX_INDEXTYPE)OMX_IndexParamAudioProfileQuerySupported,
7295                    &param, sizeof(param));
7296            if (err != OK) {
7297                break;
7298            }
7299            // For audio, level is ignored.
7300            builder->addProfileLevel(param.eProfile, 0 /* level */);
7301
7302            if (index == kMaxIndicesToCheck) {
7303                ALOGW("[%s] stopping checking profiles after %u: %x",
7304                        name.c_str(), index,
7305                        param.eProfile);
7306            }
7307        }
7308
7309        // NOTE: Without Android extensions, OMX does not provide a way to query
7310        // AAC profile support
7311        if (param.nProfileIndex == 0) {
7312            ALOGW("component %s doesn't support profile query.", name.c_str());
7313        }
7314    }
7315
7316    if (isVideo && !isEncoder) {
7317        native_handle_t *sidebandHandle = NULL;
7318        if (omx->configureVideoTunnelMode(
7319                node, kPortIndexOutput, OMX_TRUE, 0, &sidebandHandle) == OK) {
7320            // tunneled playback includes adaptive playback
7321            builder->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback
7322                    | MediaCodecInfo::Capabilities::kFlagSupportsTunneledPlayback);
7323        } else if (omx->storeMetaDataInBuffers(
7324                node, kPortIndexOutput, OMX_TRUE) == OK ||
7325            omx->prepareForAdaptivePlayback(
7326                node, kPortIndexOutput, OMX_TRUE,
7327                1280 /* width */, 720 /* height */) == OK) {
7328            builder->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback);
7329        }
7330    }
7331
7332    if (isVideo && isEncoder) {
7333        OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params;
7334        InitOMXParams(&params);
7335        params.nPortIndex = kPortIndexOutput;
7336        // TODO: should we verify if fallback is supported?
7337        if (omx->getConfig(
7338                node, (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh,
7339                &params, sizeof(params)) == OK) {
7340            builder->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsIntraRefresh);
7341        }
7342    }
7343
7344    *caps = builder;
7345    omx->freeNode(node);
7346    client.disconnect();
7347    return OK;
7348}
7349
7350// These are supposed be equivalent to the logic in
7351// "audio_channel_out_mask_from_count".
7352//static
7353status_t ACodec::getOMXChannelMapping(size_t numChannels, OMX_AUDIO_CHANNELTYPE map[]) {
7354    switch (numChannels) {
7355        case 1:
7356            map[0] = OMX_AUDIO_ChannelCF;
7357            break;
7358        case 2:
7359            map[0] = OMX_AUDIO_ChannelLF;
7360            map[1] = OMX_AUDIO_ChannelRF;
7361            break;
7362        case 3:
7363            map[0] = OMX_AUDIO_ChannelLF;
7364            map[1] = OMX_AUDIO_ChannelRF;
7365            map[2] = OMX_AUDIO_ChannelCF;
7366            break;
7367        case 4:
7368            map[0] = OMX_AUDIO_ChannelLF;
7369            map[1] = OMX_AUDIO_ChannelRF;
7370            map[2] = OMX_AUDIO_ChannelLR;
7371            map[3] = OMX_AUDIO_ChannelRR;
7372            break;
7373        case 5:
7374            map[0] = OMX_AUDIO_ChannelLF;
7375            map[1] = OMX_AUDIO_ChannelRF;
7376            map[2] = OMX_AUDIO_ChannelCF;
7377            map[3] = OMX_AUDIO_ChannelLR;
7378            map[4] = OMX_AUDIO_ChannelRR;
7379            break;
7380        case 6:
7381            map[0] = OMX_AUDIO_ChannelLF;
7382            map[1] = OMX_AUDIO_ChannelRF;
7383            map[2] = OMX_AUDIO_ChannelCF;
7384            map[3] = OMX_AUDIO_ChannelLFE;
7385            map[4] = OMX_AUDIO_ChannelLR;
7386            map[5] = OMX_AUDIO_ChannelRR;
7387            break;
7388        case 7:
7389            map[0] = OMX_AUDIO_ChannelLF;
7390            map[1] = OMX_AUDIO_ChannelRF;
7391            map[2] = OMX_AUDIO_ChannelCF;
7392            map[3] = OMX_AUDIO_ChannelLFE;
7393            map[4] = OMX_AUDIO_ChannelLR;
7394            map[5] = OMX_AUDIO_ChannelRR;
7395            map[6] = OMX_AUDIO_ChannelCS;
7396            break;
7397        case 8:
7398            map[0] = OMX_AUDIO_ChannelLF;
7399            map[1] = OMX_AUDIO_ChannelRF;
7400            map[2] = OMX_AUDIO_ChannelCF;
7401            map[3] = OMX_AUDIO_ChannelLFE;
7402            map[4] = OMX_AUDIO_ChannelLR;
7403            map[5] = OMX_AUDIO_ChannelRR;
7404            map[6] = OMX_AUDIO_ChannelLS;
7405            map[7] = OMX_AUDIO_ChannelRS;
7406            break;
7407        default:
7408            return -EINVAL;
7409    }
7410
7411    return OK;
7412}
7413
7414}  // namespace android
7415