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