• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2012, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "MediaCodec"
19 #include <inttypes.h>
20 
21 #include "include/avc_utils.h"
22 #include "include/SecureBuffer.h"
23 #include "include/SharedMemoryBuffer.h"
24 #include "include/SoftwareRenderer.h"
25 
26 #include <android/hardware/cas/native/1.0/IDescrambler.h>
27 
28 #include <binder/IMemory.h>
29 #include <binder/IPCThreadState.h>
30 #include <binder/IServiceManager.h>
31 #include <binder/MemoryDealer.h>
32 #include <gui/BufferQueue.h>
33 #include <gui/Surface.h>
34 #include <media/ICrypto.h>
35 #include <media/IOMX.h>
36 #include <media/IResourceManagerService.h>
37 #include <media/MediaCodecBuffer.h>
38 #include <media/MediaAnalyticsItem.h>
39 #include <media/stagefright/foundation/ABuffer.h>
40 #include <media/stagefright/foundation/ADebug.h>
41 #include <media/stagefright/foundation/AMessage.h>
42 #include <media/stagefright/foundation/AString.h>
43 #include <media/stagefright/foundation/AUtils.h>
44 #include <media/stagefright/foundation/hexdump.h>
45 #include <media/stagefright/ACodec.h>
46 #include <media/stagefright/BufferProducerWrapper.h>
47 #include <media/stagefright/MediaCodec.h>
48 #include <media/stagefright/MediaCodecList.h>
49 #include <media/stagefright/MediaDefs.h>
50 #include <media/stagefright/MediaErrors.h>
51 #include <media/stagefright/MediaFilter.h>
52 #include <media/stagefright/MetaData.h>
53 #include <media/stagefright/OMXClient.h>
54 #include <media/stagefright/PersistentSurface.h>
55 #include <media/stagefright/SurfaceUtils.h>
56 #include <mediautils/BatteryNotifier.h>
57 #include <private/android_filesystem_config.h>
58 #include <utils/Log.h>
59 #include <utils/Singleton.h>
60 
61 namespace android {
62 
63 // key for media statistics
64 static const char *kCodecKeyName = "codec";
65 // attrs for media statistics
66 static const char *kCodecCodec = "android.media.mediacodec.codec";  /* e.g. OMX.google.aac.decoder */
67 static const char *kCodecMime = "android.media.mediacodec.mime";    /* e.g. audio/mime */
68 static const char *kCodecMode = "android.media.mediacodec.mode";    /* audio, video */
69 static const char *kCodecSecure = "android.media.mediacodec.secure";   /* 0, 1 */
70 static const char *kCodecHeight = "android.media.mediacodec.height";   /* 0..n */
71 static const char *kCodecWidth = "android.media.mediacodec.width";     /* 0..n */
72 static const char *kCodecRotation = "android.media.mediacodec.rotation-degrees";  /* 0/90/180/270 */
73 static const char *kCodecCrypto = "android.media.mediacodec.crypto";   /* 0,1 */
74 static const char *kCodecEncoder = "android.media.mediacodec.encoder"; /* 0,1 */
75 
76 static const char *kCodecBytesIn = "android.media.mediacodec.bytesin";  /* 0..n */
77 static const char *kCodecProfile = "android.media.mediacodec.profile";  /* 0..n */
78 static const char *kCodecLevel = "android.media.mediacodec.level";  /* 0..n */
79 static const char *kCodecMaxWidth = "android.media.mediacodec.maxwidth";  /* 0..n */
80 static const char *kCodecMaxHeight = "android.media.mediacodec.maxheight";  /* 0..n */
81 static const char *kCodecError = "android.media.mediacodec.errcode";
82 static const char *kCodecErrorState = "android.media.mediacodec.errstate";
83 
84 
getId(const sp<IResourceManagerClient> & client)85 static int64_t getId(const sp<IResourceManagerClient> &client) {
86     return (int64_t) client.get();
87 }
88 
isResourceError(status_t err)89 static bool isResourceError(status_t err) {
90     return (err == NO_MEMORY);
91 }
92 
93 static const int kMaxRetry = 2;
94 static const int kMaxReclaimWaitTimeInUs = 500000;  // 0.5s
95 static const int kNumBuffersAlign = 16;
96 
97 ////////////////////////////////////////////////////////////////////////////////
98 
99 struct ResourceManagerClient : public BnResourceManagerClient {
ResourceManagerClientandroid::ResourceManagerClient100     explicit ResourceManagerClient(MediaCodec* codec) : mMediaCodec(codec) {}
101 
reclaimResourceandroid::ResourceManagerClient102     virtual bool reclaimResource() {
103         sp<MediaCodec> codec = mMediaCodec.promote();
104         if (codec == NULL) {
105             // codec is already gone.
106             return true;
107         }
108         status_t err = codec->reclaim();
109         if (err == WOULD_BLOCK) {
110             ALOGD("Wait for the client to release codec.");
111             usleep(kMaxReclaimWaitTimeInUs);
112             ALOGD("Try to reclaim again.");
113             err = codec->reclaim(true /* force */);
114         }
115         if (err != OK) {
116             ALOGW("ResourceManagerClient failed to release codec with err %d", err);
117         }
118         return (err == OK);
119     }
120 
getNameandroid::ResourceManagerClient121     virtual String8 getName() {
122         String8 ret;
123         sp<MediaCodec> codec = mMediaCodec.promote();
124         if (codec == NULL) {
125             // codec is already gone.
126             return ret;
127         }
128 
129         AString name;
130         if (codec->getName(&name) == OK) {
131             ret.setTo(name.c_str());
132         }
133         return ret;
134     }
135 
136 protected:
~ResourceManagerClientandroid::ResourceManagerClient137     virtual ~ResourceManagerClient() {}
138 
139 private:
140     wp<MediaCodec> mMediaCodec;
141 
142     DISALLOW_EVIL_CONSTRUCTORS(ResourceManagerClient);
143 };
144 
ResourceManagerServiceProxy(pid_t pid)145 MediaCodec::ResourceManagerServiceProxy::ResourceManagerServiceProxy(pid_t pid)
146         : mPid(pid) {
147     if (mPid == MediaCodec::kNoPid) {
148         mPid = IPCThreadState::self()->getCallingPid();
149     }
150 }
151 
~ResourceManagerServiceProxy()152 MediaCodec::ResourceManagerServiceProxy::~ResourceManagerServiceProxy() {
153     if (mService != NULL) {
154         IInterface::asBinder(mService)->unlinkToDeath(this);
155     }
156 }
157 
init()158 void MediaCodec::ResourceManagerServiceProxy::init() {
159     sp<IServiceManager> sm = defaultServiceManager();
160     sp<IBinder> binder = sm->getService(String16("media.resource_manager"));
161     mService = interface_cast<IResourceManagerService>(binder);
162     if (mService == NULL) {
163         ALOGE("Failed to get ResourceManagerService");
164         return;
165     }
166     IInterface::asBinder(mService)->linkToDeath(this);
167 }
168 
binderDied(const wp<IBinder> &)169 void MediaCodec::ResourceManagerServiceProxy::binderDied(const wp<IBinder>& /*who*/) {
170     ALOGW("ResourceManagerService died.");
171     Mutex::Autolock _l(mLock);
172     mService.clear();
173 }
174 
addResource(int64_t clientId,const sp<IResourceManagerClient> & client,const Vector<MediaResource> & resources)175 void MediaCodec::ResourceManagerServiceProxy::addResource(
176         int64_t clientId,
177         const sp<IResourceManagerClient> &client,
178         const Vector<MediaResource> &resources) {
179     Mutex::Autolock _l(mLock);
180     if (mService == NULL) {
181         return;
182     }
183     mService->addResource(mPid, clientId, client, resources);
184 }
185 
removeResource(int64_t clientId)186 void MediaCodec::ResourceManagerServiceProxy::removeResource(int64_t clientId) {
187     Mutex::Autolock _l(mLock);
188     if (mService == NULL) {
189         return;
190     }
191     mService->removeResource(mPid, clientId);
192 }
193 
reclaimResource(const Vector<MediaResource> & resources)194 bool MediaCodec::ResourceManagerServiceProxy::reclaimResource(
195         const Vector<MediaResource> &resources) {
196     Mutex::Autolock _l(mLock);
197     if (mService == NULL) {
198         return false;
199     }
200     return mService->reclaimResource(mPid, resources);
201 }
202 
203 ////////////////////////////////////////////////////////////////////////////////
204 
BufferInfo()205 MediaCodec::BufferInfo::BufferInfo() : mOwnedByClient(false) {}
206 
207 ////////////////////////////////////////////////////////////////////////////////
208 
209 namespace {
210 
211 enum {
212     kWhatFillThisBuffer      = 'fill',
213     kWhatDrainThisBuffer     = 'drai',
214     kWhatEOS                 = 'eos ',
215     kWhatStartCompleted      = 'Scom',
216     kWhatStopCompleted       = 'scom',
217     kWhatReleaseCompleted    = 'rcom',
218     kWhatFlushCompleted      = 'fcom',
219     kWhatError               = 'erro',
220     kWhatComponentAllocated  = 'cAll',
221     kWhatComponentConfigured = 'cCon',
222     kWhatInputSurfaceCreated = 'isfc',
223     kWhatInputSurfaceAccepted = 'isfa',
224     kWhatSignaledInputEOS    = 'seos',
225     kWhatOutputFramesRendered = 'outR',
226     kWhatOutputBuffersChanged = 'outC',
227 };
228 
229 class BufferCallback : public CodecBase::BufferCallback {
230 public:
231     explicit BufferCallback(const sp<AMessage> &notify);
232     virtual ~BufferCallback() = default;
233 
234     virtual void onInputBufferAvailable(
235             size_t index, const sp<MediaCodecBuffer> &buffer) override;
236     virtual void onOutputBufferAvailable(
237             size_t index, const sp<MediaCodecBuffer> &buffer) override;
238 private:
239     const sp<AMessage> mNotify;
240 };
241 
BufferCallback(const sp<AMessage> & notify)242 BufferCallback::BufferCallback(const sp<AMessage> &notify)
243     : mNotify(notify) {}
244 
onInputBufferAvailable(size_t index,const sp<MediaCodecBuffer> & buffer)245 void BufferCallback::onInputBufferAvailable(
246         size_t index, const sp<MediaCodecBuffer> &buffer) {
247     sp<AMessage> notify(mNotify->dup());
248     notify->setInt32("what", kWhatFillThisBuffer);
249     notify->setSize("index", index);
250     notify->setObject("buffer", buffer);
251     notify->post();
252 }
253 
onOutputBufferAvailable(size_t index,const sp<MediaCodecBuffer> & buffer)254 void BufferCallback::onOutputBufferAvailable(
255         size_t index, const sp<MediaCodecBuffer> &buffer) {
256     sp<AMessage> notify(mNotify->dup());
257     notify->setInt32("what", kWhatDrainThisBuffer);
258     notify->setSize("index", index);
259     notify->setObject("buffer", buffer);
260     notify->post();
261 }
262 
263 class CodecCallback : public CodecBase::CodecCallback {
264 public:
265     explicit CodecCallback(const sp<AMessage> &notify);
266     virtual ~CodecCallback() = default;
267 
268     virtual void onEos(status_t err) override;
269     virtual void onStartCompleted() override;
270     virtual void onStopCompleted() override;
271     virtual void onReleaseCompleted() override;
272     virtual void onFlushCompleted() override;
273     virtual void onError(status_t err, enum ActionCode actionCode) override;
274     virtual void onComponentAllocated(const char *componentName) override;
275     virtual void onComponentConfigured(
276             const sp<AMessage> &inputFormat, const sp<AMessage> &outputFormat) override;
277     virtual void onInputSurfaceCreated(
278             const sp<AMessage> &inputFormat,
279             const sp<AMessage> &outputFormat,
280             const sp<BufferProducerWrapper> &inputSurface) override;
281     virtual void onInputSurfaceCreationFailed(status_t err) override;
282     virtual void onInputSurfaceAccepted(
283             const sp<AMessage> &inputFormat,
284             const sp<AMessage> &outputFormat) override;
285     virtual void onInputSurfaceDeclined(status_t err) override;
286     virtual void onSignaledInputEOS(status_t err) override;
287     virtual void onOutputFramesRendered(const std::list<FrameRenderTracker::Info> &done) override;
288     virtual void onOutputBuffersChanged() override;
289 private:
290     const sp<AMessage> mNotify;
291 };
292 
CodecCallback(const sp<AMessage> & notify)293 CodecCallback::CodecCallback(const sp<AMessage> &notify) : mNotify(notify) {}
294 
onEos(status_t err)295 void CodecCallback::onEos(status_t err) {
296     sp<AMessage> notify(mNotify->dup());
297     notify->setInt32("what", kWhatEOS);
298     notify->setInt32("err", err);
299     notify->post();
300 }
301 
onStartCompleted()302 void CodecCallback::onStartCompleted() {
303     sp<AMessage> notify(mNotify->dup());
304     notify->setInt32("what", kWhatStartCompleted);
305     notify->post();
306 }
307 
onStopCompleted()308 void CodecCallback::onStopCompleted() {
309     sp<AMessage> notify(mNotify->dup());
310     notify->setInt32("what", kWhatStopCompleted);
311     notify->post();
312 }
313 
onReleaseCompleted()314 void CodecCallback::onReleaseCompleted() {
315     sp<AMessage> notify(mNotify->dup());
316     notify->setInt32("what", kWhatReleaseCompleted);
317     notify->post();
318 }
319 
onFlushCompleted()320 void CodecCallback::onFlushCompleted() {
321     sp<AMessage> notify(mNotify->dup());
322     notify->setInt32("what", kWhatFlushCompleted);
323     notify->post();
324 }
325 
onError(status_t err,enum ActionCode actionCode)326 void CodecCallback::onError(status_t err, enum ActionCode actionCode) {
327     sp<AMessage> notify(mNotify->dup());
328     notify->setInt32("what", kWhatError);
329     notify->setInt32("err", err);
330     notify->setInt32("actionCode", actionCode);
331     notify->post();
332 }
333 
onComponentAllocated(const char * componentName)334 void CodecCallback::onComponentAllocated(const char *componentName) {
335     sp<AMessage> notify(mNotify->dup());
336     notify->setInt32("what", kWhatComponentAllocated);
337     notify->setString("componentName", componentName);
338     notify->post();
339 }
340 
onComponentConfigured(const sp<AMessage> & inputFormat,const sp<AMessage> & outputFormat)341 void CodecCallback::onComponentConfigured(
342         const sp<AMessage> &inputFormat, const sp<AMessage> &outputFormat) {
343     sp<AMessage> notify(mNotify->dup());
344     notify->setInt32("what", kWhatComponentConfigured);
345     notify->setMessage("input-format", inputFormat);
346     notify->setMessage("output-format", outputFormat);
347     notify->post();
348 }
349 
onInputSurfaceCreated(const sp<AMessage> & inputFormat,const sp<AMessage> & outputFormat,const sp<BufferProducerWrapper> & inputSurface)350 void CodecCallback::onInputSurfaceCreated(
351         const sp<AMessage> &inputFormat,
352         const sp<AMessage> &outputFormat,
353         const sp<BufferProducerWrapper> &inputSurface) {
354     sp<AMessage> notify(mNotify->dup());
355     notify->setInt32("what", kWhatInputSurfaceCreated);
356     notify->setMessage("input-format", inputFormat);
357     notify->setMessage("output-format", outputFormat);
358     notify->setObject("input-surface", inputSurface);
359     notify->post();
360 }
361 
onInputSurfaceCreationFailed(status_t err)362 void CodecCallback::onInputSurfaceCreationFailed(status_t err) {
363     sp<AMessage> notify(mNotify->dup());
364     notify->setInt32("what", kWhatInputSurfaceCreated);
365     notify->setInt32("err", err);
366     notify->post();
367 }
368 
onInputSurfaceAccepted(const sp<AMessage> & inputFormat,const sp<AMessage> & outputFormat)369 void CodecCallback::onInputSurfaceAccepted(
370         const sp<AMessage> &inputFormat,
371         const sp<AMessage> &outputFormat) {
372     sp<AMessage> notify(mNotify->dup());
373     notify->setInt32("what", kWhatInputSurfaceAccepted);
374     notify->setMessage("input-format", inputFormat);
375     notify->setMessage("output-format", outputFormat);
376     notify->post();
377 }
378 
onInputSurfaceDeclined(status_t err)379 void CodecCallback::onInputSurfaceDeclined(status_t err) {
380     sp<AMessage> notify(mNotify->dup());
381     notify->setInt32("what", kWhatInputSurfaceAccepted);
382     notify->setInt32("err", err);
383     notify->post();
384 }
385 
onSignaledInputEOS(status_t err)386 void CodecCallback::onSignaledInputEOS(status_t err) {
387     sp<AMessage> notify(mNotify->dup());
388     notify->setInt32("what", kWhatSignaledInputEOS);
389     if (err != OK) {
390         notify->setInt32("err", err);
391     }
392     notify->post();
393 }
394 
onOutputFramesRendered(const std::list<FrameRenderTracker::Info> & done)395 void CodecCallback::onOutputFramesRendered(const std::list<FrameRenderTracker::Info> &done) {
396     sp<AMessage> notify(mNotify->dup());
397     notify->setInt32("what", kWhatOutputFramesRendered);
398     if (MediaCodec::CreateFramesRenderedMessage(done, notify)) {
399         notify->post();
400     }
401 }
402 
onOutputBuffersChanged()403 void CodecCallback::onOutputBuffersChanged() {
404     sp<AMessage> notify(mNotify->dup());
405     notify->setInt32("what", kWhatOutputBuffersChanged);
406     notify->post();
407 }
408 
409 }  // namespace
410 
411 ////////////////////////////////////////////////////////////////////////////////
412 
413 // static
CreateByType(const sp<ALooper> & looper,const AString & mime,bool encoder,status_t * err,pid_t pid,uid_t uid)414 sp<MediaCodec> MediaCodec::CreateByType(
415         const sp<ALooper> &looper, const AString &mime, bool encoder, status_t *err, pid_t pid,
416         uid_t uid) {
417     sp<MediaCodec> codec = new MediaCodec(looper, pid, uid);
418 
419     const status_t ret = codec->init(mime, true /* nameIsType */, encoder);
420     if (err != NULL) {
421         *err = ret;
422     }
423     return ret == OK ? codec : NULL; // NULL deallocates codec.
424 }
425 
426 // static
CreateByComponentName(const sp<ALooper> & looper,const AString & name,status_t * err,pid_t pid,uid_t uid)427 sp<MediaCodec> MediaCodec::CreateByComponentName(
428         const sp<ALooper> &looper, const AString &name, status_t *err, pid_t pid, uid_t uid) {
429     sp<MediaCodec> codec = new MediaCodec(looper, pid, uid);
430 
431     const status_t ret = codec->init(name, false /* nameIsType */, false /* encoder */);
432     if (err != NULL) {
433         *err = ret;
434     }
435     return ret == OK ? codec : NULL; // NULL deallocates codec.
436 }
437 
438 // static
CreatePersistentInputSurface()439 sp<PersistentSurface> MediaCodec::CreatePersistentInputSurface() {
440     OMXClient client;
441     if (client.connect() != OK) {
442         ALOGE("Failed to connect to OMX to create persistent input surface.");
443         return NULL;
444     }
445 
446     sp<IOMX> omx = client.interface();
447 
448     sp<IGraphicBufferProducer> bufferProducer;
449     sp<IGraphicBufferSource> bufferSource;
450 
451     status_t err = omx->createInputSurface(&bufferProducer, &bufferSource);
452 
453     if (err != OK) {
454         ALOGE("Failed to create persistent input surface.");
455         return NULL;
456     }
457 
458     return new PersistentSurface(bufferProducer, bufferSource);
459 }
460 
MediaCodec(const sp<ALooper> & looper,pid_t pid,uid_t uid)461 MediaCodec::MediaCodec(const sp<ALooper> &looper, pid_t pid, uid_t uid)
462     : mState(UNINITIALIZED),
463       mReleasedByResourceManager(false),
464       mLooper(looper),
465       mCodec(NULL),
466       mReplyID(0),
467       mFlags(0),
468       mStickyError(OK),
469       mSoftRenderer(NULL),
470       mAnalyticsItem(NULL),
471       mResourceManagerClient(new ResourceManagerClient(this)),
472       mResourceManagerService(new ResourceManagerServiceProxy(pid)),
473       mBatteryStatNotified(false),
474       mIsVideo(false),
475       mVideoWidth(0),
476       mVideoHeight(0),
477       mRotationDegrees(0),
478       mDequeueInputTimeoutGeneration(0),
479       mDequeueInputReplyID(0),
480       mDequeueOutputTimeoutGeneration(0),
481       mDequeueOutputReplyID(0),
482       mHaveInputSurface(false),
483       mHavePendingInputBuffers(false) {
484     if (uid == kNoUid) {
485         mUid = IPCThreadState::self()->getCallingUid();
486     } else {
487         mUid = uid;
488     }
489     initAnalyticsItem();
490 }
491 
~MediaCodec()492 MediaCodec::~MediaCodec() {
493     CHECK_EQ(mState, UNINITIALIZED);
494     mResourceManagerService->removeResource(getId(mResourceManagerClient));
495 
496     flushAnalyticsItem();
497 }
498 
initAnalyticsItem()499 void MediaCodec::initAnalyticsItem() {
500     CHECK(mAnalyticsItem == NULL);
501     // set up our new record, get a sessionID, put it into the in-progress list
502     mAnalyticsItem = new MediaAnalyticsItem(kCodecKeyName);
503     if (mAnalyticsItem != NULL) {
504         (void) mAnalyticsItem->generateSessionID();
505         // don't record it yet; only at the end, when we have decided that we have
506         // data worth writing (e.g. .count() > 0)
507     }
508 }
509 
flushAnalyticsItem()510 void MediaCodec::flushAnalyticsItem() {
511     if (mAnalyticsItem != NULL) {
512         // don't log empty records
513         if (mAnalyticsItem->count() > 0) {
514             mAnalyticsItem->setFinalized(true);
515             mAnalyticsItem->selfrecord();
516         }
517         delete mAnalyticsItem;
518         mAnalyticsItem = NULL;
519     }
520 }
521 
522 // static
PostAndAwaitResponse(const sp<AMessage> & msg,sp<AMessage> * response)523 status_t MediaCodec::PostAndAwaitResponse(
524         const sp<AMessage> &msg, sp<AMessage> *response) {
525     status_t err = msg->postAndAwaitResponse(response);
526 
527     if (err != OK) {
528         return err;
529     }
530 
531     if (!(*response)->findInt32("err", &err)) {
532         err = OK;
533     }
534 
535     return err;
536 }
537 
PostReplyWithError(const sp<AReplyToken> & replyID,int32_t err)538 void MediaCodec::PostReplyWithError(const sp<AReplyToken> &replyID, int32_t err) {
539     int32_t finalErr = err;
540     if (mReleasedByResourceManager) {
541         // override the err code if MediaCodec has been released by ResourceManager.
542         finalErr = DEAD_OBJECT;
543     }
544 
545     sp<AMessage> response = new AMessage;
546     response->setInt32("err", finalErr);
547     response->postReply(replyID);
548 }
549 
550 //static
GetCodecBase(const AString & name,bool nameIsType)551 sp<CodecBase> MediaCodec::GetCodecBase(const AString &name, bool nameIsType) {
552     // at this time only ACodec specifies a mime type.
553     if (nameIsType || name.startsWithIgnoreCase("omx.")) {
554         return new ACodec;
555     } else if (name.startsWithIgnoreCase("android.filter.")) {
556         return new MediaFilter;
557     } else {
558         return NULL;
559     }
560 }
561 
init(const AString & name,bool nameIsType,bool encoder)562 status_t MediaCodec::init(const AString &name, bool nameIsType, bool encoder) {
563     mResourceManagerService->init();
564 
565     // save init parameters for reset
566     mInitName = name;
567     mInitNameIsType = nameIsType;
568     mInitIsEncoder = encoder;
569 
570     // Current video decoders do not return from OMX_FillThisBuffer
571     // quickly, violating the OpenMAX specs, until that is remedied
572     // we need to invest in an extra looper to free the main event
573     // queue.
574 
575     mCodec = GetCodecBase(name, nameIsType);
576     if (mCodec == NULL) {
577         return NAME_NOT_FOUND;
578     }
579 
580     bool secureCodec = false;
581     if (nameIsType && !strncasecmp(name.c_str(), "video/", 6)) {
582         mIsVideo = true;
583     } else {
584         AString tmp = name;
585         if (tmp.endsWith(".secure")) {
586             secureCodec = true;
587             tmp.erase(tmp.size() - 7, 7);
588         }
589         const sp<IMediaCodecList> mcl = MediaCodecList::getInstance();
590         if (mcl == NULL) {
591             mCodec = NULL;  // remove the codec.
592             return NO_INIT; // if called from Java should raise IOException
593         }
594         ssize_t codecIdx = mcl->findCodecByName(tmp.c_str());
595         if (codecIdx >= 0) {
596             const sp<MediaCodecInfo> info = mcl->getCodecInfo(codecIdx);
597             Vector<AString> mimes;
598             info->getSupportedMimes(&mimes);
599             for (size_t i = 0; i < mimes.size(); i++) {
600                 if (mimes[i].startsWith("video/")) {
601                     mIsVideo = true;
602                     break;
603                 }
604             }
605         }
606     }
607 
608     if (mIsVideo) {
609         // video codec needs dedicated looper
610         if (mCodecLooper == NULL) {
611             mCodecLooper = new ALooper;
612             mCodecLooper->setName("CodecLooper");
613             mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
614         }
615 
616         mCodecLooper->registerHandler(mCodec);
617     } else {
618         mLooper->registerHandler(mCodec);
619     }
620 
621     mLooper->registerHandler(this);
622 
623     mCodec->setCallback(
624             std::unique_ptr<CodecBase::CodecCallback>(
625                     new CodecCallback(new AMessage(kWhatCodecNotify, this))));
626     mBufferChannel = mCodec->getBufferChannel();
627     mBufferChannel->setCallback(
628             std::unique_ptr<CodecBase::BufferCallback>(
629                     new BufferCallback(new AMessage(kWhatCodecNotify, this))));
630 
631     sp<AMessage> msg = new AMessage(kWhatInit, this);
632     msg->setString("name", name);
633     msg->setInt32("nameIsType", nameIsType);
634 
635     if (nameIsType) {
636         msg->setInt32("encoder", encoder);
637     }
638 
639     if (mAnalyticsItem != NULL) {
640         if (nameIsType) {
641             // name is the mime type
642             mAnalyticsItem->setCString(kCodecMime, name.c_str());
643         } else {
644             mAnalyticsItem->setCString(kCodecCodec, name.c_str());
645         }
646         mAnalyticsItem->setCString(kCodecMode, mIsVideo ? "video" : "audio");
647         if (nameIsType)
648             mAnalyticsItem->setInt32(kCodecEncoder, encoder);
649     }
650 
651     status_t err;
652     Vector<MediaResource> resources;
653     MediaResource::Type type =
654             secureCodec ? MediaResource::kSecureCodec : MediaResource::kNonSecureCodec;
655     MediaResource::SubType subtype =
656             mIsVideo ? MediaResource::kVideoCodec : MediaResource::kAudioCodec;
657     resources.push_back(MediaResource(type, subtype, 1));
658     for (int i = 0; i <= kMaxRetry; ++i) {
659         if (i > 0) {
660             // Don't try to reclaim resource for the first time.
661             if (!mResourceManagerService->reclaimResource(resources)) {
662                 break;
663             }
664         }
665 
666         sp<AMessage> response;
667         err = PostAndAwaitResponse(msg, &response);
668         if (!isResourceError(err)) {
669             break;
670         }
671     }
672     return err;
673 }
674 
setCallback(const sp<AMessage> & callback)675 status_t MediaCodec::setCallback(const sp<AMessage> &callback) {
676     sp<AMessage> msg = new AMessage(kWhatSetCallback, this);
677     msg->setMessage("callback", callback);
678 
679     sp<AMessage> response;
680     return PostAndAwaitResponse(msg, &response);
681 }
682 
setOnFrameRenderedNotification(const sp<AMessage> & notify)683 status_t MediaCodec::setOnFrameRenderedNotification(const sp<AMessage> &notify) {
684     sp<AMessage> msg = new AMessage(kWhatSetNotification, this);
685     msg->setMessage("on-frame-rendered", notify);
686     return msg->post();
687 }
688 
configure(const sp<AMessage> & format,const sp<Surface> & nativeWindow,const sp<ICrypto> & crypto,uint32_t flags)689 status_t MediaCodec::configure(
690         const sp<AMessage> &format,
691         const sp<Surface> &nativeWindow,
692         const sp<ICrypto> &crypto,
693         uint32_t flags) {
694     return configure(format, nativeWindow, crypto, NULL, flags);
695 }
696 
configure(const sp<AMessage> & format,const sp<Surface> & surface,const sp<ICrypto> & crypto,const sp<IDescrambler> & descrambler,uint32_t flags)697 status_t MediaCodec::configure(
698         const sp<AMessage> &format,
699         const sp<Surface> &surface,
700         const sp<ICrypto> &crypto,
701         const sp<IDescrambler> &descrambler,
702         uint32_t flags) {
703     sp<AMessage> msg = new AMessage(kWhatConfigure, this);
704 
705     if (mAnalyticsItem != NULL) {
706         int32_t profile = 0;
707         if (format->findInt32("profile", &profile)) {
708             mAnalyticsItem->setInt32(kCodecProfile, profile);
709         }
710         int32_t level = 0;
711         if (format->findInt32("level", &level)) {
712             mAnalyticsItem->setInt32(kCodecLevel, level);
713         }
714     }
715 
716     if (mIsVideo) {
717         format->findInt32("width", &mVideoWidth);
718         format->findInt32("height", &mVideoHeight);
719         if (!format->findInt32("rotation-degrees", &mRotationDegrees)) {
720             mRotationDegrees = 0;
721         }
722 
723         if (mAnalyticsItem != NULL) {
724             mAnalyticsItem->setInt32(kCodecWidth, mVideoWidth);
725             mAnalyticsItem->setInt32(kCodecHeight, mVideoHeight);
726             mAnalyticsItem->setInt32(kCodecRotation, mRotationDegrees);
727             int32_t maxWidth = 0;
728             if (format->findInt32("max-width", &maxWidth)) {
729                 mAnalyticsItem->setInt32(kCodecMaxWidth, maxWidth);
730             }
731             int32_t maxHeight = 0;
732             if (format->findInt32("max-height", &maxHeight)) {
733                 mAnalyticsItem->setInt32(kCodecMaxHeight, maxHeight);
734             }
735         }
736 
737         // Prevent possible integer overflow in downstream code.
738         if (mInitIsEncoder
739                 && (uint64_t)mVideoWidth * mVideoHeight > (uint64_t)INT32_MAX / 4) {
740             ALOGE("buffer size is too big, width=%d, height=%d", mVideoWidth, mVideoHeight);
741             return BAD_VALUE;
742         }
743     }
744 
745     msg->setMessage("format", format);
746     msg->setInt32("flags", flags);
747     msg->setObject("surface", surface);
748 
749     if (crypto != NULL || descrambler != NULL) {
750         if (crypto != NULL) {
751             msg->setPointer("crypto", crypto.get());
752         } else {
753             msg->setPointer("descrambler", descrambler.get());
754         }
755         if (mAnalyticsItem != NULL) {
756             // XXX: save indication that it's crypto in some way...
757             mAnalyticsItem->setInt32(kCodecCrypto, 1);
758         }
759     } else if (mFlags & kFlagIsSecure) {
760         ALOGW("Crypto or descrambler should be given for secure codec");
761     }
762 
763     // save msg for reset
764     mConfigureMsg = msg;
765 
766     status_t err;
767     Vector<MediaResource> resources;
768     MediaResource::Type type = (mFlags & kFlagIsSecure) ?
769             MediaResource::kSecureCodec : MediaResource::kNonSecureCodec;
770     MediaResource::SubType subtype =
771             mIsVideo ? MediaResource::kVideoCodec : MediaResource::kAudioCodec;
772     resources.push_back(MediaResource(type, subtype, 1));
773     // Don't know the buffer size at this point, but it's fine to use 1 because
774     // the reclaimResource call doesn't consider the requester's buffer size for now.
775     resources.push_back(MediaResource(MediaResource::kGraphicMemory, 1));
776     for (int i = 0; i <= kMaxRetry; ++i) {
777         if (i > 0) {
778             // Don't try to reclaim resource for the first time.
779             if (!mResourceManagerService->reclaimResource(resources)) {
780                 break;
781             }
782         }
783 
784         sp<AMessage> response;
785         err = PostAndAwaitResponse(msg, &response);
786         if (err != OK && err != INVALID_OPERATION) {
787             // MediaCodec now set state to UNINITIALIZED upon any fatal error.
788             // To maintain backward-compatibility, do a reset() to put codec
789             // back into INITIALIZED state.
790             // But don't reset if the err is INVALID_OPERATION, which means
791             // the configure failure is due to wrong state.
792 
793             ALOGE("configure failed with err 0x%08x, resetting...", err);
794             reset();
795         }
796         if (!isResourceError(err)) {
797             break;
798         }
799     }
800     return err;
801 }
802 
releaseCrypto()803 status_t MediaCodec::releaseCrypto()
804 {
805     ALOGV("releaseCrypto");
806 
807     sp<AMessage> msg = new AMessage(kWhatDrmReleaseCrypto, this);
808 
809     sp<AMessage> response;
810     status_t status = msg->postAndAwaitResponse(&response);
811 
812     if (status == OK && response != NULL) {
813         CHECK(response->findInt32("status", &status));
814         ALOGV("releaseCrypto ret: %d ", status);
815     }
816     else {
817         ALOGE("releaseCrypto err: %d", status);
818     }
819 
820     return status;
821 }
822 
onReleaseCrypto(const sp<AMessage> & msg)823 void MediaCodec::onReleaseCrypto(const sp<AMessage>& msg)
824 {
825     status_t status = INVALID_OPERATION;
826     if (mCrypto != NULL) {
827         ALOGV("onReleaseCrypto: mCrypto: %p (%d)", mCrypto.get(), mCrypto->getStrongCount());
828         mBufferChannel->setCrypto(NULL);
829         // TODO change to ALOGV
830         ALOGD("onReleaseCrypto: [before clear]  mCrypto: %p (%d)",
831                 mCrypto.get(), mCrypto->getStrongCount());
832         mCrypto.clear();
833 
834         status = OK;
835     }
836     else {
837         ALOGW("onReleaseCrypto: No mCrypto. err: %d", status);
838     }
839 
840     sp<AMessage> response = new AMessage;
841     response->setInt32("status", status);
842 
843     sp<AReplyToken> replyID;
844     CHECK(msg->senderAwaitsResponse(&replyID));
845     response->postReply(replyID);
846 }
847 
setInputSurface(const sp<PersistentSurface> & surface)848 status_t MediaCodec::setInputSurface(
849         const sp<PersistentSurface> &surface) {
850     sp<AMessage> msg = new AMessage(kWhatSetInputSurface, this);
851     msg->setObject("input-surface", surface.get());
852 
853     sp<AMessage> response;
854     return PostAndAwaitResponse(msg, &response);
855 }
856 
setSurface(const sp<Surface> & surface)857 status_t MediaCodec::setSurface(const sp<Surface> &surface) {
858     sp<AMessage> msg = new AMessage(kWhatSetSurface, this);
859     msg->setObject("surface", surface);
860 
861     sp<AMessage> response;
862     return PostAndAwaitResponse(msg, &response);
863 }
864 
createInputSurface(sp<IGraphicBufferProducer> * bufferProducer)865 status_t MediaCodec::createInputSurface(
866         sp<IGraphicBufferProducer>* bufferProducer) {
867     sp<AMessage> msg = new AMessage(kWhatCreateInputSurface, this);
868 
869     sp<AMessage> response;
870     status_t err = PostAndAwaitResponse(msg, &response);
871     if (err == NO_ERROR) {
872         // unwrap the sp<IGraphicBufferProducer>
873         sp<RefBase> obj;
874         bool found = response->findObject("input-surface", &obj);
875         CHECK(found);
876         sp<BufferProducerWrapper> wrapper(
877                 static_cast<BufferProducerWrapper*>(obj.get()));
878         *bufferProducer = wrapper->getBufferProducer();
879     } else {
880         ALOGW("createInputSurface failed, err=%d", err);
881     }
882     return err;
883 }
884 
getGraphicBufferSize()885 uint64_t MediaCodec::getGraphicBufferSize() {
886     if (!mIsVideo) {
887         return 0;
888     }
889 
890     uint64_t size = 0;
891     size_t portNum = sizeof(mPortBuffers) / sizeof((mPortBuffers)[0]);
892     for (size_t i = 0; i < portNum; ++i) {
893         // TODO: this is just an estimation, we should get the real buffer size from ACodec.
894         size += mPortBuffers[i].size() * mVideoWidth * mVideoHeight * 3 / 2;
895     }
896     return size;
897 }
898 
addResource(MediaResource::Type type,MediaResource::SubType subtype,uint64_t value)899 void MediaCodec::addResource(
900         MediaResource::Type type, MediaResource::SubType subtype, uint64_t value) {
901     Vector<MediaResource> resources;
902     resources.push_back(MediaResource(type, subtype, value));
903     mResourceManagerService->addResource(
904             getId(mResourceManagerClient), mResourceManagerClient, resources);
905 }
906 
start()907 status_t MediaCodec::start() {
908     sp<AMessage> msg = new AMessage(kWhatStart, this);
909 
910     status_t err;
911     Vector<MediaResource> resources;
912     MediaResource::Type type = (mFlags & kFlagIsSecure) ?
913             MediaResource::kSecureCodec : MediaResource::kNonSecureCodec;
914     MediaResource::SubType subtype =
915             mIsVideo ? MediaResource::kVideoCodec : MediaResource::kAudioCodec;
916     resources.push_back(MediaResource(type, subtype, 1));
917     // Don't know the buffer size at this point, but it's fine to use 1 because
918     // the reclaimResource call doesn't consider the requester's buffer size for now.
919     resources.push_back(MediaResource(MediaResource::kGraphicMemory, 1));
920     for (int i = 0; i <= kMaxRetry; ++i) {
921         if (i > 0) {
922             // Don't try to reclaim resource for the first time.
923             if (!mResourceManagerService->reclaimResource(resources)) {
924                 break;
925             }
926             // Recover codec from previous error before retry start.
927             err = reset();
928             if (err != OK) {
929                 ALOGE("retrying start: failed to reset codec");
930                 break;
931             }
932             sp<AMessage> response;
933             err = PostAndAwaitResponse(mConfigureMsg, &response);
934             if (err != OK) {
935                 ALOGE("retrying start: failed to configure codec");
936                 break;
937             }
938         }
939 
940         sp<AMessage> response;
941         err = PostAndAwaitResponse(msg, &response);
942         if (!isResourceError(err)) {
943             break;
944         }
945     }
946     return err;
947 }
948 
stop()949 status_t MediaCodec::stop() {
950     sp<AMessage> msg = new AMessage(kWhatStop, this);
951 
952     sp<AMessage> response;
953     return PostAndAwaitResponse(msg, &response);
954 }
955 
hasPendingBuffer(int portIndex)956 bool MediaCodec::hasPendingBuffer(int portIndex) {
957     return std::any_of(
958             mPortBuffers[portIndex].begin(), mPortBuffers[portIndex].end(),
959             [](const BufferInfo &info) { return info.mOwnedByClient; });
960 }
961 
hasPendingBuffer()962 bool MediaCodec::hasPendingBuffer() {
963     return hasPendingBuffer(kPortIndexInput) || hasPendingBuffer(kPortIndexOutput);
964 }
965 
reclaim(bool force)966 status_t MediaCodec::reclaim(bool force) {
967     ALOGD("MediaCodec::reclaim(%p) %s", this, mInitName.c_str());
968     sp<AMessage> msg = new AMessage(kWhatRelease, this);
969     msg->setInt32("reclaimed", 1);
970     msg->setInt32("force", force ? 1 : 0);
971 
972     sp<AMessage> response;
973     status_t ret = PostAndAwaitResponse(msg, &response);
974     if (ret == -ENOENT) {
975         ALOGD("MediaCodec looper is gone, skip reclaim");
976         ret = OK;
977     }
978     return ret;
979 }
980 
release()981 status_t MediaCodec::release() {
982     sp<AMessage> msg = new AMessage(kWhatRelease, this);
983 
984     sp<AMessage> response;
985     return PostAndAwaitResponse(msg, &response);
986 }
987 
reset()988 status_t MediaCodec::reset() {
989     /* When external-facing MediaCodec object is created,
990        it is already initialized.  Thus, reset is essentially
991        release() followed by init(), plus clearing the state */
992 
993     status_t err = release();
994 
995     // unregister handlers
996     if (mCodec != NULL) {
997         if (mCodecLooper != NULL) {
998             mCodecLooper->unregisterHandler(mCodec->id());
999         } else {
1000             mLooper->unregisterHandler(mCodec->id());
1001         }
1002         mCodec = NULL;
1003     }
1004     mLooper->unregisterHandler(id());
1005 
1006     mFlags = 0;    // clear all flags
1007     mStickyError = OK;
1008 
1009     // reset state not reset by setState(UNINITIALIZED)
1010     mReplyID = 0;
1011     mDequeueInputReplyID = 0;
1012     mDequeueOutputReplyID = 0;
1013     mDequeueInputTimeoutGeneration = 0;
1014     mDequeueOutputTimeoutGeneration = 0;
1015     mHaveInputSurface = false;
1016 
1017     if (err == OK) {
1018         err = init(mInitName, mInitNameIsType, mInitIsEncoder);
1019     }
1020     return err;
1021 }
1022 
queueInputBuffer(size_t index,size_t offset,size_t size,int64_t presentationTimeUs,uint32_t flags,AString * errorDetailMsg)1023 status_t MediaCodec::queueInputBuffer(
1024         size_t index,
1025         size_t offset,
1026         size_t size,
1027         int64_t presentationTimeUs,
1028         uint32_t flags,
1029         AString *errorDetailMsg) {
1030     if (errorDetailMsg != NULL) {
1031         errorDetailMsg->clear();
1032     }
1033 
1034     sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this);
1035     msg->setSize("index", index);
1036     msg->setSize("offset", offset);
1037     msg->setSize("size", size);
1038     msg->setInt64("timeUs", presentationTimeUs);
1039     msg->setInt32("flags", flags);
1040     msg->setPointer("errorDetailMsg", errorDetailMsg);
1041 
1042     sp<AMessage> response;
1043     return PostAndAwaitResponse(msg, &response);
1044 }
1045 
queueSecureInputBuffer(size_t index,size_t offset,const CryptoPlugin::SubSample * subSamples,size_t numSubSamples,const uint8_t key[16],const uint8_t iv[16],CryptoPlugin::Mode mode,const CryptoPlugin::Pattern & pattern,int64_t presentationTimeUs,uint32_t flags,AString * errorDetailMsg)1046 status_t MediaCodec::queueSecureInputBuffer(
1047         size_t index,
1048         size_t offset,
1049         const CryptoPlugin::SubSample *subSamples,
1050         size_t numSubSamples,
1051         const uint8_t key[16],
1052         const uint8_t iv[16],
1053         CryptoPlugin::Mode mode,
1054         const CryptoPlugin::Pattern &pattern,
1055         int64_t presentationTimeUs,
1056         uint32_t flags,
1057         AString *errorDetailMsg) {
1058     if (errorDetailMsg != NULL) {
1059         errorDetailMsg->clear();
1060     }
1061 
1062     sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this);
1063     msg->setSize("index", index);
1064     msg->setSize("offset", offset);
1065     msg->setPointer("subSamples", (void *)subSamples);
1066     msg->setSize("numSubSamples", numSubSamples);
1067     msg->setPointer("key", (void *)key);
1068     msg->setPointer("iv", (void *)iv);
1069     msg->setInt32("mode", mode);
1070     msg->setInt32("encryptBlocks", pattern.mEncryptBlocks);
1071     msg->setInt32("skipBlocks", pattern.mSkipBlocks);
1072     msg->setInt64("timeUs", presentationTimeUs);
1073     msg->setInt32("flags", flags);
1074     msg->setPointer("errorDetailMsg", errorDetailMsg);
1075 
1076     sp<AMessage> response;
1077     status_t err = PostAndAwaitResponse(msg, &response);
1078 
1079     return err;
1080 }
1081 
dequeueInputBuffer(size_t * index,int64_t timeoutUs)1082 status_t MediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
1083     sp<AMessage> msg = new AMessage(kWhatDequeueInputBuffer, this);
1084     msg->setInt64("timeoutUs", timeoutUs);
1085 
1086     sp<AMessage> response;
1087     status_t err;
1088     if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
1089         return err;
1090     }
1091 
1092     CHECK(response->findSize("index", index));
1093 
1094     return OK;
1095 }
1096 
dequeueOutputBuffer(size_t * index,size_t * offset,size_t * size,int64_t * presentationTimeUs,uint32_t * flags,int64_t timeoutUs)1097 status_t MediaCodec::dequeueOutputBuffer(
1098         size_t *index,
1099         size_t *offset,
1100         size_t *size,
1101         int64_t *presentationTimeUs,
1102         uint32_t *flags,
1103         int64_t timeoutUs) {
1104     sp<AMessage> msg = new AMessage(kWhatDequeueOutputBuffer, this);
1105     msg->setInt64("timeoutUs", timeoutUs);
1106 
1107     sp<AMessage> response;
1108     status_t err;
1109     if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
1110         return err;
1111     }
1112 
1113     CHECK(response->findSize("index", index));
1114     CHECK(response->findSize("offset", offset));
1115     CHECK(response->findSize("size", size));
1116     CHECK(response->findInt64("timeUs", presentationTimeUs));
1117     CHECK(response->findInt32("flags", (int32_t *)flags));
1118 
1119     return OK;
1120 }
1121 
renderOutputBufferAndRelease(size_t index)1122 status_t MediaCodec::renderOutputBufferAndRelease(size_t index) {
1123     sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, this);
1124     msg->setSize("index", index);
1125     msg->setInt32("render", true);
1126 
1127     sp<AMessage> response;
1128     return PostAndAwaitResponse(msg, &response);
1129 }
1130 
renderOutputBufferAndRelease(size_t index,int64_t timestampNs)1131 status_t MediaCodec::renderOutputBufferAndRelease(size_t index, int64_t timestampNs) {
1132     sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, this);
1133     msg->setSize("index", index);
1134     msg->setInt32("render", true);
1135     msg->setInt64("timestampNs", timestampNs);
1136 
1137     sp<AMessage> response;
1138     return PostAndAwaitResponse(msg, &response);
1139 }
1140 
releaseOutputBuffer(size_t index)1141 status_t MediaCodec::releaseOutputBuffer(size_t index) {
1142     sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, this);
1143     msg->setSize("index", index);
1144 
1145     sp<AMessage> response;
1146     return PostAndAwaitResponse(msg, &response);
1147 }
1148 
signalEndOfInputStream()1149 status_t MediaCodec::signalEndOfInputStream() {
1150     sp<AMessage> msg = new AMessage(kWhatSignalEndOfInputStream, this);
1151 
1152     sp<AMessage> response;
1153     return PostAndAwaitResponse(msg, &response);
1154 }
1155 
getOutputFormat(sp<AMessage> * format) const1156 status_t MediaCodec::getOutputFormat(sp<AMessage> *format) const {
1157     sp<AMessage> msg = new AMessage(kWhatGetOutputFormat, this);
1158 
1159     sp<AMessage> response;
1160     status_t err;
1161     if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
1162         return err;
1163     }
1164 
1165     CHECK(response->findMessage("format", format));
1166 
1167     return OK;
1168 }
1169 
getInputFormat(sp<AMessage> * format) const1170 status_t MediaCodec::getInputFormat(sp<AMessage> *format) const {
1171     sp<AMessage> msg = new AMessage(kWhatGetInputFormat, this);
1172 
1173     sp<AMessage> response;
1174     status_t err;
1175     if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
1176         return err;
1177     }
1178 
1179     CHECK(response->findMessage("format", format));
1180 
1181     return OK;
1182 }
1183 
getName(AString * name) const1184 status_t MediaCodec::getName(AString *name) const {
1185     sp<AMessage> msg = new AMessage(kWhatGetName, this);
1186 
1187     sp<AMessage> response;
1188     status_t err;
1189     if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
1190         return err;
1191     }
1192 
1193     CHECK(response->findString("name", name));
1194 
1195     return OK;
1196 }
1197 
getMetrics(MediaAnalyticsItem * & reply)1198 status_t MediaCodec::getMetrics(MediaAnalyticsItem * &reply) {
1199 
1200     reply = NULL;
1201 
1202     // shouldn't happen, but be safe
1203     if (mAnalyticsItem == NULL) {
1204         return UNKNOWN_ERROR;
1205     }
1206 
1207     // XXX: go get current values for whatever in-flight data we want
1208 
1209     // send it back to the caller.
1210     reply = mAnalyticsItem->dup();
1211 
1212     return OK;
1213 }
1214 
getInputBuffers(Vector<sp<MediaCodecBuffer>> * buffers) const1215 status_t MediaCodec::getInputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const {
1216     sp<AMessage> msg = new AMessage(kWhatGetBuffers, this);
1217     msg->setInt32("portIndex", kPortIndexInput);
1218     msg->setPointer("buffers", buffers);
1219 
1220     sp<AMessage> response;
1221     return PostAndAwaitResponse(msg, &response);
1222 }
1223 
getOutputBuffers(Vector<sp<MediaCodecBuffer>> * buffers) const1224 status_t MediaCodec::getOutputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const {
1225     sp<AMessage> msg = new AMessage(kWhatGetBuffers, this);
1226     msg->setInt32("portIndex", kPortIndexOutput);
1227     msg->setPointer("buffers", buffers);
1228 
1229     sp<AMessage> response;
1230     return PostAndAwaitResponse(msg, &response);
1231 }
1232 
getOutputBuffer(size_t index,sp<MediaCodecBuffer> * buffer)1233 status_t MediaCodec::getOutputBuffer(size_t index, sp<MediaCodecBuffer> *buffer) {
1234     sp<AMessage> format;
1235     return getBufferAndFormat(kPortIndexOutput, index, buffer, &format);
1236 }
1237 
getOutputFormat(size_t index,sp<AMessage> * format)1238 status_t MediaCodec::getOutputFormat(size_t index, sp<AMessage> *format) {
1239     sp<MediaCodecBuffer> buffer;
1240     return getBufferAndFormat(kPortIndexOutput, index, &buffer, format);
1241 }
1242 
getInputBuffer(size_t index,sp<MediaCodecBuffer> * buffer)1243 status_t MediaCodec::getInputBuffer(size_t index, sp<MediaCodecBuffer> *buffer) {
1244     sp<AMessage> format;
1245     return getBufferAndFormat(kPortIndexInput, index, buffer, &format);
1246 }
1247 
isExecuting() const1248 bool MediaCodec::isExecuting() const {
1249     return mState == STARTED || mState == FLUSHED;
1250 }
1251 
getBufferAndFormat(size_t portIndex,size_t index,sp<MediaCodecBuffer> * buffer,sp<AMessage> * format)1252 status_t MediaCodec::getBufferAndFormat(
1253         size_t portIndex, size_t index,
1254         sp<MediaCodecBuffer> *buffer, sp<AMessage> *format) {
1255     // use mutex instead of a context switch
1256     if (mReleasedByResourceManager) {
1257         ALOGE("getBufferAndFormat - resource already released");
1258         return DEAD_OBJECT;
1259     }
1260 
1261     if (buffer == NULL) {
1262         ALOGE("getBufferAndFormat - null MediaCodecBuffer");
1263         return INVALID_OPERATION;
1264     }
1265 
1266     if (format == NULL) {
1267         ALOGE("getBufferAndFormat - null AMessage");
1268         return INVALID_OPERATION;
1269     }
1270 
1271     buffer->clear();
1272     format->clear();
1273 
1274     if (!isExecuting()) {
1275         ALOGE("getBufferAndFormat - not executing");
1276         return INVALID_OPERATION;
1277     }
1278 
1279     // we do not want mPortBuffers to change during this section
1280     // we also don't want mOwnedByClient to change during this
1281     Mutex::Autolock al(mBufferLock);
1282 
1283     std::vector<BufferInfo> &buffers = mPortBuffers[portIndex];
1284     if (index >= buffers.size()) {
1285         ALOGE("getBufferAndFormat - trying to get buffer with "
1286               "bad index (index=%zu buffer_size=%zu)", index, buffers.size());
1287         return INVALID_OPERATION;
1288     }
1289 
1290     const BufferInfo &info = buffers[index];
1291     if (!info.mOwnedByClient) {
1292         ALOGE("getBufferAndFormat - invalid operation "
1293               "(the index %zu is not owned by client)", index);
1294         return INVALID_OPERATION;
1295     }
1296 
1297     *buffer = info.mData;
1298     *format = info.mData->format();
1299 
1300     return OK;
1301 }
1302 
flush()1303 status_t MediaCodec::flush() {
1304     sp<AMessage> msg = new AMessage(kWhatFlush, this);
1305 
1306     sp<AMessage> response;
1307     return PostAndAwaitResponse(msg, &response);
1308 }
1309 
requestIDRFrame()1310 status_t MediaCodec::requestIDRFrame() {
1311     (new AMessage(kWhatRequestIDRFrame, this))->post();
1312 
1313     return OK;
1314 }
1315 
requestActivityNotification(const sp<AMessage> & notify)1316 void MediaCodec::requestActivityNotification(const sp<AMessage> &notify) {
1317     sp<AMessage> msg = new AMessage(kWhatRequestActivityNotification, this);
1318     msg->setMessage("notify", notify);
1319     msg->post();
1320 }
1321 
1322 ////////////////////////////////////////////////////////////////////////////////
1323 
cancelPendingDequeueOperations()1324 void MediaCodec::cancelPendingDequeueOperations() {
1325     if (mFlags & kFlagDequeueInputPending) {
1326         PostReplyWithError(mDequeueInputReplyID, INVALID_OPERATION);
1327 
1328         ++mDequeueInputTimeoutGeneration;
1329         mDequeueInputReplyID = 0;
1330         mFlags &= ~kFlagDequeueInputPending;
1331     }
1332 
1333     if (mFlags & kFlagDequeueOutputPending) {
1334         PostReplyWithError(mDequeueOutputReplyID, INVALID_OPERATION);
1335 
1336         ++mDequeueOutputTimeoutGeneration;
1337         mDequeueOutputReplyID = 0;
1338         mFlags &= ~kFlagDequeueOutputPending;
1339     }
1340 }
1341 
handleDequeueInputBuffer(const sp<AReplyToken> & replyID,bool newRequest)1342 bool MediaCodec::handleDequeueInputBuffer(const sp<AReplyToken> &replyID, bool newRequest) {
1343     if (!isExecuting() || (mFlags & kFlagIsAsync)
1344             || (newRequest && (mFlags & kFlagDequeueInputPending))) {
1345         PostReplyWithError(replyID, INVALID_OPERATION);
1346         return true;
1347     } else if (mFlags & kFlagStickyError) {
1348         PostReplyWithError(replyID, getStickyError());
1349         return true;
1350     }
1351 
1352     ssize_t index = dequeuePortBuffer(kPortIndexInput);
1353 
1354     if (index < 0) {
1355         CHECK_EQ(index, -EAGAIN);
1356         return false;
1357     }
1358 
1359     sp<AMessage> response = new AMessage;
1360     response->setSize("index", index);
1361     response->postReply(replyID);
1362 
1363     return true;
1364 }
1365 
handleDequeueOutputBuffer(const sp<AReplyToken> & replyID,bool newRequest)1366 bool MediaCodec::handleDequeueOutputBuffer(const sp<AReplyToken> &replyID, bool newRequest) {
1367     if (!isExecuting() || (mFlags & kFlagIsAsync)
1368             || (newRequest && (mFlags & kFlagDequeueOutputPending))) {
1369         PostReplyWithError(replyID, INVALID_OPERATION);
1370     } else if (mFlags & kFlagStickyError) {
1371         PostReplyWithError(replyID, getStickyError());
1372     } else if (mFlags & kFlagOutputBuffersChanged) {
1373         PostReplyWithError(replyID, INFO_OUTPUT_BUFFERS_CHANGED);
1374         mFlags &= ~kFlagOutputBuffersChanged;
1375     } else if (mFlags & kFlagOutputFormatChanged) {
1376         PostReplyWithError(replyID, INFO_FORMAT_CHANGED);
1377         mFlags &= ~kFlagOutputFormatChanged;
1378     } else {
1379         sp<AMessage> response = new AMessage;
1380         ssize_t index = dequeuePortBuffer(kPortIndexOutput);
1381 
1382         if (index < 0) {
1383             CHECK_EQ(index, -EAGAIN);
1384             return false;
1385         }
1386 
1387         const sp<MediaCodecBuffer> &buffer =
1388             mPortBuffers[kPortIndexOutput][index].mData;
1389 
1390         response->setSize("index", index);
1391         response->setSize("offset", buffer->offset());
1392         response->setSize("size", buffer->size());
1393 
1394         int64_t timeUs;
1395         CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
1396 
1397         response->setInt64("timeUs", timeUs);
1398 
1399         int32_t flags;
1400         CHECK(buffer->meta()->findInt32("flags", &flags));
1401 
1402         response->setInt32("flags", flags);
1403         response->postReply(replyID);
1404     }
1405 
1406     return true;
1407 }
1408 
onMessageReceived(const sp<AMessage> & msg)1409 void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
1410     switch (msg->what()) {
1411         case kWhatCodecNotify:
1412         {
1413             int32_t what;
1414             CHECK(msg->findInt32("what", &what));
1415 
1416             switch (what) {
1417                 case kWhatError:
1418                 {
1419                     int32_t err, actionCode;
1420                     CHECK(msg->findInt32("err", &err));
1421                     CHECK(msg->findInt32("actionCode", &actionCode));
1422 
1423                     ALOGE("Codec reported err %#x, actionCode %d, while in state %d",
1424                             err, actionCode, mState);
1425                     if (err == DEAD_OBJECT) {
1426                         mFlags |= kFlagSawMediaServerDie;
1427                         mFlags &= ~kFlagIsComponentAllocated;
1428                     }
1429 
1430                     bool sendErrorResponse = true;
1431 
1432                     switch (mState) {
1433                         case INITIALIZING:
1434                         {
1435                             setState(UNINITIALIZED);
1436                             break;
1437                         }
1438 
1439                         case CONFIGURING:
1440                         {
1441                             if (actionCode == ACTION_CODE_FATAL) {
1442                                 mAnalyticsItem->setInt32(kCodecError, err);
1443                                 mAnalyticsItem->setInt32(kCodecErrorState, mState);
1444                                 flushAnalyticsItem();
1445                                 initAnalyticsItem();
1446                             }
1447                             setState(actionCode == ACTION_CODE_FATAL ?
1448                                     UNINITIALIZED : INITIALIZED);
1449                             break;
1450                         }
1451 
1452                         case STARTING:
1453                         {
1454                             if (actionCode == ACTION_CODE_FATAL) {
1455                                 mAnalyticsItem->setInt32(kCodecError, err);
1456                                 mAnalyticsItem->setInt32(kCodecErrorState, mState);
1457                                 flushAnalyticsItem();
1458                                 initAnalyticsItem();
1459                             }
1460                             setState(actionCode == ACTION_CODE_FATAL ?
1461                                     UNINITIALIZED : CONFIGURED);
1462                             break;
1463                         }
1464 
1465                         case RELEASING:
1466                         {
1467                             // Ignore the error, assuming we'll still get
1468                             // the shutdown complete notification. If we
1469                             // don't, we'll timeout and force release.
1470                             sendErrorResponse = false;
1471                         }
1472                         // fall-thru
1473                         case STOPPING:
1474                         {
1475                             if (mFlags & kFlagSawMediaServerDie) {
1476                                 // MediaServer died, there definitely won't
1477                                 // be a shutdown complete notification after
1478                                 // all.
1479 
1480                                 // note that we're directly going from
1481                                 // STOPPING->UNINITIALIZED, instead of the
1482                                 // usual STOPPING->INITIALIZED state.
1483                                 setState(UNINITIALIZED);
1484                                 if (mState == RELEASING) {
1485                                     mComponentName.clear();
1486                                 }
1487                                 (new AMessage)->postReply(mReplyID);
1488                                 sendErrorResponse = false;
1489                             }
1490                             break;
1491                         }
1492 
1493                         case FLUSHING:
1494                         {
1495                             if (actionCode == ACTION_CODE_FATAL) {
1496                                 mAnalyticsItem->setInt32(kCodecError, err);
1497                                 mAnalyticsItem->setInt32(kCodecErrorState, mState);
1498                                 flushAnalyticsItem();
1499                                 initAnalyticsItem();
1500 
1501                                 setState(UNINITIALIZED);
1502                             } else {
1503                                 setState(
1504                                         (mFlags & kFlagIsAsync) ? FLUSHED : STARTED);
1505                             }
1506                             break;
1507                         }
1508 
1509                         case FLUSHED:
1510                         case STARTED:
1511                         {
1512                             sendErrorResponse = false;
1513 
1514                             setStickyError(err);
1515                             postActivityNotificationIfPossible();
1516 
1517                             cancelPendingDequeueOperations();
1518 
1519                             if (mFlags & kFlagIsAsync) {
1520                                 onError(err, actionCode);
1521                             }
1522                             switch (actionCode) {
1523                             case ACTION_CODE_TRANSIENT:
1524                                 break;
1525                             case ACTION_CODE_RECOVERABLE:
1526                                 setState(INITIALIZED);
1527                                 break;
1528                             default:
1529                                 mAnalyticsItem->setInt32(kCodecError, err);
1530                                 mAnalyticsItem->setInt32(kCodecErrorState, mState);
1531                                 flushAnalyticsItem();
1532                                 initAnalyticsItem();
1533                                 setState(UNINITIALIZED);
1534                                 break;
1535                             }
1536                             break;
1537                         }
1538 
1539                         default:
1540                         {
1541                             sendErrorResponse = false;
1542 
1543                             setStickyError(err);
1544                             postActivityNotificationIfPossible();
1545 
1546                             // actionCode in an uninitialized state is always fatal.
1547                             if (mState == UNINITIALIZED) {
1548                                 actionCode = ACTION_CODE_FATAL;
1549                             }
1550                             if (mFlags & kFlagIsAsync) {
1551                                 onError(err, actionCode);
1552                             }
1553                             switch (actionCode) {
1554                             case ACTION_CODE_TRANSIENT:
1555                                 break;
1556                             case ACTION_CODE_RECOVERABLE:
1557                                 setState(INITIALIZED);
1558                                 break;
1559                             default:
1560                                 setState(UNINITIALIZED);
1561                                 break;
1562                             }
1563                             break;
1564                         }
1565                     }
1566 
1567                     if (sendErrorResponse) {
1568                         PostReplyWithError(mReplyID, err);
1569                     }
1570                     break;
1571                 }
1572 
1573                 case kWhatComponentAllocated:
1574                 {
1575                     CHECK_EQ(mState, INITIALIZING);
1576                     setState(INITIALIZED);
1577                     mFlags |= kFlagIsComponentAllocated;
1578 
1579                     CHECK(msg->findString("componentName", &mComponentName));
1580 
1581                     if (mComponentName.c_str()) {
1582                         mAnalyticsItem->setCString(kCodecCodec, mComponentName.c_str());
1583                     }
1584 
1585                     if (mComponentName.startsWith("OMX.google.")) {
1586                         mFlags |= kFlagUsesSoftwareRenderer;
1587                     } else {
1588                         mFlags &= ~kFlagUsesSoftwareRenderer;
1589                     }
1590 
1591                     MediaResource::Type resourceType;
1592                     if (mComponentName.endsWith(".secure")) {
1593                         mFlags |= kFlagIsSecure;
1594                         resourceType = MediaResource::kSecureCodec;
1595                         mAnalyticsItem->setInt32(kCodecSecure, 1);
1596                     } else {
1597                         mFlags &= ~kFlagIsSecure;
1598                         resourceType = MediaResource::kNonSecureCodec;
1599                         mAnalyticsItem->setInt32(kCodecSecure, 0);
1600                     }
1601 
1602                     if (mIsVideo) {
1603                         // audio codec is currently ignored.
1604                         addResource(resourceType, MediaResource::kVideoCodec, 1);
1605                     }
1606 
1607                     (new AMessage)->postReply(mReplyID);
1608                     break;
1609                 }
1610 
1611                 case kWhatComponentConfigured:
1612                 {
1613                     if (mState == UNINITIALIZED || mState == INITIALIZED) {
1614                         // In case a kWhatError message came in and replied with error,
1615                         // we log a warning and ignore.
1616                         ALOGW("configure interrupted by error, current state %d", mState);
1617                         break;
1618                     }
1619                     CHECK_EQ(mState, CONFIGURING);
1620 
1621                     // reset input surface flag
1622                     mHaveInputSurface = false;
1623 
1624                     CHECK(msg->findMessage("input-format", &mInputFormat));
1625                     CHECK(msg->findMessage("output-format", &mOutputFormat));
1626                     ALOGV("[%s] configured as input format: %s, output format: %s",
1627                             mComponentName.c_str(),
1628                             mInputFormat->debugString(4).c_str(),
1629                             mOutputFormat->debugString(4).c_str());
1630                     int32_t usingSwRenderer;
1631                     if (mOutputFormat->findInt32("using-sw-renderer", &usingSwRenderer)
1632                             && usingSwRenderer) {
1633                         mFlags |= kFlagUsesSoftwareRenderer;
1634                     }
1635                     setState(CONFIGURED);
1636                     (new AMessage)->postReply(mReplyID);
1637 
1638                     // augment our media metrics info, now that we know more things
1639                     if (mAnalyticsItem != NULL) {
1640                         sp<AMessage> format;
1641                         if (mConfigureMsg != NULL &&
1642                             mConfigureMsg->findMessage("format", &format)) {
1643                                 // format includes: mime
1644                                 AString mime;
1645                                 if (format->findString("mime", &mime)) {
1646                                     mAnalyticsItem->setCString(kCodecMime, mime.c_str());
1647                                 }
1648                             }
1649                     }
1650                     break;
1651                 }
1652 
1653                 case kWhatInputSurfaceCreated:
1654                 {
1655                     // response to initiateCreateInputSurface()
1656                     status_t err = NO_ERROR;
1657                     sp<AMessage> response = new AMessage;
1658                     if (!msg->findInt32("err", &err)) {
1659                         sp<RefBase> obj;
1660                         msg->findObject("input-surface", &obj);
1661                         CHECK(msg->findMessage("input-format", &mInputFormat));
1662                         CHECK(msg->findMessage("output-format", &mOutputFormat));
1663                         ALOGV("[%s] input surface created as input format: %s, output format: %s",
1664                                 mComponentName.c_str(),
1665                                 mInputFormat->debugString(4).c_str(),
1666                                 mOutputFormat->debugString(4).c_str());
1667                         CHECK(obj != NULL);
1668                         response->setObject("input-surface", obj);
1669                         mHaveInputSurface = true;
1670                     } else {
1671                         response->setInt32("err", err);
1672                     }
1673                     response->postReply(mReplyID);
1674                     break;
1675                 }
1676 
1677                 case kWhatInputSurfaceAccepted:
1678                 {
1679                     // response to initiateSetInputSurface()
1680                     status_t err = NO_ERROR;
1681                     sp<AMessage> response = new AMessage();
1682                     if (!msg->findInt32("err", &err)) {
1683                         CHECK(msg->findMessage("input-format", &mInputFormat));
1684                         CHECK(msg->findMessage("output-format", &mOutputFormat));
1685                         mHaveInputSurface = true;
1686                     } else {
1687                         response->setInt32("err", err);
1688                     }
1689                     response->postReply(mReplyID);
1690                     break;
1691                 }
1692 
1693                 case kWhatSignaledInputEOS:
1694                 {
1695                     // response to signalEndOfInputStream()
1696                     sp<AMessage> response = new AMessage;
1697                     status_t err;
1698                     if (msg->findInt32("err", &err)) {
1699                         response->setInt32("err", err);
1700                     }
1701                     response->postReply(mReplyID);
1702                     break;
1703                 }
1704 
1705                 case kWhatStartCompleted:
1706                 {
1707                     CHECK_EQ(mState, STARTING);
1708                     if (mIsVideo) {
1709                         addResource(
1710                                 MediaResource::kGraphicMemory,
1711                                 MediaResource::kUnspecifiedSubType,
1712                                 getGraphicBufferSize());
1713                     }
1714                     setState(STARTED);
1715                     (new AMessage)->postReply(mReplyID);
1716                     break;
1717                 }
1718 
1719                 case kWhatOutputBuffersChanged:
1720                 {
1721                     mFlags |= kFlagOutputBuffersChanged;
1722                     postActivityNotificationIfPossible();
1723                     break;
1724                 }
1725 
1726                 case kWhatOutputFramesRendered:
1727                 {
1728                     // ignore these in all states except running, and check that we have a
1729                     // notification set
1730                     if (mState == STARTED && mOnFrameRenderedNotification != NULL) {
1731                         sp<AMessage> notify = mOnFrameRenderedNotification->dup();
1732                         notify->setMessage("data", msg);
1733                         notify->post();
1734                     }
1735                     break;
1736                 }
1737 
1738                 case kWhatFillThisBuffer:
1739                 {
1740                     /* size_t index = */updateBuffers(kPortIndexInput, msg);
1741 
1742                     if (mState == FLUSHING
1743                             || mState == STOPPING
1744                             || mState == RELEASING) {
1745                         returnBuffersToCodecOnPort(kPortIndexInput);
1746                         break;
1747                     }
1748 
1749                     if (!mCSD.empty()) {
1750                         ssize_t index = dequeuePortBuffer(kPortIndexInput);
1751                         CHECK_GE(index, 0);
1752 
1753                         // If codec specific data had been specified as
1754                         // part of the format in the call to configure and
1755                         // if there's more csd left, we submit it here
1756                         // clients only get access to input buffers once
1757                         // this data has been exhausted.
1758 
1759                         status_t err = queueCSDInputBuffer(index);
1760 
1761                         if (err != OK) {
1762                             ALOGE("queueCSDInputBuffer failed w/ error %d",
1763                                   err);
1764 
1765                             setStickyError(err);
1766                             postActivityNotificationIfPossible();
1767 
1768                             cancelPendingDequeueOperations();
1769                         }
1770                         break;
1771                     }
1772 
1773                     if (mFlags & kFlagIsAsync) {
1774                         if (!mHaveInputSurface) {
1775                             if (mState == FLUSHED) {
1776                                 mHavePendingInputBuffers = true;
1777                             } else {
1778                                 onInputBufferAvailable();
1779                             }
1780                         }
1781                     } else if (mFlags & kFlagDequeueInputPending) {
1782                         CHECK(handleDequeueInputBuffer(mDequeueInputReplyID));
1783 
1784                         ++mDequeueInputTimeoutGeneration;
1785                         mFlags &= ~kFlagDequeueInputPending;
1786                         mDequeueInputReplyID = 0;
1787                     } else {
1788                         postActivityNotificationIfPossible();
1789                     }
1790                     break;
1791                 }
1792 
1793                 case kWhatDrainThisBuffer:
1794                 {
1795                     /* size_t index = */updateBuffers(kPortIndexOutput, msg);
1796 
1797                     if (mState == FLUSHING
1798                             || mState == STOPPING
1799                             || mState == RELEASING) {
1800                         returnBuffersToCodecOnPort(kPortIndexOutput);
1801                         break;
1802                     }
1803 
1804                     sp<RefBase> obj;
1805                     CHECK(msg->findObject("buffer", &obj));
1806                     sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
1807 
1808                     if (mOutputFormat != buffer->format()) {
1809                         mOutputFormat = buffer->format();
1810                         ALOGV("[%s] output format changed to: %s",
1811                                 mComponentName.c_str(), mOutputFormat->debugString(4).c_str());
1812 
1813                         if (mSoftRenderer == NULL &&
1814                                 mSurface != NULL &&
1815                                 (mFlags & kFlagUsesSoftwareRenderer)) {
1816                             AString mime;
1817                             CHECK(mOutputFormat->findString("mime", &mime));
1818 
1819                             // TODO: propagate color aspects to software renderer to allow better
1820                             // color conversion to RGB. For now, just mark dataspace for YUV
1821                             // rendering.
1822                             int32_t dataSpace;
1823                             if (mOutputFormat->findInt32("android._dataspace", &dataSpace)) {
1824                                 ALOGD("[%s] setting dataspace on output surface to #%x",
1825                                         mComponentName.c_str(), dataSpace);
1826                                 int err = native_window_set_buffers_data_space(
1827                                         mSurface.get(), (android_dataspace)dataSpace);
1828                                 ALOGW_IF(err != 0, "failed to set dataspace on surface (%d)", err);
1829                             }
1830 
1831                             if (mime.startsWithIgnoreCase("video/")) {
1832                                 mSoftRenderer = new SoftwareRenderer(mSurface, mRotationDegrees);
1833                             }
1834                         }
1835 
1836                         if (mFlags & kFlagIsEncoder) {
1837                             // Before we announce the format change we should
1838                             // collect codec specific data and amend the output
1839                             // format as necessary.
1840                             int32_t flags = 0;
1841                             (void) buffer->meta()->findInt32("flags", &flags);
1842                             if (flags & BUFFER_FLAG_CODECCONFIG) {
1843                                 status_t err =
1844                                     amendOutputFormatWithCodecSpecificData(buffer);
1845 
1846                                 if (err != OK) {
1847                                     ALOGE("Codec spit out malformed codec "
1848                                           "specific data!");
1849                                 }
1850                             }
1851                         }
1852 
1853                         if (mFlags & kFlagIsAsync) {
1854                             onOutputFormatChanged();
1855                         } else {
1856                             mFlags |= kFlagOutputFormatChanged;
1857                             postActivityNotificationIfPossible();
1858                         }
1859 
1860                         // Notify mCrypto of video resolution changes
1861                         if (mCrypto != NULL) {
1862                             int32_t left, top, right, bottom, width, height;
1863                             if (mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) {
1864                                 mCrypto->notifyResolution(right - left + 1, bottom - top + 1);
1865                             } else if (mOutputFormat->findInt32("width", &width)
1866                                     && mOutputFormat->findInt32("height", &height)) {
1867                                 mCrypto->notifyResolution(width, height);
1868                             }
1869                         }
1870                     }
1871 
1872                     if (mFlags & kFlagIsAsync) {
1873                         onOutputBufferAvailable();
1874                     } else if (mFlags & kFlagDequeueOutputPending) {
1875                         CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID));
1876 
1877                         ++mDequeueOutputTimeoutGeneration;
1878                         mFlags &= ~kFlagDequeueOutputPending;
1879                         mDequeueOutputReplyID = 0;
1880                     } else {
1881                         postActivityNotificationIfPossible();
1882                     }
1883 
1884                     break;
1885                 }
1886 
1887                 case kWhatEOS:
1888                 {
1889                     // We already notify the client of this by using the
1890                     // corresponding flag in "onOutputBufferReady".
1891                     break;
1892                 }
1893 
1894                 case kWhatStopCompleted:
1895                 {
1896                     if (mState != STOPPING) {
1897                         ALOGW("Received kWhatStopCompleted in state %d", mState);
1898                         break;
1899                     }
1900                     setState(INITIALIZED);
1901                     (new AMessage)->postReply(mReplyID);
1902                     break;
1903                 }
1904 
1905                 case kWhatReleaseCompleted:
1906                 {
1907                     if (mState != RELEASING) {
1908                         ALOGW("Received kWhatReleaseCompleted in state %d", mState);
1909                         break;
1910                     }
1911                     setState(UNINITIALIZED);
1912                     mComponentName.clear();
1913 
1914                     mFlags &= ~kFlagIsComponentAllocated;
1915 
1916                     mResourceManagerService->removeResource(getId(mResourceManagerClient));
1917 
1918                     (new AMessage)->postReply(mReplyID);
1919                     break;
1920                 }
1921 
1922                 case kWhatFlushCompleted:
1923                 {
1924                     if (mState != FLUSHING) {
1925                         ALOGW("received FlushCompleted message in state %d",
1926                                 mState);
1927                         break;
1928                     }
1929 
1930                     if (mFlags & kFlagIsAsync) {
1931                         setState(FLUSHED);
1932                     } else {
1933                         setState(STARTED);
1934                         mCodec->signalResume();
1935                     }
1936 
1937                     (new AMessage)->postReply(mReplyID);
1938                     break;
1939                 }
1940 
1941                 default:
1942                     TRESPASS();
1943             }
1944             break;
1945         }
1946 
1947         case kWhatInit:
1948         {
1949             sp<AReplyToken> replyID;
1950             CHECK(msg->senderAwaitsResponse(&replyID));
1951 
1952             if (mState != UNINITIALIZED) {
1953                 PostReplyWithError(replyID, INVALID_OPERATION);
1954                 break;
1955             }
1956 
1957             mReplyID = replyID;
1958             setState(INITIALIZING);
1959 
1960             AString name;
1961             CHECK(msg->findString("name", &name));
1962 
1963             int32_t nameIsType;
1964             int32_t encoder = false;
1965             CHECK(msg->findInt32("nameIsType", &nameIsType));
1966             if (nameIsType) {
1967                 CHECK(msg->findInt32("encoder", &encoder));
1968             }
1969 
1970             sp<AMessage> format = new AMessage;
1971 
1972             if (nameIsType) {
1973                 format->setString("mime", name.c_str());
1974                 format->setInt32("encoder", encoder);
1975             } else {
1976                 format->setString("componentName", name.c_str());
1977             }
1978 
1979             mCodec->initiateAllocateComponent(format);
1980             break;
1981         }
1982 
1983         case kWhatSetNotification:
1984         {
1985             sp<AMessage> notify;
1986             if (msg->findMessage("on-frame-rendered", &notify)) {
1987                 mOnFrameRenderedNotification = notify;
1988             }
1989             break;
1990         }
1991 
1992         case kWhatSetCallback:
1993         {
1994             sp<AReplyToken> replyID;
1995             CHECK(msg->senderAwaitsResponse(&replyID));
1996 
1997             if (mState == UNINITIALIZED
1998                     || mState == INITIALIZING
1999                     || isExecuting()) {
2000                 // callback can't be set after codec is executing,
2001                 // or before it's initialized (as the callback
2002                 // will be cleared when it goes to INITIALIZED)
2003                 PostReplyWithError(replyID, INVALID_OPERATION);
2004                 break;
2005             }
2006 
2007             sp<AMessage> callback;
2008             CHECK(msg->findMessage("callback", &callback));
2009 
2010             mCallback = callback;
2011 
2012             if (mCallback != NULL) {
2013                 ALOGI("MediaCodec will operate in async mode");
2014                 mFlags |= kFlagIsAsync;
2015             } else {
2016                 mFlags &= ~kFlagIsAsync;
2017             }
2018 
2019             sp<AMessage> response = new AMessage;
2020             response->postReply(replyID);
2021             break;
2022         }
2023 
2024         case kWhatConfigure:
2025         {
2026             sp<AReplyToken> replyID;
2027             CHECK(msg->senderAwaitsResponse(&replyID));
2028 
2029             if (mState != INITIALIZED) {
2030                 PostReplyWithError(replyID, INVALID_OPERATION);
2031                 break;
2032             }
2033 
2034             sp<RefBase> obj;
2035             CHECK(msg->findObject("surface", &obj));
2036 
2037             sp<AMessage> format;
2038             CHECK(msg->findMessage("format", &format));
2039 
2040             int32_t push;
2041             if (msg->findInt32("push-blank-buffers-on-shutdown", &push) && push != 0) {
2042                 mFlags |= kFlagPushBlankBuffersOnShutdown;
2043             }
2044 
2045             if (obj != NULL) {
2046                 format->setObject("native-window", obj);
2047                 status_t err = handleSetSurface(static_cast<Surface *>(obj.get()));
2048                 if (err != OK) {
2049                     PostReplyWithError(replyID, err);
2050                     break;
2051                 }
2052             } else {
2053                 handleSetSurface(NULL);
2054             }
2055 
2056             mReplyID = replyID;
2057             setState(CONFIGURING);
2058 
2059             void *crypto;
2060             if (!msg->findPointer("crypto", &crypto)) {
2061                 crypto = NULL;
2062             }
2063 
2064             ALOGV("kWhatConfigure: Old mCrypto: %p (%d)",
2065                     mCrypto.get(), (mCrypto != NULL ? mCrypto->getStrongCount() : 0));
2066 
2067             mCrypto = static_cast<ICrypto *>(crypto);
2068             mBufferChannel->setCrypto(mCrypto);
2069 
2070             ALOGV("kWhatConfigure: New mCrypto: %p (%d)",
2071                     mCrypto.get(), (mCrypto != NULL ? mCrypto->getStrongCount() : 0));
2072 
2073             void *descrambler;
2074             if (!msg->findPointer("descrambler", &descrambler)) {
2075                 descrambler = NULL;
2076             }
2077 
2078             mDescrambler = static_cast<IDescrambler *>(descrambler);
2079             mBufferChannel->setDescrambler(mDescrambler);
2080 
2081             uint32_t flags;
2082             CHECK(msg->findInt32("flags", (int32_t *)&flags));
2083 
2084             if (flags & CONFIGURE_FLAG_ENCODE) {
2085                 format->setInt32("encoder", true);
2086                 mFlags |= kFlagIsEncoder;
2087             }
2088 
2089             extractCSD(format);
2090 
2091             mCodec->initiateConfigureComponent(format);
2092             break;
2093         }
2094 
2095         case kWhatSetSurface:
2096         {
2097             sp<AReplyToken> replyID;
2098             CHECK(msg->senderAwaitsResponse(&replyID));
2099 
2100             status_t err = OK;
2101 
2102             switch (mState) {
2103                 case CONFIGURED:
2104                 case STARTED:
2105                 case FLUSHED:
2106                 {
2107                     sp<RefBase> obj;
2108                     (void)msg->findObject("surface", &obj);
2109                     sp<Surface> surface = static_cast<Surface *>(obj.get());
2110                     if (mSurface == NULL) {
2111                         // do not support setting surface if it was not set
2112                         err = INVALID_OPERATION;
2113                     } else if (obj == NULL) {
2114                         // do not support unsetting surface
2115                         err = BAD_VALUE;
2116                     } else {
2117                         err = connectToSurface(surface);
2118                         if (err == ALREADY_EXISTS) {
2119                             // reconnecting to same surface
2120                             err = OK;
2121                         } else {
2122                             if (err == OK) {
2123                                 if (mFlags & kFlagUsesSoftwareRenderer) {
2124                                     if (mSoftRenderer != NULL
2125                                             && (mFlags & kFlagPushBlankBuffersOnShutdown)) {
2126                                         pushBlankBuffersToNativeWindow(mSurface.get());
2127                                     }
2128                                     mSoftRenderer = new SoftwareRenderer(surface);
2129                                     // TODO: check if this was successful
2130                                 } else {
2131                                     err = mCodec->setSurface(surface);
2132                                 }
2133                             }
2134                             if (err == OK) {
2135                                 (void)disconnectFromSurface();
2136                                 mSurface = surface;
2137                             }
2138                         }
2139                     }
2140                     break;
2141                 }
2142 
2143                 default:
2144                     err = INVALID_OPERATION;
2145                     break;
2146             }
2147 
2148             PostReplyWithError(replyID, err);
2149             break;
2150         }
2151 
2152         case kWhatCreateInputSurface:
2153         case kWhatSetInputSurface:
2154         {
2155             sp<AReplyToken> replyID;
2156             CHECK(msg->senderAwaitsResponse(&replyID));
2157 
2158             // Must be configured, but can't have been started yet.
2159             if (mState != CONFIGURED) {
2160                 PostReplyWithError(replyID, INVALID_OPERATION);
2161                 break;
2162             }
2163 
2164             mReplyID = replyID;
2165             if (msg->what() == kWhatCreateInputSurface) {
2166                 mCodec->initiateCreateInputSurface();
2167             } else {
2168                 sp<RefBase> obj;
2169                 CHECK(msg->findObject("input-surface", &obj));
2170 
2171                 mCodec->initiateSetInputSurface(
2172                         static_cast<PersistentSurface *>(obj.get()));
2173             }
2174             break;
2175         }
2176         case kWhatStart:
2177         {
2178             sp<AReplyToken> replyID;
2179             CHECK(msg->senderAwaitsResponse(&replyID));
2180 
2181             if (mState == FLUSHED) {
2182                 setState(STARTED);
2183                 if (mHavePendingInputBuffers) {
2184                     onInputBufferAvailable();
2185                     mHavePendingInputBuffers = false;
2186                 }
2187                 mCodec->signalResume();
2188                 PostReplyWithError(replyID, OK);
2189                 break;
2190             } else if (mState != CONFIGURED) {
2191                 PostReplyWithError(replyID, INVALID_OPERATION);
2192                 break;
2193             }
2194 
2195             mReplyID = replyID;
2196             setState(STARTING);
2197 
2198             mCodec->initiateStart();
2199             break;
2200         }
2201 
2202         case kWhatStop:
2203         case kWhatRelease:
2204         {
2205             State targetState =
2206                 (msg->what() == kWhatStop) ? INITIALIZED : UNINITIALIZED;
2207 
2208             sp<AReplyToken> replyID;
2209             CHECK(msg->senderAwaitsResponse(&replyID));
2210 
2211             // already stopped/released
2212             if (mState == UNINITIALIZED && mReleasedByResourceManager) {
2213                 sp<AMessage> response = new AMessage;
2214                 response->setInt32("err", OK);
2215                 response->postReply(replyID);
2216                 break;
2217             }
2218 
2219             int32_t reclaimed = 0;
2220             msg->findInt32("reclaimed", &reclaimed);
2221             if (reclaimed) {
2222                 mReleasedByResourceManager = true;
2223 
2224                 int32_t force = 0;
2225                 msg->findInt32("force", &force);
2226                 if (!force && hasPendingBuffer()) {
2227                     ALOGW("Can't reclaim codec right now due to pending buffers.");
2228 
2229                     // return WOULD_BLOCK to ask resource manager to retry later.
2230                     sp<AMessage> response = new AMessage;
2231                     response->setInt32("err", WOULD_BLOCK);
2232                     response->postReply(replyID);
2233 
2234                     // notify the async client
2235                     if (mFlags & kFlagIsAsync) {
2236                         onError(DEAD_OBJECT, ACTION_CODE_FATAL);
2237                     }
2238                     break;
2239                 }
2240             }
2241 
2242             bool isReleasingAllocatedComponent =
2243                     (mFlags & kFlagIsComponentAllocated) && targetState == UNINITIALIZED;
2244             if (!isReleasingAllocatedComponent // See 1
2245                     && mState != INITIALIZED
2246                     && mState != CONFIGURED && !isExecuting()) {
2247                 // 1) Permit release to shut down the component if allocated.
2248                 //
2249                 // 2) We may be in "UNINITIALIZED" state already and
2250                 // also shutdown the encoder/decoder without the
2251                 // client being aware of this if media server died while
2252                 // we were being stopped. The client would assume that
2253                 // after stop() returned, it would be safe to call release()
2254                 // and it should be in this case, no harm to allow a release()
2255                 // if we're already uninitialized.
2256                 sp<AMessage> response = new AMessage;
2257                 // TODO: we shouldn't throw an exception for stop/release. Change this to wait until
2258                 // the previous stop/release completes and then reply with OK.
2259                 status_t err = mState == targetState ? OK : INVALID_OPERATION;
2260                 response->setInt32("err", err);
2261                 if (err == OK && targetState == UNINITIALIZED) {
2262                     mComponentName.clear();
2263                 }
2264                 response->postReply(replyID);
2265                 break;
2266             }
2267 
2268             // If we're flushing, or we're stopping but received a release
2269             // request, post the reply for the pending call first, and consider
2270             // it done. The reply token will be replaced after this, and we'll
2271             // no longer be able to reply.
2272             if (mState == FLUSHING || mState == STOPPING) {
2273                 (new AMessage)->postReply(mReplyID);
2274             }
2275 
2276             if (mFlags & kFlagSawMediaServerDie) {
2277                 // It's dead, Jim. Don't expect initiateShutdown to yield
2278                 // any useful results now...
2279                 setState(UNINITIALIZED);
2280                 if (targetState == UNINITIALIZED) {
2281                     mComponentName.clear();
2282                 }
2283                 (new AMessage)->postReply(replyID);
2284                 break;
2285             }
2286 
2287             // If we already have an error, component may not be able to
2288             // complete the shutdown properly. If we're stopping, post the
2289             // reply now with an error to unblock the client, client can
2290             // release after the failure (instead of ANR).
2291             if (msg->what() == kWhatStop && (mFlags & kFlagStickyError)) {
2292                 PostReplyWithError(replyID, getStickyError());
2293                 break;
2294             }
2295 
2296             mReplyID = replyID;
2297             setState(msg->what() == kWhatStop ? STOPPING : RELEASING);
2298 
2299             mCodec->initiateShutdown(
2300                     msg->what() == kWhatStop /* keepComponentAllocated */);
2301 
2302             returnBuffersToCodec(reclaimed);
2303 
2304             if (mSoftRenderer != NULL && (mFlags & kFlagPushBlankBuffersOnShutdown)) {
2305                 pushBlankBuffersToNativeWindow(mSurface.get());
2306             }
2307 
2308             break;
2309         }
2310 
2311         case kWhatDequeueInputBuffer:
2312         {
2313             sp<AReplyToken> replyID;
2314             CHECK(msg->senderAwaitsResponse(&replyID));
2315 
2316             if (mFlags & kFlagIsAsync) {
2317                 ALOGE("dequeueOutputBuffer can't be used in async mode");
2318                 PostReplyWithError(replyID, INVALID_OPERATION);
2319                 break;
2320             }
2321 
2322             if (mHaveInputSurface) {
2323                 ALOGE("dequeueInputBuffer can't be used with input surface");
2324                 PostReplyWithError(replyID, INVALID_OPERATION);
2325                 break;
2326             }
2327 
2328             if (handleDequeueInputBuffer(replyID, true /* new request */)) {
2329                 break;
2330             }
2331 
2332             int64_t timeoutUs;
2333             CHECK(msg->findInt64("timeoutUs", &timeoutUs));
2334 
2335             if (timeoutUs == 0ll) {
2336                 PostReplyWithError(replyID, -EAGAIN);
2337                 break;
2338             }
2339 
2340             mFlags |= kFlagDequeueInputPending;
2341             mDequeueInputReplyID = replyID;
2342 
2343             if (timeoutUs > 0ll) {
2344                 sp<AMessage> timeoutMsg =
2345                     new AMessage(kWhatDequeueInputTimedOut, this);
2346                 timeoutMsg->setInt32(
2347                         "generation", ++mDequeueInputTimeoutGeneration);
2348                 timeoutMsg->post(timeoutUs);
2349             }
2350             break;
2351         }
2352 
2353         case kWhatDequeueInputTimedOut:
2354         {
2355             int32_t generation;
2356             CHECK(msg->findInt32("generation", &generation));
2357 
2358             if (generation != mDequeueInputTimeoutGeneration) {
2359                 // Obsolete
2360                 break;
2361             }
2362 
2363             CHECK(mFlags & kFlagDequeueInputPending);
2364 
2365             PostReplyWithError(mDequeueInputReplyID, -EAGAIN);
2366 
2367             mFlags &= ~kFlagDequeueInputPending;
2368             mDequeueInputReplyID = 0;
2369             break;
2370         }
2371 
2372         case kWhatQueueInputBuffer:
2373         {
2374             sp<AReplyToken> replyID;
2375             CHECK(msg->senderAwaitsResponse(&replyID));
2376 
2377             if (!isExecuting()) {
2378                 PostReplyWithError(replyID, INVALID_OPERATION);
2379                 break;
2380             } else if (mFlags & kFlagStickyError) {
2381                 PostReplyWithError(replyID, getStickyError());
2382                 break;
2383             }
2384 
2385             status_t err = onQueueInputBuffer(msg);
2386 
2387             PostReplyWithError(replyID, err);
2388             break;
2389         }
2390 
2391         case kWhatDequeueOutputBuffer:
2392         {
2393             sp<AReplyToken> replyID;
2394             CHECK(msg->senderAwaitsResponse(&replyID));
2395 
2396             if (mFlags & kFlagIsAsync) {
2397                 ALOGE("dequeueOutputBuffer can't be used in async mode");
2398                 PostReplyWithError(replyID, INVALID_OPERATION);
2399                 break;
2400             }
2401 
2402             if (handleDequeueOutputBuffer(replyID, true /* new request */)) {
2403                 break;
2404             }
2405 
2406             int64_t timeoutUs;
2407             CHECK(msg->findInt64("timeoutUs", &timeoutUs));
2408 
2409             if (timeoutUs == 0ll) {
2410                 PostReplyWithError(replyID, -EAGAIN);
2411                 break;
2412             }
2413 
2414             mFlags |= kFlagDequeueOutputPending;
2415             mDequeueOutputReplyID = replyID;
2416 
2417             if (timeoutUs > 0ll) {
2418                 sp<AMessage> timeoutMsg =
2419                     new AMessage(kWhatDequeueOutputTimedOut, this);
2420                 timeoutMsg->setInt32(
2421                         "generation", ++mDequeueOutputTimeoutGeneration);
2422                 timeoutMsg->post(timeoutUs);
2423             }
2424             break;
2425         }
2426 
2427         case kWhatDequeueOutputTimedOut:
2428         {
2429             int32_t generation;
2430             CHECK(msg->findInt32("generation", &generation));
2431 
2432             if (generation != mDequeueOutputTimeoutGeneration) {
2433                 // Obsolete
2434                 break;
2435             }
2436 
2437             CHECK(mFlags & kFlagDequeueOutputPending);
2438 
2439             PostReplyWithError(mDequeueOutputReplyID, -EAGAIN);
2440 
2441             mFlags &= ~kFlagDequeueOutputPending;
2442             mDequeueOutputReplyID = 0;
2443             break;
2444         }
2445 
2446         case kWhatReleaseOutputBuffer:
2447         {
2448             sp<AReplyToken> replyID;
2449             CHECK(msg->senderAwaitsResponse(&replyID));
2450 
2451             if (!isExecuting()) {
2452                 PostReplyWithError(replyID, INVALID_OPERATION);
2453                 break;
2454             } else if (mFlags & kFlagStickyError) {
2455                 PostReplyWithError(replyID, getStickyError());
2456                 break;
2457             }
2458 
2459             status_t err = onReleaseOutputBuffer(msg);
2460 
2461             PostReplyWithError(replyID, err);
2462             break;
2463         }
2464 
2465         case kWhatSignalEndOfInputStream:
2466         {
2467             sp<AReplyToken> replyID;
2468             CHECK(msg->senderAwaitsResponse(&replyID));
2469 
2470             if (!isExecuting() || !mHaveInputSurface) {
2471                 PostReplyWithError(replyID, INVALID_OPERATION);
2472                 break;
2473             } else if (mFlags & kFlagStickyError) {
2474                 PostReplyWithError(replyID, getStickyError());
2475                 break;
2476             }
2477 
2478             mReplyID = replyID;
2479             mCodec->signalEndOfInputStream();
2480             break;
2481         }
2482 
2483         case kWhatGetBuffers:
2484         {
2485             sp<AReplyToken> replyID;
2486             CHECK(msg->senderAwaitsResponse(&replyID));
2487             if (!isExecuting() || (mFlags & kFlagIsAsync)) {
2488                 PostReplyWithError(replyID, INVALID_OPERATION);
2489                 break;
2490             } else if (mFlags & kFlagStickyError) {
2491                 PostReplyWithError(replyID, getStickyError());
2492                 break;
2493             }
2494 
2495             int32_t portIndex;
2496             CHECK(msg->findInt32("portIndex", &portIndex));
2497 
2498             Vector<sp<MediaCodecBuffer> > *dstBuffers;
2499             CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
2500 
2501             dstBuffers->clear();
2502             // If we're using input surface (either non-persistent created by
2503             // createInputSurface(), or persistent set by setInputSurface()),
2504             // give the client an empty input buffers array.
2505             if (portIndex != kPortIndexInput || !mHaveInputSurface) {
2506                 if (portIndex == kPortIndexInput) {
2507                     mBufferChannel->getInputBufferArray(dstBuffers);
2508                 } else {
2509                     mBufferChannel->getOutputBufferArray(dstBuffers);
2510                 }
2511             }
2512 
2513             (new AMessage)->postReply(replyID);
2514             break;
2515         }
2516 
2517         case kWhatFlush:
2518         {
2519             sp<AReplyToken> replyID;
2520             CHECK(msg->senderAwaitsResponse(&replyID));
2521 
2522             if (!isExecuting()) {
2523                 PostReplyWithError(replyID, INVALID_OPERATION);
2524                 break;
2525             } else if (mFlags & kFlagStickyError) {
2526                 PostReplyWithError(replyID, getStickyError());
2527                 break;
2528             }
2529 
2530             mReplyID = replyID;
2531             // TODO: skip flushing if already FLUSHED
2532             setState(FLUSHING);
2533 
2534             mCodec->signalFlush();
2535             returnBuffersToCodec();
2536             break;
2537         }
2538 
2539         case kWhatGetInputFormat:
2540         case kWhatGetOutputFormat:
2541         {
2542             sp<AMessage> format =
2543                 (msg->what() == kWhatGetOutputFormat ? mOutputFormat : mInputFormat);
2544 
2545             sp<AReplyToken> replyID;
2546             CHECK(msg->senderAwaitsResponse(&replyID));
2547 
2548             if ((mState != CONFIGURED && mState != STARTING &&
2549                  mState != STARTED && mState != FLUSHING &&
2550                  mState != FLUSHED)
2551                     || format == NULL) {
2552                 PostReplyWithError(replyID, INVALID_OPERATION);
2553                 break;
2554             } else if (mFlags & kFlagStickyError) {
2555                 PostReplyWithError(replyID, getStickyError());
2556                 break;
2557             }
2558 
2559             sp<AMessage> response = new AMessage;
2560             response->setMessage("format", format);
2561             response->postReply(replyID);
2562             break;
2563         }
2564 
2565         case kWhatRequestIDRFrame:
2566         {
2567             mCodec->signalRequestIDRFrame();
2568             break;
2569         }
2570 
2571         case kWhatRequestActivityNotification:
2572         {
2573             CHECK(mActivityNotify == NULL);
2574             CHECK(msg->findMessage("notify", &mActivityNotify));
2575 
2576             postActivityNotificationIfPossible();
2577             break;
2578         }
2579 
2580         case kWhatGetName:
2581         {
2582             sp<AReplyToken> replyID;
2583             CHECK(msg->senderAwaitsResponse(&replyID));
2584 
2585             if (mComponentName.empty()) {
2586                 PostReplyWithError(replyID, INVALID_OPERATION);
2587                 break;
2588             }
2589 
2590             sp<AMessage> response = new AMessage;
2591             response->setString("name", mComponentName.c_str());
2592             response->postReply(replyID);
2593             break;
2594         }
2595 
2596         case kWhatSetParameters:
2597         {
2598             sp<AReplyToken> replyID;
2599             CHECK(msg->senderAwaitsResponse(&replyID));
2600 
2601             sp<AMessage> params;
2602             CHECK(msg->findMessage("params", &params));
2603 
2604             status_t err = onSetParameters(params);
2605 
2606             PostReplyWithError(replyID, err);
2607             break;
2608         }
2609 
2610         case kWhatDrmReleaseCrypto:
2611         {
2612             onReleaseCrypto(msg);
2613             break;
2614         }
2615 
2616         default:
2617             TRESPASS();
2618     }
2619 }
2620 
extractCSD(const sp<AMessage> & format)2621 void MediaCodec::extractCSD(const sp<AMessage> &format) {
2622     mCSD.clear();
2623 
2624     size_t i = 0;
2625     for (;;) {
2626         sp<ABuffer> csd;
2627         if (!format->findBuffer(AStringPrintf("csd-%u", i).c_str(), &csd)) {
2628             break;
2629         }
2630         if (csd->size() == 0) {
2631             ALOGW("csd-%zu size is 0", i);
2632         }
2633 
2634         mCSD.push_back(csd);
2635         ++i;
2636     }
2637 
2638     ALOGV("Found %zu pieces of codec specific data.", mCSD.size());
2639 }
2640 
queueCSDInputBuffer(size_t bufferIndex)2641 status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) {
2642     CHECK(!mCSD.empty());
2643 
2644     const BufferInfo &info = mPortBuffers[kPortIndexInput][bufferIndex];
2645 
2646     sp<ABuffer> csd = *mCSD.begin();
2647     mCSD.erase(mCSD.begin());
2648 
2649     const sp<MediaCodecBuffer> &codecInputData = info.mData;
2650 
2651     if (csd->size() > codecInputData->capacity()) {
2652         return -EINVAL;
2653     }
2654     if (codecInputData->data() == NULL) {
2655         ALOGV("Input buffer %zu is not properly allocated", bufferIndex);
2656         return -EINVAL;
2657     }
2658 
2659     memcpy(codecInputData->data(), csd->data(), csd->size());
2660 
2661     AString errorDetailMsg;
2662 
2663     sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this);
2664     msg->setSize("index", bufferIndex);
2665     msg->setSize("offset", 0);
2666     msg->setSize("size", csd->size());
2667     msg->setInt64("timeUs", 0ll);
2668     msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG);
2669     msg->setPointer("errorDetailMsg", &errorDetailMsg);
2670 
2671     return onQueueInputBuffer(msg);
2672 }
2673 
setState(State newState)2674 void MediaCodec::setState(State newState) {
2675     if (newState == INITIALIZED || newState == UNINITIALIZED) {
2676         delete mSoftRenderer;
2677         mSoftRenderer = NULL;
2678 
2679         if ( mCrypto != NULL ) {
2680             ALOGV("setState: ~mCrypto: %p (%d)",
2681                     mCrypto.get(), (mCrypto != NULL ? mCrypto->getStrongCount() : 0));
2682         }
2683         mCrypto.clear();
2684         mDescrambler.clear();
2685         handleSetSurface(NULL);
2686 
2687         mInputFormat.clear();
2688         mOutputFormat.clear();
2689         mFlags &= ~kFlagOutputFormatChanged;
2690         mFlags &= ~kFlagOutputBuffersChanged;
2691         mFlags &= ~kFlagStickyError;
2692         mFlags &= ~kFlagIsEncoder;
2693         mFlags &= ~kFlagIsAsync;
2694         mStickyError = OK;
2695 
2696         mActivityNotify.clear();
2697         mCallback.clear();
2698     }
2699 
2700     if (newState == UNINITIALIZED) {
2701         // return any straggling buffers, e.g. if we got here on an error
2702         returnBuffersToCodec();
2703 
2704         // The component is gone, mediaserver's probably back up already
2705         // but should definitely be back up should we try to instantiate
2706         // another component.. and the cycle continues.
2707         mFlags &= ~kFlagSawMediaServerDie;
2708     }
2709 
2710     mState = newState;
2711 
2712     cancelPendingDequeueOperations();
2713 
2714     updateBatteryStat();
2715 }
2716 
returnBuffersToCodec(bool isReclaim)2717 void MediaCodec::returnBuffersToCodec(bool isReclaim) {
2718     returnBuffersToCodecOnPort(kPortIndexInput, isReclaim);
2719     returnBuffersToCodecOnPort(kPortIndexOutput, isReclaim);
2720 }
2721 
returnBuffersToCodecOnPort(int32_t portIndex,bool isReclaim)2722 void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex, bool isReclaim) {
2723     CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
2724     Mutex::Autolock al(mBufferLock);
2725 
2726     for (size_t i = 0; i < mPortBuffers[portIndex].size(); ++i) {
2727         BufferInfo *info = &mPortBuffers[portIndex][i];
2728 
2729         if (info->mData != nullptr) {
2730             sp<MediaCodecBuffer> buffer = info->mData;
2731             if (isReclaim && info->mOwnedByClient) {
2732                 ALOGD("port %d buffer %zu still owned by client when codec is reclaimed",
2733                         portIndex, i);
2734             } else {
2735                 info->mOwnedByClient = false;
2736                 info->mData.clear();
2737             }
2738             mBufferChannel->discardBuffer(buffer);
2739         }
2740     }
2741 
2742     mAvailPortBuffers[portIndex].clear();
2743 }
2744 
updateBuffers(int32_t portIndex,const sp<AMessage> & msg)2745 size_t MediaCodec::updateBuffers(
2746         int32_t portIndex, const sp<AMessage> &msg) {
2747     CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
2748     size_t index;
2749     CHECK(msg->findSize("index", &index));
2750     sp<RefBase> obj;
2751     CHECK(msg->findObject("buffer", &obj));
2752     sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
2753 
2754     {
2755         Mutex::Autolock al(mBufferLock);
2756         if (mPortBuffers[portIndex].size() <= index) {
2757             mPortBuffers[portIndex].resize(align(index + 1, kNumBuffersAlign));
2758         }
2759         mPortBuffers[portIndex][index].mData = buffer;
2760     }
2761     mAvailPortBuffers[portIndex].push_back(index);
2762 
2763     return index;
2764 }
2765 
onQueueInputBuffer(const sp<AMessage> & msg)2766 status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {
2767     size_t index;
2768     size_t offset;
2769     size_t size;
2770     int64_t timeUs;
2771     uint32_t flags;
2772     CHECK(msg->findSize("index", &index));
2773     CHECK(msg->findSize("offset", &offset));
2774     CHECK(msg->findInt64("timeUs", &timeUs));
2775     CHECK(msg->findInt32("flags", (int32_t *)&flags));
2776 
2777     const CryptoPlugin::SubSample *subSamples;
2778     size_t numSubSamples;
2779     const uint8_t *key;
2780     const uint8_t *iv;
2781     CryptoPlugin::Mode mode = CryptoPlugin::kMode_Unencrypted;
2782 
2783     // We allow the simpler queueInputBuffer API to be used even in
2784     // secure mode, by fabricating a single unencrypted subSample.
2785     CryptoPlugin::SubSample ss;
2786     CryptoPlugin::Pattern pattern;
2787 
2788     if (msg->findSize("size", &size)) {
2789         if (hasCryptoOrDescrambler()) {
2790             ss.mNumBytesOfClearData = size;
2791             ss.mNumBytesOfEncryptedData = 0;
2792 
2793             subSamples = &ss;
2794             numSubSamples = 1;
2795             key = NULL;
2796             iv = NULL;
2797             pattern.mEncryptBlocks = 0;
2798             pattern.mSkipBlocks = 0;
2799         }
2800     } else {
2801         if (!hasCryptoOrDescrambler()) {
2802             ALOGE("[%s] queuing secure buffer without mCrypto or mDescrambler!",
2803                     mComponentName.c_str());
2804             return -EINVAL;
2805         }
2806 
2807         CHECK(msg->findPointer("subSamples", (void **)&subSamples));
2808         CHECK(msg->findSize("numSubSamples", &numSubSamples));
2809         CHECK(msg->findPointer("key", (void **)&key));
2810         CHECK(msg->findPointer("iv", (void **)&iv));
2811         CHECK(msg->findInt32("encryptBlocks", (int32_t *)&pattern.mEncryptBlocks));
2812         CHECK(msg->findInt32("skipBlocks", (int32_t *)&pattern.mSkipBlocks));
2813 
2814         int32_t tmp;
2815         CHECK(msg->findInt32("mode", &tmp));
2816 
2817         mode = (CryptoPlugin::Mode)tmp;
2818 
2819         size = 0;
2820         for (size_t i = 0; i < numSubSamples; ++i) {
2821             size += subSamples[i].mNumBytesOfClearData;
2822             size += subSamples[i].mNumBytesOfEncryptedData;
2823         }
2824     }
2825 
2826     if (index >= mPortBuffers[kPortIndexInput].size()) {
2827         return -ERANGE;
2828     }
2829 
2830     BufferInfo *info = &mPortBuffers[kPortIndexInput][index];
2831 
2832     if (info->mData == nullptr || !info->mOwnedByClient) {
2833         return -EACCES;
2834     }
2835 
2836     if (offset + size > info->mData->capacity()) {
2837         return -EINVAL;
2838     }
2839 
2840     info->mData->setRange(offset, size);
2841     info->mData->meta()->setInt64("timeUs", timeUs);
2842     if (flags & BUFFER_FLAG_EOS) {
2843         info->mData->meta()->setInt32("eos", true);
2844     }
2845 
2846     if (flags & BUFFER_FLAG_CODECCONFIG) {
2847         info->mData->meta()->setInt32("csd", true);
2848     }
2849 
2850     sp<MediaCodecBuffer> buffer = info->mData;
2851     status_t err = OK;
2852     if (hasCryptoOrDescrambler()) {
2853         AString *errorDetailMsg;
2854         CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg));
2855 
2856         err = mBufferChannel->queueSecureInputBuffer(
2857                 buffer,
2858                 (mFlags & kFlagIsSecure),
2859                 key,
2860                 iv,
2861                 mode,
2862                 pattern,
2863                 subSamples,
2864                 numSubSamples,
2865                 errorDetailMsg);
2866     } else {
2867         err = mBufferChannel->queueInputBuffer(buffer);
2868     }
2869 
2870     if (err == OK) {
2871         // synchronization boundary for getBufferAndFormat
2872         Mutex::Autolock al(mBufferLock);
2873         info->mOwnedByClient = false;
2874         info->mData.clear();
2875         if (mAnalyticsItem != NULL) {
2876             mAnalyticsItem->addInt64(kCodecBytesIn, size);
2877         }
2878     }
2879 
2880     return err;
2881 }
2882 
2883 //static
CreateFramesRenderedMessage(const std::list<FrameRenderTracker::Info> & done,sp<AMessage> & msg)2884 size_t MediaCodec::CreateFramesRenderedMessage(
2885         const std::list<FrameRenderTracker::Info> &done, sp<AMessage> &msg) {
2886     size_t index = 0;
2887 
2888     for (std::list<FrameRenderTracker::Info>::const_iterator it = done.cbegin();
2889             it != done.cend(); ++it) {
2890         if (it->getRenderTimeNs() < 0) {
2891             continue; // dropped frame from tracking
2892         }
2893         msg->setInt64(AStringPrintf("%zu-media-time-us", index).c_str(), it->getMediaTimeUs());
2894         msg->setInt64(AStringPrintf("%zu-system-nano", index).c_str(), it->getRenderTimeNs());
2895         ++index;
2896     }
2897     return index;
2898 }
2899 
onReleaseOutputBuffer(const sp<AMessage> & msg)2900 status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) {
2901     size_t index;
2902     CHECK(msg->findSize("index", &index));
2903 
2904     int32_t render;
2905     if (!msg->findInt32("render", &render)) {
2906         render = 0;
2907     }
2908 
2909     if (!isExecuting()) {
2910         return -EINVAL;
2911     }
2912 
2913     if (index >= mPortBuffers[kPortIndexOutput].size()) {
2914         return -ERANGE;
2915     }
2916 
2917     BufferInfo *info = &mPortBuffers[kPortIndexOutput][index];
2918 
2919     if (info->mData == nullptr || !info->mOwnedByClient) {
2920         return -EACCES;
2921     }
2922 
2923     // synchronization boundary for getBufferAndFormat
2924     sp<MediaCodecBuffer> buffer;
2925     {
2926         Mutex::Autolock al(mBufferLock);
2927         info->mOwnedByClient = false;
2928         buffer = info->mData;
2929         info->mData.clear();
2930     }
2931 
2932     if (render && buffer->size() != 0) {
2933         int64_t mediaTimeUs = -1;
2934         buffer->meta()->findInt64("timeUs", &mediaTimeUs);
2935 
2936         int64_t renderTimeNs = 0;
2937         if (!msg->findInt64("timestampNs", &renderTimeNs)) {
2938             // use media timestamp if client did not request a specific render timestamp
2939             ALOGV("using buffer PTS of %lld", (long long)mediaTimeUs);
2940             renderTimeNs = mediaTimeUs * 1000;
2941         }
2942 
2943         if (mSoftRenderer != NULL) {
2944             std::list<FrameRenderTracker::Info> doneFrames = mSoftRenderer->render(
2945                     buffer->data(), buffer->size(),
2946                     mediaTimeUs, renderTimeNs, NULL, buffer->format());
2947 
2948             // if we are running, notify rendered frames
2949             if (!doneFrames.empty() && mState == STARTED && mOnFrameRenderedNotification != NULL) {
2950                 sp<AMessage> notify = mOnFrameRenderedNotification->dup();
2951                 sp<AMessage> data = new AMessage;
2952                 if (CreateFramesRenderedMessage(doneFrames, data)) {
2953                     notify->setMessage("data", data);
2954                     notify->post();
2955                 }
2956             }
2957         }
2958         mBufferChannel->renderOutputBuffer(buffer, renderTimeNs);
2959     } else {
2960         mBufferChannel->discardBuffer(buffer);
2961     }
2962 
2963     return OK;
2964 }
2965 
dequeuePortBuffer(int32_t portIndex)2966 ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) {
2967     CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
2968 
2969     List<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
2970 
2971     if (availBuffers->empty()) {
2972         return -EAGAIN;
2973     }
2974 
2975     size_t index = *availBuffers->begin();
2976     availBuffers->erase(availBuffers->begin());
2977 
2978     BufferInfo *info = &mPortBuffers[portIndex][index];
2979     CHECK(!info->mOwnedByClient);
2980     {
2981         Mutex::Autolock al(mBufferLock);
2982         info->mOwnedByClient = true;
2983 
2984         // set image-data
2985         if (info->mData->format() != NULL) {
2986             sp<ABuffer> imageData;
2987             if (info->mData->format()->findBuffer("image-data", &imageData)) {
2988                 info->mData->meta()->setBuffer("image-data", imageData);
2989             }
2990             int32_t left, top, right, bottom;
2991             if (info->mData->format()->findRect("crop", &left, &top, &right, &bottom)) {
2992                 info->mData->meta()->setRect("crop-rect", left, top, right, bottom);
2993             }
2994         }
2995     }
2996 
2997     return index;
2998 }
2999 
connectToSurface(const sp<Surface> & surface)3000 status_t MediaCodec::connectToSurface(const sp<Surface> &surface) {
3001     status_t err = OK;
3002     if (surface != NULL) {
3003         uint64_t oldId, newId;
3004         if (mSurface != NULL
3005                 && surface->getUniqueId(&newId) == NO_ERROR
3006                 && mSurface->getUniqueId(&oldId) == NO_ERROR
3007                 && newId == oldId) {
3008             ALOGI("[%s] connecting to the same surface. Nothing to do.", mComponentName.c_str());
3009             return ALREADY_EXISTS;
3010         }
3011 
3012         err = nativeWindowConnect(surface.get(), "connectToSurface");
3013         if (err == OK) {
3014             // Require a fresh set of buffers after each connect by using a unique generation
3015             // number. Rely on the fact that max supported process id by Linux is 2^22.
3016             // PID is never 0 so we don't have to worry that we use the default generation of 0.
3017             // TODO: come up with a unique scheme if other producers also set the generation number.
3018             static uint32_t mSurfaceGeneration = 0;
3019             uint32_t generation = (getpid() << 10) | (++mSurfaceGeneration & ((1 << 10) - 1));
3020             surface->setGenerationNumber(generation);
3021             ALOGI("[%s] setting surface generation to %u", mComponentName.c_str(), generation);
3022 
3023             // HACK: clear any free buffers. Remove when connect will automatically do this.
3024             // This is needed as the consumer may be holding onto stale frames that it can reattach
3025             // to this surface after disconnect/connect, and those free frames would inherit the new
3026             // generation number. Disconnecting after setting a unique generation prevents this.
3027             nativeWindowDisconnect(surface.get(), "connectToSurface(reconnect)");
3028             err = nativeWindowConnect(surface.get(), "connectToSurface(reconnect)");
3029         }
3030 
3031         if (err != OK) {
3032             ALOGE("nativeWindowConnect returned an error: %s (%d)", strerror(-err), err);
3033         }
3034     }
3035     // do not return ALREADY_EXISTS unless surfaces are the same
3036     return err == ALREADY_EXISTS ? BAD_VALUE : err;
3037 }
3038 
disconnectFromSurface()3039 status_t MediaCodec::disconnectFromSurface() {
3040     status_t err = OK;
3041     if (mSurface != NULL) {
3042         // Resetting generation is not technically needed, but there is no need to keep it either
3043         mSurface->setGenerationNumber(0);
3044         err = nativeWindowDisconnect(mSurface.get(), "disconnectFromSurface");
3045         if (err != OK) {
3046             ALOGW("nativeWindowDisconnect returned an error: %s (%d)", strerror(-err), err);
3047         }
3048         // assume disconnected even on error
3049         mSurface.clear();
3050     }
3051     return err;
3052 }
3053 
handleSetSurface(const sp<Surface> & surface)3054 status_t MediaCodec::handleSetSurface(const sp<Surface> &surface) {
3055     status_t err = OK;
3056     if (mSurface != NULL) {
3057         (void)disconnectFromSurface();
3058     }
3059     if (surface != NULL) {
3060         err = connectToSurface(surface);
3061         if (err == OK) {
3062             mSurface = surface;
3063         }
3064     }
3065     return err;
3066 }
3067 
onInputBufferAvailable()3068 void MediaCodec::onInputBufferAvailable() {
3069     int32_t index;
3070     while ((index = dequeuePortBuffer(kPortIndexInput)) >= 0) {
3071         sp<AMessage> msg = mCallback->dup();
3072         msg->setInt32("callbackID", CB_INPUT_AVAILABLE);
3073         msg->setInt32("index", index);
3074         msg->post();
3075     }
3076 }
3077 
onOutputBufferAvailable()3078 void MediaCodec::onOutputBufferAvailable() {
3079     int32_t index;
3080     while ((index = dequeuePortBuffer(kPortIndexOutput)) >= 0) {
3081         const sp<MediaCodecBuffer> &buffer =
3082             mPortBuffers[kPortIndexOutput][index].mData;
3083         sp<AMessage> msg = mCallback->dup();
3084         msg->setInt32("callbackID", CB_OUTPUT_AVAILABLE);
3085         msg->setInt32("index", index);
3086         msg->setSize("offset", buffer->offset());
3087         msg->setSize("size", buffer->size());
3088 
3089         int64_t timeUs;
3090         CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
3091 
3092         msg->setInt64("timeUs", timeUs);
3093 
3094         int32_t flags;
3095         CHECK(buffer->meta()->findInt32("flags", &flags));
3096 
3097         msg->setInt32("flags", flags);
3098 
3099         msg->post();
3100     }
3101 }
3102 
onError(status_t err,int32_t actionCode,const char * detail)3103 void MediaCodec::onError(status_t err, int32_t actionCode, const char *detail) {
3104     if (mCallback != NULL) {
3105         sp<AMessage> msg = mCallback->dup();
3106         msg->setInt32("callbackID", CB_ERROR);
3107         msg->setInt32("err", err);
3108         msg->setInt32("actionCode", actionCode);
3109 
3110         if (detail != NULL) {
3111             msg->setString("detail", detail);
3112         }
3113 
3114         msg->post();
3115     }
3116 }
3117 
onOutputFormatChanged()3118 void MediaCodec::onOutputFormatChanged() {
3119     if (mCallback != NULL) {
3120         sp<AMessage> msg = mCallback->dup();
3121         msg->setInt32("callbackID", CB_OUTPUT_FORMAT_CHANGED);
3122         msg->setMessage("format", mOutputFormat);
3123         msg->post();
3124     }
3125 }
3126 
postActivityNotificationIfPossible()3127 void MediaCodec::postActivityNotificationIfPossible() {
3128     if (mActivityNotify == NULL) {
3129         return;
3130     }
3131 
3132     bool isErrorOrOutputChanged =
3133             (mFlags & (kFlagStickyError
3134                     | kFlagOutputBuffersChanged
3135                     | kFlagOutputFormatChanged));
3136 
3137     if (isErrorOrOutputChanged
3138             || !mAvailPortBuffers[kPortIndexInput].empty()
3139             || !mAvailPortBuffers[kPortIndexOutput].empty()) {
3140         mActivityNotify->setInt32("input-buffers",
3141                 mAvailPortBuffers[kPortIndexInput].size());
3142 
3143         if (isErrorOrOutputChanged) {
3144             // we want consumer to dequeue as many times as it can
3145             mActivityNotify->setInt32("output-buffers", INT32_MAX);
3146         } else {
3147             mActivityNotify->setInt32("output-buffers",
3148                     mAvailPortBuffers[kPortIndexOutput].size());
3149         }
3150         mActivityNotify->post();
3151         mActivityNotify.clear();
3152     }
3153 }
3154 
setParameters(const sp<AMessage> & params)3155 status_t MediaCodec::setParameters(const sp<AMessage> &params) {
3156     sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
3157     msg->setMessage("params", params);
3158 
3159     sp<AMessage> response;
3160     return PostAndAwaitResponse(msg, &response);
3161 }
3162 
onSetParameters(const sp<AMessage> & params)3163 status_t MediaCodec::onSetParameters(const sp<AMessage> &params) {
3164     mCodec->signalSetParameters(params);
3165 
3166     return OK;
3167 }
3168 
amendOutputFormatWithCodecSpecificData(const sp<MediaCodecBuffer> & buffer)3169 status_t MediaCodec::amendOutputFormatWithCodecSpecificData(
3170         const sp<MediaCodecBuffer> &buffer) {
3171     AString mime;
3172     CHECK(mOutputFormat->findString("mime", &mime));
3173 
3174     if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
3175         // Codec specific data should be SPS and PPS in a single buffer,
3176         // each prefixed by a startcode (0x00 0x00 0x00 0x01).
3177         // We separate the two and put them into the output format
3178         // under the keys "csd-0" and "csd-1".
3179 
3180         unsigned csdIndex = 0;
3181 
3182         const uint8_t *data = buffer->data();
3183         size_t size = buffer->size();
3184 
3185         const uint8_t *nalStart;
3186         size_t nalSize;
3187         while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) {
3188             sp<ABuffer> csd = new ABuffer(nalSize + 4);
3189             memcpy(csd->data(), "\x00\x00\x00\x01", 4);
3190             memcpy(csd->data() + 4, nalStart, nalSize);
3191 
3192             mOutputFormat->setBuffer(
3193                     AStringPrintf("csd-%u", csdIndex).c_str(), csd);
3194 
3195             ++csdIndex;
3196         }
3197 
3198         if (csdIndex != 2) {
3199             return ERROR_MALFORMED;
3200         }
3201     } else {
3202         // For everything else we just stash the codec specific data into
3203         // the output format as a single piece of csd under "csd-0".
3204         sp<ABuffer> csd = new ABuffer(buffer->size());
3205         memcpy(csd->data(), buffer->data(), buffer->size());
3206         csd->setRange(0, buffer->size());
3207         mOutputFormat->setBuffer("csd-0", csd);
3208     }
3209 
3210     return OK;
3211 }
3212 
updateBatteryStat()3213 void MediaCodec::updateBatteryStat() {
3214     if (!mIsVideo) {
3215         return;
3216     }
3217 
3218     if (mState == CONFIGURED && !mBatteryStatNotified) {
3219         BatteryNotifier::getInstance().noteStartVideo(mUid);
3220         mBatteryStatNotified = true;
3221     } else if (mState == UNINITIALIZED && mBatteryStatNotified) {
3222         BatteryNotifier::getInstance().noteStopVideo(mUid);
3223         mBatteryStatNotified = false;
3224     }
3225 }
3226 
3227 }  // namespace android
3228