ACodec.cpp revision 0d09182a1dde960f7acda1c28469e5deead1b996
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2010 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17e7c74cc96eeecec52401d9bf720234d1421cfebcAdam Powell//#define LOG_NDEBUG 0
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "ACodec"
1963b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell
2063b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell#ifdef __LP64__
210b3c11260ae5ea09c7e702802b39f77afc74f35fAdam Powell#define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
220b3c11260ae5ea09c7e702802b39f77afc74f35fAdam Powell#endif
232442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <inttypes.h>
250b3c11260ae5ea09c7e702802b39f77afc74f35fAdam Powell#include <utils/Trace.h>
262ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
272442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell#include <media/stagefright/ACodec.h>
282388251fcd8def03a6bbc91382e84db085cf4253Adam Powell
290e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot#include <binder/MemoryDealer.h>
307d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
312442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell#include <media/stagefright/foundation/hexdump.h>
322442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell#include <media/stagefright/foundation/ABuffer.h>
332442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell#include <media/stagefright/foundation/ADebug.h>
347d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell#include <media/stagefright/foundation/AMessage.h>
3563b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell#include <media/stagefright/foundation/AUtils.h>
362442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
3713036beab1579fabe1a93e1839c13cb68a49adf6Adam Powell#include <media/stagefright/BufferProducerWrapper.h>
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <media/stagefright/MediaCodecList.h>
392388251fcd8def03a6bbc91382e84db085cf4253Adam Powell#include <media/stagefright/MediaDefs.h>
402442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell#include <media/stagefright/NativeWindowWrapper.h>
412442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell#include <media/stagefright/OMXClient.h>
422442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell#include <media/stagefright/OMXCodec.h>
43eb034652c2037a47ebfd99779e8383bb8bb528afDianne Hackborn
4452c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell#include <media/hardware/HardwareAPI.h>
452442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
462ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell#include <OMX_AudioExt.h>
472442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell#include <OMX_VideoExt.h>
487d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell#include <OMX_Component.h>
498212ae0aee1700b9c287ebadf15af8dacdc8eae6Jeff Sharkey#include <OMX_IndexExt.h>
502442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
512442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell#include "include/avc_utils.h"
522442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
532442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powellnamespace android {
542442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
5563b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell// OMX errors are directly mapped into status_t range if
56eb034652c2037a47ebfd99779e8383bb8bb528afDianne Hackborn// there is no corresponding MediaError status code.
570b3c11260ae5ea09c7e702802b39f77afc74f35fAdam Powell// Use the statusFromOMXError(int32_t omxError) function.
587d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell//
592442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell// Currently this is a direct map.
6063b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell// See frameworks/native/include/media/openmax/OMX_Core.h
617d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell//
6298b7f8943080ff4b0c636ad37b62556453018839Adam Powell// Vendor OMX errors     from 0x90000000 - 0x9000FFFF
632442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell// Extension OMX errors  from 0x8F000000 - 0x90000000
6463b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell// Standard OMX errors   from 0x80001000 - 0x80001024 (0x80001024 current)
6563b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell//
6663b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell
677d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell// returns true if err is a recognized OMX error code.
687d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell// as OMX error is OMX_S32, this is an int32_t type
697d7580019e44e2e162df01ffff51de20ed0721b3Adam Powellstatic inline bool isOMXError(int32_t err) {
707d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    return (ERROR_CODEC_MIN <= err && err <= ERROR_CODEC_MAX);
7198b7f8943080ff4b0c636ad37b62556453018839Adam Powell}
72f6e9228b8a97603d3ceb8f0d61e8d87cf19bd21fChris Wren
7352c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell// converts an OMX error to a status_t
742442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powellstatic inline status_t statusFromOMXError(int32_t omxError) {
752388251fcd8def03a6bbc91382e84db085cf4253Adam Powell    switch (omxError) {
762442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    case OMX_ErrorInvalidComponentName:
77a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell    case OMX_ErrorComponentNotFound:
78a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell        return NAME_NOT_FOUND; // can trigger illegal argument error for provided names.
792442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    default:
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return isOMXError(omxError) ? omxError : 0; // no translation required
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
820b3c11260ae5ea09c7e702802b39f77afc74f35fAdam Powell}
830b3c11260ae5ea09c7e702802b39f77afc74f35fAdam Powell
842442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell// checks and converts status_t to a non-side-effect status_t
852442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powellstatic inline status_t makeNoSideEffectStatus(status_t err) {
862ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    switch (err) {
872442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    // the following errors have side effects and may come
882442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    // from other code modules. Remap for safety reasons.
89e49d9393783f2789239f8da536abda9533ffadf0Adam Powell    case INVALID_OPERATION:
900b3c11260ae5ea09c7e702802b39f77afc74f35fAdam Powell    case DEAD_OBJECT:
912ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell        return UNKNOWN_ERROR;
922ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    default:
9352c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell        return err;
94e49d9393783f2789239f8da536abda9533ffadf0Adam Powell    }
9513036beab1579fabe1a93e1839c13cb68a49adf6Adam Powell}
9613036beab1579fabe1a93e1839c13cb68a49adf6Adam Powell
977d7580019e44e2e162df01ffff51de20ed0721b3Adam Powelltemplate<class T>
9863b31698452dbc36f6258c980d7a731518bfd6a0Adam Powellstatic void InitOMXParams(T *params) {
992442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    params->nSize = sizeof(T);
1002388251fcd8def03a6bbc91382e84db085cf4253Adam Powell    params->nVersion.s.nVersionMajor = 1;
1012388251fcd8def03a6bbc91382e84db085cf4253Adam Powell    params->nVersion.s.nVersionMinor = 0;
10252c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell    params->nVersion.s.nRevision = 0;
1032388251fcd8def03a6bbc91382e84db085cf4253Adam Powell    params->nVersion.s.nStep = 0;
1042388251fcd8def03a6bbc91382e84db085cf4253Adam Powell}
1052388251fcd8def03a6bbc91382e84db085cf4253Adam Powell
1062442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powellstruct CodecObserver : public BnOMXObserver {
1072442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    CodecObserver() {}
1082442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
1092442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    void setNotificationMessage(const sp<AMessage> &msg) {
1102442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        mNotify = msg;
11113036beab1579fabe1a93e1839c13cb68a49adf6Adam Powell    }
1122442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
1132442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    // from IOMXObserver
1142442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    virtual void onMessage(const omx_message &omx_msg) {
1152442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        sp<AMessage> msg = mNotify->dup();
1162442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
1172442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        msg->setInt32("type", omx_msg.type);
1182442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        msg->setInt32("node", omx_msg.node);
1192442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
1202442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        switch (omx_msg.type) {
1212442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell            case omx_message::EVENT:
1222442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell            {
1232442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                msg->setInt32("event", omx_msg.u.event_data.event);
1242442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                msg->setInt32("data1", omx_msg.u.event_data.data1);
125a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell                msg->setInt32("data2", omx_msg.u.event_data.data2);
126a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell                break;
127a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell            }
128a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell
1292442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell            case omx_message::EMPTY_BUFFER_DONE:
1309761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell            {
1312442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                msg->setInt32("buffer", omx_msg.u.buffer_data.buffer);
1324c470d641c6906a742b63273b305695ba575b3e1Adam Powell                break;
1334c470d641c6906a742b63273b305695ba575b3e1Adam Powell            }
1344c470d641c6906a742b63273b305695ba575b3e1Adam Powell
135565943fda5b05ac5514c216effaf76fc98c5b6c0Adam Powell            case omx_message::FILL_BUFFER_DONE:
1364c470d641c6906a742b63273b305695ba575b3e1Adam Powell            {
1372442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                msg->setInt32(
1382442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                        "buffer", omx_msg.u.extended_buffer_data.buffer);
1392442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                msg->setInt32(
1402442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                        "range_offset",
1412442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                        omx_msg.u.extended_buffer_data.range_offset);
1422442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                msg->setInt32(
1432442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                        "range_length",
1444c470d641c6906a742b63273b305695ba575b3e1Adam Powell                        omx_msg.u.extended_buffer_data.range_length);
145565943fda5b05ac5514c216effaf76fc98c5b6c0Adam Powell                msg->setInt32(
1462442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                        "flags",
1472442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                        omx_msg.u.extended_buffer_data.flags);
1482442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                msg->setInt64(
1492442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                        "timestamp",
1502442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                        omx_msg.u.extended_buffer_data.timestamp);
1512442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                break;
1522442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell            }
1532442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            default:
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                TRESPASS();
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
157eb034652c2037a47ebfd99779e8383bb8bb528afDianne Hackborn        }
158eb034652c2037a47ebfd99779e8383bb8bb528afDianne Hackborn
1599d6376a1d88ab5b3a41ee4400e3aaa4c4ee69e2aChristopher Tate        msg->post();
160eb034652c2037a47ebfd99779e8383bb8bb528afDianne Hackborn    }
1619d6376a1d88ab5b3a41ee4400e3aaa4c4ee69e2aChristopher Tate
162eb034652c2037a47ebfd99779e8383bb8bb528afDianne Hackbornprotected:
163eb034652c2037a47ebfd99779e8383bb8bb528afDianne Hackborn    virtual ~CodecObserver() {}
1642442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
165411d2aed2bb51ea0ba258fc45c8f8029c409e881Craig Mautnerprivate:
166e49d9393783f2789239f8da536abda9533ffadf0Adam Powell    sp<AMessage> mNotify;
167411d2aed2bb51ea0ba258fc45c8f8029c409e881Craig Mautner
1682ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    DISALLOW_EVIL_CONSTRUCTORS(CodecObserver);
1692ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell};
1702ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
1712ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell////////////////////////////////////////////////////////////////////////////////
1722ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
1732ed547e55f820a9c705872d802b051d8ae9c906bAdam Powellstruct ACodec::BaseState : public AState {
1742ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    BaseState(ACodec *codec, const sp<AState> &parentState = NULL);
1752ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
1762ed547e55f820a9c705872d802b051d8ae9c906bAdam Powellprotected:
1772ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    enum PortMode {
1782ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell        KEEP_BUFFERS,
1792ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell        RESUBMIT_BUFFERS,
1802ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell        FREE_BUFFERS,
1812ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    };
1822ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
1832ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    ACodec *mCodec;
1842ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
1852ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    virtual PortMode getPortMode(OMX_U32 portIndex);
1862ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
1872ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    virtual bool onMessageReceived(const sp<AMessage> &msg);
1882ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
1892ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
1902ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
1912ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
1922ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    virtual void onInputBufferFilled(const sp<AMessage> &msg);
1932ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
194e49d9393783f2789239f8da536abda9533ffadf0Adam Powell    void postFillThisBuffer(BufferInfo *info);
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
196278902c982443b3c196aa4642dcf3e0fffe4b23dAdam Powellprivate:
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool onOMXMessage(const sp<AMessage> &msg);
198278902c982443b3c196aa4642dcf3e0fffe4b23dAdam Powell
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID);
200eb034652c2037a47ebfd99779e8383bb8bb528afDianne Hackborn
201eb034652c2037a47ebfd99779e8383bb8bb528afDianne Hackborn    bool onOMXFillBufferDone(
202eb034652c2037a47ebfd99779e8383bb8bb528afDianne Hackborn            IOMX::buffer_id bufferID,
203eb034652c2037a47ebfd99779e8383bb8bb528afDianne Hackborn            size_t rangeOffset, size_t rangeLength,
204eb034652c2037a47ebfd99779e8383bb8bb528afDianne Hackborn            OMX_U32 flags,
205eb034652c2037a47ebfd99779e8383bb8bb528afDianne Hackborn            int64_t timeUs);
2062ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
207eb034652c2037a47ebfd99779e8383bb8bb528afDianne Hackborn    void getMoreInputDataIfPossible();
2089d6376a1d88ab5b3a41ee4400e3aaa4c4ee69e2aChristopher Tate
209eb034652c2037a47ebfd99779e8383bb8bb528afDianne Hackborn    DISALLOW_EVIL_CONSTRUCTORS(BaseState);
210eb034652c2037a47ebfd99779e8383bb8bb528afDianne Hackborn};
211411d2aed2bb51ea0ba258fc45c8f8029c409e881Craig Mautner
212e49d9393783f2789239f8da536abda9533ffadf0Adam Powell////////////////////////////////////////////////////////////////////////////////
213411d2aed2bb51ea0ba258fc45c8f8029c409e881Craig Mautner
214eb034652c2037a47ebfd99779e8383bb8bb528afDianne Hackbornstruct ACodec::DeathNotifier : public IBinder::DeathRecipient {
215eb034652c2037a47ebfd99779e8383bb8bb528afDianne Hackborn    DeathNotifier(const sp<AMessage> &notify)
2162442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        : mNotify(notify) {
21713036beab1579fabe1a93e1839c13cb68a49adf6Adam Powell    }
21813036beab1579fabe1a93e1839c13cb68a49adf6Adam Powell
2190b3c11260ae5ea09c7e702802b39f77afc74f35fAdam Powell    virtual void binderDied(const wp<IBinder> &) {
2200b3c11260ae5ea09c7e702802b39f77afc74f35fAdam Powell        mNotify->post();
2212ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    }
2222ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
223028ceeb472801bcfa5844fc89ed0da8463098824Dianne Hackbornprotected:
2242388251fcd8def03a6bbc91382e84db085cf4253Adam Powell    virtual ~DeathNotifier() {}
22552c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell
22652c39215db2a0e1d339733e06284a2ba81e4c794Adam Powellprivate:
22752c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell    sp<AMessage> mNotify;
22852c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell
22952c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell    DISALLOW_EVIL_CONSTRUCTORS(DeathNotifier);
23052c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell};
23152c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell
23252c39215db2a0e1d339733e06284a2ba81e4c794Adam Powellstruct ACodec::UninitializedState : public ACodec::BaseState {
23352c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell    UninitializedState(ACodec *codec);
23452c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell
23552c39215db2a0e1d339733e06284a2ba81e4c794Adam Powellprotected:
23652c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell    virtual bool onMessageReceived(const sp<AMessage> &msg);
23752c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell    virtual void stateEntered();
23852c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell
23952c39215db2a0e1d339733e06284a2ba81e4c794Adam Powellprivate:
24052c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell    void onSetup(const sp<AMessage> &msg);
24152c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell    bool onAllocateComponent(const sp<AMessage> &msg);
24252c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell
24352c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell    sp<DeathNotifier> mDeathNotifier;
24452c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell
24552c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell    DISALLOW_EVIL_CONSTRUCTORS(UninitializedState);
24652c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell};
24752c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell
24852c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell////////////////////////////////////////////////////////////////////////////////
24952c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell
25052c39215db2a0e1d339733e06284a2ba81e4c794Adam Powellstruct ACodec::LoadedState : public ACodec::BaseState {
25152c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell    LoadedState(ACodec *codec);
25252c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell
2532388251fcd8def03a6bbc91382e84db085cf4253Adam Powellprotected:
254278902c982443b3c196aa4642dcf3e0fffe4b23dAdam Powell    virtual bool onMessageReceived(const sp<AMessage> &msg);
255278902c982443b3c196aa4642dcf3e0fffe4b23dAdam Powell    virtual void stateEntered();
25698b7f8943080ff4b0c636ad37b62556453018839Adam Powell
257f6e9228b8a97603d3ceb8f0d61e8d87cf19bd21fChris Wrenprivate:
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    friend struct ACodec::UninitializedState;
259e49d9393783f2789239f8da536abda9533ffadf0Adam Powell
2602388251fcd8def03a6bbc91382e84db085cf4253Adam Powell    bool onConfigureComponent(const sp<AMessage> &msg);
2612388251fcd8def03a6bbc91382e84db085cf4253Adam Powell    void onCreateInputSurface(const sp<AMessage> &msg);
2622388251fcd8def03a6bbc91382e84db085cf4253Adam Powell    void onStart();
2632388251fcd8def03a6bbc91382e84db085cf4253Adam Powell    void onShutdown(bool keepComponentAllocated);
2642388251fcd8def03a6bbc91382e84db085cf4253Adam Powell
2652388251fcd8def03a6bbc91382e84db085cf4253Adam Powell    DISALLOW_EVIL_CONSTRUCTORS(LoadedState);
2662388251fcd8def03a6bbc91382e84db085cf4253Adam Powell};
2672388251fcd8def03a6bbc91382e84db085cf4253Adam Powell
2682388251fcd8def03a6bbc91382e84db085cf4253Adam Powell////////////////////////////////////////////////////////////////////////////////
2698212ae0aee1700b9c287ebadf15af8dacdc8eae6Jeff Sharkey
2702388251fcd8def03a6bbc91382e84db085cf4253Adam Powellstruct ACodec::LoadedToIdleState : public ACodec::BaseState {
2712388251fcd8def03a6bbc91382e84db085cf4253Adam Powell    LoadedToIdleState(ACodec *codec);
2722388251fcd8def03a6bbc91382e84db085cf4253Adam Powell
2732388251fcd8def03a6bbc91382e84db085cf4253Adam Powellprotected:
2742388251fcd8def03a6bbc91382e84db085cf4253Adam Powell    virtual bool onMessageReceived(const sp<AMessage> &msg);
2752388251fcd8def03a6bbc91382e84db085cf4253Adam Powell    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
2760b3c11260ae5ea09c7e702802b39f77afc74f35fAdam Powell    virtual void stateEntered();
2772ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
2782ed547e55f820a9c705872d802b051d8ae9c906bAdam Powellprivate:
2792ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    status_t allocateBuffers();
2802ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
2812ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState);
2822ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell};
2839761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell
2849761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell////////////////////////////////////////////////////////////////////////////////
2852ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
2862ed547e55f820a9c705872d802b051d8ae9c906bAdam Powellstruct ACodec::IdleToExecutingState : public ACodec::BaseState {
2872ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    IdleToExecutingState(ACodec *codec);
2880e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot
2890e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevotprotected:
290e49d9393783f2789239f8da536abda9533ffadf0Adam Powell    virtual bool onMessageReceived(const sp<AMessage> &msg);
2910e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
292e49d9393783f2789239f8da536abda9533ffadf0Adam Powell    virtual void stateEntered();
2930e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot
294e49d9393783f2789239f8da536abda9533ffadf0Adam Powellprivate:
295e49d9393783f2789239f8da536abda9533ffadf0Adam Powell    DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState);
296e49d9393783f2789239f8da536abda9533ffadf0Adam Powell};
297741abfc12074623d24297ebb67d98cb2d9126addNicolas Prevot
2980e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot////////////////////////////////////////////////////////////////////////////////
2990e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot
3000e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevotstruct ACodec::ExecutingState : public ACodec::BaseState {
3010e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot    ExecutingState(ACodec *codec);
3020e2b73f6858479ca963bd53c49f8955d98f14869Nicolas Prevot
303e49d9393783f2789239f8da536abda9533ffadf0Adam Powell    void submitRegularOutputBuffers();
304e49d9393783f2789239f8da536abda9533ffadf0Adam Powell    void submitOutputMetaBuffers();
3050b3c11260ae5ea09c7e702802b39f77afc74f35fAdam Powell    void submitOutputBuffers();
3062388251fcd8def03a6bbc91382e84db085cf4253Adam Powell
3070b3c11260ae5ea09c7e702802b39f77afc74f35fAdam Powell    // Submit output buffers to the decoder, submit input buffers to client
3082442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    // to fill with data.
3090b3c11260ae5ea09c7e702802b39f77afc74f35fAdam Powell    void resume();
3100b3c11260ae5ea09c7e702802b39f77afc74f35fAdam Powell
3110b3c11260ae5ea09c7e702802b39f77afc74f35fAdam Powell    // Returns true iff input and output buffers are in play.
3120b3c11260ae5ea09c7e702802b39f77afc74f35fAdam Powell    bool active() const { return mActive; }
3130b3c11260ae5ea09c7e702802b39f77afc74f35fAdam Powell
3140b3c11260ae5ea09c7e702802b39f77afc74f35fAdam Powellprotected:
3150b3c11260ae5ea09c7e702802b39f77afc74f35fAdam Powell    virtual PortMode getPortMode(OMX_U32 portIndex);
3160b3c11260ae5ea09c7e702802b39f77afc74f35fAdam Powell    virtual bool onMessageReceived(const sp<AMessage> &msg);
3170b3c11260ae5ea09c7e702802b39f77afc74f35fAdam Powell    virtual void stateEntered();
3180b3c11260ae5ea09c7e702802b39f77afc74f35fAdam Powell
3190b3c11260ae5ea09c7e702802b39f77afc74f35fAdam Powell    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
3200b3c11260ae5ea09c7e702802b39f77afc74f35fAdam Powell
3212442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powellprivate:
3222388251fcd8def03a6bbc91382e84db085cf4253Adam Powell    bool mActive;
3237d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
3247d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    DISALLOW_EVIL_CONSTRUCTORS(ExecutingState);
3257d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell};
32652c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell
32752c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell////////////////////////////////////////////////////////////////////////////////
32852c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell
32963b31698452dbc36f6258c980d7a731518bfd6a0Adam Powellstruct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState {
33063b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell    OutputPortSettingsChangedState(ACodec *codec);
33163b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell
3327d7580019e44e2e162df01ffff51de20ed0721b3Adam Powellprotected:
3337d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    virtual PortMode getPortMode(OMX_U32 portIndex);
3347d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    virtual bool onMessageReceived(const sp<AMessage> &msg);
3357d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    virtual void stateEntered();
3367d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
3377d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
3382388251fcd8def03a6bbc91382e84db085cf4253Adam Powell
3397d7580019e44e2e162df01ffff51de20ed0721b3Adam Powellprivate:
3402442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState);
3412442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell};
3422442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
3432388251fcd8def03a6bbc91382e84db085cf4253Adam Powell////////////////////////////////////////////////////////////////////////////////
3442442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
3452442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powellstruct ACodec::ExecutingToIdleState : public ACodec::BaseState {
3462442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    ExecutingToIdleState(ACodec *codec);
3479761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell
3482388251fcd8def03a6bbc91382e84db085cf4253Adam Powellprotected:
3492388251fcd8def03a6bbc91382e84db085cf4253Adam Powell    virtual bool onMessageReceived(const sp<AMessage> &msg);
3502388251fcd8def03a6bbc91382e84db085cf4253Adam Powell    virtual void stateEntered();
3512388251fcd8def03a6bbc91382e84db085cf4253Adam Powell
3522388251fcd8def03a6bbc91382e84db085cf4253Adam Powell    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
3532388251fcd8def03a6bbc91382e84db085cf4253Adam Powell
3542388251fcd8def03a6bbc91382e84db085cf4253Adam Powell    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
3552388251fcd8def03a6bbc91382e84db085cf4253Adam Powell    virtual void onInputBufferFilled(const sp<AMessage> &msg);
3562388251fcd8def03a6bbc91382e84db085cf4253Adam Powell
357e49d9393783f2789239f8da536abda9533ffadf0Adam Powellprivate:
358e49d9393783f2789239f8da536abda9533ffadf0Adam Powell    void changeStateIfWeOwnAllBuffers();
359e49d9393783f2789239f8da536abda9533ffadf0Adam Powell
360e49d9393783f2789239f8da536abda9533ffadf0Adam Powell    bool mComponentNowIdle;
361e49d9393783f2789239f8da536abda9533ffadf0Adam Powell
36213420f2311757554c314f620c83cb55153b67612Dianne Hackborn    DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState);
363e49d9393783f2789239f8da536abda9533ffadf0Adam Powell};
364e49d9393783f2789239f8da536abda9533ffadf0Adam Powell
3652442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell////////////////////////////////////////////////////////////////////////////////
3662ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
3672ed547e55f820a9c705872d802b051d8ae9c906bAdam Powellstruct ACodec::IdleToLoadedState : public ACodec::BaseState {
3682ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    IdleToLoadedState(ACodec *codec);
3692ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
3702ed547e55f820a9c705872d802b051d8ae9c906bAdam Powellprotected:
3712ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    virtual bool onMessageReceived(const sp<AMessage> &msg);
3722ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    virtual void stateEntered();
3732ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
3742ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
3752ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
3762ed547e55f820a9c705872d802b051d8ae9c906bAdam Powellprivate:
3772ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState);
3782ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell};
3792ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
3802ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell////////////////////////////////////////////////////////////////////////////////
3812ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
3822ed547e55f820a9c705872d802b051d8ae9c906bAdam Powellstruct ACodec::FlushingState : public ACodec::BaseState {
3832ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    FlushingState(ACodec *codec);
3842ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
3852ed547e55f820a9c705872d802b051d8ae9c906bAdam Powellprotected:
3862ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    virtual bool onMessageReceived(const sp<AMessage> &msg);
3872ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    virtual void stateEntered();
3882ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
3892ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
3902ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
3912ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    virtual void onOutputBufferDrained(const sp<AMessage> &msg);
3922ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    virtual void onInputBufferFilled(const sp<AMessage> &msg);
3932ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
3942ed547e55f820a9c705872d802b051d8ae9c906bAdam Powellprivate:
3952ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    bool mFlushComplete[2];
3962ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
39798b7f8943080ff4b0c636ad37b62556453018839Adam Powell    void changeStateIfWeOwnAllBuffers();
3982388251fcd8def03a6bbc91382e84db085cf4253Adam Powell
39998b7f8943080ff4b0c636ad37b62556453018839Adam Powell    DISALLOW_EVIL_CONSTRUCTORS(FlushingState);
40098b7f8943080ff4b0c636ad37b62556453018839Adam Powell};
40198b7f8943080ff4b0c636ad37b62556453018839Adam Powell
40298b7f8943080ff4b0c636ad37b62556453018839Adam Powell////////////////////////////////////////////////////////////////////////////////
40398b7f8943080ff4b0c636ad37b62556453018839Adam Powell
40498b7f8943080ff4b0c636ad37b62556453018839Adam PowellACodec::ACodec()
40598b7f8943080ff4b0c636ad37b62556453018839Adam Powell    : mQuirks(0),
40698b7f8943080ff4b0c636ad37b62556453018839Adam Powell      mNode(0),
40798b7f8943080ff4b0c636ad37b62556453018839Adam Powell      mSentFormat(false),
408f6e9228b8a97603d3ceb8f0d61e8d87cf19bd21fChris Wren      mIsEncoder(false),
40998b7f8943080ff4b0c636ad37b62556453018839Adam Powell      mUseMetadataOnEncoderOutput(false),
41098b7f8943080ff4b0c636ad37b62556453018839Adam Powell      mShutdownInProgress(false),
411f6e9228b8a97603d3ceb8f0d61e8d87cf19bd21fChris Wren      mExplicitShutdown(false),
41298b7f8943080ff4b0c636ad37b62556453018839Adam Powell      mEncoderDelay(0),
41398b7f8943080ff4b0c636ad37b62556453018839Adam Powell      mEncoderPadding(0),
41498b7f8943080ff4b0c636ad37b62556453018839Adam Powell      mRotationDegrees(0),
415f6e9228b8a97603d3ceb8f0d61e8d87cf19bd21fChris Wren      mChannelMaskPresent(false),
41698b7f8943080ff4b0c636ad37b62556453018839Adam Powell      mChannelMask(0),
41798b7f8943080ff4b0c636ad37b62556453018839Adam Powell      mDequeueCounter(0),
41898b7f8943080ff4b0c636ad37b62556453018839Adam Powell      mStoreMetaDataInOutputBuffers(false),
41998b7f8943080ff4b0c636ad37b62556453018839Adam Powell      mMetaDataBuffersToSubmit(0),
42098b7f8943080ff4b0c636ad37b62556453018839Adam Powell      mRepeatFrameDelayUs(-1ll),
42198b7f8943080ff4b0c636ad37b62556453018839Adam Powell      mMaxPtsGapUs(-1ll),
42298b7f8943080ff4b0c636ad37b62556453018839Adam Powell      mTimePerFrameUs(-1ll),
42398b7f8943080ff4b0c636ad37b62556453018839Adam Powell      mTimePerCaptureUs(-1ll),
42498b7f8943080ff4b0c636ad37b62556453018839Adam Powell      mCreateInputBuffersSuspended(false),
42598b7f8943080ff4b0c636ad37b62556453018839Adam Powell      mTunneled(false) {
42698b7f8943080ff4b0c636ad37b62556453018839Adam Powell    mUninitializedState = new UninitializedState(this);
4272442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    mLoadedState = new LoadedState(this);
4282442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    mLoadedToIdleState = new LoadedToIdleState(this);
4292442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    mIdleToExecutingState = new IdleToExecutingState(this);
4302442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    mExecutingState = new ExecutingState(this);
4312442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
4323a09c52914796135159009438a14b51b3e475fb4Adam Powell    mOutputPortSettingsChangedState =
4333a09c52914796135159009438a14b51b3e475fb4Adam Powell        new OutputPortSettingsChangedState(this);
4343a09c52914796135159009438a14b51b3e475fb4Adam Powell
4353a09c52914796135159009438a14b51b3e475fb4Adam Powell    mExecutingToIdleState = new ExecutingToIdleState(this);
4363a09c52914796135159009438a14b51b3e475fb4Adam Powell    mIdleToLoadedState = new IdleToLoadedState(this);
4372442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    mFlushingState = new FlushingState(this);
4382442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
4392442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false;
4402442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    mInputEOSResult = OK;
4412442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
4422442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    changeState(mUninitializedState);
4432442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell}
4442442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
4452442841819f9554f9b5c8b9c147a51b04e50de4dAdam PowellACodec::~ACodec() {
4462442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell}
4472442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
4482442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powellvoid ACodec::setNotificationMessage(const sp<AMessage> &msg) {
4492442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    mNotify = msg;
4502442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell}
4512442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
4522442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powellvoid ACodec::initiateSetup(const sp<AMessage> &msg) {
4532442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    msg->setWhat(kWhatSetup);
4542442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    msg->setTarget(id());
4552442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    msg->post();
4562442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell}
4572442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
4582442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powellvoid ACodec::signalSetParameters(const sp<AMessage> &params) {
4592442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    sp<AMessage> msg = new AMessage(kWhatSetParameters, id());
4602442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    msg->setMessage("params", params);
4612442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    msg->post();
4622442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell}
4632442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
46452c39215db2a0e1d339733e06284a2ba81e4c794Adam Powellvoid ACodec::initiateAllocateComponent(const sp<AMessage> &msg) {
46552c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell    msg->setWhat(kWhatAllocateComponent);
4662442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    msg->setTarget(id());
4672442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    msg->post();
4682442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell}
4699761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell
4709761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powellvoid ACodec::initiateConfigureComponent(const sp<AMessage> &msg) {
47152c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell    msg->setWhat(kWhatConfigureComponent);
47252c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell    msg->setTarget(id());
47352c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell    msg->post();
47452c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell}
47552c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell
47652c39215db2a0e1d339733e06284a2ba81e4c794Adam Powellvoid ACodec::initiateCreateInputSurface() {
4772442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    (new AMessage(kWhatCreateInputSurface, id()))->post();
4782442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell}
4792442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
4802442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powellvoid ACodec::signalEndOfInputStream() {
4812442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    (new AMessage(kWhatSignalEndOfInputStream, id()))->post();
4822442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell}
4832442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
4842442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powellvoid ACodec::initiateStart() {
4852ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    (new AMessage(kWhatStart, id()))->post();
4862ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell}
4872ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
4882442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powellvoid ACodec::signalFlush() {
4892442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    ALOGV("[%s] signalFlush", mComponentName.c_str());
4902442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    (new AMessage(kWhatFlush, id()))->post();
4912442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell}
4922442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
4932442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powellvoid ACodec::signalResume() {
4942442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    (new AMessage(kWhatResume, id()))->post();
49513036beab1579fabe1a93e1839c13cb68a49adf6Adam Powell}
4962442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
4974c470d641c6906a742b63273b305695ba575b3e1Adam Powellvoid ACodec::initiateShutdown(bool keepComponentAllocated) {
4984c470d641c6906a742b63273b305695ba575b3e1Adam Powell    sp<AMessage> msg = new AMessage(kWhatShutdown, id());
4992442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    msg->setInt32("keepComponentAllocated", keepComponentAllocated);
5002442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    msg->post();
5012442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    if (!keepComponentAllocated) {
5022442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        // ensure shutdown completes in 3 seconds
5032442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        (new AMessage(kWhatReleaseCodecInstance, id()))->post(3000000);
5042442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    }
5052442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell}
5062442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
5072442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powellvoid ACodec::signalRequestIDRFrame() {
5082442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    (new AMessage(kWhatRequestIDRFrame, id()))->post();
5092442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell}
5102442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
5112442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell// *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
5122442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell// Some codecs may return input buffers before having them processed.
5132442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell// This causes a halt if we already signaled an EOS on the input
5142442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell// port.  For now keep submitting an output buffer if there was an
5152442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell// EOS on the input port, but not yet on the output port.
5162442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powellvoid ACodec::signalSubmitOutputMetaDataBufferIfEOS_workaround() {
5172442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    if (mPortEOS[kPortIndexInput] && !mPortEOS[kPortIndexOutput] &&
5182442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell            mMetaDataBuffersToSubmit > 0) {
5192442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        (new AMessage(kWhatSubmitOutputMetaDataBufferIfEOS, id()))->post();
5202442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    }
5212442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell}
5222442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
5232442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powellstatus_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
5242442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
5252442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
5262442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    CHECK(mDealer[portIndex] == NULL);
5272442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    CHECK(mBuffers[portIndex].isEmpty());
5289761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell
5292442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    status_t err;
5302442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
53113036beab1579fabe1a93e1839c13cb68a49adf6Adam Powell        if (mStoreMetaDataInOutputBuffers) {
5322442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell            err = allocateOutputMetaDataBuffers();
5332442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        } else {
5342388251fcd8def03a6bbc91382e84db085cf4253Adam Powell            err = allocateOutputBuffersFromNativeWindow();
5354c470d641c6906a742b63273b305695ba575b3e1Adam Powell        }
5364c470d641c6906a742b63273b305695ba575b3e1Adam Powell    } else {
5374c470d641c6906a742b63273b305695ba575b3e1Adam Powell        OMX_PARAM_PORTDEFINITIONTYPE def;
5382ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell        InitOMXParams(&def);
5392ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell        def.nPortIndex = portIndex;
5402ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
5412ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell        err = mOMX->getParameter(
5422ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
5432ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
5442ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell        if (err == OK) {
5452ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell            ALOGV("[%s] Allocating %u buffers of size %u on %s port",
5462ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                    mComponentName.c_str(),
5472ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                    def.nBufferCountActual, def.nBufferSize,
5482ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                    portIndex == kPortIndexInput ? "input" : "output");
5492ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
5502ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell            size_t totalSize = def.nBufferCountActual * def.nBufferSize;
5512ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell            mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec");
5522ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
5532ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell            for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
5542ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
5552ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                CHECK(mem.get() != NULL);
5562ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
5572ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                BufferInfo info;
5582ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                info.mStatus = BufferInfo::OWNED_BY_US;
5592ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
5602ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                uint32_t requiresAllocateBufferBit =
5612ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                    (portIndex == kPortIndexInput)
5622ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                        ? OMXCodec::kRequiresAllocateBufferOnInputPorts
5632ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                        : OMXCodec::kRequiresAllocateBufferOnOutputPorts;
5642ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
5652ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                if ((portIndex == kPortIndexInput && (mFlags & kFlagIsSecure))
5662ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                        || mUseMetadataOnEncoderOutput) {
5672ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                    mem.clear();
5682ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
5692ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                    void *ptr;
5702ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                    err = mOMX->allocateBuffer(
5712ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                            mNode, portIndex, def.nBufferSize, &info.mBufferID,
5722ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                            &ptr);
5732ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
5742ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                    int32_t bufSize = mUseMetadataOnEncoderOutput ?
575666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell                            (4 + sizeof(buffer_handle_t)) : def.nBufferSize;
576666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell
577666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell                    info.mData = new ABuffer(ptr, bufSize);
578666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell                } else if (mQuirks & requiresAllocateBufferBit) {
579666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell                    err = mOMX->allocateBufferWithBackup(
580666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell                            mNode, portIndex, mem, &info.mBufferID);
581666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell                } else {
582666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell                    err = mOMX->useBuffer(mNode, portIndex, mem, &info.mBufferID);
583666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell                }
584666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell
585666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell                if (mem != NULL) {
586666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell                    info.mData = new ABuffer(mem->pointer(), def.nBufferSize);
587666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell                }
588666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell
589666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell                mBuffers[portIndex].push(info);
590666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell            }
591666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell        }
592666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell    }
593666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell
594666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell    if (err != OK) {
595666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell        return err;
596666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell    }
597666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell
598666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell    sp<AMessage> notify = mNotify->dup();
599666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell    notify->setInt32("what", CodecBase::kWhatBuffersAllocated);
600666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell
601666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell    notify->setInt32("portIndex", portIndex);
602666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell
603666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell    sp<PortDescription> desc = new PortDescription;
604666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell
6052442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
6062388251fcd8def03a6bbc91382e84db085cf4253Adam Powell        const BufferInfo &info = mBuffers[portIndex][i];
6077d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
6087d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        desc->addBuffer(info.mBufferID, info.mData);
6097d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    }
6107d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
6112442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    notify->setObject("portDesc", desc);
6122442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    notify->post();
6132442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
6142442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    return OK;
6152442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell}
6162ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
6172ed547e55f820a9c705872d802b051d8ae9c906bAdam Powellstatus_t ACodec::configureOutputBuffersFromNativeWindow(
6180ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell        OMX_U32 *bufferCount, OMX_U32 *bufferSize,
6192442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        OMX_U32 *minUndequeuedBuffers) {
6207d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    OMX_PARAM_PORTDEFINITIONTYPE def;
621ce5d92c31370b8c0e6989506e1ee95e181f93c53Alan Viverette    InitOMXParams(&def);
62213036beab1579fabe1a93e1839c13cb68a49adf6Adam Powell    def.nPortIndex = kPortIndexOutput;
6232ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
6242ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    status_t err = mOMX->getParameter(
625a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
6262442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
627a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell    if (err != OK) {
628a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell        return err;
6292442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    }
6302442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
631a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell    err = native_window_set_buffers_geometry(
6327d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            mNativeWindow.get(),
6337d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            def.format.video.nFrameWidth,
6347d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            def.format.video.nFrameHeight,
6357d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            def.format.video.eColorFormat);
6367d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
637ce5d92c31370b8c0e6989506e1ee95e181f93c53Alan Viverette    if (err != 0) {
638ce5d92c31370b8c0e6989506e1ee95e181f93c53Alan Viverette        ALOGE("native_window_set_buffers_geometry failed: %s (%d)",
639ce5d92c31370b8c0e6989506e1ee95e181f93c53Alan Viverette                strerror(-err), -err);
6407d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        return err;
6417d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    }
6427d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
64313036beab1579fabe1a93e1839c13cb68a49adf6Adam Powell    if (mRotationDegrees != 0) {
64413036beab1579fabe1a93e1839c13cb68a49adf6Adam Powell        uint32_t transform = 0;
64513036beab1579fabe1a93e1839c13cb68a49adf6Adam Powell        switch (mRotationDegrees) {
6460ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell            case 0: transform = 0; break;
6470ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell            case 90: transform = HAL_TRANSFORM_ROT_90; break;
6480ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell            case 180: transform = HAL_TRANSFORM_ROT_180; break;
6490ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell            case 270: transform = HAL_TRANSFORM_ROT_270; break;
6500ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell            default: transform = 0; break;
6510ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell        }
6522ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
6532ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell        if (transform > 0) {
6542ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell            err = native_window_set_buffers_transform(
6552ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                    mNativeWindow.get(), transform);
6562ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell            if (err != 0) {
6572ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                ALOGE("native_window_set_buffers_transform failed: %s (%d)",
6582ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                        strerror(-err), -err);
6592ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                return err;
6602ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell            }
6617d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        }
662ce5d92c31370b8c0e6989506e1ee95e181f93c53Alan Viverette    }
6632ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
6642ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    // Set up the native window.
6652ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    OMX_U32 usage = 0;
666a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell    err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage);
667a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell    if (err != 0) {
668a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell        ALOGW("querying usage flags from OMX IL component failed: %d", err);
669a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell        // XXX: Currently this error is logged, but not fatal.
670a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell        usage = 0;
6712442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    }
6722442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
6732442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    if (mFlags & kFlagIsGrallocUsageProtected) {
6742442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        usage |= GRALLOC_USAGE_PROTECTED;
6757d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    }
6760ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell
6770ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell    // Make sure to check whether either Stagefright or the video decoder
67852c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell    // requested protected buffers.
67952c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell    if (usage & GRALLOC_USAGE_PROTECTED) {
68052c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell        // Verify that the ANativeWindow sends images directly to
68152c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell        // SurfaceFlinger.
68252c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell        int queuesToNativeWindow = 0;
6832442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        err = mNativeWindow->query(
6842442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                mNativeWindow.get(), NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER,
6852442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                &queuesToNativeWindow);
6862442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        if (err != 0) {
6870ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell            ALOGE("error authenticating native window: %d", err);
6880ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell            return err;
6890ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell        }
6900ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell        if (queuesToNativeWindow != 1) {
6910ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell            ALOGE("native window could not be authenticated");
6920ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell            return PERMISSION_DENIED;
6930ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell        }
6940ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell    }
6950ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell
696666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell    err = native_window_set_usage(
69752c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell            mNativeWindow.get(),
6982ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell            usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP);
699666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell
70013036beab1579fabe1a93e1839c13cb68a49adf6Adam Powell    if (err != 0) {
7012ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell        ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err);
70213036beab1579fabe1a93e1839c13cb68a49adf6Adam Powell        return err;
70313036beab1579fabe1a93e1839c13cb68a49adf6Adam Powell    }
70413036beab1579fabe1a93e1839c13cb68a49adf6Adam Powell
70513036beab1579fabe1a93e1839c13cb68a49adf6Adam Powell    // Exits here for tunneled video playback codecs -- i.e. skips native window
7062ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    // buffer allocation step as this is managed by the tunneled OMX omponent
7072ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    // itself and explicitly sets def.nBufferCountActual to 0.
7082442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    if (mTunneled) {
7092442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        ALOGV("Tunneled Playback: skipping native window buffer allocation.");
7102442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        def.nBufferCountActual = 0;
7112442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        err = mOMX->setParameter(
712666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
7132442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
7142442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        *minUndequeuedBuffers = 0;
7152442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        *bufferCount = 0;
7162442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        *bufferSize = 0;
717666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell        return err;
7182ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    }
7192ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
7202ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    *minUndequeuedBuffers = 0;
721666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell    err = mNativeWindow->query(
722666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell            mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
72352c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell            (int *)minUndequeuedBuffers);
72452c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell
72552c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell    if (err != 0) {
72652c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell        ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
72752c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell                strerror(-err), -err);
72852c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell        return err;
72952c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell    }
73052c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell
73152c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell    // FIXME: assume that surface is controlled by app (native window
73252c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell    // returns the number for the case when surface is not controlled by app)
73352c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell    // FIXME2: This means that minUndeqeueudBufs can be 1 larger than reported
73452c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell    // For now, try to allocate 1 more buffer, but don't fail if unsuccessful
73552c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell
736666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell    // Use conservative allocation while also trying to reduce starvation
7372442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    //
7382442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    // 1. allocate at least nBufferCountMin + minUndequeuedBuffers - that is the
7392442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    //    minimum needed for the consumer to be able to work
7402442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    // 2. try to allocate two (2) additional buffers to reduce starvation from
741666d82a6d5c6a90e87591aea1aabac3d647cd541Adam Powell    //    the consumer
7422442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    //    plus an extra buffer to account for incorrect minUndequeuedBufs
7432442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    for (OMX_U32 extraBuffers = 2 + 1; /* condition inside loop */; extraBuffers--) {
7442442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        OMX_U32 newBufferCount =
7452442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell            def.nBufferCountMin + *minUndequeuedBuffers + extraBuffers;
7460ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell        def.nBufferCountActual = newBufferCount;
7472442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        err = mOMX->setParameter(
7482442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
7492442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
7502442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        if (err == OK) {
7512442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell            *minUndequeuedBuffers += extraBuffers;
7522442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell            break;
7532442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        }
7542442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
7552442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        ALOGW("[%s] setting nBufferCountActual to %u failed: %d",
75600f4aad704198a8293b9a1d2b931b8708073fe15Adam Powell                mComponentName.c_str(), newBufferCount, err);
75700f4aad704198a8293b9a1d2b931b8708073fe15Adam Powell        /* exit condition */
7582442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        if (extraBuffers == 0) {
7592442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell            return err;
7602442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        }
7612442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    }
7622442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
7632442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    err = native_window_set_buffer_count(
7642ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell            mNativeWindow.get(), def.nBufferCountActual);
7652ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
7667d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    if (err != 0) {
7677d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
7687d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell                -err);
7697d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        return err;
7707d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    }
771ce5d92c31370b8c0e6989506e1ee95e181f93c53Alan Viverette
772ce5d92c31370b8c0e6989506e1ee95e181f93c53Alan Viverette    *bufferCount = def.nBufferCountActual;
773ce5d92c31370b8c0e6989506e1ee95e181f93c53Alan Viverette    *bufferSize =  def.nBufferSize;
774ce5d92c31370b8c0e6989506e1ee95e181f93c53Alan Viverette    return err;
775ce5d92c31370b8c0e6989506e1ee95e181f93c53Alan Viverette}
7762ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
7772ed547e55f820a9c705872d802b051d8ae9c906bAdam Powellstatus_t ACodec::allocateOutputBuffersFromNativeWindow() {
7782ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers;
7792ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    status_t err = configureOutputBuffersFromNativeWindow(
7802ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell            &bufferCount, &bufferSize, &minUndequeuedBuffers);
7812ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    if (err != 0)
7822ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell        return err;
7832ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    mNumUndequeuedBuffers = minUndequeuedBuffers;
7842ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
7852ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    ALOGV("[%s] Allocating %u buffers from a native window of size %u on "
7862ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell         "output port",
7872ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell         mComponentName.c_str(), bufferCount, bufferSize);
7882ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
7892388251fcd8def03a6bbc91382e84db085cf4253Adam Powell    // Dequeue buffers and send them to OMX
7902388251fcd8def03a6bbc91382e84db085cf4253Adam Powell    for (OMX_U32 i = 0; i < bufferCount; i++) {
7912388251fcd8def03a6bbc91382e84db085cf4253Adam Powell        ANativeWindowBuffer *buf;
7922388251fcd8def03a6bbc91382e84db085cf4253Adam Powell        err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf);
7932388251fcd8def03a6bbc91382e84db085cf4253Adam Powell        if (err != 0) {
7942442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell            ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
7952442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell            break;
7962442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        }
7977d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
7987d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
7997d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        BufferInfo info;
8007d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        info.mStatus = BufferInfo::OWNED_BY_US;
8010ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell        info.mData = new ABuffer(NULL /* data */, bufferSize /* capacity */);
802a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell        info.mGraphicBuffer = graphicBuffer;
803bba0030a8529fd904056cbb7cfbbe3afbc1c8a95Adam Powell        mBuffers[kPortIndexOutput].push(info);
804a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell
8057d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        IOMX::buffer_id bufferId;
8067d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer,
807565943fda5b05ac5514c216effaf76fc98c5b6c0Adam Powell                &bufferId);
8087d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        if (err != 0) {
809a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell            ALOGE("registering GraphicBuffer %u with OMX IL component failed: "
810a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell                 "%d", i, err);
811a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell            break;
812a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell        }
813a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell
8147d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId;
8157d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
8167d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        ALOGV("[%s] Registered graphic buffer with ID %u (pointer = %p)",
8177d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell             mComponentName.c_str(),
8187d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell             bufferId, graphicBuffer.get());
8197d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    }
8207d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
8217d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    OMX_U32 cancelStart;
8227d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    OMX_U32 cancelEnd;
8237d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
8247d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    if (err != 0) {
8257d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        // If an error occurred while dequeuing we need to cancel any buffers
8267d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        // that were dequeued.
8277d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        cancelStart = 0;
82886100d18ad0bd5ae3267a0e0944d15f4fe94078aAdam Powell        cancelEnd = mBuffers[kPortIndexOutput].size();
82986100d18ad0bd5ae3267a0e0944d15f4fe94078aAdam Powell    } else {
83086100d18ad0bd5ae3267a0e0944d15f4fe94078aAdam Powell        // Return the required minimum undequeued buffers to the native window.
83186100d18ad0bd5ae3267a0e0944d15f4fe94078aAdam Powell        cancelStart = bufferCount - minUndequeuedBuffers;
83286100d18ad0bd5ae3267a0e0944d15f4fe94078aAdam Powell        cancelEnd = bufferCount;
83386100d18ad0bd5ae3267a0e0944d15f4fe94078aAdam Powell    }
83486100d18ad0bd5ae3267a0e0944d15f4fe94078aAdam Powell
83586100d18ad0bd5ae3267a0e0944d15f4fe94078aAdam Powell    for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
83686100d18ad0bd5ae3267a0e0944d15f4fe94078aAdam Powell        BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
83786100d18ad0bd5ae3267a0e0944d15f4fe94078aAdam Powell        status_t error = cancelBufferToNativeWindow(info);
83886100d18ad0bd5ae3267a0e0944d15f4fe94078aAdam Powell        if (err == 0) {
83986100d18ad0bd5ae3267a0e0944d15f4fe94078aAdam Powell            err = error;
84086100d18ad0bd5ae3267a0e0944d15f4fe94078aAdam Powell        }
84186100d18ad0bd5ae3267a0e0944d15f4fe94078aAdam Powell    }
84286100d18ad0bd5ae3267a0e0944d15f4fe94078aAdam Powell
84386100d18ad0bd5ae3267a0e0944d15f4fe94078aAdam Powell    return err;
84486100d18ad0bd5ae3267a0e0944d15f4fe94078aAdam Powell}
84586100d18ad0bd5ae3267a0e0944d15f4fe94078aAdam Powell
84686100d18ad0bd5ae3267a0e0944d15f4fe94078aAdam Powellstatus_t ACodec::allocateOutputMetaDataBuffers() {
84786100d18ad0bd5ae3267a0e0944d15f4fe94078aAdam Powell    OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers;
84886100d18ad0bd5ae3267a0e0944d15f4fe94078aAdam Powell    status_t err = configureOutputBuffersFromNativeWindow(
8497d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            &bufferCount, &bufferSize, &minUndequeuedBuffers);
8507d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    if (err != 0)
8517d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        return err;
8527d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    mNumUndequeuedBuffers = minUndequeuedBuffers;
8537d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
8547d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    ALOGV("[%s] Allocating %u meta buffers on output port",
8557d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell         mComponentName.c_str(), bufferCount);
8567d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
8577d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    size_t totalSize = bufferCount * 8;
8587d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    mDealer[kPortIndexOutput] = new MemoryDealer(totalSize, "ACodec");
8597d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
8607d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    // Dequeue buffers and send them to OMX
8619ded760f6378b79ae5f91fe694744981a4154d0bSudheer Shanka    for (OMX_U32 i = 0; i < bufferCount; i++) {
8629ded760f6378b79ae5f91fe694744981a4154d0bSudheer Shanka        BufferInfo info;
8639ded760f6378b79ae5f91fe694744981a4154d0bSudheer Shanka        info.mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
8649ded760f6378b79ae5f91fe694744981a4154d0bSudheer Shanka        info.mGraphicBuffer = NULL;
8659ded760f6378b79ae5f91fe694744981a4154d0bSudheer Shanka        info.mDequeuedAt = mDequeueCounter;
8667d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
8677d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        sp<IMemory> mem = mDealer[kPortIndexOutput]->allocate(
8687d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell                sizeof(struct VideoDecoderOutputMetaData));
869d974c7b4d150661562e341eb743986f06d150298Adam Powell        CHECK(mem.get() != NULL);
8700ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell        info.mData = new ABuffer(mem->pointer(), mem->size());
8712442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
8722442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        // we use useBuffer for metadata regardless of quirks
8732442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        err = mOMX->useBuffer(
8742442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                mNode, kPortIndexOutput, mem, &info.mBufferID);
87500f4aad704198a8293b9a1d2b931b8708073fe15Adam Powell
87600f4aad704198a8293b9a1d2b931b8708073fe15Adam Powell        mBuffers[kPortIndexOutput].push(info);
8772442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
8782442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        ALOGV("[%s] allocated meta buffer with ID %u (pointer = %p)",
8792442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell             mComponentName.c_str(), info.mBufferID, mem->pointer());
8802388251fcd8def03a6bbc91382e84db085cf4253Adam Powell    }
8812388251fcd8def03a6bbc91382e84db085cf4253Adam Powell
8822388251fcd8def03a6bbc91382e84db085cf4253Adam Powell    mMetaDataBuffersToSubmit = bufferCount - minUndequeuedBuffers;
8832388251fcd8def03a6bbc91382e84db085cf4253Adam Powell    return err;
8842388251fcd8def03a6bbc91382e84db085cf4253Adam Powell}
8852388251fcd8def03a6bbc91382e84db085cf4253Adam Powell
88652c39215db2a0e1d339733e06284a2ba81e4c794Adam Powellstatus_t ACodec::submitOutputMetaDataBuffer() {
88752c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell    CHECK(mStoreMetaDataInOutputBuffers);
88852c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell    if (mMetaDataBuffersToSubmit == 0)
8892388251fcd8def03a6bbc91382e84db085cf4253Adam Powell        return OK;
8902388251fcd8def03a6bbc91382e84db085cf4253Adam Powell
8912388251fcd8def03a6bbc91382e84db085cf4253Adam Powell    BufferInfo *info = dequeueBufferFromNativeWindow();
8922388251fcd8def03a6bbc91382e84db085cf4253Adam Powell    if (info == NULL)
8932388251fcd8def03a6bbc91382e84db085cf4253Adam Powell        return ERROR_IO;
8942388251fcd8def03a6bbc91382e84db085cf4253Adam Powell
8952388251fcd8def03a6bbc91382e84db085cf4253Adam Powell    ALOGV("[%s] submitting output meta buffer ID %u for graphic buffer %p",
8962388251fcd8def03a6bbc91382e84db085cf4253Adam Powell          mComponentName.c_str(), info->mBufferID, info->mGraphicBuffer.get());
8977d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
8982442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    --mMetaDataBuffersToSubmit;
8992442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    CHECK_EQ(mOMX->fillBuffer(mNode, info->mBufferID),
9002442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell             (status_t)OK);
9012442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
9022442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
9032442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    return OK;
9042442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell}
9052442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
9062442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powellstatus_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) {
9072442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
9082442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
9092442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    ALOGV("[%s] Calling cancelBuffer on buffer %u",
910c6d5e3a406c0e80638304980bac13abaa703a9a0Adam Powell         mComponentName.c_str(), info->mBufferID);
911c6d5e3a406c0e80638304980bac13abaa703a9a0Adam Powell
912c6d5e3a406c0e80638304980bac13abaa703a9a0Adam Powell    int err = mNativeWindow->cancelBuffer(
913c6d5e3a406c0e80638304980bac13abaa703a9a0Adam Powell        mNativeWindow.get(), info->mGraphicBuffer.get(), -1);
914c6d5e3a406c0e80638304980bac13abaa703a9a0Adam Powell
9152442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    ALOGW_IF(err != 0, "[%s] can not return buffer %u to native window",
916a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell            mComponentName.c_str(), info->mBufferID);
9172442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
9182442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
9195007735782ef5b48a5a8b6d317aff693ffad2db9Adam Powell
9205007735782ef5b48a5a8b6d317aff693ffad2db9Adam Powell    return err;
921a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell}
9225007735782ef5b48a5a8b6d317aff693ffad2db9Adam Powell
9235007735782ef5b48a5a8b6d317aff693ffad2db9Adam PowellACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
9245007735782ef5b48a5a8b6d317aff693ffad2db9Adam Powell    ANativeWindowBuffer *buf;
9257d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    int fenceFd = -1;
9267d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    CHECK(mNativeWindow.get() != NULL);
9277d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
9285007735782ef5b48a5a8b6d317aff693ffad2db9Adam Powell    if (mTunneled) {
929565943fda5b05ac5514c216effaf76fc98c5b6c0Adam Powell        ALOGW("dequeueBufferFromNativeWindow() should not be called in tunnel"
930565943fda5b05ac5514c216effaf76fc98c5b6c0Adam Powell              " video playback mode mode!");
931565943fda5b05ac5514c216effaf76fc98c5b6c0Adam Powell        return NULL;
932a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell    }
9337d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
9347d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    if (native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf) != 0) {
9357d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        ALOGE("dequeueBuffer failed.");
9367d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        return NULL;
9377d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    }
9387d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
9397d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    BufferInfo *oldest = NULL;
9407d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
9417d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        BufferInfo *info =
942a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell            &mBuffers[kPortIndexOutput].editItemAt(i);
9437d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
9447d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        if (info->mGraphicBuffer != NULL &&
9457d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            info->mGraphicBuffer->handle == buf->handle) {
9467d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            CHECK_EQ((int)info->mStatus,
9477d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell                     (int)BufferInfo::OWNED_BY_NATIVE_WINDOW);
948a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell
9497d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            info->mStatus = BufferInfo::OWNED_BY_US;
9507d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
9517d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            return info;
9527d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        }
9537d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
9547d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW &&
9557d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            (oldest == NULL ||
9567d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell             // avoid potential issues from counter rolling over
9577d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell             mDequeueCounter - info->mDequeuedAt >
9587d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell                    mDequeueCounter - oldest->mDequeuedAt)) {
9597d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            oldest = info;
9607d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        }
9617d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    }
9622442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
9632442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    if (oldest) {
9645007735782ef5b48a5a8b6d317aff693ffad2db9Adam Powell        CHECK(mStoreMetaDataInOutputBuffers);
9655007735782ef5b48a5a8b6d317aff693ffad2db9Adam Powell
9665007735782ef5b48a5a8b6d317aff693ffad2db9Adam Powell        // discard buffer in LRU info and replace with new buffer
9675007735782ef5b48a5a8b6d317aff693ffad2db9Adam Powell        oldest->mGraphicBuffer = new GraphicBuffer(buf, false);
9685007735782ef5b48a5a8b6d317aff693ffad2db9Adam Powell        oldest->mStatus = BufferInfo::OWNED_BY_US;
9692442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
9700ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell        mOMX->updateGraphicBufferInMeta(
971a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell                mNode, kPortIndexOutput, oldest->mGraphicBuffer,
9720ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell                oldest->mBufferID);
9730ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell
9740ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell        VideoDecoderOutputMetaData *metaData =
9750ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell            reinterpret_cast<VideoDecoderOutputMetaData *>(
9760ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell                    oldest->mData->base());
977a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell        CHECK_EQ(metaData->eType, kMetadataBufferTypeGrallocSource);
9780ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell
9790ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell        ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)",
9802442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                oldest - &mBuffers[kPortIndexOutput][0],
9810ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell                mDequeueCounter - oldest->mDequeuedAt,
9820ccc0e9348e42fd8094bb12324f7c5bb6ca018adAdam Powell                metaData->pHandle,
9835007735782ef5b48a5a8b6d317aff693ffad2db9Adam Powell                oldest->mGraphicBuffer->handle, oldest->mData->base());
9845007735782ef5b48a5a8b6d317aff693ffad2db9Adam Powell
9852442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        return oldest;
9862442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    }
9872442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
9882442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    TRESPASS();
9892442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
990a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell    return NULL;
991a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell}
992a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell
993bba0030a8529fd904056cbb7cfbbe3afbc1c8a95Adam Powellstatus_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) {
994a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell    for (size_t i = mBuffers[portIndex].size(); i-- > 0;) {
995a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell        CHECK_EQ((status_t)OK, freeBuffer(portIndex, i));
996a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell    }
997a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell
998a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell    mDealer[portIndex].clear();
999a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell
1000a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell    return OK;
1001a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell}
1002a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell
1003a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powellstatus_t ACodec::freeOutputBuffersNotOwnedByComponent() {
1004a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell    for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
1005a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell        BufferInfo *info =
1006a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell            &mBuffers[kPortIndexOutput].editItemAt(i);
1007a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell
1008a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell        // At this time some buffers may still be with the component
1009a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell        // or being drained.
1010a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell        if (info->mStatus != BufferInfo::OWNED_BY_COMPONENT &&
1011a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell            info->mStatus != BufferInfo::OWNED_BY_DOWNSTREAM) {
1012a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell            CHECK_EQ((status_t)OK, freeBuffer(kPortIndexOutput, i));
1013a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell        }
10142442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    }
10152442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
1016a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell    return OK;
10172442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell}
10182442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
10192442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powellstatus_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) {
10202442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
1021565943fda5b05ac5514c216effaf76fc98c5b6c0Adam Powell
1022565943fda5b05ac5514c216effaf76fc98c5b6c0Adam Powell    CHECK(info->mStatus == BufferInfo::OWNED_BY_US
1023565943fda5b05ac5514c216effaf76fc98c5b6c0Adam Powell            || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
1024565943fda5b05ac5514c216effaf76fc98c5b6c0Adam Powell
1025565943fda5b05ac5514c216effaf76fc98c5b6c0Adam Powell    if (portIndex == kPortIndexOutput && mNativeWindow != NULL
1026565943fda5b05ac5514c216effaf76fc98c5b6c0Adam Powell            && info->mStatus == BufferInfo::OWNED_BY_US) {
1027565943fda5b05ac5514c216effaf76fc98c5b6c0Adam Powell        cancelBufferToNativeWindow(info);
1028565943fda5b05ac5514c216effaf76fc98c5b6c0Adam Powell    }
1029a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell
1030a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell    CHECK_EQ(mOMX->freeBuffer(
1031a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell                mNode, portIndex, info->mBufferID),
1032a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell             (status_t)OK);
1033a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell
1034a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell    mBuffers[portIndex].removeAt(i);
1035a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell
1036a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell    return OK;
1037a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell}
1038a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell
1039a182e45c6851a8db89e8b0900f0812806ff295d4Adam PowellACodec::BufferInfo *ACodec::findBufferByID(
1040a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell        uint32_t portIndex, IOMX::buffer_id bufferID,
10412442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        ssize_t *index) {
10422442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
10432442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
10442442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
10452442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        if (info->mBufferID == bufferID) {
10462442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell            if (index != NULL) {
10472442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                *index = i;
10482442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell            }
10492442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell            return info;
10502442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        }
10512442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell    }
10522442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
1053a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell    TRESPASS();
1054a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell
1055a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell    return NULL;
1056a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell}
105777a533f5b2a1640f52fc2ccbcf8c74c9aed94d6eAdam Powell
1058a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powellstatus_t ACodec::setComponentRole(
1059a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell        bool isEncoder, const char *mime) {
1060a182e45c6851a8db89e8b0900f0812806ff295d4Adam Powell    struct MimeToRole {
106163b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        const char *mime;
106263b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        const char *decoderRole;
106363b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        const char *encoderRole;
106463b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell    };
106563b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell
106663b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell    static const MimeToRole kMimeToRole[] = {
106763b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        { MEDIA_MIMETYPE_AUDIO_MPEG,
106863b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            "audio_decoder.mp3", "audio_encoder.mp3" },
106963b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I,
107063b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            "audio_decoder.mp1", "audio_encoder.mp1" },
107163b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II,
107263b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            "audio_decoder.mp2", "audio_encoder.mp2" },
107363b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        { MEDIA_MIMETYPE_AUDIO_AMR_NB,
107463b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            "audio_decoder.amrnb", "audio_encoder.amrnb" },
107563b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        { MEDIA_MIMETYPE_AUDIO_AMR_WB,
107663b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            "audio_decoder.amrwb", "audio_encoder.amrwb" },
107763b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        { MEDIA_MIMETYPE_AUDIO_AAC,
107863b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            "audio_decoder.aac", "audio_encoder.aac" },
107963b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        { MEDIA_MIMETYPE_AUDIO_VORBIS,
108063b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            "audio_decoder.vorbis", "audio_encoder.vorbis" },
108163b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        { MEDIA_MIMETYPE_AUDIO_OPUS,
108263b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            "audio_decoder.opus", "audio_encoder.opus" },
108363b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        { MEDIA_MIMETYPE_AUDIO_G711_MLAW,
108463b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" },
108563b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        { MEDIA_MIMETYPE_AUDIO_G711_ALAW,
108663b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            "audio_decoder.g711alaw", "audio_encoder.g711alaw" },
108763b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        { MEDIA_MIMETYPE_VIDEO_AVC,
108863b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            "video_decoder.avc", "video_encoder.avc" },
108963b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        { MEDIA_MIMETYPE_VIDEO_HEVC,
109063b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            "video_decoder.hevc", "video_encoder.hevc" },
109163b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        { MEDIA_MIMETYPE_VIDEO_MPEG4,
109263b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            "video_decoder.mpeg4", "video_encoder.mpeg4" },
109363b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        { MEDIA_MIMETYPE_VIDEO_H263,
109463b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            "video_decoder.h263", "video_encoder.h263" },
109563b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        { MEDIA_MIMETYPE_VIDEO_VP8,
109663b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            "video_decoder.vp8", "video_encoder.vp8" },
109763b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        { MEDIA_MIMETYPE_VIDEO_VP9,
109863b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            "video_decoder.vp9", "video_encoder.vp9" },
109963b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        { MEDIA_MIMETYPE_AUDIO_RAW,
110063b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            "audio_decoder.raw", "audio_encoder.raw" },
110163b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        { MEDIA_MIMETYPE_AUDIO_FLAC,
110263b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            "audio_decoder.flac", "audio_encoder.flac" },
110363b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        { MEDIA_MIMETYPE_AUDIO_MSGSM,
110463b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            "audio_decoder.gsm", "audio_encoder.gsm" },
110563b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        { MEDIA_MIMETYPE_VIDEO_MPEG2,
110663b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            "video_decoder.mpeg2", "video_encoder.mpeg2" },
110763b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        { MEDIA_MIMETYPE_AUDIO_AC3,
110863b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            "audio_decoder.ac3", "audio_encoder.ac3" },
110963b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        { MEDIA_MIMETYPE_AUDIO_EAC3,
111063b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            "audio_decoder.eac3", "audio_encoder.eac3" },
111163b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell    };
111263b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell
111363b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell    static const size_t kNumMimeToRole =
111463b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
111563b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell
111663b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell    size_t i;
11177d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    for (i = 0; i < kNumMimeToRole; ++i) {
11187d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        if (!strcasecmp(mime, kMimeToRole[i].mime)) {
11197d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            break;
11207d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        }
112163b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell    }
112263b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell
11237d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    if (i == kNumMimeToRole) {
11247d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        return ERROR_UNSUPPORTED;
11257d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    }
11267d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
11277d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    const char *role =
112863b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        isEncoder ? kMimeToRole[i].encoderRole
112963b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                  : kMimeToRole[i].decoderRole;
113063b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell
11317d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    if (role != NULL) {
11327d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        OMX_PARAM_COMPONENTROLETYPE roleParams;
11337d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        InitOMXParams(&roleParams);
11347d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
113563b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        strncpy((char *)roleParams.cRole,
113663b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                role, OMX_MAX_STRINGNAME_SIZE - 1);
113763b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell
113863b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
113963b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell
114063b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        status_t err = mOMX->setParameter(
114163b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                mNode, OMX_IndexParamStandardComponentRole,
114263b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                &roleParams, sizeof(roleParams));
114363b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell
114463b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        if (err != OK) {
114563b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            ALOGW("[%s] Failed to set standard component role '%s'.",
114663b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                 mComponentName.c_str(), role);
114763b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell
114863b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            return err;
114963b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        }
115063b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell    }
115163b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell
115263b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell    return OK;
115363b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell}
11544eb9871ead5fa5f6b86bacee3a18d9ad52ad6d32Adam Powell
11554eb9871ead5fa5f6b86bacee3a18d9ad52ad6d32Adam Powellstatus_t ACodec::configureCodec(
11564eb9871ead5fa5f6b86bacee3a18d9ad52ad6d32Adam Powell        const char *mime, const sp<AMessage> &msg) {
11574eb9871ead5fa5f6b86bacee3a18d9ad52ad6d32Adam Powell    int32_t encoder;
11584eb9871ead5fa5f6b86bacee3a18d9ad52ad6d32Adam Powell    if (!msg->findInt32("encoder", &encoder)) {
11594eb9871ead5fa5f6b86bacee3a18d9ad52ad6d32Adam Powell        encoder = false;
11604eb9871ead5fa5f6b86bacee3a18d9ad52ad6d32Adam Powell    }
11614eb9871ead5fa5f6b86bacee3a18d9ad52ad6d32Adam Powell
11624eb9871ead5fa5f6b86bacee3a18d9ad52ad6d32Adam Powell    sp<AMessage> inputFormat = new AMessage();
116363b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell    sp<AMessage> outputFormat = mNotify->dup(); // will use this for kWhatOutputFormatChanged
116463b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell
116563b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell    mIsEncoder = encoder;
11667d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
11677d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    status_t err = setComponentRole(encoder /* isEncoder */, mime);
11687d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
11697d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    if (err != OK) {
11707d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        return err;
11717d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    }
11727d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
117363b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell    int32_t bitRate = 0;
117463b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell    // FLAC encoder doesn't need a bitrate, other encoders do
117563b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell    if (encoder && strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)
117663b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            && !msg->findInt32("bitrate", &bitRate)) {
117763b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        return INVALID_OPERATION;
11787d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    }
11797d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
11807d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    int32_t storeMeta;
11817d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    if (encoder
118263b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            && msg->findInt32("store-metadata-in-buffers", &storeMeta)
118363b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            && storeMeta != 0) {
118463b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexInput, OMX_TRUE);
118563b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell
118663b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        if (err != OK) {
118763b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell              ALOGE("[%s] storeMetaDataInBuffers (input) failed w/ err %d",
118863b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                    mComponentName.c_str(), err);
118963b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell
119063b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell              return err;
11917d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell          }
11927d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell      }
11937d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
119463b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell    int32_t prependSPSPPS = 0;
119563b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell    if (encoder
11967d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            && msg->findInt32("prepend-sps-pps-to-idr-frames", &prependSPSPPS)
11977d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            && prependSPSPPS != 0) {
11987d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        OMX_INDEXTYPE index;
11997d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        err = mOMX->getExtensionIndex(
120063b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                mNode,
120163b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                "OMX.google.android.index.prependSPSPPSToIDRFrames",
120263b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                &index);
120363b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell
120463b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        if (err == OK) {
120563b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            PrependSPSPPSToIDRFramesParams params;
120663b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            InitOMXParams(&params);
120763b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            params.bEnable = OMX_TRUE;
120863b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell
120963b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            err = mOMX->setParameter(
12107d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell                    mNode, index, &params, sizeof(params));
12117d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        }
12127d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
12137d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        if (err != OK) {
12147d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            ALOGE("Encoder could not be configured to emit SPS/PPS before "
12157d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell                  "IDR frames. (err %d)", err);
12167d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
12177d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            return err;
12187d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        }
12197d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    }
12207d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
12217d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    // Only enable metadata mode on encoder output if encoder can prepend
12227d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    // sps/pps to idr frames, since in metadata mode the bitstream is in an
122363b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell    // opaque handle, to which we don't have access.
12247d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    int32_t video = !strncasecmp(mime, "video/", 6);
12257d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell    if (encoder && video) {
12267d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        OMX_BOOL enable = (OMX_BOOL) (prependSPSPPS
122763b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            && msg->findInt32("store-metadata-in-buffers-output", &storeMeta)
12287d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            && storeMeta != 0);
12297d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
12307d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, enable);
123163b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell
12327d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        if (err != OK) {
12337d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            ALOGE("[%s] storeMetaDataInBuffers (output) failed w/ err %d",
123463b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                mComponentName.c_str(), err);
12357d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            mUseMetadataOnEncoderOutput = 0;
12367d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        } else {
123763b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            mUseMetadataOnEncoderOutput = enable;
123863b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        }
123963b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell
12407d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        if (!msg->findInt64(
124163b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                    "repeat-previous-frame-after",
12424eb9871ead5fa5f6b86bacee3a18d9ad52ad6d32Adam Powell                    &mRepeatFrameDelayUs)) {
124363b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            mRepeatFrameDelayUs = -1ll;
124463b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        }
124563b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell
12464eb9871ead5fa5f6b86bacee3a18d9ad52ad6d32Adam Powell        if (!msg->findInt64("max-pts-gap-to-encoder", &mMaxPtsGapUs)) {
124763b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            mMaxPtsGapUs = -1ll;
124863b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        }
124963b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell
125063b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        if (!msg->findInt64("time-lapse", &mTimePerCaptureUs)) {
125163b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            mTimePerCaptureUs = -1ll;
12522388251fcd8def03a6bbc91382e84db085cf4253Adam Powell        }
12534eb9871ead5fa5f6b86bacee3a18d9ad52ad6d32Adam Powell
12544eb9871ead5fa5f6b86bacee3a18d9ad52ad6d32Adam Powell        if (!msg->findInt32(
125563b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                    "create-input-buffers-suspended",
125663b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                    (int32_t*)&mCreateInputBuffersSuspended)) {
125763b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            mCreateInputBuffersSuspended = false;
125863b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        }
125963b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell    }
126063b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell
126163b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell    sp<RefBase> obj;
126263b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell    bool haveNativeWindow = msg->findObject("native-window", &obj)
126363b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            && obj != NULL;
126463b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell    mStoreMetaDataInOutputBuffers = false;
126563b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell    if (video && !encoder) {
126663b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        inputFormat->setInt32("adaptive-playback", false);
126763b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell
126863b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        int32_t usageProtected;
126963b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        if (msg->findInt32("protected", &usageProtected) && usageProtected) {
127063b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            if (!haveNativeWindow) {
127163b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                ALOGE("protected output buffers must be sent to an ANativeWindow");
127263b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                return PERMISSION_DENIED;
127363b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            }
127463b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            mFlags |= kFlagIsGrallocUsageProtected;
127563b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
127663b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        }
127763b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell    }
127863b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell    if (!encoder && video && haveNativeWindow) {
127963b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        sp<NativeWindowWrapper> windowWrapper(
12807d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell                static_cast<NativeWindowWrapper *>(obj.get()));
12817d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        sp<ANativeWindow> nativeWindow = windowWrapper->getNativeWindow();
12827d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
12837d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        // START of temporary support for automatic FRC - THIS WILL BE REMOVED
12847d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        int32_t autoFrc;
128563b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        if (msg->findInt32("auto-frc", &autoFrc)) {
12867d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            bool enabled = autoFrc;
12877d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            OMX_CONFIG_BOOLEANTYPE config;
12887d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            InitOMXParams(&config);
12897d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            config.bEnabled = (OMX_BOOL)enabled;
12907d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            status_t temp = mOMX->setConfig(
12917d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell                    mNode, (OMX_INDEXTYPE)OMX_IndexConfigAutoFramerateConversion,
12927d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell                    &config, sizeof(config));
12937d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            if (temp == OK) {
12947d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell                outputFormat->setInt32("auto-frc", enabled);
129563b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            } else if (enabled) {
129663b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                ALOGI("codec does not support requested auto-frc (err %d)", temp);
12977d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            }
129863b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        }
129963b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        // END of temporary support for automatic FRC
130063b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell
130163b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        int32_t tunneled;
130263b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        if (msg->findInt32("feature-tunneled-playback", &tunneled) &&
130363b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            tunneled != 0) {
130463b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            ALOGI("Configuring TUNNELED video playback.");
130563b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            mTunneled = true;
13067d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
13077d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            int32_t audioHwSync = 0;
13087d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            if (!msg->findInt32("audio-hw-sync", &audioHwSync)) {
130963b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                ALOGW("No Audio HW Sync provided for video tunnel");
13107d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            }
13117d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            err = configureTunneledVideoPlayback(audioHwSync, nativeWindow);
13124eb9871ead5fa5f6b86bacee3a18d9ad52ad6d32Adam Powell            if (err != OK) {
13134eb9871ead5fa5f6b86bacee3a18d9ad52ad6d32Adam Powell                ALOGE("configureTunneledVideoPlayback(%d,%p) failed!",
13147d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell                        audioHwSync, nativeWindow.get());
13157d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell                return err;
13167d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            }
13177d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
13187d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            int32_t maxWidth = 0, maxHeight = 0;
13197d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            if (msg->findInt32("max-width", &maxWidth) &&
13207d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell                    msg->findInt32("max-height", &maxHeight)) {
13215007735782ef5b48a5a8b6d317aff693ffad2db9Adam Powell
13227d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell                err = mOMX->prepareForAdaptivePlayback(
13237d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell                        mNode, kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight);
13247d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell                if (err != OK) {
13257d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell                    ALOGW("[%s] prepareForAdaptivePlayback failed w/ err %d",
13267d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell                            mComponentName.c_str(), err);
13277d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell                } else {
13285007735782ef5b48a5a8b6d317aff693ffad2db9Adam Powell                    inputFormat->setInt32("max-width", maxWidth);
13297d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell                    inputFormat->setInt32("max-height", maxHeight);
13307d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell                    inputFormat->setInt32("adaptive-playback", true);
13317d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell                }
13327d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            }
13337d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell        } else {
13347d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            ALOGV("Configuring CPU controlled video playback.");
13357d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            mTunneled = false;
13367d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell
13377d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            // Explicity reset the sideband handle of the window for
13387d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            // non-tunneled video in case the window was previously used
13397d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell            // for a tunneled video playback.
134063b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            err = native_window_set_sideband_stream(nativeWindow.get(), NULL);
134163b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            if (err != OK) {
134263b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                ALOGE("set_sideband_stream(NULL) failed! (err %d).", err);
134363b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                return err;
13444eb9871ead5fa5f6b86bacee3a18d9ad52ad6d32Adam Powell            }
134563b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell
134663b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            // Always try to enable dynamic output buffers on native surface
134763b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            err = mOMX->storeMetaDataInBuffers(
134863b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                    mNode, kPortIndexOutput, OMX_TRUE);
13494eb9871ead5fa5f6b86bacee3a18d9ad52ad6d32Adam Powell            if (err != OK) {
135063b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                ALOGE("[%s] storeMetaDataInBuffers failed w/ err %d",
135163b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                        mComponentName.c_str(), err);
135263b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell
135363b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                // if adaptive playback has been requested, try JB fallback
135463b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                // NOTE: THIS FALLBACK MECHANISM WILL BE REMOVED DUE TO ITS
135563b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                // LARGE MEMORY REQUIREMENT
135663b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell
135763b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                // we will not do adaptive playback on software accessed
135863b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                // surfaces as they never had to respond to changes in the
13599761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                // crop window, and we don't trust that they will be able to.
136052c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell                int usageBits = 0;
13619761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                bool canDoAdaptivePlayback;
13629761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell
13639761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                if (nativeWindow->query(
13642442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                        nativeWindow.get(),
13652442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                        NATIVE_WINDOW_CONSUMER_USAGE_BITS,
13662442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                        &usageBits) != OK) {
13672442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                    canDoAdaptivePlayback = false;
13689761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                } else {
13699761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                    canDoAdaptivePlayback =
13709761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                        (usageBits &
13719761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                                (GRALLOC_USAGE_SW_READ_MASK |
13729761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                                 GRALLOC_USAGE_SW_WRITE_MASK)) == 0;
13739761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                }
13749761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell
13759761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                int32_t maxWidth = 0, maxHeight = 0;
13769761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                if (canDoAdaptivePlayback &&
13779761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                        msg->findInt32("max-width", &maxWidth) &&
13789761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                        msg->findInt32("max-height", &maxHeight)) {
13799761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                    ALOGV("[%s] prepareForAdaptivePlayback(%dx%d)",
13809761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                            mComponentName.c_str(), maxWidth, maxHeight);
13819761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell
13822442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                    err = mOMX->prepareForAdaptivePlayback(
13832442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                            mNode, kPortIndexOutput, OMX_TRUE, maxWidth,
13842442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                            maxHeight);
13859761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                    ALOGW_IF(err != OK,
13869761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                            "[%s] prepareForAdaptivePlayback failed w/ err %d",
13879761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                            mComponentName.c_str(), err);
13882442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
13892442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                    if (err == OK) {
13902442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                        inputFormat->setInt32("max-width", maxWidth);
13912442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                        inputFormat->setInt32("max-height", maxHeight);
13922442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                        inputFormat->setInt32("adaptive-playback", true);
13932442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                    }
13949761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                }
13959761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                // allow failure
13969761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                err = OK;
13979761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell            } else {
13989761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                ALOGV("[%s] storeMetaDataInBuffers succeeded",
13999761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                        mComponentName.c_str());
14009761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                mStoreMetaDataInOutputBuffers = true;
14019761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                inputFormat->setInt32("adaptive-playback", true);
14029761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell            }
14039761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell
14049761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell            int32_t push;
14059761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell            if (msg->findInt32("push-blank-buffers-on-shutdown", &push)
14069761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                    && push != 0) {
14079761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
14089761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell            }
14099761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell        }
14102442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
14112442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        int32_t rotationDegrees;
14122442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        if (msg->findInt32("rotation-degrees", &rotationDegrees)) {
14132442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell            mRotationDegrees = rotationDegrees;
14142442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        } else {
14152442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell            mRotationDegrees = 0;
14169761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell        }
14179761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell    }
14189761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell
14199761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell    if (video) {
14209761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell        if (encoder) {
14219761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell            err = setupVideoEncoder(mime, msg);
14229761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell        } else {
14239761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell            err = setupVideoDecoder(mime, msg, haveNativeWindow);
14249761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell        }
14259761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
14269761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell        int32_t numChannels, sampleRate;
14279761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell        if (!msg->findInt32("channel-count", &numChannels)
14289761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                || !msg->findInt32("sample-rate", &sampleRate)) {
14299761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell            // Since we did not always check for these, leave them optional
14309761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell            // and have the decoder figure it all out.
14319761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell            err = OK;
14329761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell        } else {
14339761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell            err = setupRawAudioFormat(
14349761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                    encoder ? kPortIndexInput : kPortIndexOutput,
14359761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                    sampleRate,
14369761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell                    numChannels);
14379761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell        }
143852c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
14394c470d641c6906a742b63273b305695ba575b3e1Adam Powell        int32_t numChannels, sampleRate;
14402442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        if (!msg->findInt32("channel-count", &numChannels)
14412442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                || !msg->findInt32("sample-rate", &sampleRate)) {
14422442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell            err = INVALID_OPERATION;
14432442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell        } else {
14449761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell            int32_t isADTS, aacProfile;
14459761ab2a645a4643bd20619c7c148ef07e0dd39dAdam Powell            int32_t sbrMode;
144652c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell            int32_t maxOutputChannelCount;
144752c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell            int32_t pcmLimiterEnable;
144852c39215db2a0e1d339733e06284a2ba81e4c794Adam Powell            drcParams_t drc;
14492442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell            if (!msg->findInt32("is-adts", &isADTS)) {
14502442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                isADTS = 0;
14512442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell            }
14522442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell            if (!msg->findInt32("aac-profile", &aacProfile)) {
14532442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                aacProfile = OMX_AUDIO_AACObjectNull;
14542442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell            }
14552442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell            if (!msg->findInt32("aac-sbr-mode", &sbrMode)) {
14562442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                sbrMode = -1;
14572442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell            }
14582442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell
14592442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell            if (!msg->findInt32("aac-max-output-channel_count", &maxOutputChannelCount)) {
14602442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                maxOutputChannelCount = -1;
14612442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell            }
14622442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell            if (!msg->findInt32("aac-pcm-limiter-enable", &pcmLimiterEnable)) {
14632442841819f9554f9b5c8b9c147a51b04e50de4dAdam Powell                // value is unknown
14642ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                pcmLimiterEnable = -1;
14652ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell            }
14662ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell            if (!msg->findInt32("aac-encoded-target-level", &drc.encodedTargetLevel)) {
14672ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                // value is unknown
14682ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                drc.encodedTargetLevel = -1;
14692ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell            }
14702ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell            if (!msg->findInt32("aac-drc-cut-level", &drc.drcCut)) {
14712ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                // value is unknown
14722ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                drc.drcCut = -1;
14732ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell            }
14742ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell            if (!msg->findInt32("aac-drc-boost-level", &drc.drcBoost)) {
14752ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                // value is unknown
14762ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                drc.drcBoost = -1;
14772ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell            }
14782ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell            if (!msg->findInt32("aac-drc-heavy-compression", &drc.heavyCompression)) {
14792ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                // value is unknown
14802ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                drc.heavyCompression = -1;
14812ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell            }
14822ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell            if (!msg->findInt32("aac-target-ref-level", &drc.targetRefLevel)) {
14832ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                // value is unknown
14842ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                drc.targetRefLevel = -1;
14852ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell            }
14862ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
14872ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell            err = setupAACCodec(
14882ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                    encoder, numChannels, sampleRate, bitRate, aacProfile,
14892ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                    isADTS != 0, sbrMode, maxOutputChannelCount, drc,
14902ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                    pcmLimiterEnable);
14912ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell        }
14922ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
14932ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell        err = setupAMRCodec(encoder, false /* isWAMR */, bitRate);
14942ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
14952ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell        err = setupAMRCodec(encoder, true /* isWAMR */, bitRate);
14962ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW)
14972ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) {
14982ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell        // These are PCM-like formats with a fixed sample rate but
14992ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell        // a variable number of channels.
15002ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell
15012ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell        int32_t numChannels;
15022ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell        if (!msg->findInt32("channel-count", &numChannels)) {
15032ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell            err = INVALID_OPERATION;
15042ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell        } else {
15052ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell            err = setupG711Codec(encoder, numChannels);
15062ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell        }
15072ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) {
15082ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell        int32_t numChannels, sampleRate, compressionLevel = -1;
15092ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell        if (encoder &&
15102ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                (!msg->findInt32("channel-count", &numChannels)
15112ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell                        || !msg->findInt32("sample-rate", &sampleRate))) {
15122ed547e55f820a9c705872d802b051d8ae9c906bAdam Powell            ALOGE("missing channel count or sample rate for FLAC encoder");
151363b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            err = INVALID_OPERATION;
151463b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        } else {
151563b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            if (encoder) {
151663b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                if (!msg->findInt32(
151763b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                            "complexity", &compressionLevel) &&
151863b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                    !msg->findInt32(
151963b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                            "flac-compression-level", &compressionLevel)) {
152063b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                    compressionLevel = 5; // default FLAC compression level
152163b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                } else if (compressionLevel < 0) {
152263b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                    ALOGW("compression level %d outside [0..8] range, "
152363b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                          "using 0",
152463b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                          compressionLevel);
152563b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                    compressionLevel = 0;
152663b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                } else if (compressionLevel > 8) {
152763b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                    ALOGW("compression level %d outside [0..8] range, "
152863b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                          "using 8",
152963b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                          compressionLevel);
153063b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                    compressionLevel = 8;
153163b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                }
153263b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            }
153363b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            err = setupFlacCodec(
153463b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                    encoder, numChannels, sampleRate, compressionLevel);
153563b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        }
153663b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
153763b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        int32_t numChannels, sampleRate;
153863b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        if (encoder
153963b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                || !msg->findInt32("channel-count", &numChannels)
15404eb9871ead5fa5f6b86bacee3a18d9ad52ad6d32Adam Powell                || !msg->findInt32("sample-rate", &sampleRate)) {
154163b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            err = INVALID_OPERATION;
154263b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        } else {
154363b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
154463b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        }
154563b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AC3)) {
154663b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        int32_t numChannels;
154763b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        int32_t sampleRate;
154863b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        if (!msg->findInt32("channel-count", &numChannels)
154963b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell                || !msg->findInt32("sample-rate", &sampleRate)) {
155063b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            err = INVALID_OPERATION;
155163b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell        } else {
155263b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell            err = setupAC3Codec(encoder, numChannels, sampleRate);
15539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1554    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_EAC3)) {
1555        int32_t numChannels;
1556        int32_t sampleRate;
1557        if (!msg->findInt32("channel-count", &numChannels)
1558                || !msg->findInt32("sample-rate", &sampleRate)) {
1559            err = INVALID_OPERATION;
1560        } else {
1561            err = setupEAC3Codec(encoder, numChannels, sampleRate);
1562        }
1563    }
1564
1565    if (err != OK) {
1566        return err;
1567    }
1568
1569    if (!msg->findInt32("encoder-delay", &mEncoderDelay)) {
1570        mEncoderDelay = 0;
1571    }
1572
1573    if (!msg->findInt32("encoder-padding", &mEncoderPadding)) {
1574        mEncoderPadding = 0;
1575    }
1576
1577    if (msg->findInt32("channel-mask", &mChannelMask)) {
1578        mChannelMaskPresent = true;
1579    } else {
1580        mChannelMaskPresent = false;
1581    }
1582
1583    int32_t maxInputSize;
1584    if (msg->findInt32("max-input-size", &maxInputSize)) {
1585        err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize);
1586    } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) {
1587        err = setMinBufferSize(kPortIndexInput, 8192);  // XXX
1588    }
1589
1590    mBaseOutputFormat = outputFormat;
1591
1592    CHECK_EQ(getPortFormat(kPortIndexInput, inputFormat), (status_t)OK);
1593    CHECK_EQ(getPortFormat(kPortIndexOutput, outputFormat), (status_t)OK);
1594    mInputFormat = inputFormat;
1595    mOutputFormat = outputFormat;
1596
1597    return err;
1598}
1599
1600status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) {
1601    OMX_PARAM_PORTDEFINITIONTYPE def;
1602    InitOMXParams(&def);
1603    def.nPortIndex = portIndex;
1604
1605    status_t err = mOMX->getParameter(
1606            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1607
1608    if (err != OK) {
1609        return err;
1610    }
1611
1612    if (def.nBufferSize >= size) {
1613        return OK;
1614    }
1615
1616    def.nBufferSize = size;
1617
1618    err = mOMX->setParameter(
1619            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1620
1621    if (err != OK) {
1622        return err;
1623    }
1624
1625    err = mOMX->getParameter(
1626            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1627
1628    if (err != OK) {
1629        return err;
1630    }
1631
1632    CHECK(def.nBufferSize >= size);
1633
1634    return OK;
1635}
1636
1637status_t ACodec::selectAudioPortFormat(
1638        OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) {
1639    OMX_AUDIO_PARAM_PORTFORMATTYPE format;
1640    InitOMXParams(&format);
1641
1642    format.nPortIndex = portIndex;
1643    for (OMX_U32 index = 0;; ++index) {
1644        format.nIndex = index;
1645
1646        status_t err = mOMX->getParameter(
1647                mNode, OMX_IndexParamAudioPortFormat,
1648                &format, sizeof(format));
1649
1650        if (err != OK) {
1651            return err;
1652        }
1653
1654        if (format.eEncoding == desiredFormat) {
1655            break;
1656        }
1657    }
1658
1659    return mOMX->setParameter(
1660            mNode, OMX_IndexParamAudioPortFormat, &format, sizeof(format));
1661}
1662
1663status_t ACodec::setupAACCodec(
1664        bool encoder, int32_t numChannels, int32_t sampleRate,
1665        int32_t bitRate, int32_t aacProfile, bool isADTS, int32_t sbrMode,
1666        int32_t maxOutputChannelCount, const drcParams_t& drc,
1667        int32_t pcmLimiterEnable) {
1668    if (encoder && isADTS) {
1669        return -EINVAL;
1670    }
1671
1672    status_t err = setupRawAudioFormat(
1673            encoder ? kPortIndexInput : kPortIndexOutput,
1674            sampleRate,
1675            numChannels);
1676
1677    if (err != OK) {
1678        return err;
1679    }
1680
1681    if (encoder) {
1682        err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC);
1683
1684        if (err != OK) {
1685            return err;
1686        }
1687
1688        OMX_PARAM_PORTDEFINITIONTYPE def;
1689        InitOMXParams(&def);
1690        def.nPortIndex = kPortIndexOutput;
1691
1692        err = mOMX->getParameter(
1693                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1694
1695        if (err != OK) {
1696            return err;
1697        }
1698
1699        def.format.audio.bFlagErrorConcealment = OMX_TRUE;
1700        def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
1701
1702        err = mOMX->setParameter(
1703                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
1704
1705        if (err != OK) {
1706            return err;
1707        }
1708
1709        OMX_AUDIO_PARAM_AACPROFILETYPE profile;
1710        InitOMXParams(&profile);
1711        profile.nPortIndex = kPortIndexOutput;
1712
1713        err = mOMX->getParameter(
1714                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1715
1716        if (err != OK) {
1717            return err;
1718        }
1719
1720        profile.nChannels = numChannels;
1721
1722        profile.eChannelMode =
1723            (numChannels == 1)
1724                ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo;
1725
1726        profile.nSampleRate = sampleRate;
1727        profile.nBitRate = bitRate;
1728        profile.nAudioBandWidth = 0;
1729        profile.nFrameLength = 0;
1730        profile.nAACtools = OMX_AUDIO_AACToolAll;
1731        profile.nAACERtools = OMX_AUDIO_AACERNone;
1732        profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile;
1733        profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
1734        switch (sbrMode) {
1735        case 0:
1736            // disable sbr
1737            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
1738            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
1739            break;
1740        case 1:
1741            // enable single-rate sbr
1742            profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
1743            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
1744            break;
1745        case 2:
1746            // enable dual-rate sbr
1747            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
1748            profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
1749            break;
1750        case -1:
1751            // enable both modes -> the codec will decide which mode should be used
1752            profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
1753            profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
1754            break;
1755        default:
1756            // unsupported sbr mode
1757            return BAD_VALUE;
1758        }
1759
1760
1761        err = mOMX->setParameter(
1762                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1763
1764        if (err != OK) {
1765            return err;
1766        }
1767
1768        return err;
1769    }
1770
1771    OMX_AUDIO_PARAM_AACPROFILETYPE profile;
1772    InitOMXParams(&profile);
1773    profile.nPortIndex = kPortIndexInput;
1774
1775    err = mOMX->getParameter(
1776            mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1777
1778    if (err != OK) {
1779        return err;
1780    }
1781
1782    profile.nChannels = numChannels;
1783    profile.nSampleRate = sampleRate;
1784
1785    profile.eAACStreamFormat =
1786        isADTS
1787            ? OMX_AUDIO_AACStreamFormatMP4ADTS
1788            : OMX_AUDIO_AACStreamFormatMP4FF;
1789
1790    OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE presentation;
1791    presentation.nMaxOutputChannels = maxOutputChannelCount;
1792    presentation.nDrcCut = drc.drcCut;
1793    presentation.nDrcBoost = drc.drcBoost;
1794    presentation.nHeavyCompression = drc.heavyCompression;
1795    presentation.nTargetReferenceLevel = drc.targetRefLevel;
1796    presentation.nEncodedTargetLevel = drc.encodedTargetLevel;
1797    presentation.nPCMLimiterEnable = pcmLimiterEnable;
1798
1799    status_t res = mOMX->setParameter(mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
1800    if (res == OK) {
1801        // optional parameters, will not cause configuration failure
1802        mOMX->setParameter(mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacPresentation,
1803                &presentation, sizeof(presentation));
1804    } else {
1805        ALOGW("did not set AudioAndroidAacPresentation due to error %d when setting AudioAac", res);
1806    }
1807    return res;
1808}
1809
1810status_t ACodec::setupAC3Codec(
1811        bool encoder, int32_t numChannels, int32_t sampleRate) {
1812    status_t err = setupRawAudioFormat(
1813            encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
1814
1815    if (err != OK) {
1816        return err;
1817    }
1818
1819    if (encoder) {
1820        ALOGW("AC3 encoding is not supported.");
1821        return INVALID_OPERATION;
1822    }
1823
1824    OMX_AUDIO_PARAM_ANDROID_AC3TYPE def;
1825    InitOMXParams(&def);
1826    def.nPortIndex = kPortIndexInput;
1827
1828    err = mOMX->getParameter(
1829            mNode,
1830            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
1831            &def,
1832            sizeof(def));
1833
1834    if (err != OK) {
1835        return err;
1836    }
1837
1838    def.nChannels = numChannels;
1839    def.nSampleRate = sampleRate;
1840
1841    return mOMX->setParameter(
1842            mNode,
1843            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
1844            &def,
1845            sizeof(def));
1846}
1847
1848status_t ACodec::setupEAC3Codec(
1849        bool encoder, int32_t numChannels, int32_t sampleRate) {
1850    status_t err = setupRawAudioFormat(
1851            encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
1852
1853    if (err != OK) {
1854        return err;
1855    }
1856
1857    if (encoder) {
1858        ALOGW("EAC3 encoding is not supported.");
1859        return INVALID_OPERATION;
1860    }
1861
1862    OMX_AUDIO_PARAM_ANDROID_EAC3TYPE def;
1863    InitOMXParams(&def);
1864    def.nPortIndex = kPortIndexInput;
1865
1866    err = mOMX->getParameter(
1867            mNode,
1868            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
1869            &def,
1870            sizeof(def));
1871
1872    if (err != OK) {
1873        return err;
1874    }
1875
1876    def.nChannels = numChannels;
1877    def.nSampleRate = sampleRate;
1878
1879    return mOMX->setParameter(
1880            mNode,
1881            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
1882            &def,
1883            sizeof(def));
1884}
1885
1886static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(
1887        bool isAMRWB, int32_t bps) {
1888    if (isAMRWB) {
1889        if (bps <= 6600) {
1890            return OMX_AUDIO_AMRBandModeWB0;
1891        } else if (bps <= 8850) {
1892            return OMX_AUDIO_AMRBandModeWB1;
1893        } else if (bps <= 12650) {
1894            return OMX_AUDIO_AMRBandModeWB2;
1895        } else if (bps <= 14250) {
1896            return OMX_AUDIO_AMRBandModeWB3;
1897        } else if (bps <= 15850) {
1898            return OMX_AUDIO_AMRBandModeWB4;
1899        } else if (bps <= 18250) {
1900            return OMX_AUDIO_AMRBandModeWB5;
1901        } else if (bps <= 19850) {
1902            return OMX_AUDIO_AMRBandModeWB6;
1903        } else if (bps <= 23050) {
1904            return OMX_AUDIO_AMRBandModeWB7;
1905        }
1906
1907        // 23850 bps
1908        return OMX_AUDIO_AMRBandModeWB8;
1909    } else {  // AMRNB
1910        if (bps <= 4750) {
1911            return OMX_AUDIO_AMRBandModeNB0;
1912        } else if (bps <= 5150) {
1913            return OMX_AUDIO_AMRBandModeNB1;
1914        } else if (bps <= 5900) {
1915            return OMX_AUDIO_AMRBandModeNB2;
1916        } else if (bps <= 6700) {
1917            return OMX_AUDIO_AMRBandModeNB3;
1918        } else if (bps <= 7400) {
1919            return OMX_AUDIO_AMRBandModeNB4;
1920        } else if (bps <= 7950) {
1921            return OMX_AUDIO_AMRBandModeNB5;
1922        } else if (bps <= 10200) {
1923            return OMX_AUDIO_AMRBandModeNB6;
1924        }
1925
1926        // 12200 bps
1927        return OMX_AUDIO_AMRBandModeNB7;
1928    }
1929}
1930
1931status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) {
1932    OMX_AUDIO_PARAM_AMRTYPE def;
1933    InitOMXParams(&def);
1934    def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput;
1935
1936    status_t err =
1937        mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1938
1939    if (err != OK) {
1940        return err;
1941    }
1942
1943    def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
1944    def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate);
1945
1946    err = mOMX->setParameter(
1947            mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
1948
1949    if (err != OK) {
1950        return err;
1951    }
1952
1953    return setupRawAudioFormat(
1954            encoder ? kPortIndexInput : kPortIndexOutput,
1955            isWAMR ? 16000 : 8000 /* sampleRate */,
1956            1 /* numChannels */);
1957}
1958
1959status_t ACodec::setupG711Codec(bool encoder, int32_t numChannels) {
1960    CHECK(!encoder);  // XXX TODO
1961
1962    return setupRawAudioFormat(
1963            kPortIndexInput, 8000 /* sampleRate */, numChannels);
1964}
1965
1966status_t ACodec::setupFlacCodec(
1967        bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel) {
1968
1969    if (encoder) {
1970        OMX_AUDIO_PARAM_FLACTYPE def;
1971        InitOMXParams(&def);
1972        def.nPortIndex = kPortIndexOutput;
1973
1974        // configure compression level
1975        status_t err = mOMX->getParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def));
1976        if (err != OK) {
1977            ALOGE("setupFlacCodec(): Error %d getting OMX_IndexParamAudioFlac parameter", err);
1978            return err;
1979        }
1980        def.nCompressionLevel = compressionLevel;
1981        err = mOMX->setParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def));
1982        if (err != OK) {
1983            ALOGE("setupFlacCodec(): Error %d setting OMX_IndexParamAudioFlac parameter", err);
1984            return err;
1985        }
1986    }
1987
1988    return setupRawAudioFormat(
1989            encoder ? kPortIndexInput : kPortIndexOutput,
1990            sampleRate,
1991            numChannels);
1992}
1993
1994status_t ACodec::setupRawAudioFormat(
1995        OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
1996    OMX_PARAM_PORTDEFINITIONTYPE def;
1997    InitOMXParams(&def);
1998    def.nPortIndex = portIndex;
1999
2000    status_t err = mOMX->getParameter(
2001            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2002
2003    if (err != OK) {
2004        return err;
2005    }
2006
2007    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
2008
2009    err = mOMX->setParameter(
2010            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2011
2012    if (err != OK) {
2013        return err;
2014    }
2015
2016    OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
2017    InitOMXParams(&pcmParams);
2018    pcmParams.nPortIndex = portIndex;
2019
2020    err = mOMX->getParameter(
2021            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
2022
2023    if (err != OK) {
2024        return err;
2025    }
2026
2027    pcmParams.nChannels = numChannels;
2028    pcmParams.eNumData = OMX_NumericalDataSigned;
2029    pcmParams.bInterleaved = OMX_TRUE;
2030    pcmParams.nBitPerSample = 16;
2031    pcmParams.nSamplingRate = sampleRate;
2032    pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
2033
2034    if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) {
2035        return OMX_ErrorNone;
2036    }
2037
2038    return mOMX->setParameter(
2039            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
2040}
2041
2042status_t ACodec::configureTunneledVideoPlayback(
2043        int32_t audioHwSync, const sp<ANativeWindow> &nativeWindow) {
2044    native_handle_t* sidebandHandle;
2045
2046    status_t err = mOMX->configureVideoTunnelMode(
2047            mNode, kPortIndexOutput, OMX_TRUE, audioHwSync, &sidebandHandle);
2048    if (err != OK) {
2049        ALOGE("configureVideoTunnelMode failed! (err %d).", err);
2050        return err;
2051    }
2052
2053    err = native_window_set_sideband_stream(nativeWindow.get(), sidebandHandle);
2054    if (err != OK) {
2055        ALOGE("native_window_set_sideband_stream(%p) failed! (err %d).",
2056                sidebandHandle, err);
2057        return err;
2058    }
2059
2060    return OK;
2061}
2062
2063status_t ACodec::setVideoPortFormatType(
2064        OMX_U32 portIndex,
2065        OMX_VIDEO_CODINGTYPE compressionFormat,
2066        OMX_COLOR_FORMATTYPE colorFormat,
2067        bool usingNativeBuffers) {
2068    OMX_VIDEO_PARAM_PORTFORMATTYPE format;
2069    InitOMXParams(&format);
2070    format.nPortIndex = portIndex;
2071    format.nIndex = 0;
2072    bool found = false;
2073
2074    OMX_U32 index = 0;
2075    for (;;) {
2076        format.nIndex = index;
2077        status_t err = mOMX->getParameter(
2078                mNode, OMX_IndexParamVideoPortFormat,
2079                &format, sizeof(format));
2080
2081        if (err != OK) {
2082            return err;
2083        }
2084
2085        // substitute back flexible color format to codec supported format
2086        OMX_U32 flexibleEquivalent;
2087        if (compressionFormat == OMX_VIDEO_CodingUnused
2088                && isFlexibleColorFormat(
2089                        mOMX, mNode, format.eColorFormat, usingNativeBuffers, &flexibleEquivalent)
2090                && colorFormat == flexibleEquivalent) {
2091            ALOGI("[%s] using color format %#x in place of %#x",
2092                    mComponentName.c_str(), format.eColorFormat, colorFormat);
2093            colorFormat = format.eColorFormat;
2094        }
2095
2096        // The following assertion is violated by TI's video decoder.
2097        // CHECK_EQ(format.nIndex, index);
2098
2099        if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) {
2100            if (portIndex == kPortIndexInput
2101                    && colorFormat == format.eColorFormat) {
2102                // eCompressionFormat does not seem right.
2103                found = true;
2104                break;
2105            }
2106            if (portIndex == kPortIndexOutput
2107                    && compressionFormat == format.eCompressionFormat) {
2108                // eColorFormat does not seem right.
2109                found = true;
2110                break;
2111            }
2112        }
2113
2114        if (format.eCompressionFormat == compressionFormat
2115            && format.eColorFormat == colorFormat) {
2116            found = true;
2117            break;
2118        }
2119
2120        ++index;
2121    }
2122
2123    if (!found) {
2124        return UNKNOWN_ERROR;
2125    }
2126
2127    status_t err = mOMX->setParameter(
2128            mNode, OMX_IndexParamVideoPortFormat,
2129            &format, sizeof(format));
2130
2131    return err;
2132}
2133
2134// Set optimal output format. OMX component lists output formats in the order
2135// of preference, but this got more complicated since the introduction of flexible
2136// YUV formats. We support a legacy behavior for applications that do not use
2137// surface output, do not specify an output format, but expect a "usable" standard
2138// OMX format. SW readable and standard formats must be flex-YUV.
2139//
2140// Suggested preference order:
2141// - optimal format for texture rendering (mediaplayer behavior)
2142// - optimal SW readable & texture renderable format (flex-YUV support)
2143// - optimal SW readable non-renderable format (flex-YUV bytebuffer support)
2144// - legacy "usable" standard formats
2145//
2146// For legacy support, we prefer a standard format, but will settle for a SW readable
2147// flex-YUV format.
2148status_t ACodec::setSupportedOutputFormat(bool getLegacyFlexibleFormat) {
2149    OMX_VIDEO_PARAM_PORTFORMATTYPE format, legacyFormat;
2150    InitOMXParams(&format);
2151    format.nPortIndex = kPortIndexOutput;
2152
2153    InitOMXParams(&legacyFormat);
2154    // this field will change when we find a suitable legacy format
2155    legacyFormat.eColorFormat = OMX_COLOR_FormatUnused;
2156
2157    for (OMX_U32 index = 0; ; ++index) {
2158        format.nIndex = index;
2159        status_t err = mOMX->getParameter(
2160                mNode, OMX_IndexParamVideoPortFormat,
2161                &format, sizeof(format));
2162        if (err != OK) {
2163            // no more formats, pick legacy format if found
2164            if (legacyFormat.eColorFormat != OMX_COLOR_FormatUnused) {
2165                 memcpy(&format, &legacyFormat, sizeof(format));
2166                 break;
2167            }
2168            return err;
2169        }
2170        if (format.eCompressionFormat != OMX_VIDEO_CodingUnused) {
2171            return OMX_ErrorBadParameter;
2172        }
2173        if (!getLegacyFlexibleFormat) {
2174            break;
2175        }
2176        // standard formats that were exposed to users before
2177        if (format.eColorFormat == OMX_COLOR_FormatYUV420Planar
2178                || format.eColorFormat == OMX_COLOR_FormatYUV420PackedPlanar
2179                || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
2180                || format.eColorFormat == OMX_COLOR_FormatYUV420PackedSemiPlanar
2181                || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar) {
2182            break;
2183        }
2184        // find best legacy non-standard format
2185        OMX_U32 flexibleEquivalent;
2186        if (legacyFormat.eColorFormat == OMX_COLOR_FormatUnused
2187                && isFlexibleColorFormat(
2188                        mOMX, mNode, format.eColorFormat, false /* usingNativeBuffers */,
2189                        &flexibleEquivalent)
2190                && flexibleEquivalent == OMX_COLOR_FormatYUV420Flexible) {
2191            memcpy(&legacyFormat, &format, sizeof(format));
2192        }
2193    }
2194    return mOMX->setParameter(
2195            mNode, OMX_IndexParamVideoPortFormat,
2196            &format, sizeof(format));
2197}
2198
2199static const struct VideoCodingMapEntry {
2200    const char *mMime;
2201    OMX_VIDEO_CODINGTYPE mVideoCodingType;
2202} kVideoCodingMapEntry[] = {
2203    { MEDIA_MIMETYPE_VIDEO_AVC, OMX_VIDEO_CodingAVC },
2204    { MEDIA_MIMETYPE_VIDEO_HEVC, OMX_VIDEO_CodingHEVC },
2205    { MEDIA_MIMETYPE_VIDEO_MPEG4, OMX_VIDEO_CodingMPEG4 },
2206    { MEDIA_MIMETYPE_VIDEO_H263, OMX_VIDEO_CodingH263 },
2207    { MEDIA_MIMETYPE_VIDEO_MPEG2, OMX_VIDEO_CodingMPEG2 },
2208    { MEDIA_MIMETYPE_VIDEO_VP8, OMX_VIDEO_CodingVP8 },
2209    { MEDIA_MIMETYPE_VIDEO_VP9, OMX_VIDEO_CodingVP9 },
2210};
2211
2212static status_t GetVideoCodingTypeFromMime(
2213        const char *mime, OMX_VIDEO_CODINGTYPE *codingType) {
2214    for (size_t i = 0;
2215         i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
2216         ++i) {
2217        if (!strcasecmp(mime, kVideoCodingMapEntry[i].mMime)) {
2218            *codingType = kVideoCodingMapEntry[i].mVideoCodingType;
2219            return OK;
2220        }
2221    }
2222
2223    *codingType = OMX_VIDEO_CodingUnused;
2224
2225    return ERROR_UNSUPPORTED;
2226}
2227
2228static status_t GetMimeTypeForVideoCoding(
2229        OMX_VIDEO_CODINGTYPE codingType, AString *mime) {
2230    for (size_t i = 0;
2231         i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
2232         ++i) {
2233        if (codingType == kVideoCodingMapEntry[i].mVideoCodingType) {
2234            *mime = kVideoCodingMapEntry[i].mMime;
2235            return OK;
2236        }
2237    }
2238
2239    mime->clear();
2240
2241    return ERROR_UNSUPPORTED;
2242}
2243
2244status_t ACodec::setupVideoDecoder(
2245        const char *mime, const sp<AMessage> &msg, bool haveNativeWindow) {
2246    int32_t width, height;
2247    if (!msg->findInt32("width", &width)
2248            || !msg->findInt32("height", &height)) {
2249        return INVALID_OPERATION;
2250    }
2251
2252    OMX_VIDEO_CODINGTYPE compressionFormat;
2253    status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
2254
2255    if (err != OK) {
2256        return err;
2257    }
2258
2259    err = setVideoPortFormatType(
2260            kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
2261
2262    if (err != OK) {
2263        return err;
2264    }
2265
2266    int32_t tmp;
2267    if (msg->findInt32("color-format", &tmp)) {
2268        OMX_COLOR_FORMATTYPE colorFormat =
2269            static_cast<OMX_COLOR_FORMATTYPE>(tmp);
2270        err = setVideoPortFormatType(
2271                kPortIndexOutput, OMX_VIDEO_CodingUnused, colorFormat, haveNativeWindow);
2272        if (err != OK) {
2273            ALOGW("[%s] does not support color format %d",
2274                  mComponentName.c_str(), colorFormat);
2275            err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */);
2276        }
2277    } else {
2278        err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */);
2279    }
2280
2281    if (err != OK) {
2282        return err;
2283    }
2284
2285    int32_t frameRateInt;
2286    float frameRateFloat;
2287    if (!msg->findFloat("frame-rate", &frameRateFloat)) {
2288        if (!msg->findInt32("frame-rate", &frameRateInt)) {
2289            frameRateInt = -1;
2290        }
2291        frameRateFloat = (float)frameRateInt;
2292    }
2293
2294    err = setVideoFormatOnPort(
2295            kPortIndexInput, width, height, compressionFormat, frameRateFloat);
2296
2297    if (err != OK) {
2298        return err;
2299    }
2300
2301    err = setVideoFormatOnPort(
2302            kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused);
2303
2304    if (err != OK) {
2305        return err;
2306    }
2307
2308    return OK;
2309}
2310
2311status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) {
2312    int32_t tmp;
2313    if (!msg->findInt32("color-format", &tmp)) {
2314        return INVALID_OPERATION;
2315    }
2316
2317    OMX_COLOR_FORMATTYPE colorFormat =
2318        static_cast<OMX_COLOR_FORMATTYPE>(tmp);
2319
2320    status_t err = setVideoPortFormatType(
2321            kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat);
2322
2323    if (err != OK) {
2324        ALOGE("[%s] does not support color format %d",
2325              mComponentName.c_str(), colorFormat);
2326
2327        return err;
2328    }
2329
2330    /* Input port configuration */
2331
2332    OMX_PARAM_PORTDEFINITIONTYPE def;
2333    InitOMXParams(&def);
2334
2335    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
2336
2337    def.nPortIndex = kPortIndexInput;
2338
2339    err = mOMX->getParameter(
2340            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2341
2342    if (err != OK) {
2343        return err;
2344    }
2345
2346    int32_t width, height, bitrate;
2347    if (!msg->findInt32("width", &width)
2348            || !msg->findInt32("height", &height)
2349            || !msg->findInt32("bitrate", &bitrate)) {
2350        return INVALID_OPERATION;
2351    }
2352
2353    video_def->nFrameWidth = width;
2354    video_def->nFrameHeight = height;
2355
2356    int32_t stride;
2357    if (!msg->findInt32("stride", &stride)) {
2358        stride = width;
2359    }
2360
2361    video_def->nStride = stride;
2362
2363    int32_t sliceHeight;
2364    if (!msg->findInt32("slice-height", &sliceHeight)) {
2365        sliceHeight = height;
2366    }
2367
2368    video_def->nSliceHeight = sliceHeight;
2369
2370    def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2;
2371
2372    float frameRate;
2373    if (!msg->findFloat("frame-rate", &frameRate)) {
2374        int32_t tmp;
2375        if (!msg->findInt32("frame-rate", &tmp)) {
2376            return INVALID_OPERATION;
2377        }
2378        frameRate = (float)tmp;
2379        mTimePerFrameUs = (int64_t) (1000000.0f / frameRate);
2380    }
2381
2382    video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
2383    video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
2384    // this is redundant as it was already set up in setVideoPortFormatType
2385    // FIXME for now skip this only for flexible YUV formats
2386    if (colorFormat != OMX_COLOR_FormatYUV420Flexible) {
2387        video_def->eColorFormat = colorFormat;
2388    }
2389
2390    err = mOMX->setParameter(
2391            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2392
2393    if (err != OK) {
2394        ALOGE("[%s] failed to set input port definition parameters.",
2395              mComponentName.c_str());
2396
2397        return err;
2398    }
2399
2400    /* Output port configuration */
2401
2402    OMX_VIDEO_CODINGTYPE compressionFormat;
2403    err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
2404
2405    if (err != OK) {
2406        return err;
2407    }
2408
2409    err = setVideoPortFormatType(
2410            kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused);
2411
2412    if (err != OK) {
2413        ALOGE("[%s] does not support compression format %d",
2414             mComponentName.c_str(), compressionFormat);
2415
2416        return err;
2417    }
2418
2419    def.nPortIndex = kPortIndexOutput;
2420
2421    err = mOMX->getParameter(
2422            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2423
2424    if (err != OK) {
2425        return err;
2426    }
2427
2428    video_def->nFrameWidth = width;
2429    video_def->nFrameHeight = height;
2430    video_def->xFramerate = 0;
2431    video_def->nBitrate = bitrate;
2432    video_def->eCompressionFormat = compressionFormat;
2433    video_def->eColorFormat = OMX_COLOR_FormatUnused;
2434
2435    err = mOMX->setParameter(
2436            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
2437
2438    if (err != OK) {
2439        ALOGE("[%s] failed to set output port definition parameters.",
2440              mComponentName.c_str());
2441
2442        return err;
2443    }
2444
2445    switch (compressionFormat) {
2446        case OMX_VIDEO_CodingMPEG4:
2447            err = setupMPEG4EncoderParameters(msg);
2448            break;
2449
2450        case OMX_VIDEO_CodingH263:
2451            err = setupH263EncoderParameters(msg);
2452            break;
2453
2454        case OMX_VIDEO_CodingAVC:
2455            err = setupAVCEncoderParameters(msg);
2456            break;
2457
2458        case OMX_VIDEO_CodingHEVC:
2459            err = setupHEVCEncoderParameters(msg);
2460            break;
2461
2462        case OMX_VIDEO_CodingVP8:
2463        case OMX_VIDEO_CodingVP9:
2464            err = setupVPXEncoderParameters(msg);
2465            break;
2466
2467        default:
2468            break;
2469    }
2470
2471    ALOGI("setupVideoEncoder succeeded");
2472
2473    return err;
2474}
2475
2476status_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) {
2477    OMX_VIDEO_PARAM_INTRAREFRESHTYPE params;
2478    InitOMXParams(&params);
2479    params.nPortIndex = kPortIndexOutput;
2480
2481    params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode);
2482
2483    if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic ||
2484            params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
2485        int32_t mbs;
2486        if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) {
2487            return INVALID_OPERATION;
2488        }
2489        params.nCirMBs = mbs;
2490    }
2491
2492    if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive ||
2493            params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) {
2494        int32_t mbs;
2495        if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) {
2496            return INVALID_OPERATION;
2497        }
2498        params.nAirMBs = mbs;
2499
2500        int32_t ref;
2501        if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) {
2502            return INVALID_OPERATION;
2503        }
2504        params.nAirRef = ref;
2505    }
2506
2507    status_t err = mOMX->setParameter(
2508            mNode, OMX_IndexParamVideoIntraRefresh,
2509            &params, sizeof(params));
2510    return err;
2511}
2512
2513static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) {
2514    if (iFramesInterval < 0) {
2515        return 0xFFFFFFFF;
2516    } else if (iFramesInterval == 0) {
2517        return 0;
2518    }
2519    OMX_U32 ret = frameRate * iFramesInterval;
2520    return ret;
2521}
2522
2523static OMX_VIDEO_CONTROLRATETYPE getBitrateMode(const sp<AMessage> &msg) {
2524    int32_t tmp;
2525    if (!msg->findInt32("bitrate-mode", &tmp)) {
2526        return OMX_Video_ControlRateVariable;
2527    }
2528
2529    return static_cast<OMX_VIDEO_CONTROLRATETYPE>(tmp);
2530}
2531
2532status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) {
2533    int32_t bitrate, iFrameInterval;
2534    if (!msg->findInt32("bitrate", &bitrate)
2535            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2536        return INVALID_OPERATION;
2537    }
2538
2539    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2540
2541    float frameRate;
2542    if (!msg->findFloat("frame-rate", &frameRate)) {
2543        int32_t tmp;
2544        if (!msg->findInt32("frame-rate", &tmp)) {
2545            return INVALID_OPERATION;
2546        }
2547        frameRate = (float)tmp;
2548    }
2549
2550    OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
2551    InitOMXParams(&mpeg4type);
2552    mpeg4type.nPortIndex = kPortIndexOutput;
2553
2554    status_t err = mOMX->getParameter(
2555            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
2556
2557    if (err != OK) {
2558        return err;
2559    }
2560
2561    mpeg4type.nSliceHeaderSpacing = 0;
2562    mpeg4type.bSVH = OMX_FALSE;
2563    mpeg4type.bGov = OMX_FALSE;
2564
2565    mpeg4type.nAllowedPictureTypes =
2566        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
2567
2568    mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
2569    if (mpeg4type.nPFrames == 0) {
2570        mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
2571    }
2572    mpeg4type.nBFrames = 0;
2573    mpeg4type.nIDCVLCThreshold = 0;
2574    mpeg4type.bACPred = OMX_TRUE;
2575    mpeg4type.nMaxPacketSize = 256;
2576    mpeg4type.nTimeIncRes = 1000;
2577    mpeg4type.nHeaderExtension = 0;
2578    mpeg4type.bReversibleVLC = OMX_FALSE;
2579
2580    int32_t profile;
2581    if (msg->findInt32("profile", &profile)) {
2582        int32_t level;
2583        if (!msg->findInt32("level", &level)) {
2584            return INVALID_OPERATION;
2585        }
2586
2587        err = verifySupportForProfileAndLevel(profile, level);
2588
2589        if (err != OK) {
2590            return err;
2591        }
2592
2593        mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile);
2594        mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level);
2595    }
2596
2597    err = mOMX->setParameter(
2598            mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
2599
2600    if (err != OK) {
2601        return err;
2602    }
2603
2604    err = configureBitrate(bitrate, bitrateMode);
2605
2606    if (err != OK) {
2607        return err;
2608    }
2609
2610    return setupErrorCorrectionParameters();
2611}
2612
2613status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) {
2614    int32_t bitrate, iFrameInterval;
2615    if (!msg->findInt32("bitrate", &bitrate)
2616            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2617        return INVALID_OPERATION;
2618    }
2619
2620    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2621
2622    float frameRate;
2623    if (!msg->findFloat("frame-rate", &frameRate)) {
2624        int32_t tmp;
2625        if (!msg->findInt32("frame-rate", &tmp)) {
2626            return INVALID_OPERATION;
2627        }
2628        frameRate = (float)tmp;
2629    }
2630
2631    OMX_VIDEO_PARAM_H263TYPE h263type;
2632    InitOMXParams(&h263type);
2633    h263type.nPortIndex = kPortIndexOutput;
2634
2635    status_t err = mOMX->getParameter(
2636            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
2637
2638    if (err != OK) {
2639        return err;
2640    }
2641
2642    h263type.nAllowedPictureTypes =
2643        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
2644
2645    h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
2646    if (h263type.nPFrames == 0) {
2647        h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
2648    }
2649    h263type.nBFrames = 0;
2650
2651    int32_t profile;
2652    if (msg->findInt32("profile", &profile)) {
2653        int32_t level;
2654        if (!msg->findInt32("level", &level)) {
2655            return INVALID_OPERATION;
2656        }
2657
2658        err = verifySupportForProfileAndLevel(profile, level);
2659
2660        if (err != OK) {
2661            return err;
2662        }
2663
2664        h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile);
2665        h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level);
2666    }
2667
2668    h263type.bPLUSPTYPEAllowed = OMX_FALSE;
2669    h263type.bForceRoundingTypeToZero = OMX_FALSE;
2670    h263type.nPictureHeaderRepetition = 0;
2671    h263type.nGOBHeaderInterval = 0;
2672
2673    err = mOMX->setParameter(
2674            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
2675
2676    if (err != OK) {
2677        return err;
2678    }
2679
2680    err = configureBitrate(bitrate, bitrateMode);
2681
2682    if (err != OK) {
2683        return err;
2684    }
2685
2686    return setupErrorCorrectionParameters();
2687}
2688
2689// static
2690int /* OMX_VIDEO_AVCLEVELTYPE */ ACodec::getAVCLevelFor(
2691        int width, int height, int rate, int bitrate,
2692        OMX_VIDEO_AVCPROFILETYPE profile) {
2693    // convert bitrate to main/baseline profile kbps equivalent
2694    switch (profile) {
2695        case OMX_VIDEO_AVCProfileHigh10:
2696            bitrate = divUp(bitrate, 3000); break;
2697        case OMX_VIDEO_AVCProfileHigh:
2698            bitrate = divUp(bitrate, 1250); break;
2699        default:
2700            bitrate = divUp(bitrate, 1000); break;
2701    }
2702
2703    // convert size and rate to MBs
2704    width = divUp(width, 16);
2705    height = divUp(height, 16);
2706    int mbs = width * height;
2707    rate *= mbs;
2708    int maxDimension = max(width, height);
2709
2710    static const int limits[][5] = {
2711        /*   MBps     MB   dim  bitrate        level */
2712        {    1485,    99,  28,     64, OMX_VIDEO_AVCLevel1  },
2713        {    1485,    99,  28,    128, OMX_VIDEO_AVCLevel1b },
2714        {    3000,   396,  56,    192, OMX_VIDEO_AVCLevel11 },
2715        {    6000,   396,  56,    384, OMX_VIDEO_AVCLevel12 },
2716        {   11880,   396,  56,    768, OMX_VIDEO_AVCLevel13 },
2717        {   11880,   396,  56,   2000, OMX_VIDEO_AVCLevel2  },
2718        {   19800,   792,  79,   4000, OMX_VIDEO_AVCLevel21 },
2719        {   20250,  1620, 113,   4000, OMX_VIDEO_AVCLevel22 },
2720        {   40500,  1620, 113,  10000, OMX_VIDEO_AVCLevel3  },
2721        {  108000,  3600, 169,  14000, OMX_VIDEO_AVCLevel31 },
2722        {  216000,  5120, 202,  20000, OMX_VIDEO_AVCLevel32 },
2723        {  245760,  8192, 256,  20000, OMX_VIDEO_AVCLevel4  },
2724        {  245760,  8192, 256,  50000, OMX_VIDEO_AVCLevel41 },
2725        {  522240,  8704, 263,  50000, OMX_VIDEO_AVCLevel42 },
2726        {  589824, 22080, 420, 135000, OMX_VIDEO_AVCLevel5  },
2727        {  983040, 36864, 543, 240000, OMX_VIDEO_AVCLevel51 },
2728        { 2073600, 36864, 543, 240000, OMX_VIDEO_AVCLevel52 },
2729    };
2730
2731    for (size_t i = 0; i < ARRAY_SIZE(limits); i++) {
2732        const int (&limit)[5] = limits[i];
2733        if (rate <= limit[0] && mbs <= limit[1] && maxDimension <= limit[2]
2734                && bitrate <= limit[3]) {
2735            return limit[4];
2736        }
2737    }
2738    return 0;
2739}
2740
2741status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
2742    int32_t bitrate, iFrameInterval;
2743    if (!msg->findInt32("bitrate", &bitrate)
2744            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2745        return INVALID_OPERATION;
2746    }
2747
2748    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2749
2750    float frameRate;
2751    if (!msg->findFloat("frame-rate", &frameRate)) {
2752        int32_t tmp;
2753        if (!msg->findInt32("frame-rate", &tmp)) {
2754            return INVALID_OPERATION;
2755        }
2756        frameRate = (float)tmp;
2757    }
2758
2759    status_t err = OK;
2760    int32_t intraRefreshMode = 0;
2761    if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) {
2762        err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode);
2763        if (err != OK) {
2764            ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x",
2765                    err, intraRefreshMode);
2766            return err;
2767        }
2768    }
2769
2770    OMX_VIDEO_PARAM_AVCTYPE h264type;
2771    InitOMXParams(&h264type);
2772    h264type.nPortIndex = kPortIndexOutput;
2773
2774    err = mOMX->getParameter(
2775            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
2776
2777    if (err != OK) {
2778        return err;
2779    }
2780
2781    h264type.nAllowedPictureTypes =
2782        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
2783
2784    int32_t profile;
2785    if (msg->findInt32("profile", &profile)) {
2786        int32_t level;
2787        if (!msg->findInt32("level", &level)) {
2788            return INVALID_OPERATION;
2789        }
2790
2791        err = verifySupportForProfileAndLevel(profile, level);
2792
2793        if (err != OK) {
2794            return err;
2795        }
2796
2797        h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile);
2798        h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level);
2799    }
2800
2801    // XXX
2802    if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) {
2803        ALOGW("Use baseline profile instead of %d for AVC recording",
2804            h264type.eProfile);
2805        h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
2806    }
2807
2808    if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
2809        h264type.nSliceHeaderSpacing = 0;
2810        h264type.bUseHadamard = OMX_TRUE;
2811        h264type.nRefFrames = 1;
2812        h264type.nBFrames = 0;
2813        h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
2814        if (h264type.nPFrames == 0) {
2815            h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
2816        }
2817        h264type.nRefIdx10ActiveMinus1 = 0;
2818        h264type.nRefIdx11ActiveMinus1 = 0;
2819        h264type.bEntropyCodingCABAC = OMX_FALSE;
2820        h264type.bWeightedPPrediction = OMX_FALSE;
2821        h264type.bconstIpred = OMX_FALSE;
2822        h264type.bDirect8x8Inference = OMX_FALSE;
2823        h264type.bDirectSpatialTemporal = OMX_FALSE;
2824        h264type.nCabacInitIdc = 0;
2825    }
2826
2827    if (h264type.nBFrames != 0) {
2828        h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
2829    }
2830
2831    h264type.bEnableUEP = OMX_FALSE;
2832    h264type.bEnableFMO = OMX_FALSE;
2833    h264type.bEnableASO = OMX_FALSE;
2834    h264type.bEnableRS = OMX_FALSE;
2835    h264type.bFrameMBsOnly = OMX_TRUE;
2836    h264type.bMBAFF = OMX_FALSE;
2837    h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
2838
2839    err = mOMX->setParameter(
2840            mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
2841
2842    if (err != OK) {
2843        return err;
2844    }
2845
2846    return configureBitrate(bitrate, bitrateMode);
2847}
2848
2849status_t ACodec::setupHEVCEncoderParameters(const sp<AMessage> &msg) {
2850    int32_t bitrate, iFrameInterval;
2851    if (!msg->findInt32("bitrate", &bitrate)
2852            || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
2853        return INVALID_OPERATION;
2854    }
2855
2856    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2857
2858    float frameRate;
2859    if (!msg->findFloat("frame-rate", &frameRate)) {
2860        int32_t tmp;
2861        if (!msg->findInt32("frame-rate", &tmp)) {
2862            return INVALID_OPERATION;
2863        }
2864        frameRate = (float)tmp;
2865    }
2866
2867    OMX_VIDEO_PARAM_HEVCTYPE hevcType;
2868    InitOMXParams(&hevcType);
2869    hevcType.nPortIndex = kPortIndexOutput;
2870
2871    status_t err = OK;
2872    err = mOMX->getParameter(
2873            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
2874    if (err != OK) {
2875        return err;
2876    }
2877
2878    int32_t profile;
2879    if (msg->findInt32("profile", &profile)) {
2880        int32_t level;
2881        if (!msg->findInt32("level", &level)) {
2882            return INVALID_OPERATION;
2883        }
2884
2885        err = verifySupportForProfileAndLevel(profile, level);
2886        if (err != OK) {
2887            return err;
2888        }
2889
2890        hevcType.eProfile = static_cast<OMX_VIDEO_HEVCPROFILETYPE>(profile);
2891        hevcType.eLevel = static_cast<OMX_VIDEO_HEVCLEVELTYPE>(level);
2892    }
2893
2894    // TODO: Need OMX structure definition for setting iFrameInterval
2895
2896    err = mOMX->setParameter(
2897            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType));
2898    if (err != OK) {
2899        return err;
2900    }
2901
2902    return configureBitrate(bitrate, bitrateMode);
2903}
2904
2905status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg) {
2906    int32_t bitrate;
2907    int32_t iFrameInterval = 0;
2908    size_t tsLayers = 0;
2909    OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE pattern =
2910        OMX_VIDEO_VPXTemporalLayerPatternNone;
2911    static const uint32_t kVp8LayerRateAlloction
2912        [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS]
2913        [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] = {
2914        {100, 100, 100},  // 1 layer
2915        { 60, 100, 100},  // 2 layers {60%, 40%}
2916        { 40,  60, 100},  // 3 layers {40%, 20%, 40%}
2917    };
2918    if (!msg->findInt32("bitrate", &bitrate)) {
2919        return INVALID_OPERATION;
2920    }
2921    msg->findInt32("i-frame-interval", &iFrameInterval);
2922
2923    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
2924
2925    float frameRate;
2926    if (!msg->findFloat("frame-rate", &frameRate)) {
2927        int32_t tmp;
2928        if (!msg->findInt32("frame-rate", &tmp)) {
2929            return INVALID_OPERATION;
2930        }
2931        frameRate = (float)tmp;
2932    }
2933
2934    AString tsSchema;
2935    if (msg->findString("ts-schema", &tsSchema)) {
2936        if (tsSchema == "webrtc.vp8.1-layer") {
2937            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
2938            tsLayers = 1;
2939        } else if (tsSchema == "webrtc.vp8.2-layer") {
2940            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
2941            tsLayers = 2;
2942        } else if (tsSchema == "webrtc.vp8.3-layer") {
2943            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
2944            tsLayers = 3;
2945        } else {
2946            ALOGW("Unsupported ts-schema [%s]", tsSchema.c_str());
2947        }
2948    }
2949
2950    OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
2951    InitOMXParams(&vp8type);
2952    vp8type.nPortIndex = kPortIndexOutput;
2953    status_t err = mOMX->getParameter(
2954            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
2955            &vp8type, sizeof(vp8type));
2956
2957    if (err == OK) {
2958        if (iFrameInterval > 0) {
2959            vp8type.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate);
2960        }
2961        vp8type.eTemporalPattern = pattern;
2962        vp8type.nTemporalLayerCount = tsLayers;
2963        if (tsLayers > 0) {
2964            for (size_t i = 0; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) {
2965                vp8type.nTemporalLayerBitrateRatio[i] =
2966                    kVp8LayerRateAlloction[tsLayers - 1][i];
2967            }
2968        }
2969        if (bitrateMode == OMX_Video_ControlRateConstant) {
2970            vp8type.nMinQuantizer = 2;
2971            vp8type.nMaxQuantizer = 63;
2972        }
2973
2974        err = mOMX->setParameter(
2975                mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
2976                &vp8type, sizeof(vp8type));
2977        if (err != OK) {
2978            ALOGW("Extended VP8 parameters set failed: %d", err);
2979        }
2980    }
2981
2982    return configureBitrate(bitrate, bitrateMode);
2983}
2984
2985status_t ACodec::verifySupportForProfileAndLevel(
2986        int32_t profile, int32_t level) {
2987    OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
2988    InitOMXParams(&params);
2989    params.nPortIndex = kPortIndexOutput;
2990
2991    for (params.nProfileIndex = 0;; ++params.nProfileIndex) {
2992        status_t err = mOMX->getParameter(
2993                mNode,
2994                OMX_IndexParamVideoProfileLevelQuerySupported,
2995                &params,
2996                sizeof(params));
2997
2998        if (err != OK) {
2999            return err;
3000        }
3001
3002        int32_t supportedProfile = static_cast<int32_t>(params.eProfile);
3003        int32_t supportedLevel = static_cast<int32_t>(params.eLevel);
3004
3005        if (profile == supportedProfile && level <= supportedLevel) {
3006            return OK;
3007        }
3008    }
3009}
3010
3011status_t ACodec::configureBitrate(
3012        int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode) {
3013    OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
3014    InitOMXParams(&bitrateType);
3015    bitrateType.nPortIndex = kPortIndexOutput;
3016
3017    status_t err = mOMX->getParameter(
3018            mNode, OMX_IndexParamVideoBitrate,
3019            &bitrateType, sizeof(bitrateType));
3020
3021    if (err != OK) {
3022        return err;
3023    }
3024
3025    bitrateType.eControlRate = bitrateMode;
3026    bitrateType.nTargetBitrate = bitrate;
3027
3028    return mOMX->setParameter(
3029            mNode, OMX_IndexParamVideoBitrate,
3030            &bitrateType, sizeof(bitrateType));
3031}
3032
3033status_t ACodec::setupErrorCorrectionParameters() {
3034    OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
3035    InitOMXParams(&errorCorrectionType);
3036    errorCorrectionType.nPortIndex = kPortIndexOutput;
3037
3038    status_t err = mOMX->getParameter(
3039            mNode, OMX_IndexParamVideoErrorCorrection,
3040            &errorCorrectionType, sizeof(errorCorrectionType));
3041
3042    if (err != OK) {
3043        return OK;  // Optional feature. Ignore this failure
3044    }
3045
3046    errorCorrectionType.bEnableHEC = OMX_FALSE;
3047    errorCorrectionType.bEnableResync = OMX_TRUE;
3048    errorCorrectionType.nResynchMarkerSpacing = 256;
3049    errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
3050    errorCorrectionType.bEnableRVLC = OMX_FALSE;
3051
3052    return mOMX->setParameter(
3053            mNode, OMX_IndexParamVideoErrorCorrection,
3054            &errorCorrectionType, sizeof(errorCorrectionType));
3055}
3056
3057status_t ACodec::setVideoFormatOnPort(
3058        OMX_U32 portIndex,
3059        int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat,
3060        float frameRate) {
3061    OMX_PARAM_PORTDEFINITIONTYPE def;
3062    InitOMXParams(&def);
3063    def.nPortIndex = portIndex;
3064
3065    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
3066
3067    status_t err = mOMX->getParameter(
3068            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3069
3070    CHECK_EQ(err, (status_t)OK);
3071
3072    if (portIndex == kPortIndexInput) {
3073        // XXX Need a (much) better heuristic to compute input buffer sizes.
3074        const size_t X = 64 * 1024;
3075        if (def.nBufferSize < X) {
3076            def.nBufferSize = X;
3077        }
3078    }
3079
3080    CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
3081
3082    video_def->nFrameWidth = width;
3083    video_def->nFrameHeight = height;
3084
3085    if (portIndex == kPortIndexInput) {
3086        video_def->eCompressionFormat = compressionFormat;
3087        video_def->eColorFormat = OMX_COLOR_FormatUnused;
3088        if (frameRate >= 0) {
3089            video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
3090        }
3091    }
3092
3093    err = mOMX->setParameter(
3094            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
3095
3096    return err;
3097}
3098
3099status_t ACodec::initNativeWindow() {
3100    if (mNativeWindow != NULL) {
3101        return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
3102    }
3103
3104    mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE);
3105    return OK;
3106}
3107
3108size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const {
3109    size_t n = 0;
3110
3111    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
3112        const BufferInfo &info = mBuffers[portIndex].itemAt(i);
3113
3114        if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
3115            ++n;
3116        }
3117    }
3118
3119    return n;
3120}
3121
3122size_t ACodec::countBuffersOwnedByNativeWindow() const {
3123    size_t n = 0;
3124
3125    for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) {
3126        const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i);
3127
3128        if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
3129            ++n;
3130        }
3131    }
3132
3133    return n;
3134}
3135
3136void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() {
3137    if (mNativeWindow == NULL) {
3138        return;
3139    }
3140
3141    while (countBuffersOwnedByNativeWindow() > mNumUndequeuedBuffers
3142            && dequeueBufferFromNativeWindow() != NULL) {
3143        // these buffers will be submitted as regular buffers; account for this
3144        if (mStoreMetaDataInOutputBuffers && mMetaDataBuffersToSubmit > 0) {
3145            --mMetaDataBuffersToSubmit;
3146        }
3147    }
3148}
3149
3150bool ACodec::allYourBuffersAreBelongToUs(
3151        OMX_U32 portIndex) {
3152    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
3153        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
3154
3155        if (info->mStatus != BufferInfo::OWNED_BY_US
3156                && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
3157            ALOGV("[%s] Buffer %u on port %u still has status %d",
3158                    mComponentName.c_str(),
3159                    info->mBufferID, portIndex, info->mStatus);
3160            return false;
3161        }
3162    }
3163
3164    return true;
3165}
3166
3167bool ACodec::allYourBuffersAreBelongToUs() {
3168    return allYourBuffersAreBelongToUs(kPortIndexInput)
3169        && allYourBuffersAreBelongToUs(kPortIndexOutput);
3170}
3171
3172void ACodec::deferMessage(const sp<AMessage> &msg) {
3173    bool wasEmptyBefore = mDeferredQueue.empty();
3174    mDeferredQueue.push_back(msg);
3175}
3176
3177void ACodec::processDeferredMessages() {
3178    List<sp<AMessage> > queue = mDeferredQueue;
3179    mDeferredQueue.clear();
3180
3181    List<sp<AMessage> >::iterator it = queue.begin();
3182    while (it != queue.end()) {
3183        onMessageReceived(*it++);
3184    }
3185}
3186
3187// static
3188bool ACodec::describeDefaultColorFormat(DescribeColorFormatParams &params) {
3189    MediaImage &image = params.sMediaImage;
3190    memset(&image, 0, sizeof(image));
3191
3192    image.mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
3193    image.mNumPlanes = 0;
3194
3195    const OMX_COLOR_FORMATTYPE fmt = params.eColorFormat;
3196    image.mWidth = params.nFrameWidth;
3197    image.mHeight = params.nFrameHeight;
3198
3199    // only supporting YUV420
3200    if (fmt != OMX_COLOR_FormatYUV420Planar &&
3201        fmt != OMX_COLOR_FormatYUV420PackedPlanar &&
3202        fmt != OMX_COLOR_FormatYUV420SemiPlanar &&
3203        fmt != OMX_COLOR_FormatYUV420PackedSemiPlanar) {
3204        ALOGW("do not know color format 0x%x = %d", fmt, fmt);
3205        return false;
3206    }
3207
3208    // TEMPORARY FIX for some vendors that advertise sliceHeight as 0
3209    if (params.nStride != 0 && params.nSliceHeight == 0) {
3210        ALOGW("using sliceHeight=%u instead of what codec advertised (=0)",
3211                params.nFrameHeight);
3212        params.nSliceHeight = params.nFrameHeight;
3213    }
3214
3215    // we need stride and slice-height to be non-zero
3216    if (params.nStride == 0 || params.nSliceHeight == 0) {
3217        ALOGW("cannot describe color format 0x%x = %d with stride=%u and sliceHeight=%u",
3218                fmt, fmt, params.nStride, params.nSliceHeight);
3219        return false;
3220    }
3221
3222    // set-up YUV format
3223    image.mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
3224    image.mNumPlanes = 3;
3225    image.mBitDepth = 8;
3226    image.mPlane[image.Y].mOffset = 0;
3227    image.mPlane[image.Y].mColInc = 1;
3228    image.mPlane[image.Y].mRowInc = params.nStride;
3229    image.mPlane[image.Y].mHorizSubsampling = 1;
3230    image.mPlane[image.Y].mVertSubsampling = 1;
3231
3232    switch (fmt) {
3233        case OMX_COLOR_FormatYUV420Planar: // used for YV12
3234        case OMX_COLOR_FormatYUV420PackedPlanar:
3235            image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
3236            image.mPlane[image.U].mColInc = 1;
3237            image.mPlane[image.U].mRowInc = params.nStride / 2;
3238            image.mPlane[image.U].mHorizSubsampling = 2;
3239            image.mPlane[image.U].mVertSubsampling = 2;
3240
3241            image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset
3242                    + (params.nStride * params.nSliceHeight / 4);
3243            image.mPlane[image.V].mColInc = 1;
3244            image.mPlane[image.V].mRowInc = params.nStride / 2;
3245            image.mPlane[image.V].mHorizSubsampling = 2;
3246            image.mPlane[image.V].mVertSubsampling = 2;
3247            break;
3248
3249        case OMX_COLOR_FormatYUV420SemiPlanar:
3250            // FIXME: NV21 for sw-encoder, NV12 for decoder and hw-encoder
3251        case OMX_COLOR_FormatYUV420PackedSemiPlanar:
3252            // NV12
3253            image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
3254            image.mPlane[image.U].mColInc = 2;
3255            image.mPlane[image.U].mRowInc = params.nStride;
3256            image.mPlane[image.U].mHorizSubsampling = 2;
3257            image.mPlane[image.U].mVertSubsampling = 2;
3258
3259            image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset + 1;
3260            image.mPlane[image.V].mColInc = 2;
3261            image.mPlane[image.V].mRowInc = params.nStride;
3262            image.mPlane[image.V].mHorizSubsampling = 2;
3263            image.mPlane[image.V].mVertSubsampling = 2;
3264            break;
3265
3266        default:
3267            TRESPASS();
3268    }
3269    return true;
3270}
3271
3272// static
3273bool ACodec::describeColorFormat(
3274        const sp<IOMX> &omx, IOMX::node_id node,
3275        DescribeColorFormatParams &describeParams)
3276{
3277    OMX_INDEXTYPE describeColorFormatIndex;
3278    if (omx->getExtensionIndex(
3279            node, "OMX.google.android.index.describeColorFormat",
3280            &describeColorFormatIndex) != OK ||
3281        omx->getParameter(
3282            node, describeColorFormatIndex,
3283            &describeParams, sizeof(describeParams)) != OK) {
3284        return describeDefaultColorFormat(describeParams);
3285    }
3286    return describeParams.sMediaImage.mType !=
3287            MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
3288}
3289
3290// static
3291bool ACodec::isFlexibleColorFormat(
3292         const sp<IOMX> &omx, IOMX::node_id node,
3293         uint32_t colorFormat, bool usingNativeBuffers, OMX_U32 *flexibleEquivalent) {
3294    DescribeColorFormatParams describeParams;
3295    InitOMXParams(&describeParams);
3296    describeParams.eColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat;
3297    // reasonable dummy values
3298    describeParams.nFrameWidth = 128;
3299    describeParams.nFrameHeight = 128;
3300    describeParams.nStride = 128;
3301    describeParams.nSliceHeight = 128;
3302    describeParams.bUsingNativeBuffers = (OMX_BOOL)usingNativeBuffers;
3303
3304    CHECK(flexibleEquivalent != NULL);
3305
3306    if (!describeColorFormat(omx, node, describeParams)) {
3307        return false;
3308    }
3309
3310    const MediaImage &img = describeParams.sMediaImage;
3311    if (img.mType == MediaImage::MEDIA_IMAGE_TYPE_YUV) {
3312        if (img.mNumPlanes != 3 ||
3313            img.mPlane[img.Y].mHorizSubsampling != 1 ||
3314            img.mPlane[img.Y].mVertSubsampling != 1) {
3315            return false;
3316        }
3317
3318        // YUV 420
3319        if (img.mPlane[img.U].mHorizSubsampling == 2
3320                && img.mPlane[img.U].mVertSubsampling == 2
3321                && img.mPlane[img.V].mHorizSubsampling == 2
3322                && img.mPlane[img.V].mVertSubsampling == 2) {
3323            // possible flexible YUV420 format
3324            if (img.mBitDepth <= 8) {
3325               *flexibleEquivalent = OMX_COLOR_FormatYUV420Flexible;
3326               return true;
3327            }
3328        }
3329    }
3330    return false;
3331}
3332
3333status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
3334    // TODO: catch errors an return them instead of using CHECK
3335    OMX_PARAM_PORTDEFINITIONTYPE def;
3336    InitOMXParams(&def);
3337    def.nPortIndex = portIndex;
3338
3339    CHECK_EQ(mOMX->getParameter(
3340                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)),
3341             (status_t)OK);
3342
3343    CHECK_EQ((int)def.eDir,
3344            (int)(portIndex == kPortIndexOutput ? OMX_DirOutput : OMX_DirInput));
3345
3346    switch (def.eDomain) {
3347        case OMX_PortDomainVideo:
3348        {
3349            OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
3350            switch ((int)videoDef->eCompressionFormat) {
3351                case OMX_VIDEO_CodingUnused:
3352                {
3353                    CHECK(mIsEncoder ^ (portIndex == kPortIndexOutput));
3354                    notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
3355
3356                    notify->setInt32("stride", videoDef->nStride);
3357                    notify->setInt32("slice-height", videoDef->nSliceHeight);
3358                    notify->setInt32("color-format", videoDef->eColorFormat);
3359
3360                    if (mNativeWindow == NULL) {
3361                        DescribeColorFormatParams describeParams;
3362                        InitOMXParams(&describeParams);
3363                        describeParams.eColorFormat = videoDef->eColorFormat;
3364                        describeParams.nFrameWidth = videoDef->nFrameWidth;
3365                        describeParams.nFrameHeight = videoDef->nFrameHeight;
3366                        describeParams.nStride = videoDef->nStride;
3367                        describeParams.nSliceHeight = videoDef->nSliceHeight;
3368                        describeParams.bUsingNativeBuffers = OMX_FALSE;
3369
3370                        if (describeColorFormat(mOMX, mNode, describeParams)) {
3371                            notify->setBuffer(
3372                                    "image-data",
3373                                    ABuffer::CreateAsCopy(
3374                                            &describeParams.sMediaImage,
3375                                            sizeof(describeParams.sMediaImage)));
3376                        }
3377                    }
3378
3379                    if (portIndex != kPortIndexOutput) {
3380                        // TODO: also get input crop
3381                        break;
3382                    }
3383
3384                    OMX_CONFIG_RECTTYPE rect;
3385                    InitOMXParams(&rect);
3386                    rect.nPortIndex = portIndex;
3387
3388                    if (mOMX->getConfig(
3389                                mNode,
3390                                (portIndex == kPortIndexOutput ?
3391                                        OMX_IndexConfigCommonOutputCrop :
3392                                        OMX_IndexConfigCommonInputCrop),
3393                                &rect, sizeof(rect)) != OK) {
3394                        rect.nLeft = 0;
3395                        rect.nTop = 0;
3396                        rect.nWidth = videoDef->nFrameWidth;
3397                        rect.nHeight = videoDef->nFrameHeight;
3398                    }
3399
3400                    CHECK_GE(rect.nLeft, 0);
3401                    CHECK_GE(rect.nTop, 0);
3402                    CHECK_GE(rect.nWidth, 0u);
3403                    CHECK_GE(rect.nHeight, 0u);
3404                    CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth);
3405                    CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight);
3406
3407                    notify->setRect(
3408                            "crop",
3409                            rect.nLeft,
3410                            rect.nTop,
3411                            rect.nLeft + rect.nWidth - 1,
3412                            rect.nTop + rect.nHeight - 1);
3413
3414                    break;
3415                }
3416
3417                case OMX_VIDEO_CodingVP8:
3418                case OMX_VIDEO_CodingVP9:
3419                {
3420                    OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
3421                    InitOMXParams(&vp8type);
3422                    vp8type.nPortIndex = kPortIndexOutput;
3423                    status_t err = mOMX->getParameter(
3424                            mNode,
3425                            (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
3426                            &vp8type,
3427                            sizeof(vp8type));
3428
3429                    if (err == OK) {
3430                        AString tsSchema = "none";
3431                        if (vp8type.eTemporalPattern
3432                                == OMX_VIDEO_VPXTemporalLayerPatternWebRTC) {
3433                            switch (vp8type.nTemporalLayerCount) {
3434                                case 1:
3435                                {
3436                                    tsSchema = "webrtc.vp8.1-layer";
3437                                    break;
3438                                }
3439                                case 2:
3440                                {
3441                                    tsSchema = "webrtc.vp8.2-layer";
3442                                    break;
3443                                }
3444                                case 3:
3445                                {
3446                                    tsSchema = "webrtc.vp8.3-layer";
3447                                    break;
3448                                }
3449                                default:
3450                                {
3451                                    break;
3452                                }
3453                            }
3454                        }
3455                        notify->setString("ts-schema", tsSchema);
3456                    }
3457                    // Fall through to set up mime.
3458                }
3459
3460                default:
3461                {
3462                    CHECK(mIsEncoder ^ (portIndex == kPortIndexInput));
3463                    AString mime;
3464                    if (GetMimeTypeForVideoCoding(
3465                        videoDef->eCompressionFormat, &mime) != OK) {
3466                        notify->setString("mime", "application/octet-stream");
3467                    } else {
3468                        notify->setString("mime", mime.c_str());
3469                    }
3470                    break;
3471                }
3472            }
3473
3474            notify->setInt32("width", videoDef->nFrameWidth);
3475            notify->setInt32("height", videoDef->nFrameHeight);
3476            break;
3477        }
3478
3479        case OMX_PortDomainAudio:
3480        {
3481            OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
3482
3483            switch ((int)audioDef->eEncoding) {
3484                case OMX_AUDIO_CodingPCM:
3485                {
3486                    OMX_AUDIO_PARAM_PCMMODETYPE params;
3487                    InitOMXParams(&params);
3488                    params.nPortIndex = portIndex;
3489
3490                    CHECK_EQ(mOMX->getParameter(
3491                                mNode, OMX_IndexParamAudioPcm,
3492                                &params, sizeof(params)),
3493                             (status_t)OK);
3494
3495                    CHECK_GT(params.nChannels, 0);
3496                    CHECK(params.nChannels == 1 || params.bInterleaved);
3497                    CHECK_EQ(params.nBitPerSample, 16u);
3498
3499                    CHECK_EQ((int)params.eNumData,
3500                             (int)OMX_NumericalDataSigned);
3501
3502                    CHECK_EQ((int)params.ePCMMode,
3503                             (int)OMX_AUDIO_PCMModeLinear);
3504
3505                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
3506                    notify->setInt32("channel-count", params.nChannels);
3507                    notify->setInt32("sample-rate", params.nSamplingRate);
3508
3509                    if (mChannelMaskPresent) {
3510                        notify->setInt32("channel-mask", mChannelMask);
3511                    }
3512                    break;
3513                }
3514
3515                case OMX_AUDIO_CodingAAC:
3516                {
3517                    OMX_AUDIO_PARAM_AACPROFILETYPE params;
3518                    InitOMXParams(&params);
3519                    params.nPortIndex = portIndex;
3520
3521                    CHECK_EQ(mOMX->getParameter(
3522                                mNode, OMX_IndexParamAudioAac,
3523                                &params, sizeof(params)),
3524                             (status_t)OK);
3525
3526                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
3527                    notify->setInt32("channel-count", params.nChannels);
3528                    notify->setInt32("sample-rate", params.nSampleRate);
3529                    break;
3530                }
3531
3532                case OMX_AUDIO_CodingAMR:
3533                {
3534                    OMX_AUDIO_PARAM_AMRTYPE params;
3535                    InitOMXParams(&params);
3536                    params.nPortIndex = portIndex;
3537
3538                    CHECK_EQ(mOMX->getParameter(
3539                                mNode, OMX_IndexParamAudioAmr,
3540                                &params, sizeof(params)),
3541                             (status_t)OK);
3542
3543                    notify->setInt32("channel-count", 1);
3544                    if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) {
3545                        notify->setString(
3546                                "mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
3547
3548                        notify->setInt32("sample-rate", 16000);
3549                    } else {
3550                        notify->setString(
3551                                "mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
3552
3553                        notify->setInt32("sample-rate", 8000);
3554                    }
3555                    break;
3556                }
3557
3558                case OMX_AUDIO_CodingFLAC:
3559                {
3560                    OMX_AUDIO_PARAM_FLACTYPE params;
3561                    InitOMXParams(&params);
3562                    params.nPortIndex = portIndex;
3563
3564                    CHECK_EQ(mOMX->getParameter(
3565                                mNode, OMX_IndexParamAudioFlac,
3566                                &params, sizeof(params)),
3567                             (status_t)OK);
3568
3569                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC);
3570                    notify->setInt32("channel-count", params.nChannels);
3571                    notify->setInt32("sample-rate", params.nSampleRate);
3572                    break;
3573                }
3574
3575                case OMX_AUDIO_CodingMP3:
3576                {
3577                    OMX_AUDIO_PARAM_MP3TYPE params;
3578                    InitOMXParams(&params);
3579                    params.nPortIndex = portIndex;
3580
3581                    CHECK_EQ(mOMX->getParameter(
3582                                mNode, OMX_IndexParamAudioMp3,
3583                                &params, sizeof(params)),
3584                             (status_t)OK);
3585
3586                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MPEG);
3587                    notify->setInt32("channel-count", params.nChannels);
3588                    notify->setInt32("sample-rate", params.nSampleRate);
3589                    break;
3590                }
3591
3592                case OMX_AUDIO_CodingVORBIS:
3593                {
3594                    OMX_AUDIO_PARAM_VORBISTYPE params;
3595                    InitOMXParams(&params);
3596                    params.nPortIndex = portIndex;
3597
3598                    CHECK_EQ(mOMX->getParameter(
3599                                mNode, OMX_IndexParamAudioVorbis,
3600                                &params, sizeof(params)),
3601                             (status_t)OK);
3602
3603                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_VORBIS);
3604                    notify->setInt32("channel-count", params.nChannels);
3605                    notify->setInt32("sample-rate", params.nSampleRate);
3606                    break;
3607                }
3608
3609                case OMX_AUDIO_CodingAndroidAC3:
3610                {
3611                    OMX_AUDIO_PARAM_ANDROID_AC3TYPE params;
3612                    InitOMXParams(&params);
3613                    params.nPortIndex = portIndex;
3614
3615                    CHECK_EQ((status_t)OK, mOMX->getParameter(
3616                            mNode,
3617                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
3618                            &params,
3619                            sizeof(params)));
3620
3621                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3);
3622                    notify->setInt32("channel-count", params.nChannels);
3623                    notify->setInt32("sample-rate", params.nSampleRate);
3624                    break;
3625                }
3626
3627                case OMX_AUDIO_CodingAndroidEAC3:
3628                {
3629                    OMX_AUDIO_PARAM_ANDROID_EAC3TYPE params;
3630                    InitOMXParams(&params);
3631                    params.nPortIndex = portIndex;
3632
3633                    CHECK_EQ((status_t)OK, mOMX->getParameter(
3634                            mNode,
3635                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
3636                            &params,
3637                            sizeof(params)));
3638
3639                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_EAC3);
3640                    notify->setInt32("channel-count", params.nChannels);
3641                    notify->setInt32("sample-rate", params.nSampleRate);
3642                    break;
3643                }
3644
3645                case OMX_AUDIO_CodingAndroidOPUS:
3646                {
3647                    OMX_AUDIO_PARAM_ANDROID_OPUSTYPE params;
3648                    InitOMXParams(&params);
3649                    params.nPortIndex = portIndex;
3650
3651                    CHECK_EQ((status_t)OK, mOMX->getParameter(
3652                            mNode,
3653                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
3654                            &params,
3655                            sizeof(params)));
3656
3657                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_OPUS);
3658                    notify->setInt32("channel-count", params.nChannels);
3659                    notify->setInt32("sample-rate", params.nSampleRate);
3660                    break;
3661                }
3662
3663                case OMX_AUDIO_CodingG711:
3664                {
3665                    OMX_AUDIO_PARAM_PCMMODETYPE params;
3666                    InitOMXParams(&params);
3667                    params.nPortIndex = portIndex;
3668
3669                    CHECK_EQ((status_t)OK, mOMX->getParameter(
3670                            mNode,
3671                            (OMX_INDEXTYPE)OMX_IndexParamAudioPcm,
3672                            &params,
3673                            sizeof(params)));
3674
3675                    const char *mime = NULL;
3676                    if (params.ePCMMode == OMX_AUDIO_PCMModeMULaw) {
3677                        mime = MEDIA_MIMETYPE_AUDIO_G711_MLAW;
3678                    } else if (params.ePCMMode == OMX_AUDIO_PCMModeALaw) {
3679                        mime = MEDIA_MIMETYPE_AUDIO_G711_ALAW;
3680                    } else { // params.ePCMMode == OMX_AUDIO_PCMModeLinear
3681                        mime = MEDIA_MIMETYPE_AUDIO_RAW;
3682                    }
3683                    notify->setString("mime", mime);
3684                    notify->setInt32("channel-count", params.nChannels);
3685                    notify->setInt32("sample-rate", params.nSamplingRate);
3686                    break;
3687                }
3688
3689                default:
3690                    ALOGE("UNKNOWN AUDIO CODING: %d\n", audioDef->eEncoding);
3691                    TRESPASS();
3692            }
3693            break;
3694        }
3695
3696        default:
3697            TRESPASS();
3698    }
3699
3700    return OK;
3701}
3702
3703void ACodec::sendFormatChange(const sp<AMessage> &reply) {
3704    sp<AMessage> notify = mBaseOutputFormat->dup();
3705    notify->setInt32("what", kWhatOutputFormatChanged);
3706
3707    CHECK_EQ(getPortFormat(kPortIndexOutput, notify), (status_t)OK);
3708
3709    AString mime;
3710    CHECK(notify->findString("mime", &mime));
3711
3712    int32_t left, top, right, bottom;
3713    if (mime == MEDIA_MIMETYPE_VIDEO_RAW &&
3714        mNativeWindow != NULL &&
3715        notify->findRect("crop", &left, &top, &right, &bottom)) {
3716        // notify renderer of the crop change
3717        // NOTE: native window uses extended right-bottom coordinate
3718        reply->setRect("crop", left, top, right + 1, bottom + 1);
3719    } else if (mime == MEDIA_MIMETYPE_AUDIO_RAW &&
3720               (mEncoderDelay || mEncoderPadding)) {
3721        int32_t channelCount;
3722        CHECK(notify->findInt32("channel-count", &channelCount));
3723        size_t frameSize = channelCount * sizeof(int16_t);
3724        if (mSkipCutBuffer != NULL) {
3725            size_t prevbufsize = mSkipCutBuffer->size();
3726            if (prevbufsize != 0) {
3727                ALOGW("Replacing SkipCutBuffer holding %d "
3728                      "bytes",
3729                      prevbufsize);
3730            }
3731        }
3732        mSkipCutBuffer = new SkipCutBuffer(
3733                mEncoderDelay * frameSize,
3734                mEncoderPadding * frameSize);
3735    }
3736
3737    notify->post();
3738
3739    mSentFormat = true;
3740}
3741
3742void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) {
3743    sp<AMessage> notify = mNotify->dup();
3744    notify->setInt32("what", CodecBase::kWhatError);
3745    ALOGE("signalError(omxError %#x, internalError %d)", error, internalError);
3746
3747    if (internalError == UNKNOWN_ERROR) { // find better error code
3748        const status_t omxStatus = statusFromOMXError(error);
3749        if (omxStatus != 0) {
3750            internalError = omxStatus;
3751        } else {
3752            ALOGW("Invalid OMX error %#x", error);
3753        }
3754    }
3755    notify->setInt32("err", internalError);
3756    notify->setInt32("actionCode", ACTION_CODE_FATAL); // could translate from OMX error.
3757    notify->post();
3758}
3759
3760status_t ACodec::pushBlankBuffersToNativeWindow() {
3761    status_t err = NO_ERROR;
3762    ANativeWindowBuffer* anb = NULL;
3763    int numBufs = 0;
3764    int minUndequeuedBufs = 0;
3765
3766    // We need to reconnect to the ANativeWindow as a CPU client to ensure that
3767    // no frames get dropped by SurfaceFlinger assuming that these are video
3768    // frames.
3769    err = native_window_api_disconnect(mNativeWindow.get(),
3770            NATIVE_WINDOW_API_MEDIA);
3771    if (err != NO_ERROR) {
3772        ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
3773                strerror(-err), -err);
3774        return err;
3775    }
3776
3777    err = native_window_api_connect(mNativeWindow.get(),
3778            NATIVE_WINDOW_API_CPU);
3779    if (err != NO_ERROR) {
3780        ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
3781                strerror(-err), -err);
3782        return err;
3783    }
3784
3785    err = native_window_set_buffers_geometry(mNativeWindow.get(), 1, 1,
3786            HAL_PIXEL_FORMAT_RGBX_8888);
3787    if (err != NO_ERROR) {
3788        ALOGE("error pushing blank frames: set_buffers_geometry failed: %s (%d)",
3789                strerror(-err), -err);
3790        goto error;
3791    }
3792
3793    err = native_window_set_scaling_mode(mNativeWindow.get(),
3794                NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
3795    if (err != NO_ERROR) {
3796        ALOGE("error pushing blank_frames: set_scaling_mode failed: %s (%d)",
3797              strerror(-err), -err);
3798        goto error;
3799    }
3800
3801    err = native_window_set_usage(mNativeWindow.get(),
3802            GRALLOC_USAGE_SW_WRITE_OFTEN);
3803    if (err != NO_ERROR) {
3804        ALOGE("error pushing blank frames: set_usage failed: %s (%d)",
3805                strerror(-err), -err);
3806        goto error;
3807    }
3808
3809    err = mNativeWindow->query(mNativeWindow.get(),
3810            NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs);
3811    if (err != NO_ERROR) {
3812        ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query "
3813                "failed: %s (%d)", strerror(-err), -err);
3814        goto error;
3815    }
3816
3817    numBufs = minUndequeuedBufs + 1;
3818    err = native_window_set_buffer_count(mNativeWindow.get(), numBufs);
3819    if (err != NO_ERROR) {
3820        ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)",
3821                strerror(-err), -err);
3822        goto error;
3823    }
3824
3825    // We  push numBufs + 1 buffers to ensure that we've drawn into the same
3826    // buffer twice.  This should guarantee that the buffer has been displayed
3827    // on the screen and then been replaced, so an previous video frames are
3828    // guaranteed NOT to be currently displayed.
3829    for (int i = 0; i < numBufs + 1; i++) {
3830        int fenceFd = -1;
3831        err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &anb);
3832        if (err != NO_ERROR) {
3833            ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)",
3834                    strerror(-err), -err);
3835            goto error;
3836        }
3837
3838        sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
3839
3840        // Fill the buffer with the a 1x1 checkerboard pattern ;)
3841        uint32_t* img = NULL;
3842        err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
3843        if (err != NO_ERROR) {
3844            ALOGE("error pushing blank frames: lock failed: %s (%d)",
3845                    strerror(-err), -err);
3846            goto error;
3847        }
3848
3849        *img = 0;
3850
3851        err = buf->unlock();
3852        if (err != NO_ERROR) {
3853            ALOGE("error pushing blank frames: unlock failed: %s (%d)",
3854                    strerror(-err), -err);
3855            goto error;
3856        }
3857
3858        err = mNativeWindow->queueBuffer(mNativeWindow.get(),
3859                buf->getNativeBuffer(), -1);
3860        if (err != NO_ERROR) {
3861            ALOGE("error pushing blank frames: queueBuffer failed: %s (%d)",
3862                    strerror(-err), -err);
3863            goto error;
3864        }
3865
3866        anb = NULL;
3867    }
3868
3869error:
3870
3871    if (err != NO_ERROR) {
3872        // Clean up after an error.
3873        if (anb != NULL) {
3874            mNativeWindow->cancelBuffer(mNativeWindow.get(), anb, -1);
3875        }
3876
3877        native_window_api_disconnect(mNativeWindow.get(),
3878                NATIVE_WINDOW_API_CPU);
3879        native_window_api_connect(mNativeWindow.get(),
3880                NATIVE_WINDOW_API_MEDIA);
3881
3882        return err;
3883    } else {
3884        // Clean up after success.
3885        err = native_window_api_disconnect(mNativeWindow.get(),
3886                NATIVE_WINDOW_API_CPU);
3887        if (err != NO_ERROR) {
3888            ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
3889                    strerror(-err), -err);
3890            return err;
3891        }
3892
3893        err = native_window_api_connect(mNativeWindow.get(),
3894                NATIVE_WINDOW_API_MEDIA);
3895        if (err != NO_ERROR) {
3896            ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
3897                    strerror(-err), -err);
3898            return err;
3899        }
3900
3901        return NO_ERROR;
3902    }
3903}
3904
3905////////////////////////////////////////////////////////////////////////////////
3906
3907ACodec::PortDescription::PortDescription() {
3908}
3909
3910status_t ACodec::requestIDRFrame() {
3911    if (!mIsEncoder) {
3912        return ERROR_UNSUPPORTED;
3913    }
3914
3915    OMX_CONFIG_INTRAREFRESHVOPTYPE params;
3916    InitOMXParams(&params);
3917
3918    params.nPortIndex = kPortIndexOutput;
3919    params.IntraRefreshVOP = OMX_TRUE;
3920
3921    return mOMX->setConfig(
3922            mNode,
3923            OMX_IndexConfigVideoIntraVOPRefresh,
3924            &params,
3925            sizeof(params));
3926}
3927
3928void ACodec::PortDescription::addBuffer(
3929        IOMX::buffer_id id, const sp<ABuffer> &buffer) {
3930    mBufferIDs.push_back(id);
3931    mBuffers.push_back(buffer);
3932}
3933
3934size_t ACodec::PortDescription::countBuffers() {
3935    return mBufferIDs.size();
3936}
3937
3938IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const {
3939    return mBufferIDs.itemAt(index);
3940}
3941
3942sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const {
3943    return mBuffers.itemAt(index);
3944}
3945
3946////////////////////////////////////////////////////////////////////////////////
3947
3948ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
3949    : AState(parentState),
3950      mCodec(codec) {
3951}
3952
3953ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(
3954        OMX_U32 /* portIndex */) {
3955    return KEEP_BUFFERS;
3956}
3957
3958bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
3959    switch (msg->what()) {
3960        case kWhatInputBufferFilled:
3961        {
3962            onInputBufferFilled(msg);
3963            break;
3964        }
3965
3966        case kWhatOutputBufferDrained:
3967        {
3968            onOutputBufferDrained(msg);
3969            break;
3970        }
3971
3972        case ACodec::kWhatOMXMessage:
3973        {
3974            return onOMXMessage(msg);
3975        }
3976
3977        case ACodec::kWhatCreateInputSurface:
3978        case ACodec::kWhatSignalEndOfInputStream:
3979        {
3980            // This may result in an app illegal state exception.
3981            ALOGE("Message 0x%x was not handled", msg->what());
3982            mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION);
3983            return true;
3984        }
3985
3986        case ACodec::kWhatOMXDied:
3987        {
3988            // This will result in kFlagSawMediaServerDie handling in MediaCodec.
3989            ALOGE("OMX/mediaserver died, signalling error!");
3990            mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT);
3991            break;
3992        }
3993
3994        case ACodec::kWhatReleaseCodecInstance:
3995        {
3996            ALOGI("[%s] forcing the release of codec",
3997                    mCodec->mComponentName.c_str());
3998            status_t err = mCodec->mOMX->freeNode(mCodec->mNode);
3999            ALOGE_IF("[%s] failed to release codec instance: err=%d",
4000                       mCodec->mComponentName.c_str(), err);
4001            sp<AMessage> notify = mCodec->mNotify->dup();
4002            notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
4003            notify->post();
4004            break;
4005        }
4006
4007        default:
4008            return false;
4009    }
4010
4011    return true;
4012}
4013
4014bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
4015    int32_t type;
4016    CHECK(msg->findInt32("type", &type));
4017
4018    // there is a possibility that this is an outstanding message for a
4019    // codec that we have already destroyed
4020    if (mCodec->mNode == NULL) {
4021        ALOGI("ignoring message as already freed component: %s",
4022                msg->debugString().c_str());
4023        return true;
4024    }
4025
4026    IOMX::node_id nodeID;
4027    CHECK(msg->findInt32("node", (int32_t*)&nodeID));
4028    CHECK_EQ(nodeID, mCodec->mNode);
4029
4030    switch (type) {
4031        case omx_message::EVENT:
4032        {
4033            int32_t event, data1, data2;
4034            CHECK(msg->findInt32("event", &event));
4035            CHECK(msg->findInt32("data1", &data1));
4036            CHECK(msg->findInt32("data2", &data2));
4037
4038            if (event == OMX_EventCmdComplete
4039                    && data1 == OMX_CommandFlush
4040                    && data2 == (int32_t)OMX_ALL) {
4041                // Use of this notification is not consistent across
4042                // implementations. We'll drop this notification and rely
4043                // on flush-complete notifications on the individual port
4044                // indices instead.
4045
4046                return true;
4047            }
4048
4049            return onOMXEvent(
4050                    static_cast<OMX_EVENTTYPE>(event),
4051                    static_cast<OMX_U32>(data1),
4052                    static_cast<OMX_U32>(data2));
4053        }
4054
4055        case omx_message::EMPTY_BUFFER_DONE:
4056        {
4057            IOMX::buffer_id bufferID;
4058            CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
4059
4060            return onOMXEmptyBufferDone(bufferID);
4061        }
4062
4063        case omx_message::FILL_BUFFER_DONE:
4064        {
4065            IOMX::buffer_id bufferID;
4066            CHECK(msg->findInt32("buffer", (int32_t*)&bufferID));
4067
4068            int32_t rangeOffset, rangeLength, flags;
4069            int64_t timeUs;
4070
4071            CHECK(msg->findInt32("range_offset", &rangeOffset));
4072            CHECK(msg->findInt32("range_length", &rangeLength));
4073            CHECK(msg->findInt32("flags", &flags));
4074            CHECK(msg->findInt64("timestamp", &timeUs));
4075
4076            return onOMXFillBufferDone(
4077                    bufferID,
4078                    (size_t)rangeOffset, (size_t)rangeLength,
4079                    (OMX_U32)flags,
4080                    timeUs);
4081        }
4082
4083        default:
4084            TRESPASS();
4085            break;
4086    }
4087}
4088
4089bool ACodec::BaseState::onOMXEvent(
4090        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
4091    if (event != OMX_EventError) {
4092        ALOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)",
4093             mCodec->mComponentName.c_str(), event, data1, data2);
4094
4095        return false;
4096    }
4097
4098    ALOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1);
4099
4100    // verify OMX component sends back an error we expect.
4101    OMX_ERRORTYPE omxError = (OMX_ERRORTYPE)data1;
4102    if (!isOMXError(omxError)) {
4103        ALOGW("Invalid OMX error %#x", omxError);
4104        omxError = OMX_ErrorUndefined;
4105    }
4106    mCodec->signalError(omxError);
4107
4108    return true;
4109}
4110
4111bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) {
4112    ALOGV("[%s] onOMXEmptyBufferDone %p",
4113         mCodec->mComponentName.c_str(), bufferID);
4114
4115    BufferInfo *info =
4116        mCodec->findBufferByID(kPortIndexInput, bufferID);
4117
4118    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
4119    info->mStatus = BufferInfo::OWNED_BY_US;
4120
4121    // We're in "store-metadata-in-buffers" mode, the underlying
4122    // OMX component had access to data that's implicitly refcounted
4123    // by this "MediaBuffer" object. Now that the OMX component has
4124    // told us that it's done with the input buffer, we can decrement
4125    // the mediaBuffer's reference count.
4126    info->mData->setMediaBufferBase(NULL);
4127
4128    PortMode mode = getPortMode(kPortIndexInput);
4129
4130    switch (mode) {
4131        case KEEP_BUFFERS:
4132            break;
4133
4134        case RESUBMIT_BUFFERS:
4135            postFillThisBuffer(info);
4136            break;
4137
4138        default:
4139        {
4140            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4141            TRESPASS();  // Not currently used
4142            break;
4143        }
4144    }
4145
4146    return true;
4147}
4148
4149void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
4150    if (mCodec->mPortEOS[kPortIndexInput]) {
4151        return;
4152    }
4153
4154    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
4155
4156    sp<AMessage> notify = mCodec->mNotify->dup();
4157    notify->setInt32("what", CodecBase::kWhatFillThisBuffer);
4158    notify->setInt32("buffer-id", info->mBufferID);
4159
4160    info->mData->meta()->clear();
4161    notify->setBuffer("buffer", info->mData);
4162
4163    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id());
4164    reply->setInt32("buffer-id", info->mBufferID);
4165
4166    notify->setMessage("reply", reply);
4167
4168    notify->post();
4169
4170    info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
4171}
4172
4173void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
4174    IOMX::buffer_id bufferID;
4175    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
4176    sp<ABuffer> buffer;
4177    int32_t err = OK;
4178    bool eos = false;
4179    PortMode mode = getPortMode(kPortIndexInput);
4180
4181    if (!msg->findBuffer("buffer", &buffer)) {
4182        /* these are unfilled buffers returned by client */
4183        CHECK(msg->findInt32("err", &err));
4184
4185        if (err == OK) {
4186            /* buffers with no errors are returned on MediaCodec.flush */
4187            mode = KEEP_BUFFERS;
4188        } else {
4189            ALOGV("[%s] saw error %d instead of an input buffer",
4190                 mCodec->mComponentName.c_str(), err);
4191            eos = true;
4192        }
4193
4194        buffer.clear();
4195    }
4196
4197    int32_t tmp;
4198    if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
4199        eos = true;
4200        err = ERROR_END_OF_STREAM;
4201    }
4202
4203    BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
4204    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM);
4205
4206    info->mStatus = BufferInfo::OWNED_BY_US;
4207
4208    switch (mode) {
4209        case KEEP_BUFFERS:
4210        {
4211            if (eos) {
4212                if (!mCodec->mPortEOS[kPortIndexInput]) {
4213                    mCodec->mPortEOS[kPortIndexInput] = true;
4214                    mCodec->mInputEOSResult = err;
4215                }
4216            }
4217            break;
4218        }
4219
4220        case RESUBMIT_BUFFERS:
4221        {
4222            if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) {
4223                int64_t timeUs;
4224                CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
4225
4226                OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
4227
4228                int32_t isCSD;
4229                if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
4230                    flags |= OMX_BUFFERFLAG_CODECCONFIG;
4231                }
4232
4233                if (eos) {
4234                    flags |= OMX_BUFFERFLAG_EOS;
4235                }
4236
4237                if (buffer != info->mData) {
4238                    ALOGV("[%s] Needs to copy input data for buffer %p. (%p != %p)",
4239                         mCodec->mComponentName.c_str(),
4240                         bufferID,
4241                         buffer.get(), info->mData.get());
4242
4243                    CHECK_LE(buffer->size(), info->mData->capacity());
4244                    memcpy(info->mData->data(), buffer->data(), buffer->size());
4245                }
4246
4247                if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
4248                    ALOGV("[%s] calling emptyBuffer %p w/ codec specific data",
4249                         mCodec->mComponentName.c_str(), bufferID);
4250                } else if (flags & OMX_BUFFERFLAG_EOS) {
4251                    ALOGV("[%s] calling emptyBuffer %p w/ EOS",
4252                         mCodec->mComponentName.c_str(), bufferID);
4253                } else {
4254#if TRACK_BUFFER_TIMING
4255                    ALOGI("[%s] calling emptyBuffer %p w/ time %lld us",
4256                         mCodec->mComponentName.c_str(), bufferID, timeUs);
4257#else
4258                    ALOGV("[%s] calling emptyBuffer %p w/ time %lld us",
4259                         mCodec->mComponentName.c_str(), bufferID, timeUs);
4260#endif
4261                }
4262
4263#if TRACK_BUFFER_TIMING
4264                ACodec::BufferStats stats;
4265                stats.mEmptyBufferTimeUs = ALooper::GetNowUs();
4266                stats.mFillBufferDoneTimeUs = -1ll;
4267                mCodec->mBufferStats.add(timeUs, stats);
4268#endif
4269
4270                if (mCodec->mStoreMetaDataInOutputBuffers) {
4271                    // try to submit an output buffer for each input buffer
4272                    PortMode outputMode = getPortMode(kPortIndexOutput);
4273
4274                    ALOGV("MetaDataBuffersToSubmit=%u portMode=%s",
4275                            mCodec->mMetaDataBuffersToSubmit,
4276                            (outputMode == FREE_BUFFERS ? "FREE" :
4277                             outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT"));
4278                    if (outputMode == RESUBMIT_BUFFERS) {
4279                        mCodec->submitOutputMetaDataBuffer();
4280                    }
4281                }
4282
4283                CHECK_EQ(mCodec->mOMX->emptyBuffer(
4284                            mCodec->mNode,
4285                            bufferID,
4286                            0,
4287                            buffer->size(),
4288                            flags,
4289                            timeUs),
4290                         (status_t)OK);
4291
4292                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4293
4294                if (!eos) {
4295                    getMoreInputDataIfPossible();
4296                } else {
4297                    ALOGV("[%s] Signalled EOS on the input port",
4298                         mCodec->mComponentName.c_str());
4299
4300                    mCodec->mPortEOS[kPortIndexInput] = true;
4301                    mCodec->mInputEOSResult = err;
4302                }
4303            } else if (!mCodec->mPortEOS[kPortIndexInput]) {
4304                if (err != ERROR_END_OF_STREAM) {
4305                    ALOGV("[%s] Signalling EOS on the input port "
4306                         "due to error %d",
4307                         mCodec->mComponentName.c_str(), err);
4308                } else {
4309                    ALOGV("[%s] Signalling EOS on the input port",
4310                         mCodec->mComponentName.c_str());
4311                }
4312
4313                ALOGV("[%s] calling emptyBuffer %p signalling EOS",
4314                     mCodec->mComponentName.c_str(), bufferID);
4315
4316                CHECK_EQ(mCodec->mOMX->emptyBuffer(
4317                            mCodec->mNode,
4318                            bufferID,
4319                            0,
4320                            0,
4321                            OMX_BUFFERFLAG_EOS,
4322                            0),
4323                         (status_t)OK);
4324
4325                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4326
4327                mCodec->mPortEOS[kPortIndexInput] = true;
4328                mCodec->mInputEOSResult = err;
4329            }
4330            break;
4331        }
4332
4333        default:
4334            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4335            break;
4336    }
4337}
4338
4339void ACodec::BaseState::getMoreInputDataIfPossible() {
4340    if (mCodec->mPortEOS[kPortIndexInput]) {
4341        return;
4342    }
4343
4344    BufferInfo *eligible = NULL;
4345
4346    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
4347        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
4348
4349#if 0
4350        if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
4351            // There's already a "read" pending.
4352            return;
4353        }
4354#endif
4355
4356        if (info->mStatus == BufferInfo::OWNED_BY_US) {
4357            eligible = info;
4358        }
4359    }
4360
4361    if (eligible == NULL) {
4362        return;
4363    }
4364
4365    postFillThisBuffer(eligible);
4366}
4367
4368bool ACodec::BaseState::onOMXFillBufferDone(
4369        IOMX::buffer_id bufferID,
4370        size_t rangeOffset, size_t rangeLength,
4371        OMX_U32 flags,
4372        int64_t timeUs) {
4373    ALOGV("[%s] onOMXFillBufferDone %u time %" PRId64 " us, flags = 0x%08x",
4374         mCodec->mComponentName.c_str(), bufferID, timeUs, flags);
4375
4376    ssize_t index;
4377
4378#if TRACK_BUFFER_TIMING
4379    index = mCodec->mBufferStats.indexOfKey(timeUs);
4380    if (index >= 0) {
4381        ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index);
4382        stats->mFillBufferDoneTimeUs = ALooper::GetNowUs();
4383
4384        ALOGI("frame PTS %lld: %lld",
4385                timeUs,
4386                stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs);
4387
4388        mCodec->mBufferStats.removeItemsAt(index);
4389        stats = NULL;
4390    }
4391#endif
4392
4393    BufferInfo *info =
4394        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
4395
4396    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
4397
4398    info->mDequeuedAt = ++mCodec->mDequeueCounter;
4399    info->mStatus = BufferInfo::OWNED_BY_US;
4400
4401    PortMode mode = getPortMode(kPortIndexOutput);
4402
4403    switch (mode) {
4404        case KEEP_BUFFERS:
4405            break;
4406
4407        case RESUBMIT_BUFFERS:
4408        {
4409            if (rangeLength == 0 && (!(flags & OMX_BUFFERFLAG_EOS)
4410                    || mCodec->mPortEOS[kPortIndexOutput])) {
4411                ALOGV("[%s] calling fillBuffer %u",
4412                     mCodec->mComponentName.c_str(), info->mBufferID);
4413
4414                CHECK_EQ(mCodec->mOMX->fillBuffer(
4415                            mCodec->mNode, info->mBufferID),
4416                         (status_t)OK);
4417
4418                info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4419                break;
4420            }
4421
4422            sp<AMessage> reply =
4423                new AMessage(kWhatOutputBufferDrained, mCodec->id());
4424
4425            if (!mCodec->mSentFormat && rangeLength > 0) {
4426                mCodec->sendFormatChange(reply);
4427            }
4428
4429            if (mCodec->mUseMetadataOnEncoderOutput) {
4430                native_handle_t* handle =
4431                        *(native_handle_t**)(info->mData->data() + 4);
4432                info->mData->meta()->setPointer("handle", handle);
4433                info->mData->meta()->setInt32("rangeOffset", rangeOffset);
4434                info->mData->meta()->setInt32("rangeLength", rangeLength);
4435            } else {
4436                info->mData->setRange(rangeOffset, rangeLength);
4437            }
4438#if 0
4439            if (mCodec->mNativeWindow == NULL) {
4440                if (IsIDR(info->mData)) {
4441                    ALOGI("IDR frame");
4442                }
4443            }
4444#endif
4445
4446            if (mCodec->mSkipCutBuffer != NULL) {
4447                mCodec->mSkipCutBuffer->submit(info->mData);
4448            }
4449            info->mData->meta()->setInt64("timeUs", timeUs);
4450
4451            sp<AMessage> notify = mCodec->mNotify->dup();
4452            notify->setInt32("what", CodecBase::kWhatDrainThisBuffer);
4453            notify->setInt32("buffer-id", info->mBufferID);
4454            notify->setBuffer("buffer", info->mData);
4455            notify->setInt32("flags", flags);
4456
4457            reply->setInt32("buffer-id", info->mBufferID);
4458
4459            notify->setMessage("reply", reply);
4460
4461            notify->post();
4462
4463            info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
4464
4465            if (flags & OMX_BUFFERFLAG_EOS) {
4466                ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str());
4467
4468                sp<AMessage> notify = mCodec->mNotify->dup();
4469                notify->setInt32("what", CodecBase::kWhatEOS);
4470                notify->setInt32("err", mCodec->mInputEOSResult);
4471                notify->post();
4472
4473                mCodec->mPortEOS[kPortIndexOutput] = true;
4474            }
4475            break;
4476        }
4477
4478        default:
4479        {
4480            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4481
4482            CHECK_EQ((status_t)OK,
4483                     mCodec->freeBuffer(kPortIndexOutput, index));
4484            break;
4485        }
4486    }
4487
4488    return true;
4489}
4490
4491void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
4492    IOMX::buffer_id bufferID;
4493    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
4494    ssize_t index;
4495    BufferInfo *info =
4496        mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
4497    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
4498
4499    android_native_rect_t crop;
4500    if (msg->findRect("crop",
4501            &crop.left, &crop.top, &crop.right, &crop.bottom)) {
4502        CHECK_EQ(0, native_window_set_crop(
4503                mCodec->mNativeWindow.get(), &crop));
4504    }
4505
4506    int32_t render;
4507    if (mCodec->mNativeWindow != NULL
4508            && msg->findInt32("render", &render) && render != 0
4509            && info->mData != NULL && info->mData->size() != 0) {
4510        ATRACE_NAME("render");
4511        // The client wants this buffer to be rendered.
4512
4513        int64_t timestampNs = 0;
4514        if (!msg->findInt64("timestampNs", &timestampNs)) {
4515            // TODO: it seems like we should use the timestamp
4516            // in the (media)buffer as it potentially came from
4517            // an input surface, but we did not propagate it prior to
4518            // API 20.  Perhaps check for target SDK version.
4519#if 0
4520            if (info->mData->meta()->findInt64("timeUs", &timestampNs)) {
4521                ALOGV("using buffer PTS of %" PRId64, timestampNs);
4522                timestampNs *= 1000;
4523            }
4524#endif
4525        }
4526
4527        status_t err;
4528        err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs);
4529        if (err != OK) {
4530            ALOGW("failed to set buffer timestamp: %d", err);
4531        }
4532
4533        if ((err = mCodec->mNativeWindow->queueBuffer(
4534                    mCodec->mNativeWindow.get(),
4535                    info->mGraphicBuffer.get(), -1)) == OK) {
4536            info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
4537        } else {
4538            mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
4539            info->mStatus = BufferInfo::OWNED_BY_US;
4540        }
4541    } else {
4542        if (mCodec->mNativeWindow != NULL &&
4543            (info->mData == NULL || info->mData->size() != 0)) {
4544            ATRACE_NAME("frame-drop");
4545        }
4546        info->mStatus = BufferInfo::OWNED_BY_US;
4547    }
4548
4549    PortMode mode = getPortMode(kPortIndexOutput);
4550
4551    switch (mode) {
4552        case KEEP_BUFFERS:
4553        {
4554            // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
4555
4556            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4557                // We cannot resubmit the buffer we just rendered, dequeue
4558                // the spare instead.
4559
4560                info = mCodec->dequeueBufferFromNativeWindow();
4561            }
4562            break;
4563        }
4564
4565        case RESUBMIT_BUFFERS:
4566        {
4567            if (!mCodec->mPortEOS[kPortIndexOutput]) {
4568                if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
4569                    // We cannot resubmit the buffer we just rendered, dequeue
4570                    // the spare instead.
4571
4572                    info = mCodec->dequeueBufferFromNativeWindow();
4573                }
4574
4575                if (info != NULL) {
4576                    ALOGV("[%s] calling fillBuffer %u",
4577                         mCodec->mComponentName.c_str(), info->mBufferID);
4578
4579                    CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
4580                             (status_t)OK);
4581
4582                    info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
4583                }
4584            }
4585            break;
4586        }
4587
4588        default:
4589        {
4590            CHECK_EQ((int)mode, (int)FREE_BUFFERS);
4591
4592            CHECK_EQ((status_t)OK,
4593                     mCodec->freeBuffer(kPortIndexOutput, index));
4594            break;
4595        }
4596    }
4597}
4598
4599////////////////////////////////////////////////////////////////////////////////
4600
4601ACodec::UninitializedState::UninitializedState(ACodec *codec)
4602    : BaseState(codec) {
4603}
4604
4605void ACodec::UninitializedState::stateEntered() {
4606    ALOGV("Now uninitialized");
4607
4608    if (mDeathNotifier != NULL) {
4609        mCodec->mOMX->asBinder()->unlinkToDeath(mDeathNotifier);
4610        mDeathNotifier.clear();
4611    }
4612
4613    mCodec->mNativeWindow.clear();
4614    mCodec->mNode = NULL;
4615    mCodec->mOMX.clear();
4616    mCodec->mQuirks = 0;
4617    mCodec->mFlags = 0;
4618    mCodec->mUseMetadataOnEncoderOutput = 0;
4619    mCodec->mComponentName.clear();
4620}
4621
4622bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
4623    bool handled = false;
4624
4625    switch (msg->what()) {
4626        case ACodec::kWhatSetup:
4627        {
4628            onSetup(msg);
4629
4630            handled = true;
4631            break;
4632        }
4633
4634        case ACodec::kWhatAllocateComponent:
4635        {
4636            onAllocateComponent(msg);
4637            handled = true;
4638            break;
4639        }
4640
4641        case ACodec::kWhatShutdown:
4642        {
4643            int32_t keepComponentAllocated;
4644            CHECK(msg->findInt32(
4645                        "keepComponentAllocated", &keepComponentAllocated));
4646            ALOGW_IF(keepComponentAllocated,
4647                     "cannot keep component allocated on shutdown in Uninitialized state");
4648
4649            sp<AMessage> notify = mCodec->mNotify->dup();
4650            notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
4651            notify->post();
4652
4653            handled = true;
4654            break;
4655        }
4656
4657        case ACodec::kWhatFlush:
4658        {
4659            sp<AMessage> notify = mCodec->mNotify->dup();
4660            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
4661            notify->post();
4662
4663            handled = true;
4664            break;
4665        }
4666
4667        case ACodec::kWhatReleaseCodecInstance:
4668        {
4669            // nothing to do, as we have already signaled shutdown
4670            handled = true;
4671            break;
4672        }
4673
4674        default:
4675            return BaseState::onMessageReceived(msg);
4676    }
4677
4678    return handled;
4679}
4680
4681void ACodec::UninitializedState::onSetup(
4682        const sp<AMessage> &msg) {
4683    if (onAllocateComponent(msg)
4684            && mCodec->mLoadedState->onConfigureComponent(msg)) {
4685        mCodec->mLoadedState->onStart();
4686    }
4687}
4688
4689bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
4690    ALOGV("onAllocateComponent");
4691
4692    CHECK(mCodec->mNode == NULL);
4693
4694    OMXClient client;
4695    CHECK_EQ(client.connect(), (status_t)OK);
4696
4697    sp<IOMX> omx = client.interface();
4698
4699    sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec->id());
4700
4701    mDeathNotifier = new DeathNotifier(notify);
4702    if (omx->asBinder()->linkToDeath(mDeathNotifier) != OK) {
4703        // This was a local binder, if it dies so do we, we won't care
4704        // about any notifications in the afterlife.
4705        mDeathNotifier.clear();
4706    }
4707
4708    Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs;
4709
4710    AString mime;
4711
4712    AString componentName;
4713    uint32_t quirks = 0;
4714    int32_t encoder = false;
4715    if (msg->findString("componentName", &componentName)) {
4716        ssize_t index = matchingCodecs.add();
4717        OMXCodec::CodecNameAndQuirks *entry = &matchingCodecs.editItemAt(index);
4718        entry->mName = String8(componentName.c_str());
4719
4720        if (!OMXCodec::findCodecQuirks(
4721                    componentName.c_str(), &entry->mQuirks)) {
4722            entry->mQuirks = 0;
4723        }
4724    } else {
4725        CHECK(msg->findString("mime", &mime));
4726
4727        if (!msg->findInt32("encoder", &encoder)) {
4728            encoder = false;
4729        }
4730
4731        OMXCodec::findMatchingCodecs(
4732                mime.c_str(),
4733                encoder, // createEncoder
4734                NULL,  // matchComponentName
4735                0,     // flags
4736                &matchingCodecs);
4737    }
4738
4739    sp<CodecObserver> observer = new CodecObserver;
4740    IOMX::node_id node = NULL;
4741
4742    for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
4743            ++matchIndex) {
4744        componentName = matchingCodecs.itemAt(matchIndex).mName.string();
4745        quirks = matchingCodecs.itemAt(matchIndex).mQuirks;
4746
4747        pid_t tid = androidGetTid();
4748        int prevPriority = androidGetThreadPriority(tid);
4749        androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
4750        status_t err = omx->allocateNode(componentName.c_str(), observer, &node);
4751        androidSetThreadPriority(tid, prevPriority);
4752
4753        if (err == OK) {
4754            break;
4755        } else {
4756            ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str());
4757        }
4758
4759        node = NULL;
4760    }
4761
4762    if (node == NULL) {
4763        if (!mime.empty()) {
4764            ALOGE("Unable to instantiate a %scoder for type '%s'.",
4765                    encoder ? "en" : "de", mime.c_str());
4766        } else {
4767            ALOGE("Unable to instantiate codec '%s'.", componentName.c_str());
4768        }
4769
4770        mCodec->signalError(OMX_ErrorComponentNotFound);
4771        return false;
4772    }
4773
4774    notify = new AMessage(kWhatOMXMessage, mCodec->id());
4775    observer->setNotificationMessage(notify);
4776
4777    mCodec->mComponentName = componentName;
4778    mCodec->mFlags = 0;
4779
4780    if (componentName.endsWith(".secure")) {
4781        mCodec->mFlags |= kFlagIsSecure;
4782        mCodec->mFlags |= kFlagIsGrallocUsageProtected;
4783        mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
4784    }
4785
4786    mCodec->mQuirks = quirks;
4787    mCodec->mOMX = omx;
4788    mCodec->mNode = node;
4789
4790    {
4791        sp<AMessage> notify = mCodec->mNotify->dup();
4792        notify->setInt32("what", CodecBase::kWhatComponentAllocated);
4793        notify->setString("componentName", mCodec->mComponentName.c_str());
4794        notify->post();
4795    }
4796
4797    mCodec->changeState(mCodec->mLoadedState);
4798
4799    return true;
4800}
4801
4802////////////////////////////////////////////////////////////////////////////////
4803
4804ACodec::LoadedState::LoadedState(ACodec *codec)
4805    : BaseState(codec) {
4806}
4807
4808void ACodec::LoadedState::stateEntered() {
4809    ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
4810
4811    mCodec->mPortEOS[kPortIndexInput] =
4812        mCodec->mPortEOS[kPortIndexOutput] = false;
4813
4814    mCodec->mInputEOSResult = OK;
4815
4816    mCodec->mDequeueCounter = 0;
4817    mCodec->mMetaDataBuffersToSubmit = 0;
4818    mCodec->mRepeatFrameDelayUs = -1ll;
4819    mCodec->mInputFormat.clear();
4820    mCodec->mOutputFormat.clear();
4821    mCodec->mBaseOutputFormat.clear();
4822
4823    if (mCodec->mShutdownInProgress) {
4824        bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
4825
4826        mCodec->mShutdownInProgress = false;
4827        mCodec->mKeepComponentAllocated = false;
4828
4829        onShutdown(keepComponentAllocated);
4830    }
4831    mCodec->mExplicitShutdown = false;
4832
4833    mCodec->processDeferredMessages();
4834}
4835
4836void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
4837    if (!keepComponentAllocated) {
4838        CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
4839
4840        mCodec->changeState(mCodec->mUninitializedState);
4841    }
4842
4843    if (mCodec->mExplicitShutdown) {
4844        sp<AMessage> notify = mCodec->mNotify->dup();
4845        notify->setInt32("what", CodecBase::kWhatShutdownCompleted);
4846        notify->post();
4847        mCodec->mExplicitShutdown = false;
4848    }
4849}
4850
4851bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
4852    bool handled = false;
4853
4854    switch (msg->what()) {
4855        case ACodec::kWhatConfigureComponent:
4856        {
4857            onConfigureComponent(msg);
4858            handled = true;
4859            break;
4860        }
4861
4862        case ACodec::kWhatCreateInputSurface:
4863        {
4864            onCreateInputSurface(msg);
4865            handled = true;
4866            break;
4867        }
4868
4869        case ACodec::kWhatStart:
4870        {
4871            onStart();
4872            handled = true;
4873            break;
4874        }
4875
4876        case ACodec::kWhatShutdown:
4877        {
4878            int32_t keepComponentAllocated;
4879            CHECK(msg->findInt32(
4880                        "keepComponentAllocated", &keepComponentAllocated));
4881
4882            mCodec->mExplicitShutdown = true;
4883            onShutdown(keepComponentAllocated);
4884
4885            handled = true;
4886            break;
4887        }
4888
4889        case ACodec::kWhatFlush:
4890        {
4891            sp<AMessage> notify = mCodec->mNotify->dup();
4892            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
4893            notify->post();
4894
4895            handled = true;
4896            break;
4897        }
4898
4899        default:
4900            return BaseState::onMessageReceived(msg);
4901    }
4902
4903    return handled;
4904}
4905
4906bool ACodec::LoadedState::onConfigureComponent(
4907        const sp<AMessage> &msg) {
4908    ALOGV("onConfigureComponent");
4909
4910    CHECK(mCodec->mNode != NULL);
4911
4912    AString mime;
4913    CHECK(msg->findString("mime", &mime));
4914
4915    status_t err = mCodec->configureCodec(mime.c_str(), msg);
4916
4917    if (err != OK) {
4918        ALOGE("[%s] configureCodec returning error %d",
4919              mCodec->mComponentName.c_str(), err);
4920
4921        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
4922        return false;
4923    }
4924
4925    sp<RefBase> obj;
4926    if (msg->findObject("native-window", &obj)
4927            && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) {
4928        sp<NativeWindowWrapper> nativeWindow(
4929                static_cast<NativeWindowWrapper *>(obj.get()));
4930        CHECK(nativeWindow != NULL);
4931        mCodec->mNativeWindow = nativeWindow->getNativeWindow();
4932
4933        native_window_set_scaling_mode(
4934                mCodec->mNativeWindow.get(),
4935                NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
4936    }
4937    CHECK_EQ((status_t)OK, mCodec->initNativeWindow());
4938
4939    {
4940        sp<AMessage> notify = mCodec->mNotify->dup();
4941        notify->setInt32("what", CodecBase::kWhatComponentConfigured);
4942        notify->setMessage("input-format", mCodec->mInputFormat);
4943        notify->setMessage("output-format", mCodec->mOutputFormat);
4944        notify->post();
4945    }
4946
4947    return true;
4948}
4949
4950void ACodec::LoadedState::onCreateInputSurface(
4951        const sp<AMessage> & /* msg */) {
4952    ALOGV("onCreateInputSurface");
4953
4954    sp<AMessage> notify = mCodec->mNotify->dup();
4955    notify->setInt32("what", CodecBase::kWhatInputSurfaceCreated);
4956
4957    sp<IGraphicBufferProducer> bufferProducer;
4958    status_t err;
4959
4960    err = mCodec->mOMX->createInputSurface(mCodec->mNode, kPortIndexInput,
4961            &bufferProducer);
4962
4963    if (err == OK && mCodec->mRepeatFrameDelayUs > 0ll) {
4964        err = mCodec->mOMX->setInternalOption(
4965                mCodec->mNode,
4966                kPortIndexInput,
4967                IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY,
4968                &mCodec->mRepeatFrameDelayUs,
4969                sizeof(mCodec->mRepeatFrameDelayUs));
4970
4971        if (err != OK) {
4972            ALOGE("[%s] Unable to configure option to repeat previous "
4973                  "frames (err %d)",
4974                  mCodec->mComponentName.c_str(),
4975                  err);
4976        }
4977    }
4978
4979    if (err == OK && mCodec->mMaxPtsGapUs > 0ll) {
4980        err = mCodec->mOMX->setInternalOption(
4981                mCodec->mNode,
4982                kPortIndexInput,
4983                IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP,
4984                &mCodec->mMaxPtsGapUs,
4985                sizeof(mCodec->mMaxPtsGapUs));
4986
4987        if (err != OK) {
4988            ALOGE("[%s] Unable to configure max timestamp gap (err %d)",
4989                    mCodec->mComponentName.c_str(),
4990                    err);
4991        }
4992    }
4993
4994    if (err == OK && mCodec->mTimePerCaptureUs > 0ll
4995            && mCodec->mTimePerFrameUs > 0ll) {
4996        int64_t timeLapse[2];
4997        timeLapse[0] = mCodec->mTimePerFrameUs;
4998        timeLapse[1] = mCodec->mTimePerCaptureUs;
4999        err = mCodec->mOMX->setInternalOption(
5000                mCodec->mNode,
5001                kPortIndexInput,
5002                IOMX::INTERNAL_OPTION_TIME_LAPSE,
5003                &timeLapse[0],
5004                sizeof(timeLapse));
5005
5006        if (err != OK) {
5007            ALOGE("[%s] Unable to configure time lapse (err %d)",
5008                    mCodec->mComponentName.c_str(),
5009                    err);
5010        }
5011    }
5012
5013    if (err == OK && mCodec->mCreateInputBuffersSuspended) {
5014        bool suspend = true;
5015        err = mCodec->mOMX->setInternalOption(
5016                mCodec->mNode,
5017                kPortIndexInput,
5018                IOMX::INTERNAL_OPTION_SUSPEND,
5019                &suspend,
5020                sizeof(suspend));
5021
5022        if (err != OK) {
5023            ALOGE("[%s] Unable to configure option to suspend (err %d)",
5024                  mCodec->mComponentName.c_str(),
5025                  err);
5026        }
5027    }
5028
5029    if (err == OK) {
5030        notify->setObject("input-surface",
5031                new BufferProducerWrapper(bufferProducer));
5032    } else {
5033        // Can't use mCodec->signalError() here -- MediaCodec won't forward
5034        // the error through because it's in the "configured" state.  We
5035        // send a kWhatInputSurfaceCreated with an error value instead.
5036        ALOGE("[%s] onCreateInputSurface returning error %d",
5037                mCodec->mComponentName.c_str(), err);
5038        notify->setInt32("err", err);
5039    }
5040    notify->post();
5041}
5042
5043void ACodec::LoadedState::onStart() {
5044    ALOGV("onStart");
5045
5046    CHECK_EQ(mCodec->mOMX->sendCommand(
5047                mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
5048             (status_t)OK);
5049
5050    mCodec->changeState(mCodec->mLoadedToIdleState);
5051}
5052
5053////////////////////////////////////////////////////////////////////////////////
5054
5055ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
5056    : BaseState(codec) {
5057}
5058
5059void ACodec::LoadedToIdleState::stateEntered() {
5060    ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
5061
5062    status_t err;
5063    if ((err = allocateBuffers()) != OK) {
5064        ALOGE("Failed to allocate buffers after transitioning to IDLE state "
5065             "(error 0x%08x)",
5066             err);
5067
5068        mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5069
5070        mCodec->changeState(mCodec->mLoadedState);
5071    }
5072}
5073
5074status_t ACodec::LoadedToIdleState::allocateBuffers() {
5075    status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
5076
5077    if (err != OK) {
5078        return err;
5079    }
5080
5081    return mCodec->allocateBuffersOnPort(kPortIndexOutput);
5082}
5083
5084bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
5085    switch (msg->what()) {
5086        case kWhatSetParameters:
5087        case kWhatShutdown:
5088        {
5089            mCodec->deferMessage(msg);
5090            return true;
5091        }
5092
5093        case kWhatSignalEndOfInputStream:
5094        {
5095            mCodec->onSignalEndOfInputStream();
5096            return true;
5097        }
5098
5099        case kWhatResume:
5100        {
5101            // We'll be active soon enough.
5102            return true;
5103        }
5104
5105        case kWhatFlush:
5106        {
5107            // We haven't even started yet, so we're flushed alright...
5108            sp<AMessage> notify = mCodec->mNotify->dup();
5109            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5110            notify->post();
5111            return true;
5112        }
5113
5114        default:
5115            return BaseState::onMessageReceived(msg);
5116    }
5117}
5118
5119bool ACodec::LoadedToIdleState::onOMXEvent(
5120        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5121    switch (event) {
5122        case OMX_EventCmdComplete:
5123        {
5124            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
5125            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
5126
5127            CHECK_EQ(mCodec->mOMX->sendCommand(
5128                        mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
5129                     (status_t)OK);
5130
5131            mCodec->changeState(mCodec->mIdleToExecutingState);
5132
5133            return true;
5134        }
5135
5136        default:
5137            return BaseState::onOMXEvent(event, data1, data2);
5138    }
5139}
5140
5141////////////////////////////////////////////////////////////////////////////////
5142
5143ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
5144    : BaseState(codec) {
5145}
5146
5147void ACodec::IdleToExecutingState::stateEntered() {
5148    ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
5149}
5150
5151bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
5152    switch (msg->what()) {
5153        case kWhatSetParameters:
5154        case kWhatShutdown:
5155        {
5156            mCodec->deferMessage(msg);
5157            return true;
5158        }
5159
5160        case kWhatResume:
5161        {
5162            // We'll be active soon enough.
5163            return true;
5164        }
5165
5166        case kWhatFlush:
5167        {
5168            // We haven't even started yet, so we're flushed alright...
5169            sp<AMessage> notify = mCodec->mNotify->dup();
5170            notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5171            notify->post();
5172
5173            return true;
5174        }
5175
5176        case kWhatSignalEndOfInputStream:
5177        {
5178            mCodec->onSignalEndOfInputStream();
5179            return true;
5180        }
5181
5182        default:
5183            return BaseState::onMessageReceived(msg);
5184    }
5185}
5186
5187bool ACodec::IdleToExecutingState::onOMXEvent(
5188        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5189    switch (event) {
5190        case OMX_EventCmdComplete:
5191        {
5192            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
5193            CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
5194
5195            mCodec->mExecutingState->resume();
5196            mCodec->changeState(mCodec->mExecutingState);
5197
5198            return true;
5199        }
5200
5201        default:
5202            return BaseState::onOMXEvent(event, data1, data2);
5203    }
5204}
5205
5206////////////////////////////////////////////////////////////////////////////////
5207
5208ACodec::ExecutingState::ExecutingState(ACodec *codec)
5209    : BaseState(codec),
5210      mActive(false) {
5211}
5212
5213ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
5214        OMX_U32 /* portIndex */) {
5215    return RESUBMIT_BUFFERS;
5216}
5217
5218void ACodec::ExecutingState::submitOutputMetaBuffers() {
5219    // submit as many buffers as there are input buffers with the codec
5220    // in case we are in port reconfiguring
5221    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
5222        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
5223
5224        if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) {
5225            if (mCodec->submitOutputMetaDataBuffer() != OK)
5226                break;
5227        }
5228    }
5229
5230    // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
5231    mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround();
5232}
5233
5234void ACodec::ExecutingState::submitRegularOutputBuffers() {
5235    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
5236        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
5237
5238        if (mCodec->mNativeWindow != NULL) {
5239            CHECK(info->mStatus == BufferInfo::OWNED_BY_US
5240                    || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
5241
5242            if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
5243                continue;
5244            }
5245        } else {
5246            CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
5247        }
5248
5249        ALOGV("[%s] calling fillBuffer %p",
5250             mCodec->mComponentName.c_str(), info->mBufferID);
5251
5252        CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
5253                 (status_t)OK);
5254
5255        info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
5256    }
5257}
5258
5259void ACodec::ExecutingState::submitOutputBuffers() {
5260    submitRegularOutputBuffers();
5261    if (mCodec->mStoreMetaDataInOutputBuffers) {
5262        submitOutputMetaBuffers();
5263    }
5264}
5265
5266void ACodec::ExecutingState::resume() {
5267    if (mActive) {
5268        ALOGV("[%s] We're already active, no need to resume.",
5269             mCodec->mComponentName.c_str());
5270
5271        return;
5272    }
5273
5274    submitOutputBuffers();
5275
5276    // Post all available input buffers
5277    CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
5278    for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) {
5279        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
5280        if (info->mStatus == BufferInfo::OWNED_BY_US) {
5281            postFillThisBuffer(info);
5282        }
5283    }
5284
5285    mActive = true;
5286}
5287
5288void ACodec::ExecutingState::stateEntered() {
5289    ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
5290
5291    mCodec->processDeferredMessages();
5292}
5293
5294bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
5295    bool handled = false;
5296
5297    switch (msg->what()) {
5298        case kWhatShutdown:
5299        {
5300            int32_t keepComponentAllocated;
5301            CHECK(msg->findInt32(
5302                        "keepComponentAllocated", &keepComponentAllocated));
5303
5304            mCodec->mShutdownInProgress = true;
5305            mCodec->mExplicitShutdown = true;
5306            mCodec->mKeepComponentAllocated = keepComponentAllocated;
5307
5308            mActive = false;
5309
5310            CHECK_EQ(mCodec->mOMX->sendCommand(
5311                        mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
5312                     (status_t)OK);
5313
5314            mCodec->changeState(mCodec->mExecutingToIdleState);
5315
5316            handled = true;
5317            break;
5318        }
5319
5320        case kWhatFlush:
5321        {
5322            ALOGV("[%s] ExecutingState flushing now "
5323                 "(codec owns %d/%d input, %d/%d output).",
5324                    mCodec->mComponentName.c_str(),
5325                    mCodec->countBuffersOwnedByComponent(kPortIndexInput),
5326                    mCodec->mBuffers[kPortIndexInput].size(),
5327                    mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
5328                    mCodec->mBuffers[kPortIndexOutput].size());
5329
5330            mActive = false;
5331
5332            CHECK_EQ(mCodec->mOMX->sendCommand(
5333                        mCodec->mNode, OMX_CommandFlush, OMX_ALL),
5334                     (status_t)OK);
5335
5336            mCodec->changeState(mCodec->mFlushingState);
5337            handled = true;
5338            break;
5339        }
5340
5341        case kWhatResume:
5342        {
5343            resume();
5344
5345            handled = true;
5346            break;
5347        }
5348
5349        case kWhatRequestIDRFrame:
5350        {
5351            status_t err = mCodec->requestIDRFrame();
5352            if (err != OK) {
5353                ALOGW("Requesting an IDR frame failed.");
5354            }
5355
5356            handled = true;
5357            break;
5358        }
5359
5360        case kWhatSetParameters:
5361        {
5362            sp<AMessage> params;
5363            CHECK(msg->findMessage("params", &params));
5364
5365            status_t err = mCodec->setParameters(params);
5366
5367            sp<AMessage> reply;
5368            if (msg->findMessage("reply", &reply)) {
5369                reply->setInt32("err", err);
5370                reply->post();
5371            }
5372
5373            handled = true;
5374            break;
5375        }
5376
5377        case ACodec::kWhatSignalEndOfInputStream:
5378        {
5379            mCodec->onSignalEndOfInputStream();
5380            handled = true;
5381            break;
5382        }
5383
5384        // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
5385        case kWhatSubmitOutputMetaDataBufferIfEOS:
5386        {
5387            if (mCodec->mPortEOS[kPortIndexInput] &&
5388                    !mCodec->mPortEOS[kPortIndexOutput]) {
5389                status_t err = mCodec->submitOutputMetaDataBuffer();
5390                if (err == OK) {
5391                    mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround();
5392                }
5393            }
5394            return true;
5395        }
5396
5397        default:
5398            handled = BaseState::onMessageReceived(msg);
5399            break;
5400    }
5401
5402    return handled;
5403}
5404
5405status_t ACodec::setParameters(const sp<AMessage> &params) {
5406    int32_t videoBitrate;
5407    if (params->findInt32("video-bitrate", &videoBitrate)) {
5408        OMX_VIDEO_CONFIG_BITRATETYPE configParams;
5409        InitOMXParams(&configParams);
5410        configParams.nPortIndex = kPortIndexOutput;
5411        configParams.nEncodeBitrate = videoBitrate;
5412
5413        status_t err = mOMX->setConfig(
5414                mNode,
5415                OMX_IndexConfigVideoBitrate,
5416                &configParams,
5417                sizeof(configParams));
5418
5419        if (err != OK) {
5420            ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d",
5421                   videoBitrate, err);
5422
5423            return err;
5424        }
5425    }
5426
5427    int64_t skipFramesBeforeUs;
5428    if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) {
5429        status_t err =
5430            mOMX->setInternalOption(
5431                     mNode,
5432                     kPortIndexInput,
5433                     IOMX::INTERNAL_OPTION_START_TIME,
5434                     &skipFramesBeforeUs,
5435                     sizeof(skipFramesBeforeUs));
5436
5437        if (err != OK) {
5438            ALOGE("Failed to set parameter 'skip-frames-before' (err %d)", err);
5439            return err;
5440        }
5441    }
5442
5443    int32_t dropInputFrames;
5444    if (params->findInt32("drop-input-frames", &dropInputFrames)) {
5445        bool suspend = dropInputFrames != 0;
5446
5447        status_t err =
5448            mOMX->setInternalOption(
5449                     mNode,
5450                     kPortIndexInput,
5451                     IOMX::INTERNAL_OPTION_SUSPEND,
5452                     &suspend,
5453                     sizeof(suspend));
5454
5455        if (err != OK) {
5456            ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err);
5457            return err;
5458        }
5459    }
5460
5461    int32_t dummy;
5462    if (params->findInt32("request-sync", &dummy)) {
5463        status_t err = requestIDRFrame();
5464
5465        if (err != OK) {
5466            ALOGE("Requesting a sync frame failed w/ err %d", err);
5467            return err;
5468        }
5469    }
5470
5471    return OK;
5472}
5473
5474void ACodec::onSignalEndOfInputStream() {
5475    sp<AMessage> notify = mNotify->dup();
5476    notify->setInt32("what", CodecBase::kWhatSignaledInputEOS);
5477
5478    status_t err = mOMX->signalEndOfInputStream(mNode);
5479    if (err != OK) {
5480        notify->setInt32("err", err);
5481    }
5482    notify->post();
5483}
5484
5485bool ACodec::ExecutingState::onOMXEvent(
5486        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5487    switch (event) {
5488        case OMX_EventPortSettingsChanged:
5489        {
5490            CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
5491
5492            if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
5493                mCodec->mMetaDataBuffersToSubmit = 0;
5494                CHECK_EQ(mCodec->mOMX->sendCommand(
5495                            mCodec->mNode,
5496                            OMX_CommandPortDisable, kPortIndexOutput),
5497                         (status_t)OK);
5498
5499                mCodec->freeOutputBuffersNotOwnedByComponent();
5500
5501                mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
5502            } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
5503                mCodec->mSentFormat = false;
5504            } else {
5505                ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
5506                     mCodec->mComponentName.c_str(), data2);
5507            }
5508
5509            return true;
5510        }
5511
5512        case OMX_EventBufferFlag:
5513        {
5514            return true;
5515        }
5516
5517        default:
5518            return BaseState::onOMXEvent(event, data1, data2);
5519    }
5520}
5521
5522////////////////////////////////////////////////////////////////////////////////
5523
5524ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
5525        ACodec *codec)
5526    : BaseState(codec) {
5527}
5528
5529ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
5530        OMX_U32 portIndex) {
5531    if (portIndex == kPortIndexOutput) {
5532        return FREE_BUFFERS;
5533    }
5534
5535    CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
5536
5537    return RESUBMIT_BUFFERS;
5538}
5539
5540bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
5541        const sp<AMessage> &msg) {
5542    bool handled = false;
5543
5544    switch (msg->what()) {
5545        case kWhatFlush:
5546        case kWhatShutdown:
5547        case kWhatResume:
5548        {
5549            if (msg->what() == kWhatResume) {
5550                ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
5551            }
5552
5553            mCodec->deferMessage(msg);
5554            handled = true;
5555            break;
5556        }
5557
5558        default:
5559            handled = BaseState::onMessageReceived(msg);
5560            break;
5561    }
5562
5563    return handled;
5564}
5565
5566void ACodec::OutputPortSettingsChangedState::stateEntered() {
5567    ALOGV("[%s] Now handling output port settings change",
5568         mCodec->mComponentName.c_str());
5569}
5570
5571bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
5572        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5573    switch (event) {
5574        case OMX_EventCmdComplete:
5575        {
5576            if (data1 == (OMX_U32)OMX_CommandPortDisable) {
5577                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
5578
5579                ALOGV("[%s] Output port now disabled.",
5580                        mCodec->mComponentName.c_str());
5581
5582                CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
5583                mCodec->mDealer[kPortIndexOutput].clear();
5584
5585                CHECK_EQ(mCodec->mOMX->sendCommand(
5586                            mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
5587                         (status_t)OK);
5588
5589                status_t err;
5590                if ((err = mCodec->allocateBuffersOnPort(
5591                                kPortIndexOutput)) != OK) {
5592                    ALOGE("Failed to allocate output port buffers after "
5593                         "port reconfiguration (error 0x%08x)",
5594                         err);
5595
5596                    mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
5597
5598                    // This is technically not correct, but appears to be
5599                    // the only way to free the component instance.
5600                    // Controlled transitioning from excecuting->idle
5601                    // and idle->loaded seem impossible probably because
5602                    // the output port never finishes re-enabling.
5603                    mCodec->mShutdownInProgress = true;
5604                    mCodec->mKeepComponentAllocated = false;
5605                    mCodec->changeState(mCodec->mLoadedState);
5606                }
5607
5608                return true;
5609            } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
5610                CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
5611
5612                mCodec->mSentFormat = false;
5613
5614                ALOGV("[%s] Output port now reenabled.",
5615                        mCodec->mComponentName.c_str());
5616
5617                if (mCodec->mExecutingState->active()) {
5618                    mCodec->mExecutingState->submitOutputBuffers();
5619                }
5620
5621                mCodec->changeState(mCodec->mExecutingState);
5622
5623                return true;
5624            }
5625
5626            return false;
5627        }
5628
5629        default:
5630            return false;
5631    }
5632}
5633
5634////////////////////////////////////////////////////////////////////////////////
5635
5636ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
5637    : BaseState(codec),
5638      mComponentNowIdle(false) {
5639}
5640
5641bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
5642    bool handled = false;
5643
5644    switch (msg->what()) {
5645        case kWhatFlush:
5646        {
5647            // Don't send me a flush request if you previously wanted me
5648            // to shutdown.
5649            TRESPASS();
5650            break;
5651        }
5652
5653        case kWhatShutdown:
5654        {
5655            // We're already doing that...
5656
5657            handled = true;
5658            break;
5659        }
5660
5661        default:
5662            handled = BaseState::onMessageReceived(msg);
5663            break;
5664    }
5665
5666    return handled;
5667}
5668
5669void ACodec::ExecutingToIdleState::stateEntered() {
5670    ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
5671
5672    mComponentNowIdle = false;
5673    mCodec->mSentFormat = false;
5674}
5675
5676bool ACodec::ExecutingToIdleState::onOMXEvent(
5677        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5678    switch (event) {
5679        case OMX_EventCmdComplete:
5680        {
5681            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
5682            CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
5683
5684            mComponentNowIdle = true;
5685
5686            changeStateIfWeOwnAllBuffers();
5687
5688            return true;
5689        }
5690
5691        case OMX_EventPortSettingsChanged:
5692        case OMX_EventBufferFlag:
5693        {
5694            // We're shutting down and don't care about this anymore.
5695            return true;
5696        }
5697
5698        default:
5699            return BaseState::onOMXEvent(event, data1, data2);
5700    }
5701}
5702
5703void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
5704    if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
5705        CHECK_EQ(mCodec->mOMX->sendCommand(
5706                    mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
5707                 (status_t)OK);
5708
5709        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
5710        CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
5711
5712        if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown)
5713                && mCodec->mNativeWindow != NULL) {
5714            // We push enough 1x1 blank buffers to ensure that one of
5715            // them has made it to the display.  This allows the OMX
5716            // component teardown to zero out any protected buffers
5717            // without the risk of scanning out one of those buffers.
5718            mCodec->pushBlankBuffersToNativeWindow();
5719        }
5720
5721        mCodec->changeState(mCodec->mIdleToLoadedState);
5722    }
5723}
5724
5725void ACodec::ExecutingToIdleState::onInputBufferFilled(
5726        const sp<AMessage> &msg) {
5727    BaseState::onInputBufferFilled(msg);
5728
5729    changeStateIfWeOwnAllBuffers();
5730}
5731
5732void ACodec::ExecutingToIdleState::onOutputBufferDrained(
5733        const sp<AMessage> &msg) {
5734    BaseState::onOutputBufferDrained(msg);
5735
5736    changeStateIfWeOwnAllBuffers();
5737}
5738
5739////////////////////////////////////////////////////////////////////////////////
5740
5741ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
5742    : BaseState(codec) {
5743}
5744
5745bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
5746    bool handled = false;
5747
5748    switch (msg->what()) {
5749        case kWhatShutdown:
5750        {
5751            // We're already doing that...
5752
5753            handled = true;
5754            break;
5755        }
5756
5757        case kWhatFlush:
5758        {
5759            // Don't send me a flush request if you previously wanted me
5760            // to shutdown.
5761            TRESPASS();
5762            break;
5763        }
5764
5765        default:
5766            handled = BaseState::onMessageReceived(msg);
5767            break;
5768    }
5769
5770    return handled;
5771}
5772
5773void ACodec::IdleToLoadedState::stateEntered() {
5774    ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
5775}
5776
5777bool ACodec::IdleToLoadedState::onOMXEvent(
5778        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5779    switch (event) {
5780        case OMX_EventCmdComplete:
5781        {
5782            CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
5783            CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
5784
5785            mCodec->changeState(mCodec->mLoadedState);
5786
5787            return true;
5788        }
5789
5790        default:
5791            return BaseState::onOMXEvent(event, data1, data2);
5792    }
5793}
5794
5795////////////////////////////////////////////////////////////////////////////////
5796
5797ACodec::FlushingState::FlushingState(ACodec *codec)
5798    : BaseState(codec) {
5799}
5800
5801void ACodec::FlushingState::stateEntered() {
5802    ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
5803
5804    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
5805}
5806
5807bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
5808    bool handled = false;
5809
5810    switch (msg->what()) {
5811        case kWhatShutdown:
5812        {
5813            mCodec->deferMessage(msg);
5814            break;
5815        }
5816
5817        case kWhatFlush:
5818        {
5819            // We're already doing this right now.
5820            handled = true;
5821            break;
5822        }
5823
5824        default:
5825            handled = BaseState::onMessageReceived(msg);
5826            break;
5827    }
5828
5829    return handled;
5830}
5831
5832bool ACodec::FlushingState::onOMXEvent(
5833        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
5834    ALOGV("[%s] FlushingState onOMXEvent(%d,%ld)",
5835            mCodec->mComponentName.c_str(), event, data1);
5836
5837    switch (event) {
5838        case OMX_EventCmdComplete:
5839        {
5840            CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
5841
5842            if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
5843                CHECK(!mFlushComplete[data2]);
5844                mFlushComplete[data2] = true;
5845
5846                if (mFlushComplete[kPortIndexInput]
5847                        && mFlushComplete[kPortIndexOutput]) {
5848                    changeStateIfWeOwnAllBuffers();
5849                }
5850            } else {
5851                CHECK_EQ(data2, OMX_ALL);
5852                CHECK(mFlushComplete[kPortIndexInput]);
5853                CHECK(mFlushComplete[kPortIndexOutput]);
5854
5855                changeStateIfWeOwnAllBuffers();
5856            }
5857
5858            return true;
5859        }
5860
5861        case OMX_EventPortSettingsChanged:
5862        {
5863            sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id());
5864            msg->setInt32("type", omx_message::EVENT);
5865            msg->setInt32("node", mCodec->mNode);
5866            msg->setInt32("event", event);
5867            msg->setInt32("data1", data1);
5868            msg->setInt32("data2", data2);
5869
5870            ALOGV("[%s] Deferring OMX_EventPortSettingsChanged",
5871                 mCodec->mComponentName.c_str());
5872
5873            mCodec->deferMessage(msg);
5874
5875            return true;
5876        }
5877
5878        default:
5879            return BaseState::onOMXEvent(event, data1, data2);
5880    }
5881
5882    return true;
5883}
5884
5885void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
5886    BaseState::onOutputBufferDrained(msg);
5887
5888    changeStateIfWeOwnAllBuffers();
5889}
5890
5891void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
5892    BaseState::onInputBufferFilled(msg);
5893
5894    changeStateIfWeOwnAllBuffers();
5895}
5896
5897void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
5898    if (mFlushComplete[kPortIndexInput]
5899            && mFlushComplete[kPortIndexOutput]
5900            && mCodec->allYourBuffersAreBelongToUs()) {
5901        // We now own all buffers except possibly those still queued with
5902        // the native window for rendering. Let's get those back as well.
5903        mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs();
5904
5905        sp<AMessage> notify = mCodec->mNotify->dup();
5906        notify->setInt32("what", CodecBase::kWhatFlushCompleted);
5907        notify->post();
5908
5909        mCodec->mPortEOS[kPortIndexInput] =
5910            mCodec->mPortEOS[kPortIndexOutput] = false;
5911
5912        mCodec->mInputEOSResult = OK;
5913
5914        if (mCodec->mSkipCutBuffer != NULL) {
5915            mCodec->mSkipCutBuffer->clear();
5916        }
5917
5918        mCodec->changeState(mCodec->mExecutingState);
5919    }
5920}
5921
5922}  // namespace android
5923