ACodec.cpp revision b635b0e66b257ab442e230bca96afd5105cf6829
12e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson/* 22e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson * Copyright (C) 2010 The Android Open Source Project 32e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson * 42e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson * Licensed under the Apache License, Version 2.0 (the "License"); 52e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson * you may not use this file except in compliance with the License. 62e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson * You may obtain a copy of the License at 72e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson * 82e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson * http://www.apache.org/licenses/LICENSE-2.0 92e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson * 102e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson * Unless required by applicable law or agreed to in writing, software 112e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson * distributed under the License is distributed on an "AS IS" BASIS, 122e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson * See the License for the specific language governing permissions and 142e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson * limitations under the License. 152e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson */ 162e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson 172e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson//#define LOG_NDEBUG 0 182e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson#define LOG_TAG "ACodec" 192e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson 20b574627ebc383d35cf8212ee241b191b26518a0dJason Monk#include <media/stagefright/ACodec.h> 212e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson 22cd686b5b6d4166b510df8e32138479a9559bc117John Spurlock#include <binder/MemoryDealer.h> 23b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 242e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson#include <media/stagefright/foundation/hexdump.h> 252e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson#include <media/stagefright/foundation/ABuffer.h> 262f7dfa7afdaada78c46bd6fd7e307656ba3dd66aJohn Spurlock#include <media/stagefright/foundation/ADebug.h> 272e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson#include <media/stagefright/foundation/AMessage.h> 282e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson 292e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson#include <media/stagefright/BufferProducerWrapper.h> 302e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson#include <media/stagefright/MediaCodecList.h> 31af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock#include <media/stagefright/MediaDefs.h> 323128f12f216ef481b5d03892b35706cfeec26d7cJason Monk#include <media/stagefright/NativeWindowWrapper.h> 332e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson#include <media/stagefright/OMXClient.h> 34b574627ebc383d35cf8212ee241b191b26518a0dJason Monk#include <media/stagefright/OMXCodec.h> 35b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 36b574627ebc383d35cf8212ee241b191b26518a0dJason Monk#include <media/hardware/HardwareAPI.h> 375ccff81a642844138b144ad2cc339eba188812a0Daniel Sandler 382e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson#include <OMX_Component.h> 392f7dfa7afdaada78c46bd6fd7e307656ba3dd66aJohn Spurlock 403128f12f216ef481b5d03892b35706cfeec26d7cJason Monk#include "include/avc_utils.h" 413128f12f216ef481b5d03892b35706cfeec26d7cJason Monk 422e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertsonnamespace android { 4328f89d40ee7bab93cf7b783f92dbb18bdc43e473Daniel Sandler 44b3eb89190c4bb4ebbe676328cd37830d50e6ed3eJohn Spurlocktemplate<class T> 452f7dfa7afdaada78c46bd6fd7e307656ba3dd66aJohn Spurlockstatic void InitOMXParams(T *params) { 46af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock params->nSize = sizeof(T); 473128f12f216ef481b5d03892b35706cfeec26d7cJason Monk params->nVersion.s.nVersionMajor = 1; 482e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson params->nVersion.s.nVersionMinor = 0; 49b574627ebc383d35cf8212ee241b191b26518a0dJason Monk params->nVersion.s.nRevision = 0; 503128f12f216ef481b5d03892b35706cfeec26d7cJason Monk params->nVersion.s.nStep = 0; 5128f89d40ee7bab93cf7b783f92dbb18bdc43e473Daniel Sandler} 52fcc901c10bffdfb9c6b31e676dec36b47d949979John Spurlock 535ccff81a642844138b144ad2cc339eba188812a0Daniel Sandlerstruct CodecObserver : public BnOMXObserver { 54061d43c2386dd8222448bb1bec017bf9a2367a4eAndrew Flynn CodecObserver() {} 55d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 56b574627ebc383d35cf8212ee241b191b26518a0dJason Monk void setNotificationMessage(const sp<AMessage> &msg) { 57b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mNotify = msg; 5828f89d40ee7bab93cf7b783f92dbb18bdc43e473Daniel Sandler } 59b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 60b574627ebc383d35cf8212ee241b191b26518a0dJason Monk // from IOMXObserver 615172dc2f36f9c417befd0957ce2ae20f9d083a88Jorim Jaggi virtual void onMessage(const omx_message &omx_msg) { 62c737b9bd5a0bc60fd92150d55f8ddb530697b987Jorim Jaggi sp<AMessage> msg = mNotify->dup(); 63b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 64c737b9bd5a0bc60fd92150d55f8ddb530697b987Jorim Jaggi msg->setInt32("type", omx_msg.type); 65c737b9bd5a0bc60fd92150d55f8ddb530697b987Jorim Jaggi msg->setPointer("node", omx_msg.node); 66b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 676d035f15d5c8c67d97a4d5b6ed44f8cca0772e1fJorim Jaggi switch (omx_msg.type) { 686d035f15d5c8c67d97a4d5b6ed44f8cca0772e1fJorim Jaggi case omx_message::EVENT: 692e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson { 702e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson msg->setInt32("event", omx_msg.u.event_data.event); 712e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson msg->setInt32("data1", omx_msg.u.event_data.data1); 722e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson msg->setInt32("data2", omx_msg.u.event_data.data2); 732e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson break; 742e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson } 752e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson 762e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson case omx_message::EMPTY_BUFFER_DONE: 772e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson { 782e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson msg->setPointer("buffer", omx_msg.u.buffer_data.buffer); 792e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson break; 802e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson } 812e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson 82af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock case omx_message::FILL_BUFFER_DONE: 83cd686b5b6d4166b510df8e32138479a9559bc117John Spurlock { 842e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson msg->setPointer( 852e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson "buffer", omx_msg.u.extended_buffer_data.buffer); 862e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson msg->setInt32( 873128f12f216ef481b5d03892b35706cfeec26d7cJason Monk "range_offset", 883128f12f216ef481b5d03892b35706cfeec26d7cJason Monk omx_msg.u.extended_buffer_data.range_offset); 893128f12f216ef481b5d03892b35706cfeec26d7cJason Monk msg->setInt32( 903128f12f216ef481b5d03892b35706cfeec26d7cJason Monk "range_length", 913128f12f216ef481b5d03892b35706cfeec26d7cJason Monk omx_msg.u.extended_buffer_data.range_length); 923128f12f216ef481b5d03892b35706cfeec26d7cJason Monk msg->setInt32( 933128f12f216ef481b5d03892b35706cfeec26d7cJason Monk "flags", 942e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson omx_msg.u.extended_buffer_data.flags); 95c737b9bd5a0bc60fd92150d55f8ddb530697b987Jorim Jaggi msg->setInt64( 96c737b9bd5a0bc60fd92150d55f8ddb530697b987Jorim Jaggi "timestamp", 97c737b9bd5a0bc60fd92150d55f8ddb530697b987Jorim Jaggi omx_msg.u.extended_buffer_data.timestamp); 98c737b9bd5a0bc60fd92150d55f8ddb530697b987Jorim Jaggi msg->setPointer( 99b574627ebc383d35cf8212ee241b191b26518a0dJason Monk "platform_private", 100b574627ebc383d35cf8212ee241b191b26518a0dJason Monk omx_msg.u.extended_buffer_data.platform_private); 1016d035f15d5c8c67d97a4d5b6ed44f8cca0772e1fJorim Jaggi msg->setPointer( 1026d035f15d5c8c67d97a4d5b6ed44f8cca0772e1fJorim Jaggi "data_ptr", 1036d035f15d5c8c67d97a4d5b6ed44f8cca0772e1fJorim Jaggi omx_msg.u.extended_buffer_data.data_ptr); 1046d035f15d5c8c67d97a4d5b6ed44f8cca0772e1fJorim Jaggi break; 105c737b9bd5a0bc60fd92150d55f8ddb530697b987Jorim Jaggi } 106c737b9bd5a0bc60fd92150d55f8ddb530697b987Jorim Jaggi 107c737b9bd5a0bc60fd92150d55f8ddb530697b987Jorim Jaggi default: 1082e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson TRESPASS(); 1092e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson break; 1102e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson } 1113128f12f216ef481b5d03892b35706cfeec26d7cJason Monk 1122e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson msg->post(); 1132e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson } 114061d43c2386dd8222448bb1bec017bf9a2367a4eAndrew Flynn 115b574627ebc383d35cf8212ee241b191b26518a0dJason Monkprotected: 1165172dc2f36f9c417befd0957ce2ae20f9d083a88Jorim Jaggi virtual ~CodecObserver() {} 117c737b9bd5a0bc60fd92150d55f8ddb530697b987Jorim Jaggi 118b574627ebc383d35cf8212ee241b191b26518a0dJason Monkprivate: 119b574627ebc383d35cf8212ee241b191b26518a0dJason Monk sp<AMessage> mNotify; 120b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 121b574627ebc383d35cf8212ee241b191b26518a0dJason Monk DISALLOW_EVIL_CONSTRUCTORS(CodecObserver); 12228f89d40ee7bab93cf7b783f92dbb18bdc43e473Daniel Sandler}; 12328f89d40ee7bab93cf7b783f92dbb18bdc43e473Daniel Sandler 1242e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson//////////////////////////////////////////////////////////////////////////////// 1252e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson 1262e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertsonstruct ACodec::BaseState : public AState { 1272e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson BaseState(ACodec *codec, const sp<AState> &parentState = NULL); 1283128f12f216ef481b5d03892b35706cfeec26d7cJason Monk 12928f89d40ee7bab93cf7b783f92dbb18bdc43e473Daniel Sandlerprotected: 13028f89d40ee7bab93cf7b783f92dbb18bdc43e473Daniel Sandler enum PortMode { 131061d43c2386dd8222448bb1bec017bf9a2367a4eAndrew Flynn KEEP_BUFFERS, 132b574627ebc383d35cf8212ee241b191b26518a0dJason Monk RESUBMIT_BUFFERS, 133b574627ebc383d35cf8212ee241b191b26518a0dJason Monk FREE_BUFFERS, 13428f89d40ee7bab93cf7b783f92dbb18bdc43e473Daniel Sandler }; 1352e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson 1362e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson ACodec *mCodec; 1372e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson 1383128f12f216ef481b5d03892b35706cfeec26d7cJason Monk virtual PortMode getPortMode(OMX_U32 portIndex); 1393128f12f216ef481b5d03892b35706cfeec26d7cJason Monk 1403128f12f216ef481b5d03892b35706cfeec26d7cJason Monk virtual bool onMessageReceived(const sp<AMessage> &msg); 1413128f12f216ef481b5d03892b35706cfeec26d7cJason Monk 1423128f12f216ef481b5d03892b35706cfeec26d7cJason Monk virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 1433128f12f216ef481b5d03892b35706cfeec26d7cJason Monk 1443128f12f216ef481b5d03892b35706cfeec26d7cJason Monk virtual void onOutputBufferDrained(const sp<AMessage> &msg); 1453128f12f216ef481b5d03892b35706cfeec26d7cJason Monk virtual void onInputBufferFilled(const sp<AMessage> &msg); 1463128f12f216ef481b5d03892b35706cfeec26d7cJason Monk 1473128f12f216ef481b5d03892b35706cfeec26d7cJason Monk void postFillThisBuffer(BufferInfo *info); 1483128f12f216ef481b5d03892b35706cfeec26d7cJason Monk 1493128f12f216ef481b5d03892b35706cfeec26d7cJason Monkprivate: 150061d43c2386dd8222448bb1bec017bf9a2367a4eAndrew Flynn bool onOMXMessage(const sp<AMessage> &msg); 151b3eb89190c4bb4ebbe676328cd37830d50e6ed3eJohn Spurlock 15228f89d40ee7bab93cf7b783f92dbb18bdc43e473Daniel Sandler bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID); 15328f89d40ee7bab93cf7b783f92dbb18bdc43e473Daniel Sandler 154bcf6ef0b82c1daea43e03b8ad5af319ed324242aDaniel Sandler bool onOMXFillBufferDone( 15528f89d40ee7bab93cf7b783f92dbb18bdc43e473Daniel Sandler IOMX::buffer_id bufferID, 15628f89d40ee7bab93cf7b783f92dbb18bdc43e473Daniel Sandler size_t rangeOffset, size_t rangeLength, 15728f89d40ee7bab93cf7b783f92dbb18bdc43e473Daniel Sandler OMX_U32 flags, 15828f89d40ee7bab93cf7b783f92dbb18bdc43e473Daniel Sandler int64_t timeUs, 159061d43c2386dd8222448bb1bec017bf9a2367a4eAndrew Flynn void *platformPrivate, 160b3eb89190c4bb4ebbe676328cd37830d50e6ed3eJohn Spurlock void *dataPtr); 161b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 162b574627ebc383d35cf8212ee241b191b26518a0dJason Monk void getMoreInputDataIfPossible(); 163b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 164b574627ebc383d35cf8212ee241b191b26518a0dJason Monk DISALLOW_EVIL_CONSTRUCTORS(BaseState); 165b574627ebc383d35cf8212ee241b191b26518a0dJason Monk}; 166b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 167b574627ebc383d35cf8212ee241b191b26518a0dJason Monk//////////////////////////////////////////////////////////////////////////////// 168b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 169b574627ebc383d35cf8212ee241b191b26518a0dJason Monkstruct ACodec::DeathNotifier : public IBinder::DeathRecipient { 17028f89d40ee7bab93cf7b783f92dbb18bdc43e473Daniel Sandler DeathNotifier(const sp<AMessage> ¬ify) 17128f89d40ee7bab93cf7b783f92dbb18bdc43e473Daniel Sandler : mNotify(notify) { 17228f89d40ee7bab93cf7b783f92dbb18bdc43e473Daniel Sandler } 17328f89d40ee7bab93cf7b783f92dbb18bdc43e473Daniel Sandler 174061d43c2386dd8222448bb1bec017bf9a2367a4eAndrew Flynn virtual void binderDied(const wp<IBinder> &) { 175b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mNotify->post(); 176b574627ebc383d35cf8212ee241b191b26518a0dJason Monk } 177b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 178b574627ebc383d35cf8212ee241b191b26518a0dJason Monkprotected: 179b574627ebc383d35cf8212ee241b191b26518a0dJason Monk virtual ~DeathNotifier() {} 180b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 181b574627ebc383d35cf8212ee241b191b26518a0dJason Monkprivate: 182b574627ebc383d35cf8212ee241b191b26518a0dJason Monk sp<AMessage> mNotify; 183b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 184b574627ebc383d35cf8212ee241b191b26518a0dJason Monk DISALLOW_EVIL_CONSTRUCTORS(DeathNotifier); 185b574627ebc383d35cf8212ee241b191b26518a0dJason Monk}; 186b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 187b574627ebc383d35cf8212ee241b191b26518a0dJason Monkstruct ACodec::UninitializedState : public ACodec::BaseState { 188b574627ebc383d35cf8212ee241b191b26518a0dJason Monk UninitializedState(ACodec *codec); 189b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 190b574627ebc383d35cf8212ee241b191b26518a0dJason Monkprotected: 191b574627ebc383d35cf8212ee241b191b26518a0dJason Monk virtual bool onMessageReceived(const sp<AMessage> &msg); 192b574627ebc383d35cf8212ee241b191b26518a0dJason Monk virtual void stateEntered(); 193b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 194b574627ebc383d35cf8212ee241b191b26518a0dJason Monkprivate: 195b574627ebc383d35cf8212ee241b191b26518a0dJason Monk void onSetup(const sp<AMessage> &msg); 196b574627ebc383d35cf8212ee241b191b26518a0dJason Monk bool onAllocateComponent(const sp<AMessage> &msg); 197b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 198b574627ebc383d35cf8212ee241b191b26518a0dJason Monk sp<DeathNotifier> mDeathNotifier; 199b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 200b574627ebc383d35cf8212ee241b191b26518a0dJason Monk DISALLOW_EVIL_CONSTRUCTORS(UninitializedState); 201b574627ebc383d35cf8212ee241b191b26518a0dJason Monk}; 202b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 203b574627ebc383d35cf8212ee241b191b26518a0dJason Monk//////////////////////////////////////////////////////////////////////////////// 204b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 205b574627ebc383d35cf8212ee241b191b26518a0dJason Monkstruct ACodec::LoadedState : public ACodec::BaseState { 206b574627ebc383d35cf8212ee241b191b26518a0dJason Monk LoadedState(ACodec *codec); 207b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 208b574627ebc383d35cf8212ee241b191b26518a0dJason Monkprotected: 209b574627ebc383d35cf8212ee241b191b26518a0dJason Monk virtual bool onMessageReceived(const sp<AMessage> &msg); 210b574627ebc383d35cf8212ee241b191b26518a0dJason Monk virtual void stateEntered(); 211d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 2125ccff81a642844138b144ad2cc339eba188812a0Daniel Sandlerprivate: 213061d43c2386dd8222448bb1bec017bf9a2367a4eAndrew Flynn friend struct ACodec::UninitializedState; 214d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk 215061d43c2386dd8222448bb1bec017bf9a2367a4eAndrew Flynn bool onConfigureComponent(const sp<AMessage> &msg); 216061d43c2386dd8222448bb1bec017bf9a2367a4eAndrew Flynn void onCreateInputSurface(const sp<AMessage> &msg); 2175ccff81a642844138b144ad2cc339eba188812a0Daniel Sandler void onStart(); 2185ccff81a642844138b144ad2cc339eba188812a0Daniel Sandler void onShutdown(bool keepComponentAllocated); 2192f7dfa7afdaada78c46bd6fd7e307656ba3dd66aJohn Spurlock 2202f7dfa7afdaada78c46bd6fd7e307656ba3dd66aJohn Spurlock DISALLOW_EVIL_CONSTRUCTORS(LoadedState); 2212f7dfa7afdaada78c46bd6fd7e307656ba3dd66aJohn Spurlock}; 2222f7dfa7afdaada78c46bd6fd7e307656ba3dd66aJohn Spurlock 22324e028e0ec533cb7304296118a73bdc03870d10dDaniel Sandler//////////////////////////////////////////////////////////////////////////////// 2242f7dfa7afdaada78c46bd6fd7e307656ba3dd66aJohn Spurlock 225b574627ebc383d35cf8212ee241b191b26518a0dJason Monkstruct ACodec::LoadedToIdleState : public ACodec::BaseState { 226b574627ebc383d35cf8212ee241b191b26518a0dJason Monk LoadedToIdleState(ACodec *codec); 227b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 2282f7dfa7afdaada78c46bd6fd7e307656ba3dd66aJohn Spurlockprotected: 2292f7dfa7afdaada78c46bd6fd7e307656ba3dd66aJohn Spurlock virtual bool onMessageReceived(const sp<AMessage> &msg); 2302f7dfa7afdaada78c46bd6fd7e307656ba3dd66aJohn Spurlock virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 2314662611f3757bd9210f252c095f2bef278fa2043Fabrice Di Meglio virtual void stateEntered(); 2324662611f3757bd9210f252c095f2bef278fa2043Fabrice Di Meglio 2334662611f3757bd9210f252c095f2bef278fa2043Fabrice Di Meglioprivate: 2344662611f3757bd9210f252c095f2bef278fa2043Fabrice Di Meglio status_t allocateBuffers(); 2354662611f3757bd9210f252c095f2bef278fa2043Fabrice Di Meglio 2364662611f3757bd9210f252c095f2bef278fa2043Fabrice Di Meglio DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState); 2374662611f3757bd9210f252c095f2bef278fa2043Fabrice Di Meglio}; 2384662611f3757bd9210f252c095f2bef278fa2043Fabrice Di Meglio 239b574627ebc383d35cf8212ee241b191b26518a0dJason Monk//////////////////////////////////////////////////////////////////////////////// 240b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 241b574627ebc383d35cf8212ee241b191b26518a0dJason Monkstruct ACodec::IdleToExecutingState : public ACodec::BaseState { 242b574627ebc383d35cf8212ee241b191b26518a0dJason Monk IdleToExecutingState(ACodec *codec); 243b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 244b574627ebc383d35cf8212ee241b191b26518a0dJason Monkprotected: 245b574627ebc383d35cf8212ee241b191b26518a0dJason Monk virtual bool onMessageReceived(const sp<AMessage> &msg); 2464662611f3757bd9210f252c095f2bef278fa2043Fabrice Di Meglio virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 2474662611f3757bd9210f252c095f2bef278fa2043Fabrice Di Meglio virtual void stateEntered(); 2484662611f3757bd9210f252c095f2bef278fa2043Fabrice Di Meglio 2494662611f3757bd9210f252c095f2bef278fa2043Fabrice Di Meglioprivate: 2504662611f3757bd9210f252c095f2bef278fa2043Fabrice Di Meglio DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState); 2514662611f3757bd9210f252c095f2bef278fa2043Fabrice Di Meglio}; 2524662611f3757bd9210f252c095f2bef278fa2043Fabrice Di Meglio 2534662611f3757bd9210f252c095f2bef278fa2043Fabrice Di Meglio//////////////////////////////////////////////////////////////////////////////// 2544662611f3757bd9210f252c095f2bef278fa2043Fabrice Di Meglio 2550d266899da8f612194a8393ec69c4fd870f2f45cJorim Jaggistruct ACodec::ExecutingState : public ACodec::BaseState { 2560d266899da8f612194a8393ec69c4fd870f2f45cJorim Jaggi ExecutingState(ACodec *codec); 2570d266899da8f612194a8393ec69c4fd870f2f45cJorim Jaggi 2580d266899da8f612194a8393ec69c4fd870f2f45cJorim Jaggi void submitRegularOutputBuffers(); 2590d266899da8f612194a8393ec69c4fd870f2f45cJorim Jaggi void submitOutputMetaBuffers(); 26028f89d40ee7bab93cf7b783f92dbb18bdc43e473Daniel Sandler void submitOutputBuffers(); 26128f89d40ee7bab93cf7b783f92dbb18bdc43e473Daniel Sandler 2622e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson // Submit output buffers to the decoder, submit input buffers to client 2632e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson // to fill with data. 2643128f12f216ef481b5d03892b35706cfeec26d7cJason Monk void resume(); 2653128f12f216ef481b5d03892b35706cfeec26d7cJason Monk 26628f89d40ee7bab93cf7b783f92dbb18bdc43e473Daniel Sandler // Returns true iff input and output buffers are in play. 26728f89d40ee7bab93cf7b783f92dbb18bdc43e473Daniel Sandler bool active() const { return mActive; } 268bcf6ef0b82c1daea43e03b8ad5af319ed324242aDaniel Sandler 269cda096ebf3fac67daf36e775547c2a337374927bFabrice Di Meglioprotected: 2702e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson virtual PortMode getPortMode(OMX_U32 portIndex); 2712e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson virtual bool onMessageReceived(const sp<AMessage> &msg); 2722e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson virtual void stateEntered(); 2732e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson 274cd686b5b6d4166b510df8e32138479a9559bc117John Spurlock virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 275fcc901c10bffdfb9c6b31e676dec36b47d949979John Spurlock 27628f89d40ee7bab93cf7b783f92dbb18bdc43e473Daniel Sandlerprivate: 277fcc901c10bffdfb9c6b31e676dec36b47d949979John Spurlock bool mActive; 2782e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson 279b574627ebc383d35cf8212ee241b191b26518a0dJason Monk DISALLOW_EVIL_CONSTRUCTORS(ExecutingState); 280e912c9cc39807f95815400981ed27d121e8b293aDan Sandler}; 281b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 282b574627ebc383d35cf8212ee241b191b26518a0dJason Monk//////////////////////////////////////////////////////////////////////////////// 283e912c9cc39807f95815400981ed27d121e8b293aDan Sandler 284e912c9cc39807f95815400981ed27d121e8b293aDan Sandlerstruct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState { 285e912c9cc39807f95815400981ed27d121e8b293aDan Sandler OutputPortSettingsChangedState(ACodec *codec); 286e912c9cc39807f95815400981ed27d121e8b293aDan Sandler 287b574627ebc383d35cf8212ee241b191b26518a0dJason Monkprotected: 2882e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson virtual PortMode getPortMode(OMX_U32 portIndex); 28928f89d40ee7bab93cf7b783f92dbb18bdc43e473Daniel Sandler virtual bool onMessageReceived(const sp<AMessage> &msg); 290061d43c2386dd8222448bb1bec017bf9a2367a4eAndrew Flynn virtual void stateEntered(); 291061d43c2386dd8222448bb1bec017bf9a2367a4eAndrew Flynn 292d2263cd9db36d5f74a124c5ffaf8594ef702408fJason Monk virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 293b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 2948afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglioprivate: 295061d43c2386dd8222448bb1bec017bf9a2367a4eAndrew Flynn DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState); 296061d43c2386dd8222448bb1bec017bf9a2367a4eAndrew Flynn}; 297061d43c2386dd8222448bb1bec017bf9a2367a4eAndrew Flynn 298061d43c2386dd8222448bb1bec017bf9a2367a4eAndrew Flynn//////////////////////////////////////////////////////////////////////////////// 2995172dc2f36f9c417befd0957ce2ae20f9d083a88Jorim Jaggi 3005172dc2f36f9c417befd0957ce2ae20f9d083a88Jorim Jaggistruct ACodec::ExecutingToIdleState : public ACodec::BaseState { 3015ccff81a642844138b144ad2cc339eba188812a0Daniel Sandler ExecutingToIdleState(ACodec *codec); 3025172dc2f36f9c417befd0957ce2ae20f9d083a88Jorim Jaggi 3035ccff81a642844138b144ad2cc339eba188812a0Daniel Sandlerprotected: 3045ccff81a642844138b144ad2cc339eba188812a0Daniel Sandler virtual bool onMessageReceived(const sp<AMessage> &msg); 305e912c9cc39807f95815400981ed27d121e8b293aDan Sandler virtual void stateEntered(); 306c737b9bd5a0bc60fd92150d55f8ddb530697b987Jorim Jaggi 307c737b9bd5a0bc60fd92150d55f8ddb530697b987Jorim Jaggi virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 308c737b9bd5a0bc60fd92150d55f8ddb530697b987Jorim Jaggi 309c737b9bd5a0bc60fd92150d55f8ddb530697b987Jorim Jaggi virtual void onOutputBufferDrained(const sp<AMessage> &msg); 310c737b9bd5a0bc60fd92150d55f8ddb530697b987Jorim Jaggi virtual void onInputBufferFilled(const sp<AMessage> &msg); 311b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 312c737b9bd5a0bc60fd92150d55f8ddb530697b987Jorim Jaggiprivate: 313b574627ebc383d35cf8212ee241b191b26518a0dJason Monk void changeStateIfWeOwnAllBuffers(); 314b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 315b574627ebc383d35cf8212ee241b191b26518a0dJason Monk bool mComponentNowIdle; 316b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 31728f89d40ee7bab93cf7b783f92dbb18bdc43e473Daniel Sandler DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState); 318b574627ebc383d35cf8212ee241b191b26518a0dJason Monk}; 319b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 320b574627ebc383d35cf8212ee241b191b26518a0dJason Monk//////////////////////////////////////////////////////////////////////////////// 321b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 322b574627ebc383d35cf8212ee241b191b26518a0dJason Monkstruct ACodec::IdleToLoadedState : public ACodec::BaseState { 323b574627ebc383d35cf8212ee241b191b26518a0dJason Monk IdleToLoadedState(ACodec *codec); 324b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 325b574627ebc383d35cf8212ee241b191b26518a0dJason Monkprotected: 326b574627ebc383d35cf8212ee241b191b26518a0dJason Monk virtual bool onMessageReceived(const sp<AMessage> &msg); 327b574627ebc383d35cf8212ee241b191b26518a0dJason Monk virtual void stateEntered(); 328b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 329b574627ebc383d35cf8212ee241b191b26518a0dJason Monk virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 330b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 331b574627ebc383d35cf8212ee241b191b26518a0dJason Monkprivate: 332b574627ebc383d35cf8212ee241b191b26518a0dJason Monk DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState); 333b574627ebc383d35cf8212ee241b191b26518a0dJason Monk}; 3346d035f15d5c8c67d97a4d5b6ed44f8cca0772e1fJorim Jaggi 335b574627ebc383d35cf8212ee241b191b26518a0dJason Monk//////////////////////////////////////////////////////////////////////////////// 336b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 337b574627ebc383d35cf8212ee241b191b26518a0dJason Monkstruct ACodec::FlushingState : public ACodec::BaseState { 338b574627ebc383d35cf8212ee241b191b26518a0dJason Monk FlushingState(ACodec *codec); 339b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 340b574627ebc383d35cf8212ee241b191b26518a0dJason Monkprotected: 341b574627ebc383d35cf8212ee241b191b26518a0dJason Monk virtual bool onMessageReceived(const sp<AMessage> &msg); 342b574627ebc383d35cf8212ee241b191b26518a0dJason Monk virtual void stateEntered(); 343b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 344b574627ebc383d35cf8212ee241b191b26518a0dJason Monk virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 345b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 346b574627ebc383d35cf8212ee241b191b26518a0dJason Monk virtual void onOutputBufferDrained(const sp<AMessage> &msg); 347b574627ebc383d35cf8212ee241b191b26518a0dJason Monk virtual void onInputBufferFilled(const sp<AMessage> &msg); 348b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 349b574627ebc383d35cf8212ee241b191b26518a0dJason Monkprivate: 350b574627ebc383d35cf8212ee241b191b26518a0dJason Monk bool mFlushComplete[2]; 351b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 352b574627ebc383d35cf8212ee241b191b26518a0dJason Monk void changeStateIfWeOwnAllBuffers(); 353b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 354b574627ebc383d35cf8212ee241b191b26518a0dJason Monk DISALLOW_EVIL_CONSTRUCTORS(FlushingState); 355b574627ebc383d35cf8212ee241b191b26518a0dJason Monk}; 356b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 357b574627ebc383d35cf8212ee241b191b26518a0dJason Monk//////////////////////////////////////////////////////////////////////////////// 358b574627ebc383d35cf8212ee241b191b26518a0dJason Monk 359b574627ebc383d35cf8212ee241b191b26518a0dJason MonkACodec::ACodec() 360b574627ebc383d35cf8212ee241b191b26518a0dJason Monk : mQuirks(0), 361b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mNode(NULL), 362b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mSentFormat(false), 363b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mIsEncoder(false), 364b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mUseMetadataOnEncoderOutput(false), 365b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mShutdownInProgress(false), 366b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mIsConfiguredForAdaptivePlayback(false), 367b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mEncoderDelay(0), 368b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mEncoderPadding(0), 369b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mChannelMaskPresent(false), 370b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mChannelMask(0), 371b574627ebc383d35cf8212ee241b191b26518a0dJason Monk mDequeueCounter(0), 3722e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson mStoreMetaDataInOutputBuffers(false), 3732e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson mMetaDataBuffersToSubmit(0), 3742e347429dfcd03b0827c7506ba6305ab0d1f4951Christian Robertson mRepeatFrameDelayUs(-1ll), 375 mMaxPtsGapUs(-1l) { 376 mUninitializedState = new UninitializedState(this); 377 mLoadedState = new LoadedState(this); 378 mLoadedToIdleState = new LoadedToIdleState(this); 379 mIdleToExecutingState = new IdleToExecutingState(this); 380 mExecutingState = new ExecutingState(this); 381 382 mOutputPortSettingsChangedState = 383 new OutputPortSettingsChangedState(this); 384 385 mExecutingToIdleState = new ExecutingToIdleState(this); 386 mIdleToLoadedState = new IdleToLoadedState(this); 387 mFlushingState = new FlushingState(this); 388 389 mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false; 390 mInputEOSResult = OK; 391 392 changeState(mUninitializedState); 393} 394 395ACodec::~ACodec() { 396} 397 398void ACodec::setNotificationMessage(const sp<AMessage> &msg) { 399 mNotify = msg; 400} 401 402void ACodec::initiateSetup(const sp<AMessage> &msg) { 403 msg->setWhat(kWhatSetup); 404 msg->setTarget(id()); 405 msg->post(); 406} 407 408void ACodec::signalSetParameters(const sp<AMessage> ¶ms) { 409 sp<AMessage> msg = new AMessage(kWhatSetParameters, id()); 410 msg->setMessage("params", params); 411 msg->post(); 412} 413 414void ACodec::initiateAllocateComponent(const sp<AMessage> &msg) { 415 msg->setWhat(kWhatAllocateComponent); 416 msg->setTarget(id()); 417 msg->post(); 418} 419 420void ACodec::initiateConfigureComponent(const sp<AMessage> &msg) { 421 msg->setWhat(kWhatConfigureComponent); 422 msg->setTarget(id()); 423 msg->post(); 424} 425 426void ACodec::initiateCreateInputSurface() { 427 (new AMessage(kWhatCreateInputSurface, id()))->post(); 428} 429 430void ACodec::signalEndOfInputStream() { 431 (new AMessage(kWhatSignalEndOfInputStream, id()))->post(); 432} 433 434void ACodec::initiateStart() { 435 (new AMessage(kWhatStart, id()))->post(); 436} 437 438void ACodec::signalFlush() { 439 ALOGV("[%s] signalFlush", mComponentName.c_str()); 440 (new AMessage(kWhatFlush, id()))->post(); 441} 442 443void ACodec::signalResume() { 444 (new AMessage(kWhatResume, id()))->post(); 445} 446 447void ACodec::initiateShutdown(bool keepComponentAllocated) { 448 sp<AMessage> msg = new AMessage(kWhatShutdown, id()); 449 msg->setInt32("keepComponentAllocated", keepComponentAllocated); 450 msg->post(); 451} 452 453void ACodec::signalRequestIDRFrame() { 454 (new AMessage(kWhatRequestIDRFrame, id()))->post(); 455} 456 457// *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** 458// Some codecs may return input buffers before having them processed. 459// This causes a halt if we already signaled an EOS on the input 460// port. For now keep submitting an output buffer if there was an 461// EOS on the input port, but not yet on the output port. 462void ACodec::signalSubmitOutputMetaDataBufferIfEOS_workaround() { 463 if (mPortEOS[kPortIndexInput] && !mPortEOS[kPortIndexOutput] && 464 mMetaDataBuffersToSubmit > 0) { 465 (new AMessage(kWhatSubmitOutputMetaDataBufferIfEOS, id()))->post(); 466 } 467} 468 469status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) { 470 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 471 472 CHECK(mDealer[portIndex] == NULL); 473 CHECK(mBuffers[portIndex].isEmpty()); 474 475 status_t err; 476 if (mNativeWindow != NULL && portIndex == kPortIndexOutput) { 477 if (mStoreMetaDataInOutputBuffers) { 478 err = allocateOutputMetaDataBuffers(); 479 } else { 480 err = allocateOutputBuffersFromNativeWindow(); 481 } 482 } else { 483 OMX_PARAM_PORTDEFINITIONTYPE def; 484 InitOMXParams(&def); 485 def.nPortIndex = portIndex; 486 487 err = mOMX->getParameter( 488 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 489 490 if (err == OK) { 491 ALOGV("[%s] Allocating %lu buffers of size %lu on %s port", 492 mComponentName.c_str(), 493 def.nBufferCountActual, def.nBufferSize, 494 portIndex == kPortIndexInput ? "input" : "output"); 495 496 size_t totalSize = def.nBufferCountActual * def.nBufferSize; 497 mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec"); 498 499 for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) { 500 sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize); 501 CHECK(mem.get() != NULL); 502 503 BufferInfo info; 504 info.mStatus = BufferInfo::OWNED_BY_US; 505 506 uint32_t requiresAllocateBufferBit = 507 (portIndex == kPortIndexInput) 508 ? OMXCodec::kRequiresAllocateBufferOnInputPorts 509 : OMXCodec::kRequiresAllocateBufferOnOutputPorts; 510 511 if ((portIndex == kPortIndexInput && (mFlags & kFlagIsSecure)) 512 || mUseMetadataOnEncoderOutput) { 513 mem.clear(); 514 515 void *ptr; 516 err = mOMX->allocateBuffer( 517 mNode, portIndex, def.nBufferSize, &info.mBufferID, 518 &ptr); 519 520 int32_t bufSize = mUseMetadataOnEncoderOutput ? 521 (4 + sizeof(buffer_handle_t)) : def.nBufferSize; 522 523 info.mData = new ABuffer(ptr, bufSize); 524 } else if (mQuirks & requiresAllocateBufferBit) { 525 err = mOMX->allocateBufferWithBackup( 526 mNode, portIndex, mem, &info.mBufferID); 527 } else { 528 err = mOMX->useBuffer(mNode, portIndex, mem, &info.mBufferID); 529 } 530 531 if (mem != NULL) { 532 info.mData = new ABuffer(mem->pointer(), def.nBufferSize); 533 } 534 535 mBuffers[portIndex].push(info); 536 } 537 } 538 } 539 540 if (err != OK) { 541 return err; 542 } 543 544 sp<AMessage> notify = mNotify->dup(); 545 notify->setInt32("what", ACodec::kWhatBuffersAllocated); 546 547 notify->setInt32("portIndex", portIndex); 548 549 sp<PortDescription> desc = new PortDescription; 550 551 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 552 const BufferInfo &info = mBuffers[portIndex][i]; 553 554 desc->addBuffer(info.mBufferID, info.mData); 555 } 556 557 notify->setObject("portDesc", desc); 558 notify->post(); 559 560 return OK; 561} 562 563status_t ACodec::configureOutputBuffersFromNativeWindow( 564 OMX_U32 *bufferCount, OMX_U32 *bufferSize, 565 OMX_U32 *minUndequeuedBuffers) { 566 OMX_PARAM_PORTDEFINITIONTYPE def; 567 InitOMXParams(&def); 568 def.nPortIndex = kPortIndexOutput; 569 570 status_t err = mOMX->getParameter( 571 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 572 573 if (err != OK) { 574 return err; 575 } 576 577 err = native_window_set_buffers_geometry( 578 mNativeWindow.get(), 579 def.format.video.nFrameWidth, 580 def.format.video.nFrameHeight, 581 def.format.video.eColorFormat); 582 583 if (err != 0) { 584 ALOGE("native_window_set_buffers_geometry failed: %s (%d)", 585 strerror(-err), -err); 586 return err; 587 } 588 589 // Set up the native window. 590 OMX_U32 usage = 0; 591 err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage); 592 if (err != 0) { 593 ALOGW("querying usage flags from OMX IL component failed: %d", err); 594 // XXX: Currently this error is logged, but not fatal. 595 usage = 0; 596 } 597 598 if (mFlags & kFlagIsSecure) { 599 usage |= GRALLOC_USAGE_PROTECTED; 600 } 601 602 // Make sure to check whether either Stagefright or the video decoder 603 // requested protected buffers. 604 if (usage & GRALLOC_USAGE_PROTECTED) { 605 // Verify that the ANativeWindow sends images directly to 606 // SurfaceFlinger. 607 int queuesToNativeWindow = 0; 608 err = mNativeWindow->query( 609 mNativeWindow.get(), NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, 610 &queuesToNativeWindow); 611 if (err != 0) { 612 ALOGE("error authenticating native window: %d", err); 613 return err; 614 } 615 if (queuesToNativeWindow != 1) { 616 ALOGE("native window could not be authenticated"); 617 return PERMISSION_DENIED; 618 } 619 } 620 621 err = native_window_set_usage( 622 mNativeWindow.get(), 623 usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP); 624 625 if (err != 0) { 626 ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err); 627 return err; 628 } 629 630 *minUndequeuedBuffers = 0; 631 err = mNativeWindow->query( 632 mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, 633 (int *)minUndequeuedBuffers); 634 635 if (err != 0) { 636 ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)", 637 strerror(-err), -err); 638 return err; 639 } 640 641 // FIXME: assume that surface is controlled by app (native window 642 // returns the number for the case when surface is not controlled by app) 643 (*minUndequeuedBuffers)++; 644 645 646 // Use conservative allocation while also trying to reduce starvation 647 // 648 // 1. allocate at least nBufferCountMin + minUndequeuedBuffers - that is the 649 // minimum needed for the consumer to be able to work 650 // 2. try to allocate two (2) additional buffers to reduce starvation from 651 // the consumer 652 for (OMX_U32 extraBuffers = 2; /* condition inside loop */; extraBuffers--) { 653 OMX_U32 newBufferCount = 654 def.nBufferCountMin + *minUndequeuedBuffers + extraBuffers; 655 def.nBufferCountActual = newBufferCount; 656 err = mOMX->setParameter( 657 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 658 659 if (err == OK) { 660 *minUndequeuedBuffers += extraBuffers; 661 break; 662 } 663 664 ALOGW("[%s] setting nBufferCountActual to %lu failed: %d", 665 mComponentName.c_str(), newBufferCount, err); 666 /* exit condition */ 667 if (extraBuffers == 0) { 668 return err; 669 } 670 } 671 672 err = native_window_set_buffer_count( 673 mNativeWindow.get(), def.nBufferCountActual); 674 675 if (err != 0) { 676 ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), 677 -err); 678 return err; 679 } 680 681 *bufferCount = def.nBufferCountActual; 682 *bufferSize = def.nBufferSize; 683 return err; 684} 685 686status_t ACodec::allocateOutputBuffersFromNativeWindow() { 687 OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers; 688 status_t err = configureOutputBuffersFromNativeWindow( 689 &bufferCount, &bufferSize, &minUndequeuedBuffers); 690 if (err != 0) 691 return err; 692 mNumUndequeuedBuffers = minUndequeuedBuffers; 693 694 ALOGV("[%s] Allocating %lu buffers from a native window of size %lu on " 695 "output port", 696 mComponentName.c_str(), bufferCount, bufferSize); 697 698 // Dequeue buffers and send them to OMX 699 for (OMX_U32 i = 0; i < bufferCount; i++) { 700 ANativeWindowBuffer *buf; 701 err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf); 702 if (err != 0) { 703 ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err); 704 break; 705 } 706 707 sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false)); 708 BufferInfo info; 709 info.mStatus = BufferInfo::OWNED_BY_US; 710 info.mData = new ABuffer(NULL /* data */, bufferSize /* capacity */); 711 info.mGraphicBuffer = graphicBuffer; 712 mBuffers[kPortIndexOutput].push(info); 713 714 IOMX::buffer_id bufferId; 715 err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer, 716 &bufferId); 717 if (err != 0) { 718 ALOGE("registering GraphicBuffer %lu with OMX IL component failed: " 719 "%d", i, err); 720 break; 721 } 722 723 mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId; 724 725 ALOGV("[%s] Registered graphic buffer with ID %p (pointer = %p)", 726 mComponentName.c_str(), 727 bufferId, graphicBuffer.get()); 728 } 729 730 OMX_U32 cancelStart; 731 OMX_U32 cancelEnd; 732 733 if (err != 0) { 734 // If an error occurred while dequeuing we need to cancel any buffers 735 // that were dequeued. 736 cancelStart = 0; 737 cancelEnd = mBuffers[kPortIndexOutput].size(); 738 } else { 739 // Return the required minimum undequeued buffers to the native window. 740 cancelStart = bufferCount - minUndequeuedBuffers; 741 cancelEnd = bufferCount; 742 } 743 744 for (OMX_U32 i = cancelStart; i < cancelEnd; i++) { 745 BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i); 746 cancelBufferToNativeWindow(info); 747 } 748 749 return err; 750} 751 752status_t ACodec::allocateOutputMetaDataBuffers() { 753 OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers; 754 status_t err = configureOutputBuffersFromNativeWindow( 755 &bufferCount, &bufferSize, &minUndequeuedBuffers); 756 if (err != 0) 757 return err; 758 mNumUndequeuedBuffers = minUndequeuedBuffers; 759 760 ALOGV("[%s] Allocating %lu meta buffers on output port", 761 mComponentName.c_str(), bufferCount); 762 763 size_t totalSize = bufferCount * 8; 764 mDealer[kPortIndexOutput] = new MemoryDealer(totalSize, "ACodec"); 765 766 // Dequeue buffers and send them to OMX 767 for (OMX_U32 i = 0; i < bufferCount; i++) { 768 BufferInfo info; 769 info.mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 770 info.mGraphicBuffer = NULL; 771 info.mDequeuedAt = mDequeueCounter; 772 773 sp<IMemory> mem = mDealer[kPortIndexOutput]->allocate( 774 sizeof(struct VideoDecoderOutputMetaData)); 775 CHECK(mem.get() != NULL); 776 info.mData = new ABuffer(mem->pointer(), mem->size()); 777 778 // we use useBuffer for metadata regardless of quirks 779 err = mOMX->useBuffer( 780 mNode, kPortIndexOutput, mem, &info.mBufferID); 781 782 mBuffers[kPortIndexOutput].push(info); 783 784 ALOGV("[%s] allocated meta buffer with ID %p (pointer = %p)", 785 mComponentName.c_str(), info.mBufferID, mem->pointer()); 786 } 787 788 mMetaDataBuffersToSubmit = bufferCount - minUndequeuedBuffers; 789 return err; 790} 791 792status_t ACodec::submitOutputMetaDataBuffer() { 793 CHECK(mStoreMetaDataInOutputBuffers); 794 if (mMetaDataBuffersToSubmit == 0) 795 return OK; 796 797 BufferInfo *info = dequeueBufferFromNativeWindow(); 798 if (info == NULL) 799 return ERROR_IO; 800 801 ALOGV("[%s] submitting output meta buffer ID %p for graphic buffer %p", 802 mComponentName.c_str(), info->mBufferID, info->mGraphicBuffer.get()); 803 804 --mMetaDataBuffersToSubmit; 805 CHECK_EQ(mOMX->fillBuffer(mNode, info->mBufferID), 806 (status_t)OK); 807 808 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 809 return OK; 810} 811 812status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) { 813 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 814 815 ALOGV("[%s] Calling cancelBuffer on buffer %p", 816 mComponentName.c_str(), info->mBufferID); 817 818 int err = mNativeWindow->cancelBuffer( 819 mNativeWindow.get(), info->mGraphicBuffer.get(), -1); 820 821 CHECK_EQ(err, 0); 822 823 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 824 825 return OK; 826} 827 828ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() { 829 ANativeWindowBuffer *buf; 830 int fenceFd = -1; 831 CHECK(mNativeWindow.get() != NULL); 832 if (native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf) != 0) { 833 ALOGE("dequeueBuffer failed."); 834 return NULL; 835 } 836 837 BufferInfo *oldest = NULL; 838 for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) { 839 BufferInfo *info = 840 &mBuffers[kPortIndexOutput].editItemAt(i); 841 842 if (info->mGraphicBuffer != NULL && 843 info->mGraphicBuffer->handle == buf->handle) { 844 CHECK_EQ((int)info->mStatus, 845 (int)BufferInfo::OWNED_BY_NATIVE_WINDOW); 846 847 info->mStatus = BufferInfo::OWNED_BY_US; 848 849 return info; 850 } 851 852 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW && 853 (oldest == NULL || 854 // avoid potential issues from counter rolling over 855 mDequeueCounter - info->mDequeuedAt > 856 mDequeueCounter - oldest->mDequeuedAt)) { 857 oldest = info; 858 } 859 } 860 861 if (oldest) { 862 CHECK(mStoreMetaDataInOutputBuffers); 863 864 // discard buffer in LRU info and replace with new buffer 865 oldest->mGraphicBuffer = new GraphicBuffer(buf, false); 866 oldest->mStatus = BufferInfo::OWNED_BY_US; 867 868 mOMX->updateGraphicBufferInMeta( 869 mNode, kPortIndexOutput, oldest->mGraphicBuffer, 870 oldest->mBufferID); 871 872 VideoDecoderOutputMetaData *metaData = 873 reinterpret_cast<VideoDecoderOutputMetaData *>( 874 oldest->mData->base()); 875 CHECK_EQ(metaData->eType, kMetadataBufferTypeGrallocSource); 876 877 ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)", 878 oldest - &mBuffers[kPortIndexOutput][0], 879 mDequeueCounter - oldest->mDequeuedAt, 880 metaData->pHandle, 881 oldest->mGraphicBuffer->handle, oldest->mData->base()); 882 883 return oldest; 884 } 885 886 TRESPASS(); 887 888 return NULL; 889} 890 891status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) { 892 for (size_t i = mBuffers[portIndex].size(); i-- > 0;) { 893 CHECK_EQ((status_t)OK, freeBuffer(portIndex, i)); 894 } 895 896 mDealer[portIndex].clear(); 897 898 return OK; 899} 900 901status_t ACodec::freeOutputBuffersNotOwnedByComponent() { 902 for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) { 903 BufferInfo *info = 904 &mBuffers[kPortIndexOutput].editItemAt(i); 905 906 // At this time some buffers may still be with the component 907 // or being drained. 908 if (info->mStatus != BufferInfo::OWNED_BY_COMPONENT && 909 info->mStatus != BufferInfo::OWNED_BY_DOWNSTREAM) { 910 CHECK_EQ((status_t)OK, freeBuffer(kPortIndexOutput, i)); 911 } 912 } 913 914 return OK; 915} 916 917status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) { 918 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 919 920 CHECK(info->mStatus == BufferInfo::OWNED_BY_US 921 || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW); 922 923 if (portIndex == kPortIndexOutput && mNativeWindow != NULL 924 && info->mStatus == BufferInfo::OWNED_BY_US) { 925 CHECK_EQ((status_t)OK, cancelBufferToNativeWindow(info)); 926 } 927 928 CHECK_EQ(mOMX->freeBuffer( 929 mNode, portIndex, info->mBufferID), 930 (status_t)OK); 931 932 mBuffers[portIndex].removeAt(i); 933 934 return OK; 935} 936 937ACodec::BufferInfo *ACodec::findBufferByID( 938 uint32_t portIndex, IOMX::buffer_id bufferID, 939 ssize_t *index) { 940 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 941 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 942 943 if (info->mBufferID == bufferID) { 944 if (index != NULL) { 945 *index = i; 946 } 947 return info; 948 } 949 } 950 951 TRESPASS(); 952 953 return NULL; 954} 955 956status_t ACodec::setComponentRole( 957 bool isEncoder, const char *mime) { 958 struct MimeToRole { 959 const char *mime; 960 const char *decoderRole; 961 const char *encoderRole; 962 }; 963 964 static const MimeToRole kMimeToRole[] = { 965 { MEDIA_MIMETYPE_AUDIO_MPEG, 966 "audio_decoder.mp3", "audio_encoder.mp3" }, 967 { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I, 968 "audio_decoder.mp1", "audio_encoder.mp1" }, 969 { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II, 970 "audio_decoder.mp2", "audio_encoder.mp2" }, 971 { MEDIA_MIMETYPE_AUDIO_AMR_NB, 972 "audio_decoder.amrnb", "audio_encoder.amrnb" }, 973 { MEDIA_MIMETYPE_AUDIO_AMR_WB, 974 "audio_decoder.amrwb", "audio_encoder.amrwb" }, 975 { MEDIA_MIMETYPE_AUDIO_AAC, 976 "audio_decoder.aac", "audio_encoder.aac" }, 977 { MEDIA_MIMETYPE_AUDIO_VORBIS, 978 "audio_decoder.vorbis", "audio_encoder.vorbis" }, 979 { MEDIA_MIMETYPE_AUDIO_G711_MLAW, 980 "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" }, 981 { MEDIA_MIMETYPE_AUDIO_G711_ALAW, 982 "audio_decoder.g711alaw", "audio_encoder.g711alaw" }, 983 { MEDIA_MIMETYPE_VIDEO_AVC, 984 "video_decoder.avc", "video_encoder.avc" }, 985 { MEDIA_MIMETYPE_VIDEO_MPEG4, 986 "video_decoder.mpeg4", "video_encoder.mpeg4" }, 987 { MEDIA_MIMETYPE_VIDEO_H263, 988 "video_decoder.h263", "video_encoder.h263" }, 989 { MEDIA_MIMETYPE_VIDEO_VP8, 990 "video_decoder.vp8", "video_encoder.vp8" }, 991 { MEDIA_MIMETYPE_VIDEO_VP9, 992 "video_decoder.vp9", "video_encoder.vp9" }, 993 { MEDIA_MIMETYPE_AUDIO_RAW, 994 "audio_decoder.raw", "audio_encoder.raw" }, 995 { MEDIA_MIMETYPE_AUDIO_FLAC, 996 "audio_decoder.flac", "audio_encoder.flac" }, 997 { MEDIA_MIMETYPE_AUDIO_MSGSM, 998 "audio_decoder.gsm", "audio_encoder.gsm" }, 999 }; 1000 1001 static const size_t kNumMimeToRole = 1002 sizeof(kMimeToRole) / sizeof(kMimeToRole[0]); 1003 1004 size_t i; 1005 for (i = 0; i < kNumMimeToRole; ++i) { 1006 if (!strcasecmp(mime, kMimeToRole[i].mime)) { 1007 break; 1008 } 1009 } 1010 1011 if (i == kNumMimeToRole) { 1012 return ERROR_UNSUPPORTED; 1013 } 1014 1015 const char *role = 1016 isEncoder ? kMimeToRole[i].encoderRole 1017 : kMimeToRole[i].decoderRole; 1018 1019 if (role != NULL) { 1020 OMX_PARAM_COMPONENTROLETYPE roleParams; 1021 InitOMXParams(&roleParams); 1022 1023 strncpy((char *)roleParams.cRole, 1024 role, OMX_MAX_STRINGNAME_SIZE - 1); 1025 1026 roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0'; 1027 1028 status_t err = mOMX->setParameter( 1029 mNode, OMX_IndexParamStandardComponentRole, 1030 &roleParams, sizeof(roleParams)); 1031 1032 if (err != OK) { 1033 ALOGW("[%s] Failed to set standard component role '%s'.", 1034 mComponentName.c_str(), role); 1035 1036 return err; 1037 } 1038 } 1039 1040 return OK; 1041} 1042 1043status_t ACodec::configureCodec( 1044 const char *mime, const sp<AMessage> &msg) { 1045 int32_t encoder; 1046 if (!msg->findInt32("encoder", &encoder)) { 1047 encoder = false; 1048 } 1049 1050 mIsEncoder = encoder; 1051 1052 status_t err = setComponentRole(encoder /* isEncoder */, mime); 1053 1054 if (err != OK) { 1055 return err; 1056 } 1057 1058 int32_t bitRate = 0; 1059 // FLAC encoder doesn't need a bitrate, other encoders do 1060 if (encoder && strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC) 1061 && !msg->findInt32("bitrate", &bitRate)) { 1062 return INVALID_OPERATION; 1063 } 1064 1065 int32_t storeMeta; 1066 if (encoder 1067 && msg->findInt32("store-metadata-in-buffers", &storeMeta) 1068 && storeMeta != 0) { 1069 err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexInput, OMX_TRUE); 1070 1071 if (err != OK) { 1072 ALOGE("[%s] storeMetaDataInBuffers (input) failed w/ err %d", 1073 mComponentName.c_str(), err); 1074 1075 return err; 1076 } 1077 } 1078 1079 int32_t prependSPSPPS = 0; 1080 if (encoder 1081 && msg->findInt32("prepend-sps-pps-to-idr-frames", &prependSPSPPS) 1082 && prependSPSPPS != 0) { 1083 OMX_INDEXTYPE index; 1084 err = mOMX->getExtensionIndex( 1085 mNode, 1086 "OMX.google.android.index.prependSPSPPSToIDRFrames", 1087 &index); 1088 1089 if (err == OK) { 1090 PrependSPSPPSToIDRFramesParams params; 1091 InitOMXParams(¶ms); 1092 params.bEnable = OMX_TRUE; 1093 1094 err = mOMX->setParameter( 1095 mNode, index, ¶ms, sizeof(params)); 1096 } 1097 1098 if (err != OK) { 1099 ALOGE("Encoder could not be configured to emit SPS/PPS before " 1100 "IDR frames. (err %d)", err); 1101 1102 return err; 1103 } 1104 } 1105 1106 // Only enable metadata mode on encoder output if encoder can prepend 1107 // sps/pps to idr frames, since in metadata mode the bitstream is in an 1108 // opaque handle, to which we don't have access. 1109 int32_t video = !strncasecmp(mime, "video/", 6); 1110 if (encoder && video) { 1111 OMX_BOOL enable = (OMX_BOOL) (prependSPSPPS 1112 && msg->findInt32("store-metadata-in-buffers-output", &storeMeta) 1113 && storeMeta != 0); 1114 1115 err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, enable); 1116 1117 if (err != OK) { 1118 ALOGE("[%s] storeMetaDataInBuffers (output) failed w/ err %d", 1119 mComponentName.c_str(), err); 1120 mUseMetadataOnEncoderOutput = 0; 1121 } else { 1122 mUseMetadataOnEncoderOutput = enable; 1123 } 1124 1125 if (!msg->findInt64( 1126 "repeat-previous-frame-after", 1127 &mRepeatFrameDelayUs)) { 1128 mRepeatFrameDelayUs = -1ll; 1129 } 1130 1131 if (!msg->findInt64("max-pts-gap-to-encoder", &mMaxPtsGapUs)) { 1132 mMaxPtsGapUs = -1l; 1133 } 1134 } 1135 1136 // Always try to enable dynamic output buffers on native surface 1137 sp<RefBase> obj; 1138 int32_t haveNativeWindow = msg->findObject("native-window", &obj) && 1139 obj != NULL; 1140 mStoreMetaDataInOutputBuffers = false; 1141 mIsConfiguredForAdaptivePlayback = false; 1142 if (!encoder && video && haveNativeWindow) { 1143 err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, OMX_TRUE); 1144 if (err != OK) { 1145 ALOGE("[%s] storeMetaDataInBuffers failed w/ err %d", 1146 mComponentName.c_str(), err); 1147 1148 // if adaptive playback has been requested, try JB fallback 1149 // NOTE: THIS FALLBACK MECHANISM WILL BE REMOVED DUE TO ITS 1150 // LARGE MEMORY REQUIREMENT 1151 1152 // we will not do adaptive playback on software accessed 1153 // surfaces as they never had to respond to changes in the 1154 // crop window, and we don't trust that they will be able to. 1155 int usageBits = 0; 1156 bool canDoAdaptivePlayback; 1157 1158 sp<NativeWindowWrapper> windowWrapper( 1159 static_cast<NativeWindowWrapper *>(obj.get())); 1160 sp<ANativeWindow> nativeWindow = windowWrapper->getNativeWindow(); 1161 1162 if (nativeWindow->query( 1163 nativeWindow.get(), 1164 NATIVE_WINDOW_CONSUMER_USAGE_BITS, 1165 &usageBits) != OK) { 1166 canDoAdaptivePlayback = false; 1167 } else { 1168 canDoAdaptivePlayback = 1169 (usageBits & 1170 (GRALLOC_USAGE_SW_READ_MASK | 1171 GRALLOC_USAGE_SW_WRITE_MASK)) == 0; 1172 } 1173 1174 int32_t maxWidth = 0, maxHeight = 0; 1175 if (canDoAdaptivePlayback && 1176 msg->findInt32("max-width", &maxWidth) && 1177 msg->findInt32("max-height", &maxHeight)) { 1178 ALOGV("[%s] prepareForAdaptivePlayback(%ldx%ld)", 1179 mComponentName.c_str(), maxWidth, maxHeight); 1180 1181 err = mOMX->prepareForAdaptivePlayback( 1182 mNode, kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight); 1183 ALOGW_IF(err != OK, 1184 "[%s] prepareForAdaptivePlayback failed w/ err %d", 1185 mComponentName.c_str(), err); 1186 mIsConfiguredForAdaptivePlayback = (err == OK); 1187 } 1188 // allow failure 1189 err = OK; 1190 } else { 1191 ALOGV("[%s] storeMetaDataInBuffers succeeded", mComponentName.c_str()); 1192 mStoreMetaDataInOutputBuffers = true; 1193 mIsConfiguredForAdaptivePlayback = true; 1194 } 1195 1196 int32_t push; 1197 if (msg->findInt32("push-blank-buffers-on-shutdown", &push) 1198 && push != 0) { 1199 mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown; 1200 } 1201 } 1202 1203 if (video) { 1204 if (encoder) { 1205 err = setupVideoEncoder(mime, msg); 1206 } else { 1207 int32_t width, height; 1208 if (!msg->findInt32("width", &width) 1209 || !msg->findInt32("height", &height)) { 1210 err = INVALID_OPERATION; 1211 } else { 1212 err = setupVideoDecoder(mime, width, height); 1213 } 1214 } 1215 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) { 1216 int32_t numChannels, sampleRate; 1217 if (!msg->findInt32("channel-count", &numChannels) 1218 || !msg->findInt32("sample-rate", &sampleRate)) { 1219 // Since we did not always check for these, leave them optional 1220 // and have the decoder figure it all out. 1221 err = OK; 1222 } else { 1223 err = setupRawAudioFormat( 1224 encoder ? kPortIndexInput : kPortIndexOutput, 1225 sampleRate, 1226 numChannels); 1227 } 1228 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 1229 int32_t numChannels, sampleRate; 1230 if (!msg->findInt32("channel-count", &numChannels) 1231 || !msg->findInt32("sample-rate", &sampleRate)) { 1232 err = INVALID_OPERATION; 1233 } else { 1234 int32_t isADTS, aacProfile; 1235 if (!msg->findInt32("is-adts", &isADTS)) { 1236 isADTS = 0; 1237 } 1238 if (!msg->findInt32("aac-profile", &aacProfile)) { 1239 aacProfile = OMX_AUDIO_AACObjectNull; 1240 } 1241 1242 err = setupAACCodec( 1243 encoder, numChannels, sampleRate, bitRate, aacProfile, 1244 isADTS != 0); 1245 } 1246 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) { 1247 err = setupAMRCodec(encoder, false /* isWAMR */, bitRate); 1248 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) { 1249 err = setupAMRCodec(encoder, true /* isWAMR */, bitRate); 1250 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW) 1251 || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) { 1252 // These are PCM-like formats with a fixed sample rate but 1253 // a variable number of channels. 1254 1255 int32_t numChannels; 1256 if (!msg->findInt32("channel-count", &numChannels)) { 1257 err = INVALID_OPERATION; 1258 } else { 1259 err = setupG711Codec(encoder, numChannels); 1260 } 1261 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) { 1262 int32_t numChannels, sampleRate, compressionLevel = -1; 1263 if (encoder && 1264 (!msg->findInt32("channel-count", &numChannels) 1265 || !msg->findInt32("sample-rate", &sampleRate))) { 1266 ALOGE("missing channel count or sample rate for FLAC encoder"); 1267 err = INVALID_OPERATION; 1268 } else { 1269 if (encoder) { 1270 if (!msg->findInt32( 1271 "flac-compression-level", &compressionLevel)) { 1272 compressionLevel = 5;// default FLAC compression level 1273 } else if (compressionLevel < 0) { 1274 ALOGW("compression level %d outside [0..8] range, " 1275 "using 0", 1276 compressionLevel); 1277 compressionLevel = 0; 1278 } else if (compressionLevel > 8) { 1279 ALOGW("compression level %d outside [0..8] range, " 1280 "using 8", 1281 compressionLevel); 1282 compressionLevel = 8; 1283 } 1284 } 1285 err = setupFlacCodec( 1286 encoder, numChannels, sampleRate, compressionLevel); 1287 } 1288 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) { 1289 int32_t numChannels, sampleRate; 1290 if (encoder 1291 || !msg->findInt32("channel-count", &numChannels) 1292 || !msg->findInt32("sample-rate", &sampleRate)) { 1293 err = INVALID_OPERATION; 1294 } else { 1295 err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels); 1296 } 1297 } 1298 1299 if (err != OK) { 1300 return err; 1301 } 1302 1303 if (!msg->findInt32("encoder-delay", &mEncoderDelay)) { 1304 mEncoderDelay = 0; 1305 } 1306 1307 if (!msg->findInt32("encoder-padding", &mEncoderPadding)) { 1308 mEncoderPadding = 0; 1309 } 1310 1311 if (msg->findInt32("channel-mask", &mChannelMask)) { 1312 mChannelMaskPresent = true; 1313 } else { 1314 mChannelMaskPresent = false; 1315 } 1316 1317 int32_t maxInputSize; 1318 if (msg->findInt32("max-input-size", &maxInputSize)) { 1319 err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize); 1320 } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) { 1321 err = setMinBufferSize(kPortIndexInput, 8192); // XXX 1322 } 1323 1324 return err; 1325} 1326 1327status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) { 1328 OMX_PARAM_PORTDEFINITIONTYPE def; 1329 InitOMXParams(&def); 1330 def.nPortIndex = portIndex; 1331 1332 status_t err = mOMX->getParameter( 1333 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1334 1335 if (err != OK) { 1336 return err; 1337 } 1338 1339 if (def.nBufferSize >= size) { 1340 return OK; 1341 } 1342 1343 def.nBufferSize = size; 1344 1345 err = mOMX->setParameter( 1346 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1347 1348 if (err != OK) { 1349 return err; 1350 } 1351 1352 err = mOMX->getParameter( 1353 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1354 1355 if (err != OK) { 1356 return err; 1357 } 1358 1359 CHECK(def.nBufferSize >= size); 1360 1361 return OK; 1362} 1363 1364status_t ACodec::selectAudioPortFormat( 1365 OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) { 1366 OMX_AUDIO_PARAM_PORTFORMATTYPE format; 1367 InitOMXParams(&format); 1368 1369 format.nPortIndex = portIndex; 1370 for (OMX_U32 index = 0;; ++index) { 1371 format.nIndex = index; 1372 1373 status_t err = mOMX->getParameter( 1374 mNode, OMX_IndexParamAudioPortFormat, 1375 &format, sizeof(format)); 1376 1377 if (err != OK) { 1378 return err; 1379 } 1380 1381 if (format.eEncoding == desiredFormat) { 1382 break; 1383 } 1384 } 1385 1386 return mOMX->setParameter( 1387 mNode, OMX_IndexParamAudioPortFormat, &format, sizeof(format)); 1388} 1389 1390status_t ACodec::setupAACCodec( 1391 bool encoder, int32_t numChannels, int32_t sampleRate, 1392 int32_t bitRate, int32_t aacProfile, bool isADTS) { 1393 if (encoder && isADTS) { 1394 return -EINVAL; 1395 } 1396 1397 status_t err = setupRawAudioFormat( 1398 encoder ? kPortIndexInput : kPortIndexOutput, 1399 sampleRate, 1400 numChannels); 1401 1402 if (err != OK) { 1403 return err; 1404 } 1405 1406 if (encoder) { 1407 err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC); 1408 1409 if (err != OK) { 1410 return err; 1411 } 1412 1413 OMX_PARAM_PORTDEFINITIONTYPE def; 1414 InitOMXParams(&def); 1415 def.nPortIndex = kPortIndexOutput; 1416 1417 err = mOMX->getParameter( 1418 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1419 1420 if (err != OK) { 1421 return err; 1422 } 1423 1424 def.format.audio.bFlagErrorConcealment = OMX_TRUE; 1425 def.format.audio.eEncoding = OMX_AUDIO_CodingAAC; 1426 1427 err = mOMX->setParameter( 1428 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1429 1430 if (err != OK) { 1431 return err; 1432 } 1433 1434 OMX_AUDIO_PARAM_AACPROFILETYPE profile; 1435 InitOMXParams(&profile); 1436 profile.nPortIndex = kPortIndexOutput; 1437 1438 err = mOMX->getParameter( 1439 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 1440 1441 if (err != OK) { 1442 return err; 1443 } 1444 1445 profile.nChannels = numChannels; 1446 1447 profile.eChannelMode = 1448 (numChannels == 1) 1449 ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo; 1450 1451 profile.nSampleRate = sampleRate; 1452 profile.nBitRate = bitRate; 1453 profile.nAudioBandWidth = 0; 1454 profile.nFrameLength = 0; 1455 profile.nAACtools = OMX_AUDIO_AACToolAll; 1456 profile.nAACERtools = OMX_AUDIO_AACERNone; 1457 profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile; 1458 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF; 1459 1460 err = mOMX->setParameter( 1461 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 1462 1463 if (err != OK) { 1464 return err; 1465 } 1466 1467 return err; 1468 } 1469 1470 OMX_AUDIO_PARAM_AACPROFILETYPE profile; 1471 InitOMXParams(&profile); 1472 profile.nPortIndex = kPortIndexInput; 1473 1474 err = mOMX->getParameter( 1475 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 1476 1477 if (err != OK) { 1478 return err; 1479 } 1480 1481 profile.nChannels = numChannels; 1482 profile.nSampleRate = sampleRate; 1483 1484 profile.eAACStreamFormat = 1485 isADTS 1486 ? OMX_AUDIO_AACStreamFormatMP4ADTS 1487 : OMX_AUDIO_AACStreamFormatMP4FF; 1488 1489 return mOMX->setParameter( 1490 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 1491} 1492 1493static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate( 1494 bool isAMRWB, int32_t bps) { 1495 if (isAMRWB) { 1496 if (bps <= 6600) { 1497 return OMX_AUDIO_AMRBandModeWB0; 1498 } else if (bps <= 8850) { 1499 return OMX_AUDIO_AMRBandModeWB1; 1500 } else if (bps <= 12650) { 1501 return OMX_AUDIO_AMRBandModeWB2; 1502 } else if (bps <= 14250) { 1503 return OMX_AUDIO_AMRBandModeWB3; 1504 } else if (bps <= 15850) { 1505 return OMX_AUDIO_AMRBandModeWB4; 1506 } else if (bps <= 18250) { 1507 return OMX_AUDIO_AMRBandModeWB5; 1508 } else if (bps <= 19850) { 1509 return OMX_AUDIO_AMRBandModeWB6; 1510 } else if (bps <= 23050) { 1511 return OMX_AUDIO_AMRBandModeWB7; 1512 } 1513 1514 // 23850 bps 1515 return OMX_AUDIO_AMRBandModeWB8; 1516 } else { // AMRNB 1517 if (bps <= 4750) { 1518 return OMX_AUDIO_AMRBandModeNB0; 1519 } else if (bps <= 5150) { 1520 return OMX_AUDIO_AMRBandModeNB1; 1521 } else if (bps <= 5900) { 1522 return OMX_AUDIO_AMRBandModeNB2; 1523 } else if (bps <= 6700) { 1524 return OMX_AUDIO_AMRBandModeNB3; 1525 } else if (bps <= 7400) { 1526 return OMX_AUDIO_AMRBandModeNB4; 1527 } else if (bps <= 7950) { 1528 return OMX_AUDIO_AMRBandModeNB5; 1529 } else if (bps <= 10200) { 1530 return OMX_AUDIO_AMRBandModeNB6; 1531 } 1532 1533 // 12200 bps 1534 return OMX_AUDIO_AMRBandModeNB7; 1535 } 1536} 1537 1538status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) { 1539 OMX_AUDIO_PARAM_AMRTYPE def; 1540 InitOMXParams(&def); 1541 def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput; 1542 1543 status_t err = 1544 mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); 1545 1546 if (err != OK) { 1547 return err; 1548 } 1549 1550 def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF; 1551 def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate); 1552 1553 err = mOMX->setParameter( 1554 mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); 1555 1556 if (err != OK) { 1557 return err; 1558 } 1559 1560 return setupRawAudioFormat( 1561 encoder ? kPortIndexInput : kPortIndexOutput, 1562 isWAMR ? 16000 : 8000 /* sampleRate */, 1563 1 /* numChannels */); 1564} 1565 1566status_t ACodec::setupG711Codec(bool encoder, int32_t numChannels) { 1567 CHECK(!encoder); // XXX TODO 1568 1569 return setupRawAudioFormat( 1570 kPortIndexInput, 8000 /* sampleRate */, numChannels); 1571} 1572 1573status_t ACodec::setupFlacCodec( 1574 bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel) { 1575 1576 if (encoder) { 1577 OMX_AUDIO_PARAM_FLACTYPE def; 1578 InitOMXParams(&def); 1579 def.nPortIndex = kPortIndexOutput; 1580 1581 // configure compression level 1582 status_t err = mOMX->getParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def)); 1583 if (err != OK) { 1584 ALOGE("setupFlacCodec(): Error %d getting OMX_IndexParamAudioFlac parameter", err); 1585 return err; 1586 } 1587 def.nCompressionLevel = compressionLevel; 1588 err = mOMX->setParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def)); 1589 if (err != OK) { 1590 ALOGE("setupFlacCodec(): Error %d setting OMX_IndexParamAudioFlac parameter", err); 1591 return err; 1592 } 1593 } 1594 1595 return setupRawAudioFormat( 1596 encoder ? kPortIndexInput : kPortIndexOutput, 1597 sampleRate, 1598 numChannels); 1599} 1600 1601status_t ACodec::setupRawAudioFormat( 1602 OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) { 1603 OMX_PARAM_PORTDEFINITIONTYPE def; 1604 InitOMXParams(&def); 1605 def.nPortIndex = portIndex; 1606 1607 status_t err = mOMX->getParameter( 1608 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1609 1610 if (err != OK) { 1611 return err; 1612 } 1613 1614 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; 1615 1616 err = mOMX->setParameter( 1617 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1618 1619 if (err != OK) { 1620 return err; 1621 } 1622 1623 OMX_AUDIO_PARAM_PCMMODETYPE pcmParams; 1624 InitOMXParams(&pcmParams); 1625 pcmParams.nPortIndex = portIndex; 1626 1627 err = mOMX->getParameter( 1628 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); 1629 1630 if (err != OK) { 1631 return err; 1632 } 1633 1634 pcmParams.nChannels = numChannels; 1635 pcmParams.eNumData = OMX_NumericalDataSigned; 1636 pcmParams.bInterleaved = OMX_TRUE; 1637 pcmParams.nBitPerSample = 16; 1638 pcmParams.nSamplingRate = sampleRate; 1639 pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear; 1640 1641 if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) { 1642 return OMX_ErrorNone; 1643 } 1644 1645 return mOMX->setParameter( 1646 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); 1647} 1648 1649status_t ACodec::setVideoPortFormatType( 1650 OMX_U32 portIndex, 1651 OMX_VIDEO_CODINGTYPE compressionFormat, 1652 OMX_COLOR_FORMATTYPE colorFormat) { 1653 OMX_VIDEO_PARAM_PORTFORMATTYPE format; 1654 InitOMXParams(&format); 1655 format.nPortIndex = portIndex; 1656 format.nIndex = 0; 1657 bool found = false; 1658 1659 OMX_U32 index = 0; 1660 for (;;) { 1661 format.nIndex = index; 1662 status_t err = mOMX->getParameter( 1663 mNode, OMX_IndexParamVideoPortFormat, 1664 &format, sizeof(format)); 1665 1666 if (err != OK) { 1667 return err; 1668 } 1669 1670 // The following assertion is violated by TI's video decoder. 1671 // CHECK_EQ(format.nIndex, index); 1672 1673 if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) { 1674 if (portIndex == kPortIndexInput 1675 && colorFormat == format.eColorFormat) { 1676 // eCompressionFormat does not seem right. 1677 found = true; 1678 break; 1679 } 1680 if (portIndex == kPortIndexOutput 1681 && compressionFormat == format.eCompressionFormat) { 1682 // eColorFormat does not seem right. 1683 found = true; 1684 break; 1685 } 1686 } 1687 1688 if (format.eCompressionFormat == compressionFormat 1689 && format.eColorFormat == colorFormat) { 1690 found = true; 1691 break; 1692 } 1693 1694 ++index; 1695 } 1696 1697 if (!found) { 1698 return UNKNOWN_ERROR; 1699 } 1700 1701 status_t err = mOMX->setParameter( 1702 mNode, OMX_IndexParamVideoPortFormat, 1703 &format, sizeof(format)); 1704 1705 return err; 1706} 1707 1708status_t ACodec::setSupportedOutputFormat() { 1709 OMX_VIDEO_PARAM_PORTFORMATTYPE format; 1710 InitOMXParams(&format); 1711 format.nPortIndex = kPortIndexOutput; 1712 format.nIndex = 0; 1713 1714 status_t err = mOMX->getParameter( 1715 mNode, OMX_IndexParamVideoPortFormat, 1716 &format, sizeof(format)); 1717 CHECK_EQ(err, (status_t)OK); 1718 CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused); 1719 1720 return mOMX->setParameter( 1721 mNode, OMX_IndexParamVideoPortFormat, 1722 &format, sizeof(format)); 1723} 1724 1725static const struct VideoCodingMapEntry { 1726 const char *mMime; 1727 OMX_VIDEO_CODINGTYPE mVideoCodingType; 1728} kVideoCodingMapEntry[] = { 1729 { MEDIA_MIMETYPE_VIDEO_AVC, OMX_VIDEO_CodingAVC }, 1730 { MEDIA_MIMETYPE_VIDEO_MPEG4, OMX_VIDEO_CodingMPEG4 }, 1731 { MEDIA_MIMETYPE_VIDEO_H263, OMX_VIDEO_CodingH263 }, 1732 { MEDIA_MIMETYPE_VIDEO_MPEG2, OMX_VIDEO_CodingMPEG2 }, 1733 { MEDIA_MIMETYPE_VIDEO_VP8, OMX_VIDEO_CodingVP8 }, 1734 { MEDIA_MIMETYPE_VIDEO_VP9, OMX_VIDEO_CodingVP9 }, 1735}; 1736 1737static status_t GetVideoCodingTypeFromMime( 1738 const char *mime, OMX_VIDEO_CODINGTYPE *codingType) { 1739 for (size_t i = 0; 1740 i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]); 1741 ++i) { 1742 if (!strcasecmp(mime, kVideoCodingMapEntry[i].mMime)) { 1743 *codingType = kVideoCodingMapEntry[i].mVideoCodingType; 1744 return OK; 1745 } 1746 } 1747 1748 *codingType = OMX_VIDEO_CodingUnused; 1749 1750 return ERROR_UNSUPPORTED; 1751} 1752 1753static status_t GetMimeTypeForVideoCoding( 1754 OMX_VIDEO_CODINGTYPE codingType, AString *mime) { 1755 for (size_t i = 0; 1756 i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]); 1757 ++i) { 1758 if (codingType == kVideoCodingMapEntry[i].mVideoCodingType) { 1759 *mime = kVideoCodingMapEntry[i].mMime; 1760 return OK; 1761 } 1762 } 1763 1764 mime->clear(); 1765 1766 return ERROR_UNSUPPORTED; 1767} 1768 1769status_t ACodec::setupVideoDecoder( 1770 const char *mime, int32_t width, int32_t height) { 1771 OMX_VIDEO_CODINGTYPE compressionFormat; 1772 status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat); 1773 1774 if (err != OK) { 1775 return err; 1776 } 1777 1778 err = setVideoPortFormatType( 1779 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused); 1780 1781 if (err != OK) { 1782 return err; 1783 } 1784 1785 err = setSupportedOutputFormat(); 1786 1787 if (err != OK) { 1788 return err; 1789 } 1790 1791 err = setVideoFormatOnPort( 1792 kPortIndexInput, width, height, compressionFormat); 1793 1794 if (err != OK) { 1795 return err; 1796 } 1797 1798 err = setVideoFormatOnPort( 1799 kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused); 1800 1801 if (err != OK) { 1802 return err; 1803 } 1804 1805 return OK; 1806} 1807 1808status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) { 1809 int32_t tmp; 1810 if (!msg->findInt32("color-format", &tmp)) { 1811 return INVALID_OPERATION; 1812 } 1813 1814 OMX_COLOR_FORMATTYPE colorFormat = 1815 static_cast<OMX_COLOR_FORMATTYPE>(tmp); 1816 1817 status_t err = setVideoPortFormatType( 1818 kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat); 1819 1820 if (err != OK) { 1821 ALOGE("[%s] does not support color format %d", 1822 mComponentName.c_str(), colorFormat); 1823 1824 return err; 1825 } 1826 1827 /* Input port configuration */ 1828 1829 OMX_PARAM_PORTDEFINITIONTYPE def; 1830 InitOMXParams(&def); 1831 1832 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 1833 1834 def.nPortIndex = kPortIndexInput; 1835 1836 err = mOMX->getParameter( 1837 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1838 1839 if (err != OK) { 1840 return err; 1841 } 1842 1843 int32_t width, height, bitrate; 1844 if (!msg->findInt32("width", &width) 1845 || !msg->findInt32("height", &height) 1846 || !msg->findInt32("bitrate", &bitrate)) { 1847 return INVALID_OPERATION; 1848 } 1849 1850 video_def->nFrameWidth = width; 1851 video_def->nFrameHeight = height; 1852 1853 int32_t stride; 1854 if (!msg->findInt32("stride", &stride)) { 1855 stride = width; 1856 } 1857 1858 video_def->nStride = stride; 1859 1860 int32_t sliceHeight; 1861 if (!msg->findInt32("slice-height", &sliceHeight)) { 1862 sliceHeight = height; 1863 } 1864 1865 video_def->nSliceHeight = sliceHeight; 1866 1867 def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2; 1868 1869 float frameRate; 1870 if (!msg->findFloat("frame-rate", &frameRate)) { 1871 int32_t tmp; 1872 if (!msg->findInt32("frame-rate", &tmp)) { 1873 return INVALID_OPERATION; 1874 } 1875 frameRate = (float)tmp; 1876 } 1877 1878 video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f); 1879 video_def->eCompressionFormat = OMX_VIDEO_CodingUnused; 1880 video_def->eColorFormat = colorFormat; 1881 1882 err = mOMX->setParameter( 1883 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1884 1885 if (err != OK) { 1886 ALOGE("[%s] failed to set input port definition parameters.", 1887 mComponentName.c_str()); 1888 1889 return err; 1890 } 1891 1892 /* Output port configuration */ 1893 1894 OMX_VIDEO_CODINGTYPE compressionFormat; 1895 err = GetVideoCodingTypeFromMime(mime, &compressionFormat); 1896 1897 if (err != OK) { 1898 return err; 1899 } 1900 1901 err = setVideoPortFormatType( 1902 kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused); 1903 1904 if (err != OK) { 1905 ALOGE("[%s] does not support compression format %d", 1906 mComponentName.c_str(), compressionFormat); 1907 1908 return err; 1909 } 1910 1911 def.nPortIndex = kPortIndexOutput; 1912 1913 err = mOMX->getParameter( 1914 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1915 1916 if (err != OK) { 1917 return err; 1918 } 1919 1920 video_def->nFrameWidth = width; 1921 video_def->nFrameHeight = height; 1922 video_def->xFramerate = 0; 1923 video_def->nBitrate = bitrate; 1924 video_def->eCompressionFormat = compressionFormat; 1925 video_def->eColorFormat = OMX_COLOR_FormatUnused; 1926 1927 err = mOMX->setParameter( 1928 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1929 1930 if (err != OK) { 1931 ALOGE("[%s] failed to set output port definition parameters.", 1932 mComponentName.c_str()); 1933 1934 return err; 1935 } 1936 1937 switch (compressionFormat) { 1938 case OMX_VIDEO_CodingMPEG4: 1939 err = setupMPEG4EncoderParameters(msg); 1940 break; 1941 1942 case OMX_VIDEO_CodingH263: 1943 err = setupH263EncoderParameters(msg); 1944 break; 1945 1946 case OMX_VIDEO_CodingAVC: 1947 err = setupAVCEncoderParameters(msg); 1948 break; 1949 1950 case OMX_VIDEO_CodingVP8: 1951 case OMX_VIDEO_CodingVP9: 1952 err = setupVPXEncoderParameters(msg); 1953 break; 1954 1955 default: 1956 break; 1957 } 1958 1959 ALOGI("setupVideoEncoder succeeded"); 1960 1961 return err; 1962} 1963 1964status_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) { 1965 OMX_VIDEO_PARAM_INTRAREFRESHTYPE params; 1966 InitOMXParams(¶ms); 1967 params.nPortIndex = kPortIndexOutput; 1968 1969 params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode); 1970 1971 if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic || 1972 params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) { 1973 int32_t mbs; 1974 if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) { 1975 return INVALID_OPERATION; 1976 } 1977 params.nCirMBs = mbs; 1978 } 1979 1980 if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive || 1981 params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) { 1982 int32_t mbs; 1983 if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) { 1984 return INVALID_OPERATION; 1985 } 1986 params.nAirMBs = mbs; 1987 1988 int32_t ref; 1989 if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) { 1990 return INVALID_OPERATION; 1991 } 1992 params.nAirRef = ref; 1993 } 1994 1995 status_t err = mOMX->setParameter( 1996 mNode, OMX_IndexParamVideoIntraRefresh, 1997 ¶ms, sizeof(params)); 1998 return err; 1999} 2000 2001static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) { 2002 if (iFramesInterval < 0) { 2003 return 0xFFFFFFFF; 2004 } else if (iFramesInterval == 0) { 2005 return 0; 2006 } 2007 OMX_U32 ret = frameRate * iFramesInterval; 2008 CHECK(ret > 1); 2009 return ret; 2010} 2011 2012static OMX_VIDEO_CONTROLRATETYPE getBitrateMode(const sp<AMessage> &msg) { 2013 int32_t tmp; 2014 if (!msg->findInt32("bitrate-mode", &tmp)) { 2015 return OMX_Video_ControlRateVariable; 2016 } 2017 2018 return static_cast<OMX_VIDEO_CONTROLRATETYPE>(tmp); 2019} 2020 2021status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) { 2022 int32_t bitrate, iFrameInterval; 2023 if (!msg->findInt32("bitrate", &bitrate) 2024 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 2025 return INVALID_OPERATION; 2026 } 2027 2028 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 2029 2030 float frameRate; 2031 if (!msg->findFloat("frame-rate", &frameRate)) { 2032 int32_t tmp; 2033 if (!msg->findInt32("frame-rate", &tmp)) { 2034 return INVALID_OPERATION; 2035 } 2036 frameRate = (float)tmp; 2037 } 2038 2039 OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type; 2040 InitOMXParams(&mpeg4type); 2041 mpeg4type.nPortIndex = kPortIndexOutput; 2042 2043 status_t err = mOMX->getParameter( 2044 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); 2045 2046 if (err != OK) { 2047 return err; 2048 } 2049 2050 mpeg4type.nSliceHeaderSpacing = 0; 2051 mpeg4type.bSVH = OMX_FALSE; 2052 mpeg4type.bGov = OMX_FALSE; 2053 2054 mpeg4type.nAllowedPictureTypes = 2055 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 2056 2057 mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 2058 if (mpeg4type.nPFrames == 0) { 2059 mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 2060 } 2061 mpeg4type.nBFrames = 0; 2062 mpeg4type.nIDCVLCThreshold = 0; 2063 mpeg4type.bACPred = OMX_TRUE; 2064 mpeg4type.nMaxPacketSize = 256; 2065 mpeg4type.nTimeIncRes = 1000; 2066 mpeg4type.nHeaderExtension = 0; 2067 mpeg4type.bReversibleVLC = OMX_FALSE; 2068 2069 int32_t profile; 2070 if (msg->findInt32("profile", &profile)) { 2071 int32_t level; 2072 if (!msg->findInt32("level", &level)) { 2073 return INVALID_OPERATION; 2074 } 2075 2076 err = verifySupportForProfileAndLevel(profile, level); 2077 2078 if (err != OK) { 2079 return err; 2080 } 2081 2082 mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile); 2083 mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level); 2084 } 2085 2086 err = mOMX->setParameter( 2087 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); 2088 2089 if (err != OK) { 2090 return err; 2091 } 2092 2093 err = configureBitrate(bitrate, bitrateMode); 2094 2095 if (err != OK) { 2096 return err; 2097 } 2098 2099 return setupErrorCorrectionParameters(); 2100} 2101 2102status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) { 2103 int32_t bitrate, iFrameInterval; 2104 if (!msg->findInt32("bitrate", &bitrate) 2105 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 2106 return INVALID_OPERATION; 2107 } 2108 2109 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 2110 2111 float frameRate; 2112 if (!msg->findFloat("frame-rate", &frameRate)) { 2113 int32_t tmp; 2114 if (!msg->findInt32("frame-rate", &tmp)) { 2115 return INVALID_OPERATION; 2116 } 2117 frameRate = (float)tmp; 2118 } 2119 2120 OMX_VIDEO_PARAM_H263TYPE h263type; 2121 InitOMXParams(&h263type); 2122 h263type.nPortIndex = kPortIndexOutput; 2123 2124 status_t err = mOMX->getParameter( 2125 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); 2126 2127 if (err != OK) { 2128 return err; 2129 } 2130 2131 h263type.nAllowedPictureTypes = 2132 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 2133 2134 h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 2135 if (h263type.nPFrames == 0) { 2136 h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 2137 } 2138 h263type.nBFrames = 0; 2139 2140 int32_t profile; 2141 if (msg->findInt32("profile", &profile)) { 2142 int32_t level; 2143 if (!msg->findInt32("level", &level)) { 2144 return INVALID_OPERATION; 2145 } 2146 2147 err = verifySupportForProfileAndLevel(profile, level); 2148 2149 if (err != OK) { 2150 return err; 2151 } 2152 2153 h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile); 2154 h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level); 2155 } 2156 2157 h263type.bPLUSPTYPEAllowed = OMX_FALSE; 2158 h263type.bForceRoundingTypeToZero = OMX_FALSE; 2159 h263type.nPictureHeaderRepetition = 0; 2160 h263type.nGOBHeaderInterval = 0; 2161 2162 err = mOMX->setParameter( 2163 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); 2164 2165 if (err != OK) { 2166 return err; 2167 } 2168 2169 err = configureBitrate(bitrate, bitrateMode); 2170 2171 if (err != OK) { 2172 return err; 2173 } 2174 2175 return setupErrorCorrectionParameters(); 2176} 2177 2178status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) { 2179 int32_t bitrate, iFrameInterval; 2180 if (!msg->findInt32("bitrate", &bitrate) 2181 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 2182 return INVALID_OPERATION; 2183 } 2184 2185 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 2186 2187 float frameRate; 2188 if (!msg->findFloat("frame-rate", &frameRate)) { 2189 int32_t tmp; 2190 if (!msg->findInt32("frame-rate", &tmp)) { 2191 return INVALID_OPERATION; 2192 } 2193 frameRate = (float)tmp; 2194 } 2195 2196 status_t err = OK; 2197 int32_t intraRefreshMode = 0; 2198 if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) { 2199 err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode); 2200 if (err != OK) { 2201 ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x", 2202 err, intraRefreshMode); 2203 return err; 2204 } 2205 } 2206 2207 OMX_VIDEO_PARAM_AVCTYPE h264type; 2208 InitOMXParams(&h264type); 2209 h264type.nPortIndex = kPortIndexOutput; 2210 2211 err = mOMX->getParameter( 2212 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 2213 2214 if (err != OK) { 2215 return err; 2216 } 2217 2218 h264type.nAllowedPictureTypes = 2219 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 2220 2221 int32_t profile; 2222 if (msg->findInt32("profile", &profile)) { 2223 int32_t level; 2224 if (!msg->findInt32("level", &level)) { 2225 return INVALID_OPERATION; 2226 } 2227 2228 err = verifySupportForProfileAndLevel(profile, level); 2229 2230 if (err != OK) { 2231 return err; 2232 } 2233 2234 h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile); 2235 h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level); 2236 } 2237 2238 // XXX 2239 if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) { 2240 ALOGW("Use baseline profile instead of %d for AVC recording", 2241 h264type.eProfile); 2242 h264type.eProfile = OMX_VIDEO_AVCProfileBaseline; 2243 } 2244 2245 if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) { 2246 h264type.nSliceHeaderSpacing = 0; 2247 h264type.bUseHadamard = OMX_TRUE; 2248 h264type.nRefFrames = 1; 2249 h264type.nBFrames = 0; 2250 h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 2251 if (h264type.nPFrames == 0) { 2252 h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 2253 } 2254 h264type.nRefIdx10ActiveMinus1 = 0; 2255 h264type.nRefIdx11ActiveMinus1 = 0; 2256 h264type.bEntropyCodingCABAC = OMX_FALSE; 2257 h264type.bWeightedPPrediction = OMX_FALSE; 2258 h264type.bconstIpred = OMX_FALSE; 2259 h264type.bDirect8x8Inference = OMX_FALSE; 2260 h264type.bDirectSpatialTemporal = OMX_FALSE; 2261 h264type.nCabacInitIdc = 0; 2262 } 2263 2264 if (h264type.nBFrames != 0) { 2265 h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB; 2266 } 2267 2268 h264type.bEnableUEP = OMX_FALSE; 2269 h264type.bEnableFMO = OMX_FALSE; 2270 h264type.bEnableASO = OMX_FALSE; 2271 h264type.bEnableRS = OMX_FALSE; 2272 h264type.bFrameMBsOnly = OMX_TRUE; 2273 h264type.bMBAFF = OMX_FALSE; 2274 h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; 2275 2276 err = mOMX->setParameter( 2277 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 2278 2279 if (err != OK) { 2280 return err; 2281 } 2282 2283 return configureBitrate(bitrate, bitrateMode); 2284} 2285 2286status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg) { 2287 int32_t bitrate; 2288 if (!msg->findInt32("bitrate", &bitrate)) { 2289 return INVALID_OPERATION; 2290 } 2291 2292 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 2293 2294 return configureBitrate(bitrate, bitrateMode); 2295} 2296 2297status_t ACodec::verifySupportForProfileAndLevel( 2298 int32_t profile, int32_t level) { 2299 OMX_VIDEO_PARAM_PROFILELEVELTYPE params; 2300 InitOMXParams(¶ms); 2301 params.nPortIndex = kPortIndexOutput; 2302 2303 for (params.nProfileIndex = 0;; ++params.nProfileIndex) { 2304 status_t err = mOMX->getParameter( 2305 mNode, 2306 OMX_IndexParamVideoProfileLevelQuerySupported, 2307 ¶ms, 2308 sizeof(params)); 2309 2310 if (err != OK) { 2311 return err; 2312 } 2313 2314 int32_t supportedProfile = static_cast<int32_t>(params.eProfile); 2315 int32_t supportedLevel = static_cast<int32_t>(params.eLevel); 2316 2317 if (profile == supportedProfile && level <= supportedLevel) { 2318 return OK; 2319 } 2320 } 2321} 2322 2323status_t ACodec::configureBitrate( 2324 int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode) { 2325 OMX_VIDEO_PARAM_BITRATETYPE bitrateType; 2326 InitOMXParams(&bitrateType); 2327 bitrateType.nPortIndex = kPortIndexOutput; 2328 2329 status_t err = mOMX->getParameter( 2330 mNode, OMX_IndexParamVideoBitrate, 2331 &bitrateType, sizeof(bitrateType)); 2332 2333 if (err != OK) { 2334 return err; 2335 } 2336 2337 bitrateType.eControlRate = bitrateMode; 2338 bitrateType.nTargetBitrate = bitrate; 2339 2340 return mOMX->setParameter( 2341 mNode, OMX_IndexParamVideoBitrate, 2342 &bitrateType, sizeof(bitrateType)); 2343} 2344 2345status_t ACodec::setupErrorCorrectionParameters() { 2346 OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType; 2347 InitOMXParams(&errorCorrectionType); 2348 errorCorrectionType.nPortIndex = kPortIndexOutput; 2349 2350 status_t err = mOMX->getParameter( 2351 mNode, OMX_IndexParamVideoErrorCorrection, 2352 &errorCorrectionType, sizeof(errorCorrectionType)); 2353 2354 if (err != OK) { 2355 return OK; // Optional feature. Ignore this failure 2356 } 2357 2358 errorCorrectionType.bEnableHEC = OMX_FALSE; 2359 errorCorrectionType.bEnableResync = OMX_TRUE; 2360 errorCorrectionType.nResynchMarkerSpacing = 256; 2361 errorCorrectionType.bEnableDataPartitioning = OMX_FALSE; 2362 errorCorrectionType.bEnableRVLC = OMX_FALSE; 2363 2364 return mOMX->setParameter( 2365 mNode, OMX_IndexParamVideoErrorCorrection, 2366 &errorCorrectionType, sizeof(errorCorrectionType)); 2367} 2368 2369status_t ACodec::setVideoFormatOnPort( 2370 OMX_U32 portIndex, 2371 int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) { 2372 OMX_PARAM_PORTDEFINITIONTYPE def; 2373 InitOMXParams(&def); 2374 def.nPortIndex = portIndex; 2375 2376 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 2377 2378 status_t err = mOMX->getParameter( 2379 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2380 2381 CHECK_EQ(err, (status_t)OK); 2382 2383 if (portIndex == kPortIndexInput) { 2384 // XXX Need a (much) better heuristic to compute input buffer sizes. 2385 const size_t X = 64 * 1024; 2386 if (def.nBufferSize < X) { 2387 def.nBufferSize = X; 2388 } 2389 } 2390 2391 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo); 2392 2393 video_def->nFrameWidth = width; 2394 video_def->nFrameHeight = height; 2395 2396 if (portIndex == kPortIndexInput) { 2397 video_def->eCompressionFormat = compressionFormat; 2398 video_def->eColorFormat = OMX_COLOR_FormatUnused; 2399 } 2400 2401 err = mOMX->setParameter( 2402 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2403 2404 return err; 2405} 2406 2407status_t ACodec::initNativeWindow() { 2408 if (mNativeWindow != NULL) { 2409 return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE); 2410 } 2411 2412 mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE); 2413 return OK; 2414} 2415 2416size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const { 2417 size_t n = 0; 2418 2419 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 2420 const BufferInfo &info = mBuffers[portIndex].itemAt(i); 2421 2422 if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) { 2423 ++n; 2424 } 2425 } 2426 2427 return n; 2428} 2429 2430size_t ACodec::countBuffersOwnedByNativeWindow() const { 2431 size_t n = 0; 2432 2433 for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) { 2434 const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i); 2435 2436 if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 2437 ++n; 2438 } 2439 } 2440 2441 return n; 2442} 2443 2444void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() { 2445 if (mNativeWindow == NULL) { 2446 return; 2447 } 2448 2449 while (countBuffersOwnedByNativeWindow() > mNumUndequeuedBuffers 2450 && dequeueBufferFromNativeWindow() != NULL) { 2451 // these buffers will be submitted as regular buffers; account for this 2452 if (mStoreMetaDataInOutputBuffers && mMetaDataBuffersToSubmit > 0) { 2453 --mMetaDataBuffersToSubmit; 2454 } 2455 } 2456} 2457 2458bool ACodec::allYourBuffersAreBelongToUs( 2459 OMX_U32 portIndex) { 2460 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 2461 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 2462 2463 if (info->mStatus != BufferInfo::OWNED_BY_US 2464 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) { 2465 ALOGV("[%s] Buffer %p on port %ld still has status %d", 2466 mComponentName.c_str(), 2467 info->mBufferID, portIndex, info->mStatus); 2468 return false; 2469 } 2470 } 2471 2472 return true; 2473} 2474 2475bool ACodec::allYourBuffersAreBelongToUs() { 2476 return allYourBuffersAreBelongToUs(kPortIndexInput) 2477 && allYourBuffersAreBelongToUs(kPortIndexOutput); 2478} 2479 2480void ACodec::deferMessage(const sp<AMessage> &msg) { 2481 bool wasEmptyBefore = mDeferredQueue.empty(); 2482 mDeferredQueue.push_back(msg); 2483} 2484 2485void ACodec::processDeferredMessages() { 2486 List<sp<AMessage> > queue = mDeferredQueue; 2487 mDeferredQueue.clear(); 2488 2489 List<sp<AMessage> >::iterator it = queue.begin(); 2490 while (it != queue.end()) { 2491 onMessageReceived(*it++); 2492 } 2493} 2494 2495void ACodec::sendFormatChange(const sp<AMessage> &reply) { 2496 sp<AMessage> notify = mNotify->dup(); 2497 notify->setInt32("what", kWhatOutputFormatChanged); 2498 2499 OMX_PARAM_PORTDEFINITIONTYPE def; 2500 InitOMXParams(&def); 2501 def.nPortIndex = kPortIndexOutput; 2502 2503 CHECK_EQ(mOMX->getParameter( 2504 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)), 2505 (status_t)OK); 2506 2507 CHECK_EQ((int)def.eDir, (int)OMX_DirOutput); 2508 2509 switch (def.eDomain) { 2510 case OMX_PortDomainVideo: 2511 { 2512 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video; 2513 2514 AString mime; 2515 if (!mIsEncoder) { 2516 notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW); 2517 } else if (GetMimeTypeForVideoCoding( 2518 videoDef->eCompressionFormat, &mime) != OK) { 2519 notify->setString("mime", "application/octet-stream"); 2520 } else { 2521 notify->setString("mime", mime.c_str()); 2522 } 2523 2524 notify->setInt32("width", videoDef->nFrameWidth); 2525 notify->setInt32("height", videoDef->nFrameHeight); 2526 2527 if (!mIsEncoder) { 2528 notify->setInt32("stride", videoDef->nStride); 2529 notify->setInt32("slice-height", videoDef->nSliceHeight); 2530 notify->setInt32("color-format", videoDef->eColorFormat); 2531 2532 OMX_CONFIG_RECTTYPE rect; 2533 InitOMXParams(&rect); 2534 rect.nPortIndex = kPortIndexOutput; 2535 2536 if (mOMX->getConfig( 2537 mNode, OMX_IndexConfigCommonOutputCrop, 2538 &rect, sizeof(rect)) != OK) { 2539 rect.nLeft = 0; 2540 rect.nTop = 0; 2541 rect.nWidth = videoDef->nFrameWidth; 2542 rect.nHeight = videoDef->nFrameHeight; 2543 } 2544 2545 CHECK_GE(rect.nLeft, 0); 2546 CHECK_GE(rect.nTop, 0); 2547 CHECK_GE(rect.nWidth, 0u); 2548 CHECK_GE(rect.nHeight, 0u); 2549 CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth); 2550 CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight); 2551 2552 notify->setRect( 2553 "crop", 2554 rect.nLeft, 2555 rect.nTop, 2556 rect.nLeft + rect.nWidth - 1, 2557 rect.nTop + rect.nHeight - 1); 2558 2559 if (mNativeWindow != NULL) { 2560 reply->setRect( 2561 "crop", 2562 rect.nLeft, 2563 rect.nTop, 2564 rect.nLeft + rect.nWidth, 2565 rect.nTop + rect.nHeight); 2566 } 2567 } 2568 break; 2569 } 2570 2571 case OMX_PortDomainAudio: 2572 { 2573 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio; 2574 2575 switch (audioDef->eEncoding) { 2576 case OMX_AUDIO_CodingPCM: 2577 { 2578 OMX_AUDIO_PARAM_PCMMODETYPE params; 2579 InitOMXParams(¶ms); 2580 params.nPortIndex = kPortIndexOutput; 2581 2582 CHECK_EQ(mOMX->getParameter( 2583 mNode, OMX_IndexParamAudioPcm, 2584 ¶ms, sizeof(params)), 2585 (status_t)OK); 2586 2587 CHECK_GT(params.nChannels, 0); 2588 CHECK(params.nChannels == 1 || params.bInterleaved); 2589 CHECK_EQ(params.nBitPerSample, 16u); 2590 2591 CHECK_EQ((int)params.eNumData, 2592 (int)OMX_NumericalDataSigned); 2593 2594 CHECK_EQ((int)params.ePCMMode, 2595 (int)OMX_AUDIO_PCMModeLinear); 2596 2597 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW); 2598 notify->setInt32("channel-count", params.nChannels); 2599 notify->setInt32("sample-rate", params.nSamplingRate); 2600 if (mEncoderDelay + mEncoderPadding) { 2601 size_t frameSize = params.nChannels * sizeof(int16_t); 2602 if (mSkipCutBuffer != NULL) { 2603 size_t prevbufsize = mSkipCutBuffer->size(); 2604 if (prevbufsize != 0) { 2605 ALOGW("Replacing SkipCutBuffer holding %d " 2606 "bytes", 2607 prevbufsize); 2608 } 2609 } 2610 mSkipCutBuffer = new SkipCutBuffer( 2611 mEncoderDelay * frameSize, 2612 mEncoderPadding * frameSize); 2613 } 2614 2615 if (mChannelMaskPresent) { 2616 notify->setInt32("channel-mask", mChannelMask); 2617 } 2618 break; 2619 } 2620 2621 case OMX_AUDIO_CodingAAC: 2622 { 2623 OMX_AUDIO_PARAM_AACPROFILETYPE params; 2624 InitOMXParams(¶ms); 2625 params.nPortIndex = kPortIndexOutput; 2626 2627 CHECK_EQ(mOMX->getParameter( 2628 mNode, OMX_IndexParamAudioAac, 2629 ¶ms, sizeof(params)), 2630 (status_t)OK); 2631 2632 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC); 2633 notify->setInt32("channel-count", params.nChannels); 2634 notify->setInt32("sample-rate", params.nSampleRate); 2635 break; 2636 } 2637 2638 case OMX_AUDIO_CodingAMR: 2639 { 2640 OMX_AUDIO_PARAM_AMRTYPE params; 2641 InitOMXParams(¶ms); 2642 params.nPortIndex = kPortIndexOutput; 2643 2644 CHECK_EQ(mOMX->getParameter( 2645 mNode, OMX_IndexParamAudioAmr, 2646 ¶ms, sizeof(params)), 2647 (status_t)OK); 2648 2649 notify->setInt32("channel-count", 1); 2650 if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) { 2651 notify->setString( 2652 "mime", MEDIA_MIMETYPE_AUDIO_AMR_WB); 2653 2654 notify->setInt32("sample-rate", 16000); 2655 } else { 2656 notify->setString( 2657 "mime", MEDIA_MIMETYPE_AUDIO_AMR_NB); 2658 2659 notify->setInt32("sample-rate", 8000); 2660 } 2661 break; 2662 } 2663 2664 case OMX_AUDIO_CodingFLAC: 2665 { 2666 OMX_AUDIO_PARAM_FLACTYPE params; 2667 InitOMXParams(¶ms); 2668 params.nPortIndex = kPortIndexOutput; 2669 2670 CHECK_EQ(mOMX->getParameter( 2671 mNode, OMX_IndexParamAudioFlac, 2672 ¶ms, sizeof(params)), 2673 (status_t)OK); 2674 2675 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC); 2676 notify->setInt32("channel-count", params.nChannels); 2677 notify->setInt32("sample-rate", params.nSampleRate); 2678 break; 2679 } 2680 2681 default: 2682 TRESPASS(); 2683 } 2684 break; 2685 } 2686 2687 default: 2688 TRESPASS(); 2689 } 2690 2691 notify->post(); 2692 2693 mSentFormat = true; 2694} 2695 2696void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) { 2697 sp<AMessage> notify = mNotify->dup(); 2698 notify->setInt32("what", ACodec::kWhatError); 2699 notify->setInt32("omx-error", error); 2700 notify->setInt32("err", internalError); 2701 notify->post(); 2702} 2703 2704status_t ACodec::pushBlankBuffersToNativeWindow() { 2705 status_t err = NO_ERROR; 2706 ANativeWindowBuffer* anb = NULL; 2707 int numBufs = 0; 2708 int minUndequeuedBufs = 0; 2709 2710 // We need to reconnect to the ANativeWindow as a CPU client to ensure that 2711 // no frames get dropped by SurfaceFlinger assuming that these are video 2712 // frames. 2713 err = native_window_api_disconnect(mNativeWindow.get(), 2714 NATIVE_WINDOW_API_MEDIA); 2715 if (err != NO_ERROR) { 2716 ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)", 2717 strerror(-err), -err); 2718 return err; 2719 } 2720 2721 err = native_window_api_connect(mNativeWindow.get(), 2722 NATIVE_WINDOW_API_CPU); 2723 if (err != NO_ERROR) { 2724 ALOGE("error pushing blank frames: api_connect failed: %s (%d)", 2725 strerror(-err), -err); 2726 return err; 2727 } 2728 2729 err = native_window_set_buffers_geometry(mNativeWindow.get(), 1, 1, 2730 HAL_PIXEL_FORMAT_RGBX_8888); 2731 if (err != NO_ERROR) { 2732 ALOGE("error pushing blank frames: set_buffers_geometry failed: %s (%d)", 2733 strerror(-err), -err); 2734 goto error; 2735 } 2736 2737 err = native_window_set_scaling_mode(mNativeWindow.get(), 2738 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); 2739 if (err != NO_ERROR) { 2740 ALOGE("error pushing blank_frames: set_scaling_mode failed: %s (%d)", 2741 strerror(-err), -err); 2742 goto error; 2743 } 2744 2745 err = native_window_set_usage(mNativeWindow.get(), 2746 GRALLOC_USAGE_SW_WRITE_OFTEN); 2747 if (err != NO_ERROR) { 2748 ALOGE("error pushing blank frames: set_usage failed: %s (%d)", 2749 strerror(-err), -err); 2750 goto error; 2751 } 2752 2753 err = mNativeWindow->query(mNativeWindow.get(), 2754 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs); 2755 if (err != NO_ERROR) { 2756 ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query " 2757 "failed: %s (%d)", strerror(-err), -err); 2758 goto error; 2759 } 2760 2761 numBufs = minUndequeuedBufs + 1; 2762 err = native_window_set_buffer_count(mNativeWindow.get(), numBufs); 2763 if (err != NO_ERROR) { 2764 ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)", 2765 strerror(-err), -err); 2766 goto error; 2767 } 2768 2769 // We push numBufs + 1 buffers to ensure that we've drawn into the same 2770 // buffer twice. This should guarantee that the buffer has been displayed 2771 // on the screen and then been replaced, so an previous video frames are 2772 // guaranteed NOT to be currently displayed. 2773 for (int i = 0; i < numBufs + 1; i++) { 2774 int fenceFd = -1; 2775 err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &anb); 2776 if (err != NO_ERROR) { 2777 ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)", 2778 strerror(-err), -err); 2779 goto error; 2780 } 2781 2782 sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); 2783 2784 // Fill the buffer with the a 1x1 checkerboard pattern ;) 2785 uint32_t* img = NULL; 2786 err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); 2787 if (err != NO_ERROR) { 2788 ALOGE("error pushing blank frames: lock failed: %s (%d)", 2789 strerror(-err), -err); 2790 goto error; 2791 } 2792 2793 *img = 0; 2794 2795 err = buf->unlock(); 2796 if (err != NO_ERROR) { 2797 ALOGE("error pushing blank frames: unlock failed: %s (%d)", 2798 strerror(-err), -err); 2799 goto error; 2800 } 2801 2802 err = mNativeWindow->queueBuffer(mNativeWindow.get(), 2803 buf->getNativeBuffer(), -1); 2804 if (err != NO_ERROR) { 2805 ALOGE("error pushing blank frames: queueBuffer failed: %s (%d)", 2806 strerror(-err), -err); 2807 goto error; 2808 } 2809 2810 anb = NULL; 2811 } 2812 2813error: 2814 2815 if (err != NO_ERROR) { 2816 // Clean up after an error. 2817 if (anb != NULL) { 2818 mNativeWindow->cancelBuffer(mNativeWindow.get(), anb, -1); 2819 } 2820 2821 native_window_api_disconnect(mNativeWindow.get(), 2822 NATIVE_WINDOW_API_CPU); 2823 native_window_api_connect(mNativeWindow.get(), 2824 NATIVE_WINDOW_API_MEDIA); 2825 2826 return err; 2827 } else { 2828 // Clean up after success. 2829 err = native_window_api_disconnect(mNativeWindow.get(), 2830 NATIVE_WINDOW_API_CPU); 2831 if (err != NO_ERROR) { 2832 ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)", 2833 strerror(-err), -err); 2834 return err; 2835 } 2836 2837 err = native_window_api_connect(mNativeWindow.get(), 2838 NATIVE_WINDOW_API_MEDIA); 2839 if (err != NO_ERROR) { 2840 ALOGE("error pushing blank frames: api_connect failed: %s (%d)", 2841 strerror(-err), -err); 2842 return err; 2843 } 2844 2845 return NO_ERROR; 2846 } 2847} 2848 2849//////////////////////////////////////////////////////////////////////////////// 2850 2851ACodec::PortDescription::PortDescription() { 2852} 2853 2854status_t ACodec::requestIDRFrame() { 2855 if (!mIsEncoder) { 2856 return ERROR_UNSUPPORTED; 2857 } 2858 2859 OMX_CONFIG_INTRAREFRESHVOPTYPE params; 2860 InitOMXParams(¶ms); 2861 2862 params.nPortIndex = kPortIndexOutput; 2863 params.IntraRefreshVOP = OMX_TRUE; 2864 2865 return mOMX->setConfig( 2866 mNode, 2867 OMX_IndexConfigVideoIntraVOPRefresh, 2868 ¶ms, 2869 sizeof(params)); 2870} 2871 2872void ACodec::PortDescription::addBuffer( 2873 IOMX::buffer_id id, const sp<ABuffer> &buffer) { 2874 mBufferIDs.push_back(id); 2875 mBuffers.push_back(buffer); 2876} 2877 2878size_t ACodec::PortDescription::countBuffers() { 2879 return mBufferIDs.size(); 2880} 2881 2882IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const { 2883 return mBufferIDs.itemAt(index); 2884} 2885 2886sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const { 2887 return mBuffers.itemAt(index); 2888} 2889 2890//////////////////////////////////////////////////////////////////////////////// 2891 2892ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState) 2893 : AState(parentState), 2894 mCodec(codec) { 2895} 2896 2897ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(OMX_U32 portIndex) { 2898 return KEEP_BUFFERS; 2899} 2900 2901bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) { 2902 switch (msg->what()) { 2903 case kWhatInputBufferFilled: 2904 { 2905 onInputBufferFilled(msg); 2906 break; 2907 } 2908 2909 case kWhatOutputBufferDrained: 2910 { 2911 onOutputBufferDrained(msg); 2912 break; 2913 } 2914 2915 case ACodec::kWhatOMXMessage: 2916 { 2917 return onOMXMessage(msg); 2918 } 2919 2920 case ACodec::kWhatCreateInputSurface: 2921 case ACodec::kWhatSignalEndOfInputStream: 2922 { 2923 ALOGE("Message 0x%x was not handled", msg->what()); 2924 mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION); 2925 return true; 2926 } 2927 2928 case ACodec::kWhatOMXDied: 2929 { 2930 ALOGE("OMX/mediaserver died, signalling error!"); 2931 mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT); 2932 break; 2933 } 2934 2935 default: 2936 return false; 2937 } 2938 2939 return true; 2940} 2941 2942bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) { 2943 int32_t type; 2944 CHECK(msg->findInt32("type", &type)); 2945 2946 IOMX::node_id nodeID; 2947 CHECK(msg->findPointer("node", &nodeID)); 2948 CHECK_EQ(nodeID, mCodec->mNode); 2949 2950 switch (type) { 2951 case omx_message::EVENT: 2952 { 2953 int32_t event, data1, data2; 2954 CHECK(msg->findInt32("event", &event)); 2955 CHECK(msg->findInt32("data1", &data1)); 2956 CHECK(msg->findInt32("data2", &data2)); 2957 2958 if (event == OMX_EventCmdComplete 2959 && data1 == OMX_CommandFlush 2960 && data2 == (int32_t)OMX_ALL) { 2961 // Use of this notification is not consistent across 2962 // implementations. We'll drop this notification and rely 2963 // on flush-complete notifications on the individual port 2964 // indices instead. 2965 2966 return true; 2967 } 2968 2969 return onOMXEvent( 2970 static_cast<OMX_EVENTTYPE>(event), 2971 static_cast<OMX_U32>(data1), 2972 static_cast<OMX_U32>(data2)); 2973 } 2974 2975 case omx_message::EMPTY_BUFFER_DONE: 2976 { 2977 IOMX::buffer_id bufferID; 2978 CHECK(msg->findPointer("buffer", &bufferID)); 2979 2980 return onOMXEmptyBufferDone(bufferID); 2981 } 2982 2983 case omx_message::FILL_BUFFER_DONE: 2984 { 2985 IOMX::buffer_id bufferID; 2986 CHECK(msg->findPointer("buffer", &bufferID)); 2987 2988 int32_t rangeOffset, rangeLength, flags; 2989 int64_t timeUs; 2990 void *platformPrivate; 2991 void *dataPtr; 2992 2993 CHECK(msg->findInt32("range_offset", &rangeOffset)); 2994 CHECK(msg->findInt32("range_length", &rangeLength)); 2995 CHECK(msg->findInt32("flags", &flags)); 2996 CHECK(msg->findInt64("timestamp", &timeUs)); 2997 CHECK(msg->findPointer("platform_private", &platformPrivate)); 2998 CHECK(msg->findPointer("data_ptr", &dataPtr)); 2999 3000 return onOMXFillBufferDone( 3001 bufferID, 3002 (size_t)rangeOffset, (size_t)rangeLength, 3003 (OMX_U32)flags, 3004 timeUs, 3005 platformPrivate, 3006 dataPtr); 3007 } 3008 3009 default: 3010 TRESPASS(); 3011 break; 3012 } 3013} 3014 3015bool ACodec::BaseState::onOMXEvent( 3016 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3017 if (event != OMX_EventError) { 3018 ALOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)", 3019 mCodec->mComponentName.c_str(), event, data1, data2); 3020 3021 return false; 3022 } 3023 3024 ALOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1); 3025 3026 mCodec->signalError((OMX_ERRORTYPE)data1); 3027 3028 return true; 3029} 3030 3031bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) { 3032 ALOGV("[%s] onOMXEmptyBufferDone %p", 3033 mCodec->mComponentName.c_str(), bufferID); 3034 3035 BufferInfo *info = 3036 mCodec->findBufferByID(kPortIndexInput, bufferID); 3037 3038 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); 3039 info->mStatus = BufferInfo::OWNED_BY_US; 3040 3041 const sp<AMessage> &bufferMeta = info->mData->meta(); 3042 void *mediaBuffer; 3043 if (bufferMeta->findPointer("mediaBuffer", &mediaBuffer) 3044 && mediaBuffer != NULL) { 3045 // We're in "store-metadata-in-buffers" mode, the underlying 3046 // OMX component had access to data that's implicitly refcounted 3047 // by this "mediaBuffer" object. Now that the OMX component has 3048 // told us that it's done with the input buffer, we can decrement 3049 // the mediaBuffer's reference count. 3050 3051 ALOGV("releasing mbuf %p", mediaBuffer); 3052 3053 ((MediaBuffer *)mediaBuffer)->release(); 3054 mediaBuffer = NULL; 3055 3056 bufferMeta->setPointer("mediaBuffer", NULL); 3057 } 3058 3059 PortMode mode = getPortMode(kPortIndexInput); 3060 3061 switch (mode) { 3062 case KEEP_BUFFERS: 3063 break; 3064 3065 case RESUBMIT_BUFFERS: 3066 postFillThisBuffer(info); 3067 break; 3068 3069 default: 3070 { 3071 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 3072 TRESPASS(); // Not currently used 3073 break; 3074 } 3075 } 3076 3077 return true; 3078} 3079 3080void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) { 3081 if (mCodec->mPortEOS[kPortIndexInput]) { 3082 return; 3083 } 3084 3085 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 3086 3087 sp<AMessage> notify = mCodec->mNotify->dup(); 3088 notify->setInt32("what", ACodec::kWhatFillThisBuffer); 3089 notify->setPointer("buffer-id", info->mBufferID); 3090 3091 info->mData->meta()->clear(); 3092 notify->setBuffer("buffer", info->mData); 3093 3094 sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id()); 3095 reply->setPointer("buffer-id", info->mBufferID); 3096 3097 notify->setMessage("reply", reply); 3098 3099 notify->post(); 3100 3101 info->mStatus = BufferInfo::OWNED_BY_UPSTREAM; 3102} 3103 3104void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { 3105 IOMX::buffer_id bufferID; 3106 CHECK(msg->findPointer("buffer-id", &bufferID)); 3107 3108 sp<ABuffer> buffer; 3109 int32_t err = OK; 3110 bool eos = false; 3111 PortMode mode = getPortMode(kPortIndexInput); 3112 3113 if (!msg->findBuffer("buffer", &buffer)) { 3114 /* these are unfilled buffers returned by client */ 3115 CHECK(msg->findInt32("err", &err)); 3116 3117 if (err == OK) { 3118 /* buffers with no errors are returned on MediaCodec.flush */ 3119 mode = KEEP_BUFFERS; 3120 } else { 3121 ALOGV("[%s] saw error %d instead of an input buffer", 3122 mCodec->mComponentName.c_str(), err); 3123 eos = true; 3124 } 3125 3126 buffer.clear(); 3127 } 3128 3129 int32_t tmp; 3130 if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) { 3131 eos = true; 3132 err = ERROR_END_OF_STREAM; 3133 } 3134 3135 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID); 3136 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM); 3137 3138 info->mStatus = BufferInfo::OWNED_BY_US; 3139 3140 switch (mode) { 3141 case KEEP_BUFFERS: 3142 { 3143 if (eos) { 3144 if (!mCodec->mPortEOS[kPortIndexInput]) { 3145 mCodec->mPortEOS[kPortIndexInput] = true; 3146 mCodec->mInputEOSResult = err; 3147 } 3148 } 3149 break; 3150 } 3151 3152 case RESUBMIT_BUFFERS: 3153 { 3154 if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) { 3155 int64_t timeUs; 3156 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 3157 3158 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME; 3159 3160 int32_t isCSD; 3161 if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) { 3162 flags |= OMX_BUFFERFLAG_CODECCONFIG; 3163 } 3164 3165 if (eos) { 3166 flags |= OMX_BUFFERFLAG_EOS; 3167 } 3168 3169 if (buffer != info->mData) { 3170 ALOGV("[%s] Needs to copy input data for buffer %p. (%p != %p)", 3171 mCodec->mComponentName.c_str(), 3172 bufferID, 3173 buffer.get(), info->mData.get()); 3174 3175 CHECK_LE(buffer->size(), info->mData->capacity()); 3176 memcpy(info->mData->data(), buffer->data(), buffer->size()); 3177 } 3178 3179 if (flags & OMX_BUFFERFLAG_CODECCONFIG) { 3180 ALOGV("[%s] calling emptyBuffer %p w/ codec specific data", 3181 mCodec->mComponentName.c_str(), bufferID); 3182 } else if (flags & OMX_BUFFERFLAG_EOS) { 3183 ALOGV("[%s] calling emptyBuffer %p w/ EOS", 3184 mCodec->mComponentName.c_str(), bufferID); 3185 } else { 3186#if TRACK_BUFFER_TIMING 3187 ALOGI("[%s] calling emptyBuffer %p w/ time %lld us", 3188 mCodec->mComponentName.c_str(), bufferID, timeUs); 3189#else 3190 ALOGV("[%s] calling emptyBuffer %p w/ time %lld us", 3191 mCodec->mComponentName.c_str(), bufferID, timeUs); 3192#endif 3193 } 3194 3195#if TRACK_BUFFER_TIMING 3196 ACodec::BufferStats stats; 3197 stats.mEmptyBufferTimeUs = ALooper::GetNowUs(); 3198 stats.mFillBufferDoneTimeUs = -1ll; 3199 mCodec->mBufferStats.add(timeUs, stats); 3200#endif 3201 3202 if (mCodec->mStoreMetaDataInOutputBuffers) { 3203 // try to submit an output buffer for each input buffer 3204 PortMode outputMode = getPortMode(kPortIndexOutput); 3205 3206 ALOGV("MetaDataBuffersToSubmit=%u portMode=%s", 3207 mCodec->mMetaDataBuffersToSubmit, 3208 (outputMode == FREE_BUFFERS ? "FREE" : 3209 outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT")); 3210 if (outputMode == RESUBMIT_BUFFERS) { 3211 CHECK_EQ(mCodec->submitOutputMetaDataBuffer(), 3212 (status_t)OK); 3213 } 3214 } 3215 3216 CHECK_EQ(mCodec->mOMX->emptyBuffer( 3217 mCodec->mNode, 3218 bufferID, 3219 0, 3220 buffer->size(), 3221 flags, 3222 timeUs), 3223 (status_t)OK); 3224 3225 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 3226 3227 if (!eos) { 3228 getMoreInputDataIfPossible(); 3229 } else { 3230 ALOGV("[%s] Signalled EOS on the input port", 3231 mCodec->mComponentName.c_str()); 3232 3233 mCodec->mPortEOS[kPortIndexInput] = true; 3234 mCodec->mInputEOSResult = err; 3235 } 3236 } else if (!mCodec->mPortEOS[kPortIndexInput]) { 3237 if (err != ERROR_END_OF_STREAM) { 3238 ALOGV("[%s] Signalling EOS on the input port " 3239 "due to error %d", 3240 mCodec->mComponentName.c_str(), err); 3241 } else { 3242 ALOGV("[%s] Signalling EOS on the input port", 3243 mCodec->mComponentName.c_str()); 3244 } 3245 3246 ALOGV("[%s] calling emptyBuffer %p signalling EOS", 3247 mCodec->mComponentName.c_str(), bufferID); 3248 3249 CHECK_EQ(mCodec->mOMX->emptyBuffer( 3250 mCodec->mNode, 3251 bufferID, 3252 0, 3253 0, 3254 OMX_BUFFERFLAG_EOS, 3255 0), 3256 (status_t)OK); 3257 3258 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 3259 3260 mCodec->mPortEOS[kPortIndexInput] = true; 3261 mCodec->mInputEOSResult = err; 3262 } 3263 break; 3264 } 3265 3266 default: 3267 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 3268 break; 3269 } 3270} 3271 3272void ACodec::BaseState::getMoreInputDataIfPossible() { 3273 if (mCodec->mPortEOS[kPortIndexInput]) { 3274 return; 3275 } 3276 3277 BufferInfo *eligible = NULL; 3278 3279 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 3280 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 3281 3282#if 0 3283 if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) { 3284 // There's already a "read" pending. 3285 return; 3286 } 3287#endif 3288 3289 if (info->mStatus == BufferInfo::OWNED_BY_US) { 3290 eligible = info; 3291 } 3292 } 3293 3294 if (eligible == NULL) { 3295 return; 3296 } 3297 3298 postFillThisBuffer(eligible); 3299} 3300 3301bool ACodec::BaseState::onOMXFillBufferDone( 3302 IOMX::buffer_id bufferID, 3303 size_t rangeOffset, size_t rangeLength, 3304 OMX_U32 flags, 3305 int64_t timeUs, 3306 void *platformPrivate, 3307 void *dataPtr) { 3308 ALOGV("[%s] onOMXFillBufferDone %p time %lld us, flags = 0x%08lx", 3309 mCodec->mComponentName.c_str(), bufferID, timeUs, flags); 3310 3311 ssize_t index; 3312 3313#if TRACK_BUFFER_TIMING 3314 index = mCodec->mBufferStats.indexOfKey(timeUs); 3315 if (index >= 0) { 3316 ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index); 3317 stats->mFillBufferDoneTimeUs = ALooper::GetNowUs(); 3318 3319 ALOGI("frame PTS %lld: %lld", 3320 timeUs, 3321 stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs); 3322 3323 mCodec->mBufferStats.removeItemsAt(index); 3324 stats = NULL; 3325 } 3326#endif 3327 3328 BufferInfo *info = 3329 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 3330 3331 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); 3332 3333 info->mDequeuedAt = ++mCodec->mDequeueCounter; 3334 info->mStatus = BufferInfo::OWNED_BY_US; 3335 3336 PortMode mode = getPortMode(kPortIndexOutput); 3337 3338 switch (mode) { 3339 case KEEP_BUFFERS: 3340 break; 3341 3342 case RESUBMIT_BUFFERS: 3343 { 3344 if (rangeLength == 0 && !(flags & OMX_BUFFERFLAG_EOS)) { 3345 ALOGV("[%s] calling fillBuffer %p", 3346 mCodec->mComponentName.c_str(), info->mBufferID); 3347 3348 CHECK_EQ(mCodec->mOMX->fillBuffer( 3349 mCodec->mNode, info->mBufferID), 3350 (status_t)OK); 3351 3352 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 3353 break; 3354 } 3355 3356 sp<AMessage> reply = 3357 new AMessage(kWhatOutputBufferDrained, mCodec->id()); 3358 3359 if (!mCodec->mSentFormat) { 3360 mCodec->sendFormatChange(reply); 3361 } 3362 3363 if (mCodec->mUseMetadataOnEncoderOutput) { 3364 native_handle_t* handle = 3365 *(native_handle_t**)(info->mData->data() + 4); 3366 info->mData->meta()->setPointer("handle", handle); 3367 info->mData->meta()->setInt32("rangeOffset", rangeOffset); 3368 info->mData->meta()->setInt32("rangeLength", rangeLength); 3369 } else { 3370 info->mData->setRange(rangeOffset, rangeLength); 3371 } 3372#if 0 3373 if (mCodec->mNativeWindow == NULL) { 3374 if (IsIDR(info->mData)) { 3375 ALOGI("IDR frame"); 3376 } 3377 } 3378#endif 3379 3380 if (mCodec->mSkipCutBuffer != NULL) { 3381 mCodec->mSkipCutBuffer->submit(info->mData); 3382 } 3383 info->mData->meta()->setInt64("timeUs", timeUs); 3384 3385 sp<AMessage> notify = mCodec->mNotify->dup(); 3386 notify->setInt32("what", ACodec::kWhatDrainThisBuffer); 3387 notify->setPointer("buffer-id", info->mBufferID); 3388 notify->setBuffer("buffer", info->mData); 3389 notify->setInt32("flags", flags); 3390 3391 reply->setPointer("buffer-id", info->mBufferID); 3392 3393 notify->setMessage("reply", reply); 3394 3395 notify->post(); 3396 3397 info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM; 3398 3399 if (flags & OMX_BUFFERFLAG_EOS) { 3400 ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str()); 3401 3402 sp<AMessage> notify = mCodec->mNotify->dup(); 3403 notify->setInt32("what", ACodec::kWhatEOS); 3404 notify->setInt32("err", mCodec->mInputEOSResult); 3405 notify->post(); 3406 3407 mCodec->mPortEOS[kPortIndexOutput] = true; 3408 } 3409 break; 3410 } 3411 3412 default: 3413 { 3414 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 3415 3416 CHECK_EQ((status_t)OK, 3417 mCodec->freeBuffer(kPortIndexOutput, index)); 3418 break; 3419 } 3420 } 3421 3422 return true; 3423} 3424 3425void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { 3426 IOMX::buffer_id bufferID; 3427 CHECK(msg->findPointer("buffer-id", &bufferID)); 3428 3429 ssize_t index; 3430 BufferInfo *info = 3431 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 3432 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM); 3433 3434 android_native_rect_t crop; 3435 if (msg->findRect("crop", 3436 &crop.left, &crop.top, &crop.right, &crop.bottom)) { 3437 CHECK_EQ(0, native_window_set_crop( 3438 mCodec->mNativeWindow.get(), &crop)); 3439 } 3440 3441 int32_t render; 3442 if (mCodec->mNativeWindow != NULL 3443 && msg->findInt32("render", &render) && render != 0 3444 && (info->mData == NULL || info->mData->size() != 0)) { 3445 // The client wants this buffer to be rendered. 3446 3447 status_t err; 3448 if ((err = mCodec->mNativeWindow->queueBuffer( 3449 mCodec->mNativeWindow.get(), 3450 info->mGraphicBuffer.get(), -1)) == OK) { 3451 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 3452 } else { 3453 mCodec->signalError(OMX_ErrorUndefined, err); 3454 info->mStatus = BufferInfo::OWNED_BY_US; 3455 } 3456 } else { 3457 info->mStatus = BufferInfo::OWNED_BY_US; 3458 } 3459 3460 PortMode mode = getPortMode(kPortIndexOutput); 3461 3462 switch (mode) { 3463 case KEEP_BUFFERS: 3464 { 3465 // XXX fishy, revisit!!! What about the FREE_BUFFERS case below? 3466 3467 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 3468 // We cannot resubmit the buffer we just rendered, dequeue 3469 // the spare instead. 3470 3471 info = mCodec->dequeueBufferFromNativeWindow(); 3472 } 3473 break; 3474 } 3475 3476 case RESUBMIT_BUFFERS: 3477 { 3478 if (!mCodec->mPortEOS[kPortIndexOutput]) { 3479 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 3480 // We cannot resubmit the buffer we just rendered, dequeue 3481 // the spare instead. 3482 3483 info = mCodec->dequeueBufferFromNativeWindow(); 3484 } 3485 3486 if (info != NULL) { 3487 ALOGV("[%s] calling fillBuffer %p", 3488 mCodec->mComponentName.c_str(), info->mBufferID); 3489 3490 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), 3491 (status_t)OK); 3492 3493 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 3494 } 3495 } 3496 break; 3497 } 3498 3499 default: 3500 { 3501 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 3502 3503 CHECK_EQ((status_t)OK, 3504 mCodec->freeBuffer(kPortIndexOutput, index)); 3505 break; 3506 } 3507 } 3508} 3509 3510//////////////////////////////////////////////////////////////////////////////// 3511 3512ACodec::UninitializedState::UninitializedState(ACodec *codec) 3513 : BaseState(codec) { 3514} 3515 3516void ACodec::UninitializedState::stateEntered() { 3517 ALOGV("Now uninitialized"); 3518 3519 if (mDeathNotifier != NULL) { 3520 mCodec->mOMX->asBinder()->unlinkToDeath(mDeathNotifier); 3521 mDeathNotifier.clear(); 3522 } 3523 3524 mCodec->mNativeWindow.clear(); 3525 mCodec->mNode = NULL; 3526 mCodec->mOMX.clear(); 3527 mCodec->mQuirks = 0; 3528 mCodec->mFlags = 0; 3529 mCodec->mUseMetadataOnEncoderOutput = 0; 3530 mCodec->mComponentName.clear(); 3531} 3532 3533bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) { 3534 bool handled = false; 3535 3536 switch (msg->what()) { 3537 case ACodec::kWhatSetup: 3538 { 3539 onSetup(msg); 3540 3541 handled = true; 3542 break; 3543 } 3544 3545 case ACodec::kWhatAllocateComponent: 3546 { 3547 onAllocateComponent(msg); 3548 handled = true; 3549 break; 3550 } 3551 3552 case ACodec::kWhatShutdown: 3553 { 3554 int32_t keepComponentAllocated; 3555 CHECK(msg->findInt32( 3556 "keepComponentAllocated", &keepComponentAllocated)); 3557 CHECK(!keepComponentAllocated); 3558 3559 sp<AMessage> notify = mCodec->mNotify->dup(); 3560 notify->setInt32("what", ACodec::kWhatShutdownCompleted); 3561 notify->post(); 3562 3563 handled = true; 3564 break; 3565 } 3566 3567 case ACodec::kWhatFlush: 3568 { 3569 sp<AMessage> notify = mCodec->mNotify->dup(); 3570 notify->setInt32("what", ACodec::kWhatFlushCompleted); 3571 notify->post(); 3572 3573 handled = true; 3574 break; 3575 } 3576 3577 default: 3578 return BaseState::onMessageReceived(msg); 3579 } 3580 3581 return handled; 3582} 3583 3584void ACodec::UninitializedState::onSetup( 3585 const sp<AMessage> &msg) { 3586 if (onAllocateComponent(msg) 3587 && mCodec->mLoadedState->onConfigureComponent(msg)) { 3588 mCodec->mLoadedState->onStart(); 3589 } 3590} 3591 3592bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) { 3593 ALOGV("onAllocateComponent"); 3594 3595 CHECK(mCodec->mNode == NULL); 3596 3597 OMXClient client; 3598 CHECK_EQ(client.connect(), (status_t)OK); 3599 3600 sp<IOMX> omx = client.interface(); 3601 3602 sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec->id()); 3603 3604 mDeathNotifier = new DeathNotifier(notify); 3605 if (omx->asBinder()->linkToDeath(mDeathNotifier) != OK) { 3606 // This was a local binder, if it dies so do we, we won't care 3607 // about any notifications in the afterlife. 3608 mDeathNotifier.clear(); 3609 } 3610 3611 Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs; 3612 3613 AString mime; 3614 3615 AString componentName; 3616 uint32_t quirks = 0; 3617 if (msg->findString("componentName", &componentName)) { 3618 ssize_t index = matchingCodecs.add(); 3619 OMXCodec::CodecNameAndQuirks *entry = &matchingCodecs.editItemAt(index); 3620 entry->mName = String8(componentName.c_str()); 3621 3622 if (!OMXCodec::findCodecQuirks( 3623 componentName.c_str(), &entry->mQuirks)) { 3624 entry->mQuirks = 0; 3625 } 3626 } else { 3627 CHECK(msg->findString("mime", &mime)); 3628 3629 int32_t encoder; 3630 if (!msg->findInt32("encoder", &encoder)) { 3631 encoder = false; 3632 } 3633 3634 OMXCodec::findMatchingCodecs( 3635 mime.c_str(), 3636 encoder, // createEncoder 3637 NULL, // matchComponentName 3638 0, // flags 3639 &matchingCodecs); 3640 } 3641 3642 sp<CodecObserver> observer = new CodecObserver; 3643 IOMX::node_id node = NULL; 3644 3645 for (size_t matchIndex = 0; matchIndex < matchingCodecs.size(); 3646 ++matchIndex) { 3647 componentName = matchingCodecs.itemAt(matchIndex).mName.string(); 3648 quirks = matchingCodecs.itemAt(matchIndex).mQuirks; 3649 3650 pid_t tid = androidGetTid(); 3651 int prevPriority = androidGetThreadPriority(tid); 3652 androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND); 3653 status_t err = omx->allocateNode(componentName.c_str(), observer, &node); 3654 androidSetThreadPriority(tid, prevPriority); 3655 3656 if (err == OK) { 3657 break; 3658 } 3659 3660 node = NULL; 3661 } 3662 3663 if (node == NULL) { 3664 if (!mime.empty()) { 3665 ALOGE("Unable to instantiate a decoder for type '%s'.", 3666 mime.c_str()); 3667 } else { 3668 ALOGE("Unable to instantiate decoder '%s'.", componentName.c_str()); 3669 } 3670 3671 mCodec->signalError(OMX_ErrorComponentNotFound); 3672 return false; 3673 } 3674 3675 notify = new AMessage(kWhatOMXMessage, mCodec->id()); 3676 observer->setNotificationMessage(notify); 3677 3678 mCodec->mComponentName = componentName; 3679 mCodec->mFlags = 0; 3680 3681 if (componentName.endsWith(".secure")) { 3682 mCodec->mFlags |= kFlagIsSecure; 3683 mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown; 3684 } 3685 3686 mCodec->mQuirks = quirks; 3687 mCodec->mOMX = omx; 3688 mCodec->mNode = node; 3689 3690 { 3691 sp<AMessage> notify = mCodec->mNotify->dup(); 3692 notify->setInt32("what", ACodec::kWhatComponentAllocated); 3693 notify->setString("componentName", mCodec->mComponentName.c_str()); 3694 notify->post(); 3695 } 3696 3697 mCodec->changeState(mCodec->mLoadedState); 3698 3699 return true; 3700} 3701 3702//////////////////////////////////////////////////////////////////////////////// 3703 3704ACodec::LoadedState::LoadedState(ACodec *codec) 3705 : BaseState(codec) { 3706} 3707 3708void ACodec::LoadedState::stateEntered() { 3709 ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str()); 3710 3711 mCodec->mPortEOS[kPortIndexInput] = 3712 mCodec->mPortEOS[kPortIndexOutput] = false; 3713 3714 mCodec->mInputEOSResult = OK; 3715 3716 mCodec->mDequeueCounter = 0; 3717 mCodec->mMetaDataBuffersToSubmit = 0; 3718 mCodec->mRepeatFrameDelayUs = -1ll; 3719 mCodec->mIsConfiguredForAdaptivePlayback = false; 3720 3721 if (mCodec->mShutdownInProgress) { 3722 bool keepComponentAllocated = mCodec->mKeepComponentAllocated; 3723 3724 mCodec->mShutdownInProgress = false; 3725 mCodec->mKeepComponentAllocated = false; 3726 3727 onShutdown(keepComponentAllocated); 3728 } 3729} 3730 3731void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) { 3732 if (!keepComponentAllocated) { 3733 CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK); 3734 3735 mCodec->changeState(mCodec->mUninitializedState); 3736 } 3737 3738 sp<AMessage> notify = mCodec->mNotify->dup(); 3739 notify->setInt32("what", ACodec::kWhatShutdownCompleted); 3740 notify->post(); 3741} 3742 3743bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) { 3744 bool handled = false; 3745 3746 switch (msg->what()) { 3747 case ACodec::kWhatConfigureComponent: 3748 { 3749 onConfigureComponent(msg); 3750 handled = true; 3751 break; 3752 } 3753 3754 case ACodec::kWhatCreateInputSurface: 3755 { 3756 onCreateInputSurface(msg); 3757 handled = true; 3758 break; 3759 } 3760 3761 case ACodec::kWhatStart: 3762 { 3763 onStart(); 3764 handled = true; 3765 break; 3766 } 3767 3768 case ACodec::kWhatShutdown: 3769 { 3770 int32_t keepComponentAllocated; 3771 CHECK(msg->findInt32( 3772 "keepComponentAllocated", &keepComponentAllocated)); 3773 3774 onShutdown(keepComponentAllocated); 3775 3776 handled = true; 3777 break; 3778 } 3779 3780 case ACodec::kWhatFlush: 3781 { 3782 sp<AMessage> notify = mCodec->mNotify->dup(); 3783 notify->setInt32("what", ACodec::kWhatFlushCompleted); 3784 notify->post(); 3785 3786 handled = true; 3787 break; 3788 } 3789 3790 default: 3791 return BaseState::onMessageReceived(msg); 3792 } 3793 3794 return handled; 3795} 3796 3797bool ACodec::LoadedState::onConfigureComponent( 3798 const sp<AMessage> &msg) { 3799 ALOGV("onConfigureComponent"); 3800 3801 CHECK(mCodec->mNode != NULL); 3802 3803 AString mime; 3804 CHECK(msg->findString("mime", &mime)); 3805 3806 status_t err = mCodec->configureCodec(mime.c_str(), msg); 3807 3808 if (err != OK) { 3809 ALOGE("[%s] configureCodec returning error %d", 3810 mCodec->mComponentName.c_str(), err); 3811 3812 mCodec->signalError(OMX_ErrorUndefined, err); 3813 return false; 3814 } 3815 3816 sp<RefBase> obj; 3817 if (msg->findObject("native-window", &obj) 3818 && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) { 3819 sp<NativeWindowWrapper> nativeWindow( 3820 static_cast<NativeWindowWrapper *>(obj.get())); 3821 CHECK(nativeWindow != NULL); 3822 mCodec->mNativeWindow = nativeWindow->getNativeWindow(); 3823 3824 native_window_set_scaling_mode( 3825 mCodec->mNativeWindow.get(), 3826 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); 3827 } 3828 CHECK_EQ((status_t)OK, mCodec->initNativeWindow()); 3829 3830 { 3831 sp<AMessage> notify = mCodec->mNotify->dup(); 3832 notify->setInt32("what", ACodec::kWhatComponentConfigured); 3833 notify->post(); 3834 } 3835 3836 return true; 3837} 3838 3839void ACodec::LoadedState::onCreateInputSurface( 3840 const sp<AMessage> &msg) { 3841 ALOGV("onCreateInputSurface"); 3842 3843 sp<AMessage> notify = mCodec->mNotify->dup(); 3844 notify->setInt32("what", ACodec::kWhatInputSurfaceCreated); 3845 3846 sp<IGraphicBufferProducer> bufferProducer; 3847 status_t err; 3848 3849 err = mCodec->mOMX->createInputSurface(mCodec->mNode, kPortIndexInput, 3850 &bufferProducer); 3851 3852 if (err == OK && mCodec->mRepeatFrameDelayUs > 0ll) { 3853 err = mCodec->mOMX->setInternalOption( 3854 mCodec->mNode, 3855 kPortIndexInput, 3856 IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY, 3857 &mCodec->mRepeatFrameDelayUs, 3858 sizeof(mCodec->mRepeatFrameDelayUs)); 3859 3860 if (err != OK) { 3861 ALOGE("[%s] Unable to configure option to repeat previous " 3862 "frames (err %d)", 3863 mCodec->mComponentName.c_str(), 3864 err); 3865 } 3866 } 3867 3868 if (err == OK && mCodec->mMaxPtsGapUs > 0l) { 3869 err = mCodec->mOMX->setInternalOption( 3870 mCodec->mNode, 3871 kPortIndexInput, 3872 IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP, 3873 &mCodec->mMaxPtsGapUs, 3874 sizeof(mCodec->mMaxPtsGapUs)); 3875 3876 if (err != OK) { 3877 ALOGE("[%s] Unable to configure max timestamp gap (err %d)", 3878 mCodec->mComponentName.c_str(), 3879 err); 3880 } 3881 } 3882 3883 if (err == OK) { 3884 notify->setObject("input-surface", 3885 new BufferProducerWrapper(bufferProducer)); 3886 } else { 3887 // Can't use mCodec->signalError() here -- MediaCodec won't forward 3888 // the error through because it's in the "configured" state. We 3889 // send a kWhatInputSurfaceCreated with an error value instead. 3890 ALOGE("[%s] onCreateInputSurface returning error %d", 3891 mCodec->mComponentName.c_str(), err); 3892 notify->setInt32("err", err); 3893 } 3894 notify->post(); 3895} 3896 3897void ACodec::LoadedState::onStart() { 3898 ALOGV("onStart"); 3899 3900 CHECK_EQ(mCodec->mOMX->sendCommand( 3901 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle), 3902 (status_t)OK); 3903 3904 mCodec->changeState(mCodec->mLoadedToIdleState); 3905} 3906 3907//////////////////////////////////////////////////////////////////////////////// 3908 3909ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec) 3910 : BaseState(codec) { 3911} 3912 3913void ACodec::LoadedToIdleState::stateEntered() { 3914 ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str()); 3915 3916 status_t err; 3917 if ((err = allocateBuffers()) != OK) { 3918 ALOGE("Failed to allocate buffers after transitioning to IDLE state " 3919 "(error 0x%08x)", 3920 err); 3921 3922 mCodec->signalError(OMX_ErrorUndefined, err); 3923 3924 mCodec->changeState(mCodec->mLoadedState); 3925 } 3926} 3927 3928status_t ACodec::LoadedToIdleState::allocateBuffers() { 3929 status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput); 3930 3931 if (err != OK) { 3932 return err; 3933 } 3934 3935 return mCodec->allocateBuffersOnPort(kPortIndexOutput); 3936} 3937 3938bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) { 3939 switch (msg->what()) { 3940 case kWhatShutdown: 3941 { 3942 mCodec->deferMessage(msg); 3943 return true; 3944 } 3945 3946 case kWhatSignalEndOfInputStream: 3947 { 3948 mCodec->onSignalEndOfInputStream(); 3949 return true; 3950 } 3951 3952 case kWhatResume: 3953 { 3954 // We'll be active soon enough. 3955 return true; 3956 } 3957 3958 case kWhatFlush: 3959 { 3960 // We haven't even started yet, so we're flushed alright... 3961 sp<AMessage> notify = mCodec->mNotify->dup(); 3962 notify->setInt32("what", ACodec::kWhatFlushCompleted); 3963 notify->post(); 3964 return true; 3965 } 3966 3967 default: 3968 return BaseState::onMessageReceived(msg); 3969 } 3970} 3971 3972bool ACodec::LoadedToIdleState::onOMXEvent( 3973 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3974 switch (event) { 3975 case OMX_EventCmdComplete: 3976 { 3977 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 3978 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); 3979 3980 CHECK_EQ(mCodec->mOMX->sendCommand( 3981 mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting), 3982 (status_t)OK); 3983 3984 mCodec->changeState(mCodec->mIdleToExecutingState); 3985 3986 return true; 3987 } 3988 3989 default: 3990 return BaseState::onOMXEvent(event, data1, data2); 3991 } 3992} 3993 3994//////////////////////////////////////////////////////////////////////////////// 3995 3996ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec) 3997 : BaseState(codec) { 3998} 3999 4000void ACodec::IdleToExecutingState::stateEntered() { 4001 ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str()); 4002} 4003 4004bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) { 4005 switch (msg->what()) { 4006 case kWhatShutdown: 4007 { 4008 mCodec->deferMessage(msg); 4009 return true; 4010 } 4011 4012 case kWhatResume: 4013 { 4014 // We'll be active soon enough. 4015 return true; 4016 } 4017 4018 case kWhatFlush: 4019 { 4020 // We haven't even started yet, so we're flushed alright... 4021 sp<AMessage> notify = mCodec->mNotify->dup(); 4022 notify->setInt32("what", ACodec::kWhatFlushCompleted); 4023 notify->post(); 4024 4025 return true; 4026 } 4027 4028 case kWhatSignalEndOfInputStream: 4029 { 4030 mCodec->onSignalEndOfInputStream(); 4031 return true; 4032 } 4033 4034 default: 4035 return BaseState::onMessageReceived(msg); 4036 } 4037} 4038 4039bool ACodec::IdleToExecutingState::onOMXEvent( 4040 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 4041 switch (event) { 4042 case OMX_EventCmdComplete: 4043 { 4044 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 4045 CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting); 4046 4047 mCodec->mExecutingState->resume(); 4048 mCodec->changeState(mCodec->mExecutingState); 4049 4050 return true; 4051 } 4052 4053 default: 4054 return BaseState::onOMXEvent(event, data1, data2); 4055 } 4056} 4057 4058//////////////////////////////////////////////////////////////////////////////// 4059 4060ACodec::ExecutingState::ExecutingState(ACodec *codec) 4061 : BaseState(codec), 4062 mActive(false) { 4063} 4064 4065ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode( 4066 OMX_U32 portIndex) { 4067 return RESUBMIT_BUFFERS; 4068} 4069 4070void ACodec::ExecutingState::submitOutputMetaBuffers() { 4071 // submit as many buffers as there are input buffers with the codec 4072 // in case we are in port reconfiguring 4073 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 4074 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 4075 4076 if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) { 4077 if (mCodec->submitOutputMetaDataBuffer() != OK) 4078 break; 4079 } 4080 } 4081 4082 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** 4083 mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround(); 4084} 4085 4086void ACodec::ExecutingState::submitRegularOutputBuffers() { 4087 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) { 4088 BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i); 4089 4090 if (mCodec->mNativeWindow != NULL) { 4091 CHECK(info->mStatus == BufferInfo::OWNED_BY_US 4092 || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW); 4093 4094 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 4095 continue; 4096 } 4097 } else { 4098 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 4099 } 4100 4101 ALOGV("[%s] calling fillBuffer %p", 4102 mCodec->mComponentName.c_str(), info->mBufferID); 4103 4104 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), 4105 (status_t)OK); 4106 4107 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 4108 } 4109} 4110 4111void ACodec::ExecutingState::submitOutputBuffers() { 4112 submitRegularOutputBuffers(); 4113 if (mCodec->mStoreMetaDataInOutputBuffers) { 4114 submitOutputMetaBuffers(); 4115 } 4116} 4117 4118void ACodec::ExecutingState::resume() { 4119 if (mActive) { 4120 ALOGV("[%s] We're already active, no need to resume.", 4121 mCodec->mComponentName.c_str()); 4122 4123 return; 4124 } 4125 4126 submitOutputBuffers(); 4127 4128 // Post the first input buffer. 4129 CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u); 4130 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0); 4131 4132 postFillThisBuffer(info); 4133 4134 mActive = true; 4135} 4136 4137void ACodec::ExecutingState::stateEntered() { 4138 ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str()); 4139 4140 mCodec->processDeferredMessages(); 4141} 4142 4143bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) { 4144 bool handled = false; 4145 4146 switch (msg->what()) { 4147 case kWhatShutdown: 4148 { 4149 int32_t keepComponentAllocated; 4150 CHECK(msg->findInt32( 4151 "keepComponentAllocated", &keepComponentAllocated)); 4152 4153 mCodec->mShutdownInProgress = true; 4154 mCodec->mKeepComponentAllocated = keepComponentAllocated; 4155 4156 mActive = false; 4157 4158 CHECK_EQ(mCodec->mOMX->sendCommand( 4159 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle), 4160 (status_t)OK); 4161 4162 mCodec->changeState(mCodec->mExecutingToIdleState); 4163 4164 handled = true; 4165 break; 4166 } 4167 4168 case kWhatFlush: 4169 { 4170 ALOGV("[%s] ExecutingState flushing now " 4171 "(codec owns %d/%d input, %d/%d output).", 4172 mCodec->mComponentName.c_str(), 4173 mCodec->countBuffersOwnedByComponent(kPortIndexInput), 4174 mCodec->mBuffers[kPortIndexInput].size(), 4175 mCodec->countBuffersOwnedByComponent(kPortIndexOutput), 4176 mCodec->mBuffers[kPortIndexOutput].size()); 4177 4178 mActive = false; 4179 4180 CHECK_EQ(mCodec->mOMX->sendCommand( 4181 mCodec->mNode, OMX_CommandFlush, OMX_ALL), 4182 (status_t)OK); 4183 4184 mCodec->changeState(mCodec->mFlushingState); 4185 handled = true; 4186 break; 4187 } 4188 4189 case kWhatResume: 4190 { 4191 resume(); 4192 4193 handled = true; 4194 break; 4195 } 4196 4197 case kWhatRequestIDRFrame: 4198 { 4199 status_t err = mCodec->requestIDRFrame(); 4200 if (err != OK) { 4201 ALOGW("Requesting an IDR frame failed."); 4202 } 4203 4204 handled = true; 4205 break; 4206 } 4207 4208 case kWhatSetParameters: 4209 { 4210 sp<AMessage> params; 4211 CHECK(msg->findMessage("params", ¶ms)); 4212 4213 status_t err = mCodec->setParameters(params); 4214 4215 sp<AMessage> reply; 4216 if (msg->findMessage("reply", &reply)) { 4217 reply->setInt32("err", err); 4218 reply->post(); 4219 } 4220 4221 handled = true; 4222 break; 4223 } 4224 4225 case ACodec::kWhatSignalEndOfInputStream: 4226 { 4227 mCodec->onSignalEndOfInputStream(); 4228 handled = true; 4229 break; 4230 } 4231 4232 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** 4233 case kWhatSubmitOutputMetaDataBufferIfEOS: 4234 { 4235 if (mCodec->mPortEOS[kPortIndexInput] && 4236 !mCodec->mPortEOS[kPortIndexOutput]) { 4237 status_t err = mCodec->submitOutputMetaDataBuffer(); 4238 if (err == OK) { 4239 mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround(); 4240 } 4241 } 4242 return true; 4243 } 4244 4245 default: 4246 handled = BaseState::onMessageReceived(msg); 4247 break; 4248 } 4249 4250 return handled; 4251} 4252 4253status_t ACodec::setParameters(const sp<AMessage> ¶ms) { 4254 int32_t videoBitrate; 4255 if (params->findInt32("video-bitrate", &videoBitrate)) { 4256 OMX_VIDEO_CONFIG_BITRATETYPE configParams; 4257 InitOMXParams(&configParams); 4258 configParams.nPortIndex = kPortIndexOutput; 4259 configParams.nEncodeBitrate = videoBitrate; 4260 4261 status_t err = mOMX->setConfig( 4262 mNode, 4263 OMX_IndexConfigVideoBitrate, 4264 &configParams, 4265 sizeof(configParams)); 4266 4267 if (err != OK) { 4268 ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d", 4269 videoBitrate, err); 4270 4271 return err; 4272 } 4273 } 4274 4275 int32_t dropInputFrames; 4276 if (params->findInt32("drop-input-frames", &dropInputFrames)) { 4277 bool suspend = dropInputFrames != 0; 4278 4279 status_t err = 4280 mOMX->setInternalOption( 4281 mNode, 4282 kPortIndexInput, 4283 IOMX::INTERNAL_OPTION_SUSPEND, 4284 &suspend, 4285 sizeof(suspend)); 4286 4287 if (err != OK) { 4288 ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err); 4289 return err; 4290 } 4291 } 4292 4293 int32_t dummy; 4294 if (params->findInt32("request-sync", &dummy)) { 4295 status_t err = requestIDRFrame(); 4296 4297 if (err != OK) { 4298 ALOGE("Requesting a sync frame failed w/ err %d", err); 4299 return err; 4300 } 4301 } 4302 4303 return OK; 4304} 4305 4306void ACodec::onSignalEndOfInputStream() { 4307 sp<AMessage> notify = mNotify->dup(); 4308 notify->setInt32("what", ACodec::kWhatSignaledInputEOS); 4309 4310 status_t err = mOMX->signalEndOfInputStream(mNode); 4311 if (err != OK) { 4312 notify->setInt32("err", err); 4313 } 4314 notify->post(); 4315} 4316 4317bool ACodec::ExecutingState::onOMXEvent( 4318 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 4319 switch (event) { 4320 case OMX_EventPortSettingsChanged: 4321 { 4322 CHECK_EQ(data1, (OMX_U32)kPortIndexOutput); 4323 4324 if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) { 4325 mCodec->mMetaDataBuffersToSubmit = 0; 4326 CHECK_EQ(mCodec->mOMX->sendCommand( 4327 mCodec->mNode, 4328 OMX_CommandPortDisable, kPortIndexOutput), 4329 (status_t)OK); 4330 4331 mCodec->freeOutputBuffersNotOwnedByComponent(); 4332 4333 mCodec->changeState(mCodec->mOutputPortSettingsChangedState); 4334 } else if (data2 == OMX_IndexConfigCommonOutputCrop) { 4335 mCodec->mSentFormat = false; 4336 } else { 4337 ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx", 4338 mCodec->mComponentName.c_str(), data2); 4339 } 4340 4341 return true; 4342 } 4343 4344 case OMX_EventBufferFlag: 4345 { 4346 return true; 4347 } 4348 4349 default: 4350 return BaseState::onOMXEvent(event, data1, data2); 4351 } 4352} 4353 4354//////////////////////////////////////////////////////////////////////////////// 4355 4356ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState( 4357 ACodec *codec) 4358 : BaseState(codec) { 4359} 4360 4361ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode( 4362 OMX_U32 portIndex) { 4363 if (portIndex == kPortIndexOutput) { 4364 return FREE_BUFFERS; 4365 } 4366 4367 CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput); 4368 4369 return RESUBMIT_BUFFERS; 4370} 4371 4372bool ACodec::OutputPortSettingsChangedState::onMessageReceived( 4373 const sp<AMessage> &msg) { 4374 bool handled = false; 4375 4376 switch (msg->what()) { 4377 case kWhatFlush: 4378 case kWhatShutdown: 4379 case kWhatResume: 4380 { 4381 if (msg->what() == kWhatResume) { 4382 ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str()); 4383 } 4384 4385 mCodec->deferMessage(msg); 4386 handled = true; 4387 break; 4388 } 4389 4390 default: 4391 handled = BaseState::onMessageReceived(msg); 4392 break; 4393 } 4394 4395 return handled; 4396} 4397 4398void ACodec::OutputPortSettingsChangedState::stateEntered() { 4399 ALOGV("[%s] Now handling output port settings change", 4400 mCodec->mComponentName.c_str()); 4401} 4402 4403bool ACodec::OutputPortSettingsChangedState::onOMXEvent( 4404 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 4405 switch (event) { 4406 case OMX_EventCmdComplete: 4407 { 4408 if (data1 == (OMX_U32)OMX_CommandPortDisable) { 4409 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput); 4410 4411 ALOGV("[%s] Output port now disabled.", 4412 mCodec->mComponentName.c_str()); 4413 4414 CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty()); 4415 mCodec->mDealer[kPortIndexOutput].clear(); 4416 4417 CHECK_EQ(mCodec->mOMX->sendCommand( 4418 mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput), 4419 (status_t)OK); 4420 4421 status_t err; 4422 if ((err = mCodec->allocateBuffersOnPort( 4423 kPortIndexOutput)) != OK) { 4424 ALOGE("Failed to allocate output port buffers after " 4425 "port reconfiguration (error 0x%08x)", 4426 err); 4427 4428 mCodec->signalError(OMX_ErrorUndefined, err); 4429 4430 // This is technically not correct, but appears to be 4431 // the only way to free the component instance. 4432 // Controlled transitioning from excecuting->idle 4433 // and idle->loaded seem impossible probably because 4434 // the output port never finishes re-enabling. 4435 mCodec->mShutdownInProgress = true; 4436 mCodec->mKeepComponentAllocated = false; 4437 mCodec->changeState(mCodec->mLoadedState); 4438 } 4439 4440 return true; 4441 } else if (data1 == (OMX_U32)OMX_CommandPortEnable) { 4442 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput); 4443 4444 mCodec->mSentFormat = false; 4445 4446 ALOGV("[%s] Output port now reenabled.", 4447 mCodec->mComponentName.c_str()); 4448 4449 if (mCodec->mExecutingState->active()) { 4450 mCodec->mExecutingState->submitOutputBuffers(); 4451 } 4452 4453 mCodec->changeState(mCodec->mExecutingState); 4454 4455 return true; 4456 } 4457 4458 return false; 4459 } 4460 4461 default: 4462 return false; 4463 } 4464} 4465 4466//////////////////////////////////////////////////////////////////////////////// 4467 4468ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec) 4469 : BaseState(codec), 4470 mComponentNowIdle(false) { 4471} 4472 4473bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) { 4474 bool handled = false; 4475 4476 switch (msg->what()) { 4477 case kWhatFlush: 4478 { 4479 // Don't send me a flush request if you previously wanted me 4480 // to shutdown. 4481 TRESPASS(); 4482 break; 4483 } 4484 4485 case kWhatShutdown: 4486 { 4487 // We're already doing that... 4488 4489 handled = true; 4490 break; 4491 } 4492 4493 default: 4494 handled = BaseState::onMessageReceived(msg); 4495 break; 4496 } 4497 4498 return handled; 4499} 4500 4501void ACodec::ExecutingToIdleState::stateEntered() { 4502 ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str()); 4503 4504 mComponentNowIdle = false; 4505 mCodec->mSentFormat = false; 4506} 4507 4508bool ACodec::ExecutingToIdleState::onOMXEvent( 4509 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 4510 switch (event) { 4511 case OMX_EventCmdComplete: 4512 { 4513 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 4514 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); 4515 4516 mComponentNowIdle = true; 4517 4518 changeStateIfWeOwnAllBuffers(); 4519 4520 return true; 4521 } 4522 4523 case OMX_EventPortSettingsChanged: 4524 case OMX_EventBufferFlag: 4525 { 4526 // We're shutting down and don't care about this anymore. 4527 return true; 4528 } 4529 4530 default: 4531 return BaseState::onOMXEvent(event, data1, data2); 4532 } 4533} 4534 4535void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() { 4536 if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) { 4537 CHECK_EQ(mCodec->mOMX->sendCommand( 4538 mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded), 4539 (status_t)OK); 4540 4541 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK); 4542 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK); 4543 4544 if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown) 4545 && mCodec->mNativeWindow != NULL) { 4546 // We push enough 1x1 blank buffers to ensure that one of 4547 // them has made it to the display. This allows the OMX 4548 // component teardown to zero out any protected buffers 4549 // without the risk of scanning out one of those buffers. 4550 mCodec->pushBlankBuffersToNativeWindow(); 4551 } 4552 4553 mCodec->changeState(mCodec->mIdleToLoadedState); 4554 } 4555} 4556 4557void ACodec::ExecutingToIdleState::onInputBufferFilled( 4558 const sp<AMessage> &msg) { 4559 BaseState::onInputBufferFilled(msg); 4560 4561 changeStateIfWeOwnAllBuffers(); 4562} 4563 4564void ACodec::ExecutingToIdleState::onOutputBufferDrained( 4565 const sp<AMessage> &msg) { 4566 BaseState::onOutputBufferDrained(msg); 4567 4568 changeStateIfWeOwnAllBuffers(); 4569} 4570 4571//////////////////////////////////////////////////////////////////////////////// 4572 4573ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec) 4574 : BaseState(codec) { 4575} 4576 4577bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) { 4578 bool handled = false; 4579 4580 switch (msg->what()) { 4581 case kWhatShutdown: 4582 { 4583 // We're already doing that... 4584 4585 handled = true; 4586 break; 4587 } 4588 4589 case kWhatFlush: 4590 { 4591 // Don't send me a flush request if you previously wanted me 4592 // to shutdown. 4593 TRESPASS(); 4594 break; 4595 } 4596 4597 default: 4598 handled = BaseState::onMessageReceived(msg); 4599 break; 4600 } 4601 4602 return handled; 4603} 4604 4605void ACodec::IdleToLoadedState::stateEntered() { 4606 ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str()); 4607} 4608 4609bool ACodec::IdleToLoadedState::onOMXEvent( 4610 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 4611 switch (event) { 4612 case OMX_EventCmdComplete: 4613 { 4614 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 4615 CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded); 4616 4617 mCodec->changeState(mCodec->mLoadedState); 4618 4619 return true; 4620 } 4621 4622 default: 4623 return BaseState::onOMXEvent(event, data1, data2); 4624 } 4625} 4626 4627//////////////////////////////////////////////////////////////////////////////// 4628 4629ACodec::FlushingState::FlushingState(ACodec *codec) 4630 : BaseState(codec) { 4631} 4632 4633void ACodec::FlushingState::stateEntered() { 4634 ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str()); 4635 4636 mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false; 4637} 4638 4639bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) { 4640 bool handled = false; 4641 4642 switch (msg->what()) { 4643 case kWhatShutdown: 4644 { 4645 mCodec->deferMessage(msg); 4646 break; 4647 } 4648 4649 case kWhatFlush: 4650 { 4651 // We're already doing this right now. 4652 handled = true; 4653 break; 4654 } 4655 4656 default: 4657 handled = BaseState::onMessageReceived(msg); 4658 break; 4659 } 4660 4661 return handled; 4662} 4663 4664bool ACodec::FlushingState::onOMXEvent( 4665 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 4666 ALOGV("[%s] FlushingState onOMXEvent(%d,%ld)", 4667 mCodec->mComponentName.c_str(), event, data1); 4668 4669 switch (event) { 4670 case OMX_EventCmdComplete: 4671 { 4672 CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush); 4673 4674 if (data2 == kPortIndexInput || data2 == kPortIndexOutput) { 4675 CHECK(!mFlushComplete[data2]); 4676 mFlushComplete[data2] = true; 4677 4678 if (mFlushComplete[kPortIndexInput] 4679 && mFlushComplete[kPortIndexOutput]) { 4680 changeStateIfWeOwnAllBuffers(); 4681 } 4682 } else { 4683 CHECK_EQ(data2, OMX_ALL); 4684 CHECK(mFlushComplete[kPortIndexInput]); 4685 CHECK(mFlushComplete[kPortIndexOutput]); 4686 4687 changeStateIfWeOwnAllBuffers(); 4688 } 4689 4690 return true; 4691 } 4692 4693 case OMX_EventPortSettingsChanged: 4694 { 4695 sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id()); 4696 msg->setInt32("type", omx_message::EVENT); 4697 msg->setPointer("node", mCodec->mNode); 4698 msg->setInt32("event", event); 4699 msg->setInt32("data1", data1); 4700 msg->setInt32("data2", data2); 4701 4702 ALOGV("[%s] Deferring OMX_EventPortSettingsChanged", 4703 mCodec->mComponentName.c_str()); 4704 4705 mCodec->deferMessage(msg); 4706 4707 return true; 4708 } 4709 4710 default: 4711 return BaseState::onOMXEvent(event, data1, data2); 4712 } 4713 4714 return true; 4715} 4716 4717void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) { 4718 BaseState::onOutputBufferDrained(msg); 4719 4720 changeStateIfWeOwnAllBuffers(); 4721} 4722 4723void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) { 4724 BaseState::onInputBufferFilled(msg); 4725 4726 changeStateIfWeOwnAllBuffers(); 4727} 4728 4729void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() { 4730 if (mFlushComplete[kPortIndexInput] 4731 && mFlushComplete[kPortIndexOutput] 4732 && mCodec->allYourBuffersAreBelongToUs()) { 4733 // We now own all buffers except possibly those still queued with 4734 // the native window for rendering. Let's get those back as well. 4735 mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs(); 4736 4737 sp<AMessage> notify = mCodec->mNotify->dup(); 4738 notify->setInt32("what", ACodec::kWhatFlushCompleted); 4739 notify->post(); 4740 4741 mCodec->mPortEOS[kPortIndexInput] = 4742 mCodec->mPortEOS[kPortIndexOutput] = false; 4743 4744 mCodec->mInputEOSResult = OK; 4745 4746 if (mCodec->mSkipCutBuffer != NULL) { 4747 mCodec->mSkipCutBuffer->clear(); 4748 } 4749 4750 mCodec->changeState(mCodec->mExecutingState); 4751 } 4752} 4753 4754} // namespace android 4755