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