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> ¬ify) 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> ¶ms) { 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(¶ms); 120763b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell params.bEnable = OMX_TRUE; 120863b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell 120963b31698452dbc36f6258c980d7a731518bfd6a0Adam Powell err = mOMX->setParameter( 12107d7580019e44e2e162df01ffff51de20ed0721b3Adam Powell mNode, index, ¶ms, 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(¶ms); 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 ¶ms, 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(¶ms); 2989 params.nPortIndex = kPortIndexOutput; 2990 2991 for (params.nProfileIndex = 0;; ++params.nProfileIndex) { 2992 status_t err = mOMX->getParameter( 2993 mNode, 2994 OMX_IndexParamVideoProfileLevelQuerySupported, 2995 ¶ms, 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 ¶ms) { 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> ¬ify) { 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(¶ms); 3488 params.nPortIndex = portIndex; 3489 3490 CHECK_EQ(mOMX->getParameter( 3491 mNode, OMX_IndexParamAudioPcm, 3492 ¶ms, 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(¶ms); 3519 params.nPortIndex = portIndex; 3520 3521 CHECK_EQ(mOMX->getParameter( 3522 mNode, OMX_IndexParamAudioAac, 3523 ¶ms, 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(¶ms); 3536 params.nPortIndex = portIndex; 3537 3538 CHECK_EQ(mOMX->getParameter( 3539 mNode, OMX_IndexParamAudioAmr, 3540 ¶ms, 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(¶ms); 3562 params.nPortIndex = portIndex; 3563 3564 CHECK_EQ(mOMX->getParameter( 3565 mNode, OMX_IndexParamAudioFlac, 3566 ¶ms, 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(¶ms); 3579 params.nPortIndex = portIndex; 3580 3581 CHECK_EQ(mOMX->getParameter( 3582 mNode, OMX_IndexParamAudioMp3, 3583 ¶ms, 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(¶ms); 3596 params.nPortIndex = portIndex; 3597 3598 CHECK_EQ(mOMX->getParameter( 3599 mNode, OMX_IndexParamAudioVorbis, 3600 ¶ms, 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(¶ms); 3613 params.nPortIndex = portIndex; 3614 3615 CHECK_EQ((status_t)OK, mOMX->getParameter( 3616 mNode, 3617 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, 3618 ¶ms, 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(¶ms); 3631 params.nPortIndex = portIndex; 3632 3633 CHECK_EQ((status_t)OK, mOMX->getParameter( 3634 mNode, 3635 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, 3636 ¶ms, 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(¶ms); 3649 params.nPortIndex = portIndex; 3650 3651 CHECK_EQ((status_t)OK, mOMX->getParameter( 3652 mNode, 3653 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus, 3654 ¶ms, 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(¶ms); 3667 params.nPortIndex = portIndex; 3668 3669 CHECK_EQ((status_t)OK, mOMX->getParameter( 3670 mNode, 3671 (OMX_INDEXTYPE)OMX_IndexParamAudioPcm, 3672 ¶ms, 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(¶ms); 3917 3918 params.nPortIndex = kPortIndexOutput; 3919 params.IntraRefreshVOP = OMX_TRUE; 3920 3921 return mOMX->setConfig( 3922 mNode, 3923 OMX_IndexConfigVideoIntraVOPRefresh, 3924 ¶ms, 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", ×tampNs)) { 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", ×tampNs)) { 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", ¶ms)); 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> ¶ms) { 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