ACodec.cpp revision cd39746f8d83bb3f12e8f613e77c3c3b5f77c077
1a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch/* 2a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch * Copyright (C) 2010 The Android Open Source Project 3a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch * 4a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch * Licensed under the Apache License, Version 2.0 (the "License"); 5a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch * you may not use this file except in compliance with the License. 6a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch * You may obtain a copy of the License at 7a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch * 8a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch * http://www.apache.org/licenses/LICENSE-2.0 9a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch * 10a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch * Unless required by applicable law or agreed to in writing, software 11a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch * distributed under the License is distributed on an "AS IS" BASIS, 12a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch * See the License for the specific language governing permissions and 14a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch * limitations under the License. 15a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch */ 16a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 17a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch//#define LOG_NDEBUG 0 18a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#define LOG_TAG "ACodec" 19a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 20a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#ifdef __LP64__ 21a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS 22a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#endif 23a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 24a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <inttypes.h> 25a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <utils/Trace.h> 26a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 27a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <media/stagefright/ACodec.h> 28a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 29a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <binder/MemoryDealer.h> 30a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 31a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <media/stagefright/foundation/hexdump.h> 32a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <media/stagefright/foundation/ABuffer.h> 33a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <media/stagefright/foundation/ADebug.h> 34a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <media/stagefright/foundation/AMessage.h> 35a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 36a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <media/stagefright/BufferProducerWrapper.h> 375d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include <media/stagefright/MediaCodecList.h> 38a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <media/stagefright/MediaDefs.h> 39a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <media/stagefright/NativeWindowWrapper.h> 40a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <media/stagefright/OMXClient.h> 41a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <media/stagefright/OMXCodec.h> 42a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 43a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <media/hardware/HardwareAPI.h> 44c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 45a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <OMX_AudioExt.h> 46a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <OMX_VideoExt.h> 47a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <OMX_Component.h> 48f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#include <OMX_IndexExt.h> 49f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 50f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#include "include/avc_utils.h" 51f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 52f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liunamespace android { 53f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 54f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// OMX errors are directly mapped into status_t range if 55f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// there is no corresponding MediaError status code. 56f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// Use the statusFromOMXError(int32_t omxError) function. 57f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// 58f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// Currently this is a direct map. 59f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// See frameworks/native/include/media/openmax/OMX_Core.h 60f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// 61f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// Vendor OMX errors from 0x90000000 - 0x9000FFFF 62f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// Extension OMX errors from 0x8F000000 - 0x90000000 63f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// Standard OMX errors from 0x80001000 - 0x80001024 (0x80001024 current) 64f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// 65f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 66f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// returns true if err is a recognized OMX error code. 67f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// as OMX error is OMX_S32, this is an int32_t type 68f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liustatic inline bool isOMXError(int32_t err) { 69f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu return (ERROR_CODEC_MIN <= err && err <= ERROR_CODEC_MAX); 70f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu} 71f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 725d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)// converts an OMX error to a status_t 735d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)static inline status_t statusFromOMXError(int32_t omxError) { 74197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch switch (omxError) { 75197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch case OMX_ErrorInvalidComponentName: 76197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch case OMX_ErrorComponentNotFound: 77197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return NAME_NOT_FOUND; // can trigger illegal argument error for provided names. 78197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch default: 795d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) return isOMXError(omxError) ? omxError : 0; // no translation required 805d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) } 815d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)} 825d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) 835d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)// checks and converts status_t to a non-side-effect status_t 845d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)static inline status_t makeNoSideEffectStatus(status_t err) { 855d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) switch (err) { 865d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) // the following errors have side effects and may come 875d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) // from other code modules. Remap for safety reasons. 885d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) case INVALID_OPERATION: 895d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) case DEAD_OBJECT: 90197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return UNKNOWN_ERROR; 91197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch default: 92197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return err; 93197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch } 94197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch} 955d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) 965d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)template<class T> 975d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)static void InitOMXParams(T *params) { 985d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) params->nSize = sizeof(T); 995d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) params->nVersion.s.nVersionMajor = 1; 1005d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) params->nVersion.s.nVersionMinor = 0; 1015d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) params->nVersion.s.nRevision = 0; 1025d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) params->nVersion.s.nStep = 0; 1035d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)} 1045d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) 105197021e6b966cfb06891637935ef33fff06433d1Ben Murdochstruct CodecObserver : public BnOMXObserver { 106197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch CodecObserver() {} 1075d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) 1085d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) void setNotificationMessage(const sp<AMessage> &msg) { 1095d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) mNotify = msg; 1105d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) } 111a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 112a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // from IOMXObserver 113a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual void onMessage(const omx_message &omx_msg) { 114a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch sp<AMessage> msg = mNotify->dup(); 115a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 116a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch msg->setInt32("type", omx_msg.type); 117a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch msg->setInt32("node", omx_msg.node); 118a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 119a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch switch (omx_msg.type) { 120a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch case omx_message::EVENT: 121a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch { 122a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch msg->setInt32("event", omx_msg.u.event_data.event); 123a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch msg->setInt32("data1", omx_msg.u.event_data.data1); 124a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch msg->setInt32("data2", omx_msg.u.event_data.data2); 125a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch break; 126a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 127a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 128a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch case omx_message::EMPTY_BUFFER_DONE: 129a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch { 130a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch msg->setInt32("buffer", omx_msg.u.buffer_data.buffer); 131a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch break; 132a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 133a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 134a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch case omx_message::FILL_BUFFER_DONE: 135a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch { 136a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch msg->setInt32( 137a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch "buffer", omx_msg.u.extended_buffer_data.buffer); 138a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch msg->setInt32( 139a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch "range_offset", 140a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch omx_msg.u.extended_buffer_data.range_offset); 141a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch msg->setInt32( 142a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch "range_length", 143a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch omx_msg.u.extended_buffer_data.range_length); 144a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch msg->setInt32( 145a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch "flags", 146a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch omx_msg.u.extended_buffer_data.flags); 147a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch msg->setInt64( 148a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch "timestamp", 149a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch omx_msg.u.extended_buffer_data.timestamp); 150a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch break; 151a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 152a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 153a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch default: 154a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch TRESPASS(); 155a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch break; 156a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 157a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 158a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch msg->post(); 159a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 160a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 161a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprotected: 162a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual ~CodecObserver() {} 163a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 164a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprivate: 165a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch sp<AMessage> mNotify; 166a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 167a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch DISALLOW_EVIL_CONSTRUCTORS(CodecObserver); 168a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}; 169a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 170a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch//////////////////////////////////////////////////////////////////////////////// 171a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 172a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstruct ACodec::BaseState : public AState { 173a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch BaseState(ACodec *codec, const sp<AState> &parentState = NULL); 174a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 175a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprotected: 176a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch enum PortMode { 177a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch KEEP_BUFFERS, 178a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch RESUBMIT_BUFFERS, 179a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch FREE_BUFFERS, 180a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch }; 181a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 182a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch ACodec *mCodec; 183a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 184a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual PortMode getPortMode(OMX_U32 portIndex); 185a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 186a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual bool onMessageReceived(const sp<AMessage> &msg); 187a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 188a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 189a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 190a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual void onOutputBufferDrained(const sp<AMessage> &msg); 191a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual void onInputBufferFilled(const sp<AMessage> &msg); 192a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 193a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch void postFillThisBuffer(BufferInfo *info); 194a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 195a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprivate: 196a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch bool onOMXMessage(const sp<AMessage> &msg); 197a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 198a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID); 199a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 200a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch bool onOMXFillBufferDone( 201a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch IOMX::buffer_id bufferID, 202a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch size_t rangeOffset, size_t rangeLength, 203a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch OMX_U32 flags, 204a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch int64_t timeUs); 205a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 206197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch void getMoreInputDataIfPossible(); 207a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 208a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch DISALLOW_EVIL_CONSTRUCTORS(BaseState); 209a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}; 210a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 211a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch//////////////////////////////////////////////////////////////////////////////// 212a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 213a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstruct ACodec::DeathNotifier : public IBinder::DeathRecipient { 214a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch DeathNotifier(const sp<AMessage> ¬ify) 215a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch : mNotify(notify) { 216a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 217a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 218a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual void binderDied(const wp<IBinder> &) { 219197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch mNotify->post(); 220a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 221a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 222a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprotected: 223197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch virtual ~DeathNotifier() {} 224197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 225197021e6b966cfb06891637935ef33fff06433d1Ben Murdochprivate: 226a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch sp<AMessage> mNotify; 227a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 228a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch DISALLOW_EVIL_CONSTRUCTORS(DeathNotifier); 229a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}; 230a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 231a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstruct ACodec::UninitializedState : public ACodec::BaseState { 232a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch UninitializedState(ACodec *codec); 233a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 234a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprotected: 235a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual bool onMessageReceived(const sp<AMessage> &msg); 236a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual void stateEntered(); 237197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 238a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprivate: 239a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch void onSetup(const sp<AMessage> &msg); 240a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch bool onAllocateComponent(const sp<AMessage> &msg); 241a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 242a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch sp<DeathNotifier> mDeathNotifier; 243a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 244a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch DISALLOW_EVIL_CONSTRUCTORS(UninitializedState); 245a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}; 246a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 247a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch//////////////////////////////////////////////////////////////////////////////// 248a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 249a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstruct ACodec::LoadedState : public ACodec::BaseState { 250a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch LoadedState(ACodec *codec); 251a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 252a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprotected: 253197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch virtual bool onMessageReceived(const sp<AMessage> &msg); 254197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch virtual void stateEntered(); 255197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 256197021e6b966cfb06891637935ef33fff06433d1Ben Murdochprivate: 257197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch friend struct ACodec::UninitializedState; 258197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 259197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch bool onConfigureComponent(const sp<AMessage> &msg); 260197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch void onCreateInputSurface(const sp<AMessage> &msg); 261a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch void onStart(); 262a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch void onShutdown(bool keepComponentAllocated); 263a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 264a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch DISALLOW_EVIL_CONSTRUCTORS(LoadedState); 265a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}; 266a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 267a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch//////////////////////////////////////////////////////////////////////////////// 268a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 269a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstruct ACodec::LoadedToIdleState : public ACodec::BaseState { 270a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch LoadedToIdleState(ACodec *codec); 271a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 272a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprotected: 273a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual bool onMessageReceived(const sp<AMessage> &msg); 274a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 275a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual void stateEntered(); 276a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 277a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprivate: 278a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch status_t allocateBuffers(); 279197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 280a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState); 281a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}; 282a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 283a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch//////////////////////////////////////////////////////////////////////////////// 284a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 285a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstruct ACodec::IdleToExecutingState : public ACodec::BaseState { 286a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch IdleToExecutingState(ACodec *codec); 287a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 288a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprotected: 289a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual bool onMessageReceived(const sp<AMessage> &msg); 290a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 291a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual void stateEntered(); 292a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 293a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprivate: 294a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState); 295a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}; 296a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 297a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch//////////////////////////////////////////////////////////////////////////////// 298a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 299a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstruct ACodec::ExecutingState : public ACodec::BaseState { 300a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch ExecutingState(ACodec *codec); 301a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 302a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch void submitRegularOutputBuffers(); 303a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch void submitOutputMetaBuffers(); 304a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch void submitOutputBuffers(); 305a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 306a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // Submit output buffers to the decoder, submit input buffers to client 307a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // to fill with data. 308a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch void resume(); 309a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 310a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // Returns true iff input and output buffers are in play. 311a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch bool active() const { return mActive; } 312f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 313a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprotected: 314f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu virtual PortMode getPortMode(OMX_U32 portIndex); 315a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual bool onMessageReceived(const sp<AMessage> &msg); 316a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual void stateEntered(); 317a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 318a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 3195d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) 320a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprivate: 321a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch bool mActive; 322a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 323a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch DISALLOW_EVIL_CONSTRUCTORS(ExecutingState); 324a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}; 3255d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) 326a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch//////////////////////////////////////////////////////////////////////////////// 327a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 3285d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)struct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState { 329a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch OutputPortSettingsChangedState(ACodec *codec); 330a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 3315d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)protected: 332a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual PortMode getPortMode(OMX_U32 portIndex); 333a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual bool onMessageReceived(const sp<AMessage> &msg); 3345d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) virtual void stateEntered(); 335a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 336a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 3375d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) 338a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprivate: 339a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState); 340a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}; 341a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 342a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch//////////////////////////////////////////////////////////////////////////////// 3435d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) 344a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstruct ACodec::ExecutingToIdleState : public ACodec::BaseState { 345a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch ExecutingToIdleState(ACodec *codec); 346a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 347a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprotected: 348a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual bool onMessageReceived(const sp<AMessage> &msg); 349a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual void stateEntered(); 350a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 351a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 352a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 353a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual void onOutputBufferDrained(const sp<AMessage> &msg); 354a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual void onInputBufferFilled(const sp<AMessage> &msg); 355a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 356a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprivate: 357a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch void changeStateIfWeOwnAllBuffers(); 358a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 359a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch bool mComponentNowIdle; 360a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 361a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState); 362a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}; 363a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 364a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch//////////////////////////////////////////////////////////////////////////////// 365a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 366f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liustruct ACodec::IdleToLoadedState : public ACodec::BaseState { 367f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu IdleToLoadedState(ACodec *codec); 368f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 369e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)protected: 3705d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) virtual bool onMessageReceived(const sp<AMessage> &msg); 371f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu virtual void stateEntered(); 372f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 373f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 374a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 375a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprivate: 376a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState); 377a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}; 378a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 379a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch//////////////////////////////////////////////////////////////////////////////// 380a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 381a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstruct ACodec::FlushingState : public ACodec::BaseState { 382a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch FlushingState(ACodec *codec); 383a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 384a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprotected: 385a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual bool onMessageReceived(const sp<AMessage> &msg); 386a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual void stateEntered(); 387a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 388a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 389a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 390a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual void onOutputBufferDrained(const sp<AMessage> &msg); 391a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch virtual void onInputBufferFilled(const sp<AMessage> &msg); 392a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 393a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochprivate: 3945d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) bool mFlushComplete[2]; 395a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 396a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch void changeStateIfWeOwnAllBuffers(); 397a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 398a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch DISALLOW_EVIL_CONSTRUCTORS(FlushingState); 399a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}; 400a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 401a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch//////////////////////////////////////////////////////////////////////////////// 4025d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) 403a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben MurdochACodec::ACodec() 404a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch : mQuirks(0), 405a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mNode(0), 406a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mSentFormat(false), 407a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mIsEncoder(false), 408a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mUseMetadataOnEncoderOutput(false), 409a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mShutdownInProgress(false), 4105d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) mExplicitShutdown(false), 411a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mEncoderDelay(0), 412a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mEncoderPadding(0), 413a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mRotationDegrees(0), 414a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mChannelMaskPresent(false), 415a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mChannelMask(0), 416a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mDequeueCounter(0), 417a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mStoreMetaDataInOutputBuffers(false), 4185d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) mMetaDataBuffersToSubmit(0), 419a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mRepeatFrameDelayUs(-1ll), 420a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mMaxPtsGapUs(-1ll), 421a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mTimePerFrameUs(-1ll), 422a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mTimePerCaptureUs(-1ll), 423a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mCreateInputBuffersSuspended(false) { 424a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mUninitializedState = new UninitializedState(this); 425e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) mLoadedState = new LoadedState(this); 4265d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) mLoadedToIdleState = new LoadedToIdleState(this); 4275d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) mIdleToExecutingState = new IdleToExecutingState(this); 4285d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) mExecutingState = new ExecutingState(this); 4295d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) 4305d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) mOutputPortSettingsChangedState = 4315d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) new OutputPortSettingsChangedState(this); 4325d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) 4335d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) mExecutingToIdleState = new ExecutingToIdleState(this); 4345d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) mIdleToLoadedState = new IdleToLoadedState(this); 4355d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) mFlushingState = new FlushingState(this); 436a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 437a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false; 438a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mInputEOSResult = OK; 439a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 440a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch changeState(mUninitializedState); 441a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch} 442a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 443a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben MurdochACodec::~ACodec() { 444a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch} 445a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 446a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochvoid ACodec::setNotificationMessage(const sp<AMessage> &msg) { 447a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mNotify = msg; 448a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch} 449a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 450a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochvoid ACodec::initiateSetup(const sp<AMessage> &msg) { 451a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch msg->setWhat(kWhatSetup); 452a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch msg->setTarget(id()); 453a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch msg->post(); 454a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch} 455a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 456a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochvoid ACodec::signalSetParameters(const sp<AMessage> ¶ms) { 457a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch sp<AMessage> msg = new AMessage(kWhatSetParameters, id()); 458f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu msg->setMessage("params", params); 459f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu msg->post(); 460f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu} 461f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 462a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochvoid ACodec::initiateAllocateComponent(const sp<AMessage> &msg) { 463a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch msg->setWhat(kWhatAllocateComponent); 464a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch msg->setTarget(id()); 465a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch msg->post(); 466a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch} 467a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 4685d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)void ACodec::initiateConfigureComponent(const sp<AMessage> &msg) { 4695d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) msg->setWhat(kWhatConfigureComponent); 470e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) msg->setTarget(id()); 4715d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) msg->post(); 4725d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)} 4735d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) 4745d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)void ACodec::initiateCreateInputSurface() { 475a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch (new AMessage(kWhatCreateInputSurface, id()))->post(); 476a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch} 477a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 478a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochvoid ACodec::signalEndOfInputStream() { 479a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch (new AMessage(kWhatSignalEndOfInputStream, id()))->post(); 480a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch} 481a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 482a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochvoid ACodec::initiateStart() { 483a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch (new AMessage(kWhatStart, id()))->post(); 484a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch} 485a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 486a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochvoid ACodec::signalFlush() { 487a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch ALOGV("[%s] signalFlush", mComponentName.c_str()); 488a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch (new AMessage(kWhatFlush, id()))->post(); 489a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch} 490a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 4916f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdochvoid ACodec::signalResume() { 4926f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch (new AMessage(kWhatResume, id()))->post(); 4936f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch} 4946f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch 4956f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdochvoid ACodec::initiateShutdown(bool keepComponentAllocated) { 4966f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch sp<AMessage> msg = new AMessage(kWhatShutdown, id()); 497323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) msg->setInt32("keepComponentAllocated", keepComponentAllocated); 498323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) msg->post(); 499323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)} 500323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) 501323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)void ACodec::signalRequestIDRFrame() { 502323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) (new AMessage(kWhatRequestIDRFrame, id()))->post(); 503f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu} 504f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 505f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu// *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** 506a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// Some codecs may return input buffers before having them processed. 507a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// This causes a halt if we already signaled an EOS on the input 508a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// port. For now keep submitting an output buffer if there was an 509a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// EOS on the input port, but not yet on the output port. 510a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochvoid ACodec::signalSubmitOutputMetaDataBufferIfEOS_workaround() { 511a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (mPortEOS[kPortIndexInput] && !mPortEOS[kPortIndexOutput] && 512a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mMetaDataBuffersToSubmit > 0) { 513a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch (new AMessage(kWhatSubmitOutputMetaDataBufferIfEOS, id()))->post(); 514a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 515a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch} 516a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 517a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstatus_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) { 518a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 519a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 520a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch CHECK(mDealer[portIndex] == NULL); 521a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch CHECK(mBuffers[portIndex].isEmpty()); 522a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 523a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch status_t err; 524a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (mNativeWindow != NULL && portIndex == kPortIndexOutput) { 525a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (mStoreMetaDataInOutputBuffers) { 526a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch err = allocateOutputMetaDataBuffers(); 527a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } else { 528a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch err = allocateOutputBuffersFromNativeWindow(); 529a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 530a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } else { 531a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch OMX_PARAM_PORTDEFINITIONTYPE def; 532a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch InitOMXParams(&def); 533a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch def.nPortIndex = portIndex; 534a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 535a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch err = mOMX->getParameter( 536a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 537a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 538a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (err == OK) { 539a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch ALOGV("[%s] Allocating %u buffers of size %u on %s port", 540a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mComponentName.c_str(), 541a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch def.nBufferCountActual, def.nBufferSize, 542a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch portIndex == kPortIndexInput ? "input" : "output"); 543a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 544a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch size_t totalSize = def.nBufferCountActual * def.nBufferSize; 545a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec"); 546a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 547a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) { 548a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize); 549a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch CHECK(mem.get() != NULL); 550a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 551a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch BufferInfo info; 552a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch info.mStatus = BufferInfo::OWNED_BY_US; 553a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 554a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch uint32_t requiresAllocateBufferBit = 555a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch (portIndex == kPortIndexInput) 556a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch ? OMXCodec::kRequiresAllocateBufferOnInputPorts 557a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch : OMXCodec::kRequiresAllocateBufferOnOutputPorts; 558a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 559a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if ((portIndex == kPortIndexInput && (mFlags & kFlagIsSecure)) 560a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch || mUseMetadataOnEncoderOutput) { 561a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mem.clear(); 562a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 563a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch void *ptr; 564a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch err = mOMX->allocateBuffer( 565a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mNode, portIndex, def.nBufferSize, &info.mBufferID, 566a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch &ptr); 567a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 568a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch int32_t bufSize = mUseMetadataOnEncoderOutput ? 569a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch (4 + sizeof(buffer_handle_t)) : def.nBufferSize; 570a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 571a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch info.mData = new ABuffer(ptr, bufSize); 572a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } else if (mQuirks & requiresAllocateBufferBit) { 573a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch err = mOMX->allocateBufferWithBackup( 574a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mNode, portIndex, mem, &info.mBufferID); 575a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } else { 576a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch err = mOMX->useBuffer(mNode, portIndex, mem, &info.mBufferID); 577a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 578a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 579a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (mem != NULL) { 580a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch info.mData = new ABuffer(mem->pointer(), def.nBufferSize); 581a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 582a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 583a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mBuffers[portIndex].push(info); 584a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 585a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 586a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 587a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 588a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (err != OK) { 589a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return err; 590a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 591a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 592a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch sp<AMessage> notify = mNotify->dup(); 593a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch notify->setInt32("what", CodecBase::kWhatBuffersAllocated); 594f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) 595f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) notify->setInt32("portIndex", portIndex); 596a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 597a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch sp<PortDescription> desc = new PortDescription; 598a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 599a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 600a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch const BufferInfo &info = mBuffers[portIndex][i]; 601a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 602a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch desc->addBuffer(info.mBufferID, info.mData); 603a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 604a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 605a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch notify->setObject("portDesc", desc); 606a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch notify->post(); 607a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 608a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return OK; 609a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch} 610a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 611a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstatus_t ACodec::configureOutputBuffersFromNativeWindow( 612a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch OMX_U32 *bufferCount, OMX_U32 *bufferSize, 613a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch OMX_U32 *minUndequeuedBuffers) { 614a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch OMX_PARAM_PORTDEFINITIONTYPE def; 615a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch InitOMXParams(&def); 616a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch def.nPortIndex = kPortIndexOutput; 617a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 618a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch status_t err = mOMX->getParameter( 619a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 620a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 621a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (err != OK) { 622a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return err; 623a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 624a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 625a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch err = native_window_set_buffers_geometry( 626a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mNativeWindow.get(), 627a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch def.format.video.nFrameWidth, 628a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch def.format.video.nFrameHeight, 629a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch def.format.video.eColorFormat); 630a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 631a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (err != 0) { 632a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch ALOGE("native_window_set_buffers_geometry failed: %s (%d)", 633a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch strerror(-err), -err); 634a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return err; 635a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 636a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 637323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) if (mRotationDegrees != 0) { 638a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch uint32_t transform = 0; 639f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu switch (mRotationDegrees) { 640f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu case 0: transform = 0; break; 641f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu case 90: transform = HAL_TRANSFORM_ROT_90; break; 642f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu case 180: transform = HAL_TRANSFORM_ROT_180; break; 643f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu case 270: transform = HAL_TRANSFORM_ROT_270; break; 644a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch default: transform = 0; break; 645a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 646197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 647f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu if (transform > 0) { 648a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch err = native_window_set_buffers_transform( 649a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mNativeWindow.get(), transform); 650a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (err != 0) { 651a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch ALOGE("native_window_set_buffers_transform failed: %s (%d)", 652a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch strerror(-err), -err); 653a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return err; 654a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 655a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 656a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 657a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 658a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // Set up the native window. 659a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch OMX_U32 usage = 0; 660a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage); 661a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (err != 0) { 662a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch ALOGW("querying usage flags from OMX IL component failed: %d", err); 663a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // XXX: Currently this error is logged, but not fatal. 664a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch usage = 0; 665a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 666a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 667a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (mFlags & kFlagIsSecure) { 668a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch usage |= GRALLOC_USAGE_PROTECTED; 669a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 670a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 671a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // Make sure to check whether either Stagefright or the video decoder 672a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // requested protected buffers. 673a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (usage & GRALLOC_USAGE_PROTECTED) { 674a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // Verify that the ANativeWindow sends images directly to 675c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // SurfaceFlinger. 676a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch int queuesToNativeWindow = 0; 677a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch err = mNativeWindow->query( 678a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mNativeWindow.get(), NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, 679c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) &queuesToNativeWindow); 680c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (err != 0) { 681a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch ALOGE("error authenticating native window: %d", err); 682a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return err; 683c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 684a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (queuesToNativeWindow != 1) { 685a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch ALOGE("native window could not be authenticated"); 686a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return PERMISSION_DENIED; 687a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 688c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 689a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 690a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch err = native_window_set_usage( 691a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mNativeWindow.get(), 692a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP); 693a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 694a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (err != 0) { 695c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err); 696c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) return err; 697c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 698c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 699c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) *minUndequeuedBuffers = 0; 700c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) err = mNativeWindow->query( 701c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, 702c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) (int *)minUndequeuedBuffers); 703c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 704c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (err != 0) { 705c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)", 706a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch strerror(-err), -err); 707a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return err; 708a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 709a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 710a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // FIXME: assume that surface is controlled by app (native window 711a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // returns the number for the case when surface is not controlled by app) 712a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // FIXME2: This means that minUndeqeueudBufs can be 1 larger than reported 713a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // For now, try to allocate 1 more buffer, but don't fail if unsuccessful 714a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 715a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // Use conservative allocation while also trying to reduce starvation 716c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // 717c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // 1. allocate at least nBufferCountMin + minUndequeuedBuffers - that is the 718a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // minimum needed for the consumer to be able to work 719a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // 2. try to allocate two (2) additional buffers to reduce starvation from 720a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // the consumer 721a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // plus an extra buffer to account for incorrect minUndequeuedBufs 722a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch for (OMX_U32 extraBuffers = 2 + 1; /* condition inside loop */; extraBuffers--) { 723a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch OMX_U32 newBufferCount = 724a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch def.nBufferCountMin + *minUndequeuedBuffers + extraBuffers; 725a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch def.nBufferCountActual = newBufferCount; 726a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch err = mOMX->setParameter( 727a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 728a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 729a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (err == OK) { 730a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch *minUndequeuedBuffers += extraBuffers; 731a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch break; 732f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu } 733a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 734f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu ALOGW("[%s] setting nBufferCountActual to %u failed: %d", 735a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mComponentName.c_str(), newBufferCount, err); 736f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /* exit condition */ 737a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (extraBuffers == 0) { 738f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu return err; 739a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 740a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 741a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 742a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch err = native_window_set_buffer_count( 743a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mNativeWindow.get(), def.nBufferCountActual); 744a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 745a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (err != 0) { 746a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), 747a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch -err); 748a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return err; 749a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 750a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 751a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch *bufferCount = def.nBufferCountActual; 752a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch *bufferSize = def.nBufferSize; 753a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return err; 754a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch} 755a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 756a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstatus_t ACodec::allocateOutputBuffersFromNativeWindow() { 757a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers; 758a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch status_t err = configureOutputBuffersFromNativeWindow( 759a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch &bufferCount, &bufferSize, &minUndequeuedBuffers); 760a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (err != 0) 761a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return err; 762a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mNumUndequeuedBuffers = minUndequeuedBuffers; 763a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 764a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch ALOGV("[%s] Allocating %u buffers from a native window of size %u on " 765a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch "output port", 766a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mComponentName.c_str(), bufferCount, bufferSize); 767a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 768a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // Dequeue buffers and send them to OMX 769a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch for (OMX_U32 i = 0; i < bufferCount; i++) { 770a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch ANativeWindowBuffer *buf; 771a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf); 772a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (err != 0) { 773a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err); 774a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch break; 775a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 776a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 777a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false)); 778a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch BufferInfo info; 779a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch info.mStatus = BufferInfo::OWNED_BY_US; 780a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch info.mData = new ABuffer(NULL /* data */, bufferSize /* capacity */); 781a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch info.mGraphicBuffer = graphicBuffer; 782a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mBuffers[kPortIndexOutput].push(info); 783a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 784a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch IOMX::buffer_id bufferId; 785a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer, 786a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch &bufferId); 787a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (err != 0) { 788a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch ALOGE("registering GraphicBuffer %u with OMX IL component failed: " 789a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch "%d", i, err); 790a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch break; 791a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 792a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 793a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId; 794a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 795a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch ALOGV("[%s] Registered graphic buffer with ID %u (pointer = %p)", 796a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mComponentName.c_str(), 797a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch bufferId, graphicBuffer.get()); 798a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 799a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 800a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch OMX_U32 cancelStart; 801a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch OMX_U32 cancelEnd; 802a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 803a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (err != 0) { 804c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // If an error occurred while dequeuing we need to cancel any buffers 805a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // that were dequeued. 806c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) cancelStart = 0; 807a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch cancelEnd = mBuffers[kPortIndexOutput].size(); 808a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } else { 809a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // Return the required minimum undequeued buffers to the native window. 810a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch cancelStart = bufferCount - minUndequeuedBuffers; 811a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch cancelEnd = bufferCount; 812a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 813a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 814a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch for (OMX_U32 i = cancelStart; i < cancelEnd; i++) { 815c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i); 816c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) cancelBufferToNativeWindow(info); 817c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 818c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 819c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) return err; 820c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} 821c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 822c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)status_t ACodec::allocateOutputMetaDataBuffers() { 823c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers; 824a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch status_t err = configureOutputBuffersFromNativeWindow( 825c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) &bufferCount, &bufferSize, &minUndequeuedBuffers); 826c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (err != 0) 827c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) return err; 828c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) mNumUndequeuedBuffers = minUndequeuedBuffers; 829e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) 830c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) ALOGV("[%s] Allocating %u meta buffers on output port", 831c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) mComponentName.c_str(), bufferCount); 832c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 833a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch size_t totalSize = bufferCount * 8; 834a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mDealer[kPortIndexOutput] = new MemoryDealer(totalSize, "ACodec"); 835c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 836f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // Dequeue buffers and send them to OMX 837c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) for (OMX_U32 i = 0; i < bufferCount; i++) { 838c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) BufferInfo info; 839c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) info.mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 840c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) info.mGraphicBuffer = NULL; 841c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) info.mDequeuedAt = mDequeueCounter; 842c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 843c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) sp<IMemory> mem = mDealer[kPortIndexOutput]->allocate( 844c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) sizeof(struct VideoDecoderOutputMetaData)); 845c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) CHECK(mem.get() != NULL); 846c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) info.mData = new ABuffer(mem->pointer(), mem->size()); 847c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 848c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // we use useBuffer for metadata regardless of quirks 849c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) err = mOMX->useBuffer( 850c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) mNode, kPortIndexOutput, mem, &info.mBufferID); 851c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 852c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) mBuffers[kPortIndexOutput].push(info); 853c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 854c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) ALOGV("[%s] allocated meta buffer with ID %u (pointer = %p)", 855c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) mComponentName.c_str(), info.mBufferID, mem->pointer()); 856c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 857c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 858c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) mMetaDataBuffersToSubmit = bufferCount - minUndequeuedBuffers; 859c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) return err; 860c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} 861c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 862c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)status_t ACodec::submitOutputMetaDataBuffer() { 863c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) CHECK(mStoreMetaDataInOutputBuffers); 864c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (mMetaDataBuffersToSubmit == 0) 865c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) return OK; 866a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 867a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch BufferInfo *info = dequeueBufferFromNativeWindow(); 868a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (info == NULL) 869d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) return ERROR_IO; 870d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 871a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch ALOGV("[%s] submitting output meta buffer ID %u for graphic buffer %p", 872a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mComponentName.c_str(), info->mBufferID, info->mGraphicBuffer.get()); 873a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 874a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch --mMetaDataBuffersToSubmit; 875a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch CHECK_EQ(mOMX->fillBuffer(mNode, info->mBufferID), 876a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch (status_t)OK); 877a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 878d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 879a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return OK; 880a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch} 881a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 882a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstatus_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) { 883323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 884323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) 885d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) ALOGV("[%s] Calling cancelBuffer on buffer %u", 886323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) mComponentName.c_str(), info->mBufferID); 887323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) 888323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) int err = mNativeWindow->cancelBuffer( 889323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) mNativeWindow.get(), info->mGraphicBuffer.get(), -1); 890a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 891a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch CHECK_EQ(err, 0); 892d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 893d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 894a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 895a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return OK; 896a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch} 897a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 898a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben MurdochACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() { 899d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) ANativeWindowBuffer *buf; 900d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) int fenceFd = -1; 901d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) CHECK(mNativeWindow.get() != NULL); 902d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) if (native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf) != 0) { 903d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) ALOGE("dequeueBuffer failed."); 904d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) return NULL; 905d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) } 9065d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) 9075d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) BufferInfo *oldest = NULL; 9085d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) { 9095d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) BufferInfo *info = 9105d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) &mBuffers[kPortIndexOutput].editItemAt(i); 9115d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) 9125d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) if (info->mGraphicBuffer != NULL && 9135d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) info->mGraphicBuffer->handle == buf->handle) { 9145d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) CHECK_EQ((int)info->mStatus, 915a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch (int)BufferInfo::OWNED_BY_NATIVE_WINDOW); 916a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 917a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch info->mStatus = BufferInfo::OWNED_BY_US; 918a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 919a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return info; 920323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) } 921197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 922323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW && 923a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch (oldest == NULL || 924a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // avoid potential issues from counter rolling over 925a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mDequeueCounter - info->mDequeuedAt > 926a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mDequeueCounter - oldest->mDequeuedAt)) { 927a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch oldest = info; 928a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 929a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 930a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 931a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (oldest) { 9325d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) CHECK(mStoreMetaDataInOutputBuffers); 9335d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) 9345d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) // discard buffer in LRU info and replace with new buffer 9355d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) oldest->mGraphicBuffer = new GraphicBuffer(buf, false); 936a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch oldest->mStatus = BufferInfo::OWNED_BY_US; 937a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 938a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mOMX->updateGraphicBufferInMeta( 939a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mNode, kPortIndexOutput, oldest->mGraphicBuffer, 940c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) oldest->mBufferID); 941a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 942a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch VideoDecoderOutputMetaData *metaData = 943323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) reinterpret_cast<VideoDecoderOutputMetaData *>( 944c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) oldest->mData->base()); 945a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch CHECK_EQ(metaData->eType, kMetadataBufferTypeGrallocSource); 946a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 947a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)", 948d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) oldest - &mBuffers[kPortIndexOutput][0], 949a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mDequeueCounter - oldest->mDequeuedAt, 950a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch metaData->pHandle, 951e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) oldest->mGraphicBuffer->handle, oldest->mData->base()); 952a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 953a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return oldest; 954a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 955a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 956a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch TRESPASS(); 957f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) 958f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu return NULL; 959197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch} 960f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 961c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) { 962c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) for (size_t i = mBuffers[portIndex].size(); i-- > 0;) { 963c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) CHECK_EQ((status_t)OK, freeBuffer(portIndex, i)); 964a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 965a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 966a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mDealer[portIndex].clear(); 967a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 9686f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch return OK; 9696f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch} 970323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) 971323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)status_t ACodec::freeOutputBuffersNotOwnedByComponent() { 972a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) { 973a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch BufferInfo *info = 974a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch &mBuffers[kPortIndexOutput].editItemAt(i); 975a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 976197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // At this time some buffers may still be with the component 977197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // or being drained. 978c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (info->mStatus != BufferInfo::OWNED_BY_COMPONENT && 979c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) info->mStatus != BufferInfo::OWNED_BY_DOWNSTREAM) { 980c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) CHECK_EQ((status_t)OK, freeBuffer(kPortIndexOutput, i)); 981c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 982a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 983a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 984a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return OK; 985c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} 986c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 987c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) { 988a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 989a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 990a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch CHECK(info->mStatus == BufferInfo::OWNED_BY_US 991323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW); 992a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 993d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) if (portIndex == kPortIndexOutput && mNativeWindow != NULL 994a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch && info->mStatus == BufferInfo::OWNED_BY_US) { 9955d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) CHECK_EQ((status_t)OK, cancelBufferToNativeWindow(info)); 9965d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) } 9975d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) 9985d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) CHECK_EQ(mOMX->freeBuffer( 9995d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) mNode, portIndex, info->mBufferID), 10005d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) (status_t)OK); 10015d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) 10025d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) mBuffers[portIndex].removeAt(i); 1003a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 1004a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return OK; 1005a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch} 1006a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 1007a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben MurdochACodec::BufferInfo *ACodec::findBufferByID( 1008a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch uint32_t portIndex, IOMX::buffer_id bufferID, 1009a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch ssize_t *index) { 1010a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 1011a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 1012a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 1013a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (info->mBufferID == bufferID) { 1014a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (index != NULL) { 1015a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch *index = i; 1016323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) } 1017323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) return info; 1018323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) } 1019a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 1020a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 1021c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) TRESPASS(); 1022a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 1023a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return NULL; 1024a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch} 1025c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 1026a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstatus_t ACodec::setComponentRole( 1027a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch bool isEncoder, const char *mime) { 1028a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch struct MimeToRole { 1029a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch const char *mime; 1030a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch const char *decoderRole; 1031c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) const char *encoderRole; 1032a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch }; 1033a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 1034a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch static const MimeToRole kMimeToRole[] = { 1035a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch { MEDIA_MIMETYPE_AUDIO_MPEG, 1036a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch "audio_decoder.mp3", "audio_encoder.mp3" }, 1037c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I, 1038a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch "audio_decoder.mp1", "audio_encoder.mp1" }, 1039a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II, 1040a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch "audio_decoder.mp2", "audio_encoder.mp2" }, 1041a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch { MEDIA_MIMETYPE_AUDIO_AMR_NB, 1042a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch "audio_decoder.amrnb", "audio_encoder.amrnb" }, 1043c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) { MEDIA_MIMETYPE_AUDIO_AMR_WB, 1044a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch "audio_decoder.amrwb", "audio_encoder.amrwb" }, 1045a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch { MEDIA_MIMETYPE_AUDIO_AAC, 1046a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch "audio_decoder.aac", "audio_encoder.aac" }, 1047a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch { MEDIA_MIMETYPE_AUDIO_VORBIS, 1048a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch "audio_decoder.vorbis", "audio_encoder.vorbis" }, 1049c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) { MEDIA_MIMETYPE_AUDIO_OPUS, 1050a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch "audio_decoder.opus", "audio_encoder.opus" }, 1051a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch { MEDIA_MIMETYPE_AUDIO_G711_MLAW, 1052a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" }, 1053a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch { MEDIA_MIMETYPE_AUDIO_G711_ALAW, 1054a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch "audio_decoder.g711alaw", "audio_encoder.g711alaw" }, 1055c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) { MEDIA_MIMETYPE_VIDEO_AVC, 1056a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch "video_decoder.avc", "video_encoder.avc" }, 1057a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch { MEDIA_MIMETYPE_VIDEO_HEVC, 1058a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch "video_decoder.hevc", "video_encoder.hevc" }, 1059a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch { MEDIA_MIMETYPE_VIDEO_MPEG4, 1060a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch "video_decoder.mpeg4", "video_encoder.mpeg4" }, 1061c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) { MEDIA_MIMETYPE_VIDEO_H263, 1062a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch "video_decoder.h263", "video_encoder.h263" }, 1063a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch { MEDIA_MIMETYPE_VIDEO_VP8, 1064a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch "video_decoder.vp8", "video_encoder.vp8" }, 1065a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch { MEDIA_MIMETYPE_VIDEO_VP9, 1066a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch "video_decoder.vp9", "video_encoder.vp9" }, 1067a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch { MEDIA_MIMETYPE_AUDIO_RAW, 1068a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch "audio_decoder.raw", "audio_encoder.raw" }, 1069a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch { MEDIA_MIMETYPE_AUDIO_FLAC, 1070c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) "audio_decoder.flac", "audio_encoder.flac" }, 1071c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) { MEDIA_MIMETYPE_AUDIO_MSGSM, 1072c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) "audio_decoder.gsm", "audio_encoder.gsm" }, 1073a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch { MEDIA_MIMETYPE_VIDEO_MPEG2, 1074a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch "video_decoder.mpeg2", "video_encoder.mpeg2" }, 1075a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch { MEDIA_MIMETYPE_AUDIO_AC3, 1076a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch "audio_decoder.ac3", "audio_encoder.ac3" }, 1077a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch }; 1078a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 1079a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch static const size_t kNumMimeToRole = 1080a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch sizeof(kMimeToRole) / sizeof(kMimeToRole[0]); 1081a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 1082c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) size_t i; 1083a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch for (i = 0; i < kNumMimeToRole; ++i) { 1084c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (!strcasecmp(mime, kMimeToRole[i].mime)) { 1085c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) break; 1086a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 1087a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 1088c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 1089a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (i == kNumMimeToRole) { 1090a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return ERROR_UNSUPPORTED; 1091a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 1092a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 1093a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch const char *role = 1094a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch isEncoder ? kMimeToRole[i].encoderRole 1095a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch : kMimeToRole[i].decoderRole; 1096a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 1097c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (role != NULL) { 1098c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) OMX_PARAM_COMPONENTROLETYPE roleParams; 1099c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) InitOMXParams(&roleParams); 1100a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 1101a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch strncpy((char *)roleParams.cRole, 1102a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch role, OMX_MAX_STRINGNAME_SIZE - 1); 1103a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 1104a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0'; 1105a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 1106a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch status_t err = mOMX->setParameter( 1107a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mNode, OMX_IndexParamStandardComponentRole, 1108a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch &roleParams, sizeof(roleParams)); 1109c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 1110a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (err != OK) { 1111c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) ALOGW("[%s] Failed to set standard component role '%s'.", 1112c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) mComponentName.c_str(), role); 1113c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 11145d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) return err; 1115197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch } 1116c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 1117197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 1118197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return OK; 1119197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch} 11205d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) 1121a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstatus_t ACodec::configureCodec( 1122a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch const char *mime, const sp<AMessage> &msg) { 1123c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) int32_t encoder; 1124a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (!msg->findInt32("encoder", &encoder)) { 1125a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch encoder = false; 1126c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 1127c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 1128a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch sp<AMessage> inputFormat = new AMessage(); 1129a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch sp<AMessage> outputFormat = new AMessage(); 1130a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 1131a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mIsEncoder = encoder; 1132c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 1133a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch status_t err = setComponentRole(encoder /* isEncoder */, mime); 1134a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 1135c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (err != OK) { 1136a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return err; 1137a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 1138a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 1139a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch int32_t bitRate = 0; 1140a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // FLAC encoder doesn't need a bitrate, other encoders do 1141a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (encoder && strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC) 1142a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch && !msg->findInt32("bitrate", &bitRate)) { 1143a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return INVALID_OPERATION; 1144a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 1145c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 1146c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) int32_t storeMeta; 1147a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (encoder 1148a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch && msg->findInt32("store-metadata-in-buffers", &storeMeta) 1149c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) && storeMeta != 0) { 1150c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexInput, OMX_TRUE); 1151a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 1152a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (err != OK) { 1153c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) ALOGE("[%s] storeMetaDataInBuffers (input) failed w/ err %d", 1154c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) mComponentName.c_str(), err); 1155a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 1156a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return err; 1157a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 1158c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 1159a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 1160a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch int32_t prependSPSPPS = 0; 1161a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (encoder 1162a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch && msg->findInt32("prepend-sps-pps-to-idr-frames", &prependSPSPPS) 1163c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) && prependSPSPPS != 0) { 1164a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch OMX_INDEXTYPE index; 1165a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch err = mOMX->getExtensionIndex( 1166a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mNode, 1167c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) "OMX.google.android.index.prependSPSPPSToIDRFrames", 1168a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch &index); 1169a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 1170a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (err == OK) { 1171a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch PrependSPSPPSToIDRFramesParams params; 1172c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) InitOMXParams(¶ms); 1173197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch params.bEnable = OMX_TRUE; 1174197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 1175197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch err = mOMX->setParameter( 1176a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mNode, index, ¶ms, sizeof(params)); 1177323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) } 1178c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 1179323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) if (err != OK) { 1180323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) ALOGE("Encoder could not be configured to emit SPS/PPS before " 1181323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) "IDR frames. (err %d)", err); 1182323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) 1183323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) return err; 1184323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) } 11855d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) } 11865d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) 11875d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) // Only enable metadata mode on encoder output if encoder can prepend 11885d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) // sps/pps to idr frames, since in metadata mode the bitstream is in an 11895d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) // opaque handle, to which we don't have access. 11905d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) int32_t video = !strncasecmp(mime, "video/", 6); 11915d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) if (encoder && video) { 11925d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) OMX_BOOL enable = (OMX_BOOL) (prependSPSPPS 11935d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) && msg->findInt32("store-metadata-in-buffers-output", &storeMeta) 11945d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) && storeMeta != 0); 11955d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) 11965d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, enable); 11975d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) 1198c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (err != OK) { 11995d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) ALOGE("[%s] storeMetaDataInBuffers (output) failed w/ err %d", 12005d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) mComponentName.c_str(), err); 12015d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) mUseMetadataOnEncoderOutput = 0; 12025d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) } else { 12035d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) mUseMetadataOnEncoderOutput = enable; 12045d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) } 1205c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 12065d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) if (!msg->findInt64( 12075d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) "repeat-previous-frame-after", 12085d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) &mRepeatFrameDelayUs)) { 1209c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) mRepeatFrameDelayUs = -1ll; 12105d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) } 12115d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) 1212a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (!msg->findInt64("max-pts-gap-to-encoder", &mMaxPtsGapUs)) { 1213a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch mMaxPtsGapUs = -1ll; 1214a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 1215 1216 if (!msg->findInt64("time-lapse", &mTimePerCaptureUs)) { 1217 mTimePerCaptureUs = -1ll; 1218 } 1219 1220 if (!msg->findInt32( 1221 "create-input-buffers-suspended", 1222 (int32_t*)&mCreateInputBuffersSuspended)) { 1223 mCreateInputBuffersSuspended = false; 1224 } 1225 } 1226 1227 sp<RefBase> obj; 1228 int32_t haveNativeWindow = msg->findObject("native-window", &obj) && 1229 obj != NULL; 1230 mStoreMetaDataInOutputBuffers = false; 1231 if (video && !encoder) { 1232 inputFormat->setInt32("adaptive-playback", false); 1233 } 1234 if (!encoder && video && haveNativeWindow) { 1235 sp<NativeWindowWrapper> windowWrapper( 1236 static_cast<NativeWindowWrapper *>(obj.get())); 1237 sp<ANativeWindow> nativeWindow = windowWrapper->getNativeWindow(); 1238 1239 int32_t tunneled; 1240 if (msg->findInt32("feature-tunneled-playback", &tunneled) && 1241 tunneled != 0) { 1242 ALOGI("Configuring TUNNELED video playback."); 1243 1244 int64_t audioHwSync = 0; 1245 if (!msg->findInt64("audio-hw-sync", &audioHwSync)) { 1246 ALOGW("No Audio HW Sync provided for video tunnel"); 1247 } 1248 err = configureTunneledVideoPlayback(audioHwSync, nativeWindow); 1249 if (err != OK) { 1250 ALOGE("configureTunneledVideoPlayback(%" PRId64 ",%p) failed!", 1251 audioHwSync, nativeWindow.get()); 1252 return err; 1253 } 1254 1255 inputFormat->setInt32("adaptive-playback", true); 1256 } else { 1257 // Always try to enable dynamic output buffers on native surface 1258 err = mOMX->storeMetaDataInBuffers( 1259 mNode, kPortIndexOutput, OMX_TRUE); 1260 if (err != OK) { 1261 ALOGE("[%s] storeMetaDataInBuffers failed w/ err %d", 1262 mComponentName.c_str(), err); 1263 1264 // if adaptive playback has been requested, try JB fallback 1265 // NOTE: THIS FALLBACK MECHANISM WILL BE REMOVED DUE TO ITS 1266 // LARGE MEMORY REQUIREMENT 1267 1268 // we will not do adaptive playback on software accessed 1269 // surfaces as they never had to respond to changes in the 1270 // crop window, and we don't trust that they will be able to. 1271 int usageBits = 0; 1272 bool canDoAdaptivePlayback; 1273 1274 if (nativeWindow->query( 1275 nativeWindow.get(), 1276 NATIVE_WINDOW_CONSUMER_USAGE_BITS, 1277 &usageBits) != OK) { 1278 canDoAdaptivePlayback = false; 1279 } else { 1280 canDoAdaptivePlayback = 1281 (usageBits & 1282 (GRALLOC_USAGE_SW_READ_MASK | 1283 GRALLOC_USAGE_SW_WRITE_MASK)) == 0; 1284 } 1285 1286 int32_t maxWidth = 0, maxHeight = 0; 1287 if (canDoAdaptivePlayback && 1288 msg->findInt32("max-width", &maxWidth) && 1289 msg->findInt32("max-height", &maxHeight)) { 1290 ALOGV("[%s] prepareForAdaptivePlayback(%dx%d)", 1291 mComponentName.c_str(), maxWidth, maxHeight); 1292 1293 err = mOMX->prepareForAdaptivePlayback( 1294 mNode, kPortIndexOutput, OMX_TRUE, maxWidth, 1295 maxHeight); 1296 ALOGW_IF(err != OK, 1297 "[%s] prepareForAdaptivePlayback failed w/ err %d", 1298 mComponentName.c_str(), err); 1299 1300 if (err == OK) { 1301 inputFormat->setInt32("max-width", maxWidth); 1302 inputFormat->setInt32("max-height", maxHeight); 1303 inputFormat->setInt32("adaptive-playback", true); 1304 } 1305 } 1306 // allow failure 1307 err = OK; 1308 } else { 1309 ALOGV("[%s] storeMetaDataInBuffers succeeded", 1310 mComponentName.c_str()); 1311 mStoreMetaDataInOutputBuffers = true; 1312 inputFormat->setInt32("adaptive-playback", true); 1313 } 1314 1315 int32_t push; 1316 if (msg->findInt32("push-blank-buffers-on-shutdown", &push) 1317 && push != 0) { 1318 mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown; 1319 } 1320 } 1321 1322 int32_t rotationDegrees; 1323 if (msg->findInt32("rotation-degrees", &rotationDegrees)) { 1324 mRotationDegrees = rotationDegrees; 1325 } else { 1326 mRotationDegrees = 0; 1327 } 1328 } 1329 1330 if (video) { 1331 if (encoder) { 1332 err = setupVideoEncoder(mime, msg); 1333 } else { 1334 err = setupVideoDecoder(mime, msg); 1335 } 1336 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) { 1337 int32_t numChannels, sampleRate; 1338 if (!msg->findInt32("channel-count", &numChannels) 1339 || !msg->findInt32("sample-rate", &sampleRate)) { 1340 // Since we did not always check for these, leave them optional 1341 // and have the decoder figure it all out. 1342 err = OK; 1343 } else { 1344 err = setupRawAudioFormat( 1345 encoder ? kPortIndexInput : kPortIndexOutput, 1346 sampleRate, 1347 numChannels); 1348 } 1349 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 1350 int32_t numChannels, sampleRate; 1351 if (!msg->findInt32("channel-count", &numChannels) 1352 || !msg->findInt32("sample-rate", &sampleRate)) { 1353 err = INVALID_OPERATION; 1354 } else { 1355 int32_t isADTS, aacProfile; 1356 int32_t sbrMode; 1357 int32_t maxOutputChannelCount; 1358 drcParams_t drc; 1359 if (!msg->findInt32("is-adts", &isADTS)) { 1360 isADTS = 0; 1361 } 1362 if (!msg->findInt32("aac-profile", &aacProfile)) { 1363 aacProfile = OMX_AUDIO_AACObjectNull; 1364 } 1365 if (!msg->findInt32("aac-sbr-mode", &sbrMode)) { 1366 sbrMode = -1; 1367 } 1368 1369 if (!msg->findInt32("aac-max-output-channel_count", &maxOutputChannelCount)) { 1370 maxOutputChannelCount = -1; 1371 } 1372 if (!msg->findInt32("aac-encoded-target-level", &drc.encodedTargetLevel)) { 1373 // value is unknown 1374 drc.encodedTargetLevel = -1; 1375 } 1376 if (!msg->findInt32("aac-drc-cut-level", &drc.drcCut)) { 1377 // value is unknown 1378 drc.drcCut = -1; 1379 } 1380 if (!msg->findInt32("aac-drc-boost-level", &drc.drcBoost)) { 1381 // value is unknown 1382 drc.drcBoost = -1; 1383 } 1384 if (!msg->findInt32("aac-drc-heavy-compression", &drc.heavyCompression)) { 1385 // value is unknown 1386 drc.heavyCompression = -1; 1387 } 1388 if (!msg->findInt32("aac-target-ref-level", &drc.targetRefLevel)) { 1389 // value is unknown 1390 drc.targetRefLevel = -1; 1391 } 1392 1393 err = setupAACCodec( 1394 encoder, numChannels, sampleRate, bitRate, aacProfile, 1395 isADTS != 0, sbrMode, maxOutputChannelCount, drc); 1396 } 1397 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) { 1398 err = setupAMRCodec(encoder, false /* isWAMR */, bitRate); 1399 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) { 1400 err = setupAMRCodec(encoder, true /* isWAMR */, bitRate); 1401 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW) 1402 || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) { 1403 // These are PCM-like formats with a fixed sample rate but 1404 // a variable number of channels. 1405 1406 int32_t numChannels; 1407 if (!msg->findInt32("channel-count", &numChannels)) { 1408 err = INVALID_OPERATION; 1409 } else { 1410 err = setupG711Codec(encoder, numChannels); 1411 } 1412 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) { 1413 int32_t numChannels, sampleRate, compressionLevel = -1; 1414 if (encoder && 1415 (!msg->findInt32("channel-count", &numChannels) 1416 || !msg->findInt32("sample-rate", &sampleRate))) { 1417 ALOGE("missing channel count or sample rate for FLAC encoder"); 1418 err = INVALID_OPERATION; 1419 } else { 1420 if (encoder) { 1421 if (!msg->findInt32( 1422 "complexity", &compressionLevel) && 1423 !msg->findInt32( 1424 "flac-compression-level", &compressionLevel)) { 1425 compressionLevel = 5; // default FLAC compression level 1426 } else if (compressionLevel < 0) { 1427 ALOGW("compression level %d outside [0..8] range, " 1428 "using 0", 1429 compressionLevel); 1430 compressionLevel = 0; 1431 } else if (compressionLevel > 8) { 1432 ALOGW("compression level %d outside [0..8] range, " 1433 "using 8", 1434 compressionLevel); 1435 compressionLevel = 8; 1436 } 1437 } 1438 err = setupFlacCodec( 1439 encoder, numChannels, sampleRate, compressionLevel); 1440 } 1441 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) { 1442 int32_t numChannels, sampleRate; 1443 if (encoder 1444 || !msg->findInt32("channel-count", &numChannels) 1445 || !msg->findInt32("sample-rate", &sampleRate)) { 1446 err = INVALID_OPERATION; 1447 } else { 1448 err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels); 1449 } 1450 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AC3)) { 1451 int32_t numChannels; 1452 int32_t sampleRate; 1453 if (!msg->findInt32("channel-count", &numChannels) 1454 || !msg->findInt32("sample-rate", &sampleRate)) { 1455 err = INVALID_OPERATION; 1456 } else { 1457 err = setupAC3Codec(encoder, numChannels, sampleRate); 1458 } 1459 } 1460 1461 if (err != OK) { 1462 return err; 1463 } 1464 1465 if (!msg->findInt32("encoder-delay", &mEncoderDelay)) { 1466 mEncoderDelay = 0; 1467 } 1468 1469 if (!msg->findInt32("encoder-padding", &mEncoderPadding)) { 1470 mEncoderPadding = 0; 1471 } 1472 1473 if (msg->findInt32("channel-mask", &mChannelMask)) { 1474 mChannelMaskPresent = true; 1475 } else { 1476 mChannelMaskPresent = false; 1477 } 1478 1479 int32_t maxInputSize; 1480 if (msg->findInt32("max-input-size", &maxInputSize)) { 1481 err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize); 1482 } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) { 1483 err = setMinBufferSize(kPortIndexInput, 8192); // XXX 1484 } 1485 1486 CHECK_EQ(getPortFormat(kPortIndexInput, inputFormat), (status_t)OK); 1487 CHECK_EQ(getPortFormat(kPortIndexOutput, outputFormat), (status_t)OK); 1488 mInputFormat = inputFormat; 1489 mOutputFormat = outputFormat; 1490 1491 return err; 1492} 1493 1494status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) { 1495 OMX_PARAM_PORTDEFINITIONTYPE def; 1496 InitOMXParams(&def); 1497 def.nPortIndex = portIndex; 1498 1499 status_t err = mOMX->getParameter( 1500 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1501 1502 if (err != OK) { 1503 return err; 1504 } 1505 1506 if (def.nBufferSize >= size) { 1507 return OK; 1508 } 1509 1510 def.nBufferSize = size; 1511 1512 err = mOMX->setParameter( 1513 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1514 1515 if (err != OK) { 1516 return err; 1517 } 1518 1519 err = mOMX->getParameter( 1520 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1521 1522 if (err != OK) { 1523 return err; 1524 } 1525 1526 CHECK(def.nBufferSize >= size); 1527 1528 return OK; 1529} 1530 1531status_t ACodec::selectAudioPortFormat( 1532 OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) { 1533 OMX_AUDIO_PARAM_PORTFORMATTYPE format; 1534 InitOMXParams(&format); 1535 1536 format.nPortIndex = portIndex; 1537 for (OMX_U32 index = 0;; ++index) { 1538 format.nIndex = index; 1539 1540 status_t err = mOMX->getParameter( 1541 mNode, OMX_IndexParamAudioPortFormat, 1542 &format, sizeof(format)); 1543 1544 if (err != OK) { 1545 return err; 1546 } 1547 1548 if (format.eEncoding == desiredFormat) { 1549 break; 1550 } 1551 } 1552 1553 return mOMX->setParameter( 1554 mNode, OMX_IndexParamAudioPortFormat, &format, sizeof(format)); 1555} 1556 1557status_t ACodec::setupAACCodec( 1558 bool encoder, int32_t numChannels, int32_t sampleRate, 1559 int32_t bitRate, int32_t aacProfile, bool isADTS, int32_t sbrMode, 1560 int32_t maxOutputChannelCount, const drcParams_t& drc) { 1561 if (encoder && isADTS) { 1562 return -EINVAL; 1563 } 1564 1565 status_t err = setupRawAudioFormat( 1566 encoder ? kPortIndexInput : kPortIndexOutput, 1567 sampleRate, 1568 numChannels); 1569 1570 if (err != OK) { 1571 return err; 1572 } 1573 1574 if (encoder) { 1575 err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC); 1576 1577 if (err != OK) { 1578 return err; 1579 } 1580 1581 OMX_PARAM_PORTDEFINITIONTYPE def; 1582 InitOMXParams(&def); 1583 def.nPortIndex = kPortIndexOutput; 1584 1585 err = mOMX->getParameter( 1586 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1587 1588 if (err != OK) { 1589 return err; 1590 } 1591 1592 def.format.audio.bFlagErrorConcealment = OMX_TRUE; 1593 def.format.audio.eEncoding = OMX_AUDIO_CodingAAC; 1594 1595 err = mOMX->setParameter( 1596 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1597 1598 if (err != OK) { 1599 return err; 1600 } 1601 1602 OMX_AUDIO_PARAM_AACPROFILETYPE profile; 1603 InitOMXParams(&profile); 1604 profile.nPortIndex = kPortIndexOutput; 1605 1606 err = mOMX->getParameter( 1607 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 1608 1609 if (err != OK) { 1610 return err; 1611 } 1612 1613 profile.nChannels = numChannels; 1614 1615 profile.eChannelMode = 1616 (numChannels == 1) 1617 ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo; 1618 1619 profile.nSampleRate = sampleRate; 1620 profile.nBitRate = bitRate; 1621 profile.nAudioBandWidth = 0; 1622 profile.nFrameLength = 0; 1623 profile.nAACtools = OMX_AUDIO_AACToolAll; 1624 profile.nAACERtools = OMX_AUDIO_AACERNone; 1625 profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile; 1626 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF; 1627 switch (sbrMode) { 1628 case 0: 1629 // disable sbr 1630 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR; 1631 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR; 1632 break; 1633 case 1: 1634 // enable single-rate sbr 1635 profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR; 1636 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR; 1637 break; 1638 case 2: 1639 // enable dual-rate sbr 1640 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR; 1641 profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR; 1642 break; 1643 case -1: 1644 // enable both modes -> the codec will decide which mode should be used 1645 profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR; 1646 profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR; 1647 break; 1648 default: 1649 // unsupported sbr mode 1650 return BAD_VALUE; 1651 } 1652 1653 1654 err = mOMX->setParameter( 1655 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 1656 1657 if (err != OK) { 1658 return err; 1659 } 1660 1661 return err; 1662 } 1663 1664 OMX_AUDIO_PARAM_AACPROFILETYPE profile; 1665 InitOMXParams(&profile); 1666 profile.nPortIndex = kPortIndexInput; 1667 1668 err = mOMX->getParameter( 1669 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 1670 1671 if (err != OK) { 1672 return err; 1673 } 1674 1675 profile.nChannels = numChannels; 1676 profile.nSampleRate = sampleRate; 1677 1678 profile.eAACStreamFormat = 1679 isADTS 1680 ? OMX_AUDIO_AACStreamFormatMP4ADTS 1681 : OMX_AUDIO_AACStreamFormatMP4FF; 1682 1683 OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE presentation; 1684 presentation.nMaxOutputChannels = maxOutputChannelCount; 1685 presentation.nDrcCut = drc.drcCut; 1686 presentation.nDrcBoost = drc.drcBoost; 1687 presentation.nHeavyCompression = drc.heavyCompression; 1688 presentation.nTargetReferenceLevel = drc.targetRefLevel; 1689 presentation.nEncodedTargetLevel = drc.encodedTargetLevel; 1690 1691 status_t res = mOMX->setParameter(mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 1692 if (res == OK) { 1693 // optional parameters, will not cause configuration failure 1694 mOMX->setParameter(mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacPresentation, 1695 &presentation, sizeof(presentation)); 1696 } else { 1697 ALOGW("did not set AudioAndroidAacPresentation due to error %d when setting AudioAac", res); 1698 } 1699 return res; 1700} 1701 1702status_t ACodec::setupAC3Codec( 1703 bool encoder, int32_t numChannels, int32_t sampleRate) { 1704 status_t err = setupRawAudioFormat( 1705 encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels); 1706 1707 if (err != OK) { 1708 return err; 1709 } 1710 1711 if (encoder) { 1712 ALOGW("AC3 encoding is not supported."); 1713 return INVALID_OPERATION; 1714 } 1715 1716 OMX_AUDIO_PARAM_ANDROID_AC3TYPE def; 1717 InitOMXParams(&def); 1718 def.nPortIndex = kPortIndexInput; 1719 1720 err = mOMX->getParameter( 1721 mNode, 1722 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, 1723 &def, 1724 sizeof(def)); 1725 1726 if (err != OK) { 1727 return err; 1728 } 1729 1730 def.nChannels = numChannels; 1731 def.nSampleRate = sampleRate; 1732 1733 return mOMX->setParameter( 1734 mNode, 1735 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, 1736 &def, 1737 sizeof(def)); 1738} 1739 1740static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate( 1741 bool isAMRWB, int32_t bps) { 1742 if (isAMRWB) { 1743 if (bps <= 6600) { 1744 return OMX_AUDIO_AMRBandModeWB0; 1745 } else if (bps <= 8850) { 1746 return OMX_AUDIO_AMRBandModeWB1; 1747 } else if (bps <= 12650) { 1748 return OMX_AUDIO_AMRBandModeWB2; 1749 } else if (bps <= 14250) { 1750 return OMX_AUDIO_AMRBandModeWB3; 1751 } else if (bps <= 15850) { 1752 return OMX_AUDIO_AMRBandModeWB4; 1753 } else if (bps <= 18250) { 1754 return OMX_AUDIO_AMRBandModeWB5; 1755 } else if (bps <= 19850) { 1756 return OMX_AUDIO_AMRBandModeWB6; 1757 } else if (bps <= 23050) { 1758 return OMX_AUDIO_AMRBandModeWB7; 1759 } 1760 1761 // 23850 bps 1762 return OMX_AUDIO_AMRBandModeWB8; 1763 } else { // AMRNB 1764 if (bps <= 4750) { 1765 return OMX_AUDIO_AMRBandModeNB0; 1766 } else if (bps <= 5150) { 1767 return OMX_AUDIO_AMRBandModeNB1; 1768 } else if (bps <= 5900) { 1769 return OMX_AUDIO_AMRBandModeNB2; 1770 } else if (bps <= 6700) { 1771 return OMX_AUDIO_AMRBandModeNB3; 1772 } else if (bps <= 7400) { 1773 return OMX_AUDIO_AMRBandModeNB4; 1774 } else if (bps <= 7950) { 1775 return OMX_AUDIO_AMRBandModeNB5; 1776 } else if (bps <= 10200) { 1777 return OMX_AUDIO_AMRBandModeNB6; 1778 } 1779 1780 // 12200 bps 1781 return OMX_AUDIO_AMRBandModeNB7; 1782 } 1783} 1784 1785status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) { 1786 OMX_AUDIO_PARAM_AMRTYPE def; 1787 InitOMXParams(&def); 1788 def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput; 1789 1790 status_t err = 1791 mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); 1792 1793 if (err != OK) { 1794 return err; 1795 } 1796 1797 def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF; 1798 def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate); 1799 1800 err = mOMX->setParameter( 1801 mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); 1802 1803 if (err != OK) { 1804 return err; 1805 } 1806 1807 return setupRawAudioFormat( 1808 encoder ? kPortIndexInput : kPortIndexOutput, 1809 isWAMR ? 16000 : 8000 /* sampleRate */, 1810 1 /* numChannels */); 1811} 1812 1813status_t ACodec::setupG711Codec(bool encoder, int32_t numChannels) { 1814 CHECK(!encoder); // XXX TODO 1815 1816 return setupRawAudioFormat( 1817 kPortIndexInput, 8000 /* sampleRate */, numChannels); 1818} 1819 1820status_t ACodec::setupFlacCodec( 1821 bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel) { 1822 1823 if (encoder) { 1824 OMX_AUDIO_PARAM_FLACTYPE def; 1825 InitOMXParams(&def); 1826 def.nPortIndex = kPortIndexOutput; 1827 1828 // configure compression level 1829 status_t err = mOMX->getParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def)); 1830 if (err != OK) { 1831 ALOGE("setupFlacCodec(): Error %d getting OMX_IndexParamAudioFlac parameter", err); 1832 return err; 1833 } 1834 def.nCompressionLevel = compressionLevel; 1835 err = mOMX->setParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def)); 1836 if (err != OK) { 1837 ALOGE("setupFlacCodec(): Error %d setting OMX_IndexParamAudioFlac parameter", err); 1838 return err; 1839 } 1840 } 1841 1842 return setupRawAudioFormat( 1843 encoder ? kPortIndexInput : kPortIndexOutput, 1844 sampleRate, 1845 numChannels); 1846} 1847 1848status_t ACodec::setupRawAudioFormat( 1849 OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) { 1850 OMX_PARAM_PORTDEFINITIONTYPE def; 1851 InitOMXParams(&def); 1852 def.nPortIndex = portIndex; 1853 1854 status_t err = mOMX->getParameter( 1855 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1856 1857 if (err != OK) { 1858 return err; 1859 } 1860 1861 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; 1862 1863 err = mOMX->setParameter( 1864 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1865 1866 if (err != OK) { 1867 return err; 1868 } 1869 1870 OMX_AUDIO_PARAM_PCMMODETYPE pcmParams; 1871 InitOMXParams(&pcmParams); 1872 pcmParams.nPortIndex = portIndex; 1873 1874 err = mOMX->getParameter( 1875 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); 1876 1877 if (err != OK) { 1878 return err; 1879 } 1880 1881 pcmParams.nChannels = numChannels; 1882 pcmParams.eNumData = OMX_NumericalDataSigned; 1883 pcmParams.bInterleaved = OMX_TRUE; 1884 pcmParams.nBitPerSample = 16; 1885 pcmParams.nSamplingRate = sampleRate; 1886 pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear; 1887 1888 if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) { 1889 return OMX_ErrorNone; 1890 } 1891 1892 return mOMX->setParameter( 1893 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); 1894} 1895 1896status_t ACodec::configureTunneledVideoPlayback( 1897 int64_t audioHwSync, const sp<ANativeWindow> &nativeWindow) { 1898 native_handle_t* sidebandHandle; 1899 1900 status_t err = mOMX->configureVideoTunnelMode( 1901 mNode, kPortIndexOutput, OMX_TRUE, audioHwSync, &sidebandHandle); 1902 if (err != OK) { 1903 ALOGE("configureVideoTunnelMode failed! (err %d).", err); 1904 return err; 1905 } 1906 1907 err = native_window_set_sideband_stream(nativeWindow.get(), sidebandHandle); 1908 if (err != OK) { 1909 ALOGE("native_window_set_sideband_stream(%p) failed! (err %d).", 1910 sidebandHandle, err); 1911 return err; 1912 } 1913 1914 return OK; 1915} 1916 1917status_t ACodec::setVideoPortFormatType( 1918 OMX_U32 portIndex, 1919 OMX_VIDEO_CODINGTYPE compressionFormat, 1920 OMX_COLOR_FORMATTYPE colorFormat) { 1921 OMX_VIDEO_PARAM_PORTFORMATTYPE format; 1922 InitOMXParams(&format); 1923 format.nPortIndex = portIndex; 1924 format.nIndex = 0; 1925 bool found = false; 1926 1927 OMX_U32 index = 0; 1928 for (;;) { 1929 format.nIndex = index; 1930 status_t err = mOMX->getParameter( 1931 mNode, OMX_IndexParamVideoPortFormat, 1932 &format, sizeof(format)); 1933 1934 if (err != OK) { 1935 return err; 1936 } 1937 1938 // substitute back flexible color format to codec supported format 1939 OMX_U32 flexibleEquivalent; 1940 if (compressionFormat == OMX_VIDEO_CodingUnused && 1941 isFlexibleColorFormat( 1942 mOMX, mNode, format.eColorFormat, &flexibleEquivalent) && 1943 colorFormat == flexibleEquivalent) { 1944 ALOGI("[%s] using color format %#x in place of %#x", 1945 mComponentName.c_str(), format.eColorFormat, colorFormat); 1946 colorFormat = format.eColorFormat; 1947 } 1948 1949 // The following assertion is violated by TI's video decoder. 1950 // CHECK_EQ(format.nIndex, index); 1951 1952 if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) { 1953 if (portIndex == kPortIndexInput 1954 && colorFormat == format.eColorFormat) { 1955 // eCompressionFormat does not seem right. 1956 found = true; 1957 break; 1958 } 1959 if (portIndex == kPortIndexOutput 1960 && compressionFormat == format.eCompressionFormat) { 1961 // eColorFormat does not seem right. 1962 found = true; 1963 break; 1964 } 1965 } 1966 1967 if (format.eCompressionFormat == compressionFormat 1968 && format.eColorFormat == colorFormat) { 1969 found = true; 1970 break; 1971 } 1972 1973 ++index; 1974 } 1975 1976 if (!found) { 1977 return UNKNOWN_ERROR; 1978 } 1979 1980 status_t err = mOMX->setParameter( 1981 mNode, OMX_IndexParamVideoPortFormat, 1982 &format, sizeof(format)); 1983 1984 return err; 1985} 1986 1987status_t ACodec::setSupportedOutputFormat() { 1988 OMX_VIDEO_PARAM_PORTFORMATTYPE format; 1989 InitOMXParams(&format); 1990 format.nPortIndex = kPortIndexOutput; 1991 format.nIndex = 0; 1992 1993 status_t err = mOMX->getParameter( 1994 mNode, OMX_IndexParamVideoPortFormat, 1995 &format, sizeof(format)); 1996 CHECK_EQ(err, (status_t)OK); 1997 CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused); 1998 1999 return mOMX->setParameter( 2000 mNode, OMX_IndexParamVideoPortFormat, 2001 &format, sizeof(format)); 2002} 2003 2004static const struct VideoCodingMapEntry { 2005 const char *mMime; 2006 OMX_VIDEO_CODINGTYPE mVideoCodingType; 2007} kVideoCodingMapEntry[] = { 2008 { MEDIA_MIMETYPE_VIDEO_AVC, OMX_VIDEO_CodingAVC }, 2009 { MEDIA_MIMETYPE_VIDEO_HEVC, OMX_VIDEO_CodingHEVC }, 2010 { MEDIA_MIMETYPE_VIDEO_MPEG4, OMX_VIDEO_CodingMPEG4 }, 2011 { MEDIA_MIMETYPE_VIDEO_H263, OMX_VIDEO_CodingH263 }, 2012 { MEDIA_MIMETYPE_VIDEO_MPEG2, OMX_VIDEO_CodingMPEG2 }, 2013 { MEDIA_MIMETYPE_VIDEO_VP8, OMX_VIDEO_CodingVP8 }, 2014 { MEDIA_MIMETYPE_VIDEO_VP9, OMX_VIDEO_CodingVP9 }, 2015}; 2016 2017static status_t GetVideoCodingTypeFromMime( 2018 const char *mime, OMX_VIDEO_CODINGTYPE *codingType) { 2019 for (size_t i = 0; 2020 i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]); 2021 ++i) { 2022 if (!strcasecmp(mime, kVideoCodingMapEntry[i].mMime)) { 2023 *codingType = kVideoCodingMapEntry[i].mVideoCodingType; 2024 return OK; 2025 } 2026 } 2027 2028 *codingType = OMX_VIDEO_CodingUnused; 2029 2030 return ERROR_UNSUPPORTED; 2031} 2032 2033static status_t GetMimeTypeForVideoCoding( 2034 OMX_VIDEO_CODINGTYPE codingType, AString *mime) { 2035 for (size_t i = 0; 2036 i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]); 2037 ++i) { 2038 if (codingType == kVideoCodingMapEntry[i].mVideoCodingType) { 2039 *mime = kVideoCodingMapEntry[i].mMime; 2040 return OK; 2041 } 2042 } 2043 2044 mime->clear(); 2045 2046 return ERROR_UNSUPPORTED; 2047} 2048 2049status_t ACodec::setupVideoDecoder( 2050 const char *mime, const sp<AMessage> &msg) { 2051 int32_t width, height; 2052 if (!msg->findInt32("width", &width) 2053 || !msg->findInt32("height", &height)) { 2054 return INVALID_OPERATION; 2055 } 2056 2057 OMX_VIDEO_CODINGTYPE compressionFormat; 2058 status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat); 2059 2060 if (err != OK) { 2061 return err; 2062 } 2063 2064 err = setVideoPortFormatType( 2065 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused); 2066 2067 if (err != OK) { 2068 return err; 2069 } 2070 2071 int32_t tmp; 2072 if (msg->findInt32("color-format", &tmp)) { 2073 OMX_COLOR_FORMATTYPE colorFormat = 2074 static_cast<OMX_COLOR_FORMATTYPE>(tmp); 2075 err = setVideoPortFormatType( 2076 kPortIndexOutput, OMX_VIDEO_CodingUnused, colorFormat); 2077 if (err != OK) { 2078 ALOGW("[%s] does not support color format %d", 2079 mComponentName.c_str(), colorFormat); 2080 err = setSupportedOutputFormat(); 2081 } 2082 } else { 2083 err = setSupportedOutputFormat(); 2084 } 2085 2086 if (err != OK) { 2087 return err; 2088 } 2089 2090 err = setVideoFormatOnPort( 2091 kPortIndexInput, width, height, compressionFormat); 2092 2093 if (err != OK) { 2094 return err; 2095 } 2096 2097 err = setVideoFormatOnPort( 2098 kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused); 2099 2100 if (err != OK) { 2101 return err; 2102 } 2103 2104 return OK; 2105} 2106 2107status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) { 2108 int32_t tmp; 2109 if (!msg->findInt32("color-format", &tmp)) { 2110 return INVALID_OPERATION; 2111 } 2112 2113 OMX_COLOR_FORMATTYPE colorFormat = 2114 static_cast<OMX_COLOR_FORMATTYPE>(tmp); 2115 2116 status_t err = setVideoPortFormatType( 2117 kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat); 2118 2119 if (err != OK) { 2120 ALOGE("[%s] does not support color format %d", 2121 mComponentName.c_str(), colorFormat); 2122 2123 return err; 2124 } 2125 2126 /* Input port configuration */ 2127 2128 OMX_PARAM_PORTDEFINITIONTYPE def; 2129 InitOMXParams(&def); 2130 2131 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 2132 2133 def.nPortIndex = kPortIndexInput; 2134 2135 err = mOMX->getParameter( 2136 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2137 2138 if (err != OK) { 2139 return err; 2140 } 2141 2142 int32_t width, height, bitrate; 2143 if (!msg->findInt32("width", &width) 2144 || !msg->findInt32("height", &height) 2145 || !msg->findInt32("bitrate", &bitrate)) { 2146 return INVALID_OPERATION; 2147 } 2148 2149 video_def->nFrameWidth = width; 2150 video_def->nFrameHeight = height; 2151 2152 int32_t stride; 2153 if (!msg->findInt32("stride", &stride)) { 2154 stride = width; 2155 } 2156 2157 video_def->nStride = stride; 2158 2159 int32_t sliceHeight; 2160 if (!msg->findInt32("slice-height", &sliceHeight)) { 2161 sliceHeight = height; 2162 } 2163 2164 video_def->nSliceHeight = sliceHeight; 2165 2166 def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2; 2167 2168 float frameRate; 2169 if (!msg->findFloat("frame-rate", &frameRate)) { 2170 int32_t tmp; 2171 if (!msg->findInt32("frame-rate", &tmp)) { 2172 return INVALID_OPERATION; 2173 } 2174 frameRate = (float)tmp; 2175 mTimePerFrameUs = (int64_t) (1000000.0f / frameRate); 2176 } 2177 2178 video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f); 2179 video_def->eCompressionFormat = OMX_VIDEO_CodingUnused; 2180 video_def->eColorFormat = colorFormat; 2181 2182 err = mOMX->setParameter( 2183 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2184 2185 if (err != OK) { 2186 ALOGE("[%s] failed to set input port definition parameters.", 2187 mComponentName.c_str()); 2188 2189 return err; 2190 } 2191 2192 /* Output port configuration */ 2193 2194 OMX_VIDEO_CODINGTYPE compressionFormat; 2195 err = GetVideoCodingTypeFromMime(mime, &compressionFormat); 2196 2197 if (err != OK) { 2198 return err; 2199 } 2200 2201 err = setVideoPortFormatType( 2202 kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused); 2203 2204 if (err != OK) { 2205 ALOGE("[%s] does not support compression format %d", 2206 mComponentName.c_str(), compressionFormat); 2207 2208 return err; 2209 } 2210 2211 def.nPortIndex = kPortIndexOutput; 2212 2213 err = mOMX->getParameter( 2214 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2215 2216 if (err != OK) { 2217 return err; 2218 } 2219 2220 video_def->nFrameWidth = width; 2221 video_def->nFrameHeight = height; 2222 video_def->xFramerate = 0; 2223 video_def->nBitrate = bitrate; 2224 video_def->eCompressionFormat = compressionFormat; 2225 video_def->eColorFormat = OMX_COLOR_FormatUnused; 2226 2227 err = mOMX->setParameter( 2228 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2229 2230 if (err != OK) { 2231 ALOGE("[%s] failed to set output port definition parameters.", 2232 mComponentName.c_str()); 2233 2234 return err; 2235 } 2236 2237 switch (compressionFormat) { 2238 case OMX_VIDEO_CodingMPEG4: 2239 err = setupMPEG4EncoderParameters(msg); 2240 break; 2241 2242 case OMX_VIDEO_CodingH263: 2243 err = setupH263EncoderParameters(msg); 2244 break; 2245 2246 case OMX_VIDEO_CodingAVC: 2247 err = setupAVCEncoderParameters(msg); 2248 break; 2249 2250 case OMX_VIDEO_CodingHEVC: 2251 err = setupHEVCEncoderParameters(msg); 2252 break; 2253 2254 case OMX_VIDEO_CodingVP8: 2255 case OMX_VIDEO_CodingVP9: 2256 err = setupVPXEncoderParameters(msg); 2257 break; 2258 2259 default: 2260 break; 2261 } 2262 2263 ALOGI("setupVideoEncoder succeeded"); 2264 2265 return err; 2266} 2267 2268status_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) { 2269 OMX_VIDEO_PARAM_INTRAREFRESHTYPE params; 2270 InitOMXParams(¶ms); 2271 params.nPortIndex = kPortIndexOutput; 2272 2273 params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode); 2274 2275 if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic || 2276 params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) { 2277 int32_t mbs; 2278 if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) { 2279 return INVALID_OPERATION; 2280 } 2281 params.nCirMBs = mbs; 2282 } 2283 2284 if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive || 2285 params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) { 2286 int32_t mbs; 2287 if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) { 2288 return INVALID_OPERATION; 2289 } 2290 params.nAirMBs = mbs; 2291 2292 int32_t ref; 2293 if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) { 2294 return INVALID_OPERATION; 2295 } 2296 params.nAirRef = ref; 2297 } 2298 2299 status_t err = mOMX->setParameter( 2300 mNode, OMX_IndexParamVideoIntraRefresh, 2301 ¶ms, sizeof(params)); 2302 return err; 2303} 2304 2305static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) { 2306 if (iFramesInterval < 0) { 2307 return 0xFFFFFFFF; 2308 } else if (iFramesInterval == 0) { 2309 return 0; 2310 } 2311 OMX_U32 ret = frameRate * iFramesInterval; 2312 CHECK(ret > 1); 2313 return ret; 2314} 2315 2316static OMX_VIDEO_CONTROLRATETYPE getBitrateMode(const sp<AMessage> &msg) { 2317 int32_t tmp; 2318 if (!msg->findInt32("bitrate-mode", &tmp)) { 2319 return OMX_Video_ControlRateVariable; 2320 } 2321 2322 return static_cast<OMX_VIDEO_CONTROLRATETYPE>(tmp); 2323} 2324 2325status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) { 2326 int32_t bitrate, iFrameInterval; 2327 if (!msg->findInt32("bitrate", &bitrate) 2328 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 2329 return INVALID_OPERATION; 2330 } 2331 2332 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 2333 2334 float frameRate; 2335 if (!msg->findFloat("frame-rate", &frameRate)) { 2336 int32_t tmp; 2337 if (!msg->findInt32("frame-rate", &tmp)) { 2338 return INVALID_OPERATION; 2339 } 2340 frameRate = (float)tmp; 2341 } 2342 2343 OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type; 2344 InitOMXParams(&mpeg4type); 2345 mpeg4type.nPortIndex = kPortIndexOutput; 2346 2347 status_t err = mOMX->getParameter( 2348 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); 2349 2350 if (err != OK) { 2351 return err; 2352 } 2353 2354 mpeg4type.nSliceHeaderSpacing = 0; 2355 mpeg4type.bSVH = OMX_FALSE; 2356 mpeg4type.bGov = OMX_FALSE; 2357 2358 mpeg4type.nAllowedPictureTypes = 2359 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 2360 2361 mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 2362 if (mpeg4type.nPFrames == 0) { 2363 mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 2364 } 2365 mpeg4type.nBFrames = 0; 2366 mpeg4type.nIDCVLCThreshold = 0; 2367 mpeg4type.bACPred = OMX_TRUE; 2368 mpeg4type.nMaxPacketSize = 256; 2369 mpeg4type.nTimeIncRes = 1000; 2370 mpeg4type.nHeaderExtension = 0; 2371 mpeg4type.bReversibleVLC = OMX_FALSE; 2372 2373 int32_t profile; 2374 if (msg->findInt32("profile", &profile)) { 2375 int32_t level; 2376 if (!msg->findInt32("level", &level)) { 2377 return INVALID_OPERATION; 2378 } 2379 2380 err = verifySupportForProfileAndLevel(profile, level); 2381 2382 if (err != OK) { 2383 return err; 2384 } 2385 2386 mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile); 2387 mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level); 2388 } 2389 2390 err = mOMX->setParameter( 2391 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); 2392 2393 if (err != OK) { 2394 return err; 2395 } 2396 2397 err = configureBitrate(bitrate, bitrateMode); 2398 2399 if (err != OK) { 2400 return err; 2401 } 2402 2403 return setupErrorCorrectionParameters(); 2404} 2405 2406status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) { 2407 int32_t bitrate, iFrameInterval; 2408 if (!msg->findInt32("bitrate", &bitrate) 2409 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 2410 return INVALID_OPERATION; 2411 } 2412 2413 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 2414 2415 float frameRate; 2416 if (!msg->findFloat("frame-rate", &frameRate)) { 2417 int32_t tmp; 2418 if (!msg->findInt32("frame-rate", &tmp)) { 2419 return INVALID_OPERATION; 2420 } 2421 frameRate = (float)tmp; 2422 } 2423 2424 OMX_VIDEO_PARAM_H263TYPE h263type; 2425 InitOMXParams(&h263type); 2426 h263type.nPortIndex = kPortIndexOutput; 2427 2428 status_t err = mOMX->getParameter( 2429 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); 2430 2431 if (err != OK) { 2432 return err; 2433 } 2434 2435 h263type.nAllowedPictureTypes = 2436 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 2437 2438 h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 2439 if (h263type.nPFrames == 0) { 2440 h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 2441 } 2442 h263type.nBFrames = 0; 2443 2444 int32_t profile; 2445 if (msg->findInt32("profile", &profile)) { 2446 int32_t level; 2447 if (!msg->findInt32("level", &level)) { 2448 return INVALID_OPERATION; 2449 } 2450 2451 err = verifySupportForProfileAndLevel(profile, level); 2452 2453 if (err != OK) { 2454 return err; 2455 } 2456 2457 h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile); 2458 h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level); 2459 } 2460 2461 h263type.bPLUSPTYPEAllowed = OMX_FALSE; 2462 h263type.bForceRoundingTypeToZero = OMX_FALSE; 2463 h263type.nPictureHeaderRepetition = 0; 2464 h263type.nGOBHeaderInterval = 0; 2465 2466 err = mOMX->setParameter( 2467 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); 2468 2469 if (err != OK) { 2470 return err; 2471 } 2472 2473 err = configureBitrate(bitrate, bitrateMode); 2474 2475 if (err != OK) { 2476 return err; 2477 } 2478 2479 return setupErrorCorrectionParameters(); 2480} 2481 2482status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) { 2483 int32_t bitrate, iFrameInterval; 2484 if (!msg->findInt32("bitrate", &bitrate) 2485 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 2486 return INVALID_OPERATION; 2487 } 2488 2489 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 2490 2491 float frameRate; 2492 if (!msg->findFloat("frame-rate", &frameRate)) { 2493 int32_t tmp; 2494 if (!msg->findInt32("frame-rate", &tmp)) { 2495 return INVALID_OPERATION; 2496 } 2497 frameRate = (float)tmp; 2498 } 2499 2500 status_t err = OK; 2501 int32_t intraRefreshMode = 0; 2502 if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) { 2503 err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode); 2504 if (err != OK) { 2505 ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x", 2506 err, intraRefreshMode); 2507 return err; 2508 } 2509 } 2510 2511 OMX_VIDEO_PARAM_AVCTYPE h264type; 2512 InitOMXParams(&h264type); 2513 h264type.nPortIndex = kPortIndexOutput; 2514 2515 err = mOMX->getParameter( 2516 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 2517 2518 if (err != OK) { 2519 return err; 2520 } 2521 2522 h264type.nAllowedPictureTypes = 2523 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 2524 2525 int32_t profile; 2526 if (msg->findInt32("profile", &profile)) { 2527 int32_t level; 2528 if (!msg->findInt32("level", &level)) { 2529 return INVALID_OPERATION; 2530 } 2531 2532 err = verifySupportForProfileAndLevel(profile, level); 2533 2534 if (err != OK) { 2535 return err; 2536 } 2537 2538 h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile); 2539 h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level); 2540 } 2541 2542 // XXX 2543 if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) { 2544 ALOGW("Use baseline profile instead of %d for AVC recording", 2545 h264type.eProfile); 2546 h264type.eProfile = OMX_VIDEO_AVCProfileBaseline; 2547 } 2548 2549 if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) { 2550 h264type.nSliceHeaderSpacing = 0; 2551 h264type.bUseHadamard = OMX_TRUE; 2552 h264type.nRefFrames = 1; 2553 h264type.nBFrames = 0; 2554 h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 2555 if (h264type.nPFrames == 0) { 2556 h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 2557 } 2558 h264type.nRefIdx10ActiveMinus1 = 0; 2559 h264type.nRefIdx11ActiveMinus1 = 0; 2560 h264type.bEntropyCodingCABAC = OMX_FALSE; 2561 h264type.bWeightedPPrediction = OMX_FALSE; 2562 h264type.bconstIpred = OMX_FALSE; 2563 h264type.bDirect8x8Inference = OMX_FALSE; 2564 h264type.bDirectSpatialTemporal = OMX_FALSE; 2565 h264type.nCabacInitIdc = 0; 2566 } 2567 2568 if (h264type.nBFrames != 0) { 2569 h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB; 2570 } 2571 2572 h264type.bEnableUEP = OMX_FALSE; 2573 h264type.bEnableFMO = OMX_FALSE; 2574 h264type.bEnableASO = OMX_FALSE; 2575 h264type.bEnableRS = OMX_FALSE; 2576 h264type.bFrameMBsOnly = OMX_TRUE; 2577 h264type.bMBAFF = OMX_FALSE; 2578 h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; 2579 2580 err = mOMX->setParameter( 2581 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 2582 2583 if (err != OK) { 2584 return err; 2585 } 2586 2587 return configureBitrate(bitrate, bitrateMode); 2588} 2589 2590status_t ACodec::setupHEVCEncoderParameters(const sp<AMessage> &msg) { 2591 int32_t bitrate, iFrameInterval; 2592 if (!msg->findInt32("bitrate", &bitrate) 2593 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 2594 return INVALID_OPERATION; 2595 } 2596 2597 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 2598 2599 float frameRate; 2600 if (!msg->findFloat("frame-rate", &frameRate)) { 2601 int32_t tmp; 2602 if (!msg->findInt32("frame-rate", &tmp)) { 2603 return INVALID_OPERATION; 2604 } 2605 frameRate = (float)tmp; 2606 } 2607 2608 OMX_VIDEO_PARAM_HEVCTYPE hevcType; 2609 InitOMXParams(&hevcType); 2610 hevcType.nPortIndex = kPortIndexOutput; 2611 2612 status_t err = OK; 2613 err = mOMX->getParameter( 2614 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType)); 2615 if (err != OK) { 2616 return err; 2617 } 2618 2619 int32_t profile; 2620 if (msg->findInt32("profile", &profile)) { 2621 int32_t level; 2622 if (!msg->findInt32("level", &level)) { 2623 return INVALID_OPERATION; 2624 } 2625 2626 err = verifySupportForProfileAndLevel(profile, level); 2627 if (err != OK) { 2628 return err; 2629 } 2630 2631 hevcType.eProfile = static_cast<OMX_VIDEO_HEVCPROFILETYPE>(profile); 2632 hevcType.eLevel = static_cast<OMX_VIDEO_HEVCLEVELTYPE>(level); 2633 } 2634 2635 // TODO: Need OMX structure definition for setting iFrameInterval 2636 2637 err = mOMX->setParameter( 2638 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType)); 2639 if (err != OK) { 2640 return err; 2641 } 2642 2643 return configureBitrate(bitrate, bitrateMode); 2644} 2645 2646status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg) { 2647 int32_t bitrate; 2648 int32_t iFrameInterval = 0; 2649 size_t tsLayers = 0; 2650 OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE pattern = 2651 OMX_VIDEO_VPXTemporalLayerPatternNone; 2652 static const uint32_t kVp8LayerRateAlloction 2653 [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] 2654 [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] = { 2655 {100, 100, 100}, // 1 layer 2656 { 60, 100, 100}, // 2 layers {60%, 40%} 2657 { 40, 60, 100}, // 3 layers {40%, 20%, 40%} 2658 }; 2659 if (!msg->findInt32("bitrate", &bitrate)) { 2660 return INVALID_OPERATION; 2661 } 2662 msg->findInt32("i-frame-interval", &iFrameInterval); 2663 2664 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 2665 2666 float frameRate; 2667 if (!msg->findFloat("frame-rate", &frameRate)) { 2668 int32_t tmp; 2669 if (!msg->findInt32("frame-rate", &tmp)) { 2670 return INVALID_OPERATION; 2671 } 2672 frameRate = (float)tmp; 2673 } 2674 2675 AString tsSchema; 2676 if (msg->findString("ts-schema", &tsSchema)) { 2677 if (tsSchema == "webrtc.vp8.1-layer") { 2678 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC; 2679 tsLayers = 1; 2680 } else if (tsSchema == "webrtc.vp8.2-layer") { 2681 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC; 2682 tsLayers = 2; 2683 } else if (tsSchema == "webrtc.vp8.3-layer") { 2684 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC; 2685 tsLayers = 3; 2686 } else { 2687 ALOGW("Unsupported ts-schema [%s]", tsSchema.c_str()); 2688 } 2689 } 2690 2691 OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type; 2692 InitOMXParams(&vp8type); 2693 vp8type.nPortIndex = kPortIndexOutput; 2694 status_t err = mOMX->getParameter( 2695 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder, 2696 &vp8type, sizeof(vp8type)); 2697 2698 if (err == OK) { 2699 if (iFrameInterval > 0) { 2700 vp8type.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate); 2701 } 2702 vp8type.eTemporalPattern = pattern; 2703 vp8type.nTemporalLayerCount = tsLayers; 2704 if (tsLayers > 0) { 2705 for (size_t i = 0; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) { 2706 vp8type.nTemporalLayerBitrateRatio[i] = 2707 kVp8LayerRateAlloction[tsLayers - 1][i]; 2708 } 2709 } 2710 if (bitrateMode == OMX_Video_ControlRateConstant) { 2711 vp8type.nMinQuantizer = 2; 2712 vp8type.nMaxQuantizer = 63; 2713 } 2714 2715 err = mOMX->setParameter( 2716 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder, 2717 &vp8type, sizeof(vp8type)); 2718 if (err != OK) { 2719 ALOGW("Extended VP8 parameters set failed: %d", err); 2720 } 2721 } 2722 2723 return configureBitrate(bitrate, bitrateMode); 2724} 2725 2726status_t ACodec::verifySupportForProfileAndLevel( 2727 int32_t profile, int32_t level) { 2728 OMX_VIDEO_PARAM_PROFILELEVELTYPE params; 2729 InitOMXParams(¶ms); 2730 params.nPortIndex = kPortIndexOutput; 2731 2732 for (params.nProfileIndex = 0;; ++params.nProfileIndex) { 2733 status_t err = mOMX->getParameter( 2734 mNode, 2735 OMX_IndexParamVideoProfileLevelQuerySupported, 2736 ¶ms, 2737 sizeof(params)); 2738 2739 if (err != OK) { 2740 return err; 2741 } 2742 2743 int32_t supportedProfile = static_cast<int32_t>(params.eProfile); 2744 int32_t supportedLevel = static_cast<int32_t>(params.eLevel); 2745 2746 if (profile == supportedProfile && level <= supportedLevel) { 2747 return OK; 2748 } 2749 } 2750} 2751 2752status_t ACodec::configureBitrate( 2753 int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode) { 2754 OMX_VIDEO_PARAM_BITRATETYPE bitrateType; 2755 InitOMXParams(&bitrateType); 2756 bitrateType.nPortIndex = kPortIndexOutput; 2757 2758 status_t err = mOMX->getParameter( 2759 mNode, OMX_IndexParamVideoBitrate, 2760 &bitrateType, sizeof(bitrateType)); 2761 2762 if (err != OK) { 2763 return err; 2764 } 2765 2766 bitrateType.eControlRate = bitrateMode; 2767 bitrateType.nTargetBitrate = bitrate; 2768 2769 return mOMX->setParameter( 2770 mNode, OMX_IndexParamVideoBitrate, 2771 &bitrateType, sizeof(bitrateType)); 2772} 2773 2774status_t ACodec::setupErrorCorrectionParameters() { 2775 OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType; 2776 InitOMXParams(&errorCorrectionType); 2777 errorCorrectionType.nPortIndex = kPortIndexOutput; 2778 2779 status_t err = mOMX->getParameter( 2780 mNode, OMX_IndexParamVideoErrorCorrection, 2781 &errorCorrectionType, sizeof(errorCorrectionType)); 2782 2783 if (err != OK) { 2784 return OK; // Optional feature. Ignore this failure 2785 } 2786 2787 errorCorrectionType.bEnableHEC = OMX_FALSE; 2788 errorCorrectionType.bEnableResync = OMX_TRUE; 2789 errorCorrectionType.nResynchMarkerSpacing = 256; 2790 errorCorrectionType.bEnableDataPartitioning = OMX_FALSE; 2791 errorCorrectionType.bEnableRVLC = OMX_FALSE; 2792 2793 return mOMX->setParameter( 2794 mNode, OMX_IndexParamVideoErrorCorrection, 2795 &errorCorrectionType, sizeof(errorCorrectionType)); 2796} 2797 2798status_t ACodec::setVideoFormatOnPort( 2799 OMX_U32 portIndex, 2800 int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) { 2801 OMX_PARAM_PORTDEFINITIONTYPE def; 2802 InitOMXParams(&def); 2803 def.nPortIndex = portIndex; 2804 2805 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 2806 2807 status_t err = mOMX->getParameter( 2808 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2809 2810 CHECK_EQ(err, (status_t)OK); 2811 2812 if (portIndex == kPortIndexInput) { 2813 // XXX Need a (much) better heuristic to compute input buffer sizes. 2814 const size_t X = 64 * 1024; 2815 if (def.nBufferSize < X) { 2816 def.nBufferSize = X; 2817 } 2818 } 2819 2820 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo); 2821 2822 video_def->nFrameWidth = width; 2823 video_def->nFrameHeight = height; 2824 2825 if (portIndex == kPortIndexInput) { 2826 video_def->eCompressionFormat = compressionFormat; 2827 video_def->eColorFormat = OMX_COLOR_FormatUnused; 2828 } 2829 2830 err = mOMX->setParameter( 2831 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2832 2833 return err; 2834} 2835 2836status_t ACodec::initNativeWindow() { 2837 if (mNativeWindow != NULL) { 2838 return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE); 2839 } 2840 2841 mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE); 2842 return OK; 2843} 2844 2845size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const { 2846 size_t n = 0; 2847 2848 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 2849 const BufferInfo &info = mBuffers[portIndex].itemAt(i); 2850 2851 if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) { 2852 ++n; 2853 } 2854 } 2855 2856 return n; 2857} 2858 2859size_t ACodec::countBuffersOwnedByNativeWindow() const { 2860 size_t n = 0; 2861 2862 for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) { 2863 const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i); 2864 2865 if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 2866 ++n; 2867 } 2868 } 2869 2870 return n; 2871} 2872 2873void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() { 2874 if (mNativeWindow == NULL) { 2875 return; 2876 } 2877 2878 while (countBuffersOwnedByNativeWindow() > mNumUndequeuedBuffers 2879 && dequeueBufferFromNativeWindow() != NULL) { 2880 // these buffers will be submitted as regular buffers; account for this 2881 if (mStoreMetaDataInOutputBuffers && mMetaDataBuffersToSubmit > 0) { 2882 --mMetaDataBuffersToSubmit; 2883 } 2884 } 2885} 2886 2887bool ACodec::allYourBuffersAreBelongToUs( 2888 OMX_U32 portIndex) { 2889 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 2890 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 2891 2892 if (info->mStatus != BufferInfo::OWNED_BY_US 2893 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) { 2894 ALOGV("[%s] Buffer %u on port %u still has status %d", 2895 mComponentName.c_str(), 2896 info->mBufferID, portIndex, info->mStatus); 2897 return false; 2898 } 2899 } 2900 2901 return true; 2902} 2903 2904bool ACodec::allYourBuffersAreBelongToUs() { 2905 return allYourBuffersAreBelongToUs(kPortIndexInput) 2906 && allYourBuffersAreBelongToUs(kPortIndexOutput); 2907} 2908 2909void ACodec::deferMessage(const sp<AMessage> &msg) { 2910 bool wasEmptyBefore = mDeferredQueue.empty(); 2911 mDeferredQueue.push_back(msg); 2912} 2913 2914void ACodec::processDeferredMessages() { 2915 List<sp<AMessage> > queue = mDeferredQueue; 2916 mDeferredQueue.clear(); 2917 2918 List<sp<AMessage> >::iterator it = queue.begin(); 2919 while (it != queue.end()) { 2920 onMessageReceived(*it++); 2921 } 2922} 2923 2924// static 2925bool ACodec::describeDefaultColorFormat(DescribeColorFormatParams ¶ms) { 2926 MediaImage &image = params.sMediaImage; 2927 memset(&image, 0, sizeof(image)); 2928 2929 image.mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN; 2930 image.mNumPlanes = 0; 2931 2932 const OMX_COLOR_FORMATTYPE fmt = params.eColorFormat; 2933 // we need stride and slice-height to be non-zero 2934 if (params.nStride == 0 || params.nSliceHeight == 0) { 2935 ALOGW("cannot describe color format 0x%x = %d with stride=%u and sliceHeight=%u", 2936 fmt, fmt, params.nStride, params.nSliceHeight); 2937 return false; 2938 } 2939 2940 image.mWidth = params.nFrameWidth; 2941 image.mHeight = params.nFrameHeight; 2942 2943 // only supporting YUV420 2944 if (fmt != OMX_COLOR_FormatYUV420Planar && 2945 fmt != OMX_COLOR_FormatYUV420PackedPlanar && 2946 fmt != OMX_COLOR_FormatYUV420SemiPlanar && 2947 fmt != OMX_COLOR_FormatYUV420PackedSemiPlanar) { 2948 ALOGW("do not know color format 0x%x = %d", fmt, fmt); 2949 return false; 2950 } 2951 2952 // set-up YUV format 2953 image.mType = MediaImage::MEDIA_IMAGE_TYPE_YUV; 2954 image.mNumPlanes = 3; 2955 image.mBitDepth = 8; 2956 image.mPlane[image.Y].mOffset = 0; 2957 image.mPlane[image.Y].mColInc = 1; 2958 image.mPlane[image.Y].mRowInc = params.nStride; 2959 image.mPlane[image.Y].mHorizSubsampling = 1; 2960 image.mPlane[image.Y].mVertSubsampling = 1; 2961 2962 switch (fmt) { 2963 case OMX_COLOR_FormatYUV420Planar: // used for YV12 2964 case OMX_COLOR_FormatYUV420PackedPlanar: 2965 image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight; 2966 image.mPlane[image.U].mColInc = 1; 2967 image.mPlane[image.U].mRowInc = params.nStride / 2; 2968 image.mPlane[image.U].mHorizSubsampling = 2; 2969 image.mPlane[image.U].mVertSubsampling = 2; 2970 2971 image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset 2972 + (params.nStride * params.nSliceHeight / 4); 2973 image.mPlane[image.V].mColInc = 1; 2974 image.mPlane[image.V].mRowInc = params.nStride / 2; 2975 image.mPlane[image.V].mHorizSubsampling = 2; 2976 image.mPlane[image.V].mVertSubsampling = 2; 2977 break; 2978 2979 case OMX_COLOR_FormatYUV420SemiPlanar: 2980 // FIXME: NV21 for sw-encoder, NV12 for decoder and hw-encoder 2981 case OMX_COLOR_FormatYUV420PackedSemiPlanar: 2982 // NV12 2983 image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight; 2984 image.mPlane[image.U].mColInc = 2; 2985 image.mPlane[image.U].mRowInc = params.nStride; 2986 image.mPlane[image.U].mHorizSubsampling = 2; 2987 image.mPlane[image.U].mVertSubsampling = 2; 2988 2989 image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset + 1; 2990 image.mPlane[image.V].mColInc = 2; 2991 image.mPlane[image.V].mRowInc = params.nStride; 2992 image.mPlane[image.V].mHorizSubsampling = 2; 2993 image.mPlane[image.V].mVertSubsampling = 2; 2994 break; 2995 2996 default: 2997 TRESPASS(); 2998 } 2999 return true; 3000} 3001 3002// static 3003bool ACodec::describeColorFormat( 3004 const sp<IOMX> &omx, IOMX::node_id node, 3005 DescribeColorFormatParams &describeParams) 3006{ 3007 OMX_INDEXTYPE describeColorFormatIndex; 3008 if (omx->getExtensionIndex( 3009 node, "OMX.google.android.index.describeColorFormat", 3010 &describeColorFormatIndex) != OK || 3011 omx->getParameter( 3012 node, describeColorFormatIndex, 3013 &describeParams, sizeof(describeParams)) != OK) { 3014 return describeDefaultColorFormat(describeParams); 3015 } 3016 return describeParams.sMediaImage.mType != 3017 MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN; 3018} 3019 3020// static 3021bool ACodec::isFlexibleColorFormat( 3022 const sp<IOMX> &omx, IOMX::node_id node, 3023 uint32_t colorFormat, OMX_U32 *flexibleEquivalent) { 3024 DescribeColorFormatParams describeParams; 3025 InitOMXParams(&describeParams); 3026 describeParams.eColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat; 3027 // reasonable dummy values 3028 describeParams.nFrameWidth = 128; 3029 describeParams.nFrameHeight = 128; 3030 describeParams.nStride = 128; 3031 describeParams.nSliceHeight = 128; 3032 3033 CHECK(flexibleEquivalent != NULL); 3034 3035 if (!describeColorFormat(omx, node, describeParams)) { 3036 return false; 3037 } 3038 3039 const MediaImage &img = describeParams.sMediaImage; 3040 if (img.mType == MediaImage::MEDIA_IMAGE_TYPE_YUV) { 3041 if (img.mNumPlanes != 3 || 3042 img.mPlane[img.Y].mHorizSubsampling != 1 || 3043 img.mPlane[img.Y].mVertSubsampling != 1) { 3044 return false; 3045 } 3046 3047 // YUV 420 3048 if (img.mPlane[img.U].mHorizSubsampling == 2 3049 && img.mPlane[img.U].mVertSubsampling == 2 3050 && img.mPlane[img.V].mHorizSubsampling == 2 3051 && img.mPlane[img.V].mVertSubsampling == 2) { 3052 // possible flexible YUV420 format 3053 if (img.mBitDepth <= 8) { 3054 *flexibleEquivalent = OMX_COLOR_FormatYUV420Flexible; 3055 return true; 3056 } 3057 } 3058 } 3059 return false; 3060} 3061 3062status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> ¬ify) { 3063 // TODO: catch errors an return them instead of using CHECK 3064 OMX_PARAM_PORTDEFINITIONTYPE def; 3065 InitOMXParams(&def); 3066 def.nPortIndex = portIndex; 3067 3068 CHECK_EQ(mOMX->getParameter( 3069 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)), 3070 (status_t)OK); 3071 3072 CHECK_EQ((int)def.eDir, 3073 (int)(portIndex == kPortIndexOutput ? OMX_DirOutput : OMX_DirInput)); 3074 3075 switch (def.eDomain) { 3076 case OMX_PortDomainVideo: 3077 { 3078 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video; 3079 switch ((int)videoDef->eCompressionFormat) { 3080 case OMX_VIDEO_CodingUnused: 3081 { 3082 CHECK(mIsEncoder ^ (portIndex == kPortIndexOutput)); 3083 notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW); 3084 3085 notify->setInt32("stride", videoDef->nStride); 3086 notify->setInt32("slice-height", videoDef->nSliceHeight); 3087 notify->setInt32("color-format", videoDef->eColorFormat); 3088 3089 DescribeColorFormatParams describeParams; 3090 InitOMXParams(&describeParams); 3091 describeParams.eColorFormat = videoDef->eColorFormat; 3092 describeParams.nFrameWidth = videoDef->nFrameWidth; 3093 describeParams.nFrameHeight = videoDef->nFrameHeight; 3094 describeParams.nStride = videoDef->nStride; 3095 describeParams.nSliceHeight = videoDef->nSliceHeight; 3096 3097 if (describeColorFormat(mOMX, mNode, describeParams)) { 3098 notify->setBuffer( 3099 "image-data", 3100 ABuffer::CreateAsCopy( 3101 &describeParams.sMediaImage, 3102 sizeof(describeParams.sMediaImage))); 3103 } 3104 3105 OMX_CONFIG_RECTTYPE rect; 3106 InitOMXParams(&rect); 3107 rect.nPortIndex = kPortIndexOutput; 3108 3109 if (mOMX->getConfig( 3110 mNode, OMX_IndexConfigCommonOutputCrop, 3111 &rect, sizeof(rect)) != OK) { 3112 rect.nLeft = 0; 3113 rect.nTop = 0; 3114 rect.nWidth = videoDef->nFrameWidth; 3115 rect.nHeight = videoDef->nFrameHeight; 3116 } 3117 3118 CHECK_GE(rect.nLeft, 0); 3119 CHECK_GE(rect.nTop, 0); 3120 CHECK_GE(rect.nWidth, 0u); 3121 CHECK_GE(rect.nHeight, 0u); 3122 CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth); 3123 CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight); 3124 3125 notify->setRect( 3126 "crop", 3127 rect.nLeft, 3128 rect.nTop, 3129 rect.nLeft + rect.nWidth - 1, 3130 rect.nTop + rect.nHeight - 1); 3131 3132 break; 3133 } 3134 3135 case OMX_VIDEO_CodingVP8: 3136 case OMX_VIDEO_CodingVP9: 3137 { 3138 OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type; 3139 InitOMXParams(&vp8type); 3140 vp8type.nPortIndex = kPortIndexOutput; 3141 status_t err = mOMX->getParameter( 3142 mNode, 3143 (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder, 3144 &vp8type, 3145 sizeof(vp8type)); 3146 3147 if (err == OK) { 3148 AString tsSchema = "none"; 3149 if (vp8type.eTemporalPattern 3150 == OMX_VIDEO_VPXTemporalLayerPatternWebRTC) { 3151 switch (vp8type.nTemporalLayerCount) { 3152 case 1: 3153 { 3154 tsSchema = "webrtc.vp8.1-layer"; 3155 break; 3156 } 3157 case 2: 3158 { 3159 tsSchema = "webrtc.vp8.2-layer"; 3160 break; 3161 } 3162 case 3: 3163 { 3164 tsSchema = "webrtc.vp8.3-layer"; 3165 break; 3166 } 3167 default: 3168 { 3169 break; 3170 } 3171 } 3172 } 3173 notify->setString("ts-schema", tsSchema); 3174 } 3175 // Fall through to set up mime. 3176 } 3177 3178 default: 3179 { 3180 CHECK(mIsEncoder ^ (portIndex == kPortIndexInput)); 3181 AString mime; 3182 if (GetMimeTypeForVideoCoding( 3183 videoDef->eCompressionFormat, &mime) != OK) { 3184 notify->setString("mime", "application/octet-stream"); 3185 } else { 3186 notify->setString("mime", mime.c_str()); 3187 } 3188 break; 3189 } 3190 } 3191 3192 notify->setInt32("width", videoDef->nFrameWidth); 3193 notify->setInt32("height", videoDef->nFrameHeight); 3194 break; 3195 } 3196 3197 case OMX_PortDomainAudio: 3198 { 3199 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio; 3200 3201 switch ((int)audioDef->eEncoding) { 3202 case OMX_AUDIO_CodingPCM: 3203 { 3204 OMX_AUDIO_PARAM_PCMMODETYPE params; 3205 InitOMXParams(¶ms); 3206 params.nPortIndex = portIndex; 3207 3208 CHECK_EQ(mOMX->getParameter( 3209 mNode, OMX_IndexParamAudioPcm, 3210 ¶ms, sizeof(params)), 3211 (status_t)OK); 3212 3213 CHECK_GT(params.nChannels, 0); 3214 CHECK(params.nChannels == 1 || params.bInterleaved); 3215 CHECK_EQ(params.nBitPerSample, 16u); 3216 3217 CHECK_EQ((int)params.eNumData, 3218 (int)OMX_NumericalDataSigned); 3219 3220 CHECK_EQ((int)params.ePCMMode, 3221 (int)OMX_AUDIO_PCMModeLinear); 3222 3223 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW); 3224 notify->setInt32("channel-count", params.nChannels); 3225 notify->setInt32("sample-rate", params.nSamplingRate); 3226 3227 if (mChannelMaskPresent) { 3228 notify->setInt32("channel-mask", mChannelMask); 3229 } 3230 break; 3231 } 3232 3233 case OMX_AUDIO_CodingAAC: 3234 { 3235 OMX_AUDIO_PARAM_AACPROFILETYPE params; 3236 InitOMXParams(¶ms); 3237 params.nPortIndex = portIndex; 3238 3239 CHECK_EQ(mOMX->getParameter( 3240 mNode, OMX_IndexParamAudioAac, 3241 ¶ms, sizeof(params)), 3242 (status_t)OK); 3243 3244 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC); 3245 notify->setInt32("channel-count", params.nChannels); 3246 notify->setInt32("sample-rate", params.nSampleRate); 3247 break; 3248 } 3249 3250 case OMX_AUDIO_CodingAMR: 3251 { 3252 OMX_AUDIO_PARAM_AMRTYPE params; 3253 InitOMXParams(¶ms); 3254 params.nPortIndex = portIndex; 3255 3256 CHECK_EQ(mOMX->getParameter( 3257 mNode, OMX_IndexParamAudioAmr, 3258 ¶ms, sizeof(params)), 3259 (status_t)OK); 3260 3261 notify->setInt32("channel-count", 1); 3262 if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) { 3263 notify->setString( 3264 "mime", MEDIA_MIMETYPE_AUDIO_AMR_WB); 3265 3266 notify->setInt32("sample-rate", 16000); 3267 } else { 3268 notify->setString( 3269 "mime", MEDIA_MIMETYPE_AUDIO_AMR_NB); 3270 3271 notify->setInt32("sample-rate", 8000); 3272 } 3273 break; 3274 } 3275 3276 case OMX_AUDIO_CodingFLAC: 3277 { 3278 OMX_AUDIO_PARAM_FLACTYPE params; 3279 InitOMXParams(¶ms); 3280 params.nPortIndex = portIndex; 3281 3282 CHECK_EQ(mOMX->getParameter( 3283 mNode, OMX_IndexParamAudioFlac, 3284 ¶ms, sizeof(params)), 3285 (status_t)OK); 3286 3287 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC); 3288 notify->setInt32("channel-count", params.nChannels); 3289 notify->setInt32("sample-rate", params.nSampleRate); 3290 break; 3291 } 3292 3293 case OMX_AUDIO_CodingMP3: 3294 { 3295 OMX_AUDIO_PARAM_MP3TYPE params; 3296 InitOMXParams(¶ms); 3297 params.nPortIndex = portIndex; 3298 3299 CHECK_EQ(mOMX->getParameter( 3300 mNode, OMX_IndexParamAudioMp3, 3301 ¶ms, sizeof(params)), 3302 (status_t)OK); 3303 3304 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MPEG); 3305 notify->setInt32("channel-count", params.nChannels); 3306 notify->setInt32("sample-rate", params.nSampleRate); 3307 break; 3308 } 3309 3310 case OMX_AUDIO_CodingVORBIS: 3311 { 3312 OMX_AUDIO_PARAM_VORBISTYPE params; 3313 InitOMXParams(¶ms); 3314 params.nPortIndex = portIndex; 3315 3316 CHECK_EQ(mOMX->getParameter( 3317 mNode, OMX_IndexParamAudioVorbis, 3318 ¶ms, sizeof(params)), 3319 (status_t)OK); 3320 3321 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_VORBIS); 3322 notify->setInt32("channel-count", params.nChannels); 3323 notify->setInt32("sample-rate", params.nSampleRate); 3324 break; 3325 } 3326 3327 case OMX_AUDIO_CodingAndroidAC3: 3328 { 3329 OMX_AUDIO_PARAM_ANDROID_AC3TYPE params; 3330 InitOMXParams(¶ms); 3331 params.nPortIndex = portIndex; 3332 3333 CHECK_EQ((status_t)OK, mOMX->getParameter( 3334 mNode, 3335 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, 3336 ¶ms, 3337 sizeof(params))); 3338 3339 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3); 3340 notify->setInt32("channel-count", params.nChannels); 3341 notify->setInt32("sample-rate", params.nSampleRate); 3342 break; 3343 } 3344 3345 case OMX_AUDIO_CodingAndroidOPUS: 3346 { 3347 OMX_AUDIO_PARAM_ANDROID_OPUSTYPE params; 3348 InitOMXParams(¶ms); 3349 params.nPortIndex = portIndex; 3350 3351 CHECK_EQ((status_t)OK, mOMX->getParameter( 3352 mNode, 3353 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus, 3354 ¶ms, 3355 sizeof(params))); 3356 3357 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_OPUS); 3358 notify->setInt32("channel-count", params.nChannels); 3359 notify->setInt32("sample-rate", params.nSampleRate); 3360 break; 3361 } 3362 3363 default: 3364 ALOGE("UNKNOWN AUDIO CODING: %d\n", audioDef->eEncoding); 3365 TRESPASS(); 3366 } 3367 break; 3368 } 3369 3370 default: 3371 TRESPASS(); 3372 } 3373 3374 return OK; 3375} 3376 3377void ACodec::sendFormatChange(const sp<AMessage> &reply) { 3378 sp<AMessage> notify = mNotify->dup(); 3379 notify->setInt32("what", kWhatOutputFormatChanged); 3380 3381 CHECK_EQ(getPortFormat(kPortIndexOutput, notify), (status_t)OK); 3382 3383 AString mime; 3384 CHECK(notify->findString("mime", &mime)); 3385 3386 int32_t left, top, right, bottom; 3387 if (mime == MEDIA_MIMETYPE_VIDEO_RAW && 3388 mNativeWindow != NULL && 3389 notify->findRect("crop", &left, &top, &right, &bottom)) { 3390 // notify renderer of the crop change 3391 // NOTE: native window uses extended right-bottom coordinate 3392 reply->setRect("crop", left, top, right + 1, bottom + 1); 3393 } else if (mime == MEDIA_MIMETYPE_AUDIO_RAW && 3394 (mEncoderDelay || mEncoderPadding)) { 3395 int32_t channelCount; 3396 CHECK(notify->findInt32("channel-count", &channelCount)); 3397 size_t frameSize = channelCount * sizeof(int16_t); 3398 if (mSkipCutBuffer != NULL) { 3399 size_t prevbufsize = mSkipCutBuffer->size(); 3400 if (prevbufsize != 0) { 3401 ALOGW("Replacing SkipCutBuffer holding %d " 3402 "bytes", 3403 prevbufsize); 3404 } 3405 } 3406 mSkipCutBuffer = new SkipCutBuffer( 3407 mEncoderDelay * frameSize, 3408 mEncoderPadding * frameSize); 3409 } 3410 3411 notify->post(); 3412 3413 mSentFormat = true; 3414} 3415 3416void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) { 3417 sp<AMessage> notify = mNotify->dup(); 3418 notify->setInt32("what", CodecBase::kWhatError); 3419 ALOGE("signalError(omxError %#x, internalError %d)", error, internalError); 3420 3421 if (internalError == UNKNOWN_ERROR) { // find better error code 3422 const status_t omxStatus = statusFromOMXError(error); 3423 if (omxStatus != 0) { 3424 internalError = omxStatus; 3425 } else { 3426 ALOGW("Invalid OMX error %#x", error); 3427 } 3428 } 3429 notify->setInt32("err", internalError); 3430 notify->setInt32("actionCode", ACTION_CODE_FATAL); // could translate from OMX error. 3431 notify->post(); 3432} 3433 3434status_t ACodec::pushBlankBuffersToNativeWindow() { 3435 status_t err = NO_ERROR; 3436 ANativeWindowBuffer* anb = NULL; 3437 int numBufs = 0; 3438 int minUndequeuedBufs = 0; 3439 3440 // We need to reconnect to the ANativeWindow as a CPU client to ensure that 3441 // no frames get dropped by SurfaceFlinger assuming that these are video 3442 // frames. 3443 err = native_window_api_disconnect(mNativeWindow.get(), 3444 NATIVE_WINDOW_API_MEDIA); 3445 if (err != NO_ERROR) { 3446 ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)", 3447 strerror(-err), -err); 3448 return err; 3449 } 3450 3451 err = native_window_api_connect(mNativeWindow.get(), 3452 NATIVE_WINDOW_API_CPU); 3453 if (err != NO_ERROR) { 3454 ALOGE("error pushing blank frames: api_connect failed: %s (%d)", 3455 strerror(-err), -err); 3456 return err; 3457 } 3458 3459 err = native_window_set_buffers_geometry(mNativeWindow.get(), 1, 1, 3460 HAL_PIXEL_FORMAT_RGBX_8888); 3461 if (err != NO_ERROR) { 3462 ALOGE("error pushing blank frames: set_buffers_geometry failed: %s (%d)", 3463 strerror(-err), -err); 3464 goto error; 3465 } 3466 3467 err = native_window_set_scaling_mode(mNativeWindow.get(), 3468 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); 3469 if (err != NO_ERROR) { 3470 ALOGE("error pushing blank_frames: set_scaling_mode failed: %s (%d)", 3471 strerror(-err), -err); 3472 goto error; 3473 } 3474 3475 err = native_window_set_usage(mNativeWindow.get(), 3476 GRALLOC_USAGE_SW_WRITE_OFTEN); 3477 if (err != NO_ERROR) { 3478 ALOGE("error pushing blank frames: set_usage failed: %s (%d)", 3479 strerror(-err), -err); 3480 goto error; 3481 } 3482 3483 err = mNativeWindow->query(mNativeWindow.get(), 3484 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs); 3485 if (err != NO_ERROR) { 3486 ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query " 3487 "failed: %s (%d)", strerror(-err), -err); 3488 goto error; 3489 } 3490 3491 numBufs = minUndequeuedBufs + 1; 3492 err = native_window_set_buffer_count(mNativeWindow.get(), numBufs); 3493 if (err != NO_ERROR) { 3494 ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)", 3495 strerror(-err), -err); 3496 goto error; 3497 } 3498 3499 // We push numBufs + 1 buffers to ensure that we've drawn into the same 3500 // buffer twice. This should guarantee that the buffer has been displayed 3501 // on the screen and then been replaced, so an previous video frames are 3502 // guaranteed NOT to be currently displayed. 3503 for (int i = 0; i < numBufs + 1; i++) { 3504 int fenceFd = -1; 3505 err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &anb); 3506 if (err != NO_ERROR) { 3507 ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)", 3508 strerror(-err), -err); 3509 goto error; 3510 } 3511 3512 sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); 3513 3514 // Fill the buffer with the a 1x1 checkerboard pattern ;) 3515 uint32_t* img = NULL; 3516 err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); 3517 if (err != NO_ERROR) { 3518 ALOGE("error pushing blank frames: lock failed: %s (%d)", 3519 strerror(-err), -err); 3520 goto error; 3521 } 3522 3523 *img = 0; 3524 3525 err = buf->unlock(); 3526 if (err != NO_ERROR) { 3527 ALOGE("error pushing blank frames: unlock failed: %s (%d)", 3528 strerror(-err), -err); 3529 goto error; 3530 } 3531 3532 err = mNativeWindow->queueBuffer(mNativeWindow.get(), 3533 buf->getNativeBuffer(), -1); 3534 if (err != NO_ERROR) { 3535 ALOGE("error pushing blank frames: queueBuffer failed: %s (%d)", 3536 strerror(-err), -err); 3537 goto error; 3538 } 3539 3540 anb = NULL; 3541 } 3542 3543error: 3544 3545 if (err != NO_ERROR) { 3546 // Clean up after an error. 3547 if (anb != NULL) { 3548 mNativeWindow->cancelBuffer(mNativeWindow.get(), anb, -1); 3549 } 3550 3551 native_window_api_disconnect(mNativeWindow.get(), 3552 NATIVE_WINDOW_API_CPU); 3553 native_window_api_connect(mNativeWindow.get(), 3554 NATIVE_WINDOW_API_MEDIA); 3555 3556 return err; 3557 } else { 3558 // Clean up after success. 3559 err = native_window_api_disconnect(mNativeWindow.get(), 3560 NATIVE_WINDOW_API_CPU); 3561 if (err != NO_ERROR) { 3562 ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)", 3563 strerror(-err), -err); 3564 return err; 3565 } 3566 3567 err = native_window_api_connect(mNativeWindow.get(), 3568 NATIVE_WINDOW_API_MEDIA); 3569 if (err != NO_ERROR) { 3570 ALOGE("error pushing blank frames: api_connect failed: %s (%d)", 3571 strerror(-err), -err); 3572 return err; 3573 } 3574 3575 return NO_ERROR; 3576 } 3577} 3578 3579//////////////////////////////////////////////////////////////////////////////// 3580 3581ACodec::PortDescription::PortDescription() { 3582} 3583 3584status_t ACodec::requestIDRFrame() { 3585 if (!mIsEncoder) { 3586 return ERROR_UNSUPPORTED; 3587 } 3588 3589 OMX_CONFIG_INTRAREFRESHVOPTYPE params; 3590 InitOMXParams(¶ms); 3591 3592 params.nPortIndex = kPortIndexOutput; 3593 params.IntraRefreshVOP = OMX_TRUE; 3594 3595 return mOMX->setConfig( 3596 mNode, 3597 OMX_IndexConfigVideoIntraVOPRefresh, 3598 ¶ms, 3599 sizeof(params)); 3600} 3601 3602void ACodec::PortDescription::addBuffer( 3603 IOMX::buffer_id id, const sp<ABuffer> &buffer) { 3604 mBufferIDs.push_back(id); 3605 mBuffers.push_back(buffer); 3606} 3607 3608size_t ACodec::PortDescription::countBuffers() { 3609 return mBufferIDs.size(); 3610} 3611 3612IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const { 3613 return mBufferIDs.itemAt(index); 3614} 3615 3616sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const { 3617 return mBuffers.itemAt(index); 3618} 3619 3620//////////////////////////////////////////////////////////////////////////////// 3621 3622ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState) 3623 : AState(parentState), 3624 mCodec(codec) { 3625} 3626 3627ACodec::BaseState::PortMode ACodec::BaseState::getPortMode( 3628 OMX_U32 /* portIndex */) { 3629 return KEEP_BUFFERS; 3630} 3631 3632bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) { 3633 switch (msg->what()) { 3634 case kWhatInputBufferFilled: 3635 { 3636 onInputBufferFilled(msg); 3637 break; 3638 } 3639 3640 case kWhatOutputBufferDrained: 3641 { 3642 onOutputBufferDrained(msg); 3643 break; 3644 } 3645 3646 case ACodec::kWhatOMXMessage: 3647 { 3648 return onOMXMessage(msg); 3649 } 3650 3651 case ACodec::kWhatCreateInputSurface: 3652 case ACodec::kWhatSignalEndOfInputStream: 3653 { 3654 // This may result in an app illegal state exception. 3655 ALOGE("Message 0x%x was not handled", msg->what()); 3656 mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION); 3657 return true; 3658 } 3659 3660 case ACodec::kWhatOMXDied: 3661 { 3662 // This will result in kFlagSawMediaServerDie handling in MediaCodec. 3663 ALOGE("OMX/mediaserver died, signalling error!"); 3664 mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT); 3665 break; 3666 } 3667 3668 default: 3669 return false; 3670 } 3671 3672 return true; 3673} 3674 3675bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) { 3676 int32_t type; 3677 CHECK(msg->findInt32("type", &type)); 3678 3679 // there is a possibility that this is an outstanding message for a 3680 // codec that we have already destroyed 3681 if (mCodec->mNode == NULL) { 3682 ALOGI("ignoring message as already freed component: %s", 3683 msg->debugString().c_str()); 3684 return true; 3685 } 3686 3687 IOMX::node_id nodeID; 3688 CHECK(msg->findInt32("node", (int32_t*)&nodeID)); 3689 CHECK_EQ(nodeID, mCodec->mNode); 3690 3691 switch (type) { 3692 case omx_message::EVENT: 3693 { 3694 int32_t event, data1, data2; 3695 CHECK(msg->findInt32("event", &event)); 3696 CHECK(msg->findInt32("data1", &data1)); 3697 CHECK(msg->findInt32("data2", &data2)); 3698 3699 if (event == OMX_EventCmdComplete 3700 && data1 == OMX_CommandFlush 3701 && data2 == (int32_t)OMX_ALL) { 3702 // Use of this notification is not consistent across 3703 // implementations. We'll drop this notification and rely 3704 // on flush-complete notifications on the individual port 3705 // indices instead. 3706 3707 return true; 3708 } 3709 3710 return onOMXEvent( 3711 static_cast<OMX_EVENTTYPE>(event), 3712 static_cast<OMX_U32>(data1), 3713 static_cast<OMX_U32>(data2)); 3714 } 3715 3716 case omx_message::EMPTY_BUFFER_DONE: 3717 { 3718 IOMX::buffer_id bufferID; 3719 CHECK(msg->findInt32("buffer", (int32_t*)&bufferID)); 3720 3721 return onOMXEmptyBufferDone(bufferID); 3722 } 3723 3724 case omx_message::FILL_BUFFER_DONE: 3725 { 3726 IOMX::buffer_id bufferID; 3727 CHECK(msg->findInt32("buffer", (int32_t*)&bufferID)); 3728 3729 int32_t rangeOffset, rangeLength, flags; 3730 int64_t timeUs; 3731 3732 CHECK(msg->findInt32("range_offset", &rangeOffset)); 3733 CHECK(msg->findInt32("range_length", &rangeLength)); 3734 CHECK(msg->findInt32("flags", &flags)); 3735 CHECK(msg->findInt64("timestamp", &timeUs)); 3736 3737 return onOMXFillBufferDone( 3738 bufferID, 3739 (size_t)rangeOffset, (size_t)rangeLength, 3740 (OMX_U32)flags, 3741 timeUs); 3742 } 3743 3744 default: 3745 TRESPASS(); 3746 break; 3747 } 3748} 3749 3750bool ACodec::BaseState::onOMXEvent( 3751 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3752 if (event != OMX_EventError) { 3753 ALOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)", 3754 mCodec->mComponentName.c_str(), event, data1, data2); 3755 3756 return false; 3757 } 3758 3759 ALOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1); 3760 3761 // verify OMX component sends back an error we expect. 3762 OMX_ERRORTYPE omxError = (OMX_ERRORTYPE)data1; 3763 if (!isOMXError(omxError)) { 3764 ALOGW("Invalid OMX error %#x", omxError); 3765 omxError = OMX_ErrorUndefined; 3766 } 3767 mCodec->signalError(omxError); 3768 3769 return true; 3770} 3771 3772bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) { 3773 ALOGV("[%s] onOMXEmptyBufferDone %p", 3774 mCodec->mComponentName.c_str(), bufferID); 3775 3776 BufferInfo *info = 3777 mCodec->findBufferByID(kPortIndexInput, bufferID); 3778 3779 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); 3780 info->mStatus = BufferInfo::OWNED_BY_US; 3781 3782 const sp<AMessage> &bufferMeta = info->mData->meta(); 3783 void *mediaBuffer; 3784 if (bufferMeta->findPointer("mediaBuffer", &mediaBuffer) 3785 && mediaBuffer != NULL) { 3786 // We're in "store-metadata-in-buffers" mode, the underlying 3787 // OMX component had access to data that's implicitly refcounted 3788 // by this "mediaBuffer" object. Now that the OMX component has 3789 // told us that it's done with the input buffer, we can decrement 3790 // the mediaBuffer's reference count. 3791 3792 ALOGV("releasing mbuf %p", mediaBuffer); 3793 3794 ((MediaBuffer *)mediaBuffer)->release(); 3795 mediaBuffer = NULL; 3796 3797 bufferMeta->setPointer("mediaBuffer", NULL); 3798 } 3799 3800 PortMode mode = getPortMode(kPortIndexInput); 3801 3802 switch (mode) { 3803 case KEEP_BUFFERS: 3804 break; 3805 3806 case RESUBMIT_BUFFERS: 3807 postFillThisBuffer(info); 3808 break; 3809 3810 default: 3811 { 3812 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 3813 TRESPASS(); // Not currently used 3814 break; 3815 } 3816 } 3817 3818 return true; 3819} 3820 3821void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) { 3822 if (mCodec->mPortEOS[kPortIndexInput]) { 3823 return; 3824 } 3825 3826 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 3827 3828 sp<AMessage> notify = mCodec->mNotify->dup(); 3829 notify->setInt32("what", CodecBase::kWhatFillThisBuffer); 3830 notify->setInt32("buffer-id", info->mBufferID); 3831 3832 info->mData->meta()->clear(); 3833 notify->setBuffer("buffer", info->mData); 3834 3835 sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id()); 3836 reply->setInt32("buffer-id", info->mBufferID); 3837 3838 notify->setMessage("reply", reply); 3839 3840 notify->post(); 3841 3842 info->mStatus = BufferInfo::OWNED_BY_UPSTREAM; 3843} 3844 3845void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { 3846 IOMX::buffer_id bufferID; 3847 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID)); 3848 sp<ABuffer> buffer; 3849 int32_t err = OK; 3850 bool eos = false; 3851 PortMode mode = getPortMode(kPortIndexInput); 3852 3853 if (!msg->findBuffer("buffer", &buffer)) { 3854 /* these are unfilled buffers returned by client */ 3855 CHECK(msg->findInt32("err", &err)); 3856 3857 if (err == OK) { 3858 /* buffers with no errors are returned on MediaCodec.flush */ 3859 mode = KEEP_BUFFERS; 3860 } else { 3861 ALOGV("[%s] saw error %d instead of an input buffer", 3862 mCodec->mComponentName.c_str(), err); 3863 eos = true; 3864 } 3865 3866 buffer.clear(); 3867 } 3868 3869 int32_t tmp; 3870 if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) { 3871 eos = true; 3872 err = ERROR_END_OF_STREAM; 3873 } 3874 3875 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID); 3876 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM); 3877 3878 info->mStatus = BufferInfo::OWNED_BY_US; 3879 3880 switch (mode) { 3881 case KEEP_BUFFERS: 3882 { 3883 if (eos) { 3884 if (!mCodec->mPortEOS[kPortIndexInput]) { 3885 mCodec->mPortEOS[kPortIndexInput] = true; 3886 mCodec->mInputEOSResult = err; 3887 } 3888 } 3889 break; 3890 } 3891 3892 case RESUBMIT_BUFFERS: 3893 { 3894 if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) { 3895 int64_t timeUs; 3896 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 3897 3898 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME; 3899 3900 int32_t isCSD; 3901 if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) { 3902 flags |= OMX_BUFFERFLAG_CODECCONFIG; 3903 } 3904 3905 if (eos) { 3906 flags |= OMX_BUFFERFLAG_EOS; 3907 } 3908 3909 if (buffer != info->mData) { 3910 ALOGV("[%s] Needs to copy input data for buffer %p. (%p != %p)", 3911 mCodec->mComponentName.c_str(), 3912 bufferID, 3913 buffer.get(), info->mData.get()); 3914 3915 CHECK_LE(buffer->size(), info->mData->capacity()); 3916 memcpy(info->mData->data(), buffer->data(), buffer->size()); 3917 } 3918 3919 if (flags & OMX_BUFFERFLAG_CODECCONFIG) { 3920 ALOGV("[%s] calling emptyBuffer %p w/ codec specific data", 3921 mCodec->mComponentName.c_str(), bufferID); 3922 } else if (flags & OMX_BUFFERFLAG_EOS) { 3923 ALOGV("[%s] calling emptyBuffer %p w/ EOS", 3924 mCodec->mComponentName.c_str(), bufferID); 3925 } else { 3926#if TRACK_BUFFER_TIMING 3927 ALOGI("[%s] calling emptyBuffer %p w/ time %lld us", 3928 mCodec->mComponentName.c_str(), bufferID, timeUs); 3929#else 3930 ALOGV("[%s] calling emptyBuffer %p w/ time %lld us", 3931 mCodec->mComponentName.c_str(), bufferID, timeUs); 3932#endif 3933 } 3934 3935#if TRACK_BUFFER_TIMING 3936 ACodec::BufferStats stats; 3937 stats.mEmptyBufferTimeUs = ALooper::GetNowUs(); 3938 stats.mFillBufferDoneTimeUs = -1ll; 3939 mCodec->mBufferStats.add(timeUs, stats); 3940#endif 3941 3942 if (mCodec->mStoreMetaDataInOutputBuffers) { 3943 // try to submit an output buffer for each input buffer 3944 PortMode outputMode = getPortMode(kPortIndexOutput); 3945 3946 ALOGV("MetaDataBuffersToSubmit=%u portMode=%s", 3947 mCodec->mMetaDataBuffersToSubmit, 3948 (outputMode == FREE_BUFFERS ? "FREE" : 3949 outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT")); 3950 if (outputMode == RESUBMIT_BUFFERS) { 3951 mCodec->submitOutputMetaDataBuffer(); 3952 } 3953 } 3954 3955 CHECK_EQ(mCodec->mOMX->emptyBuffer( 3956 mCodec->mNode, 3957 bufferID, 3958 0, 3959 buffer->size(), 3960 flags, 3961 timeUs), 3962 (status_t)OK); 3963 3964 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 3965 3966 if (!eos) { 3967 getMoreInputDataIfPossible(); 3968 } else { 3969 ALOGV("[%s] Signalled EOS on the input port", 3970 mCodec->mComponentName.c_str()); 3971 3972 mCodec->mPortEOS[kPortIndexInput] = true; 3973 mCodec->mInputEOSResult = err; 3974 } 3975 } else if (!mCodec->mPortEOS[kPortIndexInput]) { 3976 if (err != ERROR_END_OF_STREAM) { 3977 ALOGV("[%s] Signalling EOS on the input port " 3978 "due to error %d", 3979 mCodec->mComponentName.c_str(), err); 3980 } else { 3981 ALOGV("[%s] Signalling EOS on the input port", 3982 mCodec->mComponentName.c_str()); 3983 } 3984 3985 ALOGV("[%s] calling emptyBuffer %p signalling EOS", 3986 mCodec->mComponentName.c_str(), bufferID); 3987 3988 CHECK_EQ(mCodec->mOMX->emptyBuffer( 3989 mCodec->mNode, 3990 bufferID, 3991 0, 3992 0, 3993 OMX_BUFFERFLAG_EOS, 3994 0), 3995 (status_t)OK); 3996 3997 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 3998 3999 mCodec->mPortEOS[kPortIndexInput] = true; 4000 mCodec->mInputEOSResult = err; 4001 } 4002 break; 4003 } 4004 4005 default: 4006 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 4007 break; 4008 } 4009} 4010 4011void ACodec::BaseState::getMoreInputDataIfPossible() { 4012 if (mCodec->mPortEOS[kPortIndexInput]) { 4013 return; 4014 } 4015 4016 BufferInfo *eligible = NULL; 4017 4018 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 4019 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 4020 4021#if 0 4022 if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) { 4023 // There's already a "read" pending. 4024 return; 4025 } 4026#endif 4027 4028 if (info->mStatus == BufferInfo::OWNED_BY_US) { 4029 eligible = info; 4030 } 4031 } 4032 4033 if (eligible == NULL) { 4034 return; 4035 } 4036 4037 postFillThisBuffer(eligible); 4038} 4039 4040bool ACodec::BaseState::onOMXFillBufferDone( 4041 IOMX::buffer_id bufferID, 4042 size_t rangeOffset, size_t rangeLength, 4043 OMX_U32 flags, 4044 int64_t timeUs) { 4045 ALOGV("[%s] onOMXFillBufferDone %u time %" PRId64 " us, flags = 0x%08x", 4046 mCodec->mComponentName.c_str(), bufferID, timeUs, flags); 4047 4048 ssize_t index; 4049 4050#if TRACK_BUFFER_TIMING 4051 index = mCodec->mBufferStats.indexOfKey(timeUs); 4052 if (index >= 0) { 4053 ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index); 4054 stats->mFillBufferDoneTimeUs = ALooper::GetNowUs(); 4055 4056 ALOGI("frame PTS %lld: %lld", 4057 timeUs, 4058 stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs); 4059 4060 mCodec->mBufferStats.removeItemsAt(index); 4061 stats = NULL; 4062 } 4063#endif 4064 4065 BufferInfo *info = 4066 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 4067 4068 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); 4069 4070 info->mDequeuedAt = ++mCodec->mDequeueCounter; 4071 info->mStatus = BufferInfo::OWNED_BY_US; 4072 4073 PortMode mode = getPortMode(kPortIndexOutput); 4074 4075 switch (mode) { 4076 case KEEP_BUFFERS: 4077 break; 4078 4079 case RESUBMIT_BUFFERS: 4080 { 4081 if (rangeLength == 0 && !(flags & OMX_BUFFERFLAG_EOS)) { 4082 ALOGV("[%s] calling fillBuffer %u", 4083 mCodec->mComponentName.c_str(), info->mBufferID); 4084 4085 CHECK_EQ(mCodec->mOMX->fillBuffer( 4086 mCodec->mNode, info->mBufferID), 4087 (status_t)OK); 4088 4089 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 4090 break; 4091 } 4092 4093 sp<AMessage> reply = 4094 new AMessage(kWhatOutputBufferDrained, mCodec->id()); 4095 4096 if (!mCodec->mSentFormat && rangeLength > 0) { 4097 mCodec->sendFormatChange(reply); 4098 } 4099 4100 if (mCodec->mUseMetadataOnEncoderOutput) { 4101 native_handle_t* handle = 4102 *(native_handle_t**)(info->mData->data() + 4); 4103 info->mData->meta()->setPointer("handle", handle); 4104 info->mData->meta()->setInt32("rangeOffset", rangeOffset); 4105 info->mData->meta()->setInt32("rangeLength", rangeLength); 4106 } else { 4107 info->mData->setRange(rangeOffset, rangeLength); 4108 } 4109#if 0 4110 if (mCodec->mNativeWindow == NULL) { 4111 if (IsIDR(info->mData)) { 4112 ALOGI("IDR frame"); 4113 } 4114 } 4115#endif 4116 4117 if (mCodec->mSkipCutBuffer != NULL) { 4118 mCodec->mSkipCutBuffer->submit(info->mData); 4119 } 4120 info->mData->meta()->setInt64("timeUs", timeUs); 4121 4122 sp<AMessage> notify = mCodec->mNotify->dup(); 4123 notify->setInt32("what", CodecBase::kWhatDrainThisBuffer); 4124 notify->setInt32("buffer-id", info->mBufferID); 4125 notify->setBuffer("buffer", info->mData); 4126 notify->setInt32("flags", flags); 4127 4128 reply->setInt32("buffer-id", info->mBufferID); 4129 4130 notify->setMessage("reply", reply); 4131 4132 notify->post(); 4133 4134 info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM; 4135 4136 if (flags & OMX_BUFFERFLAG_EOS) { 4137 ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str()); 4138 4139 sp<AMessage> notify = mCodec->mNotify->dup(); 4140 notify->setInt32("what", CodecBase::kWhatEOS); 4141 notify->setInt32("err", mCodec->mInputEOSResult); 4142 notify->post(); 4143 4144 mCodec->mPortEOS[kPortIndexOutput] = true; 4145 } 4146 break; 4147 } 4148 4149 default: 4150 { 4151 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 4152 4153 CHECK_EQ((status_t)OK, 4154 mCodec->freeBuffer(kPortIndexOutput, index)); 4155 break; 4156 } 4157 } 4158 4159 return true; 4160} 4161 4162void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { 4163 IOMX::buffer_id bufferID; 4164 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID)); 4165 ssize_t index; 4166 BufferInfo *info = 4167 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 4168 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM); 4169 4170 android_native_rect_t crop; 4171 if (msg->findRect("crop", 4172 &crop.left, &crop.top, &crop.right, &crop.bottom)) { 4173 CHECK_EQ(0, native_window_set_crop( 4174 mCodec->mNativeWindow.get(), &crop)); 4175 } 4176 4177 int32_t render; 4178 if (mCodec->mNativeWindow != NULL 4179 && msg->findInt32("render", &render) && render != 0 4180 && info->mData != NULL && info->mData->size() != 0) { 4181 ATRACE_NAME("render"); 4182 // The client wants this buffer to be rendered. 4183 4184 int64_t timestampNs = 0; 4185 if (!msg->findInt64("timestampNs", ×tampNs)) { 4186 // TODO: it seems like we should use the timestamp 4187 // in the (media)buffer as it potentially came from 4188 // an input surface, but we did not propagate it prior to 4189 // API 20. Perhaps check for target SDK version. 4190#if 0 4191 if (info->mData->meta()->findInt64("timeUs", ×tampNs)) { 4192 ALOGV("using buffer PTS of %" PRId64, timestampNs); 4193 timestampNs *= 1000; 4194 } 4195#endif 4196 } 4197 4198 status_t err; 4199 err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs); 4200 if (err != OK) { 4201 ALOGW("failed to set buffer timestamp: %d", err); 4202 } 4203 4204 if ((err = mCodec->mNativeWindow->queueBuffer( 4205 mCodec->mNativeWindow.get(), 4206 info->mGraphicBuffer.get(), -1)) == OK) { 4207 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 4208 } else { 4209 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 4210 info->mStatus = BufferInfo::OWNED_BY_US; 4211 } 4212 } else { 4213 if (mCodec->mNativeWindow != NULL && 4214 (info->mData == NULL || info->mData->size() != 0)) { 4215 ATRACE_NAME("frame-drop"); 4216 } 4217 info->mStatus = BufferInfo::OWNED_BY_US; 4218 } 4219 4220 PortMode mode = getPortMode(kPortIndexOutput); 4221 4222 switch (mode) { 4223 case KEEP_BUFFERS: 4224 { 4225 // XXX fishy, revisit!!! What about the FREE_BUFFERS case below? 4226 4227 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 4228 // We cannot resubmit the buffer we just rendered, dequeue 4229 // the spare instead. 4230 4231 info = mCodec->dequeueBufferFromNativeWindow(); 4232 } 4233 break; 4234 } 4235 4236 case RESUBMIT_BUFFERS: 4237 { 4238 if (!mCodec->mPortEOS[kPortIndexOutput]) { 4239 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 4240 // We cannot resubmit the buffer we just rendered, dequeue 4241 // the spare instead. 4242 4243 info = mCodec->dequeueBufferFromNativeWindow(); 4244 } 4245 4246 if (info != NULL) { 4247 ALOGV("[%s] calling fillBuffer %u", 4248 mCodec->mComponentName.c_str(), info->mBufferID); 4249 4250 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), 4251 (status_t)OK); 4252 4253 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 4254 } 4255 } 4256 break; 4257 } 4258 4259 default: 4260 { 4261 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 4262 4263 CHECK_EQ((status_t)OK, 4264 mCodec->freeBuffer(kPortIndexOutput, index)); 4265 break; 4266 } 4267 } 4268} 4269 4270//////////////////////////////////////////////////////////////////////////////// 4271 4272ACodec::UninitializedState::UninitializedState(ACodec *codec) 4273 : BaseState(codec) { 4274} 4275 4276void ACodec::UninitializedState::stateEntered() { 4277 ALOGV("Now uninitialized"); 4278 4279 if (mDeathNotifier != NULL) { 4280 mCodec->mOMX->asBinder()->unlinkToDeath(mDeathNotifier); 4281 mDeathNotifier.clear(); 4282 } 4283 4284 mCodec->mNativeWindow.clear(); 4285 mCodec->mNode = NULL; 4286 mCodec->mOMX.clear(); 4287 mCodec->mQuirks = 0; 4288 mCodec->mFlags = 0; 4289 mCodec->mUseMetadataOnEncoderOutput = 0; 4290 mCodec->mComponentName.clear(); 4291} 4292 4293bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) { 4294 bool handled = false; 4295 4296 switch (msg->what()) { 4297 case ACodec::kWhatSetup: 4298 { 4299 onSetup(msg); 4300 4301 handled = true; 4302 break; 4303 } 4304 4305 case ACodec::kWhatAllocateComponent: 4306 { 4307 onAllocateComponent(msg); 4308 handled = true; 4309 break; 4310 } 4311 4312 case ACodec::kWhatShutdown: 4313 { 4314 int32_t keepComponentAllocated; 4315 CHECK(msg->findInt32( 4316 "keepComponentAllocated", &keepComponentAllocated)); 4317 ALOGW_IF(keepComponentAllocated, 4318 "cannot keep component allocated on shutdown in Uninitialized state"); 4319 4320 sp<AMessage> notify = mCodec->mNotify->dup(); 4321 notify->setInt32("what", CodecBase::kWhatShutdownCompleted); 4322 notify->post(); 4323 4324 handled = true; 4325 break; 4326 } 4327 4328 case ACodec::kWhatFlush: 4329 { 4330 sp<AMessage> notify = mCodec->mNotify->dup(); 4331 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 4332 notify->post(); 4333 4334 handled = true; 4335 break; 4336 } 4337 4338 default: 4339 return BaseState::onMessageReceived(msg); 4340 } 4341 4342 return handled; 4343} 4344 4345void ACodec::UninitializedState::onSetup( 4346 const sp<AMessage> &msg) { 4347 if (onAllocateComponent(msg) 4348 && mCodec->mLoadedState->onConfigureComponent(msg)) { 4349 mCodec->mLoadedState->onStart(); 4350 } 4351} 4352 4353bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) { 4354 ALOGV("onAllocateComponent"); 4355 4356 CHECK(mCodec->mNode == NULL); 4357 4358 OMXClient client; 4359 CHECK_EQ(client.connect(), (status_t)OK); 4360 4361 sp<IOMX> omx = client.interface(); 4362 4363 sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec->id()); 4364 4365 mDeathNotifier = new DeathNotifier(notify); 4366 if (omx->asBinder()->linkToDeath(mDeathNotifier) != OK) { 4367 // This was a local binder, if it dies so do we, we won't care 4368 // about any notifications in the afterlife. 4369 mDeathNotifier.clear(); 4370 } 4371 4372 Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs; 4373 4374 AString mime; 4375 4376 AString componentName; 4377 uint32_t quirks = 0; 4378 int32_t encoder = false; 4379 if (msg->findString("componentName", &componentName)) { 4380 ssize_t index = matchingCodecs.add(); 4381 OMXCodec::CodecNameAndQuirks *entry = &matchingCodecs.editItemAt(index); 4382 entry->mName = String8(componentName.c_str()); 4383 4384 if (!OMXCodec::findCodecQuirks( 4385 componentName.c_str(), &entry->mQuirks)) { 4386 entry->mQuirks = 0; 4387 } 4388 } else { 4389 CHECK(msg->findString("mime", &mime)); 4390 4391 if (!msg->findInt32("encoder", &encoder)) { 4392 encoder = false; 4393 } 4394 4395 OMXCodec::findMatchingCodecs( 4396 mime.c_str(), 4397 encoder, // createEncoder 4398 NULL, // matchComponentName 4399 0, // flags 4400 &matchingCodecs); 4401 } 4402 4403 sp<CodecObserver> observer = new CodecObserver; 4404 IOMX::node_id node = NULL; 4405 4406 for (size_t matchIndex = 0; matchIndex < matchingCodecs.size(); 4407 ++matchIndex) { 4408 componentName = matchingCodecs.itemAt(matchIndex).mName.string(); 4409 quirks = matchingCodecs.itemAt(matchIndex).mQuirks; 4410 4411 pid_t tid = androidGetTid(); 4412 int prevPriority = androidGetThreadPriority(tid); 4413 androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND); 4414 status_t err = omx->allocateNode(componentName.c_str(), observer, &node); 4415 androidSetThreadPriority(tid, prevPriority); 4416 4417 if (err == OK) { 4418 break; 4419 } else { 4420 ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str()); 4421 } 4422 4423 node = NULL; 4424 } 4425 4426 if (node == NULL) { 4427 if (!mime.empty()) { 4428 ALOGE("Unable to instantiate a %scoder for type '%s'.", 4429 encoder ? "en" : "de", mime.c_str()); 4430 } else { 4431 ALOGE("Unable to instantiate codec '%s'.", componentName.c_str()); 4432 } 4433 4434 mCodec->signalError(OMX_ErrorComponentNotFound); 4435 return false; 4436 } 4437 4438 notify = new AMessage(kWhatOMXMessage, mCodec->id()); 4439 observer->setNotificationMessage(notify); 4440 4441 mCodec->mComponentName = componentName; 4442 mCodec->mFlags = 0; 4443 4444 if (componentName.endsWith(".secure")) { 4445 mCodec->mFlags |= kFlagIsSecure; 4446 mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown; 4447 } 4448 4449 mCodec->mQuirks = quirks; 4450 mCodec->mOMX = omx; 4451 mCodec->mNode = node; 4452 4453 { 4454 sp<AMessage> notify = mCodec->mNotify->dup(); 4455 notify->setInt32("what", CodecBase::kWhatComponentAllocated); 4456 notify->setString("componentName", mCodec->mComponentName.c_str()); 4457 notify->post(); 4458 } 4459 4460 mCodec->changeState(mCodec->mLoadedState); 4461 4462 return true; 4463} 4464 4465//////////////////////////////////////////////////////////////////////////////// 4466 4467ACodec::LoadedState::LoadedState(ACodec *codec) 4468 : BaseState(codec) { 4469} 4470 4471void ACodec::LoadedState::stateEntered() { 4472 ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str()); 4473 4474 mCodec->mPortEOS[kPortIndexInput] = 4475 mCodec->mPortEOS[kPortIndexOutput] = false; 4476 4477 mCodec->mInputEOSResult = OK; 4478 4479 mCodec->mDequeueCounter = 0; 4480 mCodec->mMetaDataBuffersToSubmit = 0; 4481 mCodec->mRepeatFrameDelayUs = -1ll; 4482 mCodec->mInputFormat.clear(); 4483 mCodec->mOutputFormat.clear(); 4484 4485 if (mCodec->mShutdownInProgress) { 4486 bool keepComponentAllocated = mCodec->mKeepComponentAllocated; 4487 4488 mCodec->mShutdownInProgress = false; 4489 mCodec->mKeepComponentAllocated = false; 4490 4491 onShutdown(keepComponentAllocated); 4492 } 4493 mCodec->mExplicitShutdown = false; 4494} 4495 4496void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) { 4497 if (!keepComponentAllocated) { 4498 CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK); 4499 4500 mCodec->changeState(mCodec->mUninitializedState); 4501 } 4502 4503 if (mCodec->mExplicitShutdown) { 4504 sp<AMessage> notify = mCodec->mNotify->dup(); 4505 notify->setInt32("what", CodecBase::kWhatShutdownCompleted); 4506 notify->post(); 4507 mCodec->mExplicitShutdown = false; 4508 } 4509} 4510 4511bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) { 4512 bool handled = false; 4513 4514 switch (msg->what()) { 4515 case ACodec::kWhatConfigureComponent: 4516 { 4517 onConfigureComponent(msg); 4518 handled = true; 4519 break; 4520 } 4521 4522 case ACodec::kWhatCreateInputSurface: 4523 { 4524 onCreateInputSurface(msg); 4525 handled = true; 4526 break; 4527 } 4528 4529 case ACodec::kWhatStart: 4530 { 4531 onStart(); 4532 handled = true; 4533 break; 4534 } 4535 4536 case ACodec::kWhatShutdown: 4537 { 4538 int32_t keepComponentAllocated; 4539 CHECK(msg->findInt32( 4540 "keepComponentAllocated", &keepComponentAllocated)); 4541 4542 mCodec->mExplicitShutdown = true; 4543 onShutdown(keepComponentAllocated); 4544 4545 handled = true; 4546 break; 4547 } 4548 4549 case ACodec::kWhatFlush: 4550 { 4551 sp<AMessage> notify = mCodec->mNotify->dup(); 4552 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 4553 notify->post(); 4554 4555 handled = true; 4556 break; 4557 } 4558 4559 default: 4560 return BaseState::onMessageReceived(msg); 4561 } 4562 4563 return handled; 4564} 4565 4566bool ACodec::LoadedState::onConfigureComponent( 4567 const sp<AMessage> &msg) { 4568 ALOGV("onConfigureComponent"); 4569 4570 CHECK(mCodec->mNode != NULL); 4571 4572 AString mime; 4573 CHECK(msg->findString("mime", &mime)); 4574 4575 status_t err = mCodec->configureCodec(mime.c_str(), msg); 4576 4577 if (err != OK) { 4578 ALOGE("[%s] configureCodec returning error %d", 4579 mCodec->mComponentName.c_str(), err); 4580 4581 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 4582 return false; 4583 } 4584 4585 sp<RefBase> obj; 4586 if (msg->findObject("native-window", &obj) 4587 && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) { 4588 sp<NativeWindowWrapper> nativeWindow( 4589 static_cast<NativeWindowWrapper *>(obj.get())); 4590 CHECK(nativeWindow != NULL); 4591 mCodec->mNativeWindow = nativeWindow->getNativeWindow(); 4592 4593 native_window_set_scaling_mode( 4594 mCodec->mNativeWindow.get(), 4595 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); 4596 } 4597 CHECK_EQ((status_t)OK, mCodec->initNativeWindow()); 4598 4599 { 4600 sp<AMessage> notify = mCodec->mNotify->dup(); 4601 notify->setInt32("what", CodecBase::kWhatComponentConfigured); 4602 notify->setMessage("input-format", mCodec->mInputFormat); 4603 notify->setMessage("output-format", mCodec->mOutputFormat); 4604 notify->post(); 4605 } 4606 4607 return true; 4608} 4609 4610void ACodec::LoadedState::onCreateInputSurface( 4611 const sp<AMessage> & /* msg */) { 4612 ALOGV("onCreateInputSurface"); 4613 4614 sp<AMessage> notify = mCodec->mNotify->dup(); 4615 notify->setInt32("what", CodecBase::kWhatInputSurfaceCreated); 4616 4617 sp<IGraphicBufferProducer> bufferProducer; 4618 status_t err; 4619 4620 err = mCodec->mOMX->createInputSurface(mCodec->mNode, kPortIndexInput, 4621 &bufferProducer); 4622 4623 if (err == OK && mCodec->mRepeatFrameDelayUs > 0ll) { 4624 err = mCodec->mOMX->setInternalOption( 4625 mCodec->mNode, 4626 kPortIndexInput, 4627 IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY, 4628 &mCodec->mRepeatFrameDelayUs, 4629 sizeof(mCodec->mRepeatFrameDelayUs)); 4630 4631 if (err != OK) { 4632 ALOGE("[%s] Unable to configure option to repeat previous " 4633 "frames (err %d)", 4634 mCodec->mComponentName.c_str(), 4635 err); 4636 } 4637 } 4638 4639 if (err == OK && mCodec->mMaxPtsGapUs > 0ll) { 4640 err = mCodec->mOMX->setInternalOption( 4641 mCodec->mNode, 4642 kPortIndexInput, 4643 IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP, 4644 &mCodec->mMaxPtsGapUs, 4645 sizeof(mCodec->mMaxPtsGapUs)); 4646 4647 if (err != OK) { 4648 ALOGE("[%s] Unable to configure max timestamp gap (err %d)", 4649 mCodec->mComponentName.c_str(), 4650 err); 4651 } 4652 } 4653 4654 if (err == OK && mCodec->mTimePerCaptureUs > 0ll 4655 && mCodec->mTimePerFrameUs > 0ll) { 4656 int64_t timeLapse[2]; 4657 timeLapse[0] = mCodec->mTimePerFrameUs; 4658 timeLapse[1] = mCodec->mTimePerCaptureUs; 4659 err = mCodec->mOMX->setInternalOption( 4660 mCodec->mNode, 4661 kPortIndexInput, 4662 IOMX::INTERNAL_OPTION_TIME_LAPSE, 4663 &timeLapse[0], 4664 sizeof(timeLapse)); 4665 4666 if (err != OK) { 4667 ALOGE("[%s] Unable to configure time lapse (err %d)", 4668 mCodec->mComponentName.c_str(), 4669 err); 4670 } 4671 } 4672 4673 if (err == OK && mCodec->mCreateInputBuffersSuspended) { 4674 bool suspend = true; 4675 err = mCodec->mOMX->setInternalOption( 4676 mCodec->mNode, 4677 kPortIndexInput, 4678 IOMX::INTERNAL_OPTION_SUSPEND, 4679 &suspend, 4680 sizeof(suspend)); 4681 4682 if (err != OK) { 4683 ALOGE("[%s] Unable to configure option to suspend (err %d)", 4684 mCodec->mComponentName.c_str(), 4685 err); 4686 } 4687 } 4688 4689 if (err == OK) { 4690 notify->setObject("input-surface", 4691 new BufferProducerWrapper(bufferProducer)); 4692 } else { 4693 // Can't use mCodec->signalError() here -- MediaCodec won't forward 4694 // the error through because it's in the "configured" state. We 4695 // send a kWhatInputSurfaceCreated with an error value instead. 4696 ALOGE("[%s] onCreateInputSurface returning error %d", 4697 mCodec->mComponentName.c_str(), err); 4698 notify->setInt32("err", err); 4699 } 4700 notify->post(); 4701} 4702 4703void ACodec::LoadedState::onStart() { 4704 ALOGV("onStart"); 4705 4706 CHECK_EQ(mCodec->mOMX->sendCommand( 4707 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle), 4708 (status_t)OK); 4709 4710 mCodec->changeState(mCodec->mLoadedToIdleState); 4711} 4712 4713//////////////////////////////////////////////////////////////////////////////// 4714 4715ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec) 4716 : BaseState(codec) { 4717} 4718 4719void ACodec::LoadedToIdleState::stateEntered() { 4720 ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str()); 4721 4722 status_t err; 4723 if ((err = allocateBuffers()) != OK) { 4724 ALOGE("Failed to allocate buffers after transitioning to IDLE state " 4725 "(error 0x%08x)", 4726 err); 4727 4728 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 4729 4730 mCodec->changeState(mCodec->mLoadedState); 4731 } 4732} 4733 4734status_t ACodec::LoadedToIdleState::allocateBuffers() { 4735 status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput); 4736 4737 if (err != OK) { 4738 return err; 4739 } 4740 4741 return mCodec->allocateBuffersOnPort(kPortIndexOutput); 4742} 4743 4744bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) { 4745 switch (msg->what()) { 4746 case kWhatSetParameters: 4747 case kWhatShutdown: 4748 { 4749 mCodec->deferMessage(msg); 4750 return true; 4751 } 4752 4753 case kWhatSignalEndOfInputStream: 4754 { 4755 mCodec->onSignalEndOfInputStream(); 4756 return true; 4757 } 4758 4759 case kWhatResume: 4760 { 4761 // We'll be active soon enough. 4762 return true; 4763 } 4764 4765 case kWhatFlush: 4766 { 4767 // We haven't even started yet, so we're flushed alright... 4768 sp<AMessage> notify = mCodec->mNotify->dup(); 4769 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 4770 notify->post(); 4771 return true; 4772 } 4773 4774 default: 4775 return BaseState::onMessageReceived(msg); 4776 } 4777} 4778 4779bool ACodec::LoadedToIdleState::onOMXEvent( 4780 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 4781 switch (event) { 4782 case OMX_EventCmdComplete: 4783 { 4784 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 4785 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); 4786 4787 CHECK_EQ(mCodec->mOMX->sendCommand( 4788 mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting), 4789 (status_t)OK); 4790 4791 mCodec->changeState(mCodec->mIdleToExecutingState); 4792 4793 return true; 4794 } 4795 4796 default: 4797 return BaseState::onOMXEvent(event, data1, data2); 4798 } 4799} 4800 4801//////////////////////////////////////////////////////////////////////////////// 4802 4803ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec) 4804 : BaseState(codec) { 4805} 4806 4807void ACodec::IdleToExecutingState::stateEntered() { 4808 ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str()); 4809} 4810 4811bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) { 4812 switch (msg->what()) { 4813 case kWhatSetParameters: 4814 case kWhatShutdown: 4815 { 4816 mCodec->deferMessage(msg); 4817 return true; 4818 } 4819 4820 case kWhatResume: 4821 { 4822 // We'll be active soon enough. 4823 return true; 4824 } 4825 4826 case kWhatFlush: 4827 { 4828 // We haven't even started yet, so we're flushed alright... 4829 sp<AMessage> notify = mCodec->mNotify->dup(); 4830 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 4831 notify->post(); 4832 4833 return true; 4834 } 4835 4836 case kWhatSignalEndOfInputStream: 4837 { 4838 mCodec->onSignalEndOfInputStream(); 4839 return true; 4840 } 4841 4842 default: 4843 return BaseState::onMessageReceived(msg); 4844 } 4845} 4846 4847bool ACodec::IdleToExecutingState::onOMXEvent( 4848 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 4849 switch (event) { 4850 case OMX_EventCmdComplete: 4851 { 4852 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 4853 CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting); 4854 4855 mCodec->mExecutingState->resume(); 4856 mCodec->changeState(mCodec->mExecutingState); 4857 4858 return true; 4859 } 4860 4861 default: 4862 return BaseState::onOMXEvent(event, data1, data2); 4863 } 4864} 4865 4866//////////////////////////////////////////////////////////////////////////////// 4867 4868ACodec::ExecutingState::ExecutingState(ACodec *codec) 4869 : BaseState(codec), 4870 mActive(false) { 4871} 4872 4873ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode( 4874 OMX_U32 /* portIndex */) { 4875 return RESUBMIT_BUFFERS; 4876} 4877 4878void ACodec::ExecutingState::submitOutputMetaBuffers() { 4879 // submit as many buffers as there are input buffers with the codec 4880 // in case we are in port reconfiguring 4881 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 4882 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 4883 4884 if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) { 4885 if (mCodec->submitOutputMetaDataBuffer() != OK) 4886 break; 4887 } 4888 } 4889 4890 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** 4891 mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround(); 4892} 4893 4894void ACodec::ExecutingState::submitRegularOutputBuffers() { 4895 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) { 4896 BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i); 4897 4898 if (mCodec->mNativeWindow != NULL) { 4899 CHECK(info->mStatus == BufferInfo::OWNED_BY_US 4900 || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW); 4901 4902 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 4903 continue; 4904 } 4905 } else { 4906 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 4907 } 4908 4909 ALOGV("[%s] calling fillBuffer %p", 4910 mCodec->mComponentName.c_str(), info->mBufferID); 4911 4912 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), 4913 (status_t)OK); 4914 4915 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 4916 } 4917} 4918 4919void ACodec::ExecutingState::submitOutputBuffers() { 4920 submitRegularOutputBuffers(); 4921 if (mCodec->mStoreMetaDataInOutputBuffers) { 4922 submitOutputMetaBuffers(); 4923 } 4924} 4925 4926void ACodec::ExecutingState::resume() { 4927 if (mActive) { 4928 ALOGV("[%s] We're already active, no need to resume.", 4929 mCodec->mComponentName.c_str()); 4930 4931 return; 4932 } 4933 4934 submitOutputBuffers(); 4935 4936 // Post all available input buffers 4937 CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u); 4938 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) { 4939 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 4940 if (info->mStatus == BufferInfo::OWNED_BY_US) { 4941 postFillThisBuffer(info); 4942 } 4943 } 4944 4945 mActive = true; 4946} 4947 4948void ACodec::ExecutingState::stateEntered() { 4949 ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str()); 4950 4951 mCodec->processDeferredMessages(); 4952} 4953 4954bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) { 4955 bool handled = false; 4956 4957 switch (msg->what()) { 4958 case kWhatShutdown: 4959 { 4960 int32_t keepComponentAllocated; 4961 CHECK(msg->findInt32( 4962 "keepComponentAllocated", &keepComponentAllocated)); 4963 4964 mCodec->mShutdownInProgress = true; 4965 mCodec->mExplicitShutdown = true; 4966 mCodec->mKeepComponentAllocated = keepComponentAllocated; 4967 4968 mActive = false; 4969 4970 CHECK_EQ(mCodec->mOMX->sendCommand( 4971 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle), 4972 (status_t)OK); 4973 4974 mCodec->changeState(mCodec->mExecutingToIdleState); 4975 4976 handled = true; 4977 break; 4978 } 4979 4980 case kWhatFlush: 4981 { 4982 ALOGV("[%s] ExecutingState flushing now " 4983 "(codec owns %d/%d input, %d/%d output).", 4984 mCodec->mComponentName.c_str(), 4985 mCodec->countBuffersOwnedByComponent(kPortIndexInput), 4986 mCodec->mBuffers[kPortIndexInput].size(), 4987 mCodec->countBuffersOwnedByComponent(kPortIndexOutput), 4988 mCodec->mBuffers[kPortIndexOutput].size()); 4989 4990 mActive = false; 4991 4992 CHECK_EQ(mCodec->mOMX->sendCommand( 4993 mCodec->mNode, OMX_CommandFlush, OMX_ALL), 4994 (status_t)OK); 4995 4996 mCodec->changeState(mCodec->mFlushingState); 4997 handled = true; 4998 break; 4999 } 5000 5001 case kWhatResume: 5002 { 5003 resume(); 5004 5005 handled = true; 5006 break; 5007 } 5008 5009 case kWhatRequestIDRFrame: 5010 { 5011 status_t err = mCodec->requestIDRFrame(); 5012 if (err != OK) { 5013 ALOGW("Requesting an IDR frame failed."); 5014 } 5015 5016 handled = true; 5017 break; 5018 } 5019 5020 case kWhatSetParameters: 5021 { 5022 sp<AMessage> params; 5023 CHECK(msg->findMessage("params", ¶ms)); 5024 5025 status_t err = mCodec->setParameters(params); 5026 5027 sp<AMessage> reply; 5028 if (msg->findMessage("reply", &reply)) { 5029 reply->setInt32("err", err); 5030 reply->post(); 5031 } 5032 5033 handled = true; 5034 break; 5035 } 5036 5037 case ACodec::kWhatSignalEndOfInputStream: 5038 { 5039 mCodec->onSignalEndOfInputStream(); 5040 handled = true; 5041 break; 5042 } 5043 5044 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** 5045 case kWhatSubmitOutputMetaDataBufferIfEOS: 5046 { 5047 if (mCodec->mPortEOS[kPortIndexInput] && 5048 !mCodec->mPortEOS[kPortIndexOutput]) { 5049 status_t err = mCodec->submitOutputMetaDataBuffer(); 5050 if (err == OK) { 5051 mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround(); 5052 } 5053 } 5054 return true; 5055 } 5056 5057 default: 5058 handled = BaseState::onMessageReceived(msg); 5059 break; 5060 } 5061 5062 return handled; 5063} 5064 5065status_t ACodec::setParameters(const sp<AMessage> ¶ms) { 5066 int32_t videoBitrate; 5067 if (params->findInt32("video-bitrate", &videoBitrate)) { 5068 OMX_VIDEO_CONFIG_BITRATETYPE configParams; 5069 InitOMXParams(&configParams); 5070 configParams.nPortIndex = kPortIndexOutput; 5071 configParams.nEncodeBitrate = videoBitrate; 5072 5073 status_t err = mOMX->setConfig( 5074 mNode, 5075 OMX_IndexConfigVideoBitrate, 5076 &configParams, 5077 sizeof(configParams)); 5078 5079 if (err != OK) { 5080 ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d", 5081 videoBitrate, err); 5082 5083 return err; 5084 } 5085 } 5086 5087 int64_t skipFramesBeforeUs; 5088 if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) { 5089 status_t err = 5090 mOMX->setInternalOption( 5091 mNode, 5092 kPortIndexInput, 5093 IOMX::INTERNAL_OPTION_START_TIME, 5094 &skipFramesBeforeUs, 5095 sizeof(skipFramesBeforeUs)); 5096 5097 if (err != OK) { 5098 ALOGE("Failed to set parameter 'skip-frames-before' (err %d)", err); 5099 return err; 5100 } 5101 } 5102 5103 int32_t dropInputFrames; 5104 if (params->findInt32("drop-input-frames", &dropInputFrames)) { 5105 bool suspend = dropInputFrames != 0; 5106 5107 status_t err = 5108 mOMX->setInternalOption( 5109 mNode, 5110 kPortIndexInput, 5111 IOMX::INTERNAL_OPTION_SUSPEND, 5112 &suspend, 5113 sizeof(suspend)); 5114 5115 if (err != OK) { 5116 ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err); 5117 return err; 5118 } 5119 } 5120 5121 int32_t dummy; 5122 if (params->findInt32("request-sync", &dummy)) { 5123 status_t err = requestIDRFrame(); 5124 5125 if (err != OK) { 5126 ALOGE("Requesting a sync frame failed w/ err %d", err); 5127 return err; 5128 } 5129 } 5130 5131 return OK; 5132} 5133 5134void ACodec::onSignalEndOfInputStream() { 5135 sp<AMessage> notify = mNotify->dup(); 5136 notify->setInt32("what", CodecBase::kWhatSignaledInputEOS); 5137 5138 status_t err = mOMX->signalEndOfInputStream(mNode); 5139 if (err != OK) { 5140 notify->setInt32("err", err); 5141 } 5142 notify->post(); 5143} 5144 5145bool ACodec::ExecutingState::onOMXEvent( 5146 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 5147 switch (event) { 5148 case OMX_EventPortSettingsChanged: 5149 { 5150 CHECK_EQ(data1, (OMX_U32)kPortIndexOutput); 5151 5152 if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) { 5153 mCodec->mMetaDataBuffersToSubmit = 0; 5154 CHECK_EQ(mCodec->mOMX->sendCommand( 5155 mCodec->mNode, 5156 OMX_CommandPortDisable, kPortIndexOutput), 5157 (status_t)OK); 5158 5159 mCodec->freeOutputBuffersNotOwnedByComponent(); 5160 5161 mCodec->changeState(mCodec->mOutputPortSettingsChangedState); 5162 } else if (data2 == OMX_IndexConfigCommonOutputCrop) { 5163 mCodec->mSentFormat = false; 5164 } else { 5165 ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx", 5166 mCodec->mComponentName.c_str(), data2); 5167 } 5168 5169 return true; 5170 } 5171 5172 case OMX_EventBufferFlag: 5173 { 5174 return true; 5175 } 5176 5177 default: 5178 return BaseState::onOMXEvent(event, data1, data2); 5179 } 5180} 5181 5182//////////////////////////////////////////////////////////////////////////////// 5183 5184ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState( 5185 ACodec *codec) 5186 : BaseState(codec) { 5187} 5188 5189ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode( 5190 OMX_U32 portIndex) { 5191 if (portIndex == kPortIndexOutput) { 5192 return FREE_BUFFERS; 5193 } 5194 5195 CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput); 5196 5197 return RESUBMIT_BUFFERS; 5198} 5199 5200bool ACodec::OutputPortSettingsChangedState::onMessageReceived( 5201 const sp<AMessage> &msg) { 5202 bool handled = false; 5203 5204 switch (msg->what()) { 5205 case kWhatFlush: 5206 case kWhatShutdown: 5207 case kWhatResume: 5208 { 5209 if (msg->what() == kWhatResume) { 5210 ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str()); 5211 } 5212 5213 mCodec->deferMessage(msg); 5214 handled = true; 5215 break; 5216 } 5217 5218 default: 5219 handled = BaseState::onMessageReceived(msg); 5220 break; 5221 } 5222 5223 return handled; 5224} 5225 5226void ACodec::OutputPortSettingsChangedState::stateEntered() { 5227 ALOGV("[%s] Now handling output port settings change", 5228 mCodec->mComponentName.c_str()); 5229} 5230 5231bool ACodec::OutputPortSettingsChangedState::onOMXEvent( 5232 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 5233 switch (event) { 5234 case OMX_EventCmdComplete: 5235 { 5236 if (data1 == (OMX_U32)OMX_CommandPortDisable) { 5237 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput); 5238 5239 ALOGV("[%s] Output port now disabled.", 5240 mCodec->mComponentName.c_str()); 5241 5242 CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty()); 5243 mCodec->mDealer[kPortIndexOutput].clear(); 5244 5245 CHECK_EQ(mCodec->mOMX->sendCommand( 5246 mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput), 5247 (status_t)OK); 5248 5249 status_t err; 5250 if ((err = mCodec->allocateBuffersOnPort( 5251 kPortIndexOutput)) != OK) { 5252 ALOGE("Failed to allocate output port buffers after " 5253 "port reconfiguration (error 0x%08x)", 5254 err); 5255 5256 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 5257 5258 // This is technically not correct, but appears to be 5259 // the only way to free the component instance. 5260 // Controlled transitioning from excecuting->idle 5261 // and idle->loaded seem impossible probably because 5262 // the output port never finishes re-enabling. 5263 mCodec->mShutdownInProgress = true; 5264 mCodec->mKeepComponentAllocated = false; 5265 mCodec->changeState(mCodec->mLoadedState); 5266 } 5267 5268 return true; 5269 } else if (data1 == (OMX_U32)OMX_CommandPortEnable) { 5270 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput); 5271 5272 mCodec->mSentFormat = false; 5273 5274 ALOGV("[%s] Output port now reenabled.", 5275 mCodec->mComponentName.c_str()); 5276 5277 if (mCodec->mExecutingState->active()) { 5278 mCodec->mExecutingState->submitOutputBuffers(); 5279 } 5280 5281 mCodec->changeState(mCodec->mExecutingState); 5282 5283 return true; 5284 } 5285 5286 return false; 5287 } 5288 5289 default: 5290 return false; 5291 } 5292} 5293 5294//////////////////////////////////////////////////////////////////////////////// 5295 5296ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec) 5297 : BaseState(codec), 5298 mComponentNowIdle(false) { 5299} 5300 5301bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) { 5302 bool handled = false; 5303 5304 switch (msg->what()) { 5305 case kWhatFlush: 5306 { 5307 // Don't send me a flush request if you previously wanted me 5308 // to shutdown. 5309 TRESPASS(); 5310 break; 5311 } 5312 5313 case kWhatShutdown: 5314 { 5315 // We're already doing that... 5316 5317 handled = true; 5318 break; 5319 } 5320 5321 default: 5322 handled = BaseState::onMessageReceived(msg); 5323 break; 5324 } 5325 5326 return handled; 5327} 5328 5329void ACodec::ExecutingToIdleState::stateEntered() { 5330 ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str()); 5331 5332 mComponentNowIdle = false; 5333 mCodec->mSentFormat = false; 5334} 5335 5336bool ACodec::ExecutingToIdleState::onOMXEvent( 5337 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 5338 switch (event) { 5339 case OMX_EventCmdComplete: 5340 { 5341 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 5342 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); 5343 5344 mComponentNowIdle = true; 5345 5346 changeStateIfWeOwnAllBuffers(); 5347 5348 return true; 5349 } 5350 5351 case OMX_EventPortSettingsChanged: 5352 case OMX_EventBufferFlag: 5353 { 5354 // We're shutting down and don't care about this anymore. 5355 return true; 5356 } 5357 5358 default: 5359 return BaseState::onOMXEvent(event, data1, data2); 5360 } 5361} 5362 5363void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() { 5364 if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) { 5365 CHECK_EQ(mCodec->mOMX->sendCommand( 5366 mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded), 5367 (status_t)OK); 5368 5369 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK); 5370 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK); 5371 5372 if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown) 5373 && mCodec->mNativeWindow != NULL) { 5374 // We push enough 1x1 blank buffers to ensure that one of 5375 // them has made it to the display. This allows the OMX 5376 // component teardown to zero out any protected buffers 5377 // without the risk of scanning out one of those buffers. 5378 mCodec->pushBlankBuffersToNativeWindow(); 5379 } 5380 5381 mCodec->changeState(mCodec->mIdleToLoadedState); 5382 } 5383} 5384 5385void ACodec::ExecutingToIdleState::onInputBufferFilled( 5386 const sp<AMessage> &msg) { 5387 BaseState::onInputBufferFilled(msg); 5388 5389 changeStateIfWeOwnAllBuffers(); 5390} 5391 5392void ACodec::ExecutingToIdleState::onOutputBufferDrained( 5393 const sp<AMessage> &msg) { 5394 BaseState::onOutputBufferDrained(msg); 5395 5396 changeStateIfWeOwnAllBuffers(); 5397} 5398 5399//////////////////////////////////////////////////////////////////////////////// 5400 5401ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec) 5402 : BaseState(codec) { 5403} 5404 5405bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) { 5406 bool handled = false; 5407 5408 switch (msg->what()) { 5409 case kWhatShutdown: 5410 { 5411 // We're already doing that... 5412 5413 handled = true; 5414 break; 5415 } 5416 5417 case kWhatFlush: 5418 { 5419 // Don't send me a flush request if you previously wanted me 5420 // to shutdown. 5421 TRESPASS(); 5422 break; 5423 } 5424 5425 default: 5426 handled = BaseState::onMessageReceived(msg); 5427 break; 5428 } 5429 5430 return handled; 5431} 5432 5433void ACodec::IdleToLoadedState::stateEntered() { 5434 ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str()); 5435} 5436 5437bool ACodec::IdleToLoadedState::onOMXEvent( 5438 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 5439 switch (event) { 5440 case OMX_EventCmdComplete: 5441 { 5442 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 5443 CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded); 5444 5445 mCodec->changeState(mCodec->mLoadedState); 5446 5447 return true; 5448 } 5449 5450 default: 5451 return BaseState::onOMXEvent(event, data1, data2); 5452 } 5453} 5454 5455//////////////////////////////////////////////////////////////////////////////// 5456 5457ACodec::FlushingState::FlushingState(ACodec *codec) 5458 : BaseState(codec) { 5459} 5460 5461void ACodec::FlushingState::stateEntered() { 5462 ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str()); 5463 5464 mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false; 5465} 5466 5467bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) { 5468 bool handled = false; 5469 5470 switch (msg->what()) { 5471 case kWhatShutdown: 5472 { 5473 mCodec->deferMessage(msg); 5474 break; 5475 } 5476 5477 case kWhatFlush: 5478 { 5479 // We're already doing this right now. 5480 handled = true; 5481 break; 5482 } 5483 5484 default: 5485 handled = BaseState::onMessageReceived(msg); 5486 break; 5487 } 5488 5489 return handled; 5490} 5491 5492bool ACodec::FlushingState::onOMXEvent( 5493 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 5494 ALOGV("[%s] FlushingState onOMXEvent(%d,%ld)", 5495 mCodec->mComponentName.c_str(), event, data1); 5496 5497 switch (event) { 5498 case OMX_EventCmdComplete: 5499 { 5500 CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush); 5501 5502 if (data2 == kPortIndexInput || data2 == kPortIndexOutput) { 5503 CHECK(!mFlushComplete[data2]); 5504 mFlushComplete[data2] = true; 5505 5506 if (mFlushComplete[kPortIndexInput] 5507 && mFlushComplete[kPortIndexOutput]) { 5508 changeStateIfWeOwnAllBuffers(); 5509 } 5510 } else { 5511 CHECK_EQ(data2, OMX_ALL); 5512 CHECK(mFlushComplete[kPortIndexInput]); 5513 CHECK(mFlushComplete[kPortIndexOutput]); 5514 5515 changeStateIfWeOwnAllBuffers(); 5516 } 5517 5518 return true; 5519 } 5520 5521 case OMX_EventPortSettingsChanged: 5522 { 5523 sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id()); 5524 msg->setInt32("type", omx_message::EVENT); 5525 msg->setInt32("node", mCodec->mNode); 5526 msg->setInt32("event", event); 5527 msg->setInt32("data1", data1); 5528 msg->setInt32("data2", data2); 5529 5530 ALOGV("[%s] Deferring OMX_EventPortSettingsChanged", 5531 mCodec->mComponentName.c_str()); 5532 5533 mCodec->deferMessage(msg); 5534 5535 return true; 5536 } 5537 5538 default: 5539 return BaseState::onOMXEvent(event, data1, data2); 5540 } 5541 5542 return true; 5543} 5544 5545void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) { 5546 BaseState::onOutputBufferDrained(msg); 5547 5548 changeStateIfWeOwnAllBuffers(); 5549} 5550 5551void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) { 5552 BaseState::onInputBufferFilled(msg); 5553 5554 changeStateIfWeOwnAllBuffers(); 5555} 5556 5557void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() { 5558 if (mFlushComplete[kPortIndexInput] 5559 && mFlushComplete[kPortIndexOutput] 5560 && mCodec->allYourBuffersAreBelongToUs()) { 5561 // We now own all buffers except possibly those still queued with 5562 // the native window for rendering. Let's get those back as well. 5563 mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs(); 5564 5565 sp<AMessage> notify = mCodec->mNotify->dup(); 5566 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 5567 notify->post(); 5568 5569 mCodec->mPortEOS[kPortIndexInput] = 5570 mCodec->mPortEOS[kPortIndexOutput] = false; 5571 5572 mCodec->mInputEOSResult = OK; 5573 5574 if (mCodec->mSkipCutBuffer != NULL) { 5575 mCodec->mSkipCutBuffer->clear(); 5576 } 5577 5578 mCodec->changeState(mCodec->mExecutingState); 5579 } 5580} 5581 5582} // namespace android 5583