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> &notify);
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> &notify)
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> &notify);
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> &notify) : 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> &notify) {
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> &notify) {
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", &notify)) {
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", &params));
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> &params) {
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> &params) {
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