MediaCodec.cpp revision 3b2847fa5506dc265d2e46f067bfbb66ae209f74
14774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall/* 2518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian * Copyright 2012, The Android Open Source Project 3518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian * 44774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall * Licensed under the Apache License, Version 2.0 (the "License"); 54774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall * you may not use this file except in compliance with the License. 64774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall * You may obtain a copy of the License at 7518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian * 84774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall * http://www.apache.org/licenses/LICENSE-2.0 9518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian * 104774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall * Unless required by applicable law or agreed to in writing, software 114774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall * distributed under the License is distributed on an "AS IS" BASIS, 124774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall * See the License for the specific language governing permissions and 14518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian * limitations under the License. 15518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian */ 16518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 171c8e95cf86f2182986385bc1ee85f13f425f3a3aJamie Gennis//#define LOG_NDEBUG 0 181c8e95cf86f2182986385bc1ee85f13f425f3a3aJamie Gennis#define LOG_TAG "MediaCodec" 19c07b52060acd627c8510c1a9151e0753fce76330Jesse Hall#include <inttypes.h> 20518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 21518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include "include/avc_utils.h" 22518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include "include/SecureBuffer.h" 23518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include "include/SharedMemoryBuffer.h" 24518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include "include/SoftwareRenderer.h" 25518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 26518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include <android/media/IDescrambler.h> 27518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include <binder/IMemory.h> 28518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include <binder/IPCThreadState.h> 29518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include <binder/IServiceManager.h> 30518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include <binder/MemoryDealer.h> 31518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include <gui/BufferQueue.h> 327db993a98b9239bd4e384cc4aa128262fe3cf52cMathias Agopian#include <gui/Surface.h> 33518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include <media/ICrypto.h> 34518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include <media/IOMX.h> 35518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include <media/IResourceManagerService.h> 36518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include <media/MediaCodecBuffer.h> 37518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include <media/MediaAnalyticsItem.h> 38518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include <media/stagefright/foundation/ABuffer.h> 391c8e95cf86f2182986385bc1ee85f13f425f3a3aJamie Gennis#include <media/stagefright/foundation/ADebug.h> 40518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include <media/stagefright/foundation/AMessage.h> 4139c24a20bbc697630d2b92c251b70c04d6f9d00cMathias Agopian#include <media/stagefright/foundation/AString.h> 4239c24a20bbc697630d2b92c251b70c04d6f9d00cMathias Agopian#include <media/stagefright/foundation/AUtils.h> 4339c24a20bbc697630d2b92c251b70c04d6f9d00cMathias Agopian#include <media/stagefright/foundation/hexdump.h> 44518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include <media/stagefright/ACodec.h> 45518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include <media/stagefright/BufferProducerWrapper.h> 46518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include <media/stagefright/MediaCodec.h> 47518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include <media/stagefright/MediaCodecList.h> 48ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian#include <media/stagefright/MediaDefs.h> 49518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include <media/stagefright/MediaErrors.h> 50518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include <media/stagefright/MediaFilter.h> 51518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include <media/stagefright/MetaData.h> 52518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include <media/stagefright/OMXClient.h> 53518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include <media/stagefright/PersistentSurface.h> 54e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian#include <media/stagefright/SurfaceUtils.h> 55e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian#include <mediautils/BatteryNotifier.h> 56518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include <private/android_filesystem_config.h> 57518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include <utils/Log.h> 58518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include <utils/Singleton.h> 59518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 60518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopiannamespace android { 61e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian 6221558daf691dbcdff4a41e659fd013273db4d0b7Jesse Hall// key for media statistics 63e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopianstatic const char *kCodecKeyName = "codec"; 6421558daf691dbcdff4a41e659fd013273db4d0b7Jesse Hall// attrs for media statistics 6521558daf691dbcdff4a41e659fd013273db4d0b7Jesse Hallstatic const char *kCodecCodec = "codec"; /* e.g. OMX.google.aac.decoder */ 66e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopianstatic const char *kCodecMime = "mime"; /* e.g. audio/mime */ 6721558daf691dbcdff4a41e659fd013273db4d0b7Jesse Hallstatic const char *kCodecMode = "mode"; /* audio, video */ 6821558daf691dbcdff4a41e659fd013273db4d0b7Jesse Hallstatic const char *kCodecSecure = "secure"; /* 0, 1 */ 6921558daf691dbcdff4a41e659fd013273db4d0b7Jesse Hall 7021558daf691dbcdff4a41e659fd013273db4d0b7Jesse Hall 7121558daf691dbcdff4a41e659fd013273db4d0b7Jesse Hall 7221558daf691dbcdff4a41e659fd013273db4d0b7Jesse Hallstatic int64_t getId(const sp<IResourceManagerClient> &client) { 7321558daf691dbcdff4a41e659fd013273db4d0b7Jesse Hall return (int64_t) client.get(); 7421558daf691dbcdff4a41e659fd013273db4d0b7Jesse Hall} 75e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian 7621558daf691dbcdff4a41e659fd013273db4d0b7Jesse Hallstatic bool isResourceError(status_t err) { 7721558daf691dbcdff4a41e659fd013273db4d0b7Jesse Hall return (err == NO_MEMORY); 7821558daf691dbcdff4a41e659fd013273db4d0b7Jesse Hall} 7921558daf691dbcdff4a41e659fd013273db4d0b7Jesse Hall 80e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopianstatic const int kMaxRetry = 2; 81e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopianstatic const int kMaxReclaimWaitTimeInUs = 500000; // 0.5s 82e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopianstatic const int kNumBuffersAlign = 16; 83e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian 84e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian//////////////////////////////////////////////////////////////////////////////// 85e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian 86e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopianstruct ResourceManagerClient : public BnResourceManagerClient { 87e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian explicit ResourceManagerClient(MediaCodec* codec) : mMediaCodec(codec) {} 88e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian 89e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian virtual bool reclaimResource() { 90f6d1c3930eeba6b089ba12fb82ecad1c6622e550Jamie Gennis sp<MediaCodec> codec = mMediaCodec.promote(); 91e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian if (codec == NULL) { 92e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian // codec is already gone. 93e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian return true; 942bb716871cf8bfadfff1193ed798da3bffc1f8ecMathias Agopian } 95e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian status_t err = codec->reclaim(); 96e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian if (err == WOULD_BLOCK) { 97e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian ALOGD("Wait for the client to release codec."); 98e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian usleep(kMaxReclaimWaitTimeInUs); 99e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian ALOGD("Try to reclaim again."); 100e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian err = codec->reclaim(true /* force */); 101e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian } 102e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian if (err != OK) { 103e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian ALOGW("ResourceManagerClient failed to release codec with err %d", err); 104e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian } 105e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian return (err == OK); 106e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian } 107e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian 108e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian virtual String8 getName() { 109e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian String8 ret; 110e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian sp<MediaCodec> codec = mMediaCodec.promote(); 111e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian if (codec == NULL) { 112518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian // codec is already gone. 113518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return ret; 114518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 115518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 116e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian AString name; 117e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian if (codec->getName(&name) == OK) { 118518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian ret.setTo(name.c_str()); 119518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 120518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return ret; 121518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 122e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian 123e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopianprotected: 124e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian virtual ~ResourceManagerClient() {} 125e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian 126e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopianprivate: 127e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian wp<MediaCodec> mMediaCodec; 128e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian 129e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian DISALLOW_EVIL_CONSTRUCTORS(ResourceManagerClient); 130e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian}; 131e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian 132e9b3dfb7d5cc233747407381a51a081c335dc076Mathias AgopianMediaCodec::ResourceManagerServiceProxy::ResourceManagerServiceProxy(pid_t pid) 133e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian : mPid(pid) { 134e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian if (mPid == MediaCodec::kNoPid) { 135e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian mPid = IPCThreadState::self()->getCallingPid(); 1361c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang } 1371c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang} 1381c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang 1391c3d72a2291827fb15e2ef311a571c860e0dba41Jonas YangMediaCodec::ResourceManagerServiceProxy::~ResourceManagerServiceProxy() { 140e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian if (mService != NULL) { 1412bb716871cf8bfadfff1193ed798da3bffc1f8ecMathias Agopian IInterface::asBinder(mService)->unlinkToDeath(this); 1422bb716871cf8bfadfff1193ed798da3bffc1f8ecMathias Agopian } 1432bb716871cf8bfadfff1193ed798da3bffc1f8ecMathias Agopian} 144e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian 145e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopianvoid MediaCodec::ResourceManagerServiceProxy::init() { 146e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian sp<IServiceManager> sm = defaultServiceManager(); 147e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian sp<IBinder> binder = sm->getService(String16("media.resource_manager")); 148518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mService = interface_cast<IResourceManagerService>(binder); 149518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (mService == NULL) { 150e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian ALOGE("Failed to get ResourceManagerService"); 151e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian return; 152e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian } 153e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian IInterface::asBinder(mService)->linkToDeath(this); 154e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian} 155e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian 156e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopianvoid MediaCodec::ResourceManagerServiceProxy::binderDied(const wp<IBinder>& /*who*/) { 157e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian ALOGW("ResourceManagerService died."); 158e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian Mutex::Autolock _l(mLock); 159e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian mService.clear(); 160e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian} 161e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian 162518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianvoid MediaCodec::ResourceManagerServiceProxy::addResource( 163518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian int64_t clientId, 164518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian const sp<IResourceManagerClient> &client, 165518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian const Vector<MediaResource> &resources) { 166518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian Mutex::Autolock _l(mLock); 167518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (mService == NULL) { 168518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return; 169518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 170518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mService->addResource(mPid, clientId, client, resources); 171518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 172518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 173518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianvoid MediaCodec::ResourceManagerServiceProxy::removeResource(int64_t clientId) { 174518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian Mutex::Autolock _l(mLock); 175518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (mService == NULL) { 176518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return; 177518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 178518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mService->removeResource(mPid, clientId); 179518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 180518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 181518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianbool MediaCodec::ResourceManagerServiceProxy::reclaimResource( 182a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy const Vector<MediaResource> &resources) { 183a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy Mutex::Autolock _l(mLock); 184518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (mService == NULL) { 185e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian return false; 186518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 187518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return mService->reclaimResource(mPid, resources); 188e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian} 189518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 190518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian//////////////////////////////////////////////////////////////////////////////// 191518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 192518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias AgopianMediaCodec::BufferInfo::BufferInfo() : mOwnedByClient(false) {} 193518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 194518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian//////////////////////////////////////////////////////////////////////////////// 195518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 196518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopiannamespace { 197518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 198518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianenum { 199518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian kWhatFillThisBuffer = 'fill', 200518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian kWhatDrainThisBuffer = 'drai', 201518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian kWhatEOS = 'eos ', 202518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian kWhatStartCompleted = 'Scom', 203518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian kWhatStopCompleted = 'scom', 204518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian kWhatReleaseCompleted = 'rcom', 205518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian kWhatFlushCompleted = 'fcom', 206518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian kWhatError = 'erro', 207518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian kWhatComponentAllocated = 'cAll', 208518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian kWhatComponentConfigured = 'cCon', 209518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian kWhatInputSurfaceCreated = 'isfc', 210518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian kWhatInputSurfaceAccepted = 'isfa', 211518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian kWhatSignaledInputEOS = 'seos', 212518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian kWhatOutputFramesRendered = 'outR', 213518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian kWhatOutputBuffersChanged = 'outC', 214518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian}; 215518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 216518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianclass BufferCallback : public CodecBase::BufferCallback { 217518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianpublic: 218518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian explicit BufferCallback(const sp<AMessage> ¬ify); 219518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian virtual ~BufferCallback() = default; 220518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 221b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall virtual void onInputBufferAvailable( 222518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian size_t index, const sp<MediaCodecBuffer> &buffer) override; 223518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian virtual void onOutputBufferAvailable( 224518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian size_t index, const sp<MediaCodecBuffer> &buffer) override; 225518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianprivate: 226518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian const sp<AMessage> mNotify; 227518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian}; 228518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 229518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias AgopianBufferCallback::BufferCallback(const sp<AMessage> ¬ify) 230518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian : mNotify(notify) {} 231518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 232518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianvoid BufferCallback::onInputBufferAvailable( 233518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian size_t index, const sp<MediaCodecBuffer> &buffer) { 234518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> notify(mNotify->dup()); 235518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian notify->setInt32("what", kWhatFillThisBuffer); 236518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian notify->setSize("index", index); 237b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall notify->setObject("buffer", buffer); 238518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian notify->post(); 239518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 240518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 2414774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hallvoid BufferCallback::onOutputBufferAvailable( 242518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian size_t index, const sp<MediaCodecBuffer> &buffer) { 243518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> notify(mNotify->dup()); 244518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian notify->setInt32("what", kWhatDrainThisBuffer); 245518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian notify->setSize("index", index); 246518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian notify->setObject("buffer", buffer); 247518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian notify->post(); 248518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 249518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 250518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianclass CodecCallback : public CodecBase::CodecCallback { 251518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianpublic: 252518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian explicit CodecCallback(const sp<AMessage> ¬ify); 253518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian virtual ~CodecCallback() = default; 254518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 255b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall virtual void onEos(status_t err) override; 256518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian virtual void onStartCompleted() override; 257518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian virtual void onStopCompleted() override; 2587773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian virtual void onReleaseCompleted() override; 2597773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian virtual void onFlushCompleted() override; 260518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian virtual void onError(status_t err, enum ActionCode actionCode) override; 261518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian virtual void onComponentAllocated(const char *componentName) override; 2627773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian virtual void onComponentConfigured( 2637773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian const sp<AMessage> &inputFormat, const sp<AMessage> &outputFormat) override; 2647773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian virtual void onInputSurfaceCreated( 2657773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian const sp<AMessage> &inputFormat, 2667773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian const sp<AMessage> &outputFormat, 2677773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian const sp<BufferProducerWrapper> &inputSurface) override; 2687773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian virtual void onInputSurfaceCreationFailed(status_t err) override; 269518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian virtual void onInputSurfaceAccepted( 2707773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian const sp<AMessage> &inputFormat, 2717773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian const sp<AMessage> &outputFormat) override; 272518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian virtual void onInputSurfaceDeclined(status_t err) override; 273518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian virtual void onSignaledInputEOS(status_t err) override; 274518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian virtual void onOutputFramesRendered(const std::list<FrameRenderTracker::Info> &done) override; 275518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian virtual void onOutputBuffersChanged() override; 276518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianprivate: 277518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian const sp<AMessage> mNotify; 278518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian}; 279518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 280b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse HallCodecCallback::CodecCallback(const sp<AMessage> ¬ify) : mNotify(notify) {} 281518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 282518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianvoid CodecCallback::onEos(status_t err) { 283518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> notify(mNotify->dup()); 284518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian notify->setInt32("what", kWhatEOS); 285518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian notify->setInt32("err", err); 286518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian notify->post(); 287518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 288518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 289518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianvoid CodecCallback::onStartCompleted() { 290ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian sp<AMessage> notify(mNotify->dup()); 291ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian notify->setInt32("what", kWhatStartCompleted); 2921cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy notify->post(); 2931cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy} 2941cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy 2951cffc80f978c55f09203d9d9a905775b951ba59aRomain Guyvoid CodecCallback::onStopCompleted() { 2961cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy sp<AMessage> notify(mNotify->dup()); 2971cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy notify->setInt32("what", kWhatStopCompleted); 2981cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy notify->post(); 2991cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy} 3001cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy 301be3c3e4ecad501eecfe1f7a424a792f0f7f3f307Romain Guyvoid CodecCallback::onReleaseCompleted() { 3021cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy sp<AMessage> notify(mNotify->dup()); 3031cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy notify->setInt32("what", kWhatReleaseCompleted); 3041cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy notify->post(); 3051cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy} 306be3c3e4ecad501eecfe1f7a424a792f0f7f3f307Romain Guy 3071cffc80f978c55f09203d9d9a905775b951ba59aRomain Guyvoid CodecCallback::onFlushCompleted() { 3081cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy sp<AMessage> notify(mNotify->dup()); 3091cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy notify->setInt32("what", kWhatFlushCompleted); 3101cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy notify->post(); 3111cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy} 3121cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy 3131cffc80f978c55f09203d9d9a905775b951ba59aRomain Guyvoid CodecCallback::onError(status_t err, enum ActionCode actionCode) { 3141cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy sp<AMessage> notify(mNotify->dup()); 3151cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy notify->setInt32("what", kWhatError); 3161cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy notify->setInt32("err", err); 3171cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy notify->setInt32("actionCode", actionCode); 3181cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy notify->post(); 3191cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy} 3201cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy 3211cffc80f978c55f09203d9d9a905775b951ba59aRomain Guyvoid CodecCallback::onComponentAllocated(const char *componentName) { 3224774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall sp<AMessage> notify(mNotify->dup()); 3231cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy notify->setInt32("what", kWhatComponentAllocated); 3241cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy notify->setString("componentName", componentName); 3251cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy notify->post(); 3261cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy} 3271cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy 3281cffc80f978c55f09203d9d9a905775b951ba59aRomain Guyvoid CodecCallback::onComponentConfigured( 3291cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy const sp<AMessage> &inputFormat, const sp<AMessage> &outputFormat) { 3301cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy sp<AMessage> notify(mNotify->dup()); 3311cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy notify->setInt32("what", kWhatComponentConfigured); 3321cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy notify->setMessage("input-format", inputFormat); 3331cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy notify->setMessage("output-format", outputFormat); 3341cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy notify->post(); 3351cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy} 3361cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy 3371cffc80f978c55f09203d9d9a905775b951ba59aRomain Guyvoid CodecCallback::onInputSurfaceCreated( 3381cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy const sp<AMessage> &inputFormat, 3391cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy const sp<AMessage> &outputFormat, 3401cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy const sp<BufferProducerWrapper> &inputSurface) { 3411cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy sp<AMessage> notify(mNotify->dup()); 3421cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy notify->setInt32("what", kWhatInputSurfaceCreated); 3431cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy notify->setMessage("input-format", inputFormat); 3441cffc80f978c55f09203d9d9a905775b951ba59aRomain Guy notify->setMessage("output-format", outputFormat); 3457773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian notify->setObject("input-surface", inputSurface); 3467773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian notify->post(); 347518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 348518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 349518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianvoid CodecCallback::onInputSurfaceCreationFailed(status_t err) { 350518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> notify(mNotify->dup()); 351518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian notify->setInt32("what", kWhatInputSurfaceCreated); 352518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian notify->setInt32("err", err); 353518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian notify->post(); 354518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 355518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 356b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hallvoid CodecCallback::onInputSurfaceAccepted( 357b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall const sp<AMessage> &inputFormat, 358b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall const sp<AMessage> &outputFormat) { 3594774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall sp<AMessage> notify(mNotify->dup()); 360518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian notify->setInt32("what", kWhatInputSurfaceAccepted); 3617773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian notify->setMessage("input-format", inputFormat); 362518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian notify->setMessage("output-format", outputFormat); 363518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian notify->post(); 364518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 365518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 366518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianvoid CodecCallback::onInputSurfaceDeclined(status_t err) { 367518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> notify(mNotify->dup()); 368518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian notify->setInt32("what", kWhatInputSurfaceAccepted); 369518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian notify->setInt32("err", err); 370518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian notify->post(); 371518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 372518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 373518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianvoid CodecCallback::onSignaledInputEOS(status_t err) { 374b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall sp<AMessage> notify(mNotify->dup()); 375b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall notify->setInt32("what", kWhatSignaledInputEOS); 376b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall if (err != OK) { 377ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian notify->setInt32("err", err); 378518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 379518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian notify->post(); 38081a63350527cafce6929309533c58586878f10b5Mathias Agopian} 381e6f43ddce78d6846af12550ff9193c5c6fe5844bSteve Block 38281a63350527cafce6929309533c58586878f10b5Mathias Agopianvoid CodecCallback::onOutputFramesRendered(const std::list<FrameRenderTracker::Info> &done) { 38377a9b4a6bd21188e2744ae9dcd8092c6837bff7cJonathan Hamilton sp<AMessage> notify(mNotify->dup()); 38481a63350527cafce6929309533c58586878f10b5Mathias Agopian notify->setInt32("what", kWhatOutputFramesRendered); 38581a63350527cafce6929309533c58586878f10b5Mathias Agopian if (MediaCodec::CreateFramesRenderedMessage(done, notify)) { 386518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian notify->post(); 387518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 3887773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian} 389518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 390bee205fd58a27c10a0895de5339e76025d429d2bJamie Gennisvoid CodecCallback::onOutputBuffersChanged() { 391bee205fd58a27c10a0895de5339e76025d429d2bJamie Gennis sp<AMessage> notify(mNotify->dup()); 392e6f43ddce78d6846af12550ff9193c5c6fe5844bSteve Block notify->setInt32("what", kWhatOutputBuffersChanged); 393bee205fd58a27c10a0895de5339e76025d429d2bJamie Gennis notify->post(); 39481a63350527cafce6929309533c58586878f10b5Mathias Agopian} 395bee205fd58a27c10a0895de5339e76025d429d2bJamie Gennis 396bee205fd58a27c10a0895de5339e76025d429d2bJamie Gennis} // namespace 397518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 398518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian//////////////////////////////////////////////////////////////////////////////// 399518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 40059769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennis// static 40159769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennissp<MediaCodec> MediaCodec::CreateByType( 40259769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennis const sp<ALooper> &looper, const AString &mime, bool encoder, status_t *err, pid_t pid, 40359769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennis uid_t uid) { 40459769469e4b9b2d8b12c020eb44b030b3927a50bJamie Gennis sp<MediaCodec> codec = new MediaCodec(looper, pid, uid); 405518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 4067773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian const status_t ret = codec->init(mime, true /* nameIsType */, encoder); 407518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (err != NULL) { 408b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall *err = ret; 409b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall } 410518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return ret == OK ? codec : NULL; // NULL deallocates codec. 411518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 41281a63350527cafce6929309533c58586878f10b5Mathias Agopian 41381a63350527cafce6929309533c58586878f10b5Mathias Agopian// static 41481a63350527cafce6929309533c58586878f10b5Mathias Agopiansp<MediaCodec> MediaCodec::CreateByComponentName( 41581a63350527cafce6929309533c58586878f10b5Mathias Agopian const sp<ALooper> &looper, const AString &name, status_t *err, pid_t pid, uid_t uid) { 416518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<MediaCodec> codec = new MediaCodec(looper, pid, uid); 417518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 418518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian const status_t ret = codec->init(name, false /* nameIsType */, false /* encoder */); 419518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (err != NULL) { 420518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian *err = ret; 421518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 422518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return ret == OK ? codec : NULL; // NULL deallocates codec. 423518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 424518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 425518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian// static 426b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hallstatus_t MediaCodec::QueryCapabilities( 427b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall const AString &name, const AString &mime, bool isEncoder, 428b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall sp<MediaCodecInfo::Capabilities> *caps /* nonnull */) { 429518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian // TRICKY: this method is used by MediaCodecList/Info during its 4307773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian // initialization. As such, we cannot create a MediaCodec instance 431518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian // because that requires an initialized MediaCodecList. 432b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall 433b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall sp<CodecBase> codec = GetCodecBase(name); 434518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (codec == NULL) { 435518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return NAME_NOT_FOUND; 436518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 437518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 438518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return codec->queryCapabilities(name, mime, isEncoder, caps); 439518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 440518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 441518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian// static 442518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopiansp<PersistentSurface> MediaCodec::CreatePersistentInputSurface() { 443518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian OMXClient client; 444518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (client.connect() != OK) { 445b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall ALOGE("Failed to connect to OMX to create persistent input surface."); 446b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall return NULL; 447b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall } 448518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 4497773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian sp<IOMX> omx = client.interface(); 450518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 451b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall sp<IGraphicBufferProducer> bufferProducer; 452b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall sp<IGraphicBufferSource> bufferSource; 453518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 454518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian status_t err = omx->createInputSurface(&bufferProducer, &bufferSource); 455518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 456518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (err != OK) { 457518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian ALOGE("Failed to create persistent input surface."); 4584774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall return NULL; 459518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 460518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 461518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return new PersistentSurface(bufferProducer, bufferSource); 462518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 463b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall 464518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias AgopianMediaCodec::MediaCodec(const sp<ALooper> &looper, pid_t pid, uid_t uid) 465518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian : mState(UNINITIALIZED), 466b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall mReleasedByResourceManager(false), 4675b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian mLooper(looper), 4685b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian mCodec(NULL), 469518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mReplyID(0), 470518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mFlags(0), 471ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian mStickyError(OK), 472518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mSoftRenderer(NULL), 473518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mResourceManagerClient(new ResourceManagerClient(this)), 474518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mResourceManagerService(new ResourceManagerServiceProxy(pid)), 475518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mBatteryStatNotified(false), 476518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mIsVideo(false), 477518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mVideoWidth(0), 478518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mVideoHeight(0), 479518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mRotationDegrees(0), 480518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mDequeueInputTimeoutGeneration(0), 481518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mDequeueInputReplyID(0), 482518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mDequeueOutputTimeoutGeneration(0), 483b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall mDequeueOutputReplyID(0), 484518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mHaveInputSurface(false), 485518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mHavePendingInputBuffers(false) { 486b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall if (uid == kNoUid) { 4875b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian mUid = IPCThreadState::self()->getCallingUid(); 4885b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian } else { 489518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mUid = uid; 490518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 4917773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian // set up our new record, get a sessionID, put it into the in-progress list 4927773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian mAnalyticsItem = new MediaAnalyticsItem(kCodecKeyName); 493518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (mAnalyticsItem != NULL) { 494518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian (void) mAnalyticsItem->generateSessionID(); 495e8696a40e09b24b634214684d18526187b316a2fJamie Gennis // don't record it yet; only at the end, when we have decided that we have 4961c8e95cf86f2182986385bc1ee85f13f425f3a3aJamie Gennis // data worth writing (e.g. .count() > 0) 497e8696a40e09b24b634214684d18526187b316a2fJamie Gennis } 498e8696a40e09b24b634214684d18526187b316a2fJamie Gennis} 499b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall 500e8696a40e09b24b634214684d18526187b316a2fJamie GennisMediaCodec::~MediaCodec() { 501e8696a40e09b24b634214684d18526187b316a2fJamie Gennis CHECK_EQ(mState, UNINITIALIZED); 502e8696a40e09b24b634214684d18526187b316a2fJamie Gennis mResourceManagerService->removeResource(getId(mResourceManagerClient)); 503e8696a40e09b24b634214684d18526187b316a2fJamie Gennis 504b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall if (mAnalyticsItem != NULL ) { 505e8696a40e09b24b634214684d18526187b316a2fJamie Gennis if (mAnalyticsItem->count() > 0) { 506e8696a40e09b24b634214684d18526187b316a2fJamie Gennis mAnalyticsItem->setFinalized(true); 507e8696a40e09b24b634214684d18526187b316a2fJamie Gennis mAnalyticsItem->selfrecord(); 508e8696a40e09b24b634214684d18526187b316a2fJamie Gennis } 509e8696a40e09b24b634214684d18526187b316a2fJamie Gennis delete mAnalyticsItem; 510e8696a40e09b24b634214684d18526187b316a2fJamie Gennis mAnalyticsItem = NULL; 511518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 512518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 513518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 514518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian// static 515518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianstatus_t MediaCodec::PostAndAwaitResponse( 516518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian const sp<AMessage> &msg, sp<AMessage> *response) { 517518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian status_t err = msg->postAndAwaitResponse(response); 518518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 519518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (err != OK) { 520b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall return err; 521b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall } 5220673e1e2d77c673c2e9bc57616a02c3188b55ad1Michael Chock 523518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (!(*response)->findInt32("err", &err)) { 5240673e1e2d77c673c2e9bc57616a02c3188b55ad1Michael Chock err = OK; 5250673e1e2d77c673c2e9bc57616a02c3188b55ad1Michael Chock } 5260673e1e2d77c673c2e9bc57616a02c3188b55ad1Michael Chock 527518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return err; 528518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 529518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 530518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianvoid MediaCodec::PostReplyWithError(const sp<AReplyToken> &replyID, int32_t err) { 5317773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian int32_t finalErr = err; 532518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (mReleasedByResourceManager) { 533518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian // override the err code if MediaCodec has been released by ResourceManager. 534518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian finalErr = DEAD_OBJECT; 535518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 536518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 537518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> response = new AMessage; 538518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian response->setInt32("err", finalErr); 539518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian response->postReply(replyID); 540518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 5417773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian 5424774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall//static 5437773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopiansp<CodecBase> MediaCodec::GetCodecBase(const AString &name, bool nameIsType) { 544518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian // at this time only ACodec specifies a mime type. 545518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (nameIsType || name.startsWithIgnoreCase("omx.")) { 546518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return new ACodec; 547518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } else if (name.startsWithIgnoreCase("android.filter.")) { 548b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall return new MediaFilter; 549b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall } else { 5500469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy return NULL; 551a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy } 5520469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy} 5530469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy 554518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianstatus_t MediaCodec::init(const AString &name, bool nameIsType, bool encoder) { 555500407a2c07ced40c36e7356574a47bcec9c2fd9Mathias Agopian mResourceManagerService->init(); 556500407a2c07ced40c36e7356574a47bcec9c2fd9Mathias Agopian 557500407a2c07ced40c36e7356574a47bcec9c2fd9Mathias Agopian // save init parameters for reset 558500407a2c07ced40c36e7356574a47bcec9c2fd9Mathias Agopian mInitName = name; 559500407a2c07ced40c36e7356574a47bcec9c2fd9Mathias Agopian mInitNameIsType = nameIsType; 560500407a2c07ced40c36e7356574a47bcec9c2fd9Mathias Agopian mInitIsEncoder = encoder; 561518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 562518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian // Current video decoders do not return from OMX_FillThisBuffer 563518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian // quickly, violating the OpenMAX specs, until that is remedied 564518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian // we need to invest in an extra looper to free the main event 565518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian // queue. 566518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 567518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mCodec = GetCodecBase(name, nameIsType); 568518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (mCodec == NULL) { 569518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return NAME_NOT_FOUND; 570b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall } 5715b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian 5725b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian bool secureCodec = false; 573518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (nameIsType && !strncasecmp(name.c_str(), "video/", 6)) { 574b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall mIsVideo = true; 5755b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian } else { 5765b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian AString tmp = name; 5774774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall if (tmp.endsWith(".secure")) { 578518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian secureCodec = true; 579ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian tmp.erase(tmp.size() - 7, 7); 580518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 581518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian const sp<IMediaCodecList> mcl = MediaCodecList::getInstance(); 582518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (mcl == NULL) { 583518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mCodec = NULL; // remove the codec. 584518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return NO_INIT; // if called from Java should raise IOException 585518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 586518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian ssize_t codecIdx = mcl->findCodecByName(tmp.c_str()); 587518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (codecIdx >= 0) { 588518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian const sp<MediaCodecInfo> info = mcl->getCodecInfo(codecIdx); 589518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian Vector<AString> mimes; 590518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian info->getSupportedMimes(&mimes); 591b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall for (size_t i = 0; i < mimes.size(); i++) { 592518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (mimes[i].startsWith("video/")) { 593518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mIsVideo = true; 5945b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian break; 5955b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian } 5965b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian } 597518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 598518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 599518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 600518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (mIsVideo) { 601518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian // video codec needs dedicated looper 602518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (mCodecLooper == NULL) { 603b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall mCodecLooper = new ALooper; 604b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall mCodecLooper->setName("CodecLooper"); 605b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO); 606518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 607518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 6085b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian mCodecLooper->registerHandler(mCodec); 609518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } else { 6100673e1e2d77c673c2e9bc57616a02c3188b55ad1Michael Chock mLooper->registerHandler(mCodec); 611518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 612518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 613518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mLooper->registerHandler(this); 614518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 615518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mCodec->setCallback( 616518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian std::unique_ptr<CodecBase::CodecCallback>( 617518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian new CodecCallback(new AMessage(kWhatCodecNotify, this)))); 618518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mBufferChannel = mCodec->getBufferChannel(); 619518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mBufferChannel->setCallback( 620518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian std::unique_ptr<CodecBase::BufferCallback>( 621518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian new BufferCallback(new AMessage(kWhatCodecNotify, this)))); 622518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 623518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> msg = new AMessage(kWhatInit, this); 624518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian msg->setString("name", name); 6254774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall msg->setInt32("nameIsType", nameIsType); 626518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 627518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (nameIsType) { 628518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian msg->setInt32("encoder", encoder); 629518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 630518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 6310673e1e2d77c673c2e9bc57616a02c3188b55ad1Michael Chock if (mAnalyticsItem != NULL) { 6320673e1e2d77c673c2e9bc57616a02c3188b55ad1Michael Chock if (nameIsType) { 6330673e1e2d77c673c2e9bc57616a02c3188b55ad1Michael Chock // name is the mime type 6340673e1e2d77c673c2e9bc57616a02c3188b55ad1Michael Chock mAnalyticsItem->setCString(kCodecMime, name.c_str()); 635518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } else { 636518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mAnalyticsItem->setCString(kCodecCodec, name.c_str()); 637518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 638518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mAnalyticsItem->setCString(kCodecMode, mIsVideo ? "video" : "audio"); 639518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian //mAnalyticsItem->setInt32("type", nameIsType); 640518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (nameIsType) 641518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mAnalyticsItem->setInt32("encoder", encoder); 642518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 643518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 6440673e1e2d77c673c2e9bc57616a02c3188b55ad1Michael Chock status_t err; 645518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian Vector<MediaResource> resources; 646518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian MediaResource::Type type = 647518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian secureCodec ? MediaResource::kSecureCodec : MediaResource::kNonSecureCodec; 648518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian MediaResource::SubType subtype = 649518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mIsVideo ? MediaResource::kVideoCodec : MediaResource::kAudioCodec; 650518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian resources.push_back(MediaResource(type, subtype, 1)); 6510673e1e2d77c673c2e9bc57616a02c3188b55ad1Michael Chock for (int i = 0; i <= kMaxRetry; ++i) { 652518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (i > 0) { 653518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian // Don't try to reclaim resource for the first time. 654518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (!mResourceManagerService->reclaimResource(resources)) { 655518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian break; 656518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 657b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall } 658fb87e54a9af8bc5063ca4deebe81d90126992480Mathias Agopian 659fb87e54a9af8bc5063ca4deebe81d90126992480Mathias Agopian sp<AMessage> response; 660518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian err = PostAndAwaitResponse(msg, &response); 661518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (!isResourceError(err)) { 662fb87e54a9af8bc5063ca4deebe81d90126992480Mathias Agopian break; 663518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 664518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 6650469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy return err; 666a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy} 66793a826f78f6313db791e6fc880439189897651b3Siva Velusamy 6680469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamystatus_t MediaCodec::setCallback(const sp<AMessage> &callback) { 669518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> msg = new AMessage(kWhatSetCallback, this); 670518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian msg->setMessage("callback", callback); 671518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 672518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> response; 673518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return PostAndAwaitResponse(msg, &response); 674518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 675518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 6765fecea776a5f093c21ac1a0ad3552b847d4be23eMathias Agopianstatus_t MediaCodec::setOnFrameRenderedNotification(const sp<AMessage> ¬ify) { 677e6f43ddce78d6846af12550ff9193c5c6fe5844bSteve Block sp<AMessage> msg = new AMessage(kWhatSetNotification, this); 6785fecea776a5f093c21ac1a0ad3552b847d4be23eMathias Agopian msg->setMessage("on-frame-rendered", notify); 679518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return msg->post(); 680518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 681518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 682518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianstatus_t MediaCodec::configure( 683518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian const sp<AMessage> &format, 684518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian const sp<Surface> &nativeWindow, 685518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian const sp<ICrypto> &crypto, 686518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian uint32_t flags) { 687518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return configure(format, nativeWindow, crypto, NULL, flags); 688518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 689b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall 690518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianstatus_t MediaCodec::configure( 691518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian const sp<AMessage> &format, 692b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall const sp<Surface> &surface, 693518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian const sp<ICrypto> &crypto, 694518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian const sp<IDescrambler> &descrambler, 695518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian uint32_t flags) { 6967773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian sp<AMessage> msg = new AMessage(kWhatConfigure, this); 6977773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian 698518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (mIsVideo) { 699518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian format->findInt32("width", &mVideoWidth); 700518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian format->findInt32("height", &mVideoHeight); 701518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (!format->findInt32("rotation-degrees", &mRotationDegrees)) { 702518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mRotationDegrees = 0; 703518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 704518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 705518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (mAnalyticsItem != NULL) { 706518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mAnalyticsItem->setInt32("width", mVideoWidth); 707518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mAnalyticsItem->setInt32("height", mVideoHeight); 708518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mAnalyticsItem->setInt32("rotation", mRotationDegrees); 709518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 710518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 711518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian // Prevent possible integer overflow in downstream code. 712518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (mInitIsEncoder 713518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian && (uint64_t)mVideoWidth * mVideoHeight > (uint64_t)INT32_MAX / 4) { 714518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian ALOGE("buffer size is too big, width=%d, height=%d", mVideoWidth, mVideoHeight); 715518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return BAD_VALUE; 716518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 717518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 718518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 719518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian msg->setMessage("format", format); 720518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian msg->setInt32("flags", flags); 721518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian msg->setObject("surface", surface); 722518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 723518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (crypto != NULL || descrambler != NULL) { 724518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (crypto != NULL) { 7254774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall msg->setPointer("crypto", crypto.get()); 726518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } else { 727518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian msg->setPointer("descrambler", descrambler.get()); 728518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 729518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (mAnalyticsItem != NULL) { 730518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian // XXX: save indication that it's crypto in some way... 731518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mAnalyticsItem->setInt32("crypto", 1); 732518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 733518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 734518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 735518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian // save msg for reset 736518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mConfigureMsg = msg; 737518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 738518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian status_t err; 739518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian Vector<MediaResource> resources; 740518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian MediaResource::Type type = (mFlags & kFlagIsSecure) ? 741518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian MediaResource::kSecureCodec : MediaResource::kNonSecureCodec; 742518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian MediaResource::SubType subtype = 743518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mIsVideo ? MediaResource::kVideoCodec : MediaResource::kAudioCodec; 744518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian resources.push_back(MediaResource(type, subtype, 1)); 745518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian // Don't know the buffer size at this point, but it's fine to use 1 because 746518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian // the reclaimResource call doesn't consider the requester's buffer size for now. 747518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian resources.push_back(MediaResource(MediaResource::kGraphicMemory, 1)); 748518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian for (int i = 0; i <= kMaxRetry; ++i) { 749518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (i > 0) { 750518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian // Don't try to reclaim resource for the first time. 751518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (!mResourceManagerService->reclaimResource(resources)) { 752ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian break; 753ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian } 754ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian } 755ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian 756ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian sp<AMessage> response; 757518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian err = PostAndAwaitResponse(msg, &response); 758518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (err != OK && err != INVALID_OPERATION) { 759518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian // MediaCodec now set state to UNINITIALIZED upon any fatal error. 760518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian // To maintain backward-compatibility, do a reset() to put codec 761518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian // back into INITIALIZED state. 762518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian // But don't reset if the err is INVALID_OPERATION, which means 763ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian // the configure failure is due to wrong state. 764ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian 765ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian ALOGE("configure failed with err 0x%08x, resetting...", err); 766ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian reset(); 767ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian } 768518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (!isResourceError(err)) { 769518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian break; 770518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 771518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 772ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian return err; 773ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian} 774ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian 775ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopianstatus_t MediaCodec::releaseCrypto() 776518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian{ 777ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian ALOGV("releaseCrypto"); 778ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian 779ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian sp<AMessage> msg = new AMessage(kWhatDrmReleaseCrypto, this); 780ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian 781518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> response; 782518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian status_t status = msg->postAndAwaitResponse(&response); 783c07b52060acd627c8510c1a9151e0753fce76330Jesse Hall 784c07b52060acd627c8510c1a9151e0753fce76330Jesse Hall if (status == OK && response != NULL) { 785c07b52060acd627c8510c1a9151e0753fce76330Jesse Hall CHECK(response->findInt32("status", &status)); 786c07b52060acd627c8510c1a9151e0753fce76330Jesse Hall ALOGV("releaseCrypto ret: %d ", status); 787c07b52060acd627c8510c1a9151e0753fce76330Jesse Hall } 788c07b52060acd627c8510c1a9151e0753fce76330Jesse Hall else { 789c07b52060acd627c8510c1a9151e0753fce76330Jesse Hall ALOGE("releaseCrypto err: %d", status); 790c07b52060acd627c8510c1a9151e0753fce76330Jesse Hall } 791c07b52060acd627c8510c1a9151e0753fce76330Jesse Hall 792c07b52060acd627c8510c1a9151e0753fce76330Jesse Hall return status; 793c07b52060acd627c8510c1a9151e0753fce76330Jesse Hall} 794c07b52060acd627c8510c1a9151e0753fce76330Jesse Hall 795c07b52060acd627c8510c1a9151e0753fce76330Jesse Hallvoid MediaCodec::onReleaseCrypto(const sp<AMessage>& msg) 796c07b52060acd627c8510c1a9151e0753fce76330Jesse Hall{ 797518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian status_t status = INVALID_OPERATION; 798518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (mCrypto != NULL) { 799518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian ALOGV("onReleaseCrypto: mCrypto: %p (%d)", mCrypto.get(), mCrypto->getStrongCount()); 800518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mBufferChannel->setCrypto(NULL); 801518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian // TODO change to ALOGV 802518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian ALOGD("onReleaseCrypto: [before clear] mCrypto: %p (%d)", 803518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mCrypto.get(), mCrypto->getStrongCount()); 804518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mCrypto.clear(); 805518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 806518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian status = OK; 807518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 808518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian else { 809518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian ALOGW("onReleaseCrypto: No mCrypto. err: %d", status); 810e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian } 811aca51c06f38155f1435fbc6944d7fc0a9bf1e4e9Jamie Gennis 812aca51c06f38155f1435fbc6944d7fc0a9bf1e4e9Jamie Gennis sp<AMessage> response = new AMessage; 813aca51c06f38155f1435fbc6944d7fc0a9bf1e4e9Jamie Gennis response->setInt32("status", status); 814518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 815e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian sp<AReplyToken> replyID; 816518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian CHECK(msg->senderAwaitsResponse(&replyID)); 817518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian response->postReply(replyID); 818c07b52060acd627c8510c1a9151e0753fce76330Jesse Hall} 819c07b52060acd627c8510c1a9151e0753fce76330Jesse Hall 820aca51c06f38155f1435fbc6944d7fc0a9bf1e4e9Jamie Gennisstatus_t MediaCodec::setInputSurface( 821518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian const sp<PersistentSurface> &surface) { 822518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> msg = new AMessage(kWhatSetInputSurface, this); 823518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian msg->setObject("input-surface", surface.get()); 824518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 825518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> response; 826518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return PostAndAwaitResponse(msg, &response); 827518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 828518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 829518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianstatus_t MediaCodec::setSurface(const sp<Surface> &surface) { 830518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> msg = new AMessage(kWhatSetSurface, this); 831518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian msg->setObject("surface", surface); 832518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 833518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> response; 834518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return PostAndAwaitResponse(msg, &response); 835518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 836518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 837518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianstatus_t MediaCodec::createInputSurface( 838518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<IGraphicBufferProducer>* bufferProducer) { 839518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> msg = new AMessage(kWhatCreateInputSurface, this); 840518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 841518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> response; 842518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian status_t err = PostAndAwaitResponse(msg, &response); 843518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (err == NO_ERROR) { 844518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian // unwrap the sp<IGraphicBufferProducer> 845e6f43ddce78d6846af12550ff9193c5c6fe5844bSteve Block sp<RefBase> obj; 846518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian bool found = response->findObject("input-surface", &obj); 847518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian CHECK(found); 848518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<BufferProducerWrapper> wrapper( 8490469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy static_cast<BufferProducerWrapper*>(obj.get())); 8500469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy *bufferProducer = wrapper->getBufferProducer(); 8510469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy } else { 8520469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy ALOGW("createInputSurface failed, err=%d", err); 853518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 854518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return err; 855ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian} 856ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian 857ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopianuint64_t MediaCodec::getGraphicBufferSize() { 858ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian if (!mIsVideo) { 85969d100762c7c26d8328f4bb61cfef026d3a69bbfluliuhui return 0; 8607773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian } 8617773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian 862518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian uint64_t size = 0; 863ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian size_t portNum = sizeof(mPortBuffers) / sizeof((mPortBuffers)[0]); 864ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian for (size_t i = 0; i < portNum; ++i) { 865518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian // TODO: this is just an estimation, we should get the real buffer size from ACodec. 866ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian size += mPortBuffers[i].size() * mVideoWidth * mVideoHeight * 3 / 2; 86769d100762c7c26d8328f4bb61cfef026d3a69bbfluliuhui } 868518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return size; 869ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian} 870518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 871518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianvoid MediaCodec::addResource( 872518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian MediaResource::Type type, MediaResource::SubType subtype, uint64_t value) { 873518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian Vector<MediaResource> resources; 874518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian resources.push_back(MediaResource(type, subtype, value)); 875518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mResourceManagerService->addResource( 876518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian getId(mResourceManagerClient), mResourceManagerClient, resources); 877518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 878518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 879518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianstatus_t MediaCodec::start() { 880518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> msg = new AMessage(kWhatStart, this); 88128ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis 88228ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis status_t err; 88328ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis Vector<MediaResource> resources; 88428ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis MediaResource::Type type = (mFlags & kFlagIsSecure) ? 88528ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis MediaResource::kSecureCodec : MediaResource::kNonSecureCodec; 88628ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis MediaResource::SubType subtype = 88728ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis mIsVideo ? MediaResource::kVideoCodec : MediaResource::kAudioCodec; 88828ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis resources.push_back(MediaResource(type, subtype, 1)); 88928ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis // Don't know the buffer size at this point, but it's fine to use 1 because 89028ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis // the reclaimResource call doesn't consider the requester's buffer size for now. 89128ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis resources.push_back(MediaResource(MediaResource::kGraphicMemory, 1)); 89228ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis for (int i = 0; i <= kMaxRetry; ++i) { 89328ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis if (i > 0) { 89428ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis // Don't try to reclaim resource for the first time. 89528ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis if (!mResourceManagerService->reclaimResource(resources)) { 89628ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis break; 89728ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis } 89828ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis // Recover codec from previous error before retry start. 89928ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis err = reset(); 90028ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis if (err != OK) { 90128ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis ALOGE("retrying start: failed to reset codec"); 90228ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis break; 90328ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis } 90428ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis sp<AMessage> response; 90528ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis err = PostAndAwaitResponse(mConfigureMsg, &response); 90628ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis if (err != OK) { 90728ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis ALOGE("retrying start: failed to configure codec"); 90828ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis break; 90928ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis } 91028ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis } 91128ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis 91228ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis sp<AMessage> response; 91328ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis err = PostAndAwaitResponse(msg, &response); 91428ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis if (!isResourceError(err)) { 91528ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis break; 91628ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis } 91728ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis } 91828ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis return err; 91928ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis} 92028ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis 92128ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennisstatus_t MediaCodec::stop() { 92228ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis sp<AMessage> msg = new AMessage(kWhatStop, this); 92328ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis 92428ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis sp<AMessage> response; 92528ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis return PostAndAwaitResponse(msg, &response); 92628ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis} 92728ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis 92828ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennisbool MediaCodec::hasPendingBuffer(int portIndex) { 92928ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis return std::any_of( 93028ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis mPortBuffers[portIndex].begin(), mPortBuffers[portIndex].end(), 93128ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis [](const BufferInfo &info) { return info.mOwnedByClient; }); 93228ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis} 93328ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis 93428ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennisbool MediaCodec::hasPendingBuffer() { 93528ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis return hasPendingBuffer(kPortIndexInput) || hasPendingBuffer(kPortIndexOutput); 93628ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis} 93728ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis 93828ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennisstatus_t MediaCodec::reclaim(bool force) { 93928ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis ALOGD("MediaCodec::reclaim(%p) %s", this, mInitName.c_str()); 94028ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis sp<AMessage> msg = new AMessage(kWhatRelease, this); 94128ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis msg->setInt32("reclaimed", 1); 94228ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis msg->setInt32("force", force ? 1 : 0); 94328ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis 944518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> response; 945518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian status_t ret = PostAndAwaitResponse(msg, &response); 9461c8e95cf86f2182986385bc1ee85f13f425f3a3aJamie Gennis if (ret == -ENOENT) { 947518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian ALOGD("MediaCodec looper is gone, skip reclaim"); 948518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian ret = OK; 949b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall } 950518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return ret; 951518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 952b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall 9535b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopianstatus_t MediaCodec::release() { 9545b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian sp<AMessage> msg = new AMessage(kWhatRelease, this); 955518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 9560469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy sp<AMessage> response; 957a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy return PostAndAwaitResponse(msg, &response); 958a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy} 959a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy 960a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamystatus_t MediaCodec::reset() { 961a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy /* When external-facing MediaCodec object is created, 962a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy it is already initialized. Thus, reset is essentially 963a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy release() followed by init(), plus clearing the state */ 964a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy 965a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy status_t err = release(); 966a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy 967a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy // unregister handlers 968a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy if (mCodec != NULL) { 969a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy if (mCodecLooper != NULL) { 970a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy mCodecLooper->unregisterHandler(mCodec->id()); 971a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy } else { 972a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy mLooper->unregisterHandler(mCodec->id()); 973a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy } 9740469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy mCodec = NULL; 975a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy } 976a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy mLooper->unregisterHandler(id()); 977a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy 978a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy mFlags = 0; // clear all flags 979a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy mStickyError = OK; 980a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy 981a73a97728befb5ba5ad647ab3b60058c4d536ba4Siva Velusamy // reset state not reset by setState(UNINITIALIZED) 9820469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy mReplyID = 0; 9830469dd6d55fa331bfd7de9431da98b6340d82271Siva Velusamy mDequeueInputReplyID = 0; 984518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mDequeueOutputReplyID = 0; 9857db993a98b9239bd4e384cc4aa128262fe3cf52cMathias Agopian mDequeueInputTimeoutGeneration = 0; 986ed6d08b70d775852f4827471814c83eba3606aaaMathias Agopian mDequeueOutputTimeoutGeneration = 0; 987ed6d08b70d775852f4827471814c83eba3606aaaMathias Agopian mHaveInputSurface = false; 988ed6d08b70d775852f4827471814c83eba3606aaaMathias Agopian 989ed6d08b70d775852f4827471814c83eba3606aaaMathias Agopian if (err == OK) { 990ed6d08b70d775852f4827471814c83eba3606aaaMathias Agopian err = init(mInitName, mInitNameIsType, mInitIsEncoder); 991ed6d08b70d775852f4827471814c83eba3606aaaMathias Agopian } 992ed6d08b70d775852f4827471814c83eba3606aaaMathias Agopian return err; 9937db993a98b9239bd4e384cc4aa128262fe3cf52cMathias Agopian} 9947db993a98b9239bd4e384cc4aa128262fe3cf52cMathias Agopian 9957db993a98b9239bd4e384cc4aa128262fe3cf52cMathias Agopianstatus_t MediaCodec::queueInputBuffer( 9967db993a98b9239bd4e384cc4aa128262fe3cf52cMathias Agopian size_t index, 9977db993a98b9239bd4e384cc4aa128262fe3cf52cMathias Agopian size_t offset, 9987db993a98b9239bd4e384cc4aa128262fe3cf52cMathias Agopian size_t size, 9997db993a98b9239bd4e384cc4aa128262fe3cf52cMathias Agopian int64_t presentationTimeUs, 10007db993a98b9239bd4e384cc4aa128262fe3cf52cMathias Agopian uint32_t flags, 10017db993a98b9239bd4e384cc4aa128262fe3cf52cMathias Agopian AString *errorDetailMsg) { 10027db993a98b9239bd4e384cc4aa128262fe3cf52cMathias Agopian if (errorDetailMsg != NULL) { 1003ed6d08b70d775852f4827471814c83eba3606aaaMathias Agopian errorDetailMsg->clear(); 1004518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 1005518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1006518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this); 1007518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian msg->setSize("index", index); 1008518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian msg->setSize("offset", offset); 1009518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian msg->setSize("size", size); 1010518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian msg->setInt64("timeUs", presentationTimeUs); 1011b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall msg->setInt32("flags", flags); 1012518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian msg->setPointer("errorDetailMsg", errorDetailMsg); 1013518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1014b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall sp<AMessage> response; 10155b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian return PostAndAwaitResponse(msg, &response); 10165b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian} 1017518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1018518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianstatus_t MediaCodec::queueSecureInputBuffer( 1019ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian size_t index, 1020518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian size_t offset, 1021518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian const CryptoPlugin::SubSample *subSamples, 1022518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian size_t numSubSamples, 1023518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian const uint8_t key[16], 1024518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian const uint8_t iv[16], 1025518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian CryptoPlugin::Mode mode, 1026b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall const CryptoPlugin::Pattern &pattern, 1027518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian int64_t presentationTimeUs, 1028518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian uint32_t flags, 1029518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian AString *errorDetailMsg) { 1030518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (errorDetailMsg != NULL) { 10314b9511c16195a646242eff833b0af212933b6ecaMathias Agopian errorDetailMsg->clear(); 1032518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 10334b9511c16195a646242eff833b0af212933b6ecaMathias Agopian 1034518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this); 10354b9511c16195a646242eff833b0af212933b6ecaMathias Agopian msg->setSize("index", index); 1036518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian msg->setSize("offset", offset); 10374b9511c16195a646242eff833b0af212933b6ecaMathias Agopian msg->setPointer("subSamples", (void *)subSamples); 1038518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian msg->setSize("numSubSamples", numSubSamples); 1039518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian msg->setPointer("key", (void *)key); 1040518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian msg->setPointer("iv", (void *)iv); 1041518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian msg->setInt32("mode", mode); 1042ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian msg->setInt32("encryptBlocks", pattern.mEncryptBlocks); 1043ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian msg->setInt32("skipBlocks", pattern.mSkipBlocks); 1044ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian msg->setInt64("timeUs", presentationTimeUs); 1045ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian msg->setInt32("flags", flags); 1046ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian msg->setPointer("errorDetailMsg", errorDetailMsg); 1047ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian 1048ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian sp<AMessage> response; 1049ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian status_t err = PostAndAwaitResponse(msg, &response); 1050ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian 1051ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian return err; 1052ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian} 1053ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian 1054ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopianstatus_t MediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) { 1055ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian sp<AMessage> msg = new AMessage(kWhatDequeueInputBuffer, this); 1056ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian msg->setInt64("timeoutUs", timeoutUs); 1057ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian 1058ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian sp<AMessage> response; 1059ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian status_t err; 1060ca08833d5ea99130797e10ad68a651b50e99da74Mathias Agopian if ((err = PostAndAwaitResponse(msg, &response)) != OK) { 1061518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return err; 1062518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 1063518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1064518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian CHECK(response->findSize("index", index)); 1065518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1066518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return OK; 1067518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 1068518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1069518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianstatus_t MediaCodec::dequeueOutputBuffer( 1070518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian size_t *index, 1071b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall size_t *offset, 1072518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian size_t *size, 1073518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian int64_t *presentationTimeUs, 1074b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall uint32_t *flags, 10755b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian int64_t timeoutUs) { 10765b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian sp<AMessage> msg = new AMessage(kWhatDequeueOutputBuffer, this); 1077518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian msg->setInt64("timeoutUs", timeoutUs); 1078518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1079518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> response; 1080518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian status_t err; 1081ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian if ((err = PostAndAwaitResponse(msg, &response)) != OK) { 1082518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return err; 1083518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 1084518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1085518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian CHECK(response->findSize("index", index)); 1086518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian CHECK(response->findSize("offset", offset)); 1087518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian CHECK(response->findSize("size", size)); 1088518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian CHECK(response->findInt64("timeUs", presentationTimeUs)); 1089518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian CHECK(response->findInt32("flags", (int32_t *)flags)); 1090518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1091b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall return OK; 1092518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 1093518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1094b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hallstatus_t MediaCodec::renderOutputBufferAndRelease(size_t index) { 10955b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, this); 10965b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian msg->setSize("index", index); 1097518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian msg->setInt32("render", true); 1098518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1099518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> response; 1100518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return PostAndAwaitResponse(msg, &response); 1101ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian} 1102518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1103518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianstatus_t MediaCodec::renderOutputBufferAndRelease(size_t index, int64_t timestampNs) { 1104518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, this); 1105518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian msg->setSize("index", index); 1106518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian msg->setInt32("render", true); 1107518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian msg->setInt64("timestampNs", timestampNs); 1108518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1109518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> response; 1110518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return PostAndAwaitResponse(msg, &response); 1111b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall} 1112518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1113518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianstatus_t MediaCodec::releaseOutputBuffer(size_t index) { 1114b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, this); 11155b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian msg->setSize("index", index); 11165b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian 1117518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> response; 1118518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return PostAndAwaitResponse(msg, &response); 1119518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 1120518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1121ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopianstatus_t MediaCodec::signalEndOfInputStream() { 1122518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> msg = new AMessage(kWhatSignalEndOfInputStream, this); 1123518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1124518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> response; 1125518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return PostAndAwaitResponse(msg, &response); 1126518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 1127518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1128518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianstatus_t MediaCodec::getOutputFormat(sp<AMessage> *format) const { 1129518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> msg = new AMessage(kWhatGetOutputFormat, this); 1130b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall 1131518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> response; 1132518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian status_t err; 1133518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if ((err = PostAndAwaitResponse(msg, &response)) != OK) { 1134ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian return err; 1135ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian } 1136ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian 1137518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian CHECK(response->findMessage("format", format)); 1138ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian 1139518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return OK; 1140518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 1141518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1142518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianstatus_t MediaCodec::getInputFormat(sp<AMessage> *format) const { 1143518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> msg = new AMessage(kWhatGetInputFormat, this); 1144518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1145518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> response; 1146518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian status_t err; 1147518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if ((err = PostAndAwaitResponse(msg, &response)) != OK) { 1148518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return err; 1149518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 1150518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1151ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian CHECK(response->findMessage("format", format)); 1152ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian 1153ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian return OK; 1154ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian} 1155ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian 1156ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopianstatus_t MediaCodec::getName(AString *name) const { 1157ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian sp<AMessage> msg = new AMessage(kWhatGetName, this); 1158ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian 1159ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian sp<AMessage> response; 1160518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian status_t err; 1161518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if ((err = PostAndAwaitResponse(msg, &response)) != OK) { 1162518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return err; 1163518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 1164518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1165518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian CHECK(response->findString("name", name)); 1166518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1167518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return OK; 1168518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 1169518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1170518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianstatus_t MediaCodec::getMetrics(Parcel *reply) { 1171518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1172518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian // shouldn't happen, but be safe 1173518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (mAnalyticsItem == NULL) { 1174ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian return UNKNOWN_ERROR; 1175ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian } 1176ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian 1177518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian // XXX: go get current values for whatever in-flight data we want 1178518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1179518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian // send it back to the caller. 1180518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mAnalyticsItem->writeToParcel(reply); 1181518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1182518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return OK; 1183518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 1184518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1185518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianstatus_t MediaCodec::getInputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const { 1186518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> msg = new AMessage(kWhatGetBuffers, this); 1187518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian msg->setInt32("portIndex", kPortIndexInput); 1188518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian msg->setPointer("buffers", buffers); 1189ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian 1190ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian sp<AMessage> response; 1191ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian return PostAndAwaitResponse(msg, &response); 1192518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 1193ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian 1194518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianstatus_t MediaCodec::getOutputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const { 1195518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> msg = new AMessage(kWhatGetBuffers, this); 1196518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian msg->setInt32("portIndex", kPortIndexOutput); 1197518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian msg->setPointer("buffers", buffers); 1198518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1199518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> response; 1200518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return PostAndAwaitResponse(msg, &response); 1201518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 12024e620ddce344e946ced992f61a69c367ff92fe24Mathias Agopian 12034e620ddce344e946ced992f61a69c367ff92fe24Mathias Agopianstatus_t MediaCodec::getOutputBuffer(size_t index, sp<MediaCodecBuffer> *buffer) { 12044e620ddce344e946ced992f61a69c367ff92fe24Mathias Agopian sp<AMessage> format; 12054e620ddce344e946ced992f61a69c367ff92fe24Mathias Agopian return getBufferAndFormat(kPortIndexOutput, index, buffer, &format); 12064e620ddce344e946ced992f61a69c367ff92fe24Mathias Agopian} 1207518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1208fb87e54a9af8bc5063ca4deebe81d90126992480Mathias Agopianstatus_t MediaCodec::getOutputFormat(size_t index, sp<AMessage> *format) { 1209518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<MediaCodecBuffer> buffer; 1210ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian return getBufferAndFormat(kPortIndexOutput, index, &buffer, format); 1211ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian} 1212ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian 1213518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianstatus_t MediaCodec::getInputBuffer(size_t index, sp<MediaCodecBuffer> *buffer) { 1214518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> format; 1215518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return getBufferAndFormat(kPortIndexInput, index, buffer, &format); 1216518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 1217518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1218518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianbool MediaCodec::isExecuting() const { 1219518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return mState == STARTED || mState == FLUSHED; 1220518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 1221518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1222518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianstatus_t MediaCodec::getBufferAndFormat( 1223518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian size_t portIndex, size_t index, 1224b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall sp<MediaCodecBuffer> *buffer, sp<AMessage> *format) { 1225b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall // use mutex instead of a context switch 1226b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall if (mReleasedByResourceManager) { 1227518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian ALOGE("getBufferAndFormat - resource already released"); 1228518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return DEAD_OBJECT; 12297773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian } 1230518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1231518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (buffer == NULL) { 1232518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian ALOGE("getBufferAndFormat - null MediaCodecBuffer"); 1233518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return INVALID_OPERATION; 1234518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 1235518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1236518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (format == NULL) { 1237518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian ALOGE("getBufferAndFormat - null AMessage"); 1238518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return INVALID_OPERATION; 1239518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 1240518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1241518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian buffer->clear(); 1242518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian format->clear(); 1243b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall 1244518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (!isExecuting()) { 1245518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian ALOGE("getBufferAndFormat - not executing"); 1246b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall return INVALID_OPERATION; 12475b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian } 12485b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian 1249518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian // we do not want mPortBuffers to change during this section 1250518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian // we also don't want mOwnedByClient to change during this 1251518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian Mutex::Autolock al(mBufferLock); 1252518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1253ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian std::vector<BufferInfo> &buffers = mPortBuffers[portIndex]; 1254518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (index >= buffers.size()) { 1255518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian ALOGE("getBufferAndFormat - trying to get buffer with " 1256518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian "bad index (index=%zu buffer_size=%zu)", index, buffers.size()); 1257518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return INVALID_OPERATION; 1258518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 1259518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1260518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian const BufferInfo &info = buffers[index]; 1261518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (!info.mOwnedByClient) { 1262b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall ALOGE("getBufferAndFormat - invalid operation " 1263518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian "(the index %zu is not owned by client)", index); 1264518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return INVALID_OPERATION; 1265b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall } 12665b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian 12675b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian *buffer = info.mData; 1268518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian *format = info.mData->format(); 1269518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1270518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return OK; 1271ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian} 1272518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1273518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianstatus_t MediaCodec::flush() { 1274518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> msg = new AMessage(kWhatFlush, this); 1275518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1276518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> response; 1277518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return PostAndAwaitResponse(msg, &response); 1278518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 1279518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1280518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianstatus_t MediaCodec::requestIDRFrame() { 1281b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall (new AMessage(kWhatRequestIDRFrame, this))->post(); 1282518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1283518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return OK; 1284b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall} 12857c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian 1286518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianvoid MediaCodec::requestActivityNotification(const sp<AMessage> ¬ify) { 12877c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian sp<AMessage> msg = new AMessage(kWhatRequestActivityNotification, this); 12887c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian msg->setMessage("notify", notify); 12897c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian msg->post(); 12907c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian} 12917c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian 12927c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian//////////////////////////////////////////////////////////////////////////////// 12937c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian 1294518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianvoid MediaCodec::cancelPendingDequeueOperations() { 12957c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian if (mFlags & kFlagDequeueInputPending) { 1296518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian PostReplyWithError(mDequeueInputReplyID, INVALID_OPERATION); 1297518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1298518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian ++mDequeueInputTimeoutGeneration; 1299518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mDequeueInputReplyID = 0; 1300518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mFlags &= ~kFlagDequeueInputPending; 1301518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 1302b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall 1303518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (mFlags & kFlagDequeueOutputPending) { 1304518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian PostReplyWithError(mDequeueOutputReplyID, INVALID_OPERATION); 1305646a5c593f9819dc5da6a1ec859bc70cb7ba096fSteven Holte 1306ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian ++mDequeueOutputTimeoutGeneration; 13077c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian mDequeueOutputReplyID = 0; 1308646a5c593f9819dc5da6a1ec859bc70cb7ba096fSteven Holte mFlags &= ~kFlagDequeueOutputPending; 1309518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 1310646a5c593f9819dc5da6a1ec859bc70cb7ba096fSteven Holte} 1311518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1312518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianbool MediaCodec::handleDequeueInputBuffer(const sp<AReplyToken> &replyID, bool newRequest) { 1313518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (!isExecuting() || (mFlags & kFlagIsAsync) 1314518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian || (newRequest && (mFlags & kFlagDequeueInputPending))) { 1315518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian PostReplyWithError(replyID, INVALID_OPERATION); 1316518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return true; 1317518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } else if (mFlags & kFlagStickyError) { 1318518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian PostReplyWithError(replyID, getStickyError()); 1319518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return true; 1320518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } 1321518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1322b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall ssize_t index = dequeuePortBuffer(kPortIndexInput); 1323518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1324518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (index < 0) { 1325518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian CHECK_EQ(index, -EAGAIN); 13267c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian return false; 13277c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian } 13287c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian 1329518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian sp<AMessage> response = new AMessage; 13307c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian response->setSize("index", index); 1331518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian response->postReply(replyID); 1332518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1333518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return true; 1334518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian} 1335518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1336518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianbool MediaCodec::handleDequeueOutputBuffer(const sp<AReplyToken> &replyID, bool newRequest) { 1337b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall if (!isExecuting() || (mFlags & kFlagIsAsync) 1338518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian || (newRequest && (mFlags & kFlagDequeueOutputPending))) { 1339518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian PostReplyWithError(replyID, INVALID_OPERATION); 1340518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } else if (mFlags & kFlagStickyError) { 13417c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian PostReplyWithError(replyID, getStickyError()); 13427c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian } else if (mFlags & kFlagOutputBuffersChanged) { 13437c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian PostReplyWithError(replyID, INFO_OUTPUT_BUFFERS_CHANGED); 1344518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mFlags &= ~kFlagOutputBuffersChanged; 1345518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian } else if (mFlags & kFlagOutputFormatChanged) { 1346518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian PostReplyWithError(replyID, INFO_FORMAT_CHANGED); 1347518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mFlags &= ~kFlagOutputFormatChanged; 1348e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian } else { 1349e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian sp<AMessage> response = new AMessage; 1350e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian ssize_t index = dequeuePortBuffer(kPortIndexOutput); 1351e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian 1352e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian if (index < 0) { 1353e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian CHECK_EQ(index, -EAGAIN); 1354e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian return false; 1355e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian } 1356e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian 1357e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian const sp<MediaCodecBuffer> &buffer = 1358e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian mPortBuffers[kPortIndexOutput][index].mData; 1359e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian 1360e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian response->setSize("index", index); 1361e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian response->setSize("offset", buffer->offset()); 1362e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian response->setSize("size", buffer->size()); 13637c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian 13647c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian int64_t timeUs; 1365518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 1366518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1367518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian response->setInt64("timeUs", timeUs); 1368b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall 1369518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian int32_t flags; 1370518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian CHECK(buffer->meta()->findInt32("flags", &flags)); 13717c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian 13727c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian response->setInt32("flags", flags); 13737c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian response->postReply(replyID); 13747c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian } 13757c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian 1376518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian return true; 13777c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian} 1378518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1379518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianvoid MediaCodec::onMessageReceived(const sp<AMessage> &msg) { 13807c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian switch (msg->what()) { 13817c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian case kWhatCodecNotify: 1382518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian { 1383518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian int32_t what; 1384518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian CHECK(msg->findInt32("what", &what)); 1385b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall 1386518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian switch (what) { 1387518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian case kWhatError: 13887c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian { 13897c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian int32_t err, actionCode; 13907c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian CHECK(msg->findInt32("err", &err)); 13917c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian CHECK(msg->findInt32("actionCode", &actionCode)); 13927c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian 1393518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian ALOGE("Codec reported err %#x, actionCode %d, while in state %d", 13947c0441ac271f4e00a2d63eb3048c037ebffa90b9Mathias Agopian err, actionCode, mState); 1395518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian if (err == DEAD_OBJECT) { 1396518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mFlags |= kFlagSawMediaServerDie; 1397518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian mFlags &= ~kFlagIsComponentAllocated; 13982bb716871cf8bfadfff1193ed798da3bffc1f8ecMathias Agopian } 1399518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian 1400518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian bool sendErrorResponse = true; 14012bb716871cf8bfadfff1193ed798da3bffc1f8ecMathias Agopian 1402331841b96b92646c93c87627c03f77b892f711cdJamie Gennis switch (mState) { 1403331841b96b92646c93c87627c03f77b892f711cdJamie Gennis case INITIALIZING: 14042bb716871cf8bfadfff1193ed798da3bffc1f8ecMathias Agopian { 14052bb716871cf8bfadfff1193ed798da3bffc1f8ecMathias Agopian setState(UNINITIALIZED); 1406331841b96b92646c93c87627c03f77b892f711cdJamie Gennis break; 14072bb716871cf8bfadfff1193ed798da3bffc1f8ecMathias Agopian } 14082bb716871cf8bfadfff1193ed798da3bffc1f8ecMathias Agopian 1409331841b96b92646c93c87627c03f77b892f711cdJamie Gennis case CONFIGURING: 1410331841b96b92646c93c87627c03f77b892f711cdJamie Gennis { 1411331841b96b92646c93c87627c03f77b892f711cdJamie Gennis setState(actionCode == ACTION_CODE_FATAL ? 14121c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang UNINITIALIZED : INITIALIZED); 14132bb716871cf8bfadfff1193ed798da3bffc1f8ecMathias Agopian break; 14142bb716871cf8bfadfff1193ed798da3bffc1f8ecMathias Agopian } 14152bb716871cf8bfadfff1193ed798da3bffc1f8ecMathias Agopian 14162bb716871cf8bfadfff1193ed798da3bffc1f8ecMathias Agopian case STARTING: 14172bb716871cf8bfadfff1193ed798da3bffc1f8ecMathias Agopian { 1418010dd4fb892aecf71e4631c22148fe57ef5b3958Jamie Gennis setState(actionCode == ACTION_CODE_FATAL ? 1419010dd4fb892aecf71e4631c22148fe57ef5b3958Jamie Gennis UNINITIALIZED : CONFIGURED); 1420010dd4fb892aecf71e4631c22148fe57ef5b3958Jamie Gennis break; 1421010dd4fb892aecf71e4631c22148fe57ef5b3958Jamie Gennis } 1422010dd4fb892aecf71e4631c22148fe57ef5b3958Jamie Gennis 1423010dd4fb892aecf71e4631c22148fe57ef5b3958Jamie Gennis case RELEASING: 14242bb716871cf8bfadfff1193ed798da3bffc1f8ecMathias Agopian { 1425010dd4fb892aecf71e4631c22148fe57ef5b3958Jamie Gennis // Ignore the error, assuming we'll still get 14262bb716871cf8bfadfff1193ed798da3bffc1f8ecMathias Agopian // the shutdown complete notification. If we 14272bb716871cf8bfadfff1193ed798da3bffc1f8ecMathias Agopian // don't, we'll timeout and force release. 1428010dd4fb892aecf71e4631c22148fe57ef5b3958Jamie Gennis sendErrorResponse = false; 1429010dd4fb892aecf71e4631c22148fe57ef5b3958Jamie Gennis } 1430010dd4fb892aecf71e4631c22148fe57ef5b3958Jamie Gennis // fall-thru 1431010dd4fb892aecf71e4631c22148fe57ef5b3958Jamie Gennis case STOPPING: 14327284145d564fa8a422a8e564a38c730fb4a2962bAndy McFadden { 14337284145d564fa8a422a8e564a38c730fb4a2962bAndy McFadden if (mFlags & kFlagSawMediaServerDie) { 14347284145d564fa8a422a8e564a38c730fb4a2962bAndy McFadden // MediaServer died, there definitely won't 14357284145d564fa8a422a8e564a38c730fb4a2962bAndy McFadden // be a shutdown complete notification after 14367284145d564fa8a422a8e564a38c730fb4a2962bAndy McFadden // all. 14377284145d564fa8a422a8e564a38c730fb4a2962bAndy McFadden 14387284145d564fa8a422a8e564a38c730fb4a2962bAndy McFadden // note that we're directly going from 14397284145d564fa8a422a8e564a38c730fb4a2962bAndy McFadden // STOPPING->UNINITIALIZED, instead of the 14407284145d564fa8a422a8e564a38c730fb4a2962bAndy McFadden // usual STOPPING->INITIALIZED state. 14417284145d564fa8a422a8e564a38c730fb4a2962bAndy McFadden setState(UNINITIALIZED); 14427284145d564fa8a422a8e564a38c730fb4a2962bAndy McFadden if (mState == RELEASING) { 14437284145d564fa8a422a8e564a38c730fb4a2962bAndy McFadden mComponentName.clear(); 14447284145d564fa8a422a8e564a38c730fb4a2962bAndy McFadden } 14457284145d564fa8a422a8e564a38c730fb4a2962bAndy McFadden (new AMessage)->postReply(mReplyID); 14467284145d564fa8a422a8e564a38c730fb4a2962bAndy McFadden sendErrorResponse = false; 14477284145d564fa8a422a8e564a38c730fb4a2962bAndy McFadden } 14487284145d564fa8a422a8e564a38c730fb4a2962bAndy McFadden break; 14497284145d564fa8a422a8e564a38c730fb4a2962bAndy McFadden } 14507284145d564fa8a422a8e564a38c730fb4a2962bAndy McFadden 14517284145d564fa8a422a8e564a38c730fb4a2962bAndy McFadden case FLUSHING: 14527284145d564fa8a422a8e564a38c730fb4a2962bAndy McFadden { 14537284145d564fa8a422a8e564a38c730fb4a2962bAndy McFadden if (actionCode == ACTION_CODE_FATAL) { 14541c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang setState(UNINITIALIZED); 14551c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang } else { 14561c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang setState( 14571c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang (mFlags & kFlagIsAsync) ? FLUSHED : STARTED); 14581c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang } 14591c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang break; 14601c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang } 14611c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang 14621c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang case FLUSHED: 14631c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang case STARTED: 14641c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang { 14651c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang sendErrorResponse = false; 1466ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian 14671c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang setStickyError(err); 1468ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian postActivityNotificationIfPossible(); 1469ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian 14701c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang cancelPendingDequeueOperations(); 14711c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang 14720e8bbee5775d81c7bbc479b995496cac9238559fMathias Agopian if (mFlags & kFlagIsAsync) { 14731c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang onError(err, actionCode); 14741c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang } 14751c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang switch (actionCode) { 14761c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang case ACTION_CODE_TRANSIENT: 14771c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang break; 14781c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang case ACTION_CODE_RECOVERABLE: 14791c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang setState(INITIALIZED); 14801c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang break; 14811c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang default: 14821c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang setState(UNINITIALIZED); 14831c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang break; 1484ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian } 14851c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang break; 1486ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian } 1487ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian 14881c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang default: 14891c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang { 14900e8bbee5775d81c7bbc479b995496cac9238559fMathias Agopian sendErrorResponse = false; 14911c3d72a2291827fb15e2ef311a571c860e0dba41Jonas Yang 1492 setStickyError(err); 1493 postActivityNotificationIfPossible(); 1494 1495 // actionCode in an uninitialized state is always fatal. 1496 if (mState == UNINITIALIZED) { 1497 actionCode = ACTION_CODE_FATAL; 1498 } 1499 if (mFlags & kFlagIsAsync) { 1500 onError(err, actionCode); 1501 } 1502 switch (actionCode) { 1503 case ACTION_CODE_TRANSIENT: 1504 break; 1505 case ACTION_CODE_RECOVERABLE: 1506 setState(INITIALIZED); 1507 break; 1508 default: 1509 setState(UNINITIALIZED); 1510 break; 1511 } 1512 break; 1513 } 1514 } 1515 1516 if (sendErrorResponse) { 1517 PostReplyWithError(mReplyID, err); 1518 } 1519 break; 1520 } 1521 1522 case kWhatComponentAllocated: 1523 { 1524 CHECK_EQ(mState, INITIALIZING); 1525 setState(INITIALIZED); 1526 mFlags |= kFlagIsComponentAllocated; 1527 1528 CHECK(msg->findString("componentName", &mComponentName)); 1529 1530 if (mComponentName.c_str()) { 1531 mAnalyticsItem->setCString(kCodecCodec, mComponentName.c_str()); 1532 } 1533 1534 if (mComponentName.startsWith("OMX.google.")) { 1535 mFlags |= kFlagUsesSoftwareRenderer; 1536 } else { 1537 mFlags &= ~kFlagUsesSoftwareRenderer; 1538 } 1539 1540 MediaResource::Type resourceType; 1541 if (mComponentName.endsWith(".secure")) { 1542 mFlags |= kFlagIsSecure; 1543 resourceType = MediaResource::kSecureCodec; 1544 mAnalyticsItem->setInt32(kCodecSecure, 1); 1545 } else { 1546 mFlags &= ~kFlagIsSecure; 1547 resourceType = MediaResource::kNonSecureCodec; 1548 mAnalyticsItem->setInt32(kCodecSecure, 0); 1549 } 1550 1551 if (mIsVideo) { 1552 // audio codec is currently ignored. 1553 addResource(resourceType, MediaResource::kVideoCodec, 1); 1554 } 1555 1556 (new AMessage)->postReply(mReplyID); 1557 break; 1558 } 1559 1560 case kWhatComponentConfigured: 1561 { 1562 if (mState == UNINITIALIZED || mState == INITIALIZED) { 1563 // In case a kWhatError message came in and replied with error, 1564 // we log a warning and ignore. 1565 ALOGW("configure interrupted by error, current state %d", mState); 1566 break; 1567 } 1568 CHECK_EQ(mState, CONFIGURING); 1569 1570 // reset input surface flag 1571 mHaveInputSurface = false; 1572 1573 CHECK(msg->findMessage("input-format", &mInputFormat)); 1574 CHECK(msg->findMessage("output-format", &mOutputFormat)); 1575 ALOGV("[%s] configured as input format: %s, output format: %s", 1576 mComponentName.c_str(), 1577 mInputFormat->debugString(4).c_str(), 1578 mOutputFormat->debugString(4).c_str()); 1579 int32_t usingSwRenderer; 1580 if (mOutputFormat->findInt32("using-sw-renderer", &usingSwRenderer) 1581 && usingSwRenderer) { 1582 mFlags |= kFlagUsesSoftwareRenderer; 1583 } 1584 setState(CONFIGURED); 1585 (new AMessage)->postReply(mReplyID); 1586 break; 1587 } 1588 1589 case kWhatInputSurfaceCreated: 1590 { 1591 // response to initiateCreateInputSurface() 1592 status_t err = NO_ERROR; 1593 sp<AMessage> response = new AMessage; 1594 if (!msg->findInt32("err", &err)) { 1595 sp<RefBase> obj; 1596 msg->findObject("input-surface", &obj); 1597 CHECK(msg->findMessage("input-format", &mInputFormat)); 1598 CHECK(msg->findMessage("output-format", &mOutputFormat)); 1599 ALOGV("[%s] input surface created as input format: %s, output format: %s", 1600 mComponentName.c_str(), 1601 mInputFormat->debugString(4).c_str(), 1602 mOutputFormat->debugString(4).c_str()); 1603 CHECK(obj != NULL); 1604 response->setObject("input-surface", obj); 1605 mHaveInputSurface = true; 1606 } else { 1607 response->setInt32("err", err); 1608 } 1609 response->postReply(mReplyID); 1610 break; 1611 } 1612 1613 case kWhatInputSurfaceAccepted: 1614 { 1615 // response to initiateSetInputSurface() 1616 status_t err = NO_ERROR; 1617 sp<AMessage> response = new AMessage(); 1618 if (!msg->findInt32("err", &err)) { 1619 CHECK(msg->findMessage("input-format", &mInputFormat)); 1620 CHECK(msg->findMessage("output-format", &mOutputFormat)); 1621 mHaveInputSurface = true; 1622 } else { 1623 response->setInt32("err", err); 1624 } 1625 response->postReply(mReplyID); 1626 break; 1627 } 1628 1629 case kWhatSignaledInputEOS: 1630 { 1631 // response to signalEndOfInputStream() 1632 sp<AMessage> response = new AMessage; 1633 status_t err; 1634 if (msg->findInt32("err", &err)) { 1635 response->setInt32("err", err); 1636 } 1637 response->postReply(mReplyID); 1638 break; 1639 } 1640 1641 case kWhatStartCompleted: 1642 { 1643 CHECK_EQ(mState, STARTING); 1644 if (mIsVideo) { 1645 addResource( 1646 MediaResource::kGraphicMemory, 1647 MediaResource::kUnspecifiedSubType, 1648 getGraphicBufferSize()); 1649 } 1650 setState(STARTED); 1651 (new AMessage)->postReply(mReplyID); 1652 break; 1653 } 1654 1655 case kWhatOutputBuffersChanged: 1656 { 1657 mFlags |= kFlagOutputBuffersChanged; 1658 postActivityNotificationIfPossible(); 1659 break; 1660 } 1661 1662 case kWhatOutputFramesRendered: 1663 { 1664 // ignore these in all states except running, and check that we have a 1665 // notification set 1666 if (mState == STARTED && mOnFrameRenderedNotification != NULL) { 1667 sp<AMessage> notify = mOnFrameRenderedNotification->dup(); 1668 notify->setMessage("data", msg); 1669 notify->post(); 1670 } 1671 break; 1672 } 1673 1674 case kWhatFillThisBuffer: 1675 { 1676 /* size_t index = */updateBuffers(kPortIndexInput, msg); 1677 1678 if (mState == FLUSHING 1679 || mState == STOPPING 1680 || mState == RELEASING) { 1681 returnBuffersToCodecOnPort(kPortIndexInput); 1682 break; 1683 } 1684 1685 if (!mCSD.empty()) { 1686 ssize_t index = dequeuePortBuffer(kPortIndexInput); 1687 CHECK_GE(index, 0); 1688 1689 // If codec specific data had been specified as 1690 // part of the format in the call to configure and 1691 // if there's more csd left, we submit it here 1692 // clients only get access to input buffers once 1693 // this data has been exhausted. 1694 1695 status_t err = queueCSDInputBuffer(index); 1696 1697 if (err != OK) { 1698 ALOGE("queueCSDInputBuffer failed w/ error %d", 1699 err); 1700 1701 setStickyError(err); 1702 postActivityNotificationIfPossible(); 1703 1704 cancelPendingDequeueOperations(); 1705 } 1706 break; 1707 } 1708 1709 if (mFlags & kFlagIsAsync) { 1710 if (!mHaveInputSurface) { 1711 if (mState == FLUSHED) { 1712 mHavePendingInputBuffers = true; 1713 } else { 1714 onInputBufferAvailable(); 1715 } 1716 } 1717 } else if (mFlags & kFlagDequeueInputPending) { 1718 CHECK(handleDequeueInputBuffer(mDequeueInputReplyID)); 1719 1720 ++mDequeueInputTimeoutGeneration; 1721 mFlags &= ~kFlagDequeueInputPending; 1722 mDequeueInputReplyID = 0; 1723 } else { 1724 postActivityNotificationIfPossible(); 1725 } 1726 break; 1727 } 1728 1729 case kWhatDrainThisBuffer: 1730 { 1731 /* size_t index = */updateBuffers(kPortIndexOutput, msg); 1732 1733 if (mState == FLUSHING 1734 || mState == STOPPING 1735 || mState == RELEASING) { 1736 returnBuffersToCodecOnPort(kPortIndexOutput); 1737 break; 1738 } 1739 1740 sp<RefBase> obj; 1741 CHECK(msg->findObject("buffer", &obj)); 1742 sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get()); 1743 1744 if (mOutputFormat != buffer->format()) { 1745 mOutputFormat = buffer->format(); 1746 ALOGV("[%s] output format changed to: %s", 1747 mComponentName.c_str(), mOutputFormat->debugString(4).c_str()); 1748 1749 if (mSoftRenderer == NULL && 1750 mSurface != NULL && 1751 (mFlags & kFlagUsesSoftwareRenderer)) { 1752 AString mime; 1753 CHECK(mOutputFormat->findString("mime", &mime)); 1754 1755 // TODO: propagate color aspects to software renderer to allow better 1756 // color conversion to RGB. For now, just mark dataspace for YUV 1757 // rendering. 1758 int32_t dataSpace; 1759 if (mOutputFormat->findInt32("android._dataspace", &dataSpace)) { 1760 ALOGD("[%s] setting dataspace on output surface to #%x", 1761 mComponentName.c_str(), dataSpace); 1762 int err = native_window_set_buffers_data_space( 1763 mSurface.get(), (android_dataspace)dataSpace); 1764 ALOGW_IF(err != 0, "failed to set dataspace on surface (%d)", err); 1765 } 1766 1767 if (mime.startsWithIgnoreCase("video/")) { 1768 mSoftRenderer = new SoftwareRenderer(mSurface, mRotationDegrees); 1769 } 1770 } 1771 1772 if (mFlags & kFlagIsEncoder) { 1773 // Before we announce the format change we should 1774 // collect codec specific data and amend the output 1775 // format as necessary. 1776 int32_t flags = 0; 1777 (void) buffer->meta()->findInt32("flags", &flags); 1778 if (flags & BUFFER_FLAG_CODECCONFIG) { 1779 status_t err = 1780 amendOutputFormatWithCodecSpecificData(buffer); 1781 1782 if (err != OK) { 1783 ALOGE("Codec spit out malformed codec " 1784 "specific data!"); 1785 } 1786 } 1787 } 1788 1789 if (mFlags & kFlagIsAsync) { 1790 onOutputFormatChanged(); 1791 } else { 1792 mFlags |= kFlagOutputFormatChanged; 1793 postActivityNotificationIfPossible(); 1794 } 1795 1796 // Notify mCrypto of video resolution changes 1797 if (mCrypto != NULL) { 1798 int32_t left, top, right, bottom, width, height; 1799 if (mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) { 1800 mCrypto->notifyResolution(right - left + 1, bottom - top + 1); 1801 } else if (mOutputFormat->findInt32("width", &width) 1802 && mOutputFormat->findInt32("height", &height)) { 1803 mCrypto->notifyResolution(width, height); 1804 } 1805 } 1806 } 1807 1808 if (mFlags & kFlagIsAsync) { 1809 onOutputBufferAvailable(); 1810 } else if (mFlags & kFlagDequeueOutputPending) { 1811 CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID)); 1812 1813 ++mDequeueOutputTimeoutGeneration; 1814 mFlags &= ~kFlagDequeueOutputPending; 1815 mDequeueOutputReplyID = 0; 1816 } else { 1817 postActivityNotificationIfPossible(); 1818 } 1819 1820 break; 1821 } 1822 1823 case kWhatEOS: 1824 { 1825 // We already notify the client of this by using the 1826 // corresponding flag in "onOutputBufferReady". 1827 break; 1828 } 1829 1830 case kWhatStopCompleted: 1831 { 1832 if (mState != STOPPING) { 1833 ALOGW("Received kWhatStopCompleted in state %d", mState); 1834 break; 1835 } 1836 setState(INITIALIZED); 1837 (new AMessage)->postReply(mReplyID); 1838 break; 1839 } 1840 1841 case kWhatReleaseCompleted: 1842 { 1843 if (mState != RELEASING) { 1844 ALOGW("Received kWhatReleaseCompleted in state %d", mState); 1845 break; 1846 } 1847 setState(UNINITIALIZED); 1848 mComponentName.clear(); 1849 1850 mFlags &= ~kFlagIsComponentAllocated; 1851 1852 mResourceManagerService->removeResource(getId(mResourceManagerClient)); 1853 1854 (new AMessage)->postReply(mReplyID); 1855 break; 1856 } 1857 1858 case kWhatFlushCompleted: 1859 { 1860 if (mState != FLUSHING) { 1861 ALOGW("received FlushCompleted message in state %d", 1862 mState); 1863 break; 1864 } 1865 1866 if (mFlags & kFlagIsAsync) { 1867 setState(FLUSHED); 1868 } else { 1869 setState(STARTED); 1870 mCodec->signalResume(); 1871 } 1872 1873 (new AMessage)->postReply(mReplyID); 1874 break; 1875 } 1876 1877 default: 1878 TRESPASS(); 1879 } 1880 break; 1881 } 1882 1883 case kWhatInit: 1884 { 1885 sp<AReplyToken> replyID; 1886 CHECK(msg->senderAwaitsResponse(&replyID)); 1887 1888 if (mState != UNINITIALIZED) { 1889 PostReplyWithError(replyID, INVALID_OPERATION); 1890 break; 1891 } 1892 1893 mReplyID = replyID; 1894 setState(INITIALIZING); 1895 1896 AString name; 1897 CHECK(msg->findString("name", &name)); 1898 1899 int32_t nameIsType; 1900 int32_t encoder = false; 1901 CHECK(msg->findInt32("nameIsType", &nameIsType)); 1902 if (nameIsType) { 1903 CHECK(msg->findInt32("encoder", &encoder)); 1904 } 1905 1906 sp<AMessage> format = new AMessage; 1907 1908 if (nameIsType) { 1909 format->setString("mime", name.c_str()); 1910 format->setInt32("encoder", encoder); 1911 } else { 1912 format->setString("componentName", name.c_str()); 1913 } 1914 1915 mCodec->initiateAllocateComponent(format); 1916 break; 1917 } 1918 1919 case kWhatSetNotification: 1920 { 1921 sp<AMessage> notify; 1922 if (msg->findMessage("on-frame-rendered", ¬ify)) { 1923 mOnFrameRenderedNotification = notify; 1924 } 1925 break; 1926 } 1927 1928 case kWhatSetCallback: 1929 { 1930 sp<AReplyToken> replyID; 1931 CHECK(msg->senderAwaitsResponse(&replyID)); 1932 1933 if (mState == UNINITIALIZED 1934 || mState == INITIALIZING 1935 || isExecuting()) { 1936 // callback can't be set after codec is executing, 1937 // or before it's initialized (as the callback 1938 // will be cleared when it goes to INITIALIZED) 1939 PostReplyWithError(replyID, INVALID_OPERATION); 1940 break; 1941 } 1942 1943 sp<AMessage> callback; 1944 CHECK(msg->findMessage("callback", &callback)); 1945 1946 mCallback = callback; 1947 1948 if (mCallback != NULL) { 1949 ALOGI("MediaCodec will operate in async mode"); 1950 mFlags |= kFlagIsAsync; 1951 } else { 1952 mFlags &= ~kFlagIsAsync; 1953 } 1954 1955 sp<AMessage> response = new AMessage; 1956 response->postReply(replyID); 1957 break; 1958 } 1959 1960 case kWhatConfigure: 1961 { 1962 sp<AReplyToken> replyID; 1963 CHECK(msg->senderAwaitsResponse(&replyID)); 1964 1965 if (mState != INITIALIZED) { 1966 PostReplyWithError(replyID, INVALID_OPERATION); 1967 break; 1968 } 1969 1970 sp<RefBase> obj; 1971 CHECK(msg->findObject("surface", &obj)); 1972 1973 sp<AMessage> format; 1974 CHECK(msg->findMessage("format", &format)); 1975 1976 int32_t push; 1977 if (msg->findInt32("push-blank-buffers-on-shutdown", &push) && push != 0) { 1978 mFlags |= kFlagPushBlankBuffersOnShutdown; 1979 } 1980 1981 if (obj != NULL) { 1982 format->setObject("native-window", obj); 1983 status_t err = handleSetSurface(static_cast<Surface *>(obj.get())); 1984 if (err != OK) { 1985 PostReplyWithError(replyID, err); 1986 break; 1987 } 1988 } else { 1989 handleSetSurface(NULL); 1990 } 1991 1992 mReplyID = replyID; 1993 setState(CONFIGURING); 1994 1995 void *crypto; 1996 if (!msg->findPointer("crypto", &crypto)) { 1997 crypto = NULL; 1998 } 1999 2000 ALOGV("kWhatConfigure: Old mCrypto: %p (%d)", 2001 mCrypto.get(), (mCrypto != NULL ? mCrypto->getStrongCount() : 0)); 2002 2003 mCrypto = static_cast<ICrypto *>(crypto); 2004 mBufferChannel->setCrypto(mCrypto); 2005 2006 ALOGV("kWhatConfigure: New mCrypto: %p (%d)", 2007 mCrypto.get(), (mCrypto != NULL ? mCrypto->getStrongCount() : 0)); 2008 2009 void *descrambler; 2010 if (!msg->findPointer("descrambler", &descrambler)) { 2011 descrambler = NULL; 2012 } 2013 2014 mDescrambler = static_cast<IDescrambler *>(descrambler); 2015 mBufferChannel->setDescrambler(mDescrambler); 2016 2017 uint32_t flags; 2018 CHECK(msg->findInt32("flags", (int32_t *)&flags)); 2019 2020 if (flags & CONFIGURE_FLAG_ENCODE) { 2021 format->setInt32("encoder", true); 2022 mFlags |= kFlagIsEncoder; 2023 } 2024 2025 extractCSD(format); 2026 2027 mCodec->initiateConfigureComponent(format); 2028 break; 2029 } 2030 2031 case kWhatSetSurface: 2032 { 2033 sp<AReplyToken> replyID; 2034 CHECK(msg->senderAwaitsResponse(&replyID)); 2035 2036 status_t err = OK; 2037 2038 switch (mState) { 2039 case CONFIGURED: 2040 case STARTED: 2041 case FLUSHED: 2042 { 2043 sp<RefBase> obj; 2044 (void)msg->findObject("surface", &obj); 2045 sp<Surface> surface = static_cast<Surface *>(obj.get()); 2046 if (mSurface == NULL) { 2047 // do not support setting surface if it was not set 2048 err = INVALID_OPERATION; 2049 } else if (obj == NULL) { 2050 // do not support unsetting surface 2051 err = BAD_VALUE; 2052 } else { 2053 err = connectToSurface(surface); 2054 if (err == ALREADY_EXISTS) { 2055 // reconnecting to same surface 2056 err = OK; 2057 } else { 2058 if (err == OK) { 2059 if (mFlags & kFlagUsesSoftwareRenderer) { 2060 if (mSoftRenderer != NULL 2061 && (mFlags & kFlagPushBlankBuffersOnShutdown)) { 2062 pushBlankBuffersToNativeWindow(mSurface.get()); 2063 } 2064 mSoftRenderer = new SoftwareRenderer(surface); 2065 // TODO: check if this was successful 2066 } else { 2067 err = mCodec->setSurface(surface); 2068 } 2069 } 2070 if (err == OK) { 2071 (void)disconnectFromSurface(); 2072 mSurface = surface; 2073 } 2074 } 2075 } 2076 break; 2077 } 2078 2079 default: 2080 err = INVALID_OPERATION; 2081 break; 2082 } 2083 2084 PostReplyWithError(replyID, err); 2085 break; 2086 } 2087 2088 case kWhatCreateInputSurface: 2089 case kWhatSetInputSurface: 2090 { 2091 sp<AReplyToken> replyID; 2092 CHECK(msg->senderAwaitsResponse(&replyID)); 2093 2094 // Must be configured, but can't have been started yet. 2095 if (mState != CONFIGURED) { 2096 PostReplyWithError(replyID, INVALID_OPERATION); 2097 break; 2098 } 2099 2100 mReplyID = replyID; 2101 if (msg->what() == kWhatCreateInputSurface) { 2102 mCodec->initiateCreateInputSurface(); 2103 } else { 2104 sp<RefBase> obj; 2105 CHECK(msg->findObject("input-surface", &obj)); 2106 2107 mCodec->initiateSetInputSurface( 2108 static_cast<PersistentSurface *>(obj.get())); 2109 } 2110 break; 2111 } 2112 case kWhatStart: 2113 { 2114 sp<AReplyToken> replyID; 2115 CHECK(msg->senderAwaitsResponse(&replyID)); 2116 2117 if (mState == FLUSHED) { 2118 setState(STARTED); 2119 if (mHavePendingInputBuffers) { 2120 onInputBufferAvailable(); 2121 mHavePendingInputBuffers = false; 2122 } 2123 mCodec->signalResume(); 2124 PostReplyWithError(replyID, OK); 2125 break; 2126 } else if (mState != CONFIGURED) { 2127 PostReplyWithError(replyID, INVALID_OPERATION); 2128 break; 2129 } 2130 2131 mReplyID = replyID; 2132 setState(STARTING); 2133 2134 mCodec->initiateStart(); 2135 break; 2136 } 2137 2138 case kWhatStop: 2139 case kWhatRelease: 2140 { 2141 State targetState = 2142 (msg->what() == kWhatStop) ? INITIALIZED : UNINITIALIZED; 2143 2144 sp<AReplyToken> replyID; 2145 CHECK(msg->senderAwaitsResponse(&replyID)); 2146 2147 // already stopped/released 2148 if (mState == UNINITIALIZED && mReleasedByResourceManager) { 2149 sp<AMessage> response = new AMessage; 2150 response->setInt32("err", OK); 2151 response->postReply(replyID); 2152 break; 2153 } 2154 2155 int32_t reclaimed = 0; 2156 msg->findInt32("reclaimed", &reclaimed); 2157 if (reclaimed) { 2158 mReleasedByResourceManager = true; 2159 2160 int32_t force = 0; 2161 msg->findInt32("force", &force); 2162 if (!force && hasPendingBuffer()) { 2163 ALOGW("Can't reclaim codec right now due to pending buffers."); 2164 2165 // return WOULD_BLOCK to ask resource manager to retry later. 2166 sp<AMessage> response = new AMessage; 2167 response->setInt32("err", WOULD_BLOCK); 2168 response->postReply(replyID); 2169 2170 // notify the async client 2171 if (mFlags & kFlagIsAsync) { 2172 onError(DEAD_OBJECT, ACTION_CODE_FATAL); 2173 } 2174 break; 2175 } 2176 } 2177 2178 bool isReleasingAllocatedComponent = 2179 (mFlags & kFlagIsComponentAllocated) && targetState == UNINITIALIZED; 2180 if (!isReleasingAllocatedComponent // See 1 2181 && mState != INITIALIZED 2182 && mState != CONFIGURED && !isExecuting()) { 2183 // 1) Permit release to shut down the component if allocated. 2184 // 2185 // 2) We may be in "UNINITIALIZED" state already and 2186 // also shutdown the encoder/decoder without the 2187 // client being aware of this if media server died while 2188 // we were being stopped. The client would assume that 2189 // after stop() returned, it would be safe to call release() 2190 // and it should be in this case, no harm to allow a release() 2191 // if we're already uninitialized. 2192 sp<AMessage> response = new AMessage; 2193 // TODO: we shouldn't throw an exception for stop/release. Change this to wait until 2194 // the previous stop/release completes and then reply with OK. 2195 status_t err = mState == targetState ? OK : INVALID_OPERATION; 2196 response->setInt32("err", err); 2197 if (err == OK && targetState == UNINITIALIZED) { 2198 mComponentName.clear(); 2199 } 2200 response->postReply(replyID); 2201 break; 2202 } 2203 2204 // If we're flushing, or we're stopping but received a release 2205 // request, post the reply for the pending call first, and consider 2206 // it done. The reply token will be replaced after this, and we'll 2207 // no longer be able to reply. 2208 if (mState == FLUSHING || mState == STOPPING) { 2209 (new AMessage)->postReply(mReplyID); 2210 } 2211 2212 if (mFlags & kFlagSawMediaServerDie) { 2213 // It's dead, Jim. Don't expect initiateShutdown to yield 2214 // any useful results now... 2215 setState(UNINITIALIZED); 2216 if (targetState == UNINITIALIZED) { 2217 mComponentName.clear(); 2218 } 2219 (new AMessage)->postReply(replyID); 2220 break; 2221 } 2222 2223 // If we already have an error, component may not be able to 2224 // complete the shutdown properly. If we're stopping, post the 2225 // reply now with an error to unblock the client, client can 2226 // release after the failure (instead of ANR). 2227 if (msg->what() == kWhatStop && (mFlags & kFlagStickyError)) { 2228 PostReplyWithError(replyID, getStickyError()); 2229 break; 2230 } 2231 2232 mReplyID = replyID; 2233 setState(msg->what() == kWhatStop ? STOPPING : RELEASING); 2234 2235 mCodec->initiateShutdown( 2236 msg->what() == kWhatStop /* keepComponentAllocated */); 2237 2238 returnBuffersToCodec(reclaimed); 2239 2240 if (mSoftRenderer != NULL && (mFlags & kFlagPushBlankBuffersOnShutdown)) { 2241 pushBlankBuffersToNativeWindow(mSurface.get()); 2242 } 2243 2244 break; 2245 } 2246 2247 case kWhatDequeueInputBuffer: 2248 { 2249 sp<AReplyToken> replyID; 2250 CHECK(msg->senderAwaitsResponse(&replyID)); 2251 2252 if (mFlags & kFlagIsAsync) { 2253 ALOGE("dequeueOutputBuffer can't be used in async mode"); 2254 PostReplyWithError(replyID, INVALID_OPERATION); 2255 break; 2256 } 2257 2258 if (mHaveInputSurface) { 2259 ALOGE("dequeueInputBuffer can't be used with input surface"); 2260 PostReplyWithError(replyID, INVALID_OPERATION); 2261 break; 2262 } 2263 2264 if (handleDequeueInputBuffer(replyID, true /* new request */)) { 2265 break; 2266 } 2267 2268 int64_t timeoutUs; 2269 CHECK(msg->findInt64("timeoutUs", &timeoutUs)); 2270 2271 if (timeoutUs == 0ll) { 2272 PostReplyWithError(replyID, -EAGAIN); 2273 break; 2274 } 2275 2276 mFlags |= kFlagDequeueInputPending; 2277 mDequeueInputReplyID = replyID; 2278 2279 if (timeoutUs > 0ll) { 2280 sp<AMessage> timeoutMsg = 2281 new AMessage(kWhatDequeueInputTimedOut, this); 2282 timeoutMsg->setInt32( 2283 "generation", ++mDequeueInputTimeoutGeneration); 2284 timeoutMsg->post(timeoutUs); 2285 } 2286 break; 2287 } 2288 2289 case kWhatDequeueInputTimedOut: 2290 { 2291 int32_t generation; 2292 CHECK(msg->findInt32("generation", &generation)); 2293 2294 if (generation != mDequeueInputTimeoutGeneration) { 2295 // Obsolete 2296 break; 2297 } 2298 2299 CHECK(mFlags & kFlagDequeueInputPending); 2300 2301 PostReplyWithError(mDequeueInputReplyID, -EAGAIN); 2302 2303 mFlags &= ~kFlagDequeueInputPending; 2304 mDequeueInputReplyID = 0; 2305 break; 2306 } 2307 2308 case kWhatQueueInputBuffer: 2309 { 2310 sp<AReplyToken> replyID; 2311 CHECK(msg->senderAwaitsResponse(&replyID)); 2312 2313 if (!isExecuting()) { 2314 PostReplyWithError(replyID, INVALID_OPERATION); 2315 break; 2316 } else if (mFlags & kFlagStickyError) { 2317 PostReplyWithError(replyID, getStickyError()); 2318 break; 2319 } 2320 2321 status_t err = onQueueInputBuffer(msg); 2322 2323 PostReplyWithError(replyID, err); 2324 break; 2325 } 2326 2327 case kWhatDequeueOutputBuffer: 2328 { 2329 sp<AReplyToken> replyID; 2330 CHECK(msg->senderAwaitsResponse(&replyID)); 2331 2332 if (mFlags & kFlagIsAsync) { 2333 ALOGE("dequeueOutputBuffer can't be used in async mode"); 2334 PostReplyWithError(replyID, INVALID_OPERATION); 2335 break; 2336 } 2337 2338 if (handleDequeueOutputBuffer(replyID, true /* new request */)) { 2339 break; 2340 } 2341 2342 int64_t timeoutUs; 2343 CHECK(msg->findInt64("timeoutUs", &timeoutUs)); 2344 2345 if (timeoutUs == 0ll) { 2346 PostReplyWithError(replyID, -EAGAIN); 2347 break; 2348 } 2349 2350 mFlags |= kFlagDequeueOutputPending; 2351 mDequeueOutputReplyID = replyID; 2352 2353 if (timeoutUs > 0ll) { 2354 sp<AMessage> timeoutMsg = 2355 new AMessage(kWhatDequeueOutputTimedOut, this); 2356 timeoutMsg->setInt32( 2357 "generation", ++mDequeueOutputTimeoutGeneration); 2358 timeoutMsg->post(timeoutUs); 2359 } 2360 break; 2361 } 2362 2363 case kWhatDequeueOutputTimedOut: 2364 { 2365 int32_t generation; 2366 CHECK(msg->findInt32("generation", &generation)); 2367 2368 if (generation != mDequeueOutputTimeoutGeneration) { 2369 // Obsolete 2370 break; 2371 } 2372 2373 CHECK(mFlags & kFlagDequeueOutputPending); 2374 2375 PostReplyWithError(mDequeueOutputReplyID, -EAGAIN); 2376 2377 mFlags &= ~kFlagDequeueOutputPending; 2378 mDequeueOutputReplyID = 0; 2379 break; 2380 } 2381 2382 case kWhatReleaseOutputBuffer: 2383 { 2384 sp<AReplyToken> replyID; 2385 CHECK(msg->senderAwaitsResponse(&replyID)); 2386 2387 if (!isExecuting()) { 2388 PostReplyWithError(replyID, INVALID_OPERATION); 2389 break; 2390 } else if (mFlags & kFlagStickyError) { 2391 PostReplyWithError(replyID, getStickyError()); 2392 break; 2393 } 2394 2395 status_t err = onReleaseOutputBuffer(msg); 2396 2397 PostReplyWithError(replyID, err); 2398 break; 2399 } 2400 2401 case kWhatSignalEndOfInputStream: 2402 { 2403 sp<AReplyToken> replyID; 2404 CHECK(msg->senderAwaitsResponse(&replyID)); 2405 2406 if (!isExecuting() || !mHaveInputSurface) { 2407 PostReplyWithError(replyID, INVALID_OPERATION); 2408 break; 2409 } else if (mFlags & kFlagStickyError) { 2410 PostReplyWithError(replyID, getStickyError()); 2411 break; 2412 } 2413 2414 mReplyID = replyID; 2415 mCodec->signalEndOfInputStream(); 2416 break; 2417 } 2418 2419 case kWhatGetBuffers: 2420 { 2421 sp<AReplyToken> replyID; 2422 CHECK(msg->senderAwaitsResponse(&replyID)); 2423 if (!isExecuting() || (mFlags & kFlagIsAsync)) { 2424 PostReplyWithError(replyID, INVALID_OPERATION); 2425 break; 2426 } else if (mFlags & kFlagStickyError) { 2427 PostReplyWithError(replyID, getStickyError()); 2428 break; 2429 } 2430 2431 int32_t portIndex; 2432 CHECK(msg->findInt32("portIndex", &portIndex)); 2433 2434 Vector<sp<MediaCodecBuffer> > *dstBuffers; 2435 CHECK(msg->findPointer("buffers", (void **)&dstBuffers)); 2436 2437 dstBuffers->clear(); 2438 // If we're using input surface (either non-persistent created by 2439 // createInputSurface(), or persistent set by setInputSurface()), 2440 // give the client an empty input buffers array. 2441 if (portIndex != kPortIndexInput || !mHaveInputSurface) { 2442 if (portIndex == kPortIndexInput) { 2443 mBufferChannel->getInputBufferArray(dstBuffers); 2444 } else { 2445 mBufferChannel->getOutputBufferArray(dstBuffers); 2446 } 2447 } 2448 2449 (new AMessage)->postReply(replyID); 2450 break; 2451 } 2452 2453 case kWhatFlush: 2454 { 2455 sp<AReplyToken> replyID; 2456 CHECK(msg->senderAwaitsResponse(&replyID)); 2457 2458 if (!isExecuting()) { 2459 PostReplyWithError(replyID, INVALID_OPERATION); 2460 break; 2461 } else if (mFlags & kFlagStickyError) { 2462 PostReplyWithError(replyID, getStickyError()); 2463 break; 2464 } 2465 2466 mReplyID = replyID; 2467 // TODO: skip flushing if already FLUSHED 2468 setState(FLUSHING); 2469 2470 mCodec->signalFlush(); 2471 returnBuffersToCodec(); 2472 break; 2473 } 2474 2475 case kWhatGetInputFormat: 2476 case kWhatGetOutputFormat: 2477 { 2478 sp<AMessage> format = 2479 (msg->what() == kWhatGetOutputFormat ? mOutputFormat : mInputFormat); 2480 2481 sp<AReplyToken> replyID; 2482 CHECK(msg->senderAwaitsResponse(&replyID)); 2483 2484 if ((mState != CONFIGURED && mState != STARTING && 2485 mState != STARTED && mState != FLUSHING && 2486 mState != FLUSHED) 2487 || format == NULL) { 2488 PostReplyWithError(replyID, INVALID_OPERATION); 2489 break; 2490 } else if (mFlags & kFlagStickyError) { 2491 PostReplyWithError(replyID, getStickyError()); 2492 break; 2493 } 2494 2495 sp<AMessage> response = new AMessage; 2496 response->setMessage("format", format); 2497 response->postReply(replyID); 2498 break; 2499 } 2500 2501 case kWhatRequestIDRFrame: 2502 { 2503 mCodec->signalRequestIDRFrame(); 2504 break; 2505 } 2506 2507 case kWhatRequestActivityNotification: 2508 { 2509 CHECK(mActivityNotify == NULL); 2510 CHECK(msg->findMessage("notify", &mActivityNotify)); 2511 2512 postActivityNotificationIfPossible(); 2513 break; 2514 } 2515 2516 case kWhatGetName: 2517 { 2518 sp<AReplyToken> replyID; 2519 CHECK(msg->senderAwaitsResponse(&replyID)); 2520 2521 if (mComponentName.empty()) { 2522 PostReplyWithError(replyID, INVALID_OPERATION); 2523 break; 2524 } 2525 2526 sp<AMessage> response = new AMessage; 2527 response->setString("name", mComponentName.c_str()); 2528 response->postReply(replyID); 2529 break; 2530 } 2531 2532 case kWhatSetParameters: 2533 { 2534 sp<AReplyToken> replyID; 2535 CHECK(msg->senderAwaitsResponse(&replyID)); 2536 2537 sp<AMessage> params; 2538 CHECK(msg->findMessage("params", ¶ms)); 2539 2540 status_t err = onSetParameters(params); 2541 2542 PostReplyWithError(replyID, err); 2543 break; 2544 } 2545 2546 case kWhatDrmReleaseCrypto: 2547 { 2548 onReleaseCrypto(msg); 2549 break; 2550 } 2551 2552 default: 2553 TRESPASS(); 2554 } 2555} 2556 2557void MediaCodec::extractCSD(const sp<AMessage> &format) { 2558 mCSD.clear(); 2559 2560 size_t i = 0; 2561 for (;;) { 2562 sp<ABuffer> csd; 2563 if (!format->findBuffer(AStringPrintf("csd-%u", i).c_str(), &csd)) { 2564 break; 2565 } 2566 if (csd->size() == 0) { 2567 ALOGW("csd-%zu size is 0", i); 2568 } 2569 2570 mCSD.push_back(csd); 2571 ++i; 2572 } 2573 2574 ALOGV("Found %zu pieces of codec specific data.", mCSD.size()); 2575} 2576 2577status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) { 2578 CHECK(!mCSD.empty()); 2579 2580 const BufferInfo &info = mPortBuffers[kPortIndexInput][bufferIndex]; 2581 2582 sp<ABuffer> csd = *mCSD.begin(); 2583 mCSD.erase(mCSD.begin()); 2584 2585 const sp<MediaCodecBuffer> &codecInputData = info.mData; 2586 2587 if (csd->size() > codecInputData->capacity()) { 2588 return -EINVAL; 2589 } 2590 2591 memcpy(codecInputData->data(), csd->data(), csd->size()); 2592 2593 AString errorDetailMsg; 2594 2595 sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this); 2596 msg->setSize("index", bufferIndex); 2597 msg->setSize("offset", 0); 2598 msg->setSize("size", csd->size()); 2599 msg->setInt64("timeUs", 0ll); 2600 msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG); 2601 msg->setPointer("errorDetailMsg", &errorDetailMsg); 2602 2603 return onQueueInputBuffer(msg); 2604} 2605 2606void MediaCodec::setState(State newState) { 2607 if (newState == INITIALIZED || newState == UNINITIALIZED) { 2608 delete mSoftRenderer; 2609 mSoftRenderer = NULL; 2610 2611 if ( mCrypto != NULL ) { 2612 ALOGV("setState: ~mCrypto: %p (%d)", 2613 mCrypto.get(), (mCrypto != NULL ? mCrypto->getStrongCount() : 0)); 2614 } 2615 mCrypto.clear(); 2616 mDescrambler.clear(); 2617 handleSetSurface(NULL); 2618 2619 mInputFormat.clear(); 2620 mOutputFormat.clear(); 2621 mFlags &= ~kFlagOutputFormatChanged; 2622 mFlags &= ~kFlagOutputBuffersChanged; 2623 mFlags &= ~kFlagStickyError; 2624 mFlags &= ~kFlagIsEncoder; 2625 mFlags &= ~kFlagIsAsync; 2626 mStickyError = OK; 2627 2628 mActivityNotify.clear(); 2629 mCallback.clear(); 2630 } 2631 2632 if (newState == UNINITIALIZED) { 2633 // return any straggling buffers, e.g. if we got here on an error 2634 returnBuffersToCodec(); 2635 2636 // The component is gone, mediaserver's probably back up already 2637 // but should definitely be back up should we try to instantiate 2638 // another component.. and the cycle continues. 2639 mFlags &= ~kFlagSawMediaServerDie; 2640 } 2641 2642 mState = newState; 2643 2644 cancelPendingDequeueOperations(); 2645 2646 updateBatteryStat(); 2647} 2648 2649void MediaCodec::returnBuffersToCodec(bool isReclaim) { 2650 returnBuffersToCodecOnPort(kPortIndexInput, isReclaim); 2651 returnBuffersToCodecOnPort(kPortIndexOutput, isReclaim); 2652} 2653 2654void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex, bool isReclaim) { 2655 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 2656 Mutex::Autolock al(mBufferLock); 2657 2658 for (size_t i = 0; i < mPortBuffers[portIndex].size(); ++i) { 2659 BufferInfo *info = &mPortBuffers[portIndex][i]; 2660 2661 if (info->mData != nullptr) { 2662 sp<MediaCodecBuffer> buffer = info->mData; 2663 if (isReclaim && info->mOwnedByClient) { 2664 ALOGD("port %d buffer %zu still owned by client when codec is reclaimed", 2665 portIndex, i); 2666 } else { 2667 info->mOwnedByClient = false; 2668 info->mData.clear(); 2669 } 2670 mBufferChannel->discardBuffer(buffer); 2671 } 2672 } 2673 2674 mAvailPortBuffers[portIndex].clear(); 2675} 2676 2677size_t MediaCodec::updateBuffers( 2678 int32_t portIndex, const sp<AMessage> &msg) { 2679 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 2680 size_t index; 2681 CHECK(msg->findSize("index", &index)); 2682 sp<RefBase> obj; 2683 CHECK(msg->findObject("buffer", &obj)); 2684 sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get()); 2685 2686 { 2687 Mutex::Autolock al(mBufferLock); 2688 if (mPortBuffers[portIndex].size() <= index) { 2689 mPortBuffers[portIndex].resize(align(index + 1, kNumBuffersAlign)); 2690 } 2691 mPortBuffers[portIndex][index].mData = buffer; 2692 } 2693 mAvailPortBuffers[portIndex].push_back(index); 2694 2695 return index; 2696} 2697 2698status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) { 2699 size_t index; 2700 size_t offset; 2701 size_t size; 2702 int64_t timeUs; 2703 uint32_t flags; 2704 CHECK(msg->findSize("index", &index)); 2705 CHECK(msg->findSize("offset", &offset)); 2706 CHECK(msg->findInt64("timeUs", &timeUs)); 2707 CHECK(msg->findInt32("flags", (int32_t *)&flags)); 2708 2709 const CryptoPlugin::SubSample *subSamples; 2710 size_t numSubSamples; 2711 const uint8_t *key; 2712 const uint8_t *iv; 2713 CryptoPlugin::Mode mode = CryptoPlugin::kMode_Unencrypted; 2714 2715 // We allow the simpler queueInputBuffer API to be used even in 2716 // secure mode, by fabricating a single unencrypted subSample. 2717 CryptoPlugin::SubSample ss; 2718 CryptoPlugin::Pattern pattern; 2719 2720 if (msg->findSize("size", &size)) { 2721 if (hasCryptoOrDescrambler()) { 2722 ss.mNumBytesOfClearData = size; 2723 ss.mNumBytesOfEncryptedData = 0; 2724 2725 subSamples = &ss; 2726 numSubSamples = 1; 2727 key = NULL; 2728 iv = NULL; 2729 pattern.mEncryptBlocks = 0; 2730 pattern.mSkipBlocks = 0; 2731 } 2732 } else { 2733 if (!hasCryptoOrDescrambler()) { 2734 ALOGE("[%s] queuing secure buffer without mCrypto or mDescrambler!", 2735 mComponentName.c_str()); 2736 return -EINVAL; 2737 } 2738 2739 CHECK(msg->findPointer("subSamples", (void **)&subSamples)); 2740 CHECK(msg->findSize("numSubSamples", &numSubSamples)); 2741 CHECK(msg->findPointer("key", (void **)&key)); 2742 CHECK(msg->findPointer("iv", (void **)&iv)); 2743 CHECK(msg->findInt32("encryptBlocks", (int32_t *)&pattern.mEncryptBlocks)); 2744 CHECK(msg->findInt32("skipBlocks", (int32_t *)&pattern.mSkipBlocks)); 2745 2746 int32_t tmp; 2747 CHECK(msg->findInt32("mode", &tmp)); 2748 2749 mode = (CryptoPlugin::Mode)tmp; 2750 2751 size = 0; 2752 for (size_t i = 0; i < numSubSamples; ++i) { 2753 size += subSamples[i].mNumBytesOfClearData; 2754 size += subSamples[i].mNumBytesOfEncryptedData; 2755 } 2756 } 2757 2758 if (index >= mPortBuffers[kPortIndexInput].size()) { 2759 return -ERANGE; 2760 } 2761 2762 BufferInfo *info = &mPortBuffers[kPortIndexInput][index]; 2763 2764 if (info->mData == nullptr || !info->mOwnedByClient) { 2765 return -EACCES; 2766 } 2767 2768 if (offset + size > info->mData->capacity()) { 2769 return -EINVAL; 2770 } 2771 2772 info->mData->setRange(offset, size); 2773 info->mData->meta()->setInt64("timeUs", timeUs); 2774 if (flags & BUFFER_FLAG_EOS) { 2775 info->mData->meta()->setInt32("eos", true); 2776 } 2777 2778 if (flags & BUFFER_FLAG_CODECCONFIG) { 2779 info->mData->meta()->setInt32("csd", true); 2780 } 2781 2782 sp<MediaCodecBuffer> buffer = info->mData; 2783 status_t err = OK; 2784 if (hasCryptoOrDescrambler()) { 2785 AString *errorDetailMsg; 2786 CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg)); 2787 2788 err = mBufferChannel->queueSecureInputBuffer( 2789 buffer, 2790 (mFlags & kFlagIsSecure), 2791 key, 2792 iv, 2793 mode, 2794 pattern, 2795 subSamples, 2796 numSubSamples, 2797 errorDetailMsg); 2798 } else { 2799 err = mBufferChannel->queueInputBuffer(buffer); 2800 } 2801 2802 if (err == OK) { 2803 // synchronization boundary for getBufferAndFormat 2804 Mutex::Autolock al(mBufferLock); 2805 info->mOwnedByClient = false; 2806 info->mData.clear(); 2807 } 2808 2809 return err; 2810} 2811 2812//static 2813size_t MediaCodec::CreateFramesRenderedMessage( 2814 const std::list<FrameRenderTracker::Info> &done, sp<AMessage> &msg) { 2815 size_t index = 0; 2816 2817 for (std::list<FrameRenderTracker::Info>::const_iterator it = done.cbegin(); 2818 it != done.cend(); ++it) { 2819 if (it->getRenderTimeNs() < 0) { 2820 continue; // dropped frame from tracking 2821 } 2822 msg->setInt64(AStringPrintf("%zu-media-time-us", index).c_str(), it->getMediaTimeUs()); 2823 msg->setInt64(AStringPrintf("%zu-system-nano", index).c_str(), it->getRenderTimeNs()); 2824 ++index; 2825 } 2826 return index; 2827} 2828 2829status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) { 2830 size_t index; 2831 CHECK(msg->findSize("index", &index)); 2832 2833 int32_t render; 2834 if (!msg->findInt32("render", &render)) { 2835 render = 0; 2836 } 2837 2838 if (!isExecuting()) { 2839 return -EINVAL; 2840 } 2841 2842 if (index >= mPortBuffers[kPortIndexOutput].size()) { 2843 return -ERANGE; 2844 } 2845 2846 BufferInfo *info = &mPortBuffers[kPortIndexOutput][index]; 2847 2848 if (info->mData == nullptr || !info->mOwnedByClient) { 2849 return -EACCES; 2850 } 2851 2852 // synchronization boundary for getBufferAndFormat 2853 sp<MediaCodecBuffer> buffer; 2854 { 2855 Mutex::Autolock al(mBufferLock); 2856 info->mOwnedByClient = false; 2857 buffer = info->mData; 2858 info->mData.clear(); 2859 } 2860 2861 if (render && buffer->size() != 0) { 2862 int64_t mediaTimeUs = -1; 2863 buffer->meta()->findInt64("timeUs", &mediaTimeUs); 2864 2865 int64_t renderTimeNs = 0; 2866 if (!msg->findInt64("timestampNs", &renderTimeNs)) { 2867 // use media timestamp if client did not request a specific render timestamp 2868 ALOGV("using buffer PTS of %lld", (long long)mediaTimeUs); 2869 renderTimeNs = mediaTimeUs * 1000; 2870 } 2871 2872 if (mSoftRenderer != NULL) { 2873 std::list<FrameRenderTracker::Info> doneFrames = mSoftRenderer->render( 2874 buffer->data(), buffer->size(), 2875 mediaTimeUs, renderTimeNs, NULL, buffer->format()); 2876 2877 // if we are running, notify rendered frames 2878 if (!doneFrames.empty() && mState == STARTED && mOnFrameRenderedNotification != NULL) { 2879 sp<AMessage> notify = mOnFrameRenderedNotification->dup(); 2880 sp<AMessage> data = new AMessage; 2881 if (CreateFramesRenderedMessage(doneFrames, data)) { 2882 notify->setMessage("data", data); 2883 notify->post(); 2884 } 2885 } 2886 } 2887 mBufferChannel->renderOutputBuffer(buffer, renderTimeNs); 2888 } else { 2889 mBufferChannel->discardBuffer(buffer); 2890 } 2891 2892 return OK; 2893} 2894 2895ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) { 2896 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 2897 2898 List<size_t> *availBuffers = &mAvailPortBuffers[portIndex]; 2899 2900 if (availBuffers->empty()) { 2901 return -EAGAIN; 2902 } 2903 2904 size_t index = *availBuffers->begin(); 2905 availBuffers->erase(availBuffers->begin()); 2906 2907 BufferInfo *info = &mPortBuffers[portIndex][index]; 2908 CHECK(!info->mOwnedByClient); 2909 { 2910 Mutex::Autolock al(mBufferLock); 2911 info->mOwnedByClient = true; 2912 2913 // set image-data 2914 if (info->mData->format() != NULL) { 2915 sp<ABuffer> imageData; 2916 if (info->mData->format()->findBuffer("image-data", &imageData)) { 2917 info->mData->meta()->setBuffer("image-data", imageData); 2918 } 2919 int32_t left, top, right, bottom; 2920 if (info->mData->format()->findRect("crop", &left, &top, &right, &bottom)) { 2921 info->mData->meta()->setRect("crop-rect", left, top, right, bottom); 2922 } 2923 } 2924 } 2925 2926 return index; 2927} 2928 2929status_t MediaCodec::connectToSurface(const sp<Surface> &surface) { 2930 status_t err = OK; 2931 if (surface != NULL) { 2932 uint64_t oldId, newId; 2933 if (mSurface != NULL 2934 && surface->getUniqueId(&newId) == NO_ERROR 2935 && mSurface->getUniqueId(&oldId) == NO_ERROR 2936 && newId == oldId) { 2937 ALOGI("[%s] connecting to the same surface. Nothing to do.", mComponentName.c_str()); 2938 return ALREADY_EXISTS; 2939 } 2940 2941 err = nativeWindowConnect(surface.get(), "connectToSurface"); 2942 if (err == OK) { 2943 // Require a fresh set of buffers after each connect by using a unique generation 2944 // number. Rely on the fact that max supported process id by Linux is 2^22. 2945 // PID is never 0 so we don't have to worry that we use the default generation of 0. 2946 // TODO: come up with a unique scheme if other producers also set the generation number. 2947 static uint32_t mSurfaceGeneration = 0; 2948 uint32_t generation = (getpid() << 10) | (++mSurfaceGeneration & ((1 << 10) - 1)); 2949 surface->setGenerationNumber(generation); 2950 ALOGI("[%s] setting surface generation to %u", mComponentName.c_str(), generation); 2951 2952 // HACK: clear any free buffers. Remove when connect will automatically do this. 2953 // This is needed as the consumer may be holding onto stale frames that it can reattach 2954 // to this surface after disconnect/connect, and those free frames would inherit the new 2955 // generation number. Disconnecting after setting a unique generation prevents this. 2956 nativeWindowDisconnect(surface.get(), "connectToSurface(reconnect)"); 2957 err = nativeWindowConnect(surface.get(), "connectToSurface(reconnect)"); 2958 } 2959 2960 if (err != OK) { 2961 ALOGE("nativeWindowConnect returned an error: %s (%d)", strerror(-err), err); 2962 } 2963 } 2964 // do not return ALREADY_EXISTS unless surfaces are the same 2965 return err == ALREADY_EXISTS ? BAD_VALUE : err; 2966} 2967 2968status_t MediaCodec::disconnectFromSurface() { 2969 status_t err = OK; 2970 if (mSurface != NULL) { 2971 // Resetting generation is not technically needed, but there is no need to keep it either 2972 mSurface->setGenerationNumber(0); 2973 err = nativeWindowDisconnect(mSurface.get(), "disconnectFromSurface"); 2974 if (err != OK) { 2975 ALOGW("nativeWindowDisconnect returned an error: %s (%d)", strerror(-err), err); 2976 } 2977 // assume disconnected even on error 2978 mSurface.clear(); 2979 } 2980 return err; 2981} 2982 2983status_t MediaCodec::handleSetSurface(const sp<Surface> &surface) { 2984 status_t err = OK; 2985 if (mSurface != NULL) { 2986 (void)disconnectFromSurface(); 2987 } 2988 if (surface != NULL) { 2989 err = connectToSurface(surface); 2990 if (err == OK) { 2991 mSurface = surface; 2992 } 2993 } 2994 return err; 2995} 2996 2997void MediaCodec::onInputBufferAvailable() { 2998 int32_t index; 2999 while ((index = dequeuePortBuffer(kPortIndexInput)) >= 0) { 3000 sp<AMessage> msg = mCallback->dup(); 3001 msg->setInt32("callbackID", CB_INPUT_AVAILABLE); 3002 msg->setInt32("index", index); 3003 msg->post(); 3004 } 3005} 3006 3007void MediaCodec::onOutputBufferAvailable() { 3008 int32_t index; 3009 while ((index = dequeuePortBuffer(kPortIndexOutput)) >= 0) { 3010 const sp<MediaCodecBuffer> &buffer = 3011 mPortBuffers[kPortIndexOutput][index].mData; 3012 sp<AMessage> msg = mCallback->dup(); 3013 msg->setInt32("callbackID", CB_OUTPUT_AVAILABLE); 3014 msg->setInt32("index", index); 3015 msg->setSize("offset", buffer->offset()); 3016 msg->setSize("size", buffer->size()); 3017 3018 int64_t timeUs; 3019 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 3020 3021 msg->setInt64("timeUs", timeUs); 3022 3023 int32_t flags; 3024 CHECK(buffer->meta()->findInt32("flags", &flags)); 3025 3026 msg->setInt32("flags", flags); 3027 3028 msg->post(); 3029 } 3030} 3031 3032void MediaCodec::onError(status_t err, int32_t actionCode, const char *detail) { 3033 if (mCallback != NULL) { 3034 sp<AMessage> msg = mCallback->dup(); 3035 msg->setInt32("callbackID", CB_ERROR); 3036 msg->setInt32("err", err); 3037 msg->setInt32("actionCode", actionCode); 3038 3039 if (detail != NULL) { 3040 msg->setString("detail", detail); 3041 } 3042 3043 msg->post(); 3044 } 3045} 3046 3047void MediaCodec::onOutputFormatChanged() { 3048 if (mCallback != NULL) { 3049 sp<AMessage> msg = mCallback->dup(); 3050 msg->setInt32("callbackID", CB_OUTPUT_FORMAT_CHANGED); 3051 msg->setMessage("format", mOutputFormat); 3052 msg->post(); 3053 } 3054} 3055 3056void MediaCodec::postActivityNotificationIfPossible() { 3057 if (mActivityNotify == NULL) { 3058 return; 3059 } 3060 3061 bool isErrorOrOutputChanged = 3062 (mFlags & (kFlagStickyError 3063 | kFlagOutputBuffersChanged 3064 | kFlagOutputFormatChanged)); 3065 3066 if (isErrorOrOutputChanged 3067 || !mAvailPortBuffers[kPortIndexInput].empty() 3068 || !mAvailPortBuffers[kPortIndexOutput].empty()) { 3069 mActivityNotify->setInt32("input-buffers", 3070 mAvailPortBuffers[kPortIndexInput].size()); 3071 3072 if (isErrorOrOutputChanged) { 3073 // we want consumer to dequeue as many times as it can 3074 mActivityNotify->setInt32("output-buffers", INT32_MAX); 3075 } else { 3076 mActivityNotify->setInt32("output-buffers", 3077 mAvailPortBuffers[kPortIndexOutput].size()); 3078 } 3079 mActivityNotify->post(); 3080 mActivityNotify.clear(); 3081 } 3082} 3083 3084status_t MediaCodec::setParameters(const sp<AMessage> ¶ms) { 3085 sp<AMessage> msg = new AMessage(kWhatSetParameters, this); 3086 msg->setMessage("params", params); 3087 3088 sp<AMessage> response; 3089 return PostAndAwaitResponse(msg, &response); 3090} 3091 3092status_t MediaCodec::onSetParameters(const sp<AMessage> ¶ms) { 3093 mCodec->signalSetParameters(params); 3094 3095 return OK; 3096} 3097 3098status_t MediaCodec::amendOutputFormatWithCodecSpecificData( 3099 const sp<MediaCodecBuffer> &buffer) { 3100 AString mime; 3101 CHECK(mOutputFormat->findString("mime", &mime)); 3102 3103 if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) { 3104 // Codec specific data should be SPS and PPS in a single buffer, 3105 // each prefixed by a startcode (0x00 0x00 0x00 0x01). 3106 // We separate the two and put them into the output format 3107 // under the keys "csd-0" and "csd-1". 3108 3109 unsigned csdIndex = 0; 3110 3111 const uint8_t *data = buffer->data(); 3112 size_t size = buffer->size(); 3113 3114 const uint8_t *nalStart; 3115 size_t nalSize; 3116 while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) { 3117 sp<ABuffer> csd = new ABuffer(nalSize + 4); 3118 memcpy(csd->data(), "\x00\x00\x00\x01", 4); 3119 memcpy(csd->data() + 4, nalStart, nalSize); 3120 3121 mOutputFormat->setBuffer( 3122 AStringPrintf("csd-%u", csdIndex).c_str(), csd); 3123 3124 ++csdIndex; 3125 } 3126 3127 if (csdIndex != 2) { 3128 return ERROR_MALFORMED; 3129 } 3130 } else { 3131 // For everything else we just stash the codec specific data into 3132 // the output format as a single piece of csd under "csd-0". 3133 sp<ABuffer> csd = new ABuffer(buffer->size()); 3134 memcpy(csd->data(), buffer->data(), buffer->size()); 3135 csd->setRange(0, buffer->size()); 3136 mOutputFormat->setBuffer("csd-0", csd); 3137 } 3138 3139 return OK; 3140} 3141 3142void MediaCodec::updateBatteryStat() { 3143 if (!mIsVideo) { 3144 return; 3145 } 3146 3147 if (mState == CONFIGURED && !mBatteryStatNotified) { 3148 BatteryNotifier::getInstance().noteStartVideo(mUid); 3149 mBatteryStatNotified = true; 3150 } else if (mState == UNINITIALIZED && mBatteryStatNotified) { 3151 BatteryNotifier::getInstance().noteStopVideo(mUid); 3152 mBatteryStatNotified = false; 3153 } 3154} 3155 3156} // namespace android 3157