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