ACodec.cpp revision 346de3c26a8fbd0fa0c8102f4a21ea4dcee4432a
1b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik/* 25ea1724be4d3b6039818f91fc087e1216c1463d5Chris Craik * Copyright (C) 2010 The Android Open Source Project 3b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * 4b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Licensed under the Apache License, Version 2.0 (the "License"); 5b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * you may not use this file except in compliance with the License. 6b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * You may obtain a copy of the License at 7b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * 8b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * http://www.apache.org/licenses/LICENSE-2.0 9b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * 10b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Unless required by applicable law or agreed to in writing, software 11b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * distributed under the License is distributed on an "AS IS" BASIS, 12b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * See the License for the specific language governing permissions and 14b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * limitations under the License. 15b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik */ 16b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 17f158b49c888f722194afe5a80539a2b020c130bcChris Craik//#define LOG_NDEBUG 0 18b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#define LOG_TAG "ACodec" 190b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 20161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik#ifdef __LP64__ 21766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu#define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS 2298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik#endif 23dccca44ffda4836b56a21da95a046c9708ffd49csergeyv 24161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik#include <inttypes.h> 25161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik#include <utils/Trace.h> 268ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 27b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <gui/Surface.h> 28d3daa3198e2212c985c634821682d5819346b653Chris Craik 29161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik#include <media/stagefright/ACodec.h> 30b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 31b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <binder/MemoryDealer.h> 32b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 33b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <media/stagefright/foundation/hexdump.h> 34f158b49c888f722194afe5a80539a2b020c130bcChris Craik#include <media/stagefright/foundation/ABuffer.h> 350b7e8245db728d127ada698be63d78b33fc6e4daChris Craik#include <media/stagefright/foundation/ADebug.h> 366e068c0182f6f85bccb855a647510724d1c65a13Chris Craik#include <media/stagefright/foundation/AMessage.h> 373a5811b50157e7ba50854caf957e806aee794d39Chris Craik#include <media/stagefright/foundation/AUtils.h> 386e068c0182f6f85bccb855a647510724d1c65a13Chris Craik 396e068c0182f6f85bccb855a647510724d1c65a13Chris Craik#include <media/stagefright/BufferProducerWrapper.h> 406246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik#include <media/stagefright/MediaCodec.h> 416246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik#include <media/stagefright/MediaCodecList.h> 42818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik#include <media/stagefright/MediaDefs.h> 436fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik#include <media/stagefright/OMXClient.h> 44f158b49c888f722194afe5a80539a2b020c130bcChris Craik#include <media/stagefright/OMXCodec.h> 4598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik#include <media/stagefright/PersistentSurface.h> 4698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik#include <media/stagefright/SurfaceUtils.h> 4798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik#include <media/hardware/HardwareAPI.h> 48f158b49c888f722194afe5a80539a2b020c130bcChris Craik 49f158b49c888f722194afe5a80539a2b020c130bcChris Craik#include <OMX_AudioExt.h> 5098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik#include <OMX_VideoExt.h> 51b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <OMX_Component.h> 52ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik#include <OMX_IndexExt.h> 536e068c0182f6f85bccb855a647510724d1c65a13Chris Craik#include <OMX_AsString.h> 540b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 550b7e8245db728d127ada698be63d78b33fc6e4daChris Craik#include "include/avc_utils.h" 56f158b49c888f722194afe5a80539a2b020c130bcChris Craik 570b7e8245db728d127ada698be63d78b33fc6e4daChris Craiknamespace android { 580b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 59e9c5fd888b1b33d6651bc640450b4f62e67c99f4Chris Craik// OMX errors are directly mapped into status_t range if 60e9c5fd888b1b33d6651bc640450b4f62e67c99f4Chris Craik// there is no corresponding MediaError status code. 61e9c5fd888b1b33d6651bc640450b4f62e67c99f4Chris Craik// Use the statusFromOMXError(int32_t omxError) function. 62e9c5fd888b1b33d6651bc640450b4f62e67c99f4Chris Craik// 63e9c5fd888b1b33d6651bc640450b4f62e67c99f4Chris Craik// Currently this is a direct map. 64e9c5fd888b1b33d6651bc640450b4f62e67c99f4Chris Craik// See frameworks/native/include/media/openmax/OMX_Core.h 650b7e8245db728d127ada698be63d78b33fc6e4daChris Craik// 66e9c5fd888b1b33d6651bc640450b4f62e67c99f4Chris Craik// Vendor OMX errors from 0x90000000 - 0x9000FFFF 67e9c5fd888b1b33d6651bc640450b4f62e67c99f4Chris Craik// Extension OMX errors from 0x8F000000 - 0x90000000 68e9c5fd888b1b33d6651bc640450b4f62e67c99f4Chris Craik// Standard OMX errors from 0x80001000 - 0x80001024 (0x80001024 current) 698ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik// 70e9c5fd888b1b33d6651bc640450b4f62e67c99f4Chris Craik 71e9c5fd888b1b33d6651bc640450b4f62e67c99f4Chris Craik// returns true if err is a recognized OMX error code. 720b7e8245db728d127ada698be63d78b33fc6e4daChris Craik// as OMX error is OMX_S32, this is an int32_t type 73e9c5fd888b1b33d6651bc640450b4f62e67c99f4Chris Craikstatic inline bool isOMXError(int32_t err) { 74e9c5fd888b1b33d6651bc640450b4f62e67c99f4Chris Craik return (ERROR_CODEC_MIN <= err && err <= ERROR_CODEC_MAX); 75e9c5fd888b1b33d6651bc640450b4f62e67c99f4Chris Craik} 76e9c5fd888b1b33d6651bc640450b4f62e67c99f4Chris Craik 770b7e8245db728d127ada698be63d78b33fc6e4daChris Craik// converts an OMX error to a status_t 780b7e8245db728d127ada698be63d78b33fc6e4daChris Craikstatic inline status_t statusFromOMXError(int32_t omxError) { 790b7e8245db728d127ada698be63d78b33fc6e4daChris Craik switch (omxError) { 80c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang case OMX_ErrorInvalidComponentName: 81c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang case OMX_ErrorComponentNotFound: 82c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang return NAME_NOT_FOUND; // can trigger illegal argument error for provided names. 83c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang default: 84c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang return isOMXError(omxError) ? omxError : 0; // no translation required 85c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang } 86c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang} 87c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang 88c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang// checks and converts status_t to a non-side-effect status_t 89c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhangstatic inline status_t makeNoSideEffectStatus(status_t err) { 90c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang switch (err) { 91c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang // the following errors have side effects and may come 92c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang // from other code modules. Remap for safety reasons. 93c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang case INVALID_OPERATION: 94c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang case DEAD_OBJECT: 95c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang return UNKNOWN_ERROR; 96c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang default: 97c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang return err; 98b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 99b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 1008d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 101eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malitatemplate<class T> 102c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhangstatic void InitOMXParams(T *params) { 103c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang params->nSize = sizeof(T); 104c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang params->nVersion.s.nVersionMajor = 1; 105c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang params->nVersion.s.nVersionMinor = 0; 106c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang params->nVersion.s.nRevision = 0; 107c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang params->nVersion.s.nStep = 0; 108c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang} 109c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang 110c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhangstruct MessageList : public RefBase { 111c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang MessageList() { 112c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang } 113c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang virtual ~MessageList() { 114c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang } 115c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang std::list<sp<AMessage> > &getList() { return mList; } 116c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhangprivate: 117c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang std::list<sp<AMessage> > mList; 118c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang 119c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang DISALLOW_EVIL_CONSTRUCTORS(MessageList); 120c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang}; 121c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang 122c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhangstruct CodecObserver : public BnOMXObserver { 123c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang CodecObserver() {} 124c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang 125c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang void setNotificationMessage(const sp<AMessage> &msg) { 126c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang mNotify = msg; 1270b7e8245db728d127ada698be63d78b33fc6e4daChris Craik } 1280b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 129c3bd56811268a074ffb9513bde0d940199e7ad16Chong Zhang // from IOMXObserver 130b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik virtual void onMessages(const std::list<omx_message> &messages) { 131b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (messages.empty()) { 132b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return; 133f158b49c888f722194afe5a80539a2b020c130bcChris Craik } 134818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik 135f158b49c888f722194afe5a80539a2b020c130bcChris Craik sp<AMessage> notify = mNotify->dup(); 136818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik bool first = true; 137f158b49c888f722194afe5a80539a2b020c130bcChris Craik sp<MessageList> msgList = new MessageList(); 1388ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik for (std::list<omx_message>::const_iterator it = messages.cbegin(); 1398ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik it != messages.cend(); ++it) { 1408ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik const omx_message &omx_msg = *it; 1418ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik if (first) { 1428ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik notify->setInt32("node", omx_msg.node); 1438ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik first = false; 1448ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 1458ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 1468ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik sp<AMessage> msg = new AMessage; 1478ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik msg->setInt32("type", omx_msg.type); 1488ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik switch (omx_msg.type) { 1498ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik case omx_message::EVENT: 1508ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik { 1518ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik msg->setInt32("event", omx_msg.u.event_data.event); 1528ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik msg->setInt32("data1", omx_msg.u.event_data.data1); 1538ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik msg->setInt32("data2", omx_msg.u.event_data.data2); 1548ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik break; 1558ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 1568ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 1578ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik case omx_message::EMPTY_BUFFER_DONE: 1588ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik { 1598ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik msg->setInt32("buffer", omx_msg.u.buffer_data.buffer); 1608ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik msg->setInt32("fence_fd", omx_msg.fenceFd); 1618ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik break; 1628ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 1638ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 1648ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik case omx_message::FILL_BUFFER_DONE: 1658ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik { 1668ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik msg->setInt32( 1678ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik "buffer", omx_msg.u.extended_buffer_data.buffer); 1688ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik msg->setInt32( 1698ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik "range_offset", 1708ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik omx_msg.u.extended_buffer_data.range_offset); 1718ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik msg->setInt32( 1728ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik "range_length", 1738ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik omx_msg.u.extended_buffer_data.range_length); 1748ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik msg->setInt32( 1758ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik "flags", 1768ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik omx_msg.u.extended_buffer_data.flags); 1778ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik msg->setInt64( 1788ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik "timestamp", 1798ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik omx_msg.u.extended_buffer_data.timestamp); 1808ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik msg->setInt32( 1818ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik "fence_fd", omx_msg.fenceFd); 1828ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik break; 1838ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 1848ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 1858ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik case omx_message::FRAME_RENDERED: 1868ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik { 1878ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik msg->setInt64( 1888ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik "media_time_us", omx_msg.u.render_data.timestamp); 1898ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik msg->setInt64( 1908ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik "system_nano", omx_msg.u.render_data.nanoTime); 1918ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik break; 1928ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 1938ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 1948ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik default: 1958ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik ALOGE("Unrecognized message type: %d", omx_msg.type); 1968ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik break; 1978ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 1988ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik msgList->getList().push_back(msg); 1998ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 2008ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik notify->setObject("messages", msgList); 2018ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik notify->post(); 2028ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 2038ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 2048ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craikprotected: 2058ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik virtual ~CodecObserver() {} 2068ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 2078913c8942fa15c2df6da747e42c5eda8454758ebChris Craikprivate: 2088913c8942fa15c2df6da747e42c5eda8454758ebChris Craik sp<AMessage> mNotify; 2098913c8942fa15c2df6da747e42c5eda8454758ebChris Craik 2107fc1b0349bc2ac8c880120dc5611f703faa7f06fChris Craik DISALLOW_EVIL_CONSTRUCTORS(CodecObserver); 2118ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik}; 2120b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 2130b7e8245db728d127ada698be63d78b33fc6e4daChris Craik//////////////////////////////////////////////////////////////////////////////// 2147df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck 2150b7e8245db728d127ada698be63d78b33fc6e4daChris Craikstruct ACodec::BaseState : public AState { 2160b7e8245db728d127ada698be63d78b33fc6e4daChris Craik BaseState(ACodec *codec, const sp<AState> &parentState = NULL); 2178ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 2180b7e8245db728d127ada698be63d78b33fc6e4daChris Craikprotected: 2190b7e8245db728d127ada698be63d78b33fc6e4daChris Craik enum PortMode { 2208ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik KEEP_BUFFERS, 2218ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik RESUBMIT_BUFFERS, 2228ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik FREE_BUFFERS, 2238ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }; 2248ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 2257df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck ACodec *mCodec; 2268ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 2278ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik virtual PortMode getPortMode(OMX_U32 portIndex); 228e4db79de127cfe961195f52907af8451026eaa20Chris Craik 2298ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik virtual bool onMessageReceived(const sp<AMessage> &msg); 2308d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 2317df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 2320b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 2338d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik virtual void onOutputBufferDrained(const sp<AMessage> &msg); 2340b7e8245db728d127ada698be63d78b33fc6e4daChris Craik virtual void onInputBufferFilled(const sp<AMessage> &msg); 2350b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 2360b7e8245db728d127ada698be63d78b33fc6e4daChris Craik void postFillThisBuffer(BufferInfo *info); 2370b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 238161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikprivate: 239161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik // Handles an OMX message. Returns true iff message was handled. 240161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik bool onOMXMessage(const sp<AMessage> &msg); 241161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 242161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik // Handles a list of messages. Returns true iff messages were handled. 243161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik bool onOMXMessageList(const sp<AMessage> &msg); 244161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 245161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik // returns true iff this message is for this component and the component is alive 246161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik bool checkOMXMessage(const sp<AMessage> &msg); 247161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 248161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID, int fenceFd); 249161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 250161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik bool onOMXFillBufferDone( 251161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik IOMX::buffer_id bufferID, 252161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik size_t rangeOffset, size_t rangeLength, 253161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik OMX_U32 flags, 254161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik int64_t timeUs, 255161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik int fenceFd); 256161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 257161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik virtual bool onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano); 258161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 259161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik void getMoreInputDataIfPossible(); 260161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 261161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik DISALLOW_EVIL_CONSTRUCTORS(BaseState); 262161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik}; 263161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 264161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik//////////////////////////////////////////////////////////////////////////////// 265161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 266161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikstruct ACodec::DeathNotifier : public IBinder::DeathRecipient { 267161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik DeathNotifier(const sp<AMessage> ¬ify) 268161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik : mNotify(notify) { 269161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik } 270161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 271161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik virtual void binderDied(const wp<IBinder> &) { 272f158b49c888f722194afe5a80539a2b020c130bcChris Craik mNotify->post(); 273161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik } 274161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 275161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikprotected: 276161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik virtual ~DeathNotifier() {} 277161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 278161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikprivate: 279161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik sp<AMessage> mNotify; 280161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 281161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik DISALLOW_EVIL_CONSTRUCTORS(DeathNotifier); 282161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik}; 283161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 284161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikstruct ACodec::UninitializedState : public ACodec::BaseState { 285161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik UninitializedState(ACodec *codec); 286161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 287161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikprotected: 288161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik virtual bool onMessageReceived(const sp<AMessage> &msg); 289161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik virtual void stateEntered(); 290161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 291161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikprivate: 292161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik void onSetup(const sp<AMessage> &msg); 293161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik bool onAllocateComponent(const sp<AMessage> &msg); 294161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 295161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik sp<DeathNotifier> mDeathNotifier; 296161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 297161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik DISALLOW_EVIL_CONSTRUCTORS(UninitializedState); 298161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik}; 299161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 300161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik//////////////////////////////////////////////////////////////////////////////// 301161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 302161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikstruct ACodec::LoadedState : public ACodec::BaseState { 303161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik LoadedState(ACodec *codec); 304161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 305161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikprotected: 306161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik virtual bool onMessageReceived(const sp<AMessage> &msg); 307161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik virtual void stateEntered(); 308161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 309161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikprivate: 310161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik friend struct ACodec::UninitializedState; 311161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 312161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik bool onConfigureComponent(const sp<AMessage> &msg); 313161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik void onCreateInputSurface(const sp<AMessage> &msg); 314161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik void onSetInputSurface(const sp<AMessage> &msg); 315161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik void onStart(); 316161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik void onShutdown(bool keepComponentAllocated); 317268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik 318161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik status_t setupInputSurface(); 319161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 320161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik DISALLOW_EVIL_CONSTRUCTORS(LoadedState); 321161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik}; 322f158b49c888f722194afe5a80539a2b020c130bcChris Craik 323d3daa3198e2212c985c634821682d5819346b653Chris Craik//////////////////////////////////////////////////////////////////////////////// 324d3daa3198e2212c985c634821682d5819346b653Chris Craik 325d3daa3198e2212c985c634821682d5819346b653Chris Craikstruct ACodec::LoadedToIdleState : public ACodec::BaseState { 326d3daa3198e2212c985c634821682d5819346b653Chris Craik LoadedToIdleState(ACodec *codec); 327d3daa3198e2212c985c634821682d5819346b653Chris Craik 328d3daa3198e2212c985c634821682d5819346b653Chris Craikprotected: 329d3daa3198e2212c985c634821682d5819346b653Chris Craik virtual bool onMessageReceived(const sp<AMessage> &msg); 330d3daa3198e2212c985c634821682d5819346b653Chris Craik virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 331d3daa3198e2212c985c634821682d5819346b653Chris Craik virtual void stateEntered(); 332d3daa3198e2212c985c634821682d5819346b653Chris Craik 333d3daa3198e2212c985c634821682d5819346b653Chris Craikprivate: 334d3daa3198e2212c985c634821682d5819346b653Chris Craik status_t allocateBuffers(); 335d3daa3198e2212c985c634821682d5819346b653Chris Craik 336d3daa3198e2212c985c634821682d5819346b653Chris Craik DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState); 337d3daa3198e2212c985c634821682d5819346b653Chris Craik}; 338d3daa3198e2212c985c634821682d5819346b653Chris Craik 339d3daa3198e2212c985c634821682d5819346b653Chris Craik//////////////////////////////////////////////////////////////////////////////// 340d3daa3198e2212c985c634821682d5819346b653Chris Craik 341d3daa3198e2212c985c634821682d5819346b653Chris Craikstruct ACodec::IdleToExecutingState : public ACodec::BaseState { 342d3daa3198e2212c985c634821682d5819346b653Chris Craik IdleToExecutingState(ACodec *codec); 343d3daa3198e2212c985c634821682d5819346b653Chris Craik 344d3daa3198e2212c985c634821682d5819346b653Chris Craikprotected: 345d3daa3198e2212c985c634821682d5819346b653Chris Craik virtual bool onMessageReceived(const sp<AMessage> &msg); 346d3daa3198e2212c985c634821682d5819346b653Chris Craik virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 347d3daa3198e2212c985c634821682d5819346b653Chris Craik virtual void stateEntered(); 348d3daa3198e2212c985c634821682d5819346b653Chris Craik 349d3daa3198e2212c985c634821682d5819346b653Chris Craikprivate: 350d3daa3198e2212c985c634821682d5819346b653Chris Craik DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState); 351d3daa3198e2212c985c634821682d5819346b653Chris Craik}; 352d3daa3198e2212c985c634821682d5819346b653Chris Craik 353d3daa3198e2212c985c634821682d5819346b653Chris Craik//////////////////////////////////////////////////////////////////////////////// 354d3daa3198e2212c985c634821682d5819346b653Chris Craik 355d3daa3198e2212c985c634821682d5819346b653Chris Craikstruct ACodec::ExecutingState : public ACodec::BaseState { 356d3daa3198e2212c985c634821682d5819346b653Chris Craik ExecutingState(ACodec *codec); 357d3daa3198e2212c985c634821682d5819346b653Chris Craik 358d3daa3198e2212c985c634821682d5819346b653Chris Craik void submitRegularOutputBuffers(); 359d3daa3198e2212c985c634821682d5819346b653Chris Craik void submitOutputMetaBuffers(); 360d3daa3198e2212c985c634821682d5819346b653Chris Craik void submitOutputBuffers(); 361d3daa3198e2212c985c634821682d5819346b653Chris Craik 362d3daa3198e2212c985c634821682d5819346b653Chris Craik // Submit output buffers to the decoder, submit input buffers to client 363d3daa3198e2212c985c634821682d5819346b653Chris Craik // to fill with data. 364d3daa3198e2212c985c634821682d5819346b653Chris Craik void resume(); 365d3daa3198e2212c985c634821682d5819346b653Chris Craik 366d3daa3198e2212c985c634821682d5819346b653Chris Craik // Returns true iff input and output buffers are in play. 367d3daa3198e2212c985c634821682d5819346b653Chris Craik bool active() const { return mActive; } 3686e068c0182f6f85bccb855a647510724d1c65a13Chris Craik 3696e068c0182f6f85bccb855a647510724d1c65a13Chris Craikprotected: 3706e068c0182f6f85bccb855a647510724d1c65a13Chris Craik virtual PortMode getPortMode(OMX_U32 portIndex); 3716e068c0182f6f85bccb855a647510724d1c65a13Chris Craik virtual bool onMessageReceived(const sp<AMessage> &msg); 3726e068c0182f6f85bccb855a647510724d1c65a13Chris Craik virtual void stateEntered(); 3736e068c0182f6f85bccb855a647510724d1c65a13Chris Craik 3743a5811b50157e7ba50854caf957e806aee794d39Chris Craik virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 3756e068c0182f6f85bccb855a647510724d1c65a13Chris Craik virtual bool onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano); 3766e068c0182f6f85bccb855a647510724d1c65a13Chris Craik 3776e068c0182f6f85bccb855a647510724d1c65a13Chris Craikprivate: 3786e068c0182f6f85bccb855a647510724d1c65a13Chris Craik bool mActive; 3796e068c0182f6f85bccb855a647510724d1c65a13Chris Craik 3806e068c0182f6f85bccb855a647510724d1c65a13Chris Craik DISALLOW_EVIL_CONSTRUCTORS(ExecutingState); 3816e068c0182f6f85bccb855a647510724d1c65a13Chris Craik}; 3826e068c0182f6f85bccb855a647510724d1c65a13Chris Craik 3836e068c0182f6f85bccb855a647510724d1c65a13Chris Craik//////////////////////////////////////////////////////////////////////////////// 3846e068c0182f6f85bccb855a647510724d1c65a13Chris Craik 3856e068c0182f6f85bccb855a647510724d1c65a13Chris Craikstruct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState { 3866e068c0182f6f85bccb855a647510724d1c65a13Chris Craik OutputPortSettingsChangedState(ACodec *codec); 3876e068c0182f6f85bccb855a647510724d1c65a13Chris Craik 388d3daa3198e2212c985c634821682d5819346b653Chris Craikprotected: 389161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik virtual PortMode getPortMode(OMX_U32 portIndex); 390d3daa3198e2212c985c634821682d5819346b653Chris Craik virtual bool onMessageReceived(const sp<AMessage> &msg); 391f158b49c888f722194afe5a80539a2b020c130bcChris Craik virtual void stateEntered(); 392eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita 393678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 3948d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik virtual bool onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano); 395678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 396678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craikprivate: 397678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState); 398678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik}; 399678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 400678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik//////////////////////////////////////////////////////////////////////////////// 401678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 402678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craikstruct ACodec::ExecutingToIdleState : public ACodec::BaseState { 403678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ExecutingToIdleState(ACodec *codec); 404678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 405678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craikprotected: 4068d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik virtual bool onMessageReceived(const sp<AMessage> &msg); 4078d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik virtual void stateEntered(); 4088d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 409a748c08241e43fc68c7c34767d819aef5183936eChris Craik virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 410678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 411a748c08241e43fc68c7c34767d819aef5183936eChris Craik virtual void onOutputBufferDrained(const sp<AMessage> &msg); 412a748c08241e43fc68c7c34767d819aef5183936eChris Craik virtual void onInputBufferFilled(const sp<AMessage> &msg); 413a748c08241e43fc68c7c34767d819aef5183936eChris Craik 414a748c08241e43fc68c7c34767d819aef5183936eChris Craikprivate: 415678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void changeStateIfWeOwnAllBuffers(); 416a748c08241e43fc68c7c34767d819aef5183936eChris Craik 417a748c08241e43fc68c7c34767d819aef5183936eChris Craik bool mComponentNowIdle; 418a748c08241e43fc68c7c34767d819aef5183936eChris Craik 419a748c08241e43fc68c7c34767d819aef5183936eChris Craik DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState); 420a748c08241e43fc68c7c34767d819aef5183936eChris Craik}; 421a748c08241e43fc68c7c34767d819aef5183936eChris Craik 422a748c08241e43fc68c7c34767d819aef5183936eChris Craik//////////////////////////////////////////////////////////////////////////////// 4238d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 4248d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craikstruct ACodec::IdleToLoadedState : public ACodec::BaseState { 4258d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik IdleToLoadedState(ACodec *codec); 4268d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 427b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikprotected: 428f158b49c888f722194afe5a80539a2b020c130bcChris Craik virtual bool onMessageReceived(const sp<AMessage> &msg); 429b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik virtual void stateEntered(); 4308d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 431f158b49c888f722194afe5a80539a2b020c130bcChris Craik virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 432b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 4336fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craikprivate: 434f158b49c888f722194afe5a80539a2b020c130bcChris Craik DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState); 435f158b49c888f722194afe5a80539a2b020c130bcChris Craik}; 436f158b49c888f722194afe5a80539a2b020c130bcChris Craik 4377cbf63da4f29e5a6b131796eb3b67fd9ff1521b8Chris Craik//////////////////////////////////////////////////////////////////////////////// 4388d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 4398d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craikstruct ACodec::FlushingState : public ACodec::BaseState { 4408d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik FlushingState(ACodec *codec); 441b36af87f8275f4b982906f88193ec27600f2746aChris Craik 442161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikprotected: 443161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik virtual bool onMessageReceived(const sp<AMessage> &msg); 444161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik virtual void stateEntered(); 445161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 446b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 447b36af87f8275f4b982906f88193ec27600f2746aChris Craik 448b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik virtual void onOutputBufferDrained(const sp<AMessage> &msg); 4498d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik virtual void onInputBufferFilled(const sp<AMessage> &msg); 4508d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 4518d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craikprivate: 4528d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik bool mFlushComplete[2]; 4538d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 4548d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik void changeStateIfWeOwnAllBuffers(); 455b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 456161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik DISALLOW_EVIL_CONSTRUCTORS(FlushingState); 457b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}; 458b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 459b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik//////////////////////////////////////////////////////////////////////////////// 460f158b49c888f722194afe5a80539a2b020c130bcChris Craik 461161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikvoid ACodec::BufferInfo::setWriteFence(int fenceFd, const char *dbg) { 462eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita if (mFenceFd >= 0) { 463b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik ALOGW("OVERWRITE OF %s fence %d by write fence %d in %s", 464e4db79de127cfe961195f52907af8451026eaa20Chris Craik mIsReadFence ? "read" : "write", mFenceFd, fenceFd, dbg); 465e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 466e4db79de127cfe961195f52907af8451026eaa20Chris Craik mFenceFd = fenceFd; 467b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mIsReadFence = false; 468b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 4690b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 4700b7e8245db728d127ada698be63d78b33fc6e4daChris Craikvoid ACodec::BufferInfo::setReadFence(int fenceFd, const char *dbg) { 4710b7e8245db728d127ada698be63d78b33fc6e4daChris Craik if (mFenceFd >= 0) { 4726fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik ALOGW("OVERWRITE OF %s fence %d by read fence %d in %s", 473b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mIsReadFence ? "read" : "write", mFenceFd, fenceFd, dbg); 474b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 475f158b49c888f722194afe5a80539a2b020c130bcChris Craik mFenceFd = fenceFd; 476161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik mIsReadFence = true; 477268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik} 478161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 479161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikvoid ACodec::BufferInfo::checkWriteFence(const char *dbg) { 480161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik if (mFenceFd >= 0 && mIsReadFence) { 481386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik ALOGD("REUSING read fence %d as write fence in %s", mFenceFd, dbg); 482386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik } 483386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik} 484386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 48580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craikvoid ACodec::BufferInfo::checkReadFence(const char *dbg) { 486386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik if (mFenceFd >= 0 && !mIsReadFence) { 487386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik ALOGD("REUSING write fence %d as read fence in %s", mFenceFd, dbg); 488386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik } 489e4db79de127cfe961195f52907af8451026eaa20Chris Craik} 4903a5811b50157e7ba50854caf957e806aee794d39Chris Craik 49180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik//////////////////////////////////////////////////////////////////////////////// 49280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 49380d2ade939153da87b3cd3b0a69a713bf68b64baChris CraikACodec::ACodec() 49480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik : mQuirks(0), 49580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik mNode(0), 496386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik mNativeWindowUsageBits(0), 4973a5811b50157e7ba50854caf957e806aee794d39Chris Craik mSentFormat(false), 498386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik mIsVideo(false), 499386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik mIsEncoder(false), 500386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik mFatalError(false), 501386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik mShutdownInProgress(false), 502386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik mExplicitShutdown(false), 503386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik mEncoderDelay(0), 504386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik mEncoderPadding(0), 505386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik mRotationDegrees(0), 506386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik mChannelMaskPresent(false), 507386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik mChannelMask(0), 508b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mDequeueCounter(0), 509b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mInputMetadataType(kMetadataBufferTypeInvalid), 510b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mOutputMetadataType(kMetadataBufferTypeInvalid), 511b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mLegacyAdaptiveExperiment(false), 512b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mMetadataBuffersToSubmit(0), 513f158b49c888f722194afe5a80539a2b020c130bcChris Craik mRepeatFrameDelayUs(-1ll), 514268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik mMaxPtsGapUs(-1ll), 515386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik mMaxFps(-1), 516386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik mTimePerFrameUs(-1ll), 517b87eadda1818034ce03d85f30388384d1ac65916Chris Craik mTimePerCaptureUs(-1ll), 518b87eadda1818034ce03d85f30388384d1ac65916Chris Craik mCreateInputBuffersSuspended(false), 519b87eadda1818034ce03d85f30388384d1ac65916Chris Craik mTunneled(false) { 520b87eadda1818034ce03d85f30388384d1ac65916Chris Craik mUninitializedState = new UninitializedState(this); 521b87eadda1818034ce03d85f30388384d1ac65916Chris Craik mLoadedState = new LoadedState(this); 522f158b49c888f722194afe5a80539a2b020c130bcChris Craik mLoadedToIdleState = new LoadedToIdleState(this); 52315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik mIdleToExecutingState = new IdleToExecutingState(this); 52415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik mExecutingState = new ExecutingState(this); 52580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 52615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik mOutputPortSettingsChangedState = 52715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik new OutputPortSettingsChangedState(this); 52815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 52915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik mExecutingToIdleState = new ExecutingToIdleState(this); 53015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik mIdleToLoadedState = new IdleToLoadedState(this); 53115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik mFlushingState = new FlushingState(this); 53215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 533b87eadda1818034ce03d85f30388384d1ac65916Chris Craik mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false; 534b87eadda1818034ce03d85f30388384d1ac65916Chris Craik mInputEOSResult = OK; 535b250a834e433b4f483e8d8362a6fda8d6594c7b8Chris Craik 53615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik changeState(mUninitializedState); 53715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik} 53815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 53915c3f19a445b8df575911a16e8a6dba755a084b5Chris CraikACodec::~ACodec() { 54015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik} 541b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 542b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid ACodec::setNotificationMessage(const sp<AMessage> &msg) { 543f158b49c888f722194afe5a80539a2b020c130bcChris Craik mNotify = msg; 544f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik} 545f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 546f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craikvoid ACodec::initiateSetup(const sp<AMessage> &msg) { 547f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik msg->setWhat(kWhatSetup); 548f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik msg->setTarget(this); 549f158b49c888f722194afe5a80539a2b020c130bcChris Craik msg->post(); 550f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik} 551f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 552f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craikvoid ACodec::signalSetParameters(const sp<AMessage> ¶ms) { 553f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik sp<AMessage> msg = new AMessage(kWhatSetParameters, this); 554f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik msg->setMessage("params", params); 555766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu msg->post(); 556766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu} 557766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 5587df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reckvoid ACodec::initiateAllocateComponent(const sp<AMessage> &msg) { 559766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu msg->setWhat(kWhatAllocateComponent); 560766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu msg->setTarget(this); 561766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu msg->post(); 562766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu} 563766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 564766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liuvoid ACodec::initiateConfigureComponent(const sp<AMessage> &msg) { 565766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu msg->setWhat(kWhatConfigureComponent); 566766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu msg->setTarget(this); 567f158b49c888f722194afe5a80539a2b020c130bcChris Craik msg->post(); 568268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik} 569268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik 570268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craikstatus_t ACodec::setSurface(const sp<Surface> &surface) { 571268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik sp<AMessage> msg = new AMessage(kWhatSetSurface, this); 572268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik msg->setObject("surface", surface); 573268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik 5747df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck sp<AMessage> response; 575268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik status_t err = msg->postAndAwaitResponse(&response); 576268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik 577e4db79de127cfe961195f52907af8451026eaa20Chris Craik if (err == OK) { 578268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik (void)response->findInt32("err", &err); 579268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik } 580268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik return err; 581268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik} 582a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik 583a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craikvoid ACodec::initiateCreateInputSurface() { 584a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik (new AMessage(kWhatCreateInputSurface, this))->post(); 585a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik} 586a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik 587a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craikvoid ACodec::initiateSetInputSurface( 588f158b49c888f722194afe5a80539a2b020c130bcChris Craik const sp<PersistentSurface> &surface) { 5894c3980b6e43cc7c0541f54b8e7e2d9d6108be622Chris Craik sp<AMessage> msg = new AMessage(kWhatSetInputSurface, this); 590e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik msg->setObject("input-surface", surface); 591d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik msg->post(); 592e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik} 593e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik 594f158b49c888f722194afe5a80539a2b020c130bcChris Craikvoid ACodec::signalEndOfInputStream() { 595386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik (new AMessage(kWhatSignalEndOfInputStream, this))->post(); 596268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik} 597386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 598386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craikvoid ACodec::initiateStart() { 599f158b49c888f722194afe5a80539a2b020c130bcChris Craik (new AMessage(kWhatStart, this))->post(); 600268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik} 601386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 602386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craikvoid ACodec::signalFlush() { 603f158b49c888f722194afe5a80539a2b020c130bcChris Craik ALOGV("[%s] signalFlush", mComponentName.c_str()); 604f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik (new AMessage(kWhatFlush, this))->post(); 605f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik} 606f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 607f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craikvoid ACodec::signalResume() { 608b87eadda1818034ce03d85f30388384d1ac65916Chris Craik (new AMessage(kWhatResume, this))->post(); 609b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 610b250a834e433b4f483e8d8362a6fda8d6594c7b8Chris Craik 611f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craikvoid ACodec::initiateShutdown(bool keepComponentAllocated) { 612f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik sp<AMessage> msg = new AMessage(kWhatShutdown, this); 613f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik msg->setInt32("keepComponentAllocated", keepComponentAllocated); 614f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik msg->post(); 615f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik if (!keepComponentAllocated) { 616f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik // ensure shutdown completes in 3 seconds 617f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik (new AMessage(kWhatReleaseCodecInstance, this))->post(3000000); 618f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik } 619f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik} 620f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 621f158b49c888f722194afe5a80539a2b020c130bcChris Craikvoid ACodec::signalRequestIDRFrame() { 6223a5811b50157e7ba50854caf957e806aee794d39Chris Craik (new AMessage(kWhatRequestIDRFrame, this))->post(); 6233a5811b50157e7ba50854caf957e806aee794d39Chris Craik} 6243a5811b50157e7ba50854caf957e806aee794d39Chris Craik 6253a5811b50157e7ba50854caf957e806aee794d39Chris Craik// *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** 626386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik// Some codecs may return input buffers before having them processed. 627386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik// This causes a halt if we already signaled an EOS on the input 628f158b49c888f722194afe5a80539a2b020c130bcChris Craik// port. For now keep submitting an output buffer if there was an 629386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik// EOS on the input port, but not yet on the output port. 630268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craikvoid ACodec::signalSubmitOutputMetadataBufferIfEOS_workaround() { 631268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik if (mPortEOS[kPortIndexInput] && !mPortEOS[kPortIndexOutput] && 632268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik mMetadataBuffersToSubmit > 0) { 633f158b49c888f722194afe5a80539a2b020c130bcChris Craik (new AMessage(kWhatSubmitOutputMetadataBufferIfEOS, this))->post(); 634268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik } 635a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik} 636a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 637f158b49c888f722194afe5a80539a2b020c130bcChris Craikstatus_t ACodec::handleSetSurface(const sp<Surface> &surface) { 6383a5811b50157e7ba50854caf957e806aee794d39Chris Craik // allow keeping unset surface 6393a5811b50157e7ba50854caf957e806aee794d39Chris Craik if (surface == NULL) { 6403a5811b50157e7ba50854caf957e806aee794d39Chris Craik if (mNativeWindow != NULL) { 6413a5811b50157e7ba50854caf957e806aee794d39Chris Craik ALOGW("cannot unset a surface"); 6423a5811b50157e7ba50854caf957e806aee794d39Chris Craik return INVALID_OPERATION; 6433a5811b50157e7ba50854caf957e806aee794d39Chris Craik } 644386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik return OK; 645386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik } 646f158b49c888f722194afe5a80539a2b020c130bcChris Craik 647268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik // cannot switch from bytebuffers to surface 648268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik if (mNativeWindow == NULL) { 6497df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck ALOGW("component was not configured with a surface"); 650268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik return INVALID_OPERATION; 651268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik } 652e4db79de127cfe961195f52907af8451026eaa20Chris Craik 653268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik ANativeWindow *nativeWindow = surface.get(); 654268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik // if we have not yet started the codec, we can simply set the native window 655b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (mBuffers[kPortIndexInput].size() == 0) { 656b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mNativeWindow = surface; 657f158b49c888f722194afe5a80539a2b020c130bcChris Craik return OK; 65815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 65915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 66015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // we do not support changing a tunneled surface after start 661b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (mTunneled) { 662b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik ALOGW("cannot change tunneled surface"); 663d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik return INVALID_OPERATION; 664d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik } 665d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik 666d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik int usageBits = 0; 667d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik status_t err = setupNativeWindowSizeFormatAndUsage(nativeWindow, &usageBits); 668f158b49c888f722194afe5a80539a2b020c130bcChris Craik if (err != OK) { 6697c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik return err; 6707c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik } 6717c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 67215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik int ignoredFlags = kVideoGrallocUsage; 673a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik // New output surface is not allowed to add new usage flag except ignored ones. 674d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik if ((usageBits & ~(mNativeWindowUsageBits | ignoredFlags)) != 0) { 67515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik ALOGW("cannot change usage from %#x to %#x", mNativeWindowUsageBits, usageBits); 676b87eadda1818034ce03d85f30388384d1ac65916Chris Craik return BAD_VALUE; 677b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 67815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 67915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // get min undequeued count. We cannot switch to a surface that has a higher 68015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // undequeued count than we allocated. 68115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik int minUndequeuedBuffers = 0; 68215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik err = nativeWindow->query( 6833a5811b50157e7ba50854caf957e806aee794d39Chris Craik nativeWindow, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, 6843a5811b50157e7ba50854caf957e806aee794d39Chris Craik &minUndequeuedBuffers); 6853a5811b50157e7ba50854caf957e806aee794d39Chris Craik if (err != 0) { 6863a5811b50157e7ba50854caf957e806aee794d39Chris Craik ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)", 6873a5811b50157e7ba50854caf957e806aee794d39Chris Craik strerror(-err), -err); 6883a5811b50157e7ba50854caf957e806aee794d39Chris Craik return err; 6893a5811b50157e7ba50854caf957e806aee794d39Chris Craik } 6903a5811b50157e7ba50854caf957e806aee794d39Chris Craik if (minUndequeuedBuffers > (int)mNumUndequeuedBuffers) { 6913a5811b50157e7ba50854caf957e806aee794d39Chris Craik ALOGE("new surface holds onto more buffers (%d) than planned for (%zu)", 6923a5811b50157e7ba50854caf957e806aee794d39Chris Craik minUndequeuedBuffers, mNumUndequeuedBuffers); 6933a5811b50157e7ba50854caf957e806aee794d39Chris Craik return BAD_VALUE; 6943a5811b50157e7ba50854caf957e806aee794d39Chris Craik } 6953a5811b50157e7ba50854caf957e806aee794d39Chris Craik 696a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik // we cannot change the number of output buffers while OMX is running 697a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik // set up surface to the same count 698f158b49c888f722194afe5a80539a2b020c130bcChris Craik Vector<BufferInfo> &buffers = mBuffers[kPortIndexOutput]; 6994c3980b6e43cc7c0541f54b8e7e2d9d6108be622Chris Craik ALOGV("setting up surface for %zu buffers", buffers.size()); 700d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik 701d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik err = native_window_set_buffer_count(nativeWindow, buffers.size()); 7023a5811b50157e7ba50854caf957e806aee794d39Chris Craik if (err != 0) { 7033a5811b50157e7ba50854caf957e806aee794d39Chris Craik ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), 7043a5811b50157e7ba50854caf957e806aee794d39Chris Craik -err); 705d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik return err; 706d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik } 707f158b49c888f722194afe5a80539a2b020c130bcChris Craik 708417ed6d4337e5409d52f58cc93677c8715193f32John Reck // need to enable allocation when attaching 709aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik surface->getIGraphicBufferProducer()->allowAllocation(true); 710aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 711aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik // for meta data mode, we move dequeud buffers to the new surface. 712aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik // for non-meta mode, we must move all registered buffers 713aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik for (size_t i = 0; i < buffers.size(); ++i) { 714aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik const BufferInfo &info = buffers[i]; 715aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik // skip undequeued buffers for meta data mode 716aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik if (storingMetadataInDecodedBuffers() 717aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik && !mLegacyAdaptiveExperiment 718aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik && info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 719aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik ALOGV("skipping buffer %p", info.mGraphicBuffer->getNativeBuffer()); 720d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik continue; 721d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik } 722d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik ALOGV("attaching buffer %p", info.mGraphicBuffer->getNativeBuffer()); 723d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 724f158b49c888f722194afe5a80539a2b020c130bcChris Craik err = surface->attachBuffer(info.mGraphicBuffer->getNativeBuffer()); 7258ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik if (err != OK) { 7268ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik ALOGE("failed to attach buffer %p to the new surface: %s (%d)", 7278ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik info.mGraphicBuffer->getNativeBuffer(), 7280b7e8245db728d127ada698be63d78b33fc6e4daChris Craik strerror(-err), -err); 729eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita return err; 730818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik } 7316fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 73298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 7338ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // cancel undequeued buffers to new surface 7348ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik if (!storingMetadataInDecodedBuffers() || mLegacyAdaptiveExperiment) { 7358ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik for (size_t i = 0; i < buffers.size(); ++i) { 7368ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik BufferInfo &info = buffers.editItemAt(i); 73798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 7388ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik ALOGV("canceling buffer %p", info.mGraphicBuffer->getNativeBuffer()); 739f158b49c888f722194afe5a80539a2b020c130bcChris Craik err = nativeWindow->cancelBuffer( 740f158b49c888f722194afe5a80539a2b020c130bcChris Craik nativeWindow, info.mGraphicBuffer->getNativeBuffer(), info.mFenceFd); 74184ad6149db0e1dc98ed3778ee4fc2ab685765d9aChris Craik info.mFenceFd = -1; 742f158b49c888f722194afe5a80539a2b020c130bcChris Craik if (err != OK) { 743b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik ALOGE("failed to cancel buffer %p to the new surface: %s (%d)", 744b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik info.mGraphicBuffer->getNativeBuffer(), 745f158b49c888f722194afe5a80539a2b020c130bcChris Craik strerror(-err), -err); 7460b7e8245db728d127ada698be63d78b33fc6e4daChris Craik return err; 7476fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 7480b7e8245db728d127ada698be63d78b33fc6e4daChris Craik } 7490b7e8245db728d127ada698be63d78b33fc6e4daChris Craik } 750b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // disallow further allocation 751b87eadda1818034ce03d85f30388384d1ac65916Chris Craik (void)surface->getIGraphicBufferProducer()->allowAllocation(false); 752b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 753f158b49c888f722194afe5a80539a2b020c130bcChris Craik 7548ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // push blank buffers to previous window if requested 7558ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik if (mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown) { 7568ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik pushBlankBuffersToNativeWindow(mNativeWindow.get()); 7578ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 7588ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 7598ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mNativeWindow = nativeWindow; 7608ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mNativeWindowUsageBits = usageBits; 7618ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik return OK; 762b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 7638ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 7648ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craikstatus_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) { 7658ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 7668ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 7678ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik CHECK(mDealer[portIndex] == NULL); 7688ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik CHECK(mBuffers[portIndex].isEmpty()); 7698ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 7708ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik status_t err; 7718ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik if (mNativeWindow != NULL && portIndex == kPortIndexOutput) { 7728ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik if (storingMetadataInDecodedBuffers()) { 7738ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik err = allocateOutputMetadataBuffers(); 7748ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } else { 7758ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik err = allocateOutputBuffersFromNativeWindow(); 7768ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 7778ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } else { 7788ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik OMX_PARAM_PORTDEFINITIONTYPE def; 7798ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik InitOMXParams(&def); 7808ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik def.nPortIndex = portIndex; 7818ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 7828ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik err = mOMX->getParameter( 7838ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 7848ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 7858ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik if (err == OK) { 7868ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik MetadataBufferType type = 7878ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik portIndex == kPortIndexOutput ? mOutputMetadataType : mInputMetadataType; 7888ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik int32_t bufSize = def.nBufferSize; 7898ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik if (type == kMetadataBufferTypeGrallocSource) { 7908ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik bufSize = sizeof(VideoGrallocMetadata); 7918ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } else if (type == kMetadataBufferTypeANWBuffer) { 7928ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik bufSize = sizeof(VideoNativeMetadata); 7938ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 7948ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 7958ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // If using gralloc or native source input metadata buffers, allocate largest 7960b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // metadata size as we prefer to generate native source metadata, but component 7976fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // may require gralloc source. For camera source, allocate at least enough 798f158b49c888f722194afe5a80539a2b020c130bcChris Craik // size for native metadata buffers. 7990b7e8245db728d127ada698be63d78b33fc6e4daChris Craik int32_t allottedSize = bufSize; 8006fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik if (portIndex == kPortIndexInput && type >= kMetadataBufferTypeGrallocSource) { 8010b7e8245db728d127ada698be63d78b33fc6e4daChris Craik bufSize = max(sizeof(VideoGrallocMetadata), sizeof(VideoNativeMetadata)); 8020b7e8245db728d127ada698be63d78b33fc6e4daChris Craik } else if (portIndex == kPortIndexInput && type == kMetadataBufferTypeCameraSource) { 8036fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik bufSize = max(bufSize, (int32_t)sizeof(VideoNativeMetadata)); 8046fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 8056fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 8067df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck ALOGV("[%s] Allocating %u buffers of size %d/%d (from %u using %s) on %s port", 8076fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik mComponentName.c_str(), 8086fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik def.nBufferCountActual, bufSize, allottedSize, def.nBufferSize, asString(type), 809e4db79de127cfe961195f52907af8451026eaa20Chris Craik portIndex == kPortIndexInput ? "input" : "output"); 810818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik 811f158b49c888f722194afe5a80539a2b020c130bcChris Craik size_t totalSize = def.nBufferCountActual * bufSize; 8126fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec"); 8136fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 8146fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik for (OMX_U32 i = 0; i < def.nBufferCountActual && err == OK; ++i) { 8156fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik sp<IMemory> mem = mDealer[portIndex]->allocate(bufSize); 8166fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik if (mem == NULL || mem->pointer() == NULL) { 8176fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik return NO_MEMORY; 8186fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 819b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 820b87eadda1818034ce03d85f30388384d1ac65916Chris Craik BufferInfo info; 821f158b49c888f722194afe5a80539a2b020c130bcChris Craik info.mStatus = BufferInfo::OWNED_BY_US; 8226fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik info.mFenceFd = -1; 823b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik info.mRenderInfo = NULL; 824b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 825b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik uint32_t requiresAllocateBufferBit = 826f158b49c888f722194afe5a80539a2b020c130bcChris Craik (portIndex == kPortIndexInput) 827b87eadda1818034ce03d85f30388384d1ac65916Chris Craik ? OMXCodec::kRequiresAllocateBufferOnInputPorts 828b87eadda1818034ce03d85f30388384d1ac65916Chris Craik : OMXCodec::kRequiresAllocateBufferOnOutputPorts; 829b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 830b87eadda1818034ce03d85f30388384d1ac65916Chris Craik if ((portIndex == kPortIndexInput && (mFlags & kFlagIsSecure)) 831b87eadda1818034ce03d85f30388384d1ac65916Chris Craik || (portIndex == kPortIndexOutput && usingMetadataOnEncoderOutput())) { 832b87eadda1818034ce03d85f30388384d1ac65916Chris Craik mem.clear(); 833b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 8344876de16e34622634266d09522c9153c78c7c2fbChris Craik void *ptr; 8354876de16e34622634266d09522c9153c78c7c2fbChris Craik err = mOMX->allocateBuffer( 8364876de16e34622634266d09522c9153c78c7c2fbChris Craik mNode, portIndex, bufSize, &info.mBufferID, 8374876de16e34622634266d09522c9153c78c7c2fbChris Craik &ptr); 8384876de16e34622634266d09522c9153c78c7c2fbChris Craik 8394876de16e34622634266d09522c9153c78c7c2fbChris Craik info.mData = new ABuffer(ptr, bufSize); 8404876de16e34622634266d09522c9153c78c7c2fbChris Craik } else if (mQuirks & requiresAllocateBufferBit) { 8414876de16e34622634266d09522c9153c78c7c2fbChris Craik err = mOMX->allocateBufferWithBackup( 8424876de16e34622634266d09522c9153c78c7c2fbChris Craik mNode, portIndex, mem, &info.mBufferID, allottedSize); 8434876de16e34622634266d09522c9153c78c7c2fbChris Craik } else { 8444876de16e34622634266d09522c9153c78c7c2fbChris Craik err = mOMX->useBuffer(mNode, portIndex, mem, &info.mBufferID, allottedSize); 8454876de16e34622634266d09522c9153c78c7c2fbChris Craik } 8464876de16e34622634266d09522c9153c78c7c2fbChris Craik 8474876de16e34622634266d09522c9153c78c7c2fbChris Craik if (mem != NULL) { 8484876de16e34622634266d09522c9153c78c7c2fbChris Craik info.mData = new ABuffer(mem->pointer(), bufSize); 8494876de16e34622634266d09522c9153c78c7c2fbChris Craik if (type == kMetadataBufferTypeANWBuffer) { 8504876de16e34622634266d09522c9153c78c7c2fbChris Craik ((VideoNativeMetadata *)mem->pointer())->nFenceFd = -1; 8514876de16e34622634266d09522c9153c78c7c2fbChris Craik } 8524876de16e34622634266d09522c9153c78c7c2fbChris Craik } 8534876de16e34622634266d09522c9153c78c7c2fbChris Craik 8544876de16e34622634266d09522c9153c78c7c2fbChris Craik mBuffers[portIndex].push(info); 8554876de16e34622634266d09522c9153c78c7c2fbChris Craik } 8564876de16e34622634266d09522c9153c78c7c2fbChris Craik } 8574876de16e34622634266d09522c9153c78c7c2fbChris Craik } 8584876de16e34622634266d09522c9153c78c7c2fbChris Craik 8594876de16e34622634266d09522c9153c78c7c2fbChris Craik if (err != OK) { 8604876de16e34622634266d09522c9153c78c7c2fbChris Craik return err; 8614876de16e34622634266d09522c9153c78c7c2fbChris Craik } 8624876de16e34622634266d09522c9153c78c7c2fbChris Craik 8634876de16e34622634266d09522c9153c78c7c2fbChris Craik sp<AMessage> notify = mNotify->dup(); 864b87eadda1818034ce03d85f30388384d1ac65916Chris Craik notify->setInt32("what", CodecBase::kWhatBuffersAllocated); 865b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 866f158b49c888f722194afe5a80539a2b020c130bcChris Craik notify->setInt32("portIndex", portIndex); 867b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 868b87eadda1818034ce03d85f30388384d1ac65916Chris Craik sp<PortDescription> desc = new PortDescription; 869b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 870b87eadda1818034ce03d85f30388384d1ac65916Chris Craik for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 8714876de16e34622634266d09522c9153c78c7c2fbChris Craik const BufferInfo &info = mBuffers[portIndex][i]; 8724876de16e34622634266d09522c9153c78c7c2fbChris Craik 8734876de16e34622634266d09522c9153c78c7c2fbChris Craik desc->addBuffer(info.mBufferID, info.mData); 874b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 875b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 8763a5811b50157e7ba50854caf957e806aee794d39Chris Craik notify->setObject("portDesc", desc); 8773a5811b50157e7ba50854caf957e806aee794d39Chris Craik notify->post(); 8783a5811b50157e7ba50854caf957e806aee794d39Chris Craik 8793a5811b50157e7ba50854caf957e806aee794d39Chris Craik return OK; 880b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 881b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 882status_t ACodec::setupNativeWindowSizeFormatAndUsage( 883 ANativeWindow *nativeWindow /* nonnull */, int *finalUsage /* nonnull */) { 884 OMX_PARAM_PORTDEFINITIONTYPE def; 885 InitOMXParams(&def); 886 def.nPortIndex = kPortIndexOutput; 887 888 status_t err = mOMX->getParameter( 889 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 890 891 if (err != OK) { 892 return err; 893 } 894 895 OMX_U32 usage = 0; 896 err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage); 897 if (err != 0) { 898 ALOGW("querying usage flags from OMX IL component failed: %d", err); 899 // XXX: Currently this error is logged, but not fatal. 900 usage = 0; 901 } 902 int omxUsage = usage; 903 904 if (mFlags & kFlagIsGrallocUsageProtected) { 905 usage |= GRALLOC_USAGE_PROTECTED; 906 } 907 908 usage |= kVideoGrallocUsage; 909 *finalUsage = usage; 910 911 ALOGV("gralloc usage: %#x(OMX) => %#x(ACodec)", omxUsage, usage); 912 return setNativeWindowSizeFormatAndUsage( 913 nativeWindow, 914 def.format.video.nFrameWidth, 915 def.format.video.nFrameHeight, 916 def.format.video.eColorFormat, 917 mRotationDegrees, 918 usage); 919} 920 921status_t ACodec::configureOutputBuffersFromNativeWindow( 922 OMX_U32 *bufferCount, OMX_U32 *bufferSize, 923 OMX_U32 *minUndequeuedBuffers) { 924 OMX_PARAM_PORTDEFINITIONTYPE def; 925 InitOMXParams(&def); 926 def.nPortIndex = kPortIndexOutput; 927 928 status_t err = mOMX->getParameter( 929 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 930 931 if (err == OK) { 932 err = setupNativeWindowSizeFormatAndUsage(mNativeWindow.get(), &mNativeWindowUsageBits); 933 } 934 if (err != OK) { 935 mNativeWindowUsageBits = 0; 936 return err; 937 } 938 939 // Exits here for tunneled video playback codecs -- i.e. skips native window 940 // buffer allocation step as this is managed by the tunneled OMX omponent 941 // itself and explicitly sets def.nBufferCountActual to 0. 942 if (mTunneled) { 943 ALOGV("Tunneled Playback: skipping native window buffer allocation."); 944 def.nBufferCountActual = 0; 945 err = mOMX->setParameter( 946 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 947 948 *minUndequeuedBuffers = 0; 949 *bufferCount = 0; 950 *bufferSize = 0; 951 return err; 952 } 953 954 *minUndequeuedBuffers = 0; 955 err = mNativeWindow->query( 956 mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, 957 (int *)minUndequeuedBuffers); 958 959 if (err != 0) { 960 ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)", 961 strerror(-err), -err); 962 return err; 963 } 964 965 // FIXME: assume that surface is controlled by app (native window 966 // returns the number for the case when surface is not controlled by app) 967 // FIXME2: This means that minUndeqeueudBufs can be 1 larger than reported 968 // For now, try to allocate 1 more buffer, but don't fail if unsuccessful 969 970 // Use conservative allocation while also trying to reduce starvation 971 // 972 // 1. allocate at least nBufferCountMin + minUndequeuedBuffers - that is the 973 // minimum needed for the consumer to be able to work 974 // 2. try to allocate two (2) additional buffers to reduce starvation from 975 // the consumer 976 // plus an extra buffer to account for incorrect minUndequeuedBufs 977 for (OMX_U32 extraBuffers = 2 + 1; /* condition inside loop */; extraBuffers--) { 978 OMX_U32 newBufferCount = 979 def.nBufferCountMin + *minUndequeuedBuffers + extraBuffers; 980 def.nBufferCountActual = newBufferCount; 981 err = mOMX->setParameter( 982 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 983 984 if (err == OK) { 985 *minUndequeuedBuffers += extraBuffers; 986 break; 987 } 988 989 ALOGW("[%s] setting nBufferCountActual to %u failed: %d", 990 mComponentName.c_str(), newBufferCount, err); 991 /* exit condition */ 992 if (extraBuffers == 0) { 993 return err; 994 } 995 } 996 997 err = native_window_set_buffer_count( 998 mNativeWindow.get(), def.nBufferCountActual); 999 1000 if (err != 0) { 1001 ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), 1002 -err); 1003 return err; 1004 } 1005 1006 *bufferCount = def.nBufferCountActual; 1007 *bufferSize = def.nBufferSize; 1008 return err; 1009} 1010 1011status_t ACodec::allocateOutputBuffersFromNativeWindow() { 1012 OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers; 1013 status_t err = configureOutputBuffersFromNativeWindow( 1014 &bufferCount, &bufferSize, &minUndequeuedBuffers); 1015 if (err != 0) 1016 return err; 1017 mNumUndequeuedBuffers = minUndequeuedBuffers; 1018 1019 if (!storingMetadataInDecodedBuffers()) { 1020 static_cast<Surface*>(mNativeWindow.get()) 1021 ->getIGraphicBufferProducer()->allowAllocation(true); 1022 } 1023 1024 ALOGV("[%s] Allocating %u buffers from a native window of size %u on " 1025 "output port", 1026 mComponentName.c_str(), bufferCount, bufferSize); 1027 1028 // Dequeue buffers and send them to OMX 1029 for (OMX_U32 i = 0; i < bufferCount; i++) { 1030 ANativeWindowBuffer *buf; 1031 int fenceFd; 1032 err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf, &fenceFd); 1033 if (err != 0) { 1034 ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err); 1035 break; 1036 } 1037 1038 sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false)); 1039 BufferInfo info; 1040 info.mStatus = BufferInfo::OWNED_BY_US; 1041 info.mFenceFd = fenceFd; 1042 info.mIsReadFence = false; 1043 info.mRenderInfo = NULL; 1044 info.mData = new ABuffer(NULL /* data */, bufferSize /* capacity */); 1045 info.mGraphicBuffer = graphicBuffer; 1046 mBuffers[kPortIndexOutput].push(info); 1047 1048 IOMX::buffer_id bufferId; 1049 err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer, 1050 &bufferId); 1051 if (err != 0) { 1052 ALOGE("registering GraphicBuffer %u with OMX IL component failed: " 1053 "%d", i, err); 1054 break; 1055 } 1056 1057 mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId; 1058 1059 ALOGV("[%s] Registered graphic buffer with ID %u (pointer = %p)", 1060 mComponentName.c_str(), 1061 bufferId, graphicBuffer.get()); 1062 } 1063 1064 OMX_U32 cancelStart; 1065 OMX_U32 cancelEnd; 1066 1067 if (err != 0) { 1068 // If an error occurred while dequeuing we need to cancel any buffers 1069 // that were dequeued. 1070 cancelStart = 0; 1071 cancelEnd = mBuffers[kPortIndexOutput].size(); 1072 } else { 1073 // Return the required minimum undequeued buffers to the native window. 1074 cancelStart = bufferCount - minUndequeuedBuffers; 1075 cancelEnd = bufferCount; 1076 } 1077 1078 for (OMX_U32 i = cancelStart; i < cancelEnd; i++) { 1079 BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i); 1080 if (info->mStatus == BufferInfo::OWNED_BY_US) { 1081 status_t error = cancelBufferToNativeWindow(info); 1082 if (err == 0) { 1083 err = error; 1084 } 1085 } 1086 } 1087 1088 if (!storingMetadataInDecodedBuffers()) { 1089 static_cast<Surface*>(mNativeWindow.get()) 1090 ->getIGraphicBufferProducer()->allowAllocation(false); 1091 } 1092 1093 return err; 1094} 1095 1096status_t ACodec::allocateOutputMetadataBuffers() { 1097 OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers; 1098 status_t err = configureOutputBuffersFromNativeWindow( 1099 &bufferCount, &bufferSize, &minUndequeuedBuffers); 1100 if (err != 0) 1101 return err; 1102 mNumUndequeuedBuffers = minUndequeuedBuffers; 1103 1104 ALOGV("[%s] Allocating %u meta buffers on output port", 1105 mComponentName.c_str(), bufferCount); 1106 1107 size_t bufSize = mOutputMetadataType == kMetadataBufferTypeANWBuffer ? 1108 sizeof(struct VideoNativeMetadata) : sizeof(struct VideoGrallocMetadata); 1109 size_t totalSize = bufferCount * bufSize; 1110 mDealer[kPortIndexOutput] = new MemoryDealer(totalSize, "ACodec"); 1111 1112 // Dequeue buffers and send them to OMX 1113 for (OMX_U32 i = 0; i < bufferCount; i++) { 1114 BufferInfo info; 1115 info.mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 1116 info.mFenceFd = -1; 1117 info.mRenderInfo = NULL; 1118 info.mGraphicBuffer = NULL; 1119 info.mDequeuedAt = mDequeueCounter; 1120 1121 sp<IMemory> mem = mDealer[kPortIndexOutput]->allocate(bufSize); 1122 if (mem == NULL || mem->pointer() == NULL) { 1123 return NO_MEMORY; 1124 } 1125 if (mOutputMetadataType == kMetadataBufferTypeANWBuffer) { 1126 ((VideoNativeMetadata *)mem->pointer())->nFenceFd = -1; 1127 } 1128 info.mData = new ABuffer(mem->pointer(), mem->size()); 1129 1130 // we use useBuffer for metadata regardless of quirks 1131 err = mOMX->useBuffer( 1132 mNode, kPortIndexOutput, mem, &info.mBufferID, mem->size()); 1133 1134 mBuffers[kPortIndexOutput].push(info); 1135 1136 ALOGV("[%s] allocated meta buffer with ID %u (pointer = %p)", 1137 mComponentName.c_str(), info.mBufferID, mem->pointer()); 1138 } 1139 1140 if (mLegacyAdaptiveExperiment) { 1141 // preallocate and preregister buffers 1142 static_cast<Surface *>(mNativeWindow.get()) 1143 ->getIGraphicBufferProducer()->allowAllocation(true); 1144 1145 ALOGV("[%s] Allocating %u buffers from a native window of size %u on " 1146 "output port", 1147 mComponentName.c_str(), bufferCount, bufferSize); 1148 1149 // Dequeue buffers then cancel them all 1150 for (OMX_U32 i = 0; i < bufferCount; i++) { 1151 BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i); 1152 1153 ANativeWindowBuffer *buf; 1154 int fenceFd; 1155 err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf, &fenceFd); 1156 if (err != 0) { 1157 ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err); 1158 break; 1159 } 1160 1161 sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false)); 1162 mOMX->updateGraphicBufferInMeta( 1163 mNode, kPortIndexOutput, graphicBuffer, info->mBufferID); 1164 info->mStatus = BufferInfo::OWNED_BY_US; 1165 info->setWriteFence(fenceFd, "allocateOutputMetadataBuffers for legacy"); 1166 info->mGraphicBuffer = graphicBuffer; 1167 } 1168 1169 for (OMX_U32 i = 0; i < mBuffers[kPortIndexOutput].size(); i++) { 1170 BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i); 1171 if (info->mStatus == BufferInfo::OWNED_BY_US) { 1172 status_t error = cancelBufferToNativeWindow(info); 1173 if (err == OK) { 1174 err = error; 1175 } 1176 } 1177 } 1178 1179 static_cast<Surface*>(mNativeWindow.get()) 1180 ->getIGraphicBufferProducer()->allowAllocation(false); 1181 } 1182 1183 mMetadataBuffersToSubmit = bufferCount - minUndequeuedBuffers; 1184 return err; 1185} 1186 1187status_t ACodec::submitOutputMetadataBuffer() { 1188 CHECK(storingMetadataInDecodedBuffers()); 1189 if (mMetadataBuffersToSubmit == 0) 1190 return OK; 1191 1192 BufferInfo *info = dequeueBufferFromNativeWindow(); 1193 if (info == NULL) { 1194 return ERROR_IO; 1195 } 1196 1197 ALOGV("[%s] submitting output meta buffer ID %u for graphic buffer %p", 1198 mComponentName.c_str(), info->mBufferID, info->mGraphicBuffer.get()); 1199 1200 --mMetadataBuffersToSubmit; 1201 info->checkWriteFence("submitOutputMetadataBuffer"); 1202 status_t err = mOMX->fillBuffer(mNode, info->mBufferID, info->mFenceFd); 1203 info->mFenceFd = -1; 1204 if (err == OK) { 1205 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 1206 } 1207 1208 return err; 1209} 1210 1211status_t ACodec::waitForFence(int fd, const char *dbg ) { 1212 status_t res = OK; 1213 if (fd >= 0) { 1214 sp<Fence> fence = new Fence(fd); 1215 res = fence->wait(IOMX::kFenceTimeoutMs); 1216 ALOGW_IF(res != OK, "FENCE TIMEOUT for %d in %s", fd, dbg); 1217 } 1218 return res; 1219} 1220 1221// static 1222const char *ACodec::_asString(BufferInfo::Status s) { 1223 switch (s) { 1224 case BufferInfo::OWNED_BY_US: return "OUR"; 1225 case BufferInfo::OWNED_BY_COMPONENT: return "COMPONENT"; 1226 case BufferInfo::OWNED_BY_UPSTREAM: return "UPSTREAM"; 1227 case BufferInfo::OWNED_BY_DOWNSTREAM: return "DOWNSTREAM"; 1228 case BufferInfo::OWNED_BY_NATIVE_WINDOW: return "SURFACE"; 1229 case BufferInfo::UNRECOGNIZED: return "UNRECOGNIZED"; 1230 default: return "?"; 1231 } 1232} 1233 1234void ACodec::dumpBuffers(OMX_U32 portIndex) { 1235 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 1236 ALOGI("[%s] %s port has %zu buffers:", mComponentName.c_str(), 1237 portIndex == kPortIndexInput ? "input" : "output", mBuffers[portIndex].size()); 1238 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 1239 const BufferInfo &info = mBuffers[portIndex][i]; 1240 ALOGI(" slot %2zu: #%8u %p/%p %s(%d) dequeued:%u", 1241 i, info.mBufferID, info.mGraphicBuffer.get(), 1242 info.mGraphicBuffer == NULL ? NULL : info.mGraphicBuffer->getNativeBuffer(), 1243 _asString(info.mStatus), info.mStatus, info.mDequeuedAt); 1244 } 1245} 1246 1247status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) { 1248 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 1249 1250 ALOGV("[%s] Calling cancelBuffer on buffer %u", 1251 mComponentName.c_str(), info->mBufferID); 1252 1253 info->checkWriteFence("cancelBufferToNativeWindow"); 1254 int err = mNativeWindow->cancelBuffer( 1255 mNativeWindow.get(), info->mGraphicBuffer.get(), info->mFenceFd); 1256 info->mFenceFd = -1; 1257 1258 ALOGW_IF(err != 0, "[%s] can not return buffer %u to native window", 1259 mComponentName.c_str(), info->mBufferID); 1260 // change ownership even if cancelBuffer fails 1261 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 1262 1263 return err; 1264} 1265 1266void ACodec::updateRenderInfoForDequeuedBuffer( 1267 ANativeWindowBuffer *buf, int fenceFd, BufferInfo *info) { 1268 1269 info->mRenderInfo = 1270 mRenderTracker.updateInfoForDequeuedBuffer( 1271 buf, fenceFd, info - &mBuffers[kPortIndexOutput][0]); 1272 1273 // check for any fences already signaled 1274 notifyOfRenderedFrames(false /* dropIncomplete */, info->mRenderInfo); 1275} 1276 1277void ACodec::onFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) { 1278 if (mRenderTracker.onFrameRendered(mediaTimeUs, systemNano) != OK) { 1279 mRenderTracker.dumpRenderQueue(); 1280 } 1281} 1282 1283void ACodec::notifyOfRenderedFrames(bool dropIncomplete, FrameRenderTracker::Info *until) { 1284 sp<AMessage> msg = mNotify->dup(); 1285 msg->setInt32("what", CodecBase::kWhatOutputFramesRendered); 1286 std::list<FrameRenderTracker::Info> done = 1287 mRenderTracker.checkFencesAndGetRenderedFrames(until, dropIncomplete); 1288 1289 // unlink untracked frames 1290 for (std::list<FrameRenderTracker::Info>::const_iterator it = done.cbegin(); 1291 it != done.cend(); ++it) { 1292 ssize_t index = it->getIndex(); 1293 if (index >= 0 && (size_t)index < mBuffers[kPortIndexOutput].size()) { 1294 mBuffers[kPortIndexOutput].editItemAt(index).mRenderInfo = NULL; 1295 } else if (index >= 0) { 1296 // THIS SHOULD NEVER HAPPEN 1297 ALOGE("invalid index %zd in %zu", index, mBuffers[kPortIndexOutput].size()); 1298 } 1299 } 1300 1301 if (MediaCodec::CreateFramesRenderedMessage(done, msg)) { 1302 msg->post(); 1303 } 1304} 1305 1306ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() { 1307 ANativeWindowBuffer *buf; 1308 CHECK(mNativeWindow.get() != NULL); 1309 1310 if (mTunneled) { 1311 ALOGW("dequeueBufferFromNativeWindow() should not be called in tunnel" 1312 " video playback mode mode!"); 1313 return NULL; 1314 } 1315 1316 if (mFatalError) { 1317 ALOGW("not dequeuing from native window due to fatal error"); 1318 return NULL; 1319 } 1320 1321 int fenceFd = -1; 1322 do { 1323 status_t err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf, &fenceFd); 1324 if (err != 0) { 1325 ALOGE("dequeueBuffer failed: %s(%d).", asString(err), err); 1326 return NULL; 1327 } 1328 1329 bool stale = false; 1330 for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) { 1331 i--; 1332 BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i); 1333 1334 if (info->mGraphicBuffer != NULL && 1335 info->mGraphicBuffer->handle == buf->handle) { 1336 // Since consumers can attach buffers to BufferQueues, it is possible 1337 // that a known yet stale buffer can return from a surface that we 1338 // once used. We can simply ignore this as we have already dequeued 1339 // this buffer properly. NOTE: this does not eliminate all cases, 1340 // e.g. it is possible that we have queued the valid buffer to the 1341 // NW, and a stale copy of the same buffer gets dequeued - which will 1342 // be treated as the valid buffer by ACodec. 1343 if (info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) { 1344 ALOGI("dequeued stale buffer %p. discarding", buf); 1345 stale = true; 1346 break; 1347 } 1348 1349 ALOGV("dequeued buffer %p", info->mGraphicBuffer->getNativeBuffer()); 1350 info->mStatus = BufferInfo::OWNED_BY_US; 1351 info->setWriteFence(fenceFd, "dequeueBufferFromNativeWindow"); 1352 updateRenderInfoForDequeuedBuffer(buf, fenceFd, info); 1353 return info; 1354 } 1355 } 1356 1357 // It is also possible to receive a previously unregistered buffer 1358 // in non-meta mode. These should be treated as stale buffers. The 1359 // same is possible in meta mode, in which case, it will be treated 1360 // as a normal buffer, which is not desirable. 1361 // TODO: fix this. 1362 if (!stale && (!storingMetadataInDecodedBuffers() || mLegacyAdaptiveExperiment)) { 1363 ALOGI("dequeued unrecognized (stale) buffer %p. discarding", buf); 1364 stale = true; 1365 } 1366 if (stale) { 1367 // TODO: detach stale buffer, but there is no API yet to do it. 1368 buf = NULL; 1369 } 1370 } while (buf == NULL); 1371 1372 // get oldest undequeued buffer 1373 BufferInfo *oldest = NULL; 1374 for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) { 1375 i--; 1376 BufferInfo *info = 1377 &mBuffers[kPortIndexOutput].editItemAt(i); 1378 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW && 1379 (oldest == NULL || 1380 // avoid potential issues from counter rolling over 1381 mDequeueCounter - info->mDequeuedAt > 1382 mDequeueCounter - oldest->mDequeuedAt)) { 1383 oldest = info; 1384 } 1385 } 1386 1387 // it is impossible dequeue a buffer when there are no buffers with ANW 1388 CHECK(oldest != NULL); 1389 // it is impossible to dequeue an unknown buffer in non-meta mode, as the 1390 // while loop above does not complete 1391 CHECK(storingMetadataInDecodedBuffers()); 1392 1393 // discard buffer in LRU info and replace with new buffer 1394 oldest->mGraphicBuffer = new GraphicBuffer(buf, false); 1395 oldest->mStatus = BufferInfo::OWNED_BY_US; 1396 oldest->setWriteFence(fenceFd, "dequeueBufferFromNativeWindow for oldest"); 1397 mRenderTracker.untrackFrame(oldest->mRenderInfo); 1398 oldest->mRenderInfo = NULL; 1399 1400 mOMX->updateGraphicBufferInMeta( 1401 mNode, kPortIndexOutput, oldest->mGraphicBuffer, 1402 oldest->mBufferID); 1403 1404 if (mOutputMetadataType == kMetadataBufferTypeGrallocSource) { 1405 VideoGrallocMetadata *grallocMeta = 1406 reinterpret_cast<VideoGrallocMetadata *>(oldest->mData->base()); 1407 ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)", 1408 (unsigned)(oldest - &mBuffers[kPortIndexOutput][0]), 1409 mDequeueCounter - oldest->mDequeuedAt, 1410 (void *)(uintptr_t)grallocMeta->pHandle, 1411 oldest->mGraphicBuffer->handle, oldest->mData->base()); 1412 } else if (mOutputMetadataType == kMetadataBufferTypeANWBuffer) { 1413 VideoNativeMetadata *nativeMeta = 1414 reinterpret_cast<VideoNativeMetadata *>(oldest->mData->base()); 1415 ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)", 1416 (unsigned)(oldest - &mBuffers[kPortIndexOutput][0]), 1417 mDequeueCounter - oldest->mDequeuedAt, 1418 (void *)(uintptr_t)nativeMeta->pBuffer, 1419 oldest->mGraphicBuffer->getNativeBuffer(), oldest->mData->base()); 1420 } 1421 1422 updateRenderInfoForDequeuedBuffer(buf, fenceFd, oldest); 1423 return oldest; 1424} 1425 1426status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) { 1427 status_t err = OK; 1428 for (size_t i = mBuffers[portIndex].size(); i > 0;) { 1429 i--; 1430 status_t err2 = freeBuffer(portIndex, i); 1431 if (err == OK) { 1432 err = err2; 1433 } 1434 } 1435 1436 // clear mDealer even on an error 1437 mDealer[portIndex].clear(); 1438 return err; 1439} 1440 1441status_t ACodec::freeOutputBuffersNotOwnedByComponent() { 1442 status_t err = OK; 1443 for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) { 1444 i--; 1445 BufferInfo *info = 1446 &mBuffers[kPortIndexOutput].editItemAt(i); 1447 1448 // At this time some buffers may still be with the component 1449 // or being drained. 1450 if (info->mStatus != BufferInfo::OWNED_BY_COMPONENT && 1451 info->mStatus != BufferInfo::OWNED_BY_DOWNSTREAM) { 1452 status_t err2 = freeBuffer(kPortIndexOutput, i); 1453 if (err == OK) { 1454 err = err2; 1455 } 1456 } 1457 } 1458 1459 return err; 1460} 1461 1462status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) { 1463 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 1464 status_t err = OK; 1465 1466 // there should not be any fences in the metadata 1467 MetadataBufferType type = 1468 portIndex == kPortIndexOutput ? mOutputMetadataType : mInputMetadataType; 1469 if (type == kMetadataBufferTypeANWBuffer && info->mData != NULL 1470 && info->mData->size() >= sizeof(VideoNativeMetadata)) { 1471 int fenceFd = ((VideoNativeMetadata *)info->mData->data())->nFenceFd; 1472 if (fenceFd >= 0) { 1473 ALOGW("unreleased fence (%d) in %s metadata buffer %zu", 1474 fenceFd, portIndex == kPortIndexInput ? "input" : "output", i); 1475 } 1476 } 1477 1478 switch (info->mStatus) { 1479 case BufferInfo::OWNED_BY_US: 1480 if (portIndex == kPortIndexOutput && mNativeWindow != NULL) { 1481 (void)cancelBufferToNativeWindow(info); 1482 } 1483 // fall through 1484 1485 case BufferInfo::OWNED_BY_NATIVE_WINDOW: 1486 err = mOMX->freeBuffer(mNode, portIndex, info->mBufferID); 1487 break; 1488 1489 default: 1490 ALOGE("trying to free buffer not owned by us or ANW (%d)", info->mStatus); 1491 err = FAILED_TRANSACTION; 1492 break; 1493 } 1494 1495 if (info->mFenceFd >= 0) { 1496 ::close(info->mFenceFd); 1497 } 1498 1499 if (portIndex == kPortIndexOutput) { 1500 mRenderTracker.untrackFrame(info->mRenderInfo, i); 1501 info->mRenderInfo = NULL; 1502 } 1503 1504 // remove buffer even if mOMX->freeBuffer fails 1505 mBuffers[portIndex].removeAt(i); 1506 return err; 1507} 1508 1509ACodec::BufferInfo *ACodec::findBufferByID( 1510 uint32_t portIndex, IOMX::buffer_id bufferID, ssize_t *index) { 1511 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 1512 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 1513 1514 if (info->mBufferID == bufferID) { 1515 if (index != NULL) { 1516 *index = i; 1517 } 1518 return info; 1519 } 1520 } 1521 1522 ALOGE("Could not find buffer with ID %u", bufferID); 1523 return NULL; 1524} 1525 1526status_t ACodec::setComponentRole( 1527 bool isEncoder, const char *mime) { 1528 struct MimeToRole { 1529 const char *mime; 1530 const char *decoderRole; 1531 const char *encoderRole; 1532 }; 1533 1534 static const MimeToRole kMimeToRole[] = { 1535 { MEDIA_MIMETYPE_AUDIO_MPEG, 1536 "audio_decoder.mp3", "audio_encoder.mp3" }, 1537 { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I, 1538 "audio_decoder.mp1", "audio_encoder.mp1" }, 1539 { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II, 1540 "audio_decoder.mp2", "audio_encoder.mp2" }, 1541 { MEDIA_MIMETYPE_AUDIO_AMR_NB, 1542 "audio_decoder.amrnb", "audio_encoder.amrnb" }, 1543 { MEDIA_MIMETYPE_AUDIO_AMR_WB, 1544 "audio_decoder.amrwb", "audio_encoder.amrwb" }, 1545 { MEDIA_MIMETYPE_AUDIO_AAC, 1546 "audio_decoder.aac", "audio_encoder.aac" }, 1547 { MEDIA_MIMETYPE_AUDIO_VORBIS, 1548 "audio_decoder.vorbis", "audio_encoder.vorbis" }, 1549 { MEDIA_MIMETYPE_AUDIO_OPUS, 1550 "audio_decoder.opus", "audio_encoder.opus" }, 1551 { MEDIA_MIMETYPE_AUDIO_G711_MLAW, 1552 "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" }, 1553 { MEDIA_MIMETYPE_AUDIO_G711_ALAW, 1554 "audio_decoder.g711alaw", "audio_encoder.g711alaw" }, 1555 { MEDIA_MIMETYPE_VIDEO_AVC, 1556 "video_decoder.avc", "video_encoder.avc" }, 1557 { MEDIA_MIMETYPE_VIDEO_HEVC, 1558 "video_decoder.hevc", "video_encoder.hevc" }, 1559 { MEDIA_MIMETYPE_VIDEO_MPEG4, 1560 "video_decoder.mpeg4", "video_encoder.mpeg4" }, 1561 { MEDIA_MIMETYPE_VIDEO_H263, 1562 "video_decoder.h263", "video_encoder.h263" }, 1563 { MEDIA_MIMETYPE_VIDEO_VP8, 1564 "video_decoder.vp8", "video_encoder.vp8" }, 1565 { MEDIA_MIMETYPE_VIDEO_VP9, 1566 "video_decoder.vp9", "video_encoder.vp9" }, 1567 { MEDIA_MIMETYPE_AUDIO_RAW, 1568 "audio_decoder.raw", "audio_encoder.raw" }, 1569 { MEDIA_MIMETYPE_AUDIO_FLAC, 1570 "audio_decoder.flac", "audio_encoder.flac" }, 1571 { MEDIA_MIMETYPE_AUDIO_MSGSM, 1572 "audio_decoder.gsm", "audio_encoder.gsm" }, 1573 { MEDIA_MIMETYPE_VIDEO_MPEG2, 1574 "video_decoder.mpeg2", "video_encoder.mpeg2" }, 1575 { MEDIA_MIMETYPE_AUDIO_AC3, 1576 "audio_decoder.ac3", "audio_encoder.ac3" }, 1577 { MEDIA_MIMETYPE_AUDIO_EAC3, 1578 "audio_decoder.eac3", "audio_encoder.eac3" }, 1579 }; 1580 1581 static const size_t kNumMimeToRole = 1582 sizeof(kMimeToRole) / sizeof(kMimeToRole[0]); 1583 1584 size_t i; 1585 for (i = 0; i < kNumMimeToRole; ++i) { 1586 if (!strcasecmp(mime, kMimeToRole[i].mime)) { 1587 break; 1588 } 1589 } 1590 1591 if (i == kNumMimeToRole) { 1592 return ERROR_UNSUPPORTED; 1593 } 1594 1595 const char *role = 1596 isEncoder ? kMimeToRole[i].encoderRole 1597 : kMimeToRole[i].decoderRole; 1598 1599 if (role != NULL) { 1600 OMX_PARAM_COMPONENTROLETYPE roleParams; 1601 InitOMXParams(&roleParams); 1602 1603 strncpy((char *)roleParams.cRole, 1604 role, OMX_MAX_STRINGNAME_SIZE - 1); 1605 1606 roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0'; 1607 1608 status_t err = mOMX->setParameter( 1609 mNode, OMX_IndexParamStandardComponentRole, 1610 &roleParams, sizeof(roleParams)); 1611 1612 if (err != OK) { 1613 ALOGW("[%s] Failed to set standard component role '%s'.", 1614 mComponentName.c_str(), role); 1615 1616 return err; 1617 } 1618 } 1619 1620 return OK; 1621} 1622 1623status_t ACodec::configureCodec( 1624 const char *mime, const sp<AMessage> &msg) { 1625 int32_t encoder; 1626 if (!msg->findInt32("encoder", &encoder)) { 1627 encoder = false; 1628 } 1629 1630 sp<AMessage> inputFormat = new AMessage(); 1631 sp<AMessage> outputFormat = mNotify->dup(); // will use this for kWhatOutputFormatChanged 1632 1633 mIsEncoder = encoder; 1634 1635 mInputMetadataType = kMetadataBufferTypeInvalid; 1636 mOutputMetadataType = kMetadataBufferTypeInvalid; 1637 1638 status_t err = setComponentRole(encoder /* isEncoder */, mime); 1639 1640 if (err != OK) { 1641 return err; 1642 } 1643 1644 int32_t bitRate = 0; 1645 // FLAC encoder doesn't need a bitrate, other encoders do 1646 if (encoder && strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC) 1647 && !msg->findInt32("bitrate", &bitRate)) { 1648 return INVALID_OPERATION; 1649 } 1650 1651 int32_t storeMeta; 1652 if (encoder 1653 && msg->findInt32("store-metadata-in-buffers", &storeMeta) 1654 && storeMeta != 0) { 1655 err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexInput, OMX_TRUE, &mInputMetadataType); 1656 if (err != OK) { 1657 ALOGE("[%s] storeMetaDataInBuffers (input) failed w/ err %d", 1658 mComponentName.c_str(), err); 1659 1660 return err; 1661 } 1662 // For this specific case we could be using camera source even if storeMetaDataInBuffers 1663 // returns Gralloc source. Pretend that we are; this will force us to use nBufferSize. 1664 if (mInputMetadataType == kMetadataBufferTypeGrallocSource) { 1665 mInputMetadataType = kMetadataBufferTypeCameraSource; 1666 } 1667 1668 uint32_t usageBits; 1669 if (mOMX->getParameter( 1670 mNode, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits, 1671 &usageBits, sizeof(usageBits)) == OK) { 1672 inputFormat->setInt32( 1673 "using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN)); 1674 } 1675 } 1676 1677 int32_t prependSPSPPS = 0; 1678 if (encoder 1679 && msg->findInt32("prepend-sps-pps-to-idr-frames", &prependSPSPPS) 1680 && prependSPSPPS != 0) { 1681 OMX_INDEXTYPE index; 1682 err = mOMX->getExtensionIndex( 1683 mNode, 1684 "OMX.google.android.index.prependSPSPPSToIDRFrames", 1685 &index); 1686 1687 if (err == OK) { 1688 PrependSPSPPSToIDRFramesParams params; 1689 InitOMXParams(¶ms); 1690 params.bEnable = OMX_TRUE; 1691 1692 err = mOMX->setParameter( 1693 mNode, index, ¶ms, sizeof(params)); 1694 } 1695 1696 if (err != OK) { 1697 ALOGE("Encoder could not be configured to emit SPS/PPS before " 1698 "IDR frames. (err %d)", err); 1699 1700 return err; 1701 } 1702 } 1703 1704 // Only enable metadata mode on encoder output if encoder can prepend 1705 // sps/pps to idr frames, since in metadata mode the bitstream is in an 1706 // opaque handle, to which we don't have access. 1707 int32_t video = !strncasecmp(mime, "video/", 6); 1708 mIsVideo = video; 1709 if (encoder && video) { 1710 OMX_BOOL enable = (OMX_BOOL) (prependSPSPPS 1711 && msg->findInt32("store-metadata-in-buffers-output", &storeMeta) 1712 && storeMeta != 0); 1713 1714 err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, enable, &mOutputMetadataType); 1715 if (err != OK) { 1716 ALOGE("[%s] storeMetaDataInBuffers (output) failed w/ err %d", 1717 mComponentName.c_str(), err); 1718 } 1719 1720 if (!msg->findInt64( 1721 "repeat-previous-frame-after", 1722 &mRepeatFrameDelayUs)) { 1723 mRepeatFrameDelayUs = -1ll; 1724 } 1725 1726 if (!msg->findInt64("max-pts-gap-to-encoder", &mMaxPtsGapUs)) { 1727 mMaxPtsGapUs = -1ll; 1728 } 1729 1730 if (!msg->findFloat("max-fps-to-encoder", &mMaxFps)) { 1731 mMaxFps = -1; 1732 } 1733 1734 if (!msg->findInt64("time-lapse", &mTimePerCaptureUs)) { 1735 mTimePerCaptureUs = -1ll; 1736 } 1737 1738 if (!msg->findInt32( 1739 "create-input-buffers-suspended", 1740 (int32_t*)&mCreateInputBuffersSuspended)) { 1741 mCreateInputBuffersSuspended = false; 1742 } 1743 } 1744 1745 // NOTE: we only use native window for video decoders 1746 sp<RefBase> obj; 1747 bool haveNativeWindow = msg->findObject("native-window", &obj) 1748 && obj != NULL && video && !encoder; 1749 mLegacyAdaptiveExperiment = false; 1750 if (video && !encoder) { 1751 inputFormat->setInt32("adaptive-playback", false); 1752 1753 int32_t usageProtected; 1754 if (msg->findInt32("protected", &usageProtected) && usageProtected) { 1755 if (!haveNativeWindow) { 1756 ALOGE("protected output buffers must be sent to an ANativeWindow"); 1757 return PERMISSION_DENIED; 1758 } 1759 mFlags |= kFlagIsGrallocUsageProtected; 1760 mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown; 1761 } 1762 } 1763 if (haveNativeWindow) { 1764 sp<ANativeWindow> nativeWindow = 1765 static_cast<ANativeWindow *>(static_cast<Surface *>(obj.get())); 1766 1767 // START of temporary support for automatic FRC - THIS WILL BE REMOVED 1768 int32_t autoFrc; 1769 if (msg->findInt32("auto-frc", &autoFrc)) { 1770 bool enabled = autoFrc; 1771 OMX_CONFIG_BOOLEANTYPE config; 1772 InitOMXParams(&config); 1773 config.bEnabled = (OMX_BOOL)enabled; 1774 status_t temp = mOMX->setConfig( 1775 mNode, (OMX_INDEXTYPE)OMX_IndexConfigAutoFramerateConversion, 1776 &config, sizeof(config)); 1777 if (temp == OK) { 1778 outputFormat->setInt32("auto-frc", enabled); 1779 } else if (enabled) { 1780 ALOGI("codec does not support requested auto-frc (err %d)", temp); 1781 } 1782 } 1783 // END of temporary support for automatic FRC 1784 1785 int32_t tunneled; 1786 if (msg->findInt32("feature-tunneled-playback", &tunneled) && 1787 tunneled != 0) { 1788 ALOGI("Configuring TUNNELED video playback."); 1789 mTunneled = true; 1790 1791 int32_t audioHwSync = 0; 1792 if (!msg->findInt32("audio-hw-sync", &audioHwSync)) { 1793 ALOGW("No Audio HW Sync provided for video tunnel"); 1794 } 1795 err = configureTunneledVideoPlayback(audioHwSync, nativeWindow); 1796 if (err != OK) { 1797 ALOGE("configureTunneledVideoPlayback(%d,%p) failed!", 1798 audioHwSync, nativeWindow.get()); 1799 return err; 1800 } 1801 1802 int32_t maxWidth = 0, maxHeight = 0; 1803 if (msg->findInt32("max-width", &maxWidth) && 1804 msg->findInt32("max-height", &maxHeight)) { 1805 1806 err = mOMX->prepareForAdaptivePlayback( 1807 mNode, kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight); 1808 if (err != OK) { 1809 ALOGW("[%s] prepareForAdaptivePlayback failed w/ err %d", 1810 mComponentName.c_str(), err); 1811 // allow failure 1812 err = OK; 1813 } else { 1814 inputFormat->setInt32("max-width", maxWidth); 1815 inputFormat->setInt32("max-height", maxHeight); 1816 inputFormat->setInt32("adaptive-playback", true); 1817 } 1818 } 1819 } else { 1820 ALOGV("Configuring CPU controlled video playback."); 1821 mTunneled = false; 1822 1823 // Explicity reset the sideband handle of the window for 1824 // non-tunneled video in case the window was previously used 1825 // for a tunneled video playback. 1826 err = native_window_set_sideband_stream(nativeWindow.get(), NULL); 1827 if (err != OK) { 1828 ALOGE("set_sideband_stream(NULL) failed! (err %d).", err); 1829 return err; 1830 } 1831 1832 // Always try to enable dynamic output buffers on native surface 1833 err = mOMX->storeMetaDataInBuffers( 1834 mNode, kPortIndexOutput, OMX_TRUE, &mOutputMetadataType); 1835 if (err != OK) { 1836 ALOGE("[%s] storeMetaDataInBuffers failed w/ err %d", 1837 mComponentName.c_str(), err); 1838 1839 // if adaptive playback has been requested, try JB fallback 1840 // NOTE: THIS FALLBACK MECHANISM WILL BE REMOVED DUE TO ITS 1841 // LARGE MEMORY REQUIREMENT 1842 1843 // we will not do adaptive playback on software accessed 1844 // surfaces as they never had to respond to changes in the 1845 // crop window, and we don't trust that they will be able to. 1846 int usageBits = 0; 1847 bool canDoAdaptivePlayback; 1848 1849 if (nativeWindow->query( 1850 nativeWindow.get(), 1851 NATIVE_WINDOW_CONSUMER_USAGE_BITS, 1852 &usageBits) != OK) { 1853 canDoAdaptivePlayback = false; 1854 } else { 1855 canDoAdaptivePlayback = 1856 (usageBits & 1857 (GRALLOC_USAGE_SW_READ_MASK | 1858 GRALLOC_USAGE_SW_WRITE_MASK)) == 0; 1859 } 1860 1861 int32_t maxWidth = 0, maxHeight = 0; 1862 if (canDoAdaptivePlayback && 1863 msg->findInt32("max-width", &maxWidth) && 1864 msg->findInt32("max-height", &maxHeight)) { 1865 ALOGV("[%s] prepareForAdaptivePlayback(%dx%d)", 1866 mComponentName.c_str(), maxWidth, maxHeight); 1867 1868 err = mOMX->prepareForAdaptivePlayback( 1869 mNode, kPortIndexOutput, OMX_TRUE, maxWidth, 1870 maxHeight); 1871 ALOGW_IF(err != OK, 1872 "[%s] prepareForAdaptivePlayback failed w/ err %d", 1873 mComponentName.c_str(), err); 1874 1875 if (err == OK) { 1876 inputFormat->setInt32("max-width", maxWidth); 1877 inputFormat->setInt32("max-height", maxHeight); 1878 inputFormat->setInt32("adaptive-playback", true); 1879 } 1880 } 1881 // allow failure 1882 err = OK; 1883 } else { 1884 ALOGV("[%s] storeMetaDataInBuffers succeeded", 1885 mComponentName.c_str()); 1886 CHECK(storingMetadataInDecodedBuffers()); 1887 mLegacyAdaptiveExperiment = ADebug::isExperimentEnabled( 1888 "legacy-adaptive", !msg->contains("no-experiments")); 1889 1890 inputFormat->setInt32("adaptive-playback", true); 1891 } 1892 1893 int32_t push; 1894 if (msg->findInt32("push-blank-buffers-on-shutdown", &push) 1895 && push != 0) { 1896 mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown; 1897 } 1898 } 1899 1900 int32_t rotationDegrees; 1901 if (msg->findInt32("rotation-degrees", &rotationDegrees)) { 1902 mRotationDegrees = rotationDegrees; 1903 } else { 1904 mRotationDegrees = 0; 1905 } 1906 } 1907 1908 if (video) { 1909 // determine need for software renderer 1910 bool usingSwRenderer = false; 1911 if (haveNativeWindow && mComponentName.startsWith("OMX.google.")) { 1912 usingSwRenderer = true; 1913 haveNativeWindow = false; 1914 } 1915 1916 if (encoder) { 1917 err = setupVideoEncoder(mime, msg); 1918 } else { 1919 err = setupVideoDecoder(mime, msg, haveNativeWindow); 1920 } 1921 1922 if (err != OK) { 1923 return err; 1924 } 1925 1926 if (haveNativeWindow) { 1927 mNativeWindow = static_cast<Surface *>(obj.get()); 1928 } 1929 1930 // initialize native window now to get actual output format 1931 // TODO: this is needed for some encoders even though they don't use native window 1932 err = initNativeWindow(); 1933 if (err != OK) { 1934 return err; 1935 } 1936 1937 // fallback for devices that do not handle flex-YUV for native buffers 1938 if (haveNativeWindow) { 1939 int32_t requestedColorFormat = OMX_COLOR_FormatUnused; 1940 if (msg->findInt32("color-format", &requestedColorFormat) && 1941 requestedColorFormat == OMX_COLOR_FormatYUV420Flexible) { 1942 status_t err = getPortFormat(kPortIndexOutput, outputFormat); 1943 if (err != OK) { 1944 return err; 1945 } 1946 int32_t colorFormat = OMX_COLOR_FormatUnused; 1947 OMX_U32 flexibleEquivalent = OMX_COLOR_FormatUnused; 1948 if (!outputFormat->findInt32("color-format", &colorFormat)) { 1949 ALOGE("ouptut port did not have a color format (wrong domain?)"); 1950 return BAD_VALUE; 1951 } 1952 ALOGD("[%s] Requested output format %#x and got %#x.", 1953 mComponentName.c_str(), requestedColorFormat, colorFormat); 1954 if (!isFlexibleColorFormat( 1955 mOMX, mNode, colorFormat, haveNativeWindow, &flexibleEquivalent) 1956 || flexibleEquivalent != (OMX_U32)requestedColorFormat) { 1957 // device did not handle flex-YUV request for native window, fall back 1958 // to SW renderer 1959 ALOGI("[%s] Falling back to software renderer", mComponentName.c_str()); 1960 mNativeWindow.clear(); 1961 mNativeWindowUsageBits = 0; 1962 haveNativeWindow = false; 1963 usingSwRenderer = true; 1964 if (storingMetadataInDecodedBuffers()) { 1965 err = mOMX->storeMetaDataInBuffers( 1966 mNode, kPortIndexOutput, OMX_FALSE, &mOutputMetadataType); 1967 mOutputMetadataType = kMetadataBufferTypeInvalid; // just in case 1968 // TODO: implement adaptive-playback support for bytebuffer mode. 1969 // This is done by SW codecs, but most HW codecs don't support it. 1970 inputFormat->setInt32("adaptive-playback", false); 1971 } 1972 if (err == OK) { 1973 err = mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE); 1974 } 1975 if (mFlags & kFlagIsGrallocUsageProtected) { 1976 // fallback is not supported for protected playback 1977 err = PERMISSION_DENIED; 1978 } else if (err == OK) { 1979 err = setupVideoDecoder(mime, msg, false); 1980 } 1981 } 1982 } 1983 } 1984 1985 if (usingSwRenderer) { 1986 outputFormat->setInt32("using-sw-renderer", 1); 1987 } 1988 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) { 1989 int32_t numChannels, sampleRate; 1990 if (!msg->findInt32("channel-count", &numChannels) 1991 || !msg->findInt32("sample-rate", &sampleRate)) { 1992 // Since we did not always check for these, leave them optional 1993 // and have the decoder figure it all out. 1994 err = OK; 1995 } else { 1996 err = setupRawAudioFormat( 1997 encoder ? kPortIndexInput : kPortIndexOutput, 1998 sampleRate, 1999 numChannels); 2000 } 2001 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 2002 int32_t numChannels, sampleRate; 2003 if (!msg->findInt32("channel-count", &numChannels) 2004 || !msg->findInt32("sample-rate", &sampleRate)) { 2005 err = INVALID_OPERATION; 2006 } else { 2007 int32_t isADTS, aacProfile; 2008 int32_t sbrMode; 2009 int32_t maxOutputChannelCount; 2010 int32_t pcmLimiterEnable; 2011 drcParams_t drc; 2012 if (!msg->findInt32("is-adts", &isADTS)) { 2013 isADTS = 0; 2014 } 2015 if (!msg->findInt32("aac-profile", &aacProfile)) { 2016 aacProfile = OMX_AUDIO_AACObjectNull; 2017 } 2018 if (!msg->findInt32("aac-sbr-mode", &sbrMode)) { 2019 sbrMode = -1; 2020 } 2021 2022 if (!msg->findInt32("aac-max-output-channel_count", &maxOutputChannelCount)) { 2023 maxOutputChannelCount = -1; 2024 } 2025 if (!msg->findInt32("aac-pcm-limiter-enable", &pcmLimiterEnable)) { 2026 // value is unknown 2027 pcmLimiterEnable = -1; 2028 } 2029 if (!msg->findInt32("aac-encoded-target-level", &drc.encodedTargetLevel)) { 2030 // value is unknown 2031 drc.encodedTargetLevel = -1; 2032 } 2033 if (!msg->findInt32("aac-drc-cut-level", &drc.drcCut)) { 2034 // value is unknown 2035 drc.drcCut = -1; 2036 } 2037 if (!msg->findInt32("aac-drc-boost-level", &drc.drcBoost)) { 2038 // value is unknown 2039 drc.drcBoost = -1; 2040 } 2041 if (!msg->findInt32("aac-drc-heavy-compression", &drc.heavyCompression)) { 2042 // value is unknown 2043 drc.heavyCompression = -1; 2044 } 2045 if (!msg->findInt32("aac-target-ref-level", &drc.targetRefLevel)) { 2046 // value is unknown 2047 drc.targetRefLevel = -1; 2048 } 2049 2050 err = setupAACCodec( 2051 encoder, numChannels, sampleRate, bitRate, aacProfile, 2052 isADTS != 0, sbrMode, maxOutputChannelCount, drc, 2053 pcmLimiterEnable); 2054 } 2055 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) { 2056 err = setupAMRCodec(encoder, false /* isWAMR */, bitRate); 2057 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) { 2058 err = setupAMRCodec(encoder, true /* isWAMR */, bitRate); 2059 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW) 2060 || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) { 2061 // These are PCM-like formats with a fixed sample rate but 2062 // a variable number of channels. 2063 2064 int32_t numChannels; 2065 if (!msg->findInt32("channel-count", &numChannels)) { 2066 err = INVALID_OPERATION; 2067 } else { 2068 int32_t sampleRate; 2069 if (!msg->findInt32("sample-rate", &sampleRate)) { 2070 sampleRate = 8000; 2071 } 2072 err = setupG711Codec(encoder, sampleRate, numChannels); 2073 } 2074 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) { 2075 int32_t numChannels = 0, sampleRate = 0, compressionLevel = -1; 2076 if (encoder && 2077 (!msg->findInt32("channel-count", &numChannels) 2078 || !msg->findInt32("sample-rate", &sampleRate))) { 2079 ALOGE("missing channel count or sample rate for FLAC encoder"); 2080 err = INVALID_OPERATION; 2081 } else { 2082 if (encoder) { 2083 if (!msg->findInt32( 2084 "complexity", &compressionLevel) && 2085 !msg->findInt32( 2086 "flac-compression-level", &compressionLevel)) { 2087 compressionLevel = 5; // default FLAC compression level 2088 } else if (compressionLevel < 0) { 2089 ALOGW("compression level %d outside [0..8] range, " 2090 "using 0", 2091 compressionLevel); 2092 compressionLevel = 0; 2093 } else if (compressionLevel > 8) { 2094 ALOGW("compression level %d outside [0..8] range, " 2095 "using 8", 2096 compressionLevel); 2097 compressionLevel = 8; 2098 } 2099 } 2100 err = setupFlacCodec( 2101 encoder, numChannels, sampleRate, compressionLevel); 2102 } 2103 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) { 2104 int32_t numChannels, sampleRate; 2105 if (encoder 2106 || !msg->findInt32("channel-count", &numChannels) 2107 || !msg->findInt32("sample-rate", &sampleRate)) { 2108 err = INVALID_OPERATION; 2109 } else { 2110 err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels); 2111 } 2112 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AC3)) { 2113 int32_t numChannels; 2114 int32_t sampleRate; 2115 if (!msg->findInt32("channel-count", &numChannels) 2116 || !msg->findInt32("sample-rate", &sampleRate)) { 2117 err = INVALID_OPERATION; 2118 } else { 2119 err = setupAC3Codec(encoder, numChannels, sampleRate); 2120 } 2121 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_EAC3)) { 2122 int32_t numChannels; 2123 int32_t sampleRate; 2124 if (!msg->findInt32("channel-count", &numChannels) 2125 || !msg->findInt32("sample-rate", &sampleRate)) { 2126 err = INVALID_OPERATION; 2127 } else { 2128 err = setupEAC3Codec(encoder, numChannels, sampleRate); 2129 } 2130 } 2131 2132 if (err != OK) { 2133 return err; 2134 } 2135 2136 if (!msg->findInt32("encoder-delay", &mEncoderDelay)) { 2137 mEncoderDelay = 0; 2138 } 2139 2140 if (!msg->findInt32("encoder-padding", &mEncoderPadding)) { 2141 mEncoderPadding = 0; 2142 } 2143 2144 if (msg->findInt32("channel-mask", &mChannelMask)) { 2145 mChannelMaskPresent = true; 2146 } else { 2147 mChannelMaskPresent = false; 2148 } 2149 2150 int32_t maxInputSize; 2151 if (msg->findInt32("max-input-size", &maxInputSize)) { 2152 err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize); 2153 } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) { 2154 err = setMinBufferSize(kPortIndexInput, 8192); // XXX 2155 } 2156 2157 int32_t priority; 2158 if (msg->findInt32("priority", &priority)) { 2159 err = setPriority(priority); 2160 } 2161 2162 int32_t rateInt = -1; 2163 float rateFloat = -1; 2164 if (!msg->findFloat("operating-rate", &rateFloat)) { 2165 msg->findInt32("operating-rate", &rateInt); 2166 rateFloat = (float)rateInt; // 16MHz (FLINTMAX) is OK for upper bound. 2167 } 2168 if (rateFloat > 0) { 2169 err = setOperatingRate(rateFloat, video); 2170 } 2171 2172 mBaseOutputFormat = outputFormat; 2173 2174 err = getPortFormat(kPortIndexInput, inputFormat); 2175 if (err == OK) { 2176 err = getPortFormat(kPortIndexOutput, outputFormat); 2177 if (err == OK) { 2178 mInputFormat = inputFormat; 2179 mOutputFormat = outputFormat; 2180 } 2181 } 2182 return err; 2183} 2184 2185status_t ACodec::setPriority(int32_t priority) { 2186 if (priority < 0) { 2187 return BAD_VALUE; 2188 } 2189 OMX_PARAM_U32TYPE config; 2190 InitOMXParams(&config); 2191 config.nU32 = (OMX_U32)priority; 2192 status_t temp = mOMX->setConfig( 2193 mNode, (OMX_INDEXTYPE)OMX_IndexConfigPriority, 2194 &config, sizeof(config)); 2195 if (temp != OK) { 2196 ALOGI("codec does not support config priority (err %d)", temp); 2197 } 2198 return OK; 2199} 2200 2201status_t ACodec::setOperatingRate(float rateFloat, bool isVideo) { 2202 if (rateFloat < 0) { 2203 return BAD_VALUE; 2204 } 2205 OMX_U32 rate; 2206 if (isVideo) { 2207 if (rateFloat > 65535) { 2208 return BAD_VALUE; 2209 } 2210 rate = (OMX_U32)(rateFloat * 65536.0f + 0.5f); 2211 } else { 2212 if (rateFloat > UINT_MAX) { 2213 return BAD_VALUE; 2214 } 2215 rate = (OMX_U32)(rateFloat); 2216 } 2217 OMX_PARAM_U32TYPE config; 2218 InitOMXParams(&config); 2219 config.nU32 = rate; 2220 status_t err = mOMX->setConfig( 2221 mNode, (OMX_INDEXTYPE)OMX_IndexConfigOperatingRate, 2222 &config, sizeof(config)); 2223 if (err != OK) { 2224 ALOGI("codec does not support config operating rate (err %d)", err); 2225 } 2226 return OK; 2227} 2228 2229status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) { 2230 OMX_PARAM_PORTDEFINITIONTYPE def; 2231 InitOMXParams(&def); 2232 def.nPortIndex = portIndex; 2233 2234 status_t err = mOMX->getParameter( 2235 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2236 2237 if (err != OK) { 2238 return err; 2239 } 2240 2241 if (def.nBufferSize >= size) { 2242 return OK; 2243 } 2244 2245 def.nBufferSize = size; 2246 2247 err = mOMX->setParameter( 2248 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2249 2250 if (err != OK) { 2251 return err; 2252 } 2253 2254 err = mOMX->getParameter( 2255 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2256 2257 if (err != OK) { 2258 return err; 2259 } 2260 2261 if (def.nBufferSize < size) { 2262 ALOGE("failed to set min buffer size to %zu (is still %u)", size, def.nBufferSize); 2263 return FAILED_TRANSACTION; 2264 } 2265 2266 return OK; 2267} 2268 2269status_t ACodec::selectAudioPortFormat( 2270 OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) { 2271 OMX_AUDIO_PARAM_PORTFORMATTYPE format; 2272 InitOMXParams(&format); 2273 2274 format.nPortIndex = portIndex; 2275 for (OMX_U32 index = 0;; ++index) { 2276 format.nIndex = index; 2277 2278 status_t err = mOMX->getParameter( 2279 mNode, OMX_IndexParamAudioPortFormat, 2280 &format, sizeof(format)); 2281 2282 if (err != OK) { 2283 return err; 2284 } 2285 2286 if (format.eEncoding == desiredFormat) { 2287 break; 2288 } 2289 } 2290 2291 return mOMX->setParameter( 2292 mNode, OMX_IndexParamAudioPortFormat, &format, sizeof(format)); 2293} 2294 2295status_t ACodec::setupAACCodec( 2296 bool encoder, int32_t numChannels, int32_t sampleRate, 2297 int32_t bitRate, int32_t aacProfile, bool isADTS, int32_t sbrMode, 2298 int32_t maxOutputChannelCount, const drcParams_t& drc, 2299 int32_t pcmLimiterEnable) { 2300 if (encoder && isADTS) { 2301 return -EINVAL; 2302 } 2303 2304 status_t err = setupRawAudioFormat( 2305 encoder ? kPortIndexInput : kPortIndexOutput, 2306 sampleRate, 2307 numChannels); 2308 2309 if (err != OK) { 2310 return err; 2311 } 2312 2313 if (encoder) { 2314 err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC); 2315 2316 if (err != OK) { 2317 return err; 2318 } 2319 2320 OMX_PARAM_PORTDEFINITIONTYPE def; 2321 InitOMXParams(&def); 2322 def.nPortIndex = kPortIndexOutput; 2323 2324 err = mOMX->getParameter( 2325 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2326 2327 if (err != OK) { 2328 return err; 2329 } 2330 2331 def.format.audio.bFlagErrorConcealment = OMX_TRUE; 2332 def.format.audio.eEncoding = OMX_AUDIO_CodingAAC; 2333 2334 err = mOMX->setParameter( 2335 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2336 2337 if (err != OK) { 2338 return err; 2339 } 2340 2341 OMX_AUDIO_PARAM_AACPROFILETYPE profile; 2342 InitOMXParams(&profile); 2343 profile.nPortIndex = kPortIndexOutput; 2344 2345 err = mOMX->getParameter( 2346 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 2347 2348 if (err != OK) { 2349 return err; 2350 } 2351 2352 profile.nChannels = numChannels; 2353 2354 profile.eChannelMode = 2355 (numChannels == 1) 2356 ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo; 2357 2358 profile.nSampleRate = sampleRate; 2359 profile.nBitRate = bitRate; 2360 profile.nAudioBandWidth = 0; 2361 profile.nFrameLength = 0; 2362 profile.nAACtools = OMX_AUDIO_AACToolAll; 2363 profile.nAACERtools = OMX_AUDIO_AACERNone; 2364 profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile; 2365 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF; 2366 switch (sbrMode) { 2367 case 0: 2368 // disable sbr 2369 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR; 2370 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR; 2371 break; 2372 case 1: 2373 // enable single-rate sbr 2374 profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR; 2375 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR; 2376 break; 2377 case 2: 2378 // enable dual-rate sbr 2379 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR; 2380 profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR; 2381 break; 2382 case -1: 2383 // enable both modes -> the codec will decide which mode should be used 2384 profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR; 2385 profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR; 2386 break; 2387 default: 2388 // unsupported sbr mode 2389 return BAD_VALUE; 2390 } 2391 2392 2393 err = mOMX->setParameter( 2394 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 2395 2396 if (err != OK) { 2397 return err; 2398 } 2399 2400 return err; 2401 } 2402 2403 OMX_AUDIO_PARAM_AACPROFILETYPE profile; 2404 InitOMXParams(&profile); 2405 profile.nPortIndex = kPortIndexInput; 2406 2407 err = mOMX->getParameter( 2408 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 2409 2410 if (err != OK) { 2411 return err; 2412 } 2413 2414 profile.nChannels = numChannels; 2415 profile.nSampleRate = sampleRate; 2416 2417 profile.eAACStreamFormat = 2418 isADTS 2419 ? OMX_AUDIO_AACStreamFormatMP4ADTS 2420 : OMX_AUDIO_AACStreamFormatMP4FF; 2421 2422 OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE presentation; 2423 presentation.nMaxOutputChannels = maxOutputChannelCount; 2424 presentation.nDrcCut = drc.drcCut; 2425 presentation.nDrcBoost = drc.drcBoost; 2426 presentation.nHeavyCompression = drc.heavyCompression; 2427 presentation.nTargetReferenceLevel = drc.targetRefLevel; 2428 presentation.nEncodedTargetLevel = drc.encodedTargetLevel; 2429 presentation.nPCMLimiterEnable = pcmLimiterEnable; 2430 2431 status_t res = mOMX->setParameter(mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 2432 if (res == OK) { 2433 // optional parameters, will not cause configuration failure 2434 mOMX->setParameter(mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacPresentation, 2435 &presentation, sizeof(presentation)); 2436 } else { 2437 ALOGW("did not set AudioAndroidAacPresentation due to error %d when setting AudioAac", res); 2438 } 2439 return res; 2440} 2441 2442status_t ACodec::setupAC3Codec( 2443 bool encoder, int32_t numChannels, int32_t sampleRate) { 2444 status_t err = setupRawAudioFormat( 2445 encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels); 2446 2447 if (err != OK) { 2448 return err; 2449 } 2450 2451 if (encoder) { 2452 ALOGW("AC3 encoding is not supported."); 2453 return INVALID_OPERATION; 2454 } 2455 2456 OMX_AUDIO_PARAM_ANDROID_AC3TYPE def; 2457 InitOMXParams(&def); 2458 def.nPortIndex = kPortIndexInput; 2459 2460 err = mOMX->getParameter( 2461 mNode, 2462 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, 2463 &def, 2464 sizeof(def)); 2465 2466 if (err != OK) { 2467 return err; 2468 } 2469 2470 def.nChannels = numChannels; 2471 def.nSampleRate = sampleRate; 2472 2473 return mOMX->setParameter( 2474 mNode, 2475 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, 2476 &def, 2477 sizeof(def)); 2478} 2479 2480status_t ACodec::setupEAC3Codec( 2481 bool encoder, int32_t numChannels, int32_t sampleRate) { 2482 status_t err = setupRawAudioFormat( 2483 encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels); 2484 2485 if (err != OK) { 2486 return err; 2487 } 2488 2489 if (encoder) { 2490 ALOGW("EAC3 encoding is not supported."); 2491 return INVALID_OPERATION; 2492 } 2493 2494 OMX_AUDIO_PARAM_ANDROID_EAC3TYPE def; 2495 InitOMXParams(&def); 2496 def.nPortIndex = kPortIndexInput; 2497 2498 err = mOMX->getParameter( 2499 mNode, 2500 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, 2501 &def, 2502 sizeof(def)); 2503 2504 if (err != OK) { 2505 return err; 2506 } 2507 2508 def.nChannels = numChannels; 2509 def.nSampleRate = sampleRate; 2510 2511 return mOMX->setParameter( 2512 mNode, 2513 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, 2514 &def, 2515 sizeof(def)); 2516} 2517 2518static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate( 2519 bool isAMRWB, int32_t bps) { 2520 if (isAMRWB) { 2521 if (bps <= 6600) { 2522 return OMX_AUDIO_AMRBandModeWB0; 2523 } else if (bps <= 8850) { 2524 return OMX_AUDIO_AMRBandModeWB1; 2525 } else if (bps <= 12650) { 2526 return OMX_AUDIO_AMRBandModeWB2; 2527 } else if (bps <= 14250) { 2528 return OMX_AUDIO_AMRBandModeWB3; 2529 } else if (bps <= 15850) { 2530 return OMX_AUDIO_AMRBandModeWB4; 2531 } else if (bps <= 18250) { 2532 return OMX_AUDIO_AMRBandModeWB5; 2533 } else if (bps <= 19850) { 2534 return OMX_AUDIO_AMRBandModeWB6; 2535 } else if (bps <= 23050) { 2536 return OMX_AUDIO_AMRBandModeWB7; 2537 } 2538 2539 // 23850 bps 2540 return OMX_AUDIO_AMRBandModeWB8; 2541 } else { // AMRNB 2542 if (bps <= 4750) { 2543 return OMX_AUDIO_AMRBandModeNB0; 2544 } else if (bps <= 5150) { 2545 return OMX_AUDIO_AMRBandModeNB1; 2546 } else if (bps <= 5900) { 2547 return OMX_AUDIO_AMRBandModeNB2; 2548 } else if (bps <= 6700) { 2549 return OMX_AUDIO_AMRBandModeNB3; 2550 } else if (bps <= 7400) { 2551 return OMX_AUDIO_AMRBandModeNB4; 2552 } else if (bps <= 7950) { 2553 return OMX_AUDIO_AMRBandModeNB5; 2554 } else if (bps <= 10200) { 2555 return OMX_AUDIO_AMRBandModeNB6; 2556 } 2557 2558 // 12200 bps 2559 return OMX_AUDIO_AMRBandModeNB7; 2560 } 2561} 2562 2563status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) { 2564 OMX_AUDIO_PARAM_AMRTYPE def; 2565 InitOMXParams(&def); 2566 def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput; 2567 2568 status_t err = 2569 mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); 2570 2571 if (err != OK) { 2572 return err; 2573 } 2574 2575 def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF; 2576 def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate); 2577 2578 err = mOMX->setParameter( 2579 mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); 2580 2581 if (err != OK) { 2582 return err; 2583 } 2584 2585 return setupRawAudioFormat( 2586 encoder ? kPortIndexInput : kPortIndexOutput, 2587 isWAMR ? 16000 : 8000 /* sampleRate */, 2588 1 /* numChannels */); 2589} 2590 2591status_t ACodec::setupG711Codec(bool encoder, int32_t sampleRate, int32_t numChannels) { 2592 if (encoder) { 2593 return INVALID_OPERATION; 2594 } 2595 2596 return setupRawAudioFormat( 2597 kPortIndexInput, sampleRate, numChannels); 2598} 2599 2600status_t ACodec::setupFlacCodec( 2601 bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel) { 2602 2603 if (encoder) { 2604 OMX_AUDIO_PARAM_FLACTYPE def; 2605 InitOMXParams(&def); 2606 def.nPortIndex = kPortIndexOutput; 2607 2608 // configure compression level 2609 status_t err = mOMX->getParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def)); 2610 if (err != OK) { 2611 ALOGE("setupFlacCodec(): Error %d getting OMX_IndexParamAudioFlac parameter", err); 2612 return err; 2613 } 2614 def.nCompressionLevel = compressionLevel; 2615 err = mOMX->setParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def)); 2616 if (err != OK) { 2617 ALOGE("setupFlacCodec(): Error %d setting OMX_IndexParamAudioFlac parameter", err); 2618 return err; 2619 } 2620 } 2621 2622 return setupRawAudioFormat( 2623 encoder ? kPortIndexInput : kPortIndexOutput, 2624 sampleRate, 2625 numChannels); 2626} 2627 2628status_t ACodec::setupRawAudioFormat( 2629 OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) { 2630 OMX_PARAM_PORTDEFINITIONTYPE def; 2631 InitOMXParams(&def); 2632 def.nPortIndex = portIndex; 2633 2634 status_t err = mOMX->getParameter( 2635 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2636 2637 if (err != OK) { 2638 return err; 2639 } 2640 2641 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; 2642 2643 err = mOMX->setParameter( 2644 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2645 2646 if (err != OK) { 2647 return err; 2648 } 2649 2650 OMX_AUDIO_PARAM_PCMMODETYPE pcmParams; 2651 InitOMXParams(&pcmParams); 2652 pcmParams.nPortIndex = portIndex; 2653 2654 err = mOMX->getParameter( 2655 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); 2656 2657 if (err != OK) { 2658 return err; 2659 } 2660 2661 pcmParams.nChannels = numChannels; 2662 pcmParams.eNumData = OMX_NumericalDataSigned; 2663 pcmParams.bInterleaved = OMX_TRUE; 2664 pcmParams.nBitPerSample = 16; 2665 pcmParams.nSamplingRate = sampleRate; 2666 pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear; 2667 2668 if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) { 2669 return OMX_ErrorNone; 2670 } 2671 2672 return mOMX->setParameter( 2673 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); 2674} 2675 2676status_t ACodec::configureTunneledVideoPlayback( 2677 int32_t audioHwSync, const sp<ANativeWindow> &nativeWindow) { 2678 native_handle_t* sidebandHandle; 2679 2680 status_t err = mOMX->configureVideoTunnelMode( 2681 mNode, kPortIndexOutput, OMX_TRUE, audioHwSync, &sidebandHandle); 2682 if (err != OK) { 2683 ALOGE("configureVideoTunnelMode failed! (err %d).", err); 2684 return err; 2685 } 2686 2687 err = native_window_set_sideband_stream(nativeWindow.get(), sidebandHandle); 2688 if (err != OK) { 2689 ALOGE("native_window_set_sideband_stream(%p) failed! (err %d).", 2690 sidebandHandle, err); 2691 return err; 2692 } 2693 2694 return OK; 2695} 2696 2697status_t ACodec::setVideoPortFormatType( 2698 OMX_U32 portIndex, 2699 OMX_VIDEO_CODINGTYPE compressionFormat, 2700 OMX_COLOR_FORMATTYPE colorFormat, 2701 bool usingNativeBuffers) { 2702 OMX_VIDEO_PARAM_PORTFORMATTYPE format; 2703 InitOMXParams(&format); 2704 format.nPortIndex = portIndex; 2705 format.nIndex = 0; 2706 bool found = false; 2707 2708 OMX_U32 index = 0; 2709 for (;;) { 2710 format.nIndex = index; 2711 status_t err = mOMX->getParameter( 2712 mNode, OMX_IndexParamVideoPortFormat, 2713 &format, sizeof(format)); 2714 2715 if (err != OK) { 2716 return err; 2717 } 2718 2719 // substitute back flexible color format to codec supported format 2720 OMX_U32 flexibleEquivalent; 2721 if (compressionFormat == OMX_VIDEO_CodingUnused 2722 && isFlexibleColorFormat( 2723 mOMX, mNode, format.eColorFormat, usingNativeBuffers, &flexibleEquivalent) 2724 && colorFormat == flexibleEquivalent) { 2725 ALOGI("[%s] using color format %#x in place of %#x", 2726 mComponentName.c_str(), format.eColorFormat, colorFormat); 2727 colorFormat = format.eColorFormat; 2728 } 2729 2730 // The following assertion is violated by TI's video decoder. 2731 // CHECK_EQ(format.nIndex, index); 2732 2733 if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) { 2734 if (portIndex == kPortIndexInput 2735 && colorFormat == format.eColorFormat) { 2736 // eCompressionFormat does not seem right. 2737 found = true; 2738 break; 2739 } 2740 if (portIndex == kPortIndexOutput 2741 && compressionFormat == format.eCompressionFormat) { 2742 // eColorFormat does not seem right. 2743 found = true; 2744 break; 2745 } 2746 } 2747 2748 if (format.eCompressionFormat == compressionFormat 2749 && format.eColorFormat == colorFormat) { 2750 found = true; 2751 break; 2752 } 2753 2754 ++index; 2755 } 2756 2757 if (!found) { 2758 return UNKNOWN_ERROR; 2759 } 2760 2761 status_t err = mOMX->setParameter( 2762 mNode, OMX_IndexParamVideoPortFormat, 2763 &format, sizeof(format)); 2764 2765 return err; 2766} 2767 2768// Set optimal output format. OMX component lists output formats in the order 2769// of preference, but this got more complicated since the introduction of flexible 2770// YUV formats. We support a legacy behavior for applications that do not use 2771// surface output, do not specify an output format, but expect a "usable" standard 2772// OMX format. SW readable and standard formats must be flex-YUV. 2773// 2774// Suggested preference order: 2775// - optimal format for texture rendering (mediaplayer behavior) 2776// - optimal SW readable & texture renderable format (flex-YUV support) 2777// - optimal SW readable non-renderable format (flex-YUV bytebuffer support) 2778// - legacy "usable" standard formats 2779// 2780// For legacy support, we prefer a standard format, but will settle for a SW readable 2781// flex-YUV format. 2782status_t ACodec::setSupportedOutputFormat(bool getLegacyFlexibleFormat) { 2783 OMX_VIDEO_PARAM_PORTFORMATTYPE format, legacyFormat; 2784 InitOMXParams(&format); 2785 format.nPortIndex = kPortIndexOutput; 2786 2787 InitOMXParams(&legacyFormat); 2788 // this field will change when we find a suitable legacy format 2789 legacyFormat.eColorFormat = OMX_COLOR_FormatUnused; 2790 2791 for (OMX_U32 index = 0; ; ++index) { 2792 format.nIndex = index; 2793 status_t err = mOMX->getParameter( 2794 mNode, OMX_IndexParamVideoPortFormat, 2795 &format, sizeof(format)); 2796 if (err != OK) { 2797 // no more formats, pick legacy format if found 2798 if (legacyFormat.eColorFormat != OMX_COLOR_FormatUnused) { 2799 memcpy(&format, &legacyFormat, sizeof(format)); 2800 break; 2801 } 2802 return err; 2803 } 2804 if (format.eCompressionFormat != OMX_VIDEO_CodingUnused) { 2805 return OMX_ErrorBadParameter; 2806 } 2807 if (!getLegacyFlexibleFormat) { 2808 break; 2809 } 2810 // standard formats that were exposed to users before 2811 if (format.eColorFormat == OMX_COLOR_FormatYUV420Planar 2812 || format.eColorFormat == OMX_COLOR_FormatYUV420PackedPlanar 2813 || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar 2814 || format.eColorFormat == OMX_COLOR_FormatYUV420PackedSemiPlanar 2815 || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar) { 2816 break; 2817 } 2818 // find best legacy non-standard format 2819 OMX_U32 flexibleEquivalent; 2820 if (legacyFormat.eColorFormat == OMX_COLOR_FormatUnused 2821 && isFlexibleColorFormat( 2822 mOMX, mNode, format.eColorFormat, false /* usingNativeBuffers */, 2823 &flexibleEquivalent) 2824 && flexibleEquivalent == OMX_COLOR_FormatYUV420Flexible) { 2825 memcpy(&legacyFormat, &format, sizeof(format)); 2826 } 2827 } 2828 return mOMX->setParameter( 2829 mNode, OMX_IndexParamVideoPortFormat, 2830 &format, sizeof(format)); 2831} 2832 2833static const struct VideoCodingMapEntry { 2834 const char *mMime; 2835 OMX_VIDEO_CODINGTYPE mVideoCodingType; 2836} kVideoCodingMapEntry[] = { 2837 { MEDIA_MIMETYPE_VIDEO_AVC, OMX_VIDEO_CodingAVC }, 2838 { MEDIA_MIMETYPE_VIDEO_HEVC, OMX_VIDEO_CodingHEVC }, 2839 { MEDIA_MIMETYPE_VIDEO_MPEG4, OMX_VIDEO_CodingMPEG4 }, 2840 { MEDIA_MIMETYPE_VIDEO_H263, OMX_VIDEO_CodingH263 }, 2841 { MEDIA_MIMETYPE_VIDEO_MPEG2, OMX_VIDEO_CodingMPEG2 }, 2842 { MEDIA_MIMETYPE_VIDEO_VP8, OMX_VIDEO_CodingVP8 }, 2843 { MEDIA_MIMETYPE_VIDEO_VP9, OMX_VIDEO_CodingVP9 }, 2844}; 2845 2846static status_t GetVideoCodingTypeFromMime( 2847 const char *mime, OMX_VIDEO_CODINGTYPE *codingType) { 2848 for (size_t i = 0; 2849 i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]); 2850 ++i) { 2851 if (!strcasecmp(mime, kVideoCodingMapEntry[i].mMime)) { 2852 *codingType = kVideoCodingMapEntry[i].mVideoCodingType; 2853 return OK; 2854 } 2855 } 2856 2857 *codingType = OMX_VIDEO_CodingUnused; 2858 2859 return ERROR_UNSUPPORTED; 2860} 2861 2862static status_t GetMimeTypeForVideoCoding( 2863 OMX_VIDEO_CODINGTYPE codingType, AString *mime) { 2864 for (size_t i = 0; 2865 i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]); 2866 ++i) { 2867 if (codingType == kVideoCodingMapEntry[i].mVideoCodingType) { 2868 *mime = kVideoCodingMapEntry[i].mMime; 2869 return OK; 2870 } 2871 } 2872 2873 mime->clear(); 2874 2875 return ERROR_UNSUPPORTED; 2876} 2877 2878status_t ACodec::setupVideoDecoder( 2879 const char *mime, const sp<AMessage> &msg, bool haveNativeWindow) { 2880 int32_t width, height; 2881 if (!msg->findInt32("width", &width) 2882 || !msg->findInt32("height", &height)) { 2883 return INVALID_OPERATION; 2884 } 2885 2886 OMX_VIDEO_CODINGTYPE compressionFormat; 2887 status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat); 2888 2889 if (err != OK) { 2890 return err; 2891 } 2892 2893 err = setVideoPortFormatType( 2894 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused); 2895 2896 if (err != OK) { 2897 return err; 2898 } 2899 2900 int32_t tmp; 2901 if (msg->findInt32("color-format", &tmp)) { 2902 OMX_COLOR_FORMATTYPE colorFormat = 2903 static_cast<OMX_COLOR_FORMATTYPE>(tmp); 2904 err = setVideoPortFormatType( 2905 kPortIndexOutput, OMX_VIDEO_CodingUnused, colorFormat, haveNativeWindow); 2906 if (err != OK) { 2907 ALOGW("[%s] does not support color format %d", 2908 mComponentName.c_str(), colorFormat); 2909 err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */); 2910 } 2911 } else { 2912 err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */); 2913 } 2914 2915 if (err != OK) { 2916 return err; 2917 } 2918 2919 int32_t frameRateInt; 2920 float frameRateFloat; 2921 if (!msg->findFloat("frame-rate", &frameRateFloat)) { 2922 if (!msg->findInt32("frame-rate", &frameRateInt)) { 2923 frameRateInt = -1; 2924 } 2925 frameRateFloat = (float)frameRateInt; 2926 } 2927 2928 err = setVideoFormatOnPort( 2929 kPortIndexInput, width, height, compressionFormat, frameRateFloat); 2930 2931 if (err != OK) { 2932 return err; 2933 } 2934 2935 err = setVideoFormatOnPort( 2936 kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused); 2937 2938 if (err != OK) { 2939 return err; 2940 } 2941 2942 return OK; 2943} 2944 2945status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) { 2946 int32_t tmp; 2947 if (!msg->findInt32("color-format", &tmp)) { 2948 return INVALID_OPERATION; 2949 } 2950 2951 OMX_COLOR_FORMATTYPE colorFormat = 2952 static_cast<OMX_COLOR_FORMATTYPE>(tmp); 2953 2954 status_t err = setVideoPortFormatType( 2955 kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat); 2956 2957 if (err != OK) { 2958 ALOGE("[%s] does not support color format %d", 2959 mComponentName.c_str(), colorFormat); 2960 2961 return err; 2962 } 2963 2964 /* Input port configuration */ 2965 2966 OMX_PARAM_PORTDEFINITIONTYPE def; 2967 InitOMXParams(&def); 2968 2969 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 2970 2971 def.nPortIndex = kPortIndexInput; 2972 2973 err = mOMX->getParameter( 2974 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2975 2976 if (err != OK) { 2977 return err; 2978 } 2979 2980 int32_t width, height, bitrate; 2981 if (!msg->findInt32("width", &width) 2982 || !msg->findInt32("height", &height) 2983 || !msg->findInt32("bitrate", &bitrate)) { 2984 return INVALID_OPERATION; 2985 } 2986 2987 video_def->nFrameWidth = width; 2988 video_def->nFrameHeight = height; 2989 2990 int32_t stride; 2991 if (!msg->findInt32("stride", &stride)) { 2992 stride = width; 2993 } 2994 2995 video_def->nStride = stride; 2996 2997 int32_t sliceHeight; 2998 if (!msg->findInt32("slice-height", &sliceHeight)) { 2999 sliceHeight = height; 3000 } 3001 3002 video_def->nSliceHeight = sliceHeight; 3003 3004 def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2; 3005 3006 float frameRate; 3007 if (!msg->findFloat("frame-rate", &frameRate)) { 3008 int32_t tmp; 3009 if (!msg->findInt32("frame-rate", &tmp)) { 3010 return INVALID_OPERATION; 3011 } 3012 frameRate = (float)tmp; 3013 mTimePerFrameUs = (int64_t) (1000000.0f / frameRate); 3014 } 3015 3016 video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f); 3017 video_def->eCompressionFormat = OMX_VIDEO_CodingUnused; 3018 // this is redundant as it was already set up in setVideoPortFormatType 3019 // FIXME for now skip this only for flexible YUV formats 3020 if (colorFormat != OMX_COLOR_FormatYUV420Flexible) { 3021 video_def->eColorFormat = colorFormat; 3022 } 3023 3024 err = mOMX->setParameter( 3025 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 3026 3027 if (err != OK) { 3028 ALOGE("[%s] failed to set input port definition parameters.", 3029 mComponentName.c_str()); 3030 3031 return err; 3032 } 3033 3034 /* Output port configuration */ 3035 3036 OMX_VIDEO_CODINGTYPE compressionFormat; 3037 err = GetVideoCodingTypeFromMime(mime, &compressionFormat); 3038 3039 if (err != OK) { 3040 return err; 3041 } 3042 3043 err = setVideoPortFormatType( 3044 kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused); 3045 3046 if (err != OK) { 3047 ALOGE("[%s] does not support compression format %d", 3048 mComponentName.c_str(), compressionFormat); 3049 3050 return err; 3051 } 3052 3053 def.nPortIndex = kPortIndexOutput; 3054 3055 err = mOMX->getParameter( 3056 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 3057 3058 if (err != OK) { 3059 return err; 3060 } 3061 3062 video_def->nFrameWidth = width; 3063 video_def->nFrameHeight = height; 3064 video_def->xFramerate = 0; 3065 video_def->nBitrate = bitrate; 3066 video_def->eCompressionFormat = compressionFormat; 3067 video_def->eColorFormat = OMX_COLOR_FormatUnused; 3068 3069 err = mOMX->setParameter( 3070 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 3071 3072 if (err != OK) { 3073 ALOGE("[%s] failed to set output port definition parameters.", 3074 mComponentName.c_str()); 3075 3076 return err; 3077 } 3078 3079 switch (compressionFormat) { 3080 case OMX_VIDEO_CodingMPEG4: 3081 err = setupMPEG4EncoderParameters(msg); 3082 break; 3083 3084 case OMX_VIDEO_CodingH263: 3085 err = setupH263EncoderParameters(msg); 3086 break; 3087 3088 case OMX_VIDEO_CodingAVC: 3089 err = setupAVCEncoderParameters(msg); 3090 break; 3091 3092 case OMX_VIDEO_CodingHEVC: 3093 err = setupHEVCEncoderParameters(msg); 3094 break; 3095 3096 case OMX_VIDEO_CodingVP8: 3097 case OMX_VIDEO_CodingVP9: 3098 err = setupVPXEncoderParameters(msg); 3099 break; 3100 3101 default: 3102 break; 3103 } 3104 3105 if (err == OK) { 3106 ALOGI("setupVideoEncoder succeeded"); 3107 } 3108 3109 return err; 3110} 3111 3112status_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) { 3113 OMX_VIDEO_PARAM_INTRAREFRESHTYPE params; 3114 InitOMXParams(¶ms); 3115 params.nPortIndex = kPortIndexOutput; 3116 3117 params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode); 3118 3119 if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic || 3120 params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) { 3121 int32_t mbs; 3122 if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) { 3123 return INVALID_OPERATION; 3124 } 3125 params.nCirMBs = mbs; 3126 } 3127 3128 if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive || 3129 params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) { 3130 int32_t mbs; 3131 if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) { 3132 return INVALID_OPERATION; 3133 } 3134 params.nAirMBs = mbs; 3135 3136 int32_t ref; 3137 if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) { 3138 return INVALID_OPERATION; 3139 } 3140 params.nAirRef = ref; 3141 } 3142 3143 status_t err = mOMX->setParameter( 3144 mNode, OMX_IndexParamVideoIntraRefresh, 3145 ¶ms, sizeof(params)); 3146 return err; 3147} 3148 3149static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) { 3150 if (iFramesInterval < 0) { 3151 return 0xFFFFFFFF; 3152 } else if (iFramesInterval == 0) { 3153 return 0; 3154 } 3155 OMX_U32 ret = frameRate * iFramesInterval; 3156 return ret; 3157} 3158 3159static OMX_VIDEO_CONTROLRATETYPE getBitrateMode(const sp<AMessage> &msg) { 3160 int32_t tmp; 3161 if (!msg->findInt32("bitrate-mode", &tmp)) { 3162 return OMX_Video_ControlRateVariable; 3163 } 3164 3165 return static_cast<OMX_VIDEO_CONTROLRATETYPE>(tmp); 3166} 3167 3168status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) { 3169 int32_t bitrate, iFrameInterval; 3170 if (!msg->findInt32("bitrate", &bitrate) 3171 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 3172 return INVALID_OPERATION; 3173 } 3174 3175 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 3176 3177 float frameRate; 3178 if (!msg->findFloat("frame-rate", &frameRate)) { 3179 int32_t tmp; 3180 if (!msg->findInt32("frame-rate", &tmp)) { 3181 return INVALID_OPERATION; 3182 } 3183 frameRate = (float)tmp; 3184 } 3185 3186 OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type; 3187 InitOMXParams(&mpeg4type); 3188 mpeg4type.nPortIndex = kPortIndexOutput; 3189 3190 status_t err = mOMX->getParameter( 3191 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); 3192 3193 if (err != OK) { 3194 return err; 3195 } 3196 3197 mpeg4type.nSliceHeaderSpacing = 0; 3198 mpeg4type.bSVH = OMX_FALSE; 3199 mpeg4type.bGov = OMX_FALSE; 3200 3201 mpeg4type.nAllowedPictureTypes = 3202 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 3203 3204 mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 3205 if (mpeg4type.nPFrames == 0) { 3206 mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 3207 } 3208 mpeg4type.nBFrames = 0; 3209 mpeg4type.nIDCVLCThreshold = 0; 3210 mpeg4type.bACPred = OMX_TRUE; 3211 mpeg4type.nMaxPacketSize = 256; 3212 mpeg4type.nTimeIncRes = 1000; 3213 mpeg4type.nHeaderExtension = 0; 3214 mpeg4type.bReversibleVLC = OMX_FALSE; 3215 3216 int32_t profile; 3217 if (msg->findInt32("profile", &profile)) { 3218 int32_t level; 3219 if (!msg->findInt32("level", &level)) { 3220 return INVALID_OPERATION; 3221 } 3222 3223 err = verifySupportForProfileAndLevel(profile, level); 3224 3225 if (err != OK) { 3226 return err; 3227 } 3228 3229 mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile); 3230 mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level); 3231 } 3232 3233 err = mOMX->setParameter( 3234 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); 3235 3236 if (err != OK) { 3237 return err; 3238 } 3239 3240 err = configureBitrate(bitrate, bitrateMode); 3241 3242 if (err != OK) { 3243 return err; 3244 } 3245 3246 return setupErrorCorrectionParameters(); 3247} 3248 3249status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) { 3250 int32_t bitrate, iFrameInterval; 3251 if (!msg->findInt32("bitrate", &bitrate) 3252 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 3253 return INVALID_OPERATION; 3254 } 3255 3256 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 3257 3258 float frameRate; 3259 if (!msg->findFloat("frame-rate", &frameRate)) { 3260 int32_t tmp; 3261 if (!msg->findInt32("frame-rate", &tmp)) { 3262 return INVALID_OPERATION; 3263 } 3264 frameRate = (float)tmp; 3265 } 3266 3267 OMX_VIDEO_PARAM_H263TYPE h263type; 3268 InitOMXParams(&h263type); 3269 h263type.nPortIndex = kPortIndexOutput; 3270 3271 status_t err = mOMX->getParameter( 3272 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); 3273 3274 if (err != OK) { 3275 return err; 3276 } 3277 3278 h263type.nAllowedPictureTypes = 3279 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 3280 3281 h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 3282 if (h263type.nPFrames == 0) { 3283 h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 3284 } 3285 h263type.nBFrames = 0; 3286 3287 int32_t profile; 3288 if (msg->findInt32("profile", &profile)) { 3289 int32_t level; 3290 if (!msg->findInt32("level", &level)) { 3291 return INVALID_OPERATION; 3292 } 3293 3294 err = verifySupportForProfileAndLevel(profile, level); 3295 3296 if (err != OK) { 3297 return err; 3298 } 3299 3300 h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile); 3301 h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level); 3302 } 3303 3304 h263type.bPLUSPTYPEAllowed = OMX_FALSE; 3305 h263type.bForceRoundingTypeToZero = OMX_FALSE; 3306 h263type.nPictureHeaderRepetition = 0; 3307 h263type.nGOBHeaderInterval = 0; 3308 3309 err = mOMX->setParameter( 3310 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); 3311 3312 if (err != OK) { 3313 return err; 3314 } 3315 3316 err = configureBitrate(bitrate, bitrateMode); 3317 3318 if (err != OK) { 3319 return err; 3320 } 3321 3322 return setupErrorCorrectionParameters(); 3323} 3324 3325// static 3326int /* OMX_VIDEO_AVCLEVELTYPE */ ACodec::getAVCLevelFor( 3327 int width, int height, int rate, int bitrate, 3328 OMX_VIDEO_AVCPROFILETYPE profile) { 3329 // convert bitrate to main/baseline profile kbps equivalent 3330 switch (profile) { 3331 case OMX_VIDEO_AVCProfileHigh10: 3332 bitrate = divUp(bitrate, 3000); break; 3333 case OMX_VIDEO_AVCProfileHigh: 3334 bitrate = divUp(bitrate, 1250); break; 3335 default: 3336 bitrate = divUp(bitrate, 1000); break; 3337 } 3338 3339 // convert size and rate to MBs 3340 width = divUp(width, 16); 3341 height = divUp(height, 16); 3342 int mbs = width * height; 3343 rate *= mbs; 3344 int maxDimension = max(width, height); 3345 3346 static const int limits[][5] = { 3347 /* MBps MB dim bitrate level */ 3348 { 1485, 99, 28, 64, OMX_VIDEO_AVCLevel1 }, 3349 { 1485, 99, 28, 128, OMX_VIDEO_AVCLevel1b }, 3350 { 3000, 396, 56, 192, OMX_VIDEO_AVCLevel11 }, 3351 { 6000, 396, 56, 384, OMX_VIDEO_AVCLevel12 }, 3352 { 11880, 396, 56, 768, OMX_VIDEO_AVCLevel13 }, 3353 { 11880, 396, 56, 2000, OMX_VIDEO_AVCLevel2 }, 3354 { 19800, 792, 79, 4000, OMX_VIDEO_AVCLevel21 }, 3355 { 20250, 1620, 113, 4000, OMX_VIDEO_AVCLevel22 }, 3356 { 40500, 1620, 113, 10000, OMX_VIDEO_AVCLevel3 }, 3357 { 108000, 3600, 169, 14000, OMX_VIDEO_AVCLevel31 }, 3358 { 216000, 5120, 202, 20000, OMX_VIDEO_AVCLevel32 }, 3359 { 245760, 8192, 256, 20000, OMX_VIDEO_AVCLevel4 }, 3360 { 245760, 8192, 256, 50000, OMX_VIDEO_AVCLevel41 }, 3361 { 522240, 8704, 263, 50000, OMX_VIDEO_AVCLevel42 }, 3362 { 589824, 22080, 420, 135000, OMX_VIDEO_AVCLevel5 }, 3363 { 983040, 36864, 543, 240000, OMX_VIDEO_AVCLevel51 }, 3364 { 2073600, 36864, 543, 240000, OMX_VIDEO_AVCLevel52 }, 3365 }; 3366 3367 for (size_t i = 0; i < ARRAY_SIZE(limits); i++) { 3368 const int (&limit)[5] = limits[i]; 3369 if (rate <= limit[0] && mbs <= limit[1] && maxDimension <= limit[2] 3370 && bitrate <= limit[3]) { 3371 return limit[4]; 3372 } 3373 } 3374 return 0; 3375} 3376 3377status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) { 3378 int32_t bitrate, iFrameInterval; 3379 if (!msg->findInt32("bitrate", &bitrate) 3380 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 3381 return INVALID_OPERATION; 3382 } 3383 3384 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 3385 3386 float frameRate; 3387 if (!msg->findFloat("frame-rate", &frameRate)) { 3388 int32_t tmp; 3389 if (!msg->findInt32("frame-rate", &tmp)) { 3390 return INVALID_OPERATION; 3391 } 3392 frameRate = (float)tmp; 3393 } 3394 3395 status_t err = OK; 3396 int32_t intraRefreshMode = 0; 3397 if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) { 3398 err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode); 3399 if (err != OK) { 3400 ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x", 3401 err, intraRefreshMode); 3402 return err; 3403 } 3404 } 3405 3406 OMX_VIDEO_PARAM_AVCTYPE h264type; 3407 InitOMXParams(&h264type); 3408 h264type.nPortIndex = kPortIndexOutput; 3409 3410 err = mOMX->getParameter( 3411 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 3412 3413 if (err != OK) { 3414 return err; 3415 } 3416 3417 h264type.nAllowedPictureTypes = 3418 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 3419 3420 int32_t profile; 3421 if (msg->findInt32("profile", &profile)) { 3422 int32_t level; 3423 if (!msg->findInt32("level", &level)) { 3424 return INVALID_OPERATION; 3425 } 3426 3427 err = verifySupportForProfileAndLevel(profile, level); 3428 3429 if (err != OK) { 3430 return err; 3431 } 3432 3433 h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile); 3434 h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level); 3435 } 3436 3437 // XXX 3438 if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) { 3439 ALOGW("Use baseline profile instead of %d for AVC recording", 3440 h264type.eProfile); 3441 h264type.eProfile = OMX_VIDEO_AVCProfileBaseline; 3442 } 3443 3444 if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) { 3445 h264type.nSliceHeaderSpacing = 0; 3446 h264type.bUseHadamard = OMX_TRUE; 3447 h264type.nRefFrames = 1; 3448 h264type.nBFrames = 0; 3449 h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 3450 if (h264type.nPFrames == 0) { 3451 h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 3452 } 3453 h264type.nRefIdx10ActiveMinus1 = 0; 3454 h264type.nRefIdx11ActiveMinus1 = 0; 3455 h264type.bEntropyCodingCABAC = OMX_FALSE; 3456 h264type.bWeightedPPrediction = OMX_FALSE; 3457 h264type.bconstIpred = OMX_FALSE; 3458 h264type.bDirect8x8Inference = OMX_FALSE; 3459 h264type.bDirectSpatialTemporal = OMX_FALSE; 3460 h264type.nCabacInitIdc = 0; 3461 } 3462 3463 if (h264type.nBFrames != 0) { 3464 h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB; 3465 } 3466 3467 h264type.bEnableUEP = OMX_FALSE; 3468 h264type.bEnableFMO = OMX_FALSE; 3469 h264type.bEnableASO = OMX_FALSE; 3470 h264type.bEnableRS = OMX_FALSE; 3471 h264type.bFrameMBsOnly = OMX_TRUE; 3472 h264type.bMBAFF = OMX_FALSE; 3473 h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; 3474 3475 err = mOMX->setParameter( 3476 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 3477 3478 if (err != OK) { 3479 return err; 3480 } 3481 3482 return configureBitrate(bitrate, bitrateMode); 3483} 3484 3485status_t ACodec::setupHEVCEncoderParameters(const sp<AMessage> &msg) { 3486 int32_t bitrate, iFrameInterval; 3487 if (!msg->findInt32("bitrate", &bitrate) 3488 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 3489 return INVALID_OPERATION; 3490 } 3491 3492 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 3493 3494 float frameRate; 3495 if (!msg->findFloat("frame-rate", &frameRate)) { 3496 int32_t tmp; 3497 if (!msg->findInt32("frame-rate", &tmp)) { 3498 return INVALID_OPERATION; 3499 } 3500 frameRate = (float)tmp; 3501 } 3502 3503 OMX_VIDEO_PARAM_HEVCTYPE hevcType; 3504 InitOMXParams(&hevcType); 3505 hevcType.nPortIndex = kPortIndexOutput; 3506 3507 status_t err = OK; 3508 err = mOMX->getParameter( 3509 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType)); 3510 if (err != OK) { 3511 return err; 3512 } 3513 3514 int32_t profile; 3515 if (msg->findInt32("profile", &profile)) { 3516 int32_t level; 3517 if (!msg->findInt32("level", &level)) { 3518 return INVALID_OPERATION; 3519 } 3520 3521 err = verifySupportForProfileAndLevel(profile, level); 3522 if (err != OK) { 3523 return err; 3524 } 3525 3526 hevcType.eProfile = static_cast<OMX_VIDEO_HEVCPROFILETYPE>(profile); 3527 hevcType.eLevel = static_cast<OMX_VIDEO_HEVCLEVELTYPE>(level); 3528 } 3529 3530 // TODO: Need OMX structure definition for setting iFrameInterval 3531 3532 err = mOMX->setParameter( 3533 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType)); 3534 if (err != OK) { 3535 return err; 3536 } 3537 3538 return configureBitrate(bitrate, bitrateMode); 3539} 3540 3541status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg) { 3542 int32_t bitrate; 3543 int32_t iFrameInterval = 0; 3544 size_t tsLayers = 0; 3545 OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE pattern = 3546 OMX_VIDEO_VPXTemporalLayerPatternNone; 3547 static const uint32_t kVp8LayerRateAlloction 3548 [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] 3549 [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] = { 3550 {100, 100, 100}, // 1 layer 3551 { 60, 100, 100}, // 2 layers {60%, 40%} 3552 { 40, 60, 100}, // 3 layers {40%, 20%, 40%} 3553 }; 3554 if (!msg->findInt32("bitrate", &bitrate)) { 3555 return INVALID_OPERATION; 3556 } 3557 msg->findInt32("i-frame-interval", &iFrameInterval); 3558 3559 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 3560 3561 float frameRate; 3562 if (!msg->findFloat("frame-rate", &frameRate)) { 3563 int32_t tmp; 3564 if (!msg->findInt32("frame-rate", &tmp)) { 3565 return INVALID_OPERATION; 3566 } 3567 frameRate = (float)tmp; 3568 } 3569 3570 AString tsSchema; 3571 if (msg->findString("ts-schema", &tsSchema)) { 3572 if (tsSchema == "webrtc.vp8.1-layer") { 3573 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC; 3574 tsLayers = 1; 3575 } else if (tsSchema == "webrtc.vp8.2-layer") { 3576 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC; 3577 tsLayers = 2; 3578 } else if (tsSchema == "webrtc.vp8.3-layer") { 3579 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC; 3580 tsLayers = 3; 3581 } else { 3582 ALOGW("Unsupported ts-schema [%s]", tsSchema.c_str()); 3583 } 3584 } 3585 3586 OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type; 3587 InitOMXParams(&vp8type); 3588 vp8type.nPortIndex = kPortIndexOutput; 3589 status_t err = mOMX->getParameter( 3590 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder, 3591 &vp8type, sizeof(vp8type)); 3592 3593 if (err == OK) { 3594 if (iFrameInterval > 0) { 3595 vp8type.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate); 3596 } 3597 vp8type.eTemporalPattern = pattern; 3598 vp8type.nTemporalLayerCount = tsLayers; 3599 if (tsLayers > 0) { 3600 for (size_t i = 0; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) { 3601 vp8type.nTemporalLayerBitrateRatio[i] = 3602 kVp8LayerRateAlloction[tsLayers - 1][i]; 3603 } 3604 } 3605 if (bitrateMode == OMX_Video_ControlRateConstant) { 3606 vp8type.nMinQuantizer = 2; 3607 vp8type.nMaxQuantizer = 63; 3608 } 3609 3610 err = mOMX->setParameter( 3611 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder, 3612 &vp8type, sizeof(vp8type)); 3613 if (err != OK) { 3614 ALOGW("Extended VP8 parameters set failed: %d", err); 3615 } 3616 } 3617 3618 return configureBitrate(bitrate, bitrateMode); 3619} 3620 3621status_t ACodec::verifySupportForProfileAndLevel( 3622 int32_t profile, int32_t level) { 3623 OMX_VIDEO_PARAM_PROFILELEVELTYPE params; 3624 InitOMXParams(¶ms); 3625 params.nPortIndex = kPortIndexOutput; 3626 3627 for (params.nProfileIndex = 0;; ++params.nProfileIndex) { 3628 status_t err = mOMX->getParameter( 3629 mNode, 3630 OMX_IndexParamVideoProfileLevelQuerySupported, 3631 ¶ms, 3632 sizeof(params)); 3633 3634 if (err != OK) { 3635 return err; 3636 } 3637 3638 int32_t supportedProfile = static_cast<int32_t>(params.eProfile); 3639 int32_t supportedLevel = static_cast<int32_t>(params.eLevel); 3640 3641 if (profile == supportedProfile && level <= supportedLevel) { 3642 return OK; 3643 } 3644 } 3645} 3646 3647status_t ACodec::configureBitrate( 3648 int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode) { 3649 OMX_VIDEO_PARAM_BITRATETYPE bitrateType; 3650 InitOMXParams(&bitrateType); 3651 bitrateType.nPortIndex = kPortIndexOutput; 3652 3653 status_t err = mOMX->getParameter( 3654 mNode, OMX_IndexParamVideoBitrate, 3655 &bitrateType, sizeof(bitrateType)); 3656 3657 if (err != OK) { 3658 return err; 3659 } 3660 3661 bitrateType.eControlRate = bitrateMode; 3662 bitrateType.nTargetBitrate = bitrate; 3663 3664 return mOMX->setParameter( 3665 mNode, OMX_IndexParamVideoBitrate, 3666 &bitrateType, sizeof(bitrateType)); 3667} 3668 3669status_t ACodec::setupErrorCorrectionParameters() { 3670 OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType; 3671 InitOMXParams(&errorCorrectionType); 3672 errorCorrectionType.nPortIndex = kPortIndexOutput; 3673 3674 status_t err = mOMX->getParameter( 3675 mNode, OMX_IndexParamVideoErrorCorrection, 3676 &errorCorrectionType, sizeof(errorCorrectionType)); 3677 3678 if (err != OK) { 3679 return OK; // Optional feature. Ignore this failure 3680 } 3681 3682 errorCorrectionType.bEnableHEC = OMX_FALSE; 3683 errorCorrectionType.bEnableResync = OMX_TRUE; 3684 errorCorrectionType.nResynchMarkerSpacing = 256; 3685 errorCorrectionType.bEnableDataPartitioning = OMX_FALSE; 3686 errorCorrectionType.bEnableRVLC = OMX_FALSE; 3687 3688 return mOMX->setParameter( 3689 mNode, OMX_IndexParamVideoErrorCorrection, 3690 &errorCorrectionType, sizeof(errorCorrectionType)); 3691} 3692 3693status_t ACodec::setVideoFormatOnPort( 3694 OMX_U32 portIndex, 3695 int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat, 3696 float frameRate) { 3697 OMX_PARAM_PORTDEFINITIONTYPE def; 3698 InitOMXParams(&def); 3699 def.nPortIndex = portIndex; 3700 3701 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 3702 3703 status_t err = mOMX->getParameter( 3704 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 3705 if (err != OK) { 3706 return err; 3707 } 3708 3709 if (portIndex == kPortIndexInput) { 3710 // XXX Need a (much) better heuristic to compute input buffer sizes. 3711 const size_t X = 64 * 1024; 3712 if (def.nBufferSize < X) { 3713 def.nBufferSize = X; 3714 } 3715 } 3716 3717 if (def.eDomain != OMX_PortDomainVideo) { 3718 ALOGE("expected video port, got %s(%d)", asString(def.eDomain), def.eDomain); 3719 return FAILED_TRANSACTION; 3720 } 3721 3722 video_def->nFrameWidth = width; 3723 video_def->nFrameHeight = height; 3724 3725 if (portIndex == kPortIndexInput) { 3726 video_def->eCompressionFormat = compressionFormat; 3727 video_def->eColorFormat = OMX_COLOR_FormatUnused; 3728 if (frameRate >= 0) { 3729 video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f); 3730 } 3731 } 3732 3733 err = mOMX->setParameter( 3734 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 3735 3736 return err; 3737} 3738 3739status_t ACodec::initNativeWindow() { 3740 if (mNativeWindow != NULL) { 3741 return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE); 3742 } 3743 3744 mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE); 3745 return OK; 3746} 3747 3748size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const { 3749 size_t n = 0; 3750 3751 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 3752 const BufferInfo &info = mBuffers[portIndex].itemAt(i); 3753 3754 if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) { 3755 ++n; 3756 } 3757 } 3758 3759 return n; 3760} 3761 3762size_t ACodec::countBuffersOwnedByNativeWindow() const { 3763 size_t n = 0; 3764 3765 for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) { 3766 const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i); 3767 3768 if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 3769 ++n; 3770 } 3771 } 3772 3773 return n; 3774} 3775 3776void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() { 3777 if (mNativeWindow == NULL) { 3778 return; 3779 } 3780 3781 while (countBuffersOwnedByNativeWindow() > mNumUndequeuedBuffers 3782 && dequeueBufferFromNativeWindow() != NULL) { 3783 // these buffers will be submitted as regular buffers; account for this 3784 if (storingMetadataInDecodedBuffers() && mMetadataBuffersToSubmit > 0) { 3785 --mMetadataBuffersToSubmit; 3786 } 3787 } 3788} 3789 3790bool ACodec::allYourBuffersAreBelongToUs( 3791 OMX_U32 portIndex) { 3792 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 3793 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 3794 3795 if (info->mStatus != BufferInfo::OWNED_BY_US 3796 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) { 3797 ALOGV("[%s] Buffer %u on port %u still has status %d", 3798 mComponentName.c_str(), 3799 info->mBufferID, portIndex, info->mStatus); 3800 return false; 3801 } 3802 } 3803 3804 return true; 3805} 3806 3807bool ACodec::allYourBuffersAreBelongToUs() { 3808 return allYourBuffersAreBelongToUs(kPortIndexInput) 3809 && allYourBuffersAreBelongToUs(kPortIndexOutput); 3810} 3811 3812void ACodec::deferMessage(const sp<AMessage> &msg) { 3813 mDeferredQueue.push_back(msg); 3814} 3815 3816void ACodec::processDeferredMessages() { 3817 List<sp<AMessage> > queue = mDeferredQueue; 3818 mDeferredQueue.clear(); 3819 3820 List<sp<AMessage> >::iterator it = queue.begin(); 3821 while (it != queue.end()) { 3822 onMessageReceived(*it++); 3823 } 3824} 3825 3826// static 3827bool ACodec::describeDefaultColorFormat(DescribeColorFormatParams ¶ms) { 3828 MediaImage &image = params.sMediaImage; 3829 memset(&image, 0, sizeof(image)); 3830 3831 image.mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN; 3832 image.mNumPlanes = 0; 3833 3834 const OMX_COLOR_FORMATTYPE fmt = params.eColorFormat; 3835 image.mWidth = params.nFrameWidth; 3836 image.mHeight = params.nFrameHeight; 3837 3838 // only supporting YUV420 3839 if (fmt != OMX_COLOR_FormatYUV420Planar && 3840 fmt != OMX_COLOR_FormatYUV420PackedPlanar && 3841 fmt != OMX_COLOR_FormatYUV420SemiPlanar && 3842 fmt != OMX_COLOR_FormatYUV420PackedSemiPlanar && 3843 fmt != HAL_PIXEL_FORMAT_YV12) { 3844 ALOGW("do not know color format 0x%x = %d", fmt, fmt); 3845 return false; 3846 } 3847 3848 // TEMPORARY FIX for some vendors that advertise sliceHeight as 0 3849 if (params.nStride != 0 && params.nSliceHeight == 0) { 3850 ALOGW("using sliceHeight=%u instead of what codec advertised (=0)", 3851 params.nFrameHeight); 3852 params.nSliceHeight = params.nFrameHeight; 3853 } 3854 3855 // we need stride and slice-height to be non-zero 3856 if (params.nStride == 0 || params.nSliceHeight == 0) { 3857 ALOGW("cannot describe color format 0x%x = %d with stride=%u and sliceHeight=%u", 3858 fmt, fmt, params.nStride, params.nSliceHeight); 3859 return false; 3860 } 3861 3862 // set-up YUV format 3863 image.mType = MediaImage::MEDIA_IMAGE_TYPE_YUV; 3864 image.mNumPlanes = 3; 3865 image.mBitDepth = 8; 3866 image.mPlane[image.Y].mOffset = 0; 3867 image.mPlane[image.Y].mColInc = 1; 3868 image.mPlane[image.Y].mRowInc = params.nStride; 3869 image.mPlane[image.Y].mHorizSubsampling = 1; 3870 image.mPlane[image.Y].mVertSubsampling = 1; 3871 3872 switch ((int)fmt) { 3873 case HAL_PIXEL_FORMAT_YV12: 3874 if (params.bUsingNativeBuffers) { 3875 size_t ystride = align(params.nStride, 16); 3876 size_t cstride = align(params.nStride / 2, 16); 3877 image.mPlane[image.Y].mRowInc = ystride; 3878 3879 image.mPlane[image.V].mOffset = ystride * params.nSliceHeight; 3880 image.mPlane[image.V].mColInc = 1; 3881 image.mPlane[image.V].mRowInc = cstride; 3882 image.mPlane[image.V].mHorizSubsampling = 2; 3883 image.mPlane[image.V].mVertSubsampling = 2; 3884 3885 image.mPlane[image.U].mOffset = image.mPlane[image.V].mOffset 3886 + (cstride * params.nSliceHeight / 2); 3887 image.mPlane[image.U].mColInc = 1; 3888 image.mPlane[image.U].mRowInc = cstride; 3889 image.mPlane[image.U].mHorizSubsampling = 2; 3890 image.mPlane[image.U].mVertSubsampling = 2; 3891 break; 3892 } else { 3893 // fall through as YV12 is used for YUV420Planar by some codecs 3894 } 3895 3896 case OMX_COLOR_FormatYUV420Planar: 3897 case OMX_COLOR_FormatYUV420PackedPlanar: 3898 image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight; 3899 image.mPlane[image.U].mColInc = 1; 3900 image.mPlane[image.U].mRowInc = params.nStride / 2; 3901 image.mPlane[image.U].mHorizSubsampling = 2; 3902 image.mPlane[image.U].mVertSubsampling = 2; 3903 3904 image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset 3905 + (params.nStride * params.nSliceHeight / 4); 3906 image.mPlane[image.V].mColInc = 1; 3907 image.mPlane[image.V].mRowInc = params.nStride / 2; 3908 image.mPlane[image.V].mHorizSubsampling = 2; 3909 image.mPlane[image.V].mVertSubsampling = 2; 3910 break; 3911 3912 case OMX_COLOR_FormatYUV420SemiPlanar: 3913 // FIXME: NV21 for sw-encoder, NV12 for decoder and hw-encoder 3914 case OMX_COLOR_FormatYUV420PackedSemiPlanar: 3915 // NV12 3916 image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight; 3917 image.mPlane[image.U].mColInc = 2; 3918 image.mPlane[image.U].mRowInc = params.nStride; 3919 image.mPlane[image.U].mHorizSubsampling = 2; 3920 image.mPlane[image.U].mVertSubsampling = 2; 3921 3922 image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset + 1; 3923 image.mPlane[image.V].mColInc = 2; 3924 image.mPlane[image.V].mRowInc = params.nStride; 3925 image.mPlane[image.V].mHorizSubsampling = 2; 3926 image.mPlane[image.V].mVertSubsampling = 2; 3927 break; 3928 3929 default: 3930 TRESPASS(); 3931 } 3932 return true; 3933} 3934 3935// static 3936bool ACodec::describeColorFormat( 3937 const sp<IOMX> &omx, IOMX::node_id node, 3938 DescribeColorFormatParams &describeParams) 3939{ 3940 OMX_INDEXTYPE describeColorFormatIndex; 3941 if (omx->getExtensionIndex( 3942 node, "OMX.google.android.index.describeColorFormat", 3943 &describeColorFormatIndex) != OK || 3944 omx->getParameter( 3945 node, describeColorFormatIndex, 3946 &describeParams, sizeof(describeParams)) != OK) { 3947 return describeDefaultColorFormat(describeParams); 3948 } 3949 return describeParams.sMediaImage.mType != 3950 MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN; 3951} 3952 3953// static 3954bool ACodec::isFlexibleColorFormat( 3955 const sp<IOMX> &omx, IOMX::node_id node, 3956 uint32_t colorFormat, bool usingNativeBuffers, OMX_U32 *flexibleEquivalent) { 3957 DescribeColorFormatParams describeParams; 3958 InitOMXParams(&describeParams); 3959 describeParams.eColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat; 3960 // reasonable dummy values 3961 describeParams.nFrameWidth = 128; 3962 describeParams.nFrameHeight = 128; 3963 describeParams.nStride = 128; 3964 describeParams.nSliceHeight = 128; 3965 describeParams.bUsingNativeBuffers = (OMX_BOOL)usingNativeBuffers; 3966 3967 CHECK(flexibleEquivalent != NULL); 3968 3969 if (!describeColorFormat(omx, node, describeParams)) { 3970 return false; 3971 } 3972 3973 const MediaImage &img = describeParams.sMediaImage; 3974 if (img.mType == MediaImage::MEDIA_IMAGE_TYPE_YUV) { 3975 if (img.mNumPlanes != 3 || 3976 img.mPlane[img.Y].mHorizSubsampling != 1 || 3977 img.mPlane[img.Y].mVertSubsampling != 1) { 3978 return false; 3979 } 3980 3981 // YUV 420 3982 if (img.mPlane[img.U].mHorizSubsampling == 2 3983 && img.mPlane[img.U].mVertSubsampling == 2 3984 && img.mPlane[img.V].mHorizSubsampling == 2 3985 && img.mPlane[img.V].mVertSubsampling == 2) { 3986 // possible flexible YUV420 format 3987 if (img.mBitDepth <= 8) { 3988 *flexibleEquivalent = OMX_COLOR_FormatYUV420Flexible; 3989 return true; 3990 } 3991 } 3992 } 3993 return false; 3994} 3995 3996status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> ¬ify) { 3997 const char *niceIndex = portIndex == kPortIndexInput ? "input" : "output"; 3998 OMX_PARAM_PORTDEFINITIONTYPE def; 3999 InitOMXParams(&def); 4000 def.nPortIndex = portIndex; 4001 4002 status_t err = mOMX->getParameter(mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 4003 if (err != OK) { 4004 return err; 4005 } 4006 4007 if (def.eDir != (portIndex == kPortIndexOutput ? OMX_DirOutput : OMX_DirInput)) { 4008 ALOGE("unexpected dir: %s(%d) on %s port", asString(def.eDir), def.eDir, niceIndex); 4009 return BAD_VALUE; 4010 } 4011 4012 switch (def.eDomain) { 4013 case OMX_PortDomainVideo: 4014 { 4015 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video; 4016 switch ((int)videoDef->eCompressionFormat) { 4017 case OMX_VIDEO_CodingUnused: 4018 { 4019 CHECK(mIsEncoder ^ (portIndex == kPortIndexOutput)); 4020 notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW); 4021 4022 notify->setInt32("stride", videoDef->nStride); 4023 notify->setInt32("slice-height", videoDef->nSliceHeight); 4024 notify->setInt32("color-format", videoDef->eColorFormat); 4025 4026 if (mNativeWindow == NULL) { 4027 DescribeColorFormatParams describeParams; 4028 InitOMXParams(&describeParams); 4029 describeParams.eColorFormat = videoDef->eColorFormat; 4030 describeParams.nFrameWidth = videoDef->nFrameWidth; 4031 describeParams.nFrameHeight = videoDef->nFrameHeight; 4032 describeParams.nStride = videoDef->nStride; 4033 describeParams.nSliceHeight = videoDef->nSliceHeight; 4034 describeParams.bUsingNativeBuffers = OMX_FALSE; 4035 4036 if (describeColorFormat(mOMX, mNode, describeParams)) { 4037 notify->setBuffer( 4038 "image-data", 4039 ABuffer::CreateAsCopy( 4040 &describeParams.sMediaImage, 4041 sizeof(describeParams.sMediaImage))); 4042 4043 MediaImage *img = &describeParams.sMediaImage; 4044 ALOGV("[%s] MediaImage { F(%ux%u) @%u+%u+%u @%u+%u+%u @%u+%u+%u }", 4045 mComponentName.c_str(), img->mWidth, img->mHeight, 4046 img->mPlane[0].mOffset, img->mPlane[0].mColInc, img->mPlane[0].mRowInc, 4047 img->mPlane[1].mOffset, img->mPlane[1].mColInc, img->mPlane[1].mRowInc, 4048 img->mPlane[2].mOffset, img->mPlane[2].mColInc, img->mPlane[2].mRowInc); 4049 } 4050 } 4051 4052 if (portIndex != kPortIndexOutput) { 4053 // TODO: also get input crop 4054 break; 4055 } 4056 4057 OMX_CONFIG_RECTTYPE rect; 4058 InitOMXParams(&rect); 4059 rect.nPortIndex = portIndex; 4060 4061 if (mOMX->getConfig( 4062 mNode, 4063 (portIndex == kPortIndexOutput ? 4064 OMX_IndexConfigCommonOutputCrop : 4065 OMX_IndexConfigCommonInputCrop), 4066 &rect, sizeof(rect)) != OK) { 4067 rect.nLeft = 0; 4068 rect.nTop = 0; 4069 rect.nWidth = videoDef->nFrameWidth; 4070 rect.nHeight = videoDef->nFrameHeight; 4071 } 4072 4073 if (rect.nLeft < 0 || 4074 rect.nTop < 0 || 4075 rect.nLeft + rect.nWidth > videoDef->nFrameWidth || 4076 rect.nTop + rect.nHeight > videoDef->nFrameHeight) { 4077 ALOGE("Wrong cropped rect (%d, %d) - (%u, %u) vs. frame (%u, %u)", 4078 rect.nLeft, rect.nTop, 4079 rect.nLeft + rect.nWidth, rect.nTop + rect.nHeight, 4080 videoDef->nFrameWidth, videoDef->nFrameHeight); 4081 return BAD_VALUE; 4082 } 4083 4084 notify->setRect( 4085 "crop", 4086 rect.nLeft, 4087 rect.nTop, 4088 rect.nLeft + rect.nWidth - 1, 4089 rect.nTop + rect.nHeight - 1); 4090 4091 break; 4092 } 4093 4094 case OMX_VIDEO_CodingVP8: 4095 case OMX_VIDEO_CodingVP9: 4096 { 4097 OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type; 4098 InitOMXParams(&vp8type); 4099 vp8type.nPortIndex = kPortIndexOutput; 4100 status_t err = mOMX->getParameter( 4101 mNode, 4102 (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder, 4103 &vp8type, 4104 sizeof(vp8type)); 4105 4106 if (err == OK) { 4107 AString tsSchema = "none"; 4108 if (vp8type.eTemporalPattern 4109 == OMX_VIDEO_VPXTemporalLayerPatternWebRTC) { 4110 switch (vp8type.nTemporalLayerCount) { 4111 case 1: 4112 { 4113 tsSchema = "webrtc.vp8.1-layer"; 4114 break; 4115 } 4116 case 2: 4117 { 4118 tsSchema = "webrtc.vp8.2-layer"; 4119 break; 4120 } 4121 case 3: 4122 { 4123 tsSchema = "webrtc.vp8.3-layer"; 4124 break; 4125 } 4126 default: 4127 { 4128 break; 4129 } 4130 } 4131 } 4132 notify->setString("ts-schema", tsSchema); 4133 } 4134 // Fall through to set up mime. 4135 } 4136 4137 default: 4138 { 4139 if (mIsEncoder ^ (portIndex == kPortIndexOutput)) { 4140 // should be CodingUnused 4141 ALOGE("Raw port video compression format is %s(%d)", 4142 asString(videoDef->eCompressionFormat), 4143 videoDef->eCompressionFormat); 4144 return BAD_VALUE; 4145 } 4146 AString mime; 4147 if (GetMimeTypeForVideoCoding( 4148 videoDef->eCompressionFormat, &mime) != OK) { 4149 notify->setString("mime", "application/octet-stream"); 4150 } else { 4151 notify->setString("mime", mime.c_str()); 4152 } 4153 break; 4154 } 4155 } 4156 notify->setInt32("width", videoDef->nFrameWidth); 4157 notify->setInt32("height", videoDef->nFrameHeight); 4158 ALOGV("[%s] %s format is %s", mComponentName.c_str(), 4159 portIndex == kPortIndexInput ? "input" : "output", 4160 notify->debugString().c_str()); 4161 4162 break; 4163 } 4164 4165 case OMX_PortDomainAudio: 4166 { 4167 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio; 4168 4169 switch ((int)audioDef->eEncoding) { 4170 case OMX_AUDIO_CodingPCM: 4171 { 4172 OMX_AUDIO_PARAM_PCMMODETYPE params; 4173 InitOMXParams(¶ms); 4174 params.nPortIndex = portIndex; 4175 4176 err = mOMX->getParameter( 4177 mNode, OMX_IndexParamAudioPcm, ¶ms, sizeof(params)); 4178 if (err != OK) { 4179 return err; 4180 } 4181 4182 if (params.nChannels <= 0 4183 || (params.nChannels != 1 && !params.bInterleaved) 4184 || params.nBitPerSample != 16u 4185 || params.eNumData != OMX_NumericalDataSigned 4186 || params.ePCMMode != OMX_AUDIO_PCMModeLinear) { 4187 ALOGE("unsupported PCM port: %u channels%s, %u-bit, %s(%d), %s(%d) mode ", 4188 params.nChannels, 4189 params.bInterleaved ? " interleaved" : "", 4190 params.nBitPerSample, 4191 asString(params.eNumData), params.eNumData, 4192 asString(params.ePCMMode), params.ePCMMode); 4193 return FAILED_TRANSACTION; 4194 } 4195 4196 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW); 4197 notify->setInt32("channel-count", params.nChannels); 4198 notify->setInt32("sample-rate", params.nSamplingRate); 4199 4200 if (mChannelMaskPresent) { 4201 notify->setInt32("channel-mask", mChannelMask); 4202 } 4203 break; 4204 } 4205 4206 case OMX_AUDIO_CodingAAC: 4207 { 4208 OMX_AUDIO_PARAM_AACPROFILETYPE params; 4209 InitOMXParams(¶ms); 4210 params.nPortIndex = portIndex; 4211 4212 err = mOMX->getParameter( 4213 mNode, OMX_IndexParamAudioAac, ¶ms, sizeof(params)); 4214 if (err != OK) { 4215 return err; 4216 } 4217 4218 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC); 4219 notify->setInt32("channel-count", params.nChannels); 4220 notify->setInt32("sample-rate", params.nSampleRate); 4221 break; 4222 } 4223 4224 case OMX_AUDIO_CodingAMR: 4225 { 4226 OMX_AUDIO_PARAM_AMRTYPE params; 4227 InitOMXParams(¶ms); 4228 params.nPortIndex = portIndex; 4229 4230 err = mOMX->getParameter( 4231 mNode, OMX_IndexParamAudioAmr, ¶ms, sizeof(params)); 4232 if (err != OK) { 4233 return err; 4234 } 4235 4236 notify->setInt32("channel-count", 1); 4237 if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) { 4238 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_WB); 4239 notify->setInt32("sample-rate", 16000); 4240 } else { 4241 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB); 4242 notify->setInt32("sample-rate", 8000); 4243 } 4244 break; 4245 } 4246 4247 case OMX_AUDIO_CodingFLAC: 4248 { 4249 OMX_AUDIO_PARAM_FLACTYPE params; 4250 InitOMXParams(¶ms); 4251 params.nPortIndex = portIndex; 4252 4253 err = mOMX->getParameter( 4254 mNode, OMX_IndexParamAudioFlac, ¶ms, sizeof(params)); 4255 if (err != OK) { 4256 return err; 4257 } 4258 4259 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC); 4260 notify->setInt32("channel-count", params.nChannels); 4261 notify->setInt32("sample-rate", params.nSampleRate); 4262 break; 4263 } 4264 4265 case OMX_AUDIO_CodingMP3: 4266 { 4267 OMX_AUDIO_PARAM_MP3TYPE params; 4268 InitOMXParams(¶ms); 4269 params.nPortIndex = portIndex; 4270 4271 err = mOMX->getParameter( 4272 mNode, OMX_IndexParamAudioMp3, ¶ms, sizeof(params)); 4273 if (err != OK) { 4274 return err; 4275 } 4276 4277 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MPEG); 4278 notify->setInt32("channel-count", params.nChannels); 4279 notify->setInt32("sample-rate", params.nSampleRate); 4280 break; 4281 } 4282 4283 case OMX_AUDIO_CodingVORBIS: 4284 { 4285 OMX_AUDIO_PARAM_VORBISTYPE params; 4286 InitOMXParams(¶ms); 4287 params.nPortIndex = portIndex; 4288 4289 err = mOMX->getParameter( 4290 mNode, OMX_IndexParamAudioVorbis, ¶ms, sizeof(params)); 4291 if (err != OK) { 4292 return err; 4293 } 4294 4295 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_VORBIS); 4296 notify->setInt32("channel-count", params.nChannels); 4297 notify->setInt32("sample-rate", params.nSampleRate); 4298 break; 4299 } 4300 4301 case OMX_AUDIO_CodingAndroidAC3: 4302 { 4303 OMX_AUDIO_PARAM_ANDROID_AC3TYPE params; 4304 InitOMXParams(¶ms); 4305 params.nPortIndex = portIndex; 4306 4307 err = mOMX->getParameter( 4308 mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, 4309 ¶ms, sizeof(params)); 4310 if (err != OK) { 4311 return err; 4312 } 4313 4314 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3); 4315 notify->setInt32("channel-count", params.nChannels); 4316 notify->setInt32("sample-rate", params.nSampleRate); 4317 break; 4318 } 4319 4320 case OMX_AUDIO_CodingAndroidEAC3: 4321 { 4322 OMX_AUDIO_PARAM_ANDROID_EAC3TYPE params; 4323 InitOMXParams(¶ms); 4324 params.nPortIndex = portIndex; 4325 4326 err = mOMX->getParameter( 4327 mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, 4328 ¶ms, sizeof(params)); 4329 if (err != OK) { 4330 return err; 4331 } 4332 4333 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_EAC3); 4334 notify->setInt32("channel-count", params.nChannels); 4335 notify->setInt32("sample-rate", params.nSampleRate); 4336 break; 4337 } 4338 4339 case OMX_AUDIO_CodingAndroidOPUS: 4340 { 4341 OMX_AUDIO_PARAM_ANDROID_OPUSTYPE params; 4342 InitOMXParams(¶ms); 4343 params.nPortIndex = portIndex; 4344 4345 err = mOMX->getParameter( 4346 mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus, 4347 ¶ms, sizeof(params)); 4348 if (err != OK) { 4349 return err; 4350 } 4351 4352 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_OPUS); 4353 notify->setInt32("channel-count", params.nChannels); 4354 notify->setInt32("sample-rate", params.nSampleRate); 4355 break; 4356 } 4357 4358 case OMX_AUDIO_CodingG711: 4359 { 4360 OMX_AUDIO_PARAM_PCMMODETYPE params; 4361 InitOMXParams(¶ms); 4362 params.nPortIndex = portIndex; 4363 4364 err = mOMX->getParameter( 4365 mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioPcm, ¶ms, sizeof(params)); 4366 if (err != OK) { 4367 return err; 4368 } 4369 4370 const char *mime = NULL; 4371 if (params.ePCMMode == OMX_AUDIO_PCMModeMULaw) { 4372 mime = MEDIA_MIMETYPE_AUDIO_G711_MLAW; 4373 } else if (params.ePCMMode == OMX_AUDIO_PCMModeALaw) { 4374 mime = MEDIA_MIMETYPE_AUDIO_G711_ALAW; 4375 } else { // params.ePCMMode == OMX_AUDIO_PCMModeLinear 4376 mime = MEDIA_MIMETYPE_AUDIO_RAW; 4377 } 4378 notify->setString("mime", mime); 4379 notify->setInt32("channel-count", params.nChannels); 4380 notify->setInt32("sample-rate", params.nSamplingRate); 4381 break; 4382 } 4383 4384 case OMX_AUDIO_CodingGSMFR: 4385 { 4386 OMX_AUDIO_PARAM_PCMMODETYPE params; 4387 InitOMXParams(¶ms); 4388 params.nPortIndex = portIndex; 4389 4390 err = mOMX->getParameter( 4391 mNode, OMX_IndexParamAudioPcm, ¶ms, sizeof(params)); 4392 if (err != OK) { 4393 return err; 4394 } 4395 4396 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MSGSM); 4397 notify->setInt32("channel-count", params.nChannels); 4398 notify->setInt32("sample-rate", params.nSamplingRate); 4399 break; 4400 } 4401 4402 default: 4403 ALOGE("Unsupported audio coding: %s(%d)\n", 4404 asString(audioDef->eEncoding), audioDef->eEncoding); 4405 return BAD_TYPE; 4406 } 4407 break; 4408 } 4409 4410 default: 4411 ALOGE("Unsupported domain: %s(%d)", asString(def.eDomain), def.eDomain); 4412 return BAD_TYPE; 4413 } 4414 4415 return OK; 4416} 4417 4418void ACodec::sendFormatChange(const sp<AMessage> &reply) { 4419 sp<AMessage> notify = mBaseOutputFormat->dup(); 4420 notify->setInt32("what", kWhatOutputFormatChanged); 4421 4422 if (getPortFormat(kPortIndexOutput, notify) != OK) { 4423 ALOGE("[%s] Failed to get port format to send format change", mComponentName.c_str()); 4424 return; 4425 } 4426 4427 AString mime; 4428 CHECK(notify->findString("mime", &mime)); 4429 4430 int32_t left, top, right, bottom; 4431 if (mime == MEDIA_MIMETYPE_VIDEO_RAW && 4432 mNativeWindow != NULL && 4433 notify->findRect("crop", &left, &top, &right, &bottom)) { 4434 // notify renderer of the crop change 4435 // NOTE: native window uses extended right-bottom coordinate 4436 reply->setRect("crop", left, top, right + 1, bottom + 1); 4437 } else if (mime == MEDIA_MIMETYPE_AUDIO_RAW && 4438 (mEncoderDelay || mEncoderPadding)) { 4439 int32_t channelCount; 4440 CHECK(notify->findInt32("channel-count", &channelCount)); 4441 size_t frameSize = channelCount * sizeof(int16_t); 4442 if (mSkipCutBuffer != NULL) { 4443 size_t prevbufsize = mSkipCutBuffer->size(); 4444 if (prevbufsize != 0) { 4445 ALOGW("Replacing SkipCutBuffer holding %zu bytes", prevbufsize); 4446 } 4447 } 4448 mSkipCutBuffer = new SkipCutBuffer( 4449 mEncoderDelay * frameSize, 4450 mEncoderPadding * frameSize); 4451 } 4452 4453 notify->post(); 4454 4455 mSentFormat = true; 4456} 4457 4458void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) { 4459 sp<AMessage> notify = mNotify->dup(); 4460 notify->setInt32("what", CodecBase::kWhatError); 4461 ALOGE("signalError(omxError %#x, internalError %d)", error, internalError); 4462 4463 if (internalError == UNKNOWN_ERROR) { // find better error code 4464 const status_t omxStatus = statusFromOMXError(error); 4465 if (omxStatus != 0) { 4466 internalError = omxStatus; 4467 } else { 4468 ALOGW("Invalid OMX error %#x", error); 4469 } 4470 } 4471 4472 mFatalError = true; 4473 4474 notify->setInt32("err", internalError); 4475 notify->setInt32("actionCode", ACTION_CODE_FATAL); // could translate from OMX error. 4476 notify->post(); 4477} 4478 4479//////////////////////////////////////////////////////////////////////////////// 4480 4481ACodec::PortDescription::PortDescription() { 4482} 4483 4484status_t ACodec::requestIDRFrame() { 4485 if (!mIsEncoder) { 4486 return ERROR_UNSUPPORTED; 4487 } 4488 4489 OMX_CONFIG_INTRAREFRESHVOPTYPE params; 4490 InitOMXParams(¶ms); 4491 4492 params.nPortIndex = kPortIndexOutput; 4493 params.IntraRefreshVOP = OMX_TRUE; 4494 4495 return mOMX->setConfig( 4496 mNode, 4497 OMX_IndexConfigVideoIntraVOPRefresh, 4498 ¶ms, 4499 sizeof(params)); 4500} 4501 4502void ACodec::PortDescription::addBuffer( 4503 IOMX::buffer_id id, const sp<ABuffer> &buffer) { 4504 mBufferIDs.push_back(id); 4505 mBuffers.push_back(buffer); 4506} 4507 4508size_t ACodec::PortDescription::countBuffers() { 4509 return mBufferIDs.size(); 4510} 4511 4512IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const { 4513 return mBufferIDs.itemAt(index); 4514} 4515 4516sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const { 4517 return mBuffers.itemAt(index); 4518} 4519 4520//////////////////////////////////////////////////////////////////////////////// 4521 4522ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState) 4523 : AState(parentState), 4524 mCodec(codec) { 4525} 4526 4527ACodec::BaseState::PortMode ACodec::BaseState::getPortMode( 4528 OMX_U32 /* portIndex */) { 4529 return KEEP_BUFFERS; 4530} 4531 4532bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) { 4533 switch (msg->what()) { 4534 case kWhatInputBufferFilled: 4535 { 4536 onInputBufferFilled(msg); 4537 break; 4538 } 4539 4540 case kWhatOutputBufferDrained: 4541 { 4542 onOutputBufferDrained(msg); 4543 break; 4544 } 4545 4546 case ACodec::kWhatOMXMessageList: 4547 { 4548 return checkOMXMessage(msg) ? onOMXMessageList(msg) : true; 4549 } 4550 4551 case ACodec::kWhatOMXMessageItem: 4552 { 4553 // no need to check as we already did it for kWhatOMXMessageList 4554 return onOMXMessage(msg); 4555 } 4556 4557 case ACodec::kWhatOMXMessage: 4558 { 4559 return checkOMXMessage(msg) ? onOMXMessage(msg) : true; 4560 } 4561 4562 case ACodec::kWhatSetSurface: 4563 { 4564 sp<AReplyToken> replyID; 4565 CHECK(msg->senderAwaitsResponse(&replyID)); 4566 4567 sp<RefBase> obj; 4568 CHECK(msg->findObject("surface", &obj)); 4569 4570 status_t err = mCodec->handleSetSurface(static_cast<Surface *>(obj.get())); 4571 4572 sp<AMessage> response = new AMessage; 4573 response->setInt32("err", err); 4574 response->postReply(replyID); 4575 break; 4576 } 4577 4578 case ACodec::kWhatCreateInputSurface: 4579 case ACodec::kWhatSetInputSurface: 4580 case ACodec::kWhatSignalEndOfInputStream: 4581 { 4582 // This may result in an app illegal state exception. 4583 ALOGE("Message 0x%x was not handled", msg->what()); 4584 mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION); 4585 return true; 4586 } 4587 4588 case ACodec::kWhatOMXDied: 4589 { 4590 // This will result in kFlagSawMediaServerDie handling in MediaCodec. 4591 ALOGE("OMX/mediaserver died, signalling error!"); 4592 mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT); 4593 break; 4594 } 4595 4596 case ACodec::kWhatReleaseCodecInstance: 4597 { 4598 ALOGI("[%s] forcing the release of codec", 4599 mCodec->mComponentName.c_str()); 4600 status_t err = mCodec->mOMX->freeNode(mCodec->mNode); 4601 ALOGE_IF("[%s] failed to release codec instance: err=%d", 4602 mCodec->mComponentName.c_str(), err); 4603 sp<AMessage> notify = mCodec->mNotify->dup(); 4604 notify->setInt32("what", CodecBase::kWhatShutdownCompleted); 4605 notify->post(); 4606 break; 4607 } 4608 4609 default: 4610 return false; 4611 } 4612 4613 return true; 4614} 4615 4616bool ACodec::BaseState::checkOMXMessage(const sp<AMessage> &msg) { 4617 // there is a possibility that this is an outstanding message for a 4618 // codec that we have already destroyed 4619 if (mCodec->mNode == 0) { 4620 ALOGI("ignoring message as already freed component: %s", 4621 msg->debugString().c_str()); 4622 return false; 4623 } 4624 4625 IOMX::node_id nodeID; 4626 CHECK(msg->findInt32("node", (int32_t*)&nodeID)); 4627 if (nodeID != mCodec->mNode) { 4628 ALOGE("Unexpected message for nodeID: %u, should have been %u", nodeID, mCodec->mNode); 4629 return false; 4630 } 4631 return true; 4632} 4633 4634bool ACodec::BaseState::onOMXMessageList(const sp<AMessage> &msg) { 4635 sp<RefBase> obj; 4636 CHECK(msg->findObject("messages", &obj)); 4637 sp<MessageList> msgList = static_cast<MessageList *>(obj.get()); 4638 4639 bool receivedRenderedEvents = false; 4640 for (std::list<sp<AMessage>>::const_iterator it = msgList->getList().cbegin(); 4641 it != msgList->getList().cend(); ++it) { 4642 (*it)->setWhat(ACodec::kWhatOMXMessageItem); 4643 mCodec->handleMessage(*it); 4644 int32_t type; 4645 CHECK((*it)->findInt32("type", &type)); 4646 if (type == omx_message::FRAME_RENDERED) { 4647 receivedRenderedEvents = true; 4648 } 4649 } 4650 4651 if (receivedRenderedEvents) { 4652 // NOTE: all buffers are rendered in this case 4653 mCodec->notifyOfRenderedFrames(); 4654 } 4655 return true; 4656} 4657 4658bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) { 4659 int32_t type; 4660 CHECK(msg->findInt32("type", &type)); 4661 4662 switch (type) { 4663 case omx_message::EVENT: 4664 { 4665 int32_t event, data1, data2; 4666 CHECK(msg->findInt32("event", &event)); 4667 CHECK(msg->findInt32("data1", &data1)); 4668 CHECK(msg->findInt32("data2", &data2)); 4669 4670 if (event == OMX_EventCmdComplete 4671 && data1 == OMX_CommandFlush 4672 && data2 == (int32_t)OMX_ALL) { 4673 // Use of this notification is not consistent across 4674 // implementations. We'll drop this notification and rely 4675 // on flush-complete notifications on the individual port 4676 // indices instead. 4677 4678 return true; 4679 } 4680 4681 return onOMXEvent( 4682 static_cast<OMX_EVENTTYPE>(event), 4683 static_cast<OMX_U32>(data1), 4684 static_cast<OMX_U32>(data2)); 4685 } 4686 4687 case omx_message::EMPTY_BUFFER_DONE: 4688 { 4689 IOMX::buffer_id bufferID; 4690 int32_t fenceFd; 4691 4692 CHECK(msg->findInt32("buffer", (int32_t*)&bufferID)); 4693 CHECK(msg->findInt32("fence_fd", &fenceFd)); 4694 4695 return onOMXEmptyBufferDone(bufferID, fenceFd); 4696 } 4697 4698 case omx_message::FILL_BUFFER_DONE: 4699 { 4700 IOMX::buffer_id bufferID; 4701 CHECK(msg->findInt32("buffer", (int32_t*)&bufferID)); 4702 4703 int32_t rangeOffset, rangeLength, flags, fenceFd; 4704 int64_t timeUs; 4705 4706 CHECK(msg->findInt32("range_offset", &rangeOffset)); 4707 CHECK(msg->findInt32("range_length", &rangeLength)); 4708 CHECK(msg->findInt32("flags", &flags)); 4709 CHECK(msg->findInt64("timestamp", &timeUs)); 4710 CHECK(msg->findInt32("fence_fd", &fenceFd)); 4711 4712 return onOMXFillBufferDone( 4713 bufferID, 4714 (size_t)rangeOffset, (size_t)rangeLength, 4715 (OMX_U32)flags, 4716 timeUs, 4717 fenceFd); 4718 } 4719 4720 case omx_message::FRAME_RENDERED: 4721 { 4722 int64_t mediaTimeUs, systemNano; 4723 4724 CHECK(msg->findInt64("media_time_us", &mediaTimeUs)); 4725 CHECK(msg->findInt64("system_nano", &systemNano)); 4726 4727 return onOMXFrameRendered( 4728 mediaTimeUs, systemNano); 4729 } 4730 4731 default: 4732 ALOGE("Unexpected message type: %d", type); 4733 return false; 4734 } 4735} 4736 4737bool ACodec::BaseState::onOMXFrameRendered( 4738 int64_t mediaTimeUs __unused, nsecs_t systemNano __unused) { 4739 // ignore outside of Executing and PortSettingsChanged states 4740 return true; 4741} 4742 4743bool ACodec::BaseState::onOMXEvent( 4744 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 4745 if (event != OMX_EventError) { 4746 ALOGV("[%s] EVENT(%d, 0x%08x, 0x%08x)", 4747 mCodec->mComponentName.c_str(), event, data1, data2); 4748 4749 return false; 4750 } 4751 4752 ALOGE("[%s] ERROR(0x%08x)", mCodec->mComponentName.c_str(), data1); 4753 4754 // verify OMX component sends back an error we expect. 4755 OMX_ERRORTYPE omxError = (OMX_ERRORTYPE)data1; 4756 if (!isOMXError(omxError)) { 4757 ALOGW("Invalid OMX error %#x", omxError); 4758 omxError = OMX_ErrorUndefined; 4759 } 4760 mCodec->signalError(omxError); 4761 4762 return true; 4763} 4764 4765bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID, int fenceFd) { 4766 ALOGV("[%s] onOMXEmptyBufferDone %u", 4767 mCodec->mComponentName.c_str(), bufferID); 4768 4769 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID); 4770 BufferInfo::Status status = BufferInfo::getSafeStatus(info); 4771 if (status != BufferInfo::OWNED_BY_COMPONENT) { 4772 ALOGE("Wrong ownership in EBD: %s(%d) buffer #%u", _asString(status), status, bufferID); 4773 mCodec->dumpBuffers(kPortIndexInput); 4774 if (fenceFd >= 0) { 4775 ::close(fenceFd); 4776 } 4777 return false; 4778 } 4779 info->mStatus = BufferInfo::OWNED_BY_US; 4780 4781 // input buffers cannot take fences, so wait for any fence now 4782 (void)mCodec->waitForFence(fenceFd, "onOMXEmptyBufferDone"); 4783 fenceFd = -1; 4784 4785 // still save fence for completeness 4786 info->setWriteFence(fenceFd, "onOMXEmptyBufferDone"); 4787 4788 // We're in "store-metadata-in-buffers" mode, the underlying 4789 // OMX component had access to data that's implicitly refcounted 4790 // by this "MediaBuffer" object. Now that the OMX component has 4791 // told us that it's done with the input buffer, we can decrement 4792 // the mediaBuffer's reference count. 4793 info->mData->setMediaBufferBase(NULL); 4794 4795 PortMode mode = getPortMode(kPortIndexInput); 4796 4797 switch (mode) { 4798 case KEEP_BUFFERS: 4799 break; 4800 4801 case RESUBMIT_BUFFERS: 4802 postFillThisBuffer(info); 4803 break; 4804 4805 case FREE_BUFFERS: 4806 default: 4807 ALOGE("SHOULD NOT REACH HERE: cannot free empty output buffers"); 4808 return false; 4809 } 4810 4811 return true; 4812} 4813 4814void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) { 4815 if (mCodec->mPortEOS[kPortIndexInput]) { 4816 return; 4817 } 4818 4819 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 4820 4821 sp<AMessage> notify = mCodec->mNotify->dup(); 4822 notify->setInt32("what", CodecBase::kWhatFillThisBuffer); 4823 notify->setInt32("buffer-id", info->mBufferID); 4824 4825 info->mData->meta()->clear(); 4826 notify->setBuffer("buffer", info->mData); 4827 4828 sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec); 4829 reply->setInt32("buffer-id", info->mBufferID); 4830 4831 notify->setMessage("reply", reply); 4832 4833 notify->post(); 4834 4835 info->mStatus = BufferInfo::OWNED_BY_UPSTREAM; 4836} 4837 4838void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { 4839 IOMX::buffer_id bufferID; 4840 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID)); 4841 sp<ABuffer> buffer; 4842 int32_t err = OK; 4843 bool eos = false; 4844 PortMode mode = getPortMode(kPortIndexInput); 4845 4846 if (!msg->findBuffer("buffer", &buffer)) { 4847 /* these are unfilled buffers returned by client */ 4848 CHECK(msg->findInt32("err", &err)); 4849 4850 if (err == OK) { 4851 /* buffers with no errors are returned on MediaCodec.flush */ 4852 mode = KEEP_BUFFERS; 4853 } else { 4854 ALOGV("[%s] saw error %d instead of an input buffer", 4855 mCodec->mComponentName.c_str(), err); 4856 eos = true; 4857 } 4858 4859 buffer.clear(); 4860 } 4861 4862 int32_t tmp; 4863 if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) { 4864 eos = true; 4865 err = ERROR_END_OF_STREAM; 4866 } 4867 4868 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID); 4869 BufferInfo::Status status = BufferInfo::getSafeStatus(info); 4870 if (status != BufferInfo::OWNED_BY_UPSTREAM) { 4871 ALOGE("Wrong ownership in IBF: %s(%d) buffer #%u", _asString(status), status, bufferID); 4872 mCodec->dumpBuffers(kPortIndexInput); 4873 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 4874 return; 4875 } 4876 4877 info->mStatus = BufferInfo::OWNED_BY_US; 4878 4879 switch (mode) { 4880 case KEEP_BUFFERS: 4881 { 4882 if (eos) { 4883 if (!mCodec->mPortEOS[kPortIndexInput]) { 4884 mCodec->mPortEOS[kPortIndexInput] = true; 4885 mCodec->mInputEOSResult = err; 4886 } 4887 } 4888 break; 4889 } 4890 4891 case RESUBMIT_BUFFERS: 4892 { 4893 if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) { 4894 // Do not send empty input buffer w/o EOS to the component. 4895 if (buffer->size() == 0 && !eos) { 4896 postFillThisBuffer(info); 4897 break; 4898 } 4899 4900 int64_t timeUs; 4901 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 4902 4903 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME; 4904 4905 int32_t isCSD; 4906 if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) { 4907 flags |= OMX_BUFFERFLAG_CODECCONFIG; 4908 } 4909 4910 if (eos) { 4911 flags |= OMX_BUFFERFLAG_EOS; 4912 } 4913 4914 if (buffer != info->mData) { 4915 ALOGV("[%s] Needs to copy input data for buffer %u. (%p != %p)", 4916 mCodec->mComponentName.c_str(), 4917 bufferID, 4918 buffer.get(), info->mData.get()); 4919 4920 if (buffer->size() > info->mData->capacity()) { 4921 ALOGE("data size (%zu) is greated than buffer capacity (%zu)", 4922 buffer->size(), // this is the data received 4923 info->mData->capacity()); // this is out buffer size 4924 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 4925 return; 4926 } 4927 memcpy(info->mData->data(), buffer->data(), buffer->size()); 4928 } 4929 4930 if (flags & OMX_BUFFERFLAG_CODECCONFIG) { 4931 ALOGV("[%s] calling emptyBuffer %u w/ codec specific data", 4932 mCodec->mComponentName.c_str(), bufferID); 4933 } else if (flags & OMX_BUFFERFLAG_EOS) { 4934 ALOGV("[%s] calling emptyBuffer %u w/ EOS", 4935 mCodec->mComponentName.c_str(), bufferID); 4936 } else { 4937#if TRACK_BUFFER_TIMING 4938 ALOGI("[%s] calling emptyBuffer %u w/ time %lld us", 4939 mCodec->mComponentName.c_str(), bufferID, (long long)timeUs); 4940#else 4941 ALOGV("[%s] calling emptyBuffer %u w/ time %lld us", 4942 mCodec->mComponentName.c_str(), bufferID, (long long)timeUs); 4943#endif 4944 } 4945 4946#if TRACK_BUFFER_TIMING 4947 ACodec::BufferStats stats; 4948 stats.mEmptyBufferTimeUs = ALooper::GetNowUs(); 4949 stats.mFillBufferDoneTimeUs = -1ll; 4950 mCodec->mBufferStats.add(timeUs, stats); 4951#endif 4952 4953 if (mCodec->storingMetadataInDecodedBuffers()) { 4954 // try to submit an output buffer for each input buffer 4955 PortMode outputMode = getPortMode(kPortIndexOutput); 4956 4957 ALOGV("MetadataBuffersToSubmit=%u portMode=%s", 4958 mCodec->mMetadataBuffersToSubmit, 4959 (outputMode == FREE_BUFFERS ? "FREE" : 4960 outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT")); 4961 if (outputMode == RESUBMIT_BUFFERS) { 4962 mCodec->submitOutputMetadataBuffer(); 4963 } 4964 } 4965 info->checkReadFence("onInputBufferFilled"); 4966 status_t err2 = mCodec->mOMX->emptyBuffer( 4967 mCodec->mNode, 4968 bufferID, 4969 0, 4970 buffer->size(), 4971 flags, 4972 timeUs, 4973 info->mFenceFd); 4974 info->mFenceFd = -1; 4975 if (err2 != OK) { 4976 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2)); 4977 return; 4978 } 4979 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 4980 4981 if (!eos && err == OK) { 4982 getMoreInputDataIfPossible(); 4983 } else { 4984 ALOGV("[%s] Signalled EOS (%d) on the input port", 4985 mCodec->mComponentName.c_str(), err); 4986 4987 mCodec->mPortEOS[kPortIndexInput] = true; 4988 mCodec->mInputEOSResult = err; 4989 } 4990 } else if (!mCodec->mPortEOS[kPortIndexInput]) { 4991 if (err != OK && err != ERROR_END_OF_STREAM) { 4992 ALOGV("[%s] Signalling EOS on the input port due to error %d", 4993 mCodec->mComponentName.c_str(), err); 4994 } else { 4995 ALOGV("[%s] Signalling EOS on the input port", 4996 mCodec->mComponentName.c_str()); 4997 } 4998 4999 ALOGV("[%s] calling emptyBuffer %u signalling EOS", 5000 mCodec->mComponentName.c_str(), bufferID); 5001 5002 info->checkReadFence("onInputBufferFilled"); 5003 status_t err2 = mCodec->mOMX->emptyBuffer( 5004 mCodec->mNode, 5005 bufferID, 5006 0, 5007 0, 5008 OMX_BUFFERFLAG_EOS, 5009 0, 5010 info->mFenceFd); 5011 info->mFenceFd = -1; 5012 if (err2 != OK) { 5013 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2)); 5014 return; 5015 } 5016 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 5017 5018 mCodec->mPortEOS[kPortIndexInput] = true; 5019 mCodec->mInputEOSResult = err; 5020 } 5021 break; 5022 } 5023 5024 case FREE_BUFFERS: 5025 break; 5026 5027 default: 5028 ALOGE("invalid port mode: %d", mode); 5029 break; 5030 } 5031} 5032 5033void ACodec::BaseState::getMoreInputDataIfPossible() { 5034 if (mCodec->mPortEOS[kPortIndexInput]) { 5035 return; 5036 } 5037 5038 BufferInfo *eligible = NULL; 5039 5040 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 5041 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 5042 5043#if 0 5044 if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) { 5045 // There's already a "read" pending. 5046 return; 5047 } 5048#endif 5049 5050 if (info->mStatus == BufferInfo::OWNED_BY_US) { 5051 eligible = info; 5052 } 5053 } 5054 5055 if (eligible == NULL) { 5056 return; 5057 } 5058 5059 postFillThisBuffer(eligible); 5060} 5061 5062bool ACodec::BaseState::onOMXFillBufferDone( 5063 IOMX::buffer_id bufferID, 5064 size_t rangeOffset, size_t rangeLength, 5065 OMX_U32 flags, 5066 int64_t timeUs, 5067 int fenceFd) { 5068 ALOGV("[%s] onOMXFillBufferDone %u time %" PRId64 " us, flags = 0x%08x", 5069 mCodec->mComponentName.c_str(), bufferID, timeUs, flags); 5070 5071 ssize_t index; 5072 status_t err= OK; 5073 5074#if TRACK_BUFFER_TIMING 5075 index = mCodec->mBufferStats.indexOfKey(timeUs); 5076 if (index >= 0) { 5077 ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index); 5078 stats->mFillBufferDoneTimeUs = ALooper::GetNowUs(); 5079 5080 ALOGI("frame PTS %lld: %lld", 5081 timeUs, 5082 stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs); 5083 5084 mCodec->mBufferStats.removeItemsAt(index); 5085 stats = NULL; 5086 } 5087#endif 5088 5089 BufferInfo *info = 5090 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 5091 BufferInfo::Status status = BufferInfo::getSafeStatus(info); 5092 if (status != BufferInfo::OWNED_BY_COMPONENT) { 5093 ALOGE("Wrong ownership in FBD: %s(%d) buffer #%u", _asString(status), status, bufferID); 5094 mCodec->dumpBuffers(kPortIndexOutput); 5095 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 5096 if (fenceFd >= 0) { 5097 ::close(fenceFd); 5098 } 5099 return true; 5100 } 5101 5102 info->mDequeuedAt = ++mCodec->mDequeueCounter; 5103 info->mStatus = BufferInfo::OWNED_BY_US; 5104 5105 if (info->mRenderInfo != NULL) { 5106 // The fence for an emptied buffer must have signaled, but there still could be queued 5107 // or out-of-order dequeued buffers in the render queue prior to this buffer. Drop these, 5108 // as we will soon requeue this buffer to the surface. While in theory we could still keep 5109 // track of buffers that are requeued to the surface, it is better to add support to the 5110 // buffer-queue to notify us of released buffers and their fences (in the future). 5111 mCodec->notifyOfRenderedFrames(true /* dropIncomplete */); 5112 } 5113 5114 // byte buffers cannot take fences, so wait for any fence now 5115 if (mCodec->mNativeWindow == NULL) { 5116 (void)mCodec->waitForFence(fenceFd, "onOMXFillBufferDone"); 5117 fenceFd = -1; 5118 } 5119 info->setReadFence(fenceFd, "onOMXFillBufferDone"); 5120 5121 PortMode mode = getPortMode(kPortIndexOutput); 5122 5123 switch (mode) { 5124 case KEEP_BUFFERS: 5125 break; 5126 5127 case RESUBMIT_BUFFERS: 5128 { 5129 if (rangeLength == 0 && (!(flags & OMX_BUFFERFLAG_EOS) 5130 || mCodec->mPortEOS[kPortIndexOutput])) { 5131 ALOGV("[%s] calling fillBuffer %u", 5132 mCodec->mComponentName.c_str(), info->mBufferID); 5133 5134 err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID, info->mFenceFd); 5135 info->mFenceFd = -1; 5136 if (err != OK) { 5137 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 5138 return true; 5139 } 5140 5141 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 5142 break; 5143 } 5144 5145 sp<AMessage> reply = 5146 new AMessage(kWhatOutputBufferDrained, mCodec); 5147 5148 if (!mCodec->mSentFormat && rangeLength > 0) { 5149 mCodec->sendFormatChange(reply); 5150 } 5151 if (mCodec->usingMetadataOnEncoderOutput()) { 5152 native_handle_t *handle = NULL; 5153 VideoGrallocMetadata &grallocMeta = *(VideoGrallocMetadata *)info->mData->data(); 5154 VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)info->mData->data(); 5155 if (info->mData->size() >= sizeof(grallocMeta) 5156 && grallocMeta.eType == kMetadataBufferTypeGrallocSource) { 5157 handle = (native_handle_t *)(uintptr_t)grallocMeta.pHandle; 5158 } else if (info->mData->size() >= sizeof(nativeMeta) 5159 && nativeMeta.eType == kMetadataBufferTypeANWBuffer) { 5160#ifdef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS 5161 // ANativeWindowBuffer is only valid on 32-bit/mediaserver process 5162 handle = NULL; 5163#else 5164 handle = (native_handle_t *)nativeMeta.pBuffer->handle; 5165#endif 5166 } 5167 info->mData->meta()->setPointer("handle", handle); 5168 info->mData->meta()->setInt32("rangeOffset", rangeOffset); 5169 info->mData->meta()->setInt32("rangeLength", rangeLength); 5170 } else { 5171 info->mData->setRange(rangeOffset, rangeLength); 5172 } 5173#if 0 5174 if (mCodec->mNativeWindow == NULL) { 5175 if (IsIDR(info->mData)) { 5176 ALOGI("IDR frame"); 5177 } 5178 } 5179#endif 5180 5181 if (mCodec->mSkipCutBuffer != NULL) { 5182 mCodec->mSkipCutBuffer->submit(info->mData); 5183 } 5184 info->mData->meta()->setInt64("timeUs", timeUs); 5185 5186 sp<AMessage> notify = mCodec->mNotify->dup(); 5187 notify->setInt32("what", CodecBase::kWhatDrainThisBuffer); 5188 notify->setInt32("buffer-id", info->mBufferID); 5189 notify->setBuffer("buffer", info->mData); 5190 notify->setInt32("flags", flags); 5191 5192 reply->setInt32("buffer-id", info->mBufferID); 5193 5194 notify->setMessage("reply", reply); 5195 5196 notify->post(); 5197 5198 info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM; 5199 5200 if (flags & OMX_BUFFERFLAG_EOS) { 5201 ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str()); 5202 5203 sp<AMessage> notify = mCodec->mNotify->dup(); 5204 notify->setInt32("what", CodecBase::kWhatEOS); 5205 notify->setInt32("err", mCodec->mInputEOSResult); 5206 notify->post(); 5207 5208 mCodec->mPortEOS[kPortIndexOutput] = true; 5209 } 5210 break; 5211 } 5212 5213 case FREE_BUFFERS: 5214 err = mCodec->freeBuffer(kPortIndexOutput, index); 5215 if (err != OK) { 5216 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 5217 return true; 5218 } 5219 break; 5220 5221 default: 5222 ALOGE("Invalid port mode: %d", mode); 5223 return false; 5224 } 5225 5226 return true; 5227} 5228 5229void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { 5230 IOMX::buffer_id bufferID; 5231 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID)); 5232 ssize_t index; 5233 BufferInfo *info = mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 5234 BufferInfo::Status status = BufferInfo::getSafeStatus(info); 5235 if (status != BufferInfo::OWNED_BY_DOWNSTREAM) { 5236 ALOGE("Wrong ownership in OBD: %s(%d) buffer #%u", _asString(status), status, bufferID); 5237 mCodec->dumpBuffers(kPortIndexOutput); 5238 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 5239 return; 5240 } 5241 5242 android_native_rect_t crop; 5243 if (msg->findRect("crop", &crop.left, &crop.top, &crop.right, &crop.bottom)) { 5244 status_t err = native_window_set_crop(mCodec->mNativeWindow.get(), &crop); 5245 ALOGW_IF(err != NO_ERROR, "failed to set crop: %d", err); 5246 } 5247 5248 int32_t render; 5249 if (mCodec->mNativeWindow != NULL 5250 && msg->findInt32("render", &render) && render != 0 5251 && info->mData != NULL && info->mData->size() != 0) { 5252 ATRACE_NAME("render"); 5253 // The client wants this buffer to be rendered. 5254 5255 // save buffers sent to the surface so we can get render time when they return 5256 int64_t mediaTimeUs = -1; 5257 info->mData->meta()->findInt64("timeUs", &mediaTimeUs); 5258 if (mediaTimeUs >= 0) { 5259 mCodec->mRenderTracker.onFrameQueued( 5260 mediaTimeUs, info->mGraphicBuffer, new Fence(::dup(info->mFenceFd))); 5261 } 5262 5263 int64_t timestampNs = 0; 5264 if (!msg->findInt64("timestampNs", ×tampNs)) { 5265 // use media timestamp if client did not request a specific render timestamp 5266 if (info->mData->meta()->findInt64("timeUs", ×tampNs)) { 5267 ALOGV("using buffer PTS of %lld", (long long)timestampNs); 5268 timestampNs *= 1000; 5269 } 5270 } 5271 5272 status_t err; 5273 err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs); 5274 ALOGW_IF(err != NO_ERROR, "failed to set buffer timestamp: %d", err); 5275 5276 info->checkReadFence("onOutputBufferDrained before queueBuffer"); 5277 err = mCodec->mNativeWindow->queueBuffer( 5278 mCodec->mNativeWindow.get(), info->mGraphicBuffer.get(), info->mFenceFd); 5279 info->mFenceFd = -1; 5280 if (err == OK) { 5281 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 5282 } else { 5283 ALOGE("queueBuffer failed in onOutputBufferDrained: %d", err); 5284 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 5285 info->mStatus = BufferInfo::OWNED_BY_US; 5286 // keeping read fence as write fence to avoid clobbering 5287 info->mIsReadFence = false; 5288 } 5289 } else { 5290 if (mCodec->mNativeWindow != NULL && 5291 (info->mData == NULL || info->mData->size() != 0)) { 5292 // move read fence into write fence to avoid clobbering 5293 info->mIsReadFence = false; 5294 ATRACE_NAME("frame-drop"); 5295 } 5296 info->mStatus = BufferInfo::OWNED_BY_US; 5297 } 5298 5299 PortMode mode = getPortMode(kPortIndexOutput); 5300 5301 switch (mode) { 5302 case KEEP_BUFFERS: 5303 { 5304 // XXX fishy, revisit!!! What about the FREE_BUFFERS case below? 5305 5306 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 5307 // We cannot resubmit the buffer we just rendered, dequeue 5308 // the spare instead. 5309 5310 info = mCodec->dequeueBufferFromNativeWindow(); 5311 } 5312 break; 5313 } 5314 5315 case RESUBMIT_BUFFERS: 5316 { 5317 if (!mCodec->mPortEOS[kPortIndexOutput]) { 5318 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 5319 // We cannot resubmit the buffer we just rendered, dequeue 5320 // the spare instead. 5321 5322 info = mCodec->dequeueBufferFromNativeWindow(); 5323 } 5324 5325 if (info != NULL) { 5326 ALOGV("[%s] calling fillBuffer %u", 5327 mCodec->mComponentName.c_str(), info->mBufferID); 5328 info->checkWriteFence("onOutputBufferDrained::RESUBMIT_BUFFERS"); 5329 status_t err = mCodec->mOMX->fillBuffer( 5330 mCodec->mNode, info->mBufferID, info->mFenceFd); 5331 info->mFenceFd = -1; 5332 if (err == OK) { 5333 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 5334 } else { 5335 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 5336 } 5337 } 5338 } 5339 break; 5340 } 5341 5342 case FREE_BUFFERS: 5343 { 5344 status_t err = mCodec->freeBuffer(kPortIndexOutput, index); 5345 if (err != OK) { 5346 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 5347 } 5348 break; 5349 } 5350 5351 default: 5352 ALOGE("Invalid port mode: %d", mode); 5353 return; 5354 } 5355} 5356 5357//////////////////////////////////////////////////////////////////////////////// 5358 5359ACodec::UninitializedState::UninitializedState(ACodec *codec) 5360 : BaseState(codec) { 5361} 5362 5363void ACodec::UninitializedState::stateEntered() { 5364 ALOGV("Now uninitialized"); 5365 5366 if (mDeathNotifier != NULL) { 5367 IInterface::asBinder(mCodec->mOMX)->unlinkToDeath(mDeathNotifier); 5368 mDeathNotifier.clear(); 5369 } 5370 5371 mCodec->mNativeWindow.clear(); 5372 mCodec->mNativeWindowUsageBits = 0; 5373 mCodec->mNode = 0; 5374 mCodec->mOMX.clear(); 5375 mCodec->mQuirks = 0; 5376 mCodec->mFlags = 0; 5377 mCodec->mInputMetadataType = kMetadataBufferTypeInvalid; 5378 mCodec->mOutputMetadataType = kMetadataBufferTypeInvalid; 5379 mCodec->mComponentName.clear(); 5380} 5381 5382bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) { 5383 bool handled = false; 5384 5385 switch (msg->what()) { 5386 case ACodec::kWhatSetup: 5387 { 5388 onSetup(msg); 5389 5390 handled = true; 5391 break; 5392 } 5393 5394 case ACodec::kWhatAllocateComponent: 5395 { 5396 onAllocateComponent(msg); 5397 handled = true; 5398 break; 5399 } 5400 5401 case ACodec::kWhatShutdown: 5402 { 5403 int32_t keepComponentAllocated; 5404 CHECK(msg->findInt32( 5405 "keepComponentAllocated", &keepComponentAllocated)); 5406 ALOGW_IF(keepComponentAllocated, 5407 "cannot keep component allocated on shutdown in Uninitialized state"); 5408 5409 sp<AMessage> notify = mCodec->mNotify->dup(); 5410 notify->setInt32("what", CodecBase::kWhatShutdownCompleted); 5411 notify->post(); 5412 5413 handled = true; 5414 break; 5415 } 5416 5417 case ACodec::kWhatFlush: 5418 { 5419 sp<AMessage> notify = mCodec->mNotify->dup(); 5420 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 5421 notify->post(); 5422 5423 handled = true; 5424 break; 5425 } 5426 5427 case ACodec::kWhatReleaseCodecInstance: 5428 { 5429 // nothing to do, as we have already signaled shutdown 5430 handled = true; 5431 break; 5432 } 5433 5434 default: 5435 return BaseState::onMessageReceived(msg); 5436 } 5437 5438 return handled; 5439} 5440 5441void ACodec::UninitializedState::onSetup( 5442 const sp<AMessage> &msg) { 5443 if (onAllocateComponent(msg) 5444 && mCodec->mLoadedState->onConfigureComponent(msg)) { 5445 mCodec->mLoadedState->onStart(); 5446 } 5447} 5448 5449bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) { 5450 ALOGV("onAllocateComponent"); 5451 5452 CHECK(mCodec->mNode == 0); 5453 5454 OMXClient client; 5455 if (client.connect() != OK) { 5456 mCodec->signalError(OMX_ErrorUndefined, NO_INIT); 5457 return false; 5458 } 5459 5460 sp<IOMX> omx = client.interface(); 5461 5462 sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec); 5463 5464 mDeathNotifier = new DeathNotifier(notify); 5465 if (IInterface::asBinder(omx)->linkToDeath(mDeathNotifier) != OK) { 5466 // This was a local binder, if it dies so do we, we won't care 5467 // about any notifications in the afterlife. 5468 mDeathNotifier.clear(); 5469 } 5470 5471 Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs; 5472 5473 AString mime; 5474 5475 AString componentName; 5476 uint32_t quirks = 0; 5477 int32_t encoder = false; 5478 if (msg->findString("componentName", &componentName)) { 5479 ssize_t index = matchingCodecs.add(); 5480 OMXCodec::CodecNameAndQuirks *entry = &matchingCodecs.editItemAt(index); 5481 entry->mName = String8(componentName.c_str()); 5482 5483 if (!OMXCodec::findCodecQuirks( 5484 componentName.c_str(), &entry->mQuirks)) { 5485 entry->mQuirks = 0; 5486 } 5487 } else { 5488 CHECK(msg->findString("mime", &mime)); 5489 5490 if (!msg->findInt32("encoder", &encoder)) { 5491 encoder = false; 5492 } 5493 5494 OMXCodec::findMatchingCodecs( 5495 mime.c_str(), 5496 encoder, // createEncoder 5497 NULL, // matchComponentName 5498 0, // flags 5499 &matchingCodecs); 5500 } 5501 5502 sp<CodecObserver> observer = new CodecObserver; 5503 IOMX::node_id node = 0; 5504 5505 status_t err = NAME_NOT_FOUND; 5506 for (size_t matchIndex = 0; matchIndex < matchingCodecs.size(); 5507 ++matchIndex) { 5508 componentName = matchingCodecs.itemAt(matchIndex).mName.string(); 5509 quirks = matchingCodecs.itemAt(matchIndex).mQuirks; 5510 5511 pid_t tid = gettid(); 5512 int prevPriority = androidGetThreadPriority(tid); 5513 androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND); 5514 err = omx->allocateNode(componentName.c_str(), observer, &node); 5515 androidSetThreadPriority(tid, prevPriority); 5516 5517 if (err == OK) { 5518 break; 5519 } else { 5520 ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str()); 5521 } 5522 5523 node = 0; 5524 } 5525 5526 if (node == 0) { 5527 if (!mime.empty()) { 5528 ALOGE("Unable to instantiate a %scoder for type '%s' with err %#x.", 5529 encoder ? "en" : "de", mime.c_str(), err); 5530 } else { 5531 ALOGE("Unable to instantiate codec '%s' with err %#x.", componentName.c_str(), err); 5532 } 5533 5534 mCodec->signalError((OMX_ERRORTYPE)err, makeNoSideEffectStatus(err)); 5535 return false; 5536 } 5537 5538 notify = new AMessage(kWhatOMXMessageList, mCodec); 5539 observer->setNotificationMessage(notify); 5540 5541 mCodec->mComponentName = componentName; 5542 mCodec->mRenderTracker.setComponentName(componentName); 5543 mCodec->mFlags = 0; 5544 5545 if (componentName.endsWith(".secure")) { 5546 mCodec->mFlags |= kFlagIsSecure; 5547 mCodec->mFlags |= kFlagIsGrallocUsageProtected; 5548 mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown; 5549 } 5550 5551 mCodec->mQuirks = quirks; 5552 mCodec->mOMX = omx; 5553 mCodec->mNode = node; 5554 5555 { 5556 sp<AMessage> notify = mCodec->mNotify->dup(); 5557 notify->setInt32("what", CodecBase::kWhatComponentAllocated); 5558 notify->setString("componentName", mCodec->mComponentName.c_str()); 5559 notify->post(); 5560 } 5561 5562 mCodec->changeState(mCodec->mLoadedState); 5563 5564 return true; 5565} 5566 5567//////////////////////////////////////////////////////////////////////////////// 5568 5569ACodec::LoadedState::LoadedState(ACodec *codec) 5570 : BaseState(codec) { 5571} 5572 5573void ACodec::LoadedState::stateEntered() { 5574 ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str()); 5575 5576 mCodec->mPortEOS[kPortIndexInput] = 5577 mCodec->mPortEOS[kPortIndexOutput] = false; 5578 5579 mCodec->mInputEOSResult = OK; 5580 5581 mCodec->mDequeueCounter = 0; 5582 mCodec->mMetadataBuffersToSubmit = 0; 5583 mCodec->mRepeatFrameDelayUs = -1ll; 5584 mCodec->mInputFormat.clear(); 5585 mCodec->mOutputFormat.clear(); 5586 mCodec->mBaseOutputFormat.clear(); 5587 5588 if (mCodec->mShutdownInProgress) { 5589 bool keepComponentAllocated = mCodec->mKeepComponentAllocated; 5590 5591 mCodec->mShutdownInProgress = false; 5592 mCodec->mKeepComponentAllocated = false; 5593 5594 onShutdown(keepComponentAllocated); 5595 } 5596 mCodec->mExplicitShutdown = false; 5597 5598 mCodec->processDeferredMessages(); 5599} 5600 5601void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) { 5602 if (!keepComponentAllocated) { 5603 (void)mCodec->mOMX->freeNode(mCodec->mNode); 5604 5605 mCodec->changeState(mCodec->mUninitializedState); 5606 } 5607 5608 if (mCodec->mExplicitShutdown) { 5609 sp<AMessage> notify = mCodec->mNotify->dup(); 5610 notify->setInt32("what", CodecBase::kWhatShutdownCompleted); 5611 notify->post(); 5612 mCodec->mExplicitShutdown = false; 5613 } 5614} 5615 5616bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) { 5617 bool handled = false; 5618 5619 switch (msg->what()) { 5620 case ACodec::kWhatConfigureComponent: 5621 { 5622 onConfigureComponent(msg); 5623 handled = true; 5624 break; 5625 } 5626 5627 case ACodec::kWhatCreateInputSurface: 5628 { 5629 onCreateInputSurface(msg); 5630 handled = true; 5631 break; 5632 } 5633 5634 case ACodec::kWhatSetInputSurface: 5635 { 5636 onSetInputSurface(msg); 5637 handled = true; 5638 break; 5639 } 5640 5641 case ACodec::kWhatStart: 5642 { 5643 onStart(); 5644 handled = true; 5645 break; 5646 } 5647 5648 case ACodec::kWhatShutdown: 5649 { 5650 int32_t keepComponentAllocated; 5651 CHECK(msg->findInt32( 5652 "keepComponentAllocated", &keepComponentAllocated)); 5653 5654 mCodec->mExplicitShutdown = true; 5655 onShutdown(keepComponentAllocated); 5656 5657 handled = true; 5658 break; 5659 } 5660 5661 case ACodec::kWhatFlush: 5662 { 5663 sp<AMessage> notify = mCodec->mNotify->dup(); 5664 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 5665 notify->post(); 5666 5667 handled = true; 5668 break; 5669 } 5670 5671 default: 5672 return BaseState::onMessageReceived(msg); 5673 } 5674 5675 return handled; 5676} 5677 5678bool ACodec::LoadedState::onConfigureComponent( 5679 const sp<AMessage> &msg) { 5680 ALOGV("onConfigureComponent"); 5681 5682 CHECK(mCodec->mNode != 0); 5683 5684 status_t err = OK; 5685 AString mime; 5686 if (!msg->findString("mime", &mime)) { 5687 err = BAD_VALUE; 5688 } else { 5689 err = mCodec->configureCodec(mime.c_str(), msg); 5690 } 5691 if (err != OK) { 5692 ALOGE("[%s] configureCodec returning error %d", 5693 mCodec->mComponentName.c_str(), err); 5694 5695 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 5696 return false; 5697 } 5698 5699 { 5700 sp<AMessage> notify = mCodec->mNotify->dup(); 5701 notify->setInt32("what", CodecBase::kWhatComponentConfigured); 5702 notify->setMessage("input-format", mCodec->mInputFormat); 5703 notify->setMessage("output-format", mCodec->mOutputFormat); 5704 notify->post(); 5705 } 5706 5707 return true; 5708} 5709 5710status_t ACodec::LoadedState::setupInputSurface() { 5711 status_t err = OK; 5712 5713 if (mCodec->mRepeatFrameDelayUs > 0ll) { 5714 err = mCodec->mOMX->setInternalOption( 5715 mCodec->mNode, 5716 kPortIndexInput, 5717 IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY, 5718 &mCodec->mRepeatFrameDelayUs, 5719 sizeof(mCodec->mRepeatFrameDelayUs)); 5720 5721 if (err != OK) { 5722 ALOGE("[%s] Unable to configure option to repeat previous " 5723 "frames (err %d)", 5724 mCodec->mComponentName.c_str(), 5725 err); 5726 return err; 5727 } 5728 } 5729 5730 if (mCodec->mMaxPtsGapUs > 0ll) { 5731 err = mCodec->mOMX->setInternalOption( 5732 mCodec->mNode, 5733 kPortIndexInput, 5734 IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP, 5735 &mCodec->mMaxPtsGapUs, 5736 sizeof(mCodec->mMaxPtsGapUs)); 5737 5738 if (err != OK) { 5739 ALOGE("[%s] Unable to configure max timestamp gap (err %d)", 5740 mCodec->mComponentName.c_str(), 5741 err); 5742 return err; 5743 } 5744 } 5745 5746 if (mCodec->mMaxFps > 0) { 5747 err = mCodec->mOMX->setInternalOption( 5748 mCodec->mNode, 5749 kPortIndexInput, 5750 IOMX::INTERNAL_OPTION_MAX_FPS, 5751 &mCodec->mMaxFps, 5752 sizeof(mCodec->mMaxFps)); 5753 5754 if (err != OK) { 5755 ALOGE("[%s] Unable to configure max fps (err %d)", 5756 mCodec->mComponentName.c_str(), 5757 err); 5758 return err; 5759 } 5760 } 5761 5762 if (mCodec->mTimePerCaptureUs > 0ll 5763 && mCodec->mTimePerFrameUs > 0ll) { 5764 int64_t timeLapse[2]; 5765 timeLapse[0] = mCodec->mTimePerFrameUs; 5766 timeLapse[1] = mCodec->mTimePerCaptureUs; 5767 err = mCodec->mOMX->setInternalOption( 5768 mCodec->mNode, 5769 kPortIndexInput, 5770 IOMX::INTERNAL_OPTION_TIME_LAPSE, 5771 &timeLapse[0], 5772 sizeof(timeLapse)); 5773 5774 if (err != OK) { 5775 ALOGE("[%s] Unable to configure time lapse (err %d)", 5776 mCodec->mComponentName.c_str(), 5777 err); 5778 return err; 5779 } 5780 } 5781 5782 if (mCodec->mCreateInputBuffersSuspended) { 5783 bool suspend = true; 5784 err = mCodec->mOMX->setInternalOption( 5785 mCodec->mNode, 5786 kPortIndexInput, 5787 IOMX::INTERNAL_OPTION_SUSPEND, 5788 &suspend, 5789 sizeof(suspend)); 5790 5791 if (err != OK) { 5792 ALOGE("[%s] Unable to configure option to suspend (err %d)", 5793 mCodec->mComponentName.c_str(), 5794 err); 5795 return err; 5796 } 5797 } 5798 5799 uint32_t usageBits; 5800 if (mCodec->mOMX->getParameter( 5801 mCodec->mNode, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits, 5802 &usageBits, sizeof(usageBits)) == OK) { 5803 mCodec->mInputFormat->setInt32( 5804 "using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN)); 5805 } 5806 5807 return OK; 5808} 5809 5810void ACodec::LoadedState::onCreateInputSurface( 5811 const sp<AMessage> & /* msg */) { 5812 ALOGV("onCreateInputSurface"); 5813 5814 sp<AMessage> notify = mCodec->mNotify->dup(); 5815 notify->setInt32("what", CodecBase::kWhatInputSurfaceCreated); 5816 5817 sp<IGraphicBufferProducer> bufferProducer; 5818 status_t err = mCodec->mOMX->createInputSurface( 5819 mCodec->mNode, kPortIndexInput, &bufferProducer, &mCodec->mInputMetadataType); 5820 5821 if (err == OK) { 5822 err = setupInputSurface(); 5823 } 5824 5825 if (err == OK) { 5826 notify->setObject("input-surface", 5827 new BufferProducerWrapper(bufferProducer)); 5828 } else { 5829 // Can't use mCodec->signalError() here -- MediaCodec won't forward 5830 // the error through because it's in the "configured" state. We 5831 // send a kWhatInputSurfaceCreated with an error value instead. 5832 ALOGE("[%s] onCreateInputSurface returning error %d", 5833 mCodec->mComponentName.c_str(), err); 5834 notify->setInt32("err", err); 5835 } 5836 notify->post(); 5837} 5838 5839void ACodec::LoadedState::onSetInputSurface( 5840 const sp<AMessage> &msg) { 5841 ALOGV("onSetInputSurface"); 5842 5843 sp<AMessage> notify = mCodec->mNotify->dup(); 5844 notify->setInt32("what", CodecBase::kWhatInputSurfaceAccepted); 5845 5846 sp<RefBase> obj; 5847 CHECK(msg->findObject("input-surface", &obj)); 5848 sp<PersistentSurface> surface = static_cast<PersistentSurface *>(obj.get()); 5849 5850 status_t err = mCodec->mOMX->setInputSurface( 5851 mCodec->mNode, kPortIndexInput, surface->getBufferConsumer(), 5852 &mCodec->mInputMetadataType); 5853 5854 if (err == OK) { 5855 err = setupInputSurface(); 5856 } 5857 5858 if (err != OK) { 5859 // Can't use mCodec->signalError() here -- MediaCodec won't forward 5860 // the error through because it's in the "configured" state. We 5861 // send a kWhatInputSurfaceAccepted with an error value instead. 5862 ALOGE("[%s] onSetInputSurface returning error %d", 5863 mCodec->mComponentName.c_str(), err); 5864 notify->setInt32("err", err); 5865 } 5866 notify->post(); 5867} 5868 5869void ACodec::LoadedState::onStart() { 5870 ALOGV("onStart"); 5871 5872 status_t err = mCodec->mOMX->sendCommand(mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle); 5873 if (err != OK) { 5874 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 5875 } else { 5876 mCodec->changeState(mCodec->mLoadedToIdleState); 5877 } 5878} 5879 5880//////////////////////////////////////////////////////////////////////////////// 5881 5882ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec) 5883 : BaseState(codec) { 5884} 5885 5886void ACodec::LoadedToIdleState::stateEntered() { 5887 ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str()); 5888 5889 status_t err; 5890 if ((err = allocateBuffers()) != OK) { 5891 ALOGE("Failed to allocate buffers after transitioning to IDLE state " 5892 "(error 0x%08x)", 5893 err); 5894 5895 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 5896 5897 mCodec->changeState(mCodec->mLoadedState); 5898 } 5899} 5900 5901status_t ACodec::LoadedToIdleState::allocateBuffers() { 5902 status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput); 5903 5904 if (err != OK) { 5905 return err; 5906 } 5907 5908 return mCodec->allocateBuffersOnPort(kPortIndexOutput); 5909} 5910 5911bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) { 5912 switch (msg->what()) { 5913 case kWhatSetParameters: 5914 case kWhatShutdown: 5915 { 5916 mCodec->deferMessage(msg); 5917 return true; 5918 } 5919 5920 case kWhatSignalEndOfInputStream: 5921 { 5922 mCodec->onSignalEndOfInputStream(); 5923 return true; 5924 } 5925 5926 case kWhatResume: 5927 { 5928 // We'll be active soon enough. 5929 return true; 5930 } 5931 5932 case kWhatFlush: 5933 { 5934 // We haven't even started yet, so we're flushed alright... 5935 sp<AMessage> notify = mCodec->mNotify->dup(); 5936 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 5937 notify->post(); 5938 return true; 5939 } 5940 5941 default: 5942 return BaseState::onMessageReceived(msg); 5943 } 5944} 5945 5946bool ACodec::LoadedToIdleState::onOMXEvent( 5947 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 5948 switch (event) { 5949 case OMX_EventCmdComplete: 5950 { 5951 status_t err = OK; 5952 if (data1 != (OMX_U32)OMX_CommandStateSet 5953 || data2 != (OMX_U32)OMX_StateIdle) { 5954 ALOGE("Unexpected command completion in LoadedToIdleState: %s(%u) %s(%u)", 5955 asString((OMX_COMMANDTYPE)data1), data1, 5956 asString((OMX_STATETYPE)data2), data2); 5957 err = FAILED_TRANSACTION; 5958 } 5959 5960 if (err == OK) { 5961 err = mCodec->mOMX->sendCommand( 5962 mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting); 5963 } 5964 5965 if (err != OK) { 5966 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 5967 } else { 5968 mCodec->changeState(mCodec->mIdleToExecutingState); 5969 } 5970 5971 return true; 5972 } 5973 5974 default: 5975 return BaseState::onOMXEvent(event, data1, data2); 5976 } 5977} 5978 5979//////////////////////////////////////////////////////////////////////////////// 5980 5981ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec) 5982 : BaseState(codec) { 5983} 5984 5985void ACodec::IdleToExecutingState::stateEntered() { 5986 ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str()); 5987} 5988 5989bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) { 5990 switch (msg->what()) { 5991 case kWhatSetParameters: 5992 case kWhatShutdown: 5993 { 5994 mCodec->deferMessage(msg); 5995 return true; 5996 } 5997 5998 case kWhatResume: 5999 { 6000 // We'll be active soon enough. 6001 return true; 6002 } 6003 6004 case kWhatFlush: 6005 { 6006 // We haven't even started yet, so we're flushed alright... 6007 sp<AMessage> notify = mCodec->mNotify->dup(); 6008 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 6009 notify->post(); 6010 6011 return true; 6012 } 6013 6014 case kWhatSignalEndOfInputStream: 6015 { 6016 mCodec->onSignalEndOfInputStream(); 6017 return true; 6018 } 6019 6020 default: 6021 return BaseState::onMessageReceived(msg); 6022 } 6023} 6024 6025bool ACodec::IdleToExecutingState::onOMXEvent( 6026 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 6027 switch (event) { 6028 case OMX_EventCmdComplete: 6029 { 6030 if (data1 != (OMX_U32)OMX_CommandStateSet 6031 || data2 != (OMX_U32)OMX_StateExecuting) { 6032 ALOGE("Unexpected command completion in IdleToExecutingState: %s(%u) %s(%u)", 6033 asString((OMX_COMMANDTYPE)data1), data1, 6034 asString((OMX_STATETYPE)data2), data2); 6035 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6036 return true; 6037 } 6038 6039 mCodec->mExecutingState->resume(); 6040 mCodec->changeState(mCodec->mExecutingState); 6041 6042 return true; 6043 } 6044 6045 default: 6046 return BaseState::onOMXEvent(event, data1, data2); 6047 } 6048} 6049 6050//////////////////////////////////////////////////////////////////////////////// 6051 6052ACodec::ExecutingState::ExecutingState(ACodec *codec) 6053 : BaseState(codec), 6054 mActive(false) { 6055} 6056 6057ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode( 6058 OMX_U32 /* portIndex */) { 6059 return RESUBMIT_BUFFERS; 6060} 6061 6062void ACodec::ExecutingState::submitOutputMetaBuffers() { 6063 // submit as many buffers as there are input buffers with the codec 6064 // in case we are in port reconfiguring 6065 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 6066 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 6067 6068 if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) { 6069 if (mCodec->submitOutputMetadataBuffer() != OK) 6070 break; 6071 } 6072 } 6073 6074 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** 6075 mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround(); 6076} 6077 6078void ACodec::ExecutingState::submitRegularOutputBuffers() { 6079 bool failed = false; 6080 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) { 6081 BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i); 6082 6083 if (mCodec->mNativeWindow != NULL) { 6084 if (info->mStatus != BufferInfo::OWNED_BY_US 6085 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) { 6086 ALOGE("buffers should be owned by us or the surface"); 6087 failed = true; 6088 break; 6089 } 6090 6091 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 6092 continue; 6093 } 6094 } else { 6095 if (info->mStatus != BufferInfo::OWNED_BY_US) { 6096 ALOGE("buffers should be owned by us"); 6097 failed = true; 6098 break; 6099 } 6100 } 6101 6102 ALOGV("[%s] calling fillBuffer %u", mCodec->mComponentName.c_str(), info->mBufferID); 6103 6104 info->checkWriteFence("submitRegularOutputBuffers"); 6105 status_t err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID, info->mFenceFd); 6106 info->mFenceFd = -1; 6107 if (err != OK) { 6108 failed = true; 6109 break; 6110 } 6111 6112 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 6113 } 6114 6115 if (failed) { 6116 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6117 } 6118} 6119 6120void ACodec::ExecutingState::submitOutputBuffers() { 6121 submitRegularOutputBuffers(); 6122 if (mCodec->storingMetadataInDecodedBuffers()) { 6123 submitOutputMetaBuffers(); 6124 } 6125} 6126 6127void ACodec::ExecutingState::resume() { 6128 if (mActive) { 6129 ALOGV("[%s] We're already active, no need to resume.", mCodec->mComponentName.c_str()); 6130 return; 6131 } 6132 6133 submitOutputBuffers(); 6134 6135 // Post all available input buffers 6136 if (mCodec->mBuffers[kPortIndexInput].size() == 0u) { 6137 ALOGW("[%s] we don't have any input buffers to resume", mCodec->mComponentName.c_str()); 6138 } 6139 6140 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) { 6141 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 6142 if (info->mStatus == BufferInfo::OWNED_BY_US) { 6143 postFillThisBuffer(info); 6144 } 6145 } 6146 6147 mActive = true; 6148} 6149 6150void ACodec::ExecutingState::stateEntered() { 6151 ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str()); 6152 6153 mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC)); 6154 mCodec->processDeferredMessages(); 6155} 6156 6157bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) { 6158 bool handled = false; 6159 6160 switch (msg->what()) { 6161 case kWhatShutdown: 6162 { 6163 int32_t keepComponentAllocated; 6164 CHECK(msg->findInt32( 6165 "keepComponentAllocated", &keepComponentAllocated)); 6166 6167 mCodec->mShutdownInProgress = true; 6168 mCodec->mExplicitShutdown = true; 6169 mCodec->mKeepComponentAllocated = keepComponentAllocated; 6170 6171 mActive = false; 6172 6173 status_t err = mCodec->mOMX->sendCommand( 6174 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle); 6175 if (err != OK) { 6176 if (keepComponentAllocated) { 6177 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6178 } 6179 // TODO: do some recovery here. 6180 } else { 6181 mCodec->changeState(mCodec->mExecutingToIdleState); 6182 } 6183 6184 handled = true; 6185 break; 6186 } 6187 6188 case kWhatFlush: 6189 { 6190 ALOGV("[%s] ExecutingState flushing now " 6191 "(codec owns %zu/%zu input, %zu/%zu output).", 6192 mCodec->mComponentName.c_str(), 6193 mCodec->countBuffersOwnedByComponent(kPortIndexInput), 6194 mCodec->mBuffers[kPortIndexInput].size(), 6195 mCodec->countBuffersOwnedByComponent(kPortIndexOutput), 6196 mCodec->mBuffers[kPortIndexOutput].size()); 6197 6198 mActive = false; 6199 6200 status_t err = mCodec->mOMX->sendCommand(mCodec->mNode, OMX_CommandFlush, OMX_ALL); 6201 if (err != OK) { 6202 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6203 } else { 6204 mCodec->changeState(mCodec->mFlushingState); 6205 } 6206 6207 handled = true; 6208 break; 6209 } 6210 6211 case kWhatResume: 6212 { 6213 resume(); 6214 6215 handled = true; 6216 break; 6217 } 6218 6219 case kWhatRequestIDRFrame: 6220 { 6221 status_t err = mCodec->requestIDRFrame(); 6222 if (err != OK) { 6223 ALOGW("Requesting an IDR frame failed."); 6224 } 6225 6226 handled = true; 6227 break; 6228 } 6229 6230 case kWhatSetParameters: 6231 { 6232 sp<AMessage> params; 6233 CHECK(msg->findMessage("params", ¶ms)); 6234 6235 status_t err = mCodec->setParameters(params); 6236 6237 sp<AMessage> reply; 6238 if (msg->findMessage("reply", &reply)) { 6239 reply->setInt32("err", err); 6240 reply->post(); 6241 } 6242 6243 handled = true; 6244 break; 6245 } 6246 6247 case ACodec::kWhatSignalEndOfInputStream: 6248 { 6249 mCodec->onSignalEndOfInputStream(); 6250 handled = true; 6251 break; 6252 } 6253 6254 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** 6255 case kWhatSubmitOutputMetadataBufferIfEOS: 6256 { 6257 if (mCodec->mPortEOS[kPortIndexInput] && 6258 !mCodec->mPortEOS[kPortIndexOutput]) { 6259 status_t err = mCodec->submitOutputMetadataBuffer(); 6260 if (err == OK) { 6261 mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround(); 6262 } 6263 } 6264 return true; 6265 } 6266 6267 default: 6268 handled = BaseState::onMessageReceived(msg); 6269 break; 6270 } 6271 6272 return handled; 6273} 6274 6275status_t ACodec::setParameters(const sp<AMessage> ¶ms) { 6276 int32_t videoBitrate; 6277 if (params->findInt32("video-bitrate", &videoBitrate)) { 6278 OMX_VIDEO_CONFIG_BITRATETYPE configParams; 6279 InitOMXParams(&configParams); 6280 configParams.nPortIndex = kPortIndexOutput; 6281 configParams.nEncodeBitrate = videoBitrate; 6282 6283 status_t err = mOMX->setConfig( 6284 mNode, 6285 OMX_IndexConfigVideoBitrate, 6286 &configParams, 6287 sizeof(configParams)); 6288 6289 if (err != OK) { 6290 ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d", 6291 videoBitrate, err); 6292 6293 return err; 6294 } 6295 } 6296 6297 int64_t skipFramesBeforeUs; 6298 if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) { 6299 status_t err = 6300 mOMX->setInternalOption( 6301 mNode, 6302 kPortIndexInput, 6303 IOMX::INTERNAL_OPTION_START_TIME, 6304 &skipFramesBeforeUs, 6305 sizeof(skipFramesBeforeUs)); 6306 6307 if (err != OK) { 6308 ALOGE("Failed to set parameter 'skip-frames-before' (err %d)", err); 6309 return err; 6310 } 6311 } 6312 6313 int32_t dropInputFrames; 6314 if (params->findInt32("drop-input-frames", &dropInputFrames)) { 6315 bool suspend = dropInputFrames != 0; 6316 6317 status_t err = 6318 mOMX->setInternalOption( 6319 mNode, 6320 kPortIndexInput, 6321 IOMX::INTERNAL_OPTION_SUSPEND, 6322 &suspend, 6323 sizeof(suspend)); 6324 6325 if (err != OK) { 6326 ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err); 6327 return err; 6328 } 6329 } 6330 6331 int32_t dummy; 6332 if (params->findInt32("request-sync", &dummy)) { 6333 status_t err = requestIDRFrame(); 6334 6335 if (err != OK) { 6336 ALOGE("Requesting a sync frame failed w/ err %d", err); 6337 return err; 6338 } 6339 } 6340 6341 float rate; 6342 if (params->findFloat("operating-rate", &rate) && rate > 0) { 6343 status_t err = setOperatingRate(rate, mIsVideo); 6344 if (err != OK) { 6345 ALOGE("Failed to set parameter 'operating-rate' (err %d)", err); 6346 return err; 6347 } 6348 } 6349 6350 return OK; 6351} 6352 6353void ACodec::onSignalEndOfInputStream() { 6354 sp<AMessage> notify = mNotify->dup(); 6355 notify->setInt32("what", CodecBase::kWhatSignaledInputEOS); 6356 6357 status_t err = mOMX->signalEndOfInputStream(mNode); 6358 if (err != OK) { 6359 notify->setInt32("err", err); 6360 } 6361 notify->post(); 6362} 6363 6364bool ACodec::ExecutingState::onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) { 6365 mCodec->onFrameRendered(mediaTimeUs, systemNano); 6366 return true; 6367} 6368 6369bool ACodec::ExecutingState::onOMXEvent( 6370 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 6371 switch (event) { 6372 case OMX_EventPortSettingsChanged: 6373 { 6374 CHECK_EQ(data1, (OMX_U32)kPortIndexOutput); 6375 6376 if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) { 6377 mCodec->mMetadataBuffersToSubmit = 0; 6378 CHECK_EQ(mCodec->mOMX->sendCommand( 6379 mCodec->mNode, 6380 OMX_CommandPortDisable, kPortIndexOutput), 6381 (status_t)OK); 6382 6383 mCodec->freeOutputBuffersNotOwnedByComponent(); 6384 6385 mCodec->changeState(mCodec->mOutputPortSettingsChangedState); 6386 } else if (data2 == OMX_IndexConfigCommonOutputCrop) { 6387 mCodec->mSentFormat = false; 6388 6389 if (mCodec->mTunneled) { 6390 sp<AMessage> dummy = new AMessage(kWhatOutputBufferDrained, mCodec); 6391 mCodec->sendFormatChange(dummy); 6392 } 6393 } else { 6394 ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08x", 6395 mCodec->mComponentName.c_str(), data2); 6396 } 6397 6398 return true; 6399 } 6400 6401 case OMX_EventBufferFlag: 6402 { 6403 return true; 6404 } 6405 6406 default: 6407 return BaseState::onOMXEvent(event, data1, data2); 6408 } 6409} 6410 6411//////////////////////////////////////////////////////////////////////////////// 6412 6413ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState( 6414 ACodec *codec) 6415 : BaseState(codec) { 6416} 6417 6418ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode( 6419 OMX_U32 portIndex) { 6420 if (portIndex == kPortIndexOutput) { 6421 return FREE_BUFFERS; 6422 } 6423 6424 CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput); 6425 6426 return RESUBMIT_BUFFERS; 6427} 6428 6429bool ACodec::OutputPortSettingsChangedState::onMessageReceived( 6430 const sp<AMessage> &msg) { 6431 bool handled = false; 6432 6433 switch (msg->what()) { 6434 case kWhatFlush: 6435 case kWhatShutdown: 6436 case kWhatResume: 6437 case kWhatSetParameters: 6438 { 6439 if (msg->what() == kWhatResume) { 6440 ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str()); 6441 } 6442 6443 mCodec->deferMessage(msg); 6444 handled = true; 6445 break; 6446 } 6447 6448 default: 6449 handled = BaseState::onMessageReceived(msg); 6450 break; 6451 } 6452 6453 return handled; 6454} 6455 6456void ACodec::OutputPortSettingsChangedState::stateEntered() { 6457 ALOGV("[%s] Now handling output port settings change", 6458 mCodec->mComponentName.c_str()); 6459} 6460 6461bool ACodec::OutputPortSettingsChangedState::onOMXFrameRendered( 6462 int64_t mediaTimeUs, nsecs_t systemNano) { 6463 mCodec->onFrameRendered(mediaTimeUs, systemNano); 6464 return true; 6465} 6466 6467bool ACodec::OutputPortSettingsChangedState::onOMXEvent( 6468 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 6469 switch (event) { 6470 case OMX_EventCmdComplete: 6471 { 6472 if (data1 == (OMX_U32)OMX_CommandPortDisable) { 6473 if (data2 != (OMX_U32)kPortIndexOutput) { 6474 ALOGW("ignoring EventCmdComplete CommandPortDisable for port %u", data2); 6475 return false; 6476 } 6477 6478 ALOGV("[%s] Output port now disabled.", mCodec->mComponentName.c_str()); 6479 6480 status_t err = OK; 6481 if (!mCodec->mBuffers[kPortIndexOutput].isEmpty()) { 6482 ALOGE("disabled port should be empty, but has %zu buffers", 6483 mCodec->mBuffers[kPortIndexOutput].size()); 6484 err = FAILED_TRANSACTION; 6485 } else { 6486 mCodec->mDealer[kPortIndexOutput].clear(); 6487 } 6488 6489 if (err == OK) { 6490 err = mCodec->mOMX->sendCommand( 6491 mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput); 6492 } 6493 6494 if (err == OK) { 6495 err = mCodec->allocateBuffersOnPort(kPortIndexOutput); 6496 ALOGE_IF(err != OK, "Failed to allocate output port buffers after port " 6497 "reconfiguration: (%d)", err); 6498 } 6499 6500 if (err != OK) { 6501 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6502 6503 // This is technically not correct, but appears to be 6504 // the only way to free the component instance. 6505 // Controlled transitioning from excecuting->idle 6506 // and idle->loaded seem impossible probably because 6507 // the output port never finishes re-enabling. 6508 mCodec->mShutdownInProgress = true; 6509 mCodec->mKeepComponentAllocated = false; 6510 mCodec->changeState(mCodec->mLoadedState); 6511 } 6512 6513 return true; 6514 } else if (data1 == (OMX_U32)OMX_CommandPortEnable) { 6515 if (data2 != (OMX_U32)kPortIndexOutput) { 6516 ALOGW("ignoring EventCmdComplete OMX_CommandPortEnable for port %u", data2); 6517 return false; 6518 } 6519 6520 mCodec->mSentFormat = false; 6521 6522 if (mCodec->mTunneled) { 6523 sp<AMessage> dummy = new AMessage(kWhatOutputBufferDrained, mCodec); 6524 mCodec->sendFormatChange(dummy); 6525 } 6526 6527 ALOGV("[%s] Output port now reenabled.", mCodec->mComponentName.c_str()); 6528 6529 if (mCodec->mExecutingState->active()) { 6530 mCodec->mExecutingState->submitOutputBuffers(); 6531 } 6532 6533 mCodec->changeState(mCodec->mExecutingState); 6534 6535 return true; 6536 } 6537 6538 return false; 6539 } 6540 6541 default: 6542 return false; 6543 } 6544} 6545 6546//////////////////////////////////////////////////////////////////////////////// 6547 6548ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec) 6549 : BaseState(codec), 6550 mComponentNowIdle(false) { 6551} 6552 6553bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) { 6554 bool handled = false; 6555 6556 switch (msg->what()) { 6557 case kWhatFlush: 6558 { 6559 // Don't send me a flush request if you previously wanted me 6560 // to shutdown. 6561 ALOGW("Ignoring flush request in ExecutingToIdleState"); 6562 break; 6563 } 6564 6565 case kWhatShutdown: 6566 { 6567 // We're already doing that... 6568 6569 handled = true; 6570 break; 6571 } 6572 6573 default: 6574 handled = BaseState::onMessageReceived(msg); 6575 break; 6576 } 6577 6578 return handled; 6579} 6580 6581void ACodec::ExecutingToIdleState::stateEntered() { 6582 ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str()); 6583 6584 mComponentNowIdle = false; 6585 mCodec->mSentFormat = false; 6586} 6587 6588bool ACodec::ExecutingToIdleState::onOMXEvent( 6589 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 6590 switch (event) { 6591 case OMX_EventCmdComplete: 6592 { 6593 if (data1 != (OMX_U32)OMX_CommandStateSet 6594 || data2 != (OMX_U32)OMX_StateIdle) { 6595 ALOGE("Unexpected command completion in ExecutingToIdleState: %s(%u) %s(%u)", 6596 asString((OMX_COMMANDTYPE)data1), data1, 6597 asString((OMX_STATETYPE)data2), data2); 6598 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6599 return true; 6600 } 6601 6602 mComponentNowIdle = true; 6603 6604 changeStateIfWeOwnAllBuffers(); 6605 6606 return true; 6607 } 6608 6609 case OMX_EventPortSettingsChanged: 6610 case OMX_EventBufferFlag: 6611 { 6612 // We're shutting down and don't care about this anymore. 6613 return true; 6614 } 6615 6616 default: 6617 return BaseState::onOMXEvent(event, data1, data2); 6618 } 6619} 6620 6621void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() { 6622 if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) { 6623 status_t err = mCodec->mOMX->sendCommand( 6624 mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded); 6625 if (err == OK) { 6626 err = mCodec->freeBuffersOnPort(kPortIndexInput); 6627 status_t err2 = mCodec->freeBuffersOnPort(kPortIndexOutput); 6628 if (err == OK) { 6629 err = err2; 6630 } 6631 } 6632 6633 if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown) 6634 && mCodec->mNativeWindow != NULL) { 6635 // We push enough 1x1 blank buffers to ensure that one of 6636 // them has made it to the display. This allows the OMX 6637 // component teardown to zero out any protected buffers 6638 // without the risk of scanning out one of those buffers. 6639 pushBlankBuffersToNativeWindow(mCodec->mNativeWindow.get()); 6640 } 6641 6642 if (err != OK) { 6643 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6644 return; 6645 } 6646 6647 mCodec->changeState(mCodec->mIdleToLoadedState); 6648 } 6649} 6650 6651void ACodec::ExecutingToIdleState::onInputBufferFilled( 6652 const sp<AMessage> &msg) { 6653 BaseState::onInputBufferFilled(msg); 6654 6655 changeStateIfWeOwnAllBuffers(); 6656} 6657 6658void ACodec::ExecutingToIdleState::onOutputBufferDrained( 6659 const sp<AMessage> &msg) { 6660 BaseState::onOutputBufferDrained(msg); 6661 6662 changeStateIfWeOwnAllBuffers(); 6663} 6664 6665//////////////////////////////////////////////////////////////////////////////// 6666 6667ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec) 6668 : BaseState(codec) { 6669} 6670 6671bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) { 6672 bool handled = false; 6673 6674 switch (msg->what()) { 6675 case kWhatShutdown: 6676 { 6677 // We're already doing that... 6678 6679 handled = true; 6680 break; 6681 } 6682 6683 case kWhatFlush: 6684 { 6685 // Don't send me a flush request if you previously wanted me 6686 // to shutdown. 6687 ALOGE("Got flush request in IdleToLoadedState"); 6688 break; 6689 } 6690 6691 default: 6692 handled = BaseState::onMessageReceived(msg); 6693 break; 6694 } 6695 6696 return handled; 6697} 6698 6699void ACodec::IdleToLoadedState::stateEntered() { 6700 ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str()); 6701} 6702 6703bool ACodec::IdleToLoadedState::onOMXEvent( 6704 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 6705 switch (event) { 6706 case OMX_EventCmdComplete: 6707 { 6708 if (data1 != (OMX_U32)OMX_CommandStateSet 6709 || data2 != (OMX_U32)OMX_StateLoaded) { 6710 ALOGE("Unexpected command completion in IdleToLoadedState: %s(%u) %s(%u)", 6711 asString((OMX_COMMANDTYPE)data1), data1, 6712 asString((OMX_STATETYPE)data2), data2); 6713 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6714 return true; 6715 } 6716 6717 mCodec->changeState(mCodec->mLoadedState); 6718 6719 return true; 6720 } 6721 6722 default: 6723 return BaseState::onOMXEvent(event, data1, data2); 6724 } 6725} 6726 6727//////////////////////////////////////////////////////////////////////////////// 6728 6729ACodec::FlushingState::FlushingState(ACodec *codec) 6730 : BaseState(codec) { 6731} 6732 6733void ACodec::FlushingState::stateEntered() { 6734 ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str()); 6735 6736 mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false; 6737} 6738 6739bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) { 6740 bool handled = false; 6741 6742 switch (msg->what()) { 6743 case kWhatShutdown: 6744 { 6745 mCodec->deferMessage(msg); 6746 break; 6747 } 6748 6749 case kWhatFlush: 6750 { 6751 // We're already doing this right now. 6752 handled = true; 6753 break; 6754 } 6755 6756 default: 6757 handled = BaseState::onMessageReceived(msg); 6758 break; 6759 } 6760 6761 return handled; 6762} 6763 6764bool ACodec::FlushingState::onOMXEvent( 6765 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 6766 ALOGV("[%s] FlushingState onOMXEvent(%u,%d)", 6767 mCodec->mComponentName.c_str(), event, (OMX_S32)data1); 6768 6769 switch (event) { 6770 case OMX_EventCmdComplete: 6771 { 6772 if (data1 != (OMX_U32)OMX_CommandFlush) { 6773 ALOGE("unexpected EventCmdComplete %s(%d) data2:%d in FlushingState", 6774 asString((OMX_COMMANDTYPE)data1), data1, data2); 6775 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6776 return true; 6777 } 6778 6779 if (data2 == kPortIndexInput || data2 == kPortIndexOutput) { 6780 if (mFlushComplete[data2]) { 6781 ALOGW("Flush already completed for %s port", 6782 data2 == kPortIndexInput ? "input" : "output"); 6783 return true; 6784 } 6785 mFlushComplete[data2] = true; 6786 6787 if (mFlushComplete[kPortIndexInput] && mFlushComplete[kPortIndexOutput]) { 6788 changeStateIfWeOwnAllBuffers(); 6789 } 6790 } else if (data2 == OMX_ALL) { 6791 if (!mFlushComplete[kPortIndexInput] || !mFlushComplete[kPortIndexOutput]) { 6792 ALOGW("received flush complete event for OMX_ALL before ports have been" 6793 "flushed (%d/%d)", 6794 mFlushComplete[kPortIndexInput], mFlushComplete[kPortIndexOutput]); 6795 return false; 6796 } 6797 6798 changeStateIfWeOwnAllBuffers(); 6799 } else { 6800 ALOGW("data2 not OMX_ALL but %u in EventCmdComplete CommandFlush", data2); 6801 } 6802 6803 return true; 6804 } 6805 6806 case OMX_EventPortSettingsChanged: 6807 { 6808 sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec); 6809 msg->setInt32("type", omx_message::EVENT); 6810 msg->setInt32("node", mCodec->mNode); 6811 msg->setInt32("event", event); 6812 msg->setInt32("data1", data1); 6813 msg->setInt32("data2", data2); 6814 6815 ALOGV("[%s] Deferring OMX_EventPortSettingsChanged", 6816 mCodec->mComponentName.c_str()); 6817 6818 mCodec->deferMessage(msg); 6819 6820 return true; 6821 } 6822 6823 default: 6824 return BaseState::onOMXEvent(event, data1, data2); 6825 } 6826 6827 return true; 6828} 6829 6830void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) { 6831 BaseState::onOutputBufferDrained(msg); 6832 6833 changeStateIfWeOwnAllBuffers(); 6834} 6835 6836void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) { 6837 BaseState::onInputBufferFilled(msg); 6838 6839 changeStateIfWeOwnAllBuffers(); 6840} 6841 6842void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() { 6843 if (mFlushComplete[kPortIndexInput] 6844 && mFlushComplete[kPortIndexOutput] 6845 && mCodec->allYourBuffersAreBelongToUs()) { 6846 // We now own all buffers except possibly those still queued with 6847 // the native window for rendering. Let's get those back as well. 6848 mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs(); 6849 6850 mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC)); 6851 6852 sp<AMessage> notify = mCodec->mNotify->dup(); 6853 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 6854 notify->post(); 6855 6856 mCodec->mPortEOS[kPortIndexInput] = 6857 mCodec->mPortEOS[kPortIndexOutput] = false; 6858 6859 mCodec->mInputEOSResult = OK; 6860 6861 if (mCodec->mSkipCutBuffer != NULL) { 6862 mCodec->mSkipCutBuffer->clear(); 6863 } 6864 6865 mCodec->changeState(mCodec->mExecutingState); 6866 } 6867} 6868 6869} // namespace android 6870