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