• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2012, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //#define LOG_NDEBUG 0
18 #include "hidl/HidlSupport.h"
19 #define LOG_TAG "MediaCodec"
20 #include <utils/Log.h>
21 
22 #include <set>
23 
24 #include <inttypes.h>
25 #include <stdlib.h>
26 
27 #include <C2Buffer.h>
28 
29 #include "include/SoftwareRenderer.h"
30 
31 #include <android/hardware/cas/native/1.0/IDescrambler.h>
32 #include <android/hardware/media/omx/1.0/IGraphicBufferSource.h>
33 
34 #include <aidl/android/media/BnResourceManagerClient.h>
35 #include <aidl/android/media/IResourceManagerService.h>
36 #include <android/binder_ibinder.h>
37 #include <android/binder_manager.h>
38 #include <binder/IMemory.h>
39 #include <binder/MemoryDealer.h>
40 #include <cutils/properties.h>
41 #include <gui/BufferQueue.h>
42 #include <gui/Surface.h>
43 #include <hidlmemory/FrameworkUtils.h>
44 #include <mediadrm/ICrypto.h>
45 #include <media/IOMX.h>
46 #include <media/MediaCodecBuffer.h>
47 #include <media/MediaCodecInfo.h>
48 #include <media/MediaMetricsItem.h>
49 #include <media/MediaResource.h>
50 #include <media/stagefright/foundation/ABuffer.h>
51 #include <media/stagefright/foundation/ADebug.h>
52 #include <media/stagefright/foundation/AMessage.h>
53 #include <media/stagefright/foundation/AString.h>
54 #include <media/stagefright/foundation/AUtils.h>
55 #include <media/stagefright/foundation/avc_utils.h>
56 #include <media/stagefright/foundation/hexdump.h>
57 #include <media/stagefright/ACodec.h>
58 #include <media/stagefright/BatteryChecker.h>
59 #include <media/stagefright/BufferProducerWrapper.h>
60 #include <media/stagefright/CCodec.h>
61 #include <media/stagefright/MediaCodec.h>
62 #include <media/stagefright/MediaCodecConstants.h>
63 #include <media/stagefright/MediaCodecList.h>
64 #include <media/stagefright/MediaDefs.h>
65 #include <media/stagefright/MediaErrors.h>
66 #include <media/stagefright/MediaFilter.h>
67 #include <media/stagefright/OMXClient.h>
68 #include <media/stagefright/PersistentSurface.h>
69 #include <media/stagefright/SurfaceUtils.h>
70 #include <private/android_filesystem_config.h>
71 #include <utils/Singleton.h>
72 
73 namespace android {
74 
75 using Status = ::ndk::ScopedAStatus;
76 using aidl::android::media::BnResourceManagerClient;
77 using aidl::android::media::IResourceManagerClient;
78 using aidl::android::media::IResourceManagerService;
79 
80 // key for media statistics
81 static const char *kCodecKeyName = "codec";
82 // attrs for media statistics
83 // NB: these are matched with public Java API constants defined
84 // in frameworks/base/media/java/android/media/MediaCodec.java
85 // These must be kept synchronized with the constants there.
86 static const char *kCodecCodec = "android.media.mediacodec.codec";  /* e.g. OMX.google.aac.decoder */
87 static const char *kCodecMime = "android.media.mediacodec.mime";    /* e.g. audio/mime */
88 static const char *kCodecMode = "android.media.mediacodec.mode";    /* audio, video */
89 static const char *kCodecModeVideo = "video";            /* values returned for kCodecMode */
90 static const char *kCodecModeAudio = "audio";
91 static const char *kCodecEncoder = "android.media.mediacodec.encoder"; /* 0,1 */
92 static const char *kCodecSecure = "android.media.mediacodec.secure";   /* 0, 1 */
93 static const char *kCodecWidth = "android.media.mediacodec.width";     /* 0..n */
94 static const char *kCodecHeight = "android.media.mediacodec.height";   /* 0..n */
95 static const char *kCodecRotation = "android.media.mediacodec.rotation-degrees";  /* 0/90/180/270 */
96 
97 // NB: These are not yet exposed as public Java API constants.
98 static const char *kCodecCrypto = "android.media.mediacodec.crypto";   /* 0,1 */
99 static const char *kCodecProfile = "android.media.mediacodec.profile";  /* 0..n */
100 static const char *kCodecLevel = "android.media.mediacodec.level";  /* 0..n */
101 static const char *kCodecBitrateMode = "android.media.mediacodec.bitrate_mode";  /* CQ/VBR/CBR */
102 static const char *kCodecBitrate = "android.media.mediacodec.bitrate";  /* 0..n */
103 static const char *kCodecMaxWidth = "android.media.mediacodec.maxwidth";  /* 0..n */
104 static const char *kCodecMaxHeight = "android.media.mediacodec.maxheight";  /* 0..n */
105 static const char *kCodecError = "android.media.mediacodec.errcode";
106 static const char *kCodecLifetimeMs = "android.media.mediacodec.lifetimeMs";   /* 0..n ms*/
107 static const char *kCodecErrorState = "android.media.mediacodec.errstate";
108 static const char *kCodecLatencyMax = "android.media.mediacodec.latency.max";   /* in us */
109 static const char *kCodecLatencyMin = "android.media.mediacodec.latency.min";   /* in us */
110 static const char *kCodecLatencyAvg = "android.media.mediacodec.latency.avg";   /* in us */
111 static const char *kCodecLatencyCount = "android.media.mediacodec.latency.n";
112 static const char *kCodecLatencyHist = "android.media.mediacodec.latency.hist"; /* in us */
113 static const char *kCodecLatencyUnknown = "android.media.mediacodec.latency.unknown";
114 static const char *kCodecQueueSecureInputBufferError = "android.media.mediacodec.queueSecureInputBufferError";
115 static const char *kCodecQueueInputBufferError = "android.media.mediacodec.queueInputBufferError";
116 
117 static const char *kCodecNumLowLatencyModeOn = "android.media.mediacodec.low-latency.on";  /* 0..n */
118 static const char *kCodecNumLowLatencyModeOff = "android.media.mediacodec.low-latency.off";  /* 0..n */
119 static const char *kCodecFirstFrameIndexLowLatencyModeOn = "android.media.mediacodec.low-latency.first-frame";  /* 0..n */
120 
121 // the kCodecRecent* fields appear only in getMetrics() results
122 static const char *kCodecRecentLatencyMax = "android.media.mediacodec.recent.max";      /* in us */
123 static const char *kCodecRecentLatencyMin = "android.media.mediacodec.recent.min";      /* in us */
124 static const char *kCodecRecentLatencyAvg = "android.media.mediacodec.recent.avg";      /* in us */
125 static const char *kCodecRecentLatencyCount = "android.media.mediacodec.recent.n";
126 static const char *kCodecRecentLatencyHist = "android.media.mediacodec.recent.hist";    /* in us */
127 
128 // XXX suppress until we get our representation right
129 static bool kEmitHistogram = false;
130 
131 
getId(const std::shared_ptr<IResourceManagerClient> & client)132 static int64_t getId(const std::shared_ptr<IResourceManagerClient> &client) {
133     return (int64_t) client.get();
134 }
135 
isResourceError(status_t err)136 static bool isResourceError(status_t err) {
137     return (err == NO_MEMORY);
138 }
139 
140 static const int kMaxRetry = 2;
141 static const int kMaxReclaimWaitTimeInUs = 500000;  // 0.5s
142 static const int kNumBuffersAlign = 16;
143 
144 static const C2MemoryUsage kDefaultReadWriteUsage{
145     C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE};
146 
147 ////////////////////////////////////////////////////////////////////////////////
148 
149 struct ResourceManagerClient : public BnResourceManagerClient {
ResourceManagerClientandroid::ResourceManagerClient150     explicit ResourceManagerClient(MediaCodec* codec) : mMediaCodec(codec) {}
151 
reclaimResourceandroid::ResourceManagerClient152     Status reclaimResource(bool* _aidl_return) override {
153         sp<MediaCodec> codec = mMediaCodec.promote();
154         if (codec == NULL) {
155             // codec is already gone.
156             *_aidl_return = true;
157             return Status::ok();
158         }
159         status_t err = codec->reclaim();
160         if (err == WOULD_BLOCK) {
161             ALOGD("Wait for the client to release codec.");
162             usleep(kMaxReclaimWaitTimeInUs);
163             ALOGD("Try to reclaim again.");
164             err = codec->reclaim(true /* force */);
165         }
166         if (err != OK) {
167             ALOGW("ResourceManagerClient failed to release codec with err %d", err);
168         }
169         *_aidl_return = (err == OK);
170         return Status::ok();
171     }
172 
getNameandroid::ResourceManagerClient173     Status getName(::std::string* _aidl_return) override {
174         _aidl_return->clear();
175         sp<MediaCodec> codec = mMediaCodec.promote();
176         if (codec == NULL) {
177             // codec is already gone.
178             return Status::ok();
179         }
180 
181         AString name;
182         if (codec->getName(&name) == OK) {
183             *_aidl_return = name.c_str();
184         }
185         return Status::ok();
186     }
187 
~ResourceManagerClientandroid::ResourceManagerClient188     virtual ~ResourceManagerClient() {}
189 
190 private:
191     wp<MediaCodec> mMediaCodec;
192 
193     DISALLOW_EVIL_CONSTRUCTORS(ResourceManagerClient);
194 };
195 
196 struct MediaCodec::ResourceManagerServiceProxy : public RefBase {
197     ResourceManagerServiceProxy(pid_t pid, uid_t uid,
198             const std::shared_ptr<IResourceManagerClient> &client);
199     virtual ~ResourceManagerServiceProxy();
200 
201     void init();
202 
203     // implements DeathRecipient
204     static void BinderDiedCallback(void* cookie);
205     void binderDied();
206     static Mutex sLockCookies;
207     static std::set<void*> sCookies;
208     static void addCookie(void* cookie);
209     static void removeCookie(void* cookie);
210 
211     void addResource(const MediaResourceParcel &resource);
212     void removeResource(const MediaResourceParcel &resource);
213     void removeClient();
214     void markClientForPendingRemoval();
215     bool reclaimResource(const std::vector<MediaResourceParcel> &resources);
216 
217 private:
218     Mutex mLock;
219     pid_t mPid;
220     uid_t mUid;
221     std::shared_ptr<IResourceManagerService> mService;
222     std::shared_ptr<IResourceManagerClient> mClient;
223     ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
224 };
225 
ResourceManagerServiceProxy(pid_t pid,uid_t uid,const std::shared_ptr<IResourceManagerClient> & client)226 MediaCodec::ResourceManagerServiceProxy::ResourceManagerServiceProxy(
227         pid_t pid, uid_t uid, const std::shared_ptr<IResourceManagerClient> &client)
228         : mPid(pid), mUid(uid), mClient(client),
229           mDeathRecipient(AIBinder_DeathRecipient_new(BinderDiedCallback)) {
230     if (mPid == MediaCodec::kNoPid) {
231         mPid = AIBinder_getCallingPid();
232     }
233 }
234 
~ResourceManagerServiceProxy()235 MediaCodec::ResourceManagerServiceProxy::~ResourceManagerServiceProxy() {
236 
237     // remove the cookie, so any in-flight death notification will get dropped
238     // by our handler.
239     removeCookie(this);
240 
241     Mutex::Autolock _l(mLock);
242     if (mService != nullptr) {
243         AIBinder_unlinkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
244         mService = nullptr;
245     }
246 }
247 
init()248 void MediaCodec::ResourceManagerServiceProxy::init() {
249     ::ndk::SpAIBinder binder(AServiceManager_getService("media.resource_manager"));
250     mService = IResourceManagerService::fromBinder(binder);
251     if (mService == nullptr) {
252         ALOGE("Failed to get ResourceManagerService");
253         return;
254     }
255 
256     // so our handler will process the death notifications
257     addCookie(this);
258 
259     // after this, require mLock whenever using mService
260     AIBinder_linkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
261 
262     // Kill clients pending removal.
263     mService->reclaimResourcesFromClientsPendingRemoval(mPid);
264 }
265 
266 //static
267 Mutex MediaCodec::ResourceManagerServiceProxy::sLockCookies;
268 std::set<void*> MediaCodec::ResourceManagerServiceProxy::sCookies;
269 
270 //static
addCookie(void * cookie)271 void MediaCodec::ResourceManagerServiceProxy::addCookie(void* cookie) {
272     Mutex::Autolock _l(sLockCookies);
273     sCookies.insert(cookie);
274 }
275 
276 //static
removeCookie(void * cookie)277 void MediaCodec::ResourceManagerServiceProxy::removeCookie(void* cookie) {
278     Mutex::Autolock _l(sLockCookies);
279     sCookies.erase(cookie);
280 }
281 
282 //static
BinderDiedCallback(void * cookie)283 void MediaCodec::ResourceManagerServiceProxy::BinderDiedCallback(void* cookie) {
284     Mutex::Autolock _l(sLockCookies);
285     if (sCookies.find(cookie) != sCookies.end()) {
286         auto thiz = static_cast<ResourceManagerServiceProxy*>(cookie);
287         thiz->binderDied();
288     }
289 }
290 
binderDied()291 void MediaCodec::ResourceManagerServiceProxy::binderDied() {
292     ALOGW("ResourceManagerService died.");
293     Mutex::Autolock _l(mLock);
294     mService = nullptr;
295 }
296 
addResource(const MediaResourceParcel & resource)297 void MediaCodec::ResourceManagerServiceProxy::addResource(
298         const MediaResourceParcel &resource) {
299     std::vector<MediaResourceParcel> resources;
300     resources.push_back(resource);
301 
302     Mutex::Autolock _l(mLock);
303     if (mService == nullptr) {
304         return;
305     }
306     mService->addResource(mPid, mUid, getId(mClient), mClient, resources);
307 }
308 
removeResource(const MediaResourceParcel & resource)309 void MediaCodec::ResourceManagerServiceProxy::removeResource(
310         const MediaResourceParcel &resource) {
311     std::vector<MediaResourceParcel> resources;
312     resources.push_back(resource);
313 
314     Mutex::Autolock _l(mLock);
315     if (mService == nullptr) {
316         return;
317     }
318     mService->removeResource(mPid, getId(mClient), resources);
319 }
320 
removeClient()321 void MediaCodec::ResourceManagerServiceProxy::removeClient() {
322     Mutex::Autolock _l(mLock);
323     if (mService == nullptr) {
324         return;
325     }
326     mService->removeClient(mPid, getId(mClient));
327 }
328 
markClientForPendingRemoval()329 void MediaCodec::ResourceManagerServiceProxy::markClientForPendingRemoval() {
330     Mutex::Autolock _l(mLock);
331     if (mService == nullptr) {
332         return;
333     }
334     mService->markClientForPendingRemoval(mPid, getId(mClient));
335 }
336 
reclaimResource(const std::vector<MediaResourceParcel> & resources)337 bool MediaCodec::ResourceManagerServiceProxy::reclaimResource(
338         const std::vector<MediaResourceParcel> &resources) {
339     Mutex::Autolock _l(mLock);
340     if (mService == NULL) {
341         return false;
342     }
343     bool success;
344     Status status = mService->reclaimResource(mPid, resources, &success);
345     return status.isOk() && success;
346 }
347 
348 ////////////////////////////////////////////////////////////////////////////////
349 
BufferInfo()350 MediaCodec::BufferInfo::BufferInfo() : mOwnedByClient(false) {}
351 
352 ////////////////////////////////////////////////////////////////////////////////
353 
354 class MediaCodec::ReleaseSurface {
355 public:
ReleaseSurface(uint64_t usage)356     explicit ReleaseSurface(uint64_t usage) {
357         BufferQueue::createBufferQueue(&mProducer, &mConsumer);
358         mSurface = new Surface(mProducer, false /* controlledByApp */);
359         struct ConsumerListener : public BnConsumerListener {
360             void onFrameAvailable(const BufferItem&) override {}
361             void onBuffersReleased() override {}
362             void onSidebandStreamChanged() override {}
363         };
364         sp<ConsumerListener> listener{new ConsumerListener};
365         mConsumer->consumerConnect(listener, false);
366         mConsumer->setConsumerName(String8{"MediaCodec.release"});
367         mConsumer->setConsumerUsageBits(usage);
368     }
369 
getSurface()370     const sp<Surface> &getSurface() {
371         return mSurface;
372     }
373 
374 private:
375     sp<IGraphicBufferProducer> mProducer;
376     sp<IGraphicBufferConsumer> mConsumer;
377     sp<Surface> mSurface;
378 };
379 
380 ////////////////////////////////////////////////////////////////////////////////
381 
382 namespace {
383 
384 enum {
385     kWhatFillThisBuffer      = 'fill',
386     kWhatDrainThisBuffer     = 'drai',
387     kWhatEOS                 = 'eos ',
388     kWhatStartCompleted      = 'Scom',
389     kWhatStopCompleted       = 'scom',
390     kWhatReleaseCompleted    = 'rcom',
391     kWhatFlushCompleted      = 'fcom',
392     kWhatError               = 'erro',
393     kWhatComponentAllocated  = 'cAll',
394     kWhatComponentConfigured = 'cCon',
395     kWhatInputSurfaceCreated = 'isfc',
396     kWhatInputSurfaceAccepted = 'isfa',
397     kWhatSignaledInputEOS    = 'seos',
398     kWhatOutputFramesRendered = 'outR',
399     kWhatOutputBuffersChanged = 'outC',
400 };
401 
402 class BufferCallback : public CodecBase::BufferCallback {
403 public:
404     explicit BufferCallback(const sp<AMessage> &notify);
405     virtual ~BufferCallback() = default;
406 
407     virtual void onInputBufferAvailable(
408             size_t index, const sp<MediaCodecBuffer> &buffer) override;
409     virtual void onOutputBufferAvailable(
410             size_t index, const sp<MediaCodecBuffer> &buffer) override;
411 private:
412     const sp<AMessage> mNotify;
413 };
414 
BufferCallback(const sp<AMessage> & notify)415 BufferCallback::BufferCallback(const sp<AMessage> &notify)
416     : mNotify(notify) {}
417 
onInputBufferAvailable(size_t index,const sp<MediaCodecBuffer> & buffer)418 void BufferCallback::onInputBufferAvailable(
419         size_t index, const sp<MediaCodecBuffer> &buffer) {
420     sp<AMessage> notify(mNotify->dup());
421     notify->setInt32("what", kWhatFillThisBuffer);
422     notify->setSize("index", index);
423     notify->setObject("buffer", buffer);
424     notify->post();
425 }
426 
onOutputBufferAvailable(size_t index,const sp<MediaCodecBuffer> & buffer)427 void BufferCallback::onOutputBufferAvailable(
428         size_t index, const sp<MediaCodecBuffer> &buffer) {
429     sp<AMessage> notify(mNotify->dup());
430     notify->setInt32("what", kWhatDrainThisBuffer);
431     notify->setSize("index", index);
432     notify->setObject("buffer", buffer);
433     notify->post();
434 }
435 
436 class CodecCallback : public CodecBase::CodecCallback {
437 public:
438     explicit CodecCallback(const sp<AMessage> &notify);
439     virtual ~CodecCallback() = default;
440 
441     virtual void onEos(status_t err) override;
442     virtual void onStartCompleted() override;
443     virtual void onStopCompleted() override;
444     virtual void onReleaseCompleted() override;
445     virtual void onFlushCompleted() override;
446     virtual void onError(status_t err, enum ActionCode actionCode) override;
447     virtual void onComponentAllocated(const char *componentName) override;
448     virtual void onComponentConfigured(
449             const sp<AMessage> &inputFormat, const sp<AMessage> &outputFormat) override;
450     virtual void onInputSurfaceCreated(
451             const sp<AMessage> &inputFormat,
452             const sp<AMessage> &outputFormat,
453             const sp<BufferProducerWrapper> &inputSurface) override;
454     virtual void onInputSurfaceCreationFailed(status_t err) override;
455     virtual void onInputSurfaceAccepted(
456             const sp<AMessage> &inputFormat,
457             const sp<AMessage> &outputFormat) override;
458     virtual void onInputSurfaceDeclined(status_t err) override;
459     virtual void onSignaledInputEOS(status_t err) override;
460     virtual void onOutputFramesRendered(const std::list<FrameRenderTracker::Info> &done) override;
461     virtual void onOutputBuffersChanged() override;
462 private:
463     const sp<AMessage> mNotify;
464 };
465 
CodecCallback(const sp<AMessage> & notify)466 CodecCallback::CodecCallback(const sp<AMessage> &notify) : mNotify(notify) {}
467 
onEos(status_t err)468 void CodecCallback::onEos(status_t err) {
469     sp<AMessage> notify(mNotify->dup());
470     notify->setInt32("what", kWhatEOS);
471     notify->setInt32("err", err);
472     notify->post();
473 }
474 
onStartCompleted()475 void CodecCallback::onStartCompleted() {
476     sp<AMessage> notify(mNotify->dup());
477     notify->setInt32("what", kWhatStartCompleted);
478     notify->post();
479 }
480 
onStopCompleted()481 void CodecCallback::onStopCompleted() {
482     sp<AMessage> notify(mNotify->dup());
483     notify->setInt32("what", kWhatStopCompleted);
484     notify->post();
485 }
486 
onReleaseCompleted()487 void CodecCallback::onReleaseCompleted() {
488     sp<AMessage> notify(mNotify->dup());
489     notify->setInt32("what", kWhatReleaseCompleted);
490     notify->post();
491 }
492 
onFlushCompleted()493 void CodecCallback::onFlushCompleted() {
494     sp<AMessage> notify(mNotify->dup());
495     notify->setInt32("what", kWhatFlushCompleted);
496     notify->post();
497 }
498 
onError(status_t err,enum ActionCode actionCode)499 void CodecCallback::onError(status_t err, enum ActionCode actionCode) {
500     sp<AMessage> notify(mNotify->dup());
501     notify->setInt32("what", kWhatError);
502     notify->setInt32("err", err);
503     notify->setInt32("actionCode", actionCode);
504     notify->post();
505 }
506 
onComponentAllocated(const char * componentName)507 void CodecCallback::onComponentAllocated(const char *componentName) {
508     sp<AMessage> notify(mNotify->dup());
509     notify->setInt32("what", kWhatComponentAllocated);
510     notify->setString("componentName", componentName);
511     notify->post();
512 }
513 
onComponentConfigured(const sp<AMessage> & inputFormat,const sp<AMessage> & outputFormat)514 void CodecCallback::onComponentConfigured(
515         const sp<AMessage> &inputFormat, const sp<AMessage> &outputFormat) {
516     sp<AMessage> notify(mNotify->dup());
517     notify->setInt32("what", kWhatComponentConfigured);
518     notify->setMessage("input-format", inputFormat);
519     notify->setMessage("output-format", outputFormat);
520     notify->post();
521 }
522 
onInputSurfaceCreated(const sp<AMessage> & inputFormat,const sp<AMessage> & outputFormat,const sp<BufferProducerWrapper> & inputSurface)523 void CodecCallback::onInputSurfaceCreated(
524         const sp<AMessage> &inputFormat,
525         const sp<AMessage> &outputFormat,
526         const sp<BufferProducerWrapper> &inputSurface) {
527     sp<AMessage> notify(mNotify->dup());
528     notify->setInt32("what", kWhatInputSurfaceCreated);
529     notify->setMessage("input-format", inputFormat);
530     notify->setMessage("output-format", outputFormat);
531     notify->setObject("input-surface", inputSurface);
532     notify->post();
533 }
534 
onInputSurfaceCreationFailed(status_t err)535 void CodecCallback::onInputSurfaceCreationFailed(status_t err) {
536     sp<AMessage> notify(mNotify->dup());
537     notify->setInt32("what", kWhatInputSurfaceCreated);
538     notify->setInt32("err", err);
539     notify->post();
540 }
541 
onInputSurfaceAccepted(const sp<AMessage> & inputFormat,const sp<AMessage> & outputFormat)542 void CodecCallback::onInputSurfaceAccepted(
543         const sp<AMessage> &inputFormat,
544         const sp<AMessage> &outputFormat) {
545     sp<AMessage> notify(mNotify->dup());
546     notify->setInt32("what", kWhatInputSurfaceAccepted);
547     notify->setMessage("input-format", inputFormat);
548     notify->setMessage("output-format", outputFormat);
549     notify->post();
550 }
551 
onInputSurfaceDeclined(status_t err)552 void CodecCallback::onInputSurfaceDeclined(status_t err) {
553     sp<AMessage> notify(mNotify->dup());
554     notify->setInt32("what", kWhatInputSurfaceAccepted);
555     notify->setInt32("err", err);
556     notify->post();
557 }
558 
onSignaledInputEOS(status_t err)559 void CodecCallback::onSignaledInputEOS(status_t err) {
560     sp<AMessage> notify(mNotify->dup());
561     notify->setInt32("what", kWhatSignaledInputEOS);
562     if (err != OK) {
563         notify->setInt32("err", err);
564     }
565     notify->post();
566 }
567 
onOutputFramesRendered(const std::list<FrameRenderTracker::Info> & done)568 void CodecCallback::onOutputFramesRendered(const std::list<FrameRenderTracker::Info> &done) {
569     sp<AMessage> notify(mNotify->dup());
570     notify->setInt32("what", kWhatOutputFramesRendered);
571     if (MediaCodec::CreateFramesRenderedMessage(done, notify)) {
572         notify->post();
573     }
574 }
575 
onOutputBuffersChanged()576 void CodecCallback::onOutputBuffersChanged() {
577     sp<AMessage> notify(mNotify->dup());
578     notify->setInt32("what", kWhatOutputBuffersChanged);
579     notify->post();
580 }
581 
582 }  // namespace
583 
584 ////////////////////////////////////////////////////////////////////////////////
585 
586 // static
CreateByType(const sp<ALooper> & looper,const AString & mime,bool encoder,status_t * err,pid_t pid,uid_t uid)587 sp<MediaCodec> MediaCodec::CreateByType(
588         const sp<ALooper> &looper, const AString &mime, bool encoder, status_t *err, pid_t pid,
589         uid_t uid) {
590     Vector<AString> matchingCodecs;
591 
592     MediaCodecList::findMatchingCodecs(
593             mime.c_str(),
594             encoder,
595             0,
596             &matchingCodecs);
597 
598     if (err != NULL) {
599         *err = NAME_NOT_FOUND;
600     }
601     for (size_t i = 0; i < matchingCodecs.size(); ++i) {
602         sp<MediaCodec> codec = new MediaCodec(looper, pid, uid);
603         AString componentName = matchingCodecs[i];
604         status_t ret = codec->init(componentName);
605         if (err != NULL) {
606             *err = ret;
607         }
608         if (ret == OK) {
609             return codec;
610         }
611         ALOGD("Allocating component '%s' failed (%d), try next one.",
612                 componentName.c_str(), ret);
613     }
614     return NULL;
615 }
616 
617 // static
CreateByComponentName(const sp<ALooper> & looper,const AString & name,status_t * err,pid_t pid,uid_t uid)618 sp<MediaCodec> MediaCodec::CreateByComponentName(
619         const sp<ALooper> &looper, const AString &name, status_t *err, pid_t pid, uid_t uid) {
620     sp<MediaCodec> codec = new MediaCodec(looper, pid, uid);
621 
622     const status_t ret = codec->init(name);
623     if (err != NULL) {
624         *err = ret;
625     }
626     return ret == OK ? codec : NULL; // NULL deallocates codec.
627 }
628 
629 // static
CreatePersistentInputSurface()630 sp<PersistentSurface> MediaCodec::CreatePersistentInputSurface() {
631     sp<PersistentSurface> pluginSurface = CCodec::CreateInputSurface();
632     if (pluginSurface != nullptr) {
633         return pluginSurface;
634     }
635 
636     OMXClient client;
637     if (client.connect() != OK) {
638         ALOGE("Failed to connect to OMX to create persistent input surface.");
639         return NULL;
640     }
641 
642     sp<IOMX> omx = client.interface();
643 
644     sp<IGraphicBufferProducer> bufferProducer;
645     sp<hardware::media::omx::V1_0::IGraphicBufferSource> bufferSource;
646 
647     status_t err = omx->createInputSurface(&bufferProducer, &bufferSource);
648 
649     if (err != OK) {
650         ALOGE("Failed to create persistent input surface.");
651         return NULL;
652     }
653 
654     return new PersistentSurface(bufferProducer, bufferSource);
655 }
656 
MediaCodec(const sp<ALooper> & looper,pid_t pid,uid_t uid,std::function<sp<CodecBase> (const AString &,const char *)> getCodecBase,std::function<status_t (const AString &,sp<MediaCodecInfo> *)> getCodecInfo)657 MediaCodec::MediaCodec(
658         const sp<ALooper> &looper, pid_t pid, uid_t uid,
659         std::function<sp<CodecBase>(const AString &, const char *)> getCodecBase,
660         std::function<status_t(const AString &, sp<MediaCodecInfo> *)> getCodecInfo)
661     : mState(UNINITIALIZED),
662       mReleasedByResourceManager(false),
663       mLooper(looper),
664       mCodec(NULL),
665       mReplyID(0),
666       mFlags(0),
667       mStickyError(OK),
668       mSoftRenderer(NULL),
669       mIsVideo(false),
670       mVideoWidth(0),
671       mVideoHeight(0),
672       mRotationDegrees(0),
673       mDequeueInputTimeoutGeneration(0),
674       mDequeueInputReplyID(0),
675       mDequeueOutputTimeoutGeneration(0),
676       mDequeueOutputReplyID(0),
677       mHaveInputSurface(false),
678       mHavePendingInputBuffers(false),
679       mCpuBoostRequested(false),
680       mLatencyUnknown(0),
681       mNumLowLatencyEnables(0),
682       mNumLowLatencyDisables(0),
683       mIsLowLatencyModeOn(false),
684       mIndexOfFirstFrameWhenLowLatencyOn(-1),
685       mInputBufferCounter(0),
686       mGetCodecBase(getCodecBase),
687       mGetCodecInfo(getCodecInfo) {
688     if (uid == kNoUid) {
689         mUid = AIBinder_getCallingUid();
690     } else {
691         mUid = uid;
692     }
693     mResourceManagerProxy = new ResourceManagerServiceProxy(pid, mUid,
694             ::ndk::SharedRefBase::make<ResourceManagerClient>(this));
695     if (!mGetCodecBase) {
696         mGetCodecBase = [](const AString &name, const char *owner) {
697             return GetCodecBase(name, owner);
698         };
699     }
700     if (!mGetCodecInfo) {
701         mGetCodecInfo = [](const AString &name, sp<MediaCodecInfo> *info) -> status_t {
702             *info = nullptr;
703             const sp<IMediaCodecList> mcl = MediaCodecList::getInstance();
704             if (!mcl) {
705                 return NO_INIT;  // if called from Java should raise IOException
706             }
707             AString tmp = name;
708             if (tmp.endsWith(".secure")) {
709                 tmp.erase(tmp.size() - 7, 7);
710             }
711             for (const AString &codecName : { name, tmp }) {
712                 ssize_t codecIdx = mcl->findCodecByName(codecName.c_str());
713                 if (codecIdx < 0) {
714                     continue;
715                 }
716                 *info = mcl->getCodecInfo(codecIdx);
717                 return OK;
718             }
719             return NAME_NOT_FOUND;
720         };
721     }
722 
723     initMediametrics();
724 }
725 
~MediaCodec()726 MediaCodec::~MediaCodec() {
727     CHECK_EQ(mState, UNINITIALIZED);
728     mResourceManagerProxy->removeClient();
729 
730     flushMediametrics();
731 }
732 
initMediametrics()733 void MediaCodec::initMediametrics() {
734     if (mMetricsHandle == 0) {
735         mMetricsHandle = mediametrics_create(kCodecKeyName);
736     }
737 
738     mLatencyHist.setup(kLatencyHistBuckets, kLatencyHistWidth, kLatencyHistFloor);
739 
740     {
741         Mutex::Autolock al(mRecentLock);
742         for (int i = 0; i<kRecentLatencyFrames; i++) {
743             mRecentSamples[i] = kRecentSampleInvalid;
744         }
745         mRecentHead = 0;
746     }
747 
748     {
749         Mutex::Autolock al(mLatencyLock);
750         mBuffersInFlight.clear();
751         mNumLowLatencyEnables = 0;
752         mNumLowLatencyDisables = 0;
753         mIsLowLatencyModeOn = false;
754         mIndexOfFirstFrameWhenLowLatencyOn = -1;
755         mInputBufferCounter = 0;
756     }
757 
758     mLifetimeStartNs = systemTime(SYSTEM_TIME_MONOTONIC);
759 }
760 
updateMediametrics()761 void MediaCodec::updateMediametrics() {
762     ALOGV("MediaCodec::updateMediametrics");
763     if (mMetricsHandle == 0) {
764         return;
765     }
766 
767     if (mLatencyHist.getCount() != 0 ) {
768         mediametrics_setInt64(mMetricsHandle, kCodecLatencyMax, mLatencyHist.getMax());
769         mediametrics_setInt64(mMetricsHandle, kCodecLatencyMin, mLatencyHist.getMin());
770         mediametrics_setInt64(mMetricsHandle, kCodecLatencyAvg, mLatencyHist.getAvg());
771         mediametrics_setInt64(mMetricsHandle, kCodecLatencyCount, mLatencyHist.getCount());
772 
773         if (kEmitHistogram) {
774             // and the histogram itself
775             std::string hist = mLatencyHist.emit();
776             mediametrics_setCString(mMetricsHandle, kCodecLatencyHist, hist.c_str());
777         }
778     }
779     if (mLatencyUnknown > 0) {
780         mediametrics_setInt64(mMetricsHandle, kCodecLatencyUnknown, mLatencyUnknown);
781     }
782     if (mLifetimeStartNs > 0) {
783         nsecs_t lifetime = systemTime(SYSTEM_TIME_MONOTONIC) - mLifetimeStartNs;
784         lifetime = lifetime / (1000 * 1000);    // emitted in ms, truncated not rounded
785         mediametrics_setInt64(mMetricsHandle, kCodecLifetimeMs, lifetime);
786     }
787 
788     {
789         Mutex::Autolock al(mLatencyLock);
790         mediametrics_setInt64(mMetricsHandle, kCodecNumLowLatencyModeOn, mNumLowLatencyEnables);
791         mediametrics_setInt64(mMetricsHandle, kCodecNumLowLatencyModeOff, mNumLowLatencyDisables);
792         mediametrics_setInt64(mMetricsHandle, kCodecFirstFrameIndexLowLatencyModeOn,
793                               mIndexOfFirstFrameWhenLowLatencyOn);
794     }
795 #if 0
796     // enable for short term, only while debugging
797     updateEphemeralMediametrics(mMetricsHandle);
798 #endif
799 }
800 
updateEphemeralMediametrics(mediametrics_handle_t item)801 void MediaCodec::updateEphemeralMediametrics(mediametrics_handle_t item) {
802     ALOGD("MediaCodec::updateEphemeralMediametrics()");
803 
804     if (item == 0) {
805         return;
806     }
807 
808     Histogram recentHist;
809 
810     // build an empty histogram
811     recentHist.setup(kLatencyHistBuckets, kLatencyHistWidth, kLatencyHistFloor);
812 
813     // stuff it with the samples in the ring buffer
814     {
815         Mutex::Autolock al(mRecentLock);
816 
817         for (int i=0; i<kRecentLatencyFrames; i++) {
818             if (mRecentSamples[i] != kRecentSampleInvalid) {
819                 recentHist.insert(mRecentSamples[i]);
820             }
821         }
822     }
823 
824     // spit the data (if any) into the supplied analytics record
825     if (recentHist.getCount()!= 0 ) {
826         mediametrics_setInt64(item, kCodecRecentLatencyMax, recentHist.getMax());
827         mediametrics_setInt64(item, kCodecRecentLatencyMin, recentHist.getMin());
828         mediametrics_setInt64(item, kCodecRecentLatencyAvg, recentHist.getAvg());
829         mediametrics_setInt64(item, kCodecRecentLatencyCount, recentHist.getCount());
830 
831         if (kEmitHistogram) {
832             // and the histogram itself
833             std::string hist = recentHist.emit();
834             mediametrics_setCString(item, kCodecRecentLatencyHist, hist.c_str());
835         }
836     }
837 }
838 
flushMediametrics()839 void MediaCodec::flushMediametrics() {
840     updateMediametrics();
841     if (mMetricsHandle != 0) {
842         if (mediametrics_count(mMetricsHandle) > 0) {
843             mediametrics_selfRecord(mMetricsHandle);
844         }
845         mediametrics_delete(mMetricsHandle);
846         mMetricsHandle = 0;
847     }
848 }
849 
updateLowLatency(const sp<AMessage> & msg)850 void MediaCodec::updateLowLatency(const sp<AMessage> &msg) {
851     int32_t lowLatency = 0;
852     if (msg->findInt32("low-latency", &lowLatency)) {
853         Mutex::Autolock al(mLatencyLock);
854         if (lowLatency > 0) {
855             ++mNumLowLatencyEnables;
856             // This is just an estimate since low latency mode change happens ONLY at key frame
857             mIsLowLatencyModeOn = true;
858         } else if (lowLatency == 0) {
859             ++mNumLowLatencyDisables;
860             // This is just an estimate since low latency mode change happens ONLY at key frame
861             mIsLowLatencyModeOn = false;
862         }
863     }
864 }
865 
setup(int nbuckets,int64_t width,int64_t floor)866 bool MediaCodec::Histogram::setup(int nbuckets, int64_t width, int64_t floor)
867 {
868     if (nbuckets <= 0 || width <= 0) {
869         return false;
870     }
871 
872     // get histogram buckets
873     if (nbuckets == mBucketCount && mBuckets != NULL) {
874         // reuse our existing buffer
875         memset(mBuckets, 0, sizeof(*mBuckets) * mBucketCount);
876     } else {
877         // get a new pre-zeroed buffer
878         int64_t *newbuckets = (int64_t *)calloc(nbuckets, sizeof (*mBuckets));
879         if (newbuckets == NULL) {
880             goto bad;
881         }
882         if (mBuckets != NULL)
883             free(mBuckets);
884         mBuckets = newbuckets;
885     }
886 
887     mWidth = width;
888     mFloor = floor;
889     mCeiling = floor + nbuckets * width;
890     mBucketCount = nbuckets;
891 
892     mMin = INT64_MAX;
893     mMax = INT64_MIN;
894     mSum = 0;
895     mCount = 0;
896     mBelow = mAbove = 0;
897 
898     return true;
899 
900   bad:
901     if (mBuckets != NULL) {
902         free(mBuckets);
903         mBuckets = NULL;
904     }
905 
906     return false;
907 }
908 
insert(int64_t sample)909 void MediaCodec::Histogram::insert(int64_t sample)
910 {
911     // histogram is not set up
912     if (mBuckets == NULL) {
913         return;
914     }
915 
916     mCount++;
917     mSum += sample;
918     if (mMin > sample) mMin = sample;
919     if (mMax < sample) mMax = sample;
920 
921     if (sample < mFloor) {
922         mBelow++;
923     } else if (sample >= mCeiling) {
924         mAbove++;
925     } else {
926         int64_t slot = (sample - mFloor) / mWidth;
927         CHECK(slot < mBucketCount);
928         mBuckets[slot]++;
929     }
930     return;
931 }
932 
emit()933 std::string MediaCodec::Histogram::emit()
934 {
935     std::string value;
936     char buffer[64];
937 
938     // emits:  width,Below{bucket0,bucket1,...., bucketN}above
939     // unconfigured will emit: 0,0{}0
940     // XXX: is this best representation?
941     snprintf(buffer, sizeof(buffer), "%" PRId64 ",%" PRId64 ",%" PRId64 "{",
942              mFloor, mWidth, mBelow);
943     value = buffer;
944     for (int i = 0; i < mBucketCount; i++) {
945         if (i != 0) {
946             value = value + ",";
947         }
948         snprintf(buffer, sizeof(buffer), "%" PRId64, mBuckets[i]);
949         value = value + buffer;
950     }
951     snprintf(buffer, sizeof(buffer), "}%" PRId64 , mAbove);
952     value = value + buffer;
953     return value;
954 }
955 
956 // when we send a buffer to the codec;
statsBufferSent(int64_t presentationUs)957 void MediaCodec::statsBufferSent(int64_t presentationUs) {
958 
959     // only enqueue if we have a legitimate time
960     if (presentationUs <= 0) {
961         ALOGV("presentation time: %" PRId64, presentationUs);
962         return;
963     }
964 
965     if (mBatteryChecker != nullptr) {
966         mBatteryChecker->onCodecActivity([this] () {
967             mResourceManagerProxy->addResource(MediaResource::VideoBatteryResource());
968         });
969     }
970 
971     const int64_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
972     BufferFlightTiming_t startdata = { presentationUs, nowNs };
973 
974     {
975         // mutex access to mBuffersInFlight and other stats
976         Mutex::Autolock al(mLatencyLock);
977 
978 
979         // XXX: we *could* make sure that the time is later than the end of queue
980         // as part of a consistency check...
981         mBuffersInFlight.push_back(startdata);
982 
983         if (mIsLowLatencyModeOn && mIndexOfFirstFrameWhenLowLatencyOn < 0) {
984             mIndexOfFirstFrameWhenLowLatencyOn = mInputBufferCounter;
985         }
986         ++mInputBufferCounter;
987     }
988 }
989 
990 // when we get a buffer back from the codec
statsBufferReceived(int64_t presentationUs)991 void MediaCodec::statsBufferReceived(int64_t presentationUs) {
992 
993     CHECK_NE(mState, UNINITIALIZED);
994 
995     // mutex access to mBuffersInFlight and other stats
996     Mutex::Autolock al(mLatencyLock);
997 
998     // how long this buffer took for the round trip through the codec
999     // NB: pipelining can/will make these times larger. e.g., if each packet
1000     // is always 2 msec and we have 3 in flight at any given time, we're going to
1001     // see "6 msec" as an answer.
1002 
1003     // ignore stuff with no presentation time
1004     if (presentationUs <= 0) {
1005         ALOGV("-- returned buffer timestamp %" PRId64 " <= 0, ignore it", presentationUs);
1006         mLatencyUnknown++;
1007         return;
1008     }
1009 
1010     if (mBatteryChecker != nullptr) {
1011         mBatteryChecker->onCodecActivity([this] () {
1012             mResourceManagerProxy->addResource(MediaResource::VideoBatteryResource());
1013         });
1014     }
1015 
1016     BufferFlightTiming_t startdata;
1017     bool valid = false;
1018     while (mBuffersInFlight.size() > 0) {
1019         startdata = *mBuffersInFlight.begin();
1020         ALOGV("-- Looking at startdata. presentation %" PRId64 ", start %" PRId64,
1021               startdata.presentationUs, startdata.startedNs);
1022         if (startdata.presentationUs == presentationUs) {
1023             // a match
1024             ALOGV("-- match entry for %" PRId64 ", hits our frame of %" PRId64,
1025                   startdata.presentationUs, presentationUs);
1026             mBuffersInFlight.pop_front();
1027             valid = true;
1028             break;
1029         } else if (startdata.presentationUs < presentationUs) {
1030             // we must have missed the match for this, drop it and keep looking
1031             ALOGV("--  drop entry for %" PRId64 ", before our frame of %" PRId64,
1032                   startdata.presentationUs, presentationUs);
1033             mBuffersInFlight.pop_front();
1034             continue;
1035         } else {
1036             // head is after, so we don't have a frame for ourselves
1037             ALOGV("--  found entry for %" PRId64 ", AFTER our frame of %" PRId64
1038                   " we have nothing to pair with",
1039                   startdata.presentationUs, presentationUs);
1040             mLatencyUnknown++;
1041             return;
1042         }
1043     }
1044     if (!valid) {
1045         ALOGV("-- empty queue, so ignore that.");
1046         mLatencyUnknown++;
1047         return;
1048     }
1049 
1050     // nowNs start our calculations
1051     const int64_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
1052     int64_t latencyUs = (nowNs - startdata.startedNs + 500) / 1000;
1053 
1054     mLatencyHist.insert(latencyUs);
1055 
1056     // push into the recent samples
1057     {
1058         Mutex::Autolock al(mRecentLock);
1059 
1060         if (mRecentHead >= kRecentLatencyFrames) {
1061             mRecentHead = 0;
1062         }
1063         mRecentSamples[mRecentHead++] = latencyUs;
1064     }
1065 }
1066 
1067 // static
PostAndAwaitResponse(const sp<AMessage> & msg,sp<AMessage> * response)1068 status_t MediaCodec::PostAndAwaitResponse(
1069         const sp<AMessage> &msg, sp<AMessage> *response) {
1070     status_t err = msg->postAndAwaitResponse(response);
1071 
1072     if (err != OK) {
1073         return err;
1074     }
1075 
1076     if (!(*response)->findInt32("err", &err)) {
1077         err = OK;
1078     }
1079 
1080     return err;
1081 }
1082 
PostReplyWithError(const sp<AMessage> & msg,int32_t err)1083 void MediaCodec::PostReplyWithError(const sp<AMessage> &msg, int32_t err) {
1084     sp<AReplyToken> replyID;
1085     CHECK(msg->senderAwaitsResponse(&replyID));
1086     PostReplyWithError(replyID, err);
1087 }
1088 
PostReplyWithError(const sp<AReplyToken> & replyID,int32_t err)1089 void MediaCodec::PostReplyWithError(const sp<AReplyToken> &replyID, int32_t err) {
1090     int32_t finalErr = err;
1091     if (mReleasedByResourceManager) {
1092         // override the err code if MediaCodec has been released by ResourceManager.
1093         finalErr = DEAD_OBJECT;
1094     }
1095 
1096     sp<AMessage> response = new AMessage;
1097     response->setInt32("err", finalErr);
1098     response->postReply(replyID);
1099 }
1100 
CreateCCodec()1101 static CodecBase *CreateCCodec() {
1102     return new CCodec;
1103 }
1104 
1105 //static
GetCodecBase(const AString & name,const char * owner)1106 sp<CodecBase> MediaCodec::GetCodecBase(const AString &name, const char *owner) {
1107     if (owner) {
1108         if (strcmp(owner, "default") == 0) {
1109             return new ACodec;
1110         } else if (strncmp(owner, "codec2", 6) == 0) {
1111             return CreateCCodec();
1112         }
1113     }
1114 
1115     if (name.startsWithIgnoreCase("c2.")) {
1116         return CreateCCodec();
1117     } else if (name.startsWithIgnoreCase("omx.")) {
1118         // at this time only ACodec specifies a mime type.
1119         return new ACodec;
1120     } else if (name.startsWithIgnoreCase("android.filter.")) {
1121         return new MediaFilter;
1122     } else {
1123         return NULL;
1124     }
1125 }
1126 
1127 struct CodecListCache {
CodecListCacheandroid::CodecListCache1128     CodecListCache()
1129         : mCodecInfoMap{[] {
1130               const sp<IMediaCodecList> mcl = MediaCodecList::getInstance();
1131               size_t count = mcl->countCodecs();
1132               std::map<std::string, sp<MediaCodecInfo>> codecInfoMap;
1133               for (size_t i = 0; i < count; ++i) {
1134                   sp<MediaCodecInfo> info = mcl->getCodecInfo(i);
1135                   codecInfoMap.emplace(info->getCodecName(), info);
1136               }
1137               return codecInfoMap;
1138           }()} {
1139     }
1140 
1141     const std::map<std::string, sp<MediaCodecInfo>> mCodecInfoMap;
1142 };
1143 
GetCodecListCache()1144 static const CodecListCache &GetCodecListCache() {
1145     static CodecListCache sCache{};
1146     return sCache;
1147 }
1148 
init(const AString & name)1149 status_t MediaCodec::init(const AString &name) {
1150     mResourceManagerProxy->init();
1151 
1152     // save init parameters for reset
1153     mInitName = name;
1154 
1155     // Current video decoders do not return from OMX_FillThisBuffer
1156     // quickly, violating the OpenMAX specs, until that is remedied
1157     // we need to invest in an extra looper to free the main event
1158     // queue.
1159 
1160     mCodecInfo.clear();
1161 
1162     bool secureCodec = false;
1163     const char *owner = "";
1164     if (!name.startsWith("android.filter.")) {
1165         status_t err = mGetCodecInfo(name, &mCodecInfo);
1166         if (err != OK) {
1167             mCodec = NULL;  // remove the codec.
1168             return err;
1169         }
1170         if (mCodecInfo == nullptr) {
1171             ALOGE("Getting codec info with name '%s' failed", name.c_str());
1172             return NAME_NOT_FOUND;
1173         }
1174         secureCodec = name.endsWith(".secure");
1175         Vector<AString> mediaTypes;
1176         mCodecInfo->getSupportedMediaTypes(&mediaTypes);
1177         for (size_t i = 0; i < mediaTypes.size(); ++i) {
1178             if (mediaTypes[i].startsWith("video/")) {
1179                 mIsVideo = true;
1180                 break;
1181             }
1182         }
1183         owner = mCodecInfo->getOwnerName();
1184     }
1185 
1186     mCodec = mGetCodecBase(name, owner);
1187     if (mCodec == NULL) {
1188         ALOGE("Getting codec base with name '%s' (owner='%s') failed", name.c_str(), owner);
1189         return NAME_NOT_FOUND;
1190     }
1191 
1192     if (mIsVideo) {
1193         // video codec needs dedicated looper
1194         if (mCodecLooper == NULL) {
1195             mCodecLooper = new ALooper;
1196             mCodecLooper->setName("CodecLooper");
1197             mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
1198         }
1199 
1200         mCodecLooper->registerHandler(mCodec);
1201     } else {
1202         mLooper->registerHandler(mCodec);
1203     }
1204 
1205     mLooper->registerHandler(this);
1206 
1207     mCodec->setCallback(
1208             std::unique_ptr<CodecBase::CodecCallback>(
1209                     new CodecCallback(new AMessage(kWhatCodecNotify, this))));
1210     mBufferChannel = mCodec->getBufferChannel();
1211     mBufferChannel->setCallback(
1212             std::unique_ptr<CodecBase::BufferCallback>(
1213                     new BufferCallback(new AMessage(kWhatCodecNotify, this))));
1214 
1215     sp<AMessage> msg = new AMessage(kWhatInit, this);
1216     if (mCodecInfo) {
1217         msg->setObject("codecInfo", mCodecInfo);
1218         // name may be different from mCodecInfo->getCodecName() if we stripped
1219         // ".secure"
1220     }
1221     msg->setString("name", name);
1222 
1223     if (mMetricsHandle != 0) {
1224         mediametrics_setCString(mMetricsHandle, kCodecCodec, name.c_str());
1225         mediametrics_setCString(mMetricsHandle, kCodecMode,
1226                                 mIsVideo ? kCodecModeVideo : kCodecModeAudio);
1227     }
1228 
1229     if (mIsVideo) {
1230         mBatteryChecker = new BatteryChecker(new AMessage(kWhatCheckBatteryStats, this));
1231     }
1232 
1233     status_t err;
1234     std::vector<MediaResourceParcel> resources;
1235     resources.push_back(MediaResource::CodecResource(secureCodec, mIsVideo));
1236     for (int i = 0; i <= kMaxRetry; ++i) {
1237         if (i > 0) {
1238             // Don't try to reclaim resource for the first time.
1239             if (!mResourceManagerProxy->reclaimResource(resources)) {
1240                 break;
1241             }
1242         }
1243 
1244         sp<AMessage> response;
1245         err = PostAndAwaitResponse(msg, &response);
1246         if (!isResourceError(err)) {
1247             break;
1248         }
1249     }
1250     return err;
1251 }
1252 
setCallback(const sp<AMessage> & callback)1253 status_t MediaCodec::setCallback(const sp<AMessage> &callback) {
1254     sp<AMessage> msg = new AMessage(kWhatSetCallback, this);
1255     msg->setMessage("callback", callback);
1256 
1257     sp<AMessage> response;
1258     return PostAndAwaitResponse(msg, &response);
1259 }
1260 
setOnFrameRenderedNotification(const sp<AMessage> & notify)1261 status_t MediaCodec::setOnFrameRenderedNotification(const sp<AMessage> &notify) {
1262     sp<AMessage> msg = new AMessage(kWhatSetNotification, this);
1263     msg->setMessage("on-frame-rendered", notify);
1264     return msg->post();
1265 }
1266 
configure(const sp<AMessage> & format,const sp<Surface> & nativeWindow,const sp<ICrypto> & crypto,uint32_t flags)1267 status_t MediaCodec::configure(
1268         const sp<AMessage> &format,
1269         const sp<Surface> &nativeWindow,
1270         const sp<ICrypto> &crypto,
1271         uint32_t flags) {
1272     return configure(format, nativeWindow, crypto, NULL, flags);
1273 }
1274 
configure(const sp<AMessage> & format,const sp<Surface> & surface,const sp<ICrypto> & crypto,const sp<IDescrambler> & descrambler,uint32_t flags)1275 status_t MediaCodec::configure(
1276         const sp<AMessage> &format,
1277         const sp<Surface> &surface,
1278         const sp<ICrypto> &crypto,
1279         const sp<IDescrambler> &descrambler,
1280         uint32_t flags) {
1281     sp<AMessage> msg = new AMessage(kWhatConfigure, this);
1282 
1283     if (mMetricsHandle != 0) {
1284         int32_t profile = 0;
1285         if (format->findInt32("profile", &profile)) {
1286             mediametrics_setInt32(mMetricsHandle, kCodecProfile, profile);
1287         }
1288         int32_t level = 0;
1289         if (format->findInt32("level", &level)) {
1290             mediametrics_setInt32(mMetricsHandle, kCodecLevel, level);
1291         }
1292         mediametrics_setInt32(mMetricsHandle, kCodecEncoder,
1293                               (flags & CONFIGURE_FLAG_ENCODE) ? 1 : 0);
1294     }
1295 
1296     if (mIsVideo) {
1297         format->findInt32("width", &mVideoWidth);
1298         format->findInt32("height", &mVideoHeight);
1299         if (!format->findInt32("rotation-degrees", &mRotationDegrees)) {
1300             mRotationDegrees = 0;
1301         }
1302 
1303         if (mMetricsHandle != 0) {
1304             mediametrics_setInt32(mMetricsHandle, kCodecWidth, mVideoWidth);
1305             mediametrics_setInt32(mMetricsHandle, kCodecHeight, mVideoHeight);
1306             mediametrics_setInt32(mMetricsHandle, kCodecRotation, mRotationDegrees);
1307             int32_t maxWidth = 0;
1308             if (format->findInt32("max-width", &maxWidth)) {
1309                 mediametrics_setInt32(mMetricsHandle, kCodecMaxWidth, maxWidth);
1310             }
1311             int32_t maxHeight = 0;
1312             if (format->findInt32("max-height", &maxHeight)) {
1313                 mediametrics_setInt32(mMetricsHandle, kCodecMaxHeight, maxHeight);
1314             }
1315         }
1316 
1317         // Prevent possible integer overflow in downstream code.
1318         if (mVideoWidth < 0 || mVideoHeight < 0 ||
1319                (uint64_t)mVideoWidth * mVideoHeight > (uint64_t)INT32_MAX / 4) {
1320             ALOGE("Invalid size(s), width=%d, height=%d", mVideoWidth, mVideoHeight);
1321             return BAD_VALUE;
1322         }
1323     }
1324 
1325     updateLowLatency(format);
1326 
1327     msg->setMessage("format", format);
1328     msg->setInt32("flags", flags);
1329     msg->setObject("surface", surface);
1330 
1331     if (crypto != NULL || descrambler != NULL) {
1332         if (crypto != NULL) {
1333             msg->setPointer("crypto", crypto.get());
1334         } else {
1335             msg->setPointer("descrambler", descrambler.get());
1336         }
1337         if (mMetricsHandle != 0) {
1338             mediametrics_setInt32(mMetricsHandle, kCodecCrypto, 1);
1339         }
1340     } else if (mFlags & kFlagIsSecure) {
1341         ALOGW("Crypto or descrambler should be given for secure codec");
1342     }
1343 
1344     // save msg for reset
1345     mConfigureMsg = msg;
1346 
1347     status_t err;
1348     std::vector<MediaResourceParcel> resources;
1349     resources.push_back(MediaResource::CodecResource(mFlags & kFlagIsSecure, mIsVideo));
1350     // Don't know the buffer size at this point, but it's fine to use 1 because
1351     // the reclaimResource call doesn't consider the requester's buffer size for now.
1352     resources.push_back(MediaResource::GraphicMemoryResource(1));
1353     for (int i = 0; i <= kMaxRetry; ++i) {
1354         if (i > 0) {
1355             // Don't try to reclaim resource for the first time.
1356             if (!mResourceManagerProxy->reclaimResource(resources)) {
1357                 break;
1358             }
1359         }
1360 
1361         sp<AMessage> response;
1362         err = PostAndAwaitResponse(msg, &response);
1363         if (err != OK && err != INVALID_OPERATION) {
1364             // MediaCodec now set state to UNINITIALIZED upon any fatal error.
1365             // To maintain backward-compatibility, do a reset() to put codec
1366             // back into INITIALIZED state.
1367             // But don't reset if the err is INVALID_OPERATION, which means
1368             // the configure failure is due to wrong state.
1369 
1370             ALOGE("configure failed with err 0x%08x, resetting...", err);
1371             reset();
1372         }
1373         if (!isResourceError(err)) {
1374             break;
1375         }
1376     }
1377 
1378     return err;
1379 }
1380 
releaseCrypto()1381 status_t MediaCodec::releaseCrypto()
1382 {
1383     ALOGV("releaseCrypto");
1384 
1385     sp<AMessage> msg = new AMessage(kWhatDrmReleaseCrypto, this);
1386 
1387     sp<AMessage> response;
1388     status_t status = msg->postAndAwaitResponse(&response);
1389 
1390     if (status == OK && response != NULL) {
1391         CHECK(response->findInt32("status", &status));
1392         ALOGV("releaseCrypto ret: %d ", status);
1393     }
1394     else {
1395         ALOGE("releaseCrypto err: %d", status);
1396     }
1397 
1398     return status;
1399 }
1400 
onReleaseCrypto(const sp<AMessage> & msg)1401 void MediaCodec::onReleaseCrypto(const sp<AMessage>& msg)
1402 {
1403     status_t status = INVALID_OPERATION;
1404     if (mCrypto != NULL) {
1405         ALOGV("onReleaseCrypto: mCrypto: %p (%d)", mCrypto.get(), mCrypto->getStrongCount());
1406         mBufferChannel->setCrypto(NULL);
1407         // TODO change to ALOGV
1408         ALOGD("onReleaseCrypto: [before clear]  mCrypto: %p (%d)",
1409                 mCrypto.get(), mCrypto->getStrongCount());
1410         mCrypto.clear();
1411 
1412         status = OK;
1413     }
1414     else {
1415         ALOGW("onReleaseCrypto: No mCrypto. err: %d", status);
1416     }
1417 
1418     sp<AMessage> response = new AMessage;
1419     response->setInt32("status", status);
1420 
1421     sp<AReplyToken> replyID;
1422     CHECK(msg->senderAwaitsResponse(&replyID));
1423     response->postReply(replyID);
1424 }
1425 
setInputSurface(const sp<PersistentSurface> & surface)1426 status_t MediaCodec::setInputSurface(
1427         const sp<PersistentSurface> &surface) {
1428     sp<AMessage> msg = new AMessage(kWhatSetInputSurface, this);
1429     msg->setObject("input-surface", surface.get());
1430 
1431     sp<AMessage> response;
1432     return PostAndAwaitResponse(msg, &response);
1433 }
1434 
setSurface(const sp<Surface> & surface)1435 status_t MediaCodec::setSurface(const sp<Surface> &surface) {
1436     sp<AMessage> msg = new AMessage(kWhatSetSurface, this);
1437     msg->setObject("surface", surface);
1438 
1439     sp<AMessage> response;
1440     return PostAndAwaitResponse(msg, &response);
1441 }
1442 
createInputSurface(sp<IGraphicBufferProducer> * bufferProducer)1443 status_t MediaCodec::createInputSurface(
1444         sp<IGraphicBufferProducer>* bufferProducer) {
1445     sp<AMessage> msg = new AMessage(kWhatCreateInputSurface, this);
1446 
1447     sp<AMessage> response;
1448     status_t err = PostAndAwaitResponse(msg, &response);
1449     if (err == NO_ERROR) {
1450         // unwrap the sp<IGraphicBufferProducer>
1451         sp<RefBase> obj;
1452         bool found = response->findObject("input-surface", &obj);
1453         CHECK(found);
1454         sp<BufferProducerWrapper> wrapper(
1455                 static_cast<BufferProducerWrapper*>(obj.get()));
1456         *bufferProducer = wrapper->getBufferProducer();
1457     } else {
1458         ALOGW("createInputSurface failed, err=%d", err);
1459     }
1460     return err;
1461 }
1462 
getGraphicBufferSize()1463 uint64_t MediaCodec::getGraphicBufferSize() {
1464     if (!mIsVideo) {
1465         return 0;
1466     }
1467 
1468     uint64_t size = 0;
1469     size_t portNum = sizeof(mPortBuffers) / sizeof((mPortBuffers)[0]);
1470     for (size_t i = 0; i < portNum; ++i) {
1471         // TODO: this is just an estimation, we should get the real buffer size from ACodec.
1472         size += mPortBuffers[i].size() * mVideoWidth * mVideoHeight * 3 / 2;
1473     }
1474     return size;
1475 }
1476 
start()1477 status_t MediaCodec::start() {
1478     sp<AMessage> msg = new AMessage(kWhatStart, this);
1479 
1480     status_t err;
1481     std::vector<MediaResourceParcel> resources;
1482     resources.push_back(MediaResource::CodecResource(mFlags & kFlagIsSecure, mIsVideo));
1483     // Don't know the buffer size at this point, but it's fine to use 1 because
1484     // the reclaimResource call doesn't consider the requester's buffer size for now.
1485     resources.push_back(MediaResource::GraphicMemoryResource(1));
1486     for (int i = 0; i <= kMaxRetry; ++i) {
1487         if (i > 0) {
1488             // Don't try to reclaim resource for the first time.
1489             if (!mResourceManagerProxy->reclaimResource(resources)) {
1490                 break;
1491             }
1492             // Recover codec from previous error before retry start.
1493             err = reset();
1494             if (err != OK) {
1495                 ALOGE("retrying start: failed to reset codec");
1496                 break;
1497             }
1498             sp<AMessage> response;
1499             err = PostAndAwaitResponse(mConfigureMsg, &response);
1500             if (err != OK) {
1501                 ALOGE("retrying start: failed to configure codec");
1502                 break;
1503             }
1504         }
1505 
1506         sp<AMessage> response;
1507         err = PostAndAwaitResponse(msg, &response);
1508         if (!isResourceError(err)) {
1509             break;
1510         }
1511     }
1512     return err;
1513 }
1514 
stop()1515 status_t MediaCodec::stop() {
1516     sp<AMessage> msg = new AMessage(kWhatStop, this);
1517 
1518     sp<AMessage> response;
1519     return PostAndAwaitResponse(msg, &response);
1520 }
1521 
hasPendingBuffer(int portIndex)1522 bool MediaCodec::hasPendingBuffer(int portIndex) {
1523     return std::any_of(
1524             mPortBuffers[portIndex].begin(), mPortBuffers[portIndex].end(),
1525             [](const BufferInfo &info) { return info.mOwnedByClient; });
1526 }
1527 
hasPendingBuffer()1528 bool MediaCodec::hasPendingBuffer() {
1529     return hasPendingBuffer(kPortIndexInput) || hasPendingBuffer(kPortIndexOutput);
1530 }
1531 
reclaim(bool force)1532 status_t MediaCodec::reclaim(bool force) {
1533     ALOGD("MediaCodec::reclaim(%p) %s", this, mInitName.c_str());
1534     sp<AMessage> msg = new AMessage(kWhatRelease, this);
1535     msg->setInt32("reclaimed", 1);
1536     msg->setInt32("force", force ? 1 : 0);
1537 
1538     sp<AMessage> response;
1539     status_t ret = PostAndAwaitResponse(msg, &response);
1540     if (ret == -ENOENT) {
1541         ALOGD("MediaCodec looper is gone, skip reclaim");
1542         ret = OK;
1543     }
1544     return ret;
1545 }
1546 
release()1547 status_t MediaCodec::release() {
1548     sp<AMessage> msg = new AMessage(kWhatRelease, this);
1549     sp<AMessage> response;
1550     return PostAndAwaitResponse(msg, &response);
1551 }
1552 
releaseAsync(const sp<AMessage> & notify)1553 status_t MediaCodec::releaseAsync(const sp<AMessage> &notify) {
1554     sp<AMessage> msg = new AMessage(kWhatRelease, this);
1555     msg->setMessage("async", notify);
1556     sp<AMessage> response;
1557     return PostAndAwaitResponse(msg, &response);
1558 }
1559 
reset()1560 status_t MediaCodec::reset() {
1561     /* When external-facing MediaCodec object is created,
1562        it is already initialized.  Thus, reset is essentially
1563        release() followed by init(), plus clearing the state */
1564 
1565     status_t err = release();
1566 
1567     // unregister handlers
1568     if (mCodec != NULL) {
1569         if (mCodecLooper != NULL) {
1570             mCodecLooper->unregisterHandler(mCodec->id());
1571         } else {
1572             mLooper->unregisterHandler(mCodec->id());
1573         }
1574         mCodec = NULL;
1575     }
1576     mLooper->unregisterHandler(id());
1577 
1578     mFlags = 0;    // clear all flags
1579     mStickyError = OK;
1580 
1581     // reset state not reset by setState(UNINITIALIZED)
1582     mDequeueInputReplyID = 0;
1583     mDequeueOutputReplyID = 0;
1584     mDequeueInputTimeoutGeneration = 0;
1585     mDequeueOutputTimeoutGeneration = 0;
1586     mHaveInputSurface = false;
1587 
1588     if (err == OK) {
1589         err = init(mInitName);
1590     }
1591     return err;
1592 }
1593 
queueInputBuffer(size_t index,size_t offset,size_t size,int64_t presentationTimeUs,uint32_t flags,AString * errorDetailMsg)1594 status_t MediaCodec::queueInputBuffer(
1595         size_t index,
1596         size_t offset,
1597         size_t size,
1598         int64_t presentationTimeUs,
1599         uint32_t flags,
1600         AString *errorDetailMsg) {
1601     if (errorDetailMsg != NULL) {
1602         errorDetailMsg->clear();
1603     }
1604 
1605     sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this);
1606     msg->setSize("index", index);
1607     msg->setSize("offset", offset);
1608     msg->setSize("size", size);
1609     msg->setInt64("timeUs", presentationTimeUs);
1610     msg->setInt32("flags", flags);
1611     msg->setPointer("errorDetailMsg", errorDetailMsg);
1612 
1613     sp<AMessage> response;
1614     return PostAndAwaitResponse(msg, &response);
1615 }
1616 
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)1617 status_t MediaCodec::queueSecureInputBuffer(
1618         size_t index,
1619         size_t offset,
1620         const CryptoPlugin::SubSample *subSamples,
1621         size_t numSubSamples,
1622         const uint8_t key[16],
1623         const uint8_t iv[16],
1624         CryptoPlugin::Mode mode,
1625         const CryptoPlugin::Pattern &pattern,
1626         int64_t presentationTimeUs,
1627         uint32_t flags,
1628         AString *errorDetailMsg) {
1629     if (errorDetailMsg != NULL) {
1630         errorDetailMsg->clear();
1631     }
1632 
1633     sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this);
1634     msg->setSize("index", index);
1635     msg->setSize("offset", offset);
1636     msg->setPointer("subSamples", (void *)subSamples);
1637     msg->setSize("numSubSamples", numSubSamples);
1638     msg->setPointer("key", (void *)key);
1639     msg->setPointer("iv", (void *)iv);
1640     msg->setInt32("mode", mode);
1641     msg->setInt32("encryptBlocks", pattern.mEncryptBlocks);
1642     msg->setInt32("skipBlocks", pattern.mSkipBlocks);
1643     msg->setInt64("timeUs", presentationTimeUs);
1644     msg->setInt32("flags", flags);
1645     msg->setPointer("errorDetailMsg", errorDetailMsg);
1646 
1647     sp<AMessage> response;
1648     status_t err = PostAndAwaitResponse(msg, &response);
1649 
1650     return err;
1651 }
1652 
queueBuffer(size_t index,const std::shared_ptr<C2Buffer> & buffer,int64_t presentationTimeUs,uint32_t flags,const sp<AMessage> & tunings,AString * errorDetailMsg)1653 status_t MediaCodec::queueBuffer(
1654         size_t index,
1655         const std::shared_ptr<C2Buffer> &buffer,
1656         int64_t presentationTimeUs,
1657         uint32_t flags,
1658         const sp<AMessage> &tunings,
1659         AString *errorDetailMsg) {
1660     if (errorDetailMsg != NULL) {
1661         errorDetailMsg->clear();
1662     }
1663 
1664     sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this);
1665     msg->setSize("index", index);
1666     sp<WrapperObject<std::shared_ptr<C2Buffer>>> obj{
1667         new WrapperObject<std::shared_ptr<C2Buffer>>{buffer}};
1668     msg->setObject("c2buffer", obj);
1669     msg->setInt64("timeUs", presentationTimeUs);
1670     msg->setInt32("flags", flags);
1671     msg->setMessage("tunings", tunings);
1672     msg->setPointer("errorDetailMsg", errorDetailMsg);
1673 
1674     sp<AMessage> response;
1675     status_t err = PostAndAwaitResponse(msg, &response);
1676 
1677     return err;
1678 }
1679 
queueEncryptedBuffer(size_t index,const sp<hardware::HidlMemory> & buffer,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,const sp<AMessage> & tunings,AString * errorDetailMsg)1680 status_t MediaCodec::queueEncryptedBuffer(
1681         size_t index,
1682         const sp<hardware::HidlMemory> &buffer,
1683         size_t offset,
1684         const CryptoPlugin::SubSample *subSamples,
1685         size_t numSubSamples,
1686         const uint8_t key[16],
1687         const uint8_t iv[16],
1688         CryptoPlugin::Mode mode,
1689         const CryptoPlugin::Pattern &pattern,
1690         int64_t presentationTimeUs,
1691         uint32_t flags,
1692         const sp<AMessage> &tunings,
1693         AString *errorDetailMsg) {
1694     if (errorDetailMsg != NULL) {
1695         errorDetailMsg->clear();
1696     }
1697 
1698     sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this);
1699     msg->setSize("index", index);
1700     sp<WrapperObject<sp<hardware::HidlMemory>>> memory{
1701         new WrapperObject<sp<hardware::HidlMemory>>{buffer}};
1702     msg->setObject("memory", memory);
1703     msg->setSize("offset", offset);
1704     msg->setPointer("subSamples", (void *)subSamples);
1705     msg->setSize("numSubSamples", numSubSamples);
1706     msg->setPointer("key", (void *)key);
1707     msg->setPointer("iv", (void *)iv);
1708     msg->setInt32("mode", mode);
1709     msg->setInt32("encryptBlocks", pattern.mEncryptBlocks);
1710     msg->setInt32("skipBlocks", pattern.mSkipBlocks);
1711     msg->setInt64("timeUs", presentationTimeUs);
1712     msg->setInt32("flags", flags);
1713     msg->setMessage("tunings", tunings);
1714     msg->setPointer("errorDetailMsg", errorDetailMsg);
1715 
1716     sp<AMessage> response;
1717     status_t err = PostAndAwaitResponse(msg, &response);
1718 
1719     return err;
1720 }
1721 
dequeueInputBuffer(size_t * index,int64_t timeoutUs)1722 status_t MediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
1723     sp<AMessage> msg = new AMessage(kWhatDequeueInputBuffer, this);
1724     msg->setInt64("timeoutUs", timeoutUs);
1725 
1726     sp<AMessage> response;
1727     status_t err;
1728     if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
1729         return err;
1730     }
1731 
1732     CHECK(response->findSize("index", index));
1733 
1734     return OK;
1735 }
1736 
dequeueOutputBuffer(size_t * index,size_t * offset,size_t * size,int64_t * presentationTimeUs,uint32_t * flags,int64_t timeoutUs)1737 status_t MediaCodec::dequeueOutputBuffer(
1738         size_t *index,
1739         size_t *offset,
1740         size_t *size,
1741         int64_t *presentationTimeUs,
1742         uint32_t *flags,
1743         int64_t timeoutUs) {
1744     sp<AMessage> msg = new AMessage(kWhatDequeueOutputBuffer, this);
1745     msg->setInt64("timeoutUs", timeoutUs);
1746 
1747     sp<AMessage> response;
1748     status_t err;
1749     if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
1750         return err;
1751     }
1752 
1753     CHECK(response->findSize("index", index));
1754     CHECK(response->findSize("offset", offset));
1755     CHECK(response->findSize("size", size));
1756     CHECK(response->findInt64("timeUs", presentationTimeUs));
1757     CHECK(response->findInt32("flags", (int32_t *)flags));
1758 
1759     return OK;
1760 }
1761 
renderOutputBufferAndRelease(size_t index)1762 status_t MediaCodec::renderOutputBufferAndRelease(size_t index) {
1763     sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, this);
1764     msg->setSize("index", index);
1765     msg->setInt32("render", true);
1766 
1767     sp<AMessage> response;
1768     return PostAndAwaitResponse(msg, &response);
1769 }
1770 
renderOutputBufferAndRelease(size_t index,int64_t timestampNs)1771 status_t MediaCodec::renderOutputBufferAndRelease(size_t index, int64_t timestampNs) {
1772     sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, this);
1773     msg->setSize("index", index);
1774     msg->setInt32("render", true);
1775     msg->setInt64("timestampNs", timestampNs);
1776 
1777     sp<AMessage> response;
1778     return PostAndAwaitResponse(msg, &response);
1779 }
1780 
releaseOutputBuffer(size_t index)1781 status_t MediaCodec::releaseOutputBuffer(size_t index) {
1782     sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, this);
1783     msg->setSize("index", index);
1784 
1785     sp<AMessage> response;
1786     return PostAndAwaitResponse(msg, &response);
1787 }
1788 
signalEndOfInputStream()1789 status_t MediaCodec::signalEndOfInputStream() {
1790     sp<AMessage> msg = new AMessage(kWhatSignalEndOfInputStream, this);
1791 
1792     sp<AMessage> response;
1793     return PostAndAwaitResponse(msg, &response);
1794 }
1795 
getOutputFormat(sp<AMessage> * format) const1796 status_t MediaCodec::getOutputFormat(sp<AMessage> *format) const {
1797     sp<AMessage> msg = new AMessage(kWhatGetOutputFormat, this);
1798 
1799     sp<AMessage> response;
1800     status_t err;
1801     if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
1802         return err;
1803     }
1804 
1805     CHECK(response->findMessage("format", format));
1806 
1807     return OK;
1808 }
1809 
getInputFormat(sp<AMessage> * format) const1810 status_t MediaCodec::getInputFormat(sp<AMessage> *format) const {
1811     sp<AMessage> msg = new AMessage(kWhatGetInputFormat, this);
1812 
1813     sp<AMessage> response;
1814     status_t err;
1815     if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
1816         return err;
1817     }
1818 
1819     CHECK(response->findMessage("format", format));
1820 
1821     return OK;
1822 }
1823 
getName(AString * name) const1824 status_t MediaCodec::getName(AString *name) const {
1825     sp<AMessage> msg = new AMessage(kWhatGetName, this);
1826 
1827     sp<AMessage> response;
1828     status_t err;
1829     if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
1830         return err;
1831     }
1832 
1833     CHECK(response->findString("name", name));
1834 
1835     return OK;
1836 }
1837 
getCodecInfo(sp<MediaCodecInfo> * codecInfo) const1838 status_t MediaCodec::getCodecInfo(sp<MediaCodecInfo> *codecInfo) const {
1839     sp<AMessage> msg = new AMessage(kWhatGetCodecInfo, this);
1840 
1841     sp<AMessage> response;
1842     status_t err;
1843     if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
1844         return err;
1845     }
1846 
1847     sp<RefBase> obj;
1848     CHECK(response->findObject("codecInfo", &obj));
1849     *codecInfo = static_cast<MediaCodecInfo *>(obj.get());
1850 
1851     return OK;
1852 }
1853 
getMetrics(mediametrics_handle_t & reply)1854 status_t MediaCodec::getMetrics(mediametrics_handle_t &reply) {
1855 
1856     reply = 0;
1857 
1858     // shouldn't happen, but be safe
1859     if (mMetricsHandle == 0) {
1860         return UNKNOWN_ERROR;
1861     }
1862 
1863     // update any in-flight data that's not carried within the record
1864     updateMediametrics();
1865 
1866     // send it back to the caller.
1867     reply = mediametrics_dup(mMetricsHandle);
1868 
1869     updateEphemeralMediametrics(reply);
1870 
1871     return OK;
1872 }
1873 
getInputBuffers(Vector<sp<MediaCodecBuffer>> * buffers) const1874 status_t MediaCodec::getInputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const {
1875     sp<AMessage> msg = new AMessage(kWhatGetBuffers, this);
1876     msg->setInt32("portIndex", kPortIndexInput);
1877     msg->setPointer("buffers", buffers);
1878 
1879     sp<AMessage> response;
1880     return PostAndAwaitResponse(msg, &response);
1881 }
1882 
getOutputBuffers(Vector<sp<MediaCodecBuffer>> * buffers) const1883 status_t MediaCodec::getOutputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const {
1884     sp<AMessage> msg = new AMessage(kWhatGetBuffers, this);
1885     msg->setInt32("portIndex", kPortIndexOutput);
1886     msg->setPointer("buffers", buffers);
1887 
1888     sp<AMessage> response;
1889     return PostAndAwaitResponse(msg, &response);
1890 }
1891 
getOutputBuffer(size_t index,sp<MediaCodecBuffer> * buffer)1892 status_t MediaCodec::getOutputBuffer(size_t index, sp<MediaCodecBuffer> *buffer) {
1893     sp<AMessage> format;
1894     return getBufferAndFormat(kPortIndexOutput, index, buffer, &format);
1895 }
1896 
getOutputFormat(size_t index,sp<AMessage> * format)1897 status_t MediaCodec::getOutputFormat(size_t index, sp<AMessage> *format) {
1898     sp<MediaCodecBuffer> buffer;
1899     return getBufferAndFormat(kPortIndexOutput, index, &buffer, format);
1900 }
1901 
getInputBuffer(size_t index,sp<MediaCodecBuffer> * buffer)1902 status_t MediaCodec::getInputBuffer(size_t index, sp<MediaCodecBuffer> *buffer) {
1903     sp<AMessage> format;
1904     return getBufferAndFormat(kPortIndexInput, index, buffer, &format);
1905 }
1906 
isExecuting() const1907 bool MediaCodec::isExecuting() const {
1908     return mState == STARTED || mState == FLUSHED;
1909 }
1910 
getBufferAndFormat(size_t portIndex,size_t index,sp<MediaCodecBuffer> * buffer,sp<AMessage> * format)1911 status_t MediaCodec::getBufferAndFormat(
1912         size_t portIndex, size_t index,
1913         sp<MediaCodecBuffer> *buffer, sp<AMessage> *format) {
1914     // use mutex instead of a context switch
1915     if (mReleasedByResourceManager) {
1916         ALOGE("getBufferAndFormat - resource already released");
1917         return DEAD_OBJECT;
1918     }
1919 
1920     if (buffer == NULL) {
1921         ALOGE("getBufferAndFormat - null MediaCodecBuffer");
1922         return INVALID_OPERATION;
1923     }
1924 
1925     if (format == NULL) {
1926         ALOGE("getBufferAndFormat - null AMessage");
1927         return INVALID_OPERATION;
1928     }
1929 
1930     buffer->clear();
1931     format->clear();
1932 
1933     if (!isExecuting()) {
1934         ALOGE("getBufferAndFormat - not executing");
1935         return INVALID_OPERATION;
1936     }
1937 
1938     // we do not want mPortBuffers to change during this section
1939     // we also don't want mOwnedByClient to change during this
1940     Mutex::Autolock al(mBufferLock);
1941 
1942     std::vector<BufferInfo> &buffers = mPortBuffers[portIndex];
1943     if (index >= buffers.size()) {
1944         ALOGE("getBufferAndFormat - trying to get buffer with "
1945               "bad index (index=%zu buffer_size=%zu)", index, buffers.size());
1946         return INVALID_OPERATION;
1947     }
1948 
1949     const BufferInfo &info = buffers[index];
1950     if (!info.mOwnedByClient) {
1951         ALOGE("getBufferAndFormat - invalid operation "
1952               "(the index %zu is not owned by client)", index);
1953         return INVALID_OPERATION;
1954     }
1955 
1956     *buffer = info.mData;
1957     *format = info.mData->format();
1958 
1959     return OK;
1960 }
1961 
flush()1962 status_t MediaCodec::flush() {
1963     sp<AMessage> msg = new AMessage(kWhatFlush, this);
1964 
1965     sp<AMessage> response;
1966     return PostAndAwaitResponse(msg, &response);
1967 }
1968 
requestIDRFrame()1969 status_t MediaCodec::requestIDRFrame() {
1970     (new AMessage(kWhatRequestIDRFrame, this))->post();
1971 
1972     return OK;
1973 }
1974 
requestActivityNotification(const sp<AMessage> & notify)1975 void MediaCodec::requestActivityNotification(const sp<AMessage> &notify) {
1976     sp<AMessage> msg = new AMessage(kWhatRequestActivityNotification, this);
1977     msg->setMessage("notify", notify);
1978     msg->post();
1979 }
1980 
requestCpuBoostIfNeeded()1981 void MediaCodec::requestCpuBoostIfNeeded() {
1982     if (mCpuBoostRequested) {
1983         return;
1984     }
1985     int32_t colorFormat;
1986     if (mOutputFormat->contains("hdr-static-info")
1987             && mOutputFormat->findInt32("color-format", &colorFormat)
1988             // check format for OMX only, for C2 the format is always opaque since the
1989             // software rendering doesn't go through client
1990             && ((mSoftRenderer != NULL && colorFormat == OMX_COLOR_FormatYUV420Planar16)
1991                     || mOwnerName.equalsIgnoreCase("codec2::software"))) {
1992         int32_t left, top, right, bottom, width, height;
1993         int64_t totalPixel = 0;
1994         if (mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) {
1995             totalPixel = (right - left + 1) * (bottom - top + 1);
1996         } else if (mOutputFormat->findInt32("width", &width)
1997                 && mOutputFormat->findInt32("height", &height)) {
1998             totalPixel = width * height;
1999         }
2000         if (totalPixel >= 1920 * 1080) {
2001             mResourceManagerProxy->addResource(MediaResource::CpuBoostResource());
2002             mCpuBoostRequested = true;
2003         }
2004     }
2005 }
2006 
BatteryChecker(const sp<AMessage> & msg,int64_t timeoutUs)2007 BatteryChecker::BatteryChecker(const sp<AMessage> &msg, int64_t timeoutUs)
2008     : mTimeoutUs(timeoutUs)
2009     , mLastActivityTimeUs(-1ll)
2010     , mBatteryStatNotified(false)
2011     , mBatteryCheckerGeneration(0)
2012     , mIsExecuting(false)
2013     , mBatteryCheckerMsg(msg) {}
2014 
onCodecActivity(std::function<void ()> batteryOnCb)2015 void BatteryChecker::onCodecActivity(std::function<void()> batteryOnCb) {
2016     if (!isExecuting()) {
2017         // ignore if not executing
2018         return;
2019     }
2020     if (!mBatteryStatNotified) {
2021         batteryOnCb();
2022         mBatteryStatNotified = true;
2023         sp<AMessage> msg = mBatteryCheckerMsg->dup();
2024         msg->setInt32("generation", mBatteryCheckerGeneration);
2025 
2026         // post checker and clear last activity time
2027         msg->post(mTimeoutUs);
2028         mLastActivityTimeUs = -1ll;
2029     } else {
2030         // update last activity time
2031         mLastActivityTimeUs = ALooper::GetNowUs();
2032     }
2033 }
2034 
onCheckBatteryTimer(const sp<AMessage> & msg,std::function<void ()> batteryOffCb)2035 void BatteryChecker::onCheckBatteryTimer(
2036         const sp<AMessage> &msg, std::function<void()> batteryOffCb) {
2037     // ignore if this checker already expired because the client resource was removed
2038     int32_t generation;
2039     if (!msg->findInt32("generation", &generation)
2040             || generation != mBatteryCheckerGeneration) {
2041         return;
2042     }
2043 
2044     if (mLastActivityTimeUs < 0ll) {
2045         // timed out inactive, do not repost checker
2046         batteryOffCb();
2047         mBatteryStatNotified = false;
2048     } else {
2049         // repost checker and clear last activity time
2050         msg->post(mTimeoutUs + mLastActivityTimeUs - ALooper::GetNowUs());
2051         mLastActivityTimeUs = -1ll;
2052     }
2053 }
2054 
onClientRemoved()2055 void BatteryChecker::onClientRemoved() {
2056     mBatteryStatNotified = false;
2057     mBatteryCheckerGeneration++;
2058 }
2059 
2060 ////////////////////////////////////////////////////////////////////////////////
2061 
cancelPendingDequeueOperations()2062 void MediaCodec::cancelPendingDequeueOperations() {
2063     if (mFlags & kFlagDequeueInputPending) {
2064         PostReplyWithError(mDequeueInputReplyID, INVALID_OPERATION);
2065 
2066         ++mDequeueInputTimeoutGeneration;
2067         mDequeueInputReplyID = 0;
2068         mFlags &= ~kFlagDequeueInputPending;
2069     }
2070 
2071     if (mFlags & kFlagDequeueOutputPending) {
2072         PostReplyWithError(mDequeueOutputReplyID, INVALID_OPERATION);
2073 
2074         ++mDequeueOutputTimeoutGeneration;
2075         mDequeueOutputReplyID = 0;
2076         mFlags &= ~kFlagDequeueOutputPending;
2077     }
2078 }
2079 
handleDequeueInputBuffer(const sp<AReplyToken> & replyID,bool newRequest)2080 bool MediaCodec::handleDequeueInputBuffer(const sp<AReplyToken> &replyID, bool newRequest) {
2081     if (!isExecuting() || (mFlags & kFlagIsAsync)
2082             || (newRequest && (mFlags & kFlagDequeueInputPending))) {
2083         PostReplyWithError(replyID, INVALID_OPERATION);
2084         return true;
2085     } else if (mFlags & kFlagStickyError) {
2086         PostReplyWithError(replyID, getStickyError());
2087         return true;
2088     }
2089 
2090     ssize_t index = dequeuePortBuffer(kPortIndexInput);
2091 
2092     if (index < 0) {
2093         CHECK_EQ(index, -EAGAIN);
2094         return false;
2095     }
2096 
2097     sp<AMessage> response = new AMessage;
2098     response->setSize("index", index);
2099     response->postReply(replyID);
2100 
2101     return true;
2102 }
2103 
handleDequeueOutputBuffer(const sp<AReplyToken> & replyID,bool newRequest)2104 bool MediaCodec::handleDequeueOutputBuffer(const sp<AReplyToken> &replyID, bool newRequest) {
2105     if (!isExecuting() || (mFlags & kFlagIsAsync)
2106             || (newRequest && (mFlags & kFlagDequeueOutputPending))) {
2107         PostReplyWithError(replyID, INVALID_OPERATION);
2108     } else if (mFlags & kFlagStickyError) {
2109         PostReplyWithError(replyID, getStickyError());
2110     } else if (mFlags & kFlagOutputBuffersChanged) {
2111         PostReplyWithError(replyID, INFO_OUTPUT_BUFFERS_CHANGED);
2112         mFlags &= ~kFlagOutputBuffersChanged;
2113     } else {
2114         sp<AMessage> response = new AMessage;
2115         BufferInfo *info = peekNextPortBuffer(kPortIndexOutput);
2116         if (!info) {
2117             return false;
2118         }
2119 
2120         // In synchronous mode, output format change should be handled
2121         // at dequeue to put the event at the correct order.
2122 
2123         const sp<MediaCodecBuffer> &buffer = info->mData;
2124         handleOutputFormatChangeIfNeeded(buffer);
2125         if (mFlags & kFlagOutputFormatChanged) {
2126             PostReplyWithError(replyID, INFO_FORMAT_CHANGED);
2127             mFlags &= ~kFlagOutputFormatChanged;
2128             return true;
2129         }
2130 
2131         ssize_t index = dequeuePortBuffer(kPortIndexOutput);
2132 
2133         response->setSize("index", index);
2134         response->setSize("offset", buffer->offset());
2135         response->setSize("size", buffer->size());
2136 
2137         int64_t timeUs;
2138         CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
2139 
2140         statsBufferReceived(timeUs);
2141 
2142         response->setInt64("timeUs", timeUs);
2143 
2144         int32_t flags;
2145         CHECK(buffer->meta()->findInt32("flags", &flags));
2146 
2147         response->setInt32("flags", flags);
2148         response->postReply(replyID);
2149     }
2150 
2151     return true;
2152 }
2153 
onMessageReceived(const sp<AMessage> & msg)2154 void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
2155     switch (msg->what()) {
2156         case kWhatCodecNotify:
2157         {
2158             int32_t what;
2159             CHECK(msg->findInt32("what", &what));
2160 
2161             switch (what) {
2162                 case kWhatError:
2163                 {
2164                     int32_t err, actionCode;
2165                     CHECK(msg->findInt32("err", &err));
2166                     CHECK(msg->findInt32("actionCode", &actionCode));
2167 
2168                     ALOGE("Codec reported err %#x, actionCode %d, while in state %d",
2169                             err, actionCode, mState);
2170                     if (err == DEAD_OBJECT) {
2171                         mFlags |= kFlagSawMediaServerDie;
2172                         mFlags &= ~kFlagIsComponentAllocated;
2173                     }
2174 
2175                     bool sendErrorResponse = true;
2176                     std::string origin{"kWhatError:"};
2177                     origin += stateString(mState);
2178 
2179                     switch (mState) {
2180                         case INITIALIZING:
2181                         {
2182                             setState(UNINITIALIZED);
2183                             break;
2184                         }
2185 
2186                         case CONFIGURING:
2187                         {
2188                             if (actionCode == ACTION_CODE_FATAL) {
2189                                 mediametrics_setInt32(mMetricsHandle, kCodecError, err);
2190                                 mediametrics_setCString(mMetricsHandle, kCodecErrorState,
2191                                                         stateString(mState).c_str());
2192                                 flushMediametrics();
2193                                 initMediametrics();
2194                             }
2195                             setState(actionCode == ACTION_CODE_FATAL ?
2196                                     UNINITIALIZED : INITIALIZED);
2197                             break;
2198                         }
2199 
2200                         case STARTING:
2201                         {
2202                             if (actionCode == ACTION_CODE_FATAL) {
2203                                 mediametrics_setInt32(mMetricsHandle, kCodecError, err);
2204                                 mediametrics_setCString(mMetricsHandle, kCodecErrorState,
2205                                                         stateString(mState).c_str());
2206                                 flushMediametrics();
2207                                 initMediametrics();
2208                             }
2209                             setState(actionCode == ACTION_CODE_FATAL ?
2210                                     UNINITIALIZED : CONFIGURED);
2211                             break;
2212                         }
2213 
2214                         case RELEASING:
2215                         {
2216                             // Ignore the error, assuming we'll still get
2217                             // the shutdown complete notification. If we
2218                             // don't, we'll timeout and force release.
2219                             sendErrorResponse = false;
2220                             FALLTHROUGH_INTENDED;
2221                         }
2222                         case STOPPING:
2223                         {
2224                             if (mFlags & kFlagSawMediaServerDie) {
2225                                 // MediaServer died, there definitely won't
2226                                 // be a shutdown complete notification after
2227                                 // all.
2228 
2229                                 // note that we may be directly going from
2230                                 // STOPPING->UNINITIALIZED, instead of the
2231                                 // usual STOPPING->INITIALIZED state.
2232                                 setState(UNINITIALIZED);
2233                                 if (mState == RELEASING) {
2234                                     mComponentName.clear();
2235                                 }
2236                                 postPendingRepliesAndDeferredMessages(origin + ":dead");
2237                                 sendErrorResponse = false;
2238                             }
2239                             break;
2240                         }
2241 
2242                         case FLUSHING:
2243                         {
2244                             if (actionCode == ACTION_CODE_FATAL) {
2245                                 mediametrics_setInt32(mMetricsHandle, kCodecError, err);
2246                                 mediametrics_setCString(mMetricsHandle, kCodecErrorState,
2247                                                         stateString(mState).c_str());
2248                                 flushMediametrics();
2249                                 initMediametrics();
2250 
2251                                 setState(UNINITIALIZED);
2252                             } else {
2253                                 setState(
2254                                         (mFlags & kFlagIsAsync) ? FLUSHED : STARTED);
2255                             }
2256                             break;
2257                         }
2258 
2259                         case FLUSHED:
2260                         case STARTED:
2261                         {
2262                             sendErrorResponse = (mReplyID != nullptr);
2263 
2264                             setStickyError(err);
2265                             postActivityNotificationIfPossible();
2266 
2267                             cancelPendingDequeueOperations();
2268 
2269                             if (mFlags & kFlagIsAsync) {
2270                                 onError(err, actionCode);
2271                             }
2272                             switch (actionCode) {
2273                             case ACTION_CODE_TRANSIENT:
2274                                 break;
2275                             case ACTION_CODE_RECOVERABLE:
2276                                 setState(INITIALIZED);
2277                                 break;
2278                             default:
2279                                 mediametrics_setInt32(mMetricsHandle, kCodecError, err);
2280                                 mediametrics_setCString(mMetricsHandle, kCodecErrorState,
2281                                                         stateString(mState).c_str());
2282                                 flushMediametrics();
2283                                 initMediametrics();
2284                                 setState(UNINITIALIZED);
2285                                 break;
2286                             }
2287                             break;
2288                         }
2289 
2290                         default:
2291                         {
2292                             sendErrorResponse = (mReplyID != nullptr);
2293 
2294                             setStickyError(err);
2295                             postActivityNotificationIfPossible();
2296 
2297                             // actionCode in an uninitialized state is always fatal.
2298                             if (mState == UNINITIALIZED) {
2299                                 actionCode = ACTION_CODE_FATAL;
2300                             }
2301                             if (mFlags & kFlagIsAsync) {
2302                                 onError(err, actionCode);
2303                             }
2304                             switch (actionCode) {
2305                             case ACTION_CODE_TRANSIENT:
2306                                 break;
2307                             case ACTION_CODE_RECOVERABLE:
2308                                 setState(INITIALIZED);
2309                                 break;
2310                             default:
2311                                 setState(UNINITIALIZED);
2312                                 break;
2313                             }
2314                             break;
2315                         }
2316                     }
2317 
2318                     if (sendErrorResponse) {
2319                         // TRICKY: replicate PostReplyWithError logic for
2320                         //         err code override
2321                         int32_t finalErr = err;
2322                         if (mReleasedByResourceManager) {
2323                             // override the err code if MediaCodec has been
2324                             // released by ResourceManager.
2325                             finalErr = DEAD_OBJECT;
2326                         }
2327                         postPendingRepliesAndDeferredMessages(origin, finalErr);
2328                     }
2329                     break;
2330                 }
2331 
2332                 case kWhatComponentAllocated:
2333                 {
2334                     if (mState == RELEASING || mState == UNINITIALIZED) {
2335                         // In case a kWhatError or kWhatRelease message came in and replied,
2336                         // we log a warning and ignore.
2337                         ALOGW("allocate interrupted by error or release, current state %d",
2338                               mState);
2339                         break;
2340                     }
2341                     CHECK_EQ(mState, INITIALIZING);
2342                     setState(INITIALIZED);
2343                     mFlags |= kFlagIsComponentAllocated;
2344 
2345                     CHECK(msg->findString("componentName", &mComponentName));
2346 
2347                     if (mComponentName.c_str()) {
2348                         mediametrics_setCString(mMetricsHandle, kCodecCodec,
2349                                                 mComponentName.c_str());
2350                     }
2351 
2352                     const char *owner = mCodecInfo ? mCodecInfo->getOwnerName() : "";
2353                     if (mComponentName.startsWith("OMX.google.")
2354                             && strncmp(owner, "default", 8) == 0) {
2355                         mFlags |= kFlagUsesSoftwareRenderer;
2356                     } else {
2357                         mFlags &= ~kFlagUsesSoftwareRenderer;
2358                     }
2359                     mOwnerName = owner;
2360 
2361                     if (mComponentName.endsWith(".secure")) {
2362                         mFlags |= kFlagIsSecure;
2363                         mediametrics_setInt32(mMetricsHandle, kCodecSecure, 1);
2364                     } else {
2365                         mFlags &= ~kFlagIsSecure;
2366                         mediametrics_setInt32(mMetricsHandle, kCodecSecure, 0);
2367                     }
2368 
2369                     if (mIsVideo) {
2370                         // audio codec is currently ignored.
2371                         mResourceManagerProxy->addResource(
2372                                 MediaResource::CodecResource(mFlags & kFlagIsSecure, mIsVideo));
2373                     }
2374 
2375                     postPendingRepliesAndDeferredMessages("kWhatComponentAllocated");
2376                     break;
2377                 }
2378 
2379                 case kWhatComponentConfigured:
2380                 {
2381                     if (mState == RELEASING || mState == UNINITIALIZED || mState == INITIALIZED) {
2382                         // In case a kWhatError or kWhatRelease message came in and replied,
2383                         // we log a warning and ignore.
2384                         ALOGW("configure interrupted by error or release, current state %d",
2385                               mState);
2386                         break;
2387                     }
2388                     CHECK_EQ(mState, CONFIGURING);
2389 
2390                     // reset input surface flag
2391                     mHaveInputSurface = false;
2392 
2393                     CHECK(msg->findMessage("input-format", &mInputFormat));
2394                     CHECK(msg->findMessage("output-format", &mOutputFormat));
2395 
2396                     // limit to confirming the opt-in behavior to minimize any behavioral change
2397                     if (mSurface != nullptr && !mAllowFrameDroppingBySurface) {
2398                         // signal frame dropping mode in the input format as this may also be
2399                         // meaningful and confusing for an encoder in a transcoder scenario
2400                         mInputFormat->setInt32("allow-frame-drop", mAllowFrameDroppingBySurface);
2401                     }
2402                     sp<AMessage> interestingFormat =
2403                             (mFlags & kFlagIsEncoder) ? mOutputFormat : mInputFormat;
2404                     ALOGV("[%s] configured as input format: %s, output format: %s",
2405                             mComponentName.c_str(),
2406                             mInputFormat->debugString(4).c_str(),
2407                             mOutputFormat->debugString(4).c_str());
2408                     int32_t usingSwRenderer;
2409                     if (mOutputFormat->findInt32("using-sw-renderer", &usingSwRenderer)
2410                             && usingSwRenderer) {
2411                         mFlags |= kFlagUsesSoftwareRenderer;
2412                     }
2413                     setState(CONFIGURED);
2414                     postPendingRepliesAndDeferredMessages("kWhatComponentConfigured");
2415 
2416                     // augment our media metrics info, now that we know more things
2417                     // such as what the codec extracted from any CSD passed in.
2418                     if (mMetricsHandle != 0) {
2419                         sp<AMessage> format;
2420                         if (mConfigureMsg != NULL &&
2421                             mConfigureMsg->findMessage("format", &format)) {
2422                                 // format includes: mime
2423                                 AString mime;
2424                                 if (format->findString("mime", &mime)) {
2425                                     mediametrics_setCString(mMetricsHandle, kCodecMime,
2426                                                             mime.c_str());
2427                                 }
2428                             }
2429                         // perhaps video only?
2430                         int32_t profile = 0;
2431                         if (interestingFormat->findInt32("profile", &profile)) {
2432                             mediametrics_setInt32(mMetricsHandle, kCodecProfile, profile);
2433                         }
2434                         int32_t level = 0;
2435                         if (interestingFormat->findInt32("level", &level)) {
2436                             mediametrics_setInt32(mMetricsHandle, kCodecLevel, level);
2437                         }
2438                         // bitrate and bitrate mode, encoder only
2439                         if (mFlags & kFlagIsEncoder) {
2440                             // encoder specific values
2441                             int32_t bitrate_mode = -1;
2442                             if (mOutputFormat->findInt32(KEY_BITRATE_MODE, &bitrate_mode)) {
2443                                     mediametrics_setCString(mMetricsHandle, kCodecBitrateMode,
2444                                           asString_BitrateMode(bitrate_mode));
2445                             }
2446                             int32_t bitrate = -1;
2447                             if (mOutputFormat->findInt32(KEY_BIT_RATE, &bitrate)) {
2448                                     mediametrics_setInt32(mMetricsHandle, kCodecBitrate, bitrate);
2449                             }
2450                         } else {
2451                             // decoder specific values
2452                         }
2453                     }
2454                     break;
2455                 }
2456 
2457                 case kWhatInputSurfaceCreated:
2458                 {
2459                     if (mState != CONFIGURED) {
2460                         // state transitioned unexpectedly; we should have replied already.
2461                         ALOGD("received kWhatInputSurfaceCreated message in state %s",
2462                                 stateString(mState).c_str());
2463                         break;
2464                     }
2465                     // response to initiateCreateInputSurface()
2466                     status_t err = NO_ERROR;
2467                     sp<AMessage> response = new AMessage;
2468                     if (!msg->findInt32("err", &err)) {
2469                         sp<RefBase> obj;
2470                         msg->findObject("input-surface", &obj);
2471                         CHECK(msg->findMessage("input-format", &mInputFormat));
2472                         CHECK(msg->findMessage("output-format", &mOutputFormat));
2473                         ALOGV("[%s] input surface created as input format: %s, output format: %s",
2474                                 mComponentName.c_str(),
2475                                 mInputFormat->debugString(4).c_str(),
2476                                 mOutputFormat->debugString(4).c_str());
2477                         CHECK(obj != NULL);
2478                         response->setObject("input-surface", obj);
2479                         mHaveInputSurface = true;
2480                     } else {
2481                         response->setInt32("err", err);
2482                     }
2483                     postPendingRepliesAndDeferredMessages("kWhatInputSurfaceCreated", response);
2484                     break;
2485                 }
2486 
2487                 case kWhatInputSurfaceAccepted:
2488                 {
2489                     if (mState != CONFIGURED) {
2490                         // state transitioned unexpectedly; we should have replied already.
2491                         ALOGD("received kWhatInputSurfaceAccepted message in state %s",
2492                                 stateString(mState).c_str());
2493                         break;
2494                     }
2495                     // response to initiateSetInputSurface()
2496                     status_t err = NO_ERROR;
2497                     sp<AMessage> response = new AMessage();
2498                     if (!msg->findInt32("err", &err)) {
2499                         CHECK(msg->findMessage("input-format", &mInputFormat));
2500                         CHECK(msg->findMessage("output-format", &mOutputFormat));
2501                         mHaveInputSurface = true;
2502                     } else {
2503                         response->setInt32("err", err);
2504                     }
2505                     postPendingRepliesAndDeferredMessages("kWhatInputSurfaceAccepted", response);
2506                     break;
2507                 }
2508 
2509                 case kWhatSignaledInputEOS:
2510                 {
2511                     if (!isExecuting()) {
2512                         // state transitioned unexpectedly; we should have replied already.
2513                         ALOGD("received kWhatSignaledInputEOS message in state %s",
2514                                 stateString(mState).c_str());
2515                         break;
2516                     }
2517                     // response to signalEndOfInputStream()
2518                     sp<AMessage> response = new AMessage;
2519                     status_t err;
2520                     if (msg->findInt32("err", &err)) {
2521                         response->setInt32("err", err);
2522                     }
2523                     postPendingRepliesAndDeferredMessages("kWhatSignaledInputEOS", response);
2524                     break;
2525                 }
2526 
2527                 case kWhatStartCompleted:
2528                 {
2529                     if (mState == RELEASING || mState == UNINITIALIZED) {
2530                         // In case a kWhatRelease message came in and replied,
2531                         // we log a warning and ignore.
2532                         ALOGW("start interrupted by release, current state %d", mState);
2533                         break;
2534                     }
2535 
2536                     CHECK_EQ(mState, STARTING);
2537                     if (mIsVideo) {
2538                         mResourceManagerProxy->addResource(
2539                                 MediaResource::GraphicMemoryResource(getGraphicBufferSize()));
2540                     }
2541                     setState(STARTED);
2542                     postPendingRepliesAndDeferredMessages("kWhatStartCompleted");
2543                     break;
2544                 }
2545 
2546                 case kWhatOutputBuffersChanged:
2547                 {
2548                     mFlags |= kFlagOutputBuffersChanged;
2549                     postActivityNotificationIfPossible();
2550                     break;
2551                 }
2552 
2553                 case kWhatOutputFramesRendered:
2554                 {
2555                     // ignore these in all states except running, and check that we have a
2556                     // notification set
2557                     if (mState == STARTED && mOnFrameRenderedNotification != NULL) {
2558                         sp<AMessage> notify = mOnFrameRenderedNotification->dup();
2559                         notify->setMessage("data", msg);
2560                         notify->post();
2561                     }
2562                     break;
2563                 }
2564 
2565                 case kWhatFillThisBuffer:
2566                 {
2567                     /* size_t index = */updateBuffers(kPortIndexInput, msg);
2568 
2569                     if (mState == FLUSHING
2570                             || mState == STOPPING
2571                             || mState == RELEASING) {
2572                         returnBuffersToCodecOnPort(kPortIndexInput);
2573                         break;
2574                     }
2575 
2576                     if (!mCSD.empty()) {
2577                         ssize_t index = dequeuePortBuffer(kPortIndexInput);
2578                         CHECK_GE(index, 0);
2579 
2580                         // If codec specific data had been specified as
2581                         // part of the format in the call to configure and
2582                         // if there's more csd left, we submit it here
2583                         // clients only get access to input buffers once
2584                         // this data has been exhausted.
2585 
2586                         status_t err = queueCSDInputBuffer(index);
2587 
2588                         if (err != OK) {
2589                             ALOGE("queueCSDInputBuffer failed w/ error %d",
2590                                   err);
2591 
2592                             setStickyError(err);
2593                             postActivityNotificationIfPossible();
2594 
2595                             cancelPendingDequeueOperations();
2596                         }
2597                         break;
2598                     }
2599                     if (!mLeftover.empty()) {
2600                         ssize_t index = dequeuePortBuffer(kPortIndexInput);
2601                         CHECK_GE(index, 0);
2602 
2603                         status_t err = handleLeftover(index);
2604                         if (err != OK) {
2605                             setStickyError(err);
2606                             postActivityNotificationIfPossible();
2607                             cancelPendingDequeueOperations();
2608                         }
2609                         break;
2610                     }
2611 
2612                     if (mFlags & kFlagIsAsync) {
2613                         if (!mHaveInputSurface) {
2614                             if (mState == FLUSHED) {
2615                                 mHavePendingInputBuffers = true;
2616                             } else {
2617                                 onInputBufferAvailable();
2618                             }
2619                         }
2620                     } else if (mFlags & kFlagDequeueInputPending) {
2621                         CHECK(handleDequeueInputBuffer(mDequeueInputReplyID));
2622 
2623                         ++mDequeueInputTimeoutGeneration;
2624                         mFlags &= ~kFlagDequeueInputPending;
2625                         mDequeueInputReplyID = 0;
2626                     } else {
2627                         postActivityNotificationIfPossible();
2628                     }
2629                     break;
2630                 }
2631 
2632                 case kWhatDrainThisBuffer:
2633                 {
2634                     /* size_t index = */updateBuffers(kPortIndexOutput, msg);
2635 
2636                     if (mState == FLUSHING
2637                             || mState == STOPPING
2638                             || mState == RELEASING) {
2639                         returnBuffersToCodecOnPort(kPortIndexOutput);
2640                         break;
2641                     }
2642 
2643                     if (mFlags & kFlagIsAsync) {
2644                         sp<RefBase> obj;
2645                         CHECK(msg->findObject("buffer", &obj));
2646                         sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
2647 
2648                         // In asynchronous mode, output format change is processed immediately.
2649                         handleOutputFormatChangeIfNeeded(buffer);
2650                         onOutputBufferAvailable();
2651                     } else if (mFlags & kFlagDequeueOutputPending) {
2652                         CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID));
2653 
2654                         ++mDequeueOutputTimeoutGeneration;
2655                         mFlags &= ~kFlagDequeueOutputPending;
2656                         mDequeueOutputReplyID = 0;
2657                     } else {
2658                         postActivityNotificationIfPossible();
2659                     }
2660 
2661                     break;
2662                 }
2663 
2664                 case kWhatEOS:
2665                 {
2666                     // We already notify the client of this by using the
2667                     // corresponding flag in "onOutputBufferReady".
2668                     break;
2669                 }
2670 
2671                 case kWhatStopCompleted:
2672                 {
2673                     if (mState != STOPPING) {
2674                         ALOGW("Received kWhatStopCompleted in state %d", mState);
2675                         break;
2676                     }
2677                     setState(INITIALIZED);
2678                     if (mReplyID) {
2679                         postPendingRepliesAndDeferredMessages("kWhatStopCompleted");
2680                     } else {
2681                         ALOGW("kWhatStopCompleted: presumably an error occurred earlier, "
2682                               "but the operation completed anyway. (last reply origin=%s)",
2683                               mLastReplyOrigin.c_str());
2684                     }
2685                     break;
2686                 }
2687 
2688                 case kWhatReleaseCompleted:
2689                 {
2690                     if (mState != RELEASING) {
2691                         ALOGW("Received kWhatReleaseCompleted in state %d", mState);
2692                         break;
2693                     }
2694                     setState(UNINITIALIZED);
2695                     mComponentName.clear();
2696 
2697                     mFlags &= ~kFlagIsComponentAllocated;
2698 
2699                     // off since we're removing all resources including the battery on
2700                     if (mBatteryChecker != nullptr) {
2701                         mBatteryChecker->onClientRemoved();
2702                     }
2703 
2704                     mResourceManagerProxy->removeClient();
2705                     mReleaseSurface.reset();
2706 
2707                     if (mReplyID != nullptr) {
2708                         postPendingRepliesAndDeferredMessages("kWhatReleaseCompleted");
2709                     }
2710                     if (mAsyncReleaseCompleteNotification != nullptr) {
2711                         flushMediametrics();
2712                         mAsyncReleaseCompleteNotification->post();
2713                         mAsyncReleaseCompleteNotification.clear();
2714                     }
2715                     break;
2716                 }
2717 
2718                 case kWhatFlushCompleted:
2719                 {
2720                     if (mState != FLUSHING) {
2721                         ALOGW("received FlushCompleted message in state %d",
2722                                 mState);
2723                         break;
2724                     }
2725 
2726                     if (mFlags & kFlagIsAsync) {
2727                         setState(FLUSHED);
2728                     } else {
2729                         setState(STARTED);
2730                         mCodec->signalResume();
2731                     }
2732 
2733                     postPendingRepliesAndDeferredMessages("kWhatFlushCompleted");
2734                     break;
2735                 }
2736 
2737                 default:
2738                     TRESPASS();
2739             }
2740             break;
2741         }
2742 
2743         case kWhatInit:
2744         {
2745             if (mState != UNINITIALIZED) {
2746                 PostReplyWithError(msg, INVALID_OPERATION);
2747                 break;
2748             }
2749 
2750             if (mReplyID) {
2751                 mDeferredMessages.push_back(msg);
2752                 break;
2753             }
2754             sp<AReplyToken> replyID;
2755             CHECK(msg->senderAwaitsResponse(&replyID));
2756 
2757             mReplyID = replyID;
2758             setState(INITIALIZING);
2759 
2760             sp<RefBase> codecInfo;
2761             (void)msg->findObject("codecInfo", &codecInfo);
2762             AString name;
2763             CHECK(msg->findString("name", &name));
2764 
2765             sp<AMessage> format = new AMessage;
2766             if (codecInfo) {
2767                 format->setObject("codecInfo", codecInfo);
2768             }
2769             format->setString("componentName", name);
2770 
2771             mCodec->initiateAllocateComponent(format);
2772             break;
2773         }
2774 
2775         case kWhatSetNotification:
2776         {
2777             sp<AMessage> notify;
2778             if (msg->findMessage("on-frame-rendered", &notify)) {
2779                 mOnFrameRenderedNotification = notify;
2780             }
2781             break;
2782         }
2783 
2784         case kWhatSetCallback:
2785         {
2786             sp<AReplyToken> replyID;
2787             CHECK(msg->senderAwaitsResponse(&replyID));
2788 
2789             if (mState == UNINITIALIZED
2790                     || mState == INITIALIZING
2791                     || isExecuting()) {
2792                 // callback can't be set after codec is executing,
2793                 // or before it's initialized (as the callback
2794                 // will be cleared when it goes to INITIALIZED)
2795                 PostReplyWithError(replyID, INVALID_OPERATION);
2796                 break;
2797             }
2798 
2799             sp<AMessage> callback;
2800             CHECK(msg->findMessage("callback", &callback));
2801 
2802             mCallback = callback;
2803 
2804             if (mCallback != NULL) {
2805                 ALOGI("MediaCodec will operate in async mode");
2806                 mFlags |= kFlagIsAsync;
2807             } else {
2808                 mFlags &= ~kFlagIsAsync;
2809             }
2810 
2811             sp<AMessage> response = new AMessage;
2812             response->postReply(replyID);
2813             break;
2814         }
2815 
2816         case kWhatConfigure:
2817         {
2818             if (mState != INITIALIZED) {
2819                 PostReplyWithError(msg, INVALID_OPERATION);
2820                 break;
2821             }
2822 
2823             if (mReplyID) {
2824                 mDeferredMessages.push_back(msg);
2825                 break;
2826             }
2827             sp<AReplyToken> replyID;
2828             CHECK(msg->senderAwaitsResponse(&replyID));
2829 
2830             sp<RefBase> obj;
2831             CHECK(msg->findObject("surface", &obj));
2832 
2833             sp<AMessage> format;
2834             CHECK(msg->findMessage("format", &format));
2835 
2836             int32_t push;
2837             if (msg->findInt32("push-blank-buffers-on-shutdown", &push) && push != 0) {
2838                 mFlags |= kFlagPushBlankBuffersOnShutdown;
2839             }
2840 
2841             if (obj != NULL) {
2842                 if (!format->findInt32("allow-frame-drop", &mAllowFrameDroppingBySurface)) {
2843                     // allow frame dropping by surface by default
2844                     mAllowFrameDroppingBySurface = true;
2845                 }
2846 
2847                 format->setObject("native-window", obj);
2848                 status_t err = handleSetSurface(static_cast<Surface *>(obj.get()));
2849                 if (err != OK) {
2850                     PostReplyWithError(replyID, err);
2851                     break;
2852                 }
2853             } else {
2854                 // we are not using surface so this variable is not used, but initialize sensibly anyway
2855                 mAllowFrameDroppingBySurface = false;
2856 
2857                 handleSetSurface(NULL);
2858             }
2859 
2860             uint32_t flags;
2861             CHECK(msg->findInt32("flags", (int32_t *)&flags));
2862             if (flags & CONFIGURE_FLAG_USE_BLOCK_MODEL) {
2863                 if (!(mFlags & kFlagIsAsync)) {
2864                     PostReplyWithError(replyID, INVALID_OPERATION);
2865                     break;
2866                 }
2867                 mFlags |= kFlagUseBlockModel;
2868             }
2869             mReplyID = replyID;
2870             setState(CONFIGURING);
2871 
2872             void *crypto;
2873             if (!msg->findPointer("crypto", &crypto)) {
2874                 crypto = NULL;
2875             }
2876 
2877             ALOGV("kWhatConfigure: Old mCrypto: %p (%d)",
2878                     mCrypto.get(), (mCrypto != NULL ? mCrypto->getStrongCount() : 0));
2879 
2880             mCrypto = static_cast<ICrypto *>(crypto);
2881             mBufferChannel->setCrypto(mCrypto);
2882 
2883             ALOGV("kWhatConfigure: New mCrypto: %p (%d)",
2884                     mCrypto.get(), (mCrypto != NULL ? mCrypto->getStrongCount() : 0));
2885 
2886             void *descrambler;
2887             if (!msg->findPointer("descrambler", &descrambler)) {
2888                 descrambler = NULL;
2889             }
2890 
2891             mDescrambler = static_cast<IDescrambler *>(descrambler);
2892             mBufferChannel->setDescrambler(mDescrambler);
2893 
2894             format->setInt32("flags", flags);
2895             if (flags & CONFIGURE_FLAG_ENCODE) {
2896                 format->setInt32("encoder", true);
2897                 mFlags |= kFlagIsEncoder;
2898             }
2899 
2900             extractCSD(format);
2901 
2902             mCodec->initiateConfigureComponent(format);
2903             break;
2904         }
2905 
2906         case kWhatSetSurface:
2907         {
2908             sp<AReplyToken> replyID;
2909             CHECK(msg->senderAwaitsResponse(&replyID));
2910 
2911             status_t err = OK;
2912 
2913             switch (mState) {
2914                 case CONFIGURED:
2915                 case STARTED:
2916                 case FLUSHED:
2917                 {
2918                     sp<RefBase> obj;
2919                     (void)msg->findObject("surface", &obj);
2920                     sp<Surface> surface = static_cast<Surface *>(obj.get());
2921                     if (mSurface == NULL) {
2922                         // do not support setting surface if it was not set
2923                         err = INVALID_OPERATION;
2924                     } else if (obj == NULL) {
2925                         // do not support unsetting surface
2926                         err = BAD_VALUE;
2927                     } else {
2928                         err = connectToSurface(surface);
2929                         if (err == ALREADY_EXISTS) {
2930                             // reconnecting to same surface
2931                             err = OK;
2932                         } else {
2933                             if (err == OK) {
2934                                 if (mFlags & kFlagUsesSoftwareRenderer) {
2935                                     if (mSoftRenderer != NULL
2936                                             && (mFlags & kFlagPushBlankBuffersOnShutdown)) {
2937                                         pushBlankBuffersToNativeWindow(mSurface.get());
2938                                     }
2939                                     surface->setDequeueTimeout(-1);
2940                                     mSoftRenderer = new SoftwareRenderer(surface);
2941                                     // TODO: check if this was successful
2942                                 } else {
2943                                     err = mCodec->setSurface(surface);
2944                                 }
2945                             }
2946                             if (err == OK) {
2947                                 (void)disconnectFromSurface();
2948                                 mSurface = surface;
2949                             }
2950                         }
2951                     }
2952                     break;
2953                 }
2954 
2955                 default:
2956                     err = INVALID_OPERATION;
2957                     break;
2958             }
2959 
2960             PostReplyWithError(replyID, err);
2961             break;
2962         }
2963 
2964         case kWhatCreateInputSurface:
2965         case kWhatSetInputSurface:
2966         {
2967             // Must be configured, but can't have been started yet.
2968             if (mState != CONFIGURED) {
2969                 PostReplyWithError(msg, INVALID_OPERATION);
2970                 break;
2971             }
2972 
2973             if (mReplyID) {
2974                 mDeferredMessages.push_back(msg);
2975                 break;
2976             }
2977             sp<AReplyToken> replyID;
2978             CHECK(msg->senderAwaitsResponse(&replyID));
2979 
2980             mReplyID = replyID;
2981             if (msg->what() == kWhatCreateInputSurface) {
2982                 mCodec->initiateCreateInputSurface();
2983             } else {
2984                 sp<RefBase> obj;
2985                 CHECK(msg->findObject("input-surface", &obj));
2986 
2987                 mCodec->initiateSetInputSurface(
2988                         static_cast<PersistentSurface *>(obj.get()));
2989             }
2990             break;
2991         }
2992         case kWhatStart:
2993         {
2994             if (mState == FLUSHED) {
2995                 setState(STARTED);
2996                 if (mHavePendingInputBuffers) {
2997                     onInputBufferAvailable();
2998                     mHavePendingInputBuffers = false;
2999                 }
3000                 mCodec->signalResume();
3001                 PostReplyWithError(msg, OK);
3002                 break;
3003             } else if (mState != CONFIGURED) {
3004                 PostReplyWithError(msg, INVALID_OPERATION);
3005                 break;
3006             }
3007 
3008             if (mReplyID) {
3009                 mDeferredMessages.push_back(msg);
3010                 break;
3011             }
3012             sp<AReplyToken> replyID;
3013             CHECK(msg->senderAwaitsResponse(&replyID));
3014 
3015             mReplyID = replyID;
3016             setState(STARTING);
3017 
3018             mCodec->initiateStart();
3019             break;
3020         }
3021 
3022         case kWhatStop: {
3023             if (mReplyID) {
3024                 mDeferredMessages.push_back(msg);
3025                 break;
3026             }
3027             [[fallthrough]];
3028         }
3029         case kWhatRelease:
3030         {
3031             State targetState =
3032                 (msg->what() == kWhatStop) ? INITIALIZED : UNINITIALIZED;
3033 
3034             if ((mState == RELEASING && targetState == UNINITIALIZED)
3035                     || (mState == STOPPING && targetState == INITIALIZED)) {
3036                 mDeferredMessages.push_back(msg);
3037                 break;
3038             }
3039 
3040             sp<AReplyToken> replyID;
3041             CHECK(msg->senderAwaitsResponse(&replyID));
3042 
3043             sp<AMessage> asyncNotify;
3044             (void)msg->findMessage("async", &asyncNotify);
3045             // post asyncNotify if going out of scope.
3046             struct AsyncNotifyPost {
3047                 AsyncNotifyPost(const sp<AMessage> &asyncNotify) : mAsyncNotify(asyncNotify) {}
3048                 ~AsyncNotifyPost() {
3049                     if (mAsyncNotify) {
3050                         mAsyncNotify->post();
3051                     }
3052                 }
3053                 void clear() { mAsyncNotify.clear(); }
3054             private:
3055                 sp<AMessage> mAsyncNotify;
3056             } asyncNotifyPost{asyncNotify};
3057 
3058             // already stopped/released
3059             if (mState == UNINITIALIZED && mReleasedByResourceManager) {
3060                 sp<AMessage> response = new AMessage;
3061                 response->setInt32("err", OK);
3062                 response->postReply(replyID);
3063                 break;
3064             }
3065 
3066             int32_t reclaimed = 0;
3067             msg->findInt32("reclaimed", &reclaimed);
3068             if (reclaimed) {
3069                 mReleasedByResourceManager = true;
3070 
3071                 int32_t force = 0;
3072                 msg->findInt32("force", &force);
3073                 if (!force && hasPendingBuffer()) {
3074                     ALOGW("Can't reclaim codec right now due to pending buffers.");
3075 
3076                     // return WOULD_BLOCK to ask resource manager to retry later.
3077                     sp<AMessage> response = new AMessage;
3078                     response->setInt32("err", WOULD_BLOCK);
3079                     response->postReply(replyID);
3080 
3081                     // notify the async client
3082                     if (mFlags & kFlagIsAsync) {
3083                         onError(DEAD_OBJECT, ACTION_CODE_FATAL);
3084                     }
3085                     break;
3086                 }
3087             }
3088 
3089             bool isReleasingAllocatedComponent =
3090                     (mFlags & kFlagIsComponentAllocated) && targetState == UNINITIALIZED;
3091             if (!isReleasingAllocatedComponent // See 1
3092                     && mState != INITIALIZED
3093                     && mState != CONFIGURED && !isExecuting()) {
3094                 // 1) Permit release to shut down the component if allocated.
3095                 //
3096                 // 2) We may be in "UNINITIALIZED" state already and
3097                 // also shutdown the encoder/decoder without the
3098                 // client being aware of this if media server died while
3099                 // we were being stopped. The client would assume that
3100                 // after stop() returned, it would be safe to call release()
3101                 // and it should be in this case, no harm to allow a release()
3102                 // if we're already uninitialized.
3103                 sp<AMessage> response = new AMessage;
3104                 // TODO: we shouldn't throw an exception for stop/release. Change this to wait until
3105                 // the previous stop/release completes and then reply with OK.
3106                 status_t err = mState == targetState ? OK : INVALID_OPERATION;
3107                 response->setInt32("err", err);
3108                 if (err == OK && targetState == UNINITIALIZED) {
3109                     mComponentName.clear();
3110                 }
3111                 response->postReply(replyID);
3112                 break;
3113             }
3114 
3115             // If we're flushing, stopping, configuring or starting  but
3116             // received a release request, post the reply for the pending call
3117             // first, and consider it done. The reply token will be replaced
3118             // after this, and we'll no longer be able to reply.
3119             if (mState == FLUSHING || mState == STOPPING
3120                     || mState == CONFIGURING || mState == STARTING) {
3121                 // mReply is always set if in these states.
3122                 postPendingRepliesAndDeferredMessages(
3123                         std::string("kWhatRelease:") + stateString(mState));
3124             }
3125 
3126             if (mFlags & kFlagSawMediaServerDie) {
3127                 // It's dead, Jim. Don't expect initiateShutdown to yield
3128                 // any useful results now...
3129                 // Any pending reply would have been handled at kWhatError.
3130                 setState(UNINITIALIZED);
3131                 if (targetState == UNINITIALIZED) {
3132                     mComponentName.clear();
3133                 }
3134                 (new AMessage)->postReply(replyID);
3135                 break;
3136             }
3137 
3138             // If we already have an error, component may not be able to
3139             // complete the shutdown properly. If we're stopping, post the
3140             // reply now with an error to unblock the client, client can
3141             // release after the failure (instead of ANR).
3142             if (msg->what() == kWhatStop && (mFlags & kFlagStickyError)) {
3143                 // Any pending reply would have been handled at kWhatError.
3144                 PostReplyWithError(replyID, getStickyError());
3145                 break;
3146             }
3147 
3148             if (asyncNotify != nullptr) {
3149                 if (mSurface != NULL) {
3150                     if (!mReleaseSurface) {
3151                         uint64_t usage = 0;
3152                         if (mSurface->getConsumerUsage(&usage) != OK) {
3153                             usage = 0;
3154                         }
3155                         mReleaseSurface.reset(new ReleaseSurface(usage));
3156                     }
3157                     if (mSurface != mReleaseSurface->getSurface()) {
3158                         status_t err = connectToSurface(mReleaseSurface->getSurface());
3159                         ALOGW_IF(err != OK, "error connecting to release surface: err = %d", err);
3160                         if (err == OK && !(mFlags & kFlagUsesSoftwareRenderer)) {
3161                             err = mCodec->setSurface(mReleaseSurface->getSurface());
3162                             ALOGW_IF(err != OK, "error setting release surface: err = %d", err);
3163                         }
3164                         if (err == OK) {
3165                             (void)disconnectFromSurface();
3166                             mSurface = mReleaseSurface->getSurface();
3167                         }
3168                     }
3169                 }
3170             }
3171 
3172             if (mReplyID) {
3173                 // State transition replies are handled above, so this reply
3174                 // would not be related to state transition. As we are
3175                 // shutting down the component, just fail the operation.
3176                 postPendingRepliesAndDeferredMessages("kWhatRelease:reply", UNKNOWN_ERROR);
3177             }
3178             mReplyID = replyID;
3179             setState(msg->what() == kWhatStop ? STOPPING : RELEASING);
3180 
3181             mCodec->initiateShutdown(
3182                     msg->what() == kWhatStop /* keepComponentAllocated */);
3183 
3184             returnBuffersToCodec(reclaimed);
3185 
3186             if (mSoftRenderer != NULL && (mFlags & kFlagPushBlankBuffersOnShutdown)) {
3187                 pushBlankBuffersToNativeWindow(mSurface.get());
3188             }
3189 
3190             if (asyncNotify != nullptr) {
3191                 mResourceManagerProxy->markClientForPendingRemoval();
3192                 postPendingRepliesAndDeferredMessages("kWhatRelease:async");
3193                 asyncNotifyPost.clear();
3194                 mAsyncReleaseCompleteNotification = asyncNotify;
3195             }
3196 
3197             break;
3198         }
3199 
3200         case kWhatDequeueInputBuffer:
3201         {
3202             sp<AReplyToken> replyID;
3203             CHECK(msg->senderAwaitsResponse(&replyID));
3204 
3205             if (mFlags & kFlagIsAsync) {
3206                 ALOGE("dequeueInputBuffer can't be used in async mode");
3207                 PostReplyWithError(replyID, INVALID_OPERATION);
3208                 break;
3209             }
3210 
3211             if (mHaveInputSurface) {
3212                 ALOGE("dequeueInputBuffer can't be used with input surface");
3213                 PostReplyWithError(replyID, INVALID_OPERATION);
3214                 break;
3215             }
3216 
3217             if (handleDequeueInputBuffer(replyID, true /* new request */)) {
3218                 break;
3219             }
3220 
3221             int64_t timeoutUs;
3222             CHECK(msg->findInt64("timeoutUs", &timeoutUs));
3223 
3224             if (timeoutUs == 0LL) {
3225                 PostReplyWithError(replyID, -EAGAIN);
3226                 break;
3227             }
3228 
3229             mFlags |= kFlagDequeueInputPending;
3230             mDequeueInputReplyID = replyID;
3231 
3232             if (timeoutUs > 0LL) {
3233                 sp<AMessage> timeoutMsg =
3234                     new AMessage(kWhatDequeueInputTimedOut, this);
3235                 timeoutMsg->setInt32(
3236                         "generation", ++mDequeueInputTimeoutGeneration);
3237                 timeoutMsg->post(timeoutUs);
3238             }
3239             break;
3240         }
3241 
3242         case kWhatDequeueInputTimedOut:
3243         {
3244             int32_t generation;
3245             CHECK(msg->findInt32("generation", &generation));
3246 
3247             if (generation != mDequeueInputTimeoutGeneration) {
3248                 // Obsolete
3249                 break;
3250             }
3251 
3252             CHECK(mFlags & kFlagDequeueInputPending);
3253 
3254             PostReplyWithError(mDequeueInputReplyID, -EAGAIN);
3255 
3256             mFlags &= ~kFlagDequeueInputPending;
3257             mDequeueInputReplyID = 0;
3258             break;
3259         }
3260 
3261         case kWhatQueueInputBuffer:
3262         {
3263             sp<AReplyToken> replyID;
3264             CHECK(msg->senderAwaitsResponse(&replyID));
3265 
3266             if (!isExecuting()) {
3267                 PostReplyWithError(replyID, INVALID_OPERATION);
3268                 break;
3269             } else if (mFlags & kFlagStickyError) {
3270                 PostReplyWithError(replyID, getStickyError());
3271                 break;
3272             }
3273 
3274             status_t err = UNKNOWN_ERROR;
3275             if (!mLeftover.empty()) {
3276                 mLeftover.push_back(msg);
3277                 size_t index;
3278                 msg->findSize("index", &index);
3279                 err = handleLeftover(index);
3280             } else {
3281                 err = onQueueInputBuffer(msg);
3282             }
3283 
3284             PostReplyWithError(replyID, err);
3285             break;
3286         }
3287 
3288         case kWhatDequeueOutputBuffer:
3289         {
3290             sp<AReplyToken> replyID;
3291             CHECK(msg->senderAwaitsResponse(&replyID));
3292 
3293             if (mFlags & kFlagIsAsync) {
3294                 ALOGE("dequeueOutputBuffer can't be used in async mode");
3295                 PostReplyWithError(replyID, INVALID_OPERATION);
3296                 break;
3297             }
3298 
3299             if (handleDequeueOutputBuffer(replyID, true /* new request */)) {
3300                 break;
3301             }
3302 
3303             int64_t timeoutUs;
3304             CHECK(msg->findInt64("timeoutUs", &timeoutUs));
3305 
3306             if (timeoutUs == 0LL) {
3307                 PostReplyWithError(replyID, -EAGAIN);
3308                 break;
3309             }
3310 
3311             mFlags |= kFlagDequeueOutputPending;
3312             mDequeueOutputReplyID = replyID;
3313 
3314             if (timeoutUs > 0LL) {
3315                 sp<AMessage> timeoutMsg =
3316                     new AMessage(kWhatDequeueOutputTimedOut, this);
3317                 timeoutMsg->setInt32(
3318                         "generation", ++mDequeueOutputTimeoutGeneration);
3319                 timeoutMsg->post(timeoutUs);
3320             }
3321             break;
3322         }
3323 
3324         case kWhatDequeueOutputTimedOut:
3325         {
3326             int32_t generation;
3327             CHECK(msg->findInt32("generation", &generation));
3328 
3329             if (generation != mDequeueOutputTimeoutGeneration) {
3330                 // Obsolete
3331                 break;
3332             }
3333 
3334             CHECK(mFlags & kFlagDequeueOutputPending);
3335 
3336             PostReplyWithError(mDequeueOutputReplyID, -EAGAIN);
3337 
3338             mFlags &= ~kFlagDequeueOutputPending;
3339             mDequeueOutputReplyID = 0;
3340             break;
3341         }
3342 
3343         case kWhatReleaseOutputBuffer:
3344         {
3345             sp<AReplyToken> replyID;
3346             CHECK(msg->senderAwaitsResponse(&replyID));
3347 
3348             if (!isExecuting()) {
3349                 PostReplyWithError(replyID, INVALID_OPERATION);
3350                 break;
3351             } else if (mFlags & kFlagStickyError) {
3352                 PostReplyWithError(replyID, getStickyError());
3353                 break;
3354             }
3355 
3356             status_t err = onReleaseOutputBuffer(msg);
3357 
3358             PostReplyWithError(replyID, err);
3359             break;
3360         }
3361 
3362         case kWhatSignalEndOfInputStream:
3363         {
3364             if (!isExecuting() || !mHaveInputSurface) {
3365                 PostReplyWithError(msg, INVALID_OPERATION);
3366                 break;
3367             } else if (mFlags & kFlagStickyError) {
3368                 PostReplyWithError(msg, getStickyError());
3369                 break;
3370             }
3371 
3372             if (mReplyID) {
3373                 mDeferredMessages.push_back(msg);
3374                 break;
3375             }
3376             sp<AReplyToken> replyID;
3377             CHECK(msg->senderAwaitsResponse(&replyID));
3378 
3379             mReplyID = replyID;
3380             mCodec->signalEndOfInputStream();
3381             break;
3382         }
3383 
3384         case kWhatGetBuffers:
3385         {
3386             sp<AReplyToken> replyID;
3387             CHECK(msg->senderAwaitsResponse(&replyID));
3388             if (!isExecuting() || (mFlags & kFlagIsAsync)) {
3389                 PostReplyWithError(replyID, INVALID_OPERATION);
3390                 break;
3391             } else if (mFlags & kFlagStickyError) {
3392                 PostReplyWithError(replyID, getStickyError());
3393                 break;
3394             }
3395 
3396             int32_t portIndex;
3397             CHECK(msg->findInt32("portIndex", &portIndex));
3398 
3399             Vector<sp<MediaCodecBuffer> > *dstBuffers;
3400             CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
3401 
3402             dstBuffers->clear();
3403             // If we're using input surface (either non-persistent created by
3404             // createInputSurface(), or persistent set by setInputSurface()),
3405             // give the client an empty input buffers array.
3406             if (portIndex != kPortIndexInput || !mHaveInputSurface) {
3407                 if (portIndex == kPortIndexInput) {
3408                     mBufferChannel->getInputBufferArray(dstBuffers);
3409                 } else {
3410                     mBufferChannel->getOutputBufferArray(dstBuffers);
3411                 }
3412             }
3413 
3414             (new AMessage)->postReply(replyID);
3415             break;
3416         }
3417 
3418         case kWhatFlush:
3419         {
3420             if (!isExecuting()) {
3421                 PostReplyWithError(msg, INVALID_OPERATION);
3422                 break;
3423             } else if (mFlags & kFlagStickyError) {
3424                 PostReplyWithError(msg, getStickyError());
3425                 break;
3426             }
3427 
3428             if (mReplyID) {
3429                 mDeferredMessages.push_back(msg);
3430                 break;
3431             }
3432             sp<AReplyToken> replyID;
3433             CHECK(msg->senderAwaitsResponse(&replyID));
3434 
3435             mReplyID = replyID;
3436             // TODO: skip flushing if already FLUSHED
3437             setState(FLUSHING);
3438 
3439             mCodec->signalFlush();
3440             returnBuffersToCodec();
3441             break;
3442         }
3443 
3444         case kWhatGetInputFormat:
3445         case kWhatGetOutputFormat:
3446         {
3447             sp<AMessage> format =
3448                 (msg->what() == kWhatGetOutputFormat ? mOutputFormat : mInputFormat);
3449 
3450             sp<AReplyToken> replyID;
3451             CHECK(msg->senderAwaitsResponse(&replyID));
3452 
3453             if ((mState != CONFIGURED && mState != STARTING &&
3454                  mState != STARTED && mState != FLUSHING &&
3455                  mState != FLUSHED)
3456                     || format == NULL) {
3457                 PostReplyWithError(replyID, INVALID_OPERATION);
3458                 break;
3459             } else if (mFlags & kFlagStickyError) {
3460                 PostReplyWithError(replyID, getStickyError());
3461                 break;
3462             }
3463 
3464             sp<AMessage> response = new AMessage;
3465             response->setMessage("format", format);
3466             response->postReply(replyID);
3467             break;
3468         }
3469 
3470         case kWhatRequestIDRFrame:
3471         {
3472             mCodec->signalRequestIDRFrame();
3473             break;
3474         }
3475 
3476         case kWhatRequestActivityNotification:
3477         {
3478             CHECK(mActivityNotify == NULL);
3479             CHECK(msg->findMessage("notify", &mActivityNotify));
3480 
3481             postActivityNotificationIfPossible();
3482             break;
3483         }
3484 
3485         case kWhatGetName:
3486         {
3487             sp<AReplyToken> replyID;
3488             CHECK(msg->senderAwaitsResponse(&replyID));
3489 
3490             if (mComponentName.empty()) {
3491                 PostReplyWithError(replyID, INVALID_OPERATION);
3492                 break;
3493             }
3494 
3495             sp<AMessage> response = new AMessage;
3496             response->setString("name", mComponentName.c_str());
3497             response->postReply(replyID);
3498             break;
3499         }
3500 
3501         case kWhatGetCodecInfo:
3502         {
3503             sp<AReplyToken> replyID;
3504             CHECK(msg->senderAwaitsResponse(&replyID));
3505 
3506             sp<AMessage> response = new AMessage;
3507             response->setObject("codecInfo", mCodecInfo);
3508             response->postReply(replyID);
3509             break;
3510         }
3511 
3512         case kWhatSetParameters:
3513         {
3514             sp<AReplyToken> replyID;
3515             CHECK(msg->senderAwaitsResponse(&replyID));
3516 
3517             sp<AMessage> params;
3518             CHECK(msg->findMessage("params", &params));
3519 
3520             status_t err = onSetParameters(params);
3521 
3522             PostReplyWithError(replyID, err);
3523             break;
3524         }
3525 
3526         case kWhatDrmReleaseCrypto:
3527         {
3528             onReleaseCrypto(msg);
3529             break;
3530         }
3531 
3532         case kWhatCheckBatteryStats:
3533         {
3534             if (mBatteryChecker != nullptr) {
3535                 mBatteryChecker->onCheckBatteryTimer(msg, [this] () {
3536                     mResourceManagerProxy->removeResource(
3537                             MediaResource::VideoBatteryResource());
3538                 });
3539             }
3540             break;
3541         }
3542 
3543         default:
3544             TRESPASS();
3545     }
3546 }
3547 
handleOutputFormatChangeIfNeeded(const sp<MediaCodecBuffer> & buffer)3548 void MediaCodec::handleOutputFormatChangeIfNeeded(const sp<MediaCodecBuffer> &buffer) {
3549     sp<AMessage> format = buffer->format();
3550     if (mOutputFormat == format) {
3551         return;
3552     }
3553     if (mFlags & kFlagUseBlockModel) {
3554         sp<AMessage> diff1 = mOutputFormat->changesFrom(format);
3555         sp<AMessage> diff2 = format->changesFrom(mOutputFormat);
3556         std::set<std::string> keys;
3557         size_t numEntries = diff1->countEntries();
3558         AMessage::Type type;
3559         for (size_t i = 0; i < numEntries; ++i) {
3560             keys.emplace(diff1->getEntryNameAt(i, &type));
3561         }
3562         numEntries = diff2->countEntries();
3563         for (size_t i = 0; i < numEntries; ++i) {
3564             keys.emplace(diff2->getEntryNameAt(i, &type));
3565         }
3566         sp<WrapperObject<std::set<std::string>>> changedKeys{
3567             new WrapperObject<std::set<std::string>>{std::move(keys)}};
3568         buffer->meta()->setObject("changedKeys", changedKeys);
3569     }
3570     mOutputFormat = format;
3571     ALOGV("[%s] output format changed to: %s",
3572             mComponentName.c_str(), mOutputFormat->debugString(4).c_str());
3573 
3574     if (mSoftRenderer == NULL &&
3575             mSurface != NULL &&
3576             (mFlags & kFlagUsesSoftwareRenderer)) {
3577         AString mime;
3578         CHECK(mOutputFormat->findString("mime", &mime));
3579 
3580         // TODO: propagate color aspects to software renderer to allow better
3581         // color conversion to RGB. For now, just mark dataspace for YUV
3582         // rendering.
3583         int32_t dataSpace;
3584         if (mOutputFormat->findInt32("android._dataspace", &dataSpace)) {
3585             ALOGD("[%s] setting dataspace on output surface to #%x",
3586                     mComponentName.c_str(), dataSpace);
3587             int err = native_window_set_buffers_data_space(
3588                     mSurface.get(), (android_dataspace)dataSpace);
3589             ALOGW_IF(err != 0, "failed to set dataspace on surface (%d)", err);
3590         }
3591         if (mOutputFormat->contains("hdr-static-info")) {
3592             HDRStaticInfo info;
3593             if (ColorUtils::getHDRStaticInfoFromFormat(mOutputFormat, &info)) {
3594                 setNativeWindowHdrMetadata(mSurface.get(), &info);
3595             }
3596         }
3597 
3598         sp<ABuffer> hdr10PlusInfo;
3599         if (mOutputFormat->findBuffer("hdr10-plus-info", &hdr10PlusInfo)
3600                 && hdr10PlusInfo != nullptr && hdr10PlusInfo->size() > 0) {
3601             native_window_set_buffers_hdr10_plus_metadata(mSurface.get(),
3602                     hdr10PlusInfo->size(), hdr10PlusInfo->data());
3603         }
3604 
3605         if (mime.startsWithIgnoreCase("video/")) {
3606             mSurface->setDequeueTimeout(-1);
3607             mSoftRenderer = new SoftwareRenderer(mSurface, mRotationDegrees);
3608         }
3609     }
3610 
3611     requestCpuBoostIfNeeded();
3612 
3613     if (mFlags & kFlagIsEncoder) {
3614         // Before we announce the format change we should
3615         // collect codec specific data and amend the output
3616         // format as necessary.
3617         int32_t flags = 0;
3618         (void) buffer->meta()->findInt32("flags", &flags);
3619         if ((flags & BUFFER_FLAG_CODECCONFIG) && !(mFlags & kFlagIsSecure)) {
3620             status_t err =
3621                 amendOutputFormatWithCodecSpecificData(buffer);
3622 
3623             if (err != OK) {
3624                 ALOGE("Codec spit out malformed codec "
3625                       "specific data!");
3626             }
3627         }
3628     }
3629     if (mFlags & kFlagIsAsync) {
3630         onOutputFormatChanged();
3631     } else {
3632         mFlags |= kFlagOutputFormatChanged;
3633         postActivityNotificationIfPossible();
3634     }
3635 
3636     // Notify mCrypto of video resolution changes
3637     if (mCrypto != NULL) {
3638         int32_t left, top, right, bottom, width, height;
3639         if (mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) {
3640             mCrypto->notifyResolution(right - left + 1, bottom - top + 1);
3641         } else if (mOutputFormat->findInt32("width", &width)
3642                 && mOutputFormat->findInt32("height", &height)) {
3643             mCrypto->notifyResolution(width, height);
3644         }
3645     }
3646 }
3647 
extractCSD(const sp<AMessage> & format)3648 void MediaCodec::extractCSD(const sp<AMessage> &format) {
3649     mCSD.clear();
3650 
3651     size_t i = 0;
3652     for (;;) {
3653         sp<ABuffer> csd;
3654         if (!format->findBuffer(AStringPrintf("csd-%u", i).c_str(), &csd)) {
3655             break;
3656         }
3657         if (csd->size() == 0) {
3658             ALOGW("csd-%zu size is 0", i);
3659         }
3660 
3661         mCSD.push_back(csd);
3662         ++i;
3663     }
3664 
3665     ALOGV("Found %zu pieces of codec specific data.", mCSD.size());
3666 }
3667 
queueCSDInputBuffer(size_t bufferIndex)3668 status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) {
3669     CHECK(!mCSD.empty());
3670 
3671     sp<ABuffer> csd = *mCSD.begin();
3672     mCSD.erase(mCSD.begin());
3673     std::shared_ptr<C2Buffer> c2Buffer;
3674     sp<hardware::HidlMemory> memory;
3675     size_t offset = 0;
3676 
3677     if (mFlags & kFlagUseBlockModel) {
3678         if (hasCryptoOrDescrambler()) {
3679             constexpr size_t kInitialDealerCapacity = 1048576;  // 1MB
3680             thread_local sp<MemoryDealer> sDealer = new MemoryDealer(
3681                     kInitialDealerCapacity, "CSD(1MB)");
3682             sp<IMemory> mem = sDealer->allocate(csd->size());
3683             if (mem == nullptr) {
3684                 size_t newDealerCapacity = sDealer->getMemoryHeap()->getSize() * 2;
3685                 while (csd->size() * 2 > newDealerCapacity) {
3686                     newDealerCapacity *= 2;
3687                 }
3688                 sDealer = new MemoryDealer(
3689                         newDealerCapacity,
3690                         AStringPrintf("CSD(%dMB)", newDealerCapacity / 1048576).c_str());
3691                 mem = sDealer->allocate(csd->size());
3692             }
3693             memcpy(mem->unsecurePointer(), csd->data(), csd->size());
3694             ssize_t heapOffset;
3695             memory = hardware::fromHeap(mem->getMemory(&heapOffset, nullptr));
3696             offset += heapOffset;
3697         } else {
3698             std::shared_ptr<C2LinearBlock> block =
3699                 FetchLinearBlock(csd->size(), {std::string{mComponentName.c_str()}});
3700             C2WriteView view{block->map().get()};
3701             if (view.error() != C2_OK) {
3702                 return -EINVAL;
3703             }
3704             if (csd->size() > view.capacity()) {
3705                 return -EINVAL;
3706             }
3707             memcpy(view.base(), csd->data(), csd->size());
3708             c2Buffer = C2Buffer::CreateLinearBuffer(block->share(0, csd->size(), C2Fence{}));
3709         }
3710     } else {
3711         const BufferInfo &info = mPortBuffers[kPortIndexInput][bufferIndex];
3712         const sp<MediaCodecBuffer> &codecInputData = info.mData;
3713 
3714         if (csd->size() > codecInputData->capacity()) {
3715             return -EINVAL;
3716         }
3717         if (codecInputData->data() == NULL) {
3718             ALOGV("Input buffer %zu is not properly allocated", bufferIndex);
3719             return -EINVAL;
3720         }
3721 
3722         memcpy(codecInputData->data(), csd->data(), csd->size());
3723     }
3724 
3725     AString errorDetailMsg;
3726 
3727     sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this);
3728     msg->setSize("index", bufferIndex);
3729     msg->setSize("offset", 0);
3730     msg->setSize("size", csd->size());
3731     msg->setInt64("timeUs", 0LL);
3732     msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG);
3733     msg->setPointer("errorDetailMsg", &errorDetailMsg);
3734     if (c2Buffer) {
3735         sp<WrapperObject<std::shared_ptr<C2Buffer>>> obj{
3736             new WrapperObject<std::shared_ptr<C2Buffer>>{c2Buffer}};
3737         msg->setObject("c2buffer", obj);
3738         msg->setMessage("tunings", new AMessage);
3739     } else if (memory) {
3740         sp<WrapperObject<sp<hardware::HidlMemory>>> obj{
3741             new WrapperObject<sp<hardware::HidlMemory>>{memory}};
3742         msg->setObject("memory", obj);
3743         msg->setMessage("tunings", new AMessage);
3744     }
3745 
3746     return onQueueInputBuffer(msg);
3747 }
3748 
setState(State newState)3749 void MediaCodec::setState(State newState) {
3750     if (newState == INITIALIZED || newState == UNINITIALIZED) {
3751         delete mSoftRenderer;
3752         mSoftRenderer = NULL;
3753 
3754         if ( mCrypto != NULL ) {
3755             ALOGV("setState: ~mCrypto: %p (%d)",
3756                     mCrypto.get(), (mCrypto != NULL ? mCrypto->getStrongCount() : 0));
3757         }
3758         mCrypto.clear();
3759         mDescrambler.clear();
3760         handleSetSurface(NULL);
3761 
3762         mInputFormat.clear();
3763         mOutputFormat.clear();
3764         mFlags &= ~kFlagOutputFormatChanged;
3765         mFlags &= ~kFlagOutputBuffersChanged;
3766         mFlags &= ~kFlagStickyError;
3767         mFlags &= ~kFlagIsEncoder;
3768         mFlags &= ~kFlagIsAsync;
3769         mStickyError = OK;
3770 
3771         mActivityNotify.clear();
3772         mCallback.clear();
3773     }
3774 
3775     if (newState == UNINITIALIZED) {
3776         // return any straggling buffers, e.g. if we got here on an error
3777         returnBuffersToCodec();
3778 
3779         // The component is gone, mediaserver's probably back up already
3780         // but should definitely be back up should we try to instantiate
3781         // another component.. and the cycle continues.
3782         mFlags &= ~kFlagSawMediaServerDie;
3783     }
3784 
3785     mState = newState;
3786 
3787     if (mBatteryChecker != nullptr) {
3788         mBatteryChecker->setExecuting(isExecuting());
3789     }
3790 
3791     cancelPendingDequeueOperations();
3792 }
3793 
returnBuffersToCodec(bool isReclaim)3794 void MediaCodec::returnBuffersToCodec(bool isReclaim) {
3795     returnBuffersToCodecOnPort(kPortIndexInput, isReclaim);
3796     returnBuffersToCodecOnPort(kPortIndexOutput, isReclaim);
3797 }
3798 
returnBuffersToCodecOnPort(int32_t portIndex,bool isReclaim)3799 void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex, bool isReclaim) {
3800     CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
3801     Mutex::Autolock al(mBufferLock);
3802 
3803     if (portIndex == kPortIndexInput) {
3804         mLeftover.clear();
3805     }
3806     for (size_t i = 0; i < mPortBuffers[portIndex].size(); ++i) {
3807         BufferInfo *info = &mPortBuffers[portIndex][i];
3808 
3809         if (info->mData != nullptr) {
3810             sp<MediaCodecBuffer> buffer = info->mData;
3811             if (isReclaim && info->mOwnedByClient) {
3812                 ALOGD("port %d buffer %zu still owned by client when codec is reclaimed",
3813                         portIndex, i);
3814             } else {
3815                 info->mOwnedByClient = false;
3816                 info->mData.clear();
3817             }
3818             mBufferChannel->discardBuffer(buffer);
3819         }
3820     }
3821 
3822     mAvailPortBuffers[portIndex].clear();
3823 }
3824 
updateBuffers(int32_t portIndex,const sp<AMessage> & msg)3825 size_t MediaCodec::updateBuffers(
3826         int32_t portIndex, const sp<AMessage> &msg) {
3827     CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
3828     size_t index;
3829     CHECK(msg->findSize("index", &index));
3830     sp<RefBase> obj;
3831     CHECK(msg->findObject("buffer", &obj));
3832     sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
3833 
3834     {
3835         Mutex::Autolock al(mBufferLock);
3836         if (mPortBuffers[portIndex].size() <= index) {
3837             mPortBuffers[portIndex].resize(align(index + 1, kNumBuffersAlign));
3838         }
3839         mPortBuffers[portIndex][index].mData = buffer;
3840     }
3841     mAvailPortBuffers[portIndex].push_back(index);
3842 
3843     return index;
3844 }
3845 
onQueueInputBuffer(const sp<AMessage> & msg)3846 status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {
3847     size_t index;
3848     size_t offset;
3849     size_t size;
3850     int64_t timeUs;
3851     uint32_t flags;
3852     CHECK(msg->findSize("index", &index));
3853     CHECK(msg->findInt64("timeUs", &timeUs));
3854     CHECK(msg->findInt32("flags", (int32_t *)&flags));
3855     std::shared_ptr<C2Buffer> c2Buffer;
3856     sp<hardware::HidlMemory> memory;
3857     sp<RefBase> obj;
3858     if (msg->findObject("c2buffer", &obj)) {
3859         CHECK(obj);
3860         c2Buffer = static_cast<WrapperObject<std::shared_ptr<C2Buffer>> *>(obj.get())->value;
3861     } else if (msg->findObject("memory", &obj)) {
3862         CHECK(obj);
3863         memory = static_cast<WrapperObject<sp<hardware::HidlMemory>> *>(obj.get())->value;
3864         CHECK(msg->findSize("offset", &offset));
3865     } else {
3866         CHECK(msg->findSize("offset", &offset));
3867     }
3868     const CryptoPlugin::SubSample *subSamples;
3869     size_t numSubSamples;
3870     const uint8_t *key;
3871     const uint8_t *iv;
3872     CryptoPlugin::Mode mode = CryptoPlugin::kMode_Unencrypted;
3873 
3874     // We allow the simpler queueInputBuffer API to be used even in
3875     // secure mode, by fabricating a single unencrypted subSample.
3876     CryptoPlugin::SubSample ss;
3877     CryptoPlugin::Pattern pattern;
3878 
3879     if (msg->findSize("size", &size)) {
3880         if (hasCryptoOrDescrambler()) {
3881             ss.mNumBytesOfClearData = size;
3882             ss.mNumBytesOfEncryptedData = 0;
3883 
3884             subSamples = &ss;
3885             numSubSamples = 1;
3886             key = NULL;
3887             iv = NULL;
3888             pattern.mEncryptBlocks = 0;
3889             pattern.mSkipBlocks = 0;
3890         }
3891     } else if (!c2Buffer) {
3892         if (!hasCryptoOrDescrambler()) {
3893             ALOGE("[%s] queuing secure buffer without mCrypto or mDescrambler!",
3894                     mComponentName.c_str());
3895             return -EINVAL;
3896         }
3897 
3898         CHECK(msg->findPointer("subSamples", (void **)&subSamples));
3899         CHECK(msg->findSize("numSubSamples", &numSubSamples));
3900         CHECK(msg->findPointer("key", (void **)&key));
3901         CHECK(msg->findPointer("iv", (void **)&iv));
3902         CHECK(msg->findInt32("encryptBlocks", (int32_t *)&pattern.mEncryptBlocks));
3903         CHECK(msg->findInt32("skipBlocks", (int32_t *)&pattern.mSkipBlocks));
3904 
3905         int32_t tmp;
3906         CHECK(msg->findInt32("mode", &tmp));
3907 
3908         mode = (CryptoPlugin::Mode)tmp;
3909 
3910         size = 0;
3911         for (size_t i = 0; i < numSubSamples; ++i) {
3912             size += subSamples[i].mNumBytesOfClearData;
3913             size += subSamples[i].mNumBytesOfEncryptedData;
3914         }
3915     }
3916 
3917     if (index >= mPortBuffers[kPortIndexInput].size()) {
3918         return -ERANGE;
3919     }
3920 
3921     BufferInfo *info = &mPortBuffers[kPortIndexInput][index];
3922     sp<MediaCodecBuffer> buffer = info->mData;
3923 
3924     if (c2Buffer || memory) {
3925         sp<AMessage> tunings;
3926         CHECK(msg->findMessage("tunings", &tunings));
3927         onSetParameters(tunings);
3928 
3929         status_t err = OK;
3930         if (c2Buffer) {
3931             err = mBufferChannel->attachBuffer(c2Buffer, buffer);
3932         } else if (memory) {
3933             err = mBufferChannel->attachEncryptedBuffer(
3934                     memory, (mFlags & kFlagIsSecure), key, iv, mode, pattern,
3935                     offset, subSamples, numSubSamples, buffer);
3936         } else {
3937             err = UNKNOWN_ERROR;
3938         }
3939 
3940         if (err == OK && !buffer->asC2Buffer()
3941                 && c2Buffer && c2Buffer->data().type() == C2BufferData::LINEAR) {
3942             C2ConstLinearBlock block{c2Buffer->data().linearBlocks().front()};
3943             if (block.size() > buffer->size()) {
3944                 C2ConstLinearBlock leftover = block.subBlock(
3945                         block.offset() + buffer->size(), block.size() - buffer->size());
3946                 sp<WrapperObject<std::shared_ptr<C2Buffer>>> obj{
3947                     new WrapperObject<std::shared_ptr<C2Buffer>>{
3948                         C2Buffer::CreateLinearBuffer(leftover)}};
3949                 msg->setObject("c2buffer", obj);
3950                 mLeftover.push_front(msg);
3951                 // Not sending EOS if we have leftovers
3952                 flags &= ~BUFFER_FLAG_EOS;
3953             }
3954         }
3955 
3956         offset = buffer->offset();
3957         size = buffer->size();
3958         if (err != OK) {
3959             return err;
3960         }
3961     }
3962 
3963     if (buffer == nullptr || !info->mOwnedByClient) {
3964         return -EACCES;
3965     }
3966 
3967     if (offset + size > buffer->capacity()) {
3968         return -EINVAL;
3969     }
3970 
3971     buffer->setRange(offset, size);
3972     buffer->meta()->setInt64("timeUs", timeUs);
3973     if (flags & BUFFER_FLAG_EOS) {
3974         buffer->meta()->setInt32("eos", true);
3975     }
3976 
3977     if (flags & BUFFER_FLAG_CODECCONFIG) {
3978         buffer->meta()->setInt32("csd", true);
3979     }
3980 
3981     status_t err = OK;
3982     if (hasCryptoOrDescrambler() && !c2Buffer && !memory) {
3983         AString *errorDetailMsg;
3984         CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg));
3985 
3986         err = mBufferChannel->queueSecureInputBuffer(
3987                 buffer,
3988                 (mFlags & kFlagIsSecure),
3989                 key,
3990                 iv,
3991                 mode,
3992                 pattern,
3993                 subSamples,
3994                 numSubSamples,
3995                 errorDetailMsg);
3996         if (err != OK) {
3997             mediametrics_setInt32(mMetricsHandle, kCodecQueueSecureInputBufferError, err);
3998             ALOGW("Log queueSecureInputBuffer error: %d", err);
3999         }
4000     } else {
4001         err = mBufferChannel->queueInputBuffer(buffer);
4002         if (err != OK) {
4003             mediametrics_setInt32(mMetricsHandle, kCodecQueueInputBufferError, err);
4004             ALOGW("Log queueInputBuffer error: %d", err);
4005         }
4006     }
4007 
4008     if (err == OK) {
4009         // synchronization boundary for getBufferAndFormat
4010         Mutex::Autolock al(mBufferLock);
4011         info->mOwnedByClient = false;
4012         info->mData.clear();
4013 
4014         statsBufferSent(timeUs);
4015     }
4016 
4017     return err;
4018 }
4019 
handleLeftover(size_t index)4020 status_t MediaCodec::handleLeftover(size_t index) {
4021     if (mLeftover.empty()) {
4022         return OK;
4023     }
4024     sp<AMessage> msg = mLeftover.front();
4025     mLeftover.pop_front();
4026     msg->setSize("index", index);
4027     return onQueueInputBuffer(msg);
4028 }
4029 
4030 //static
CreateFramesRenderedMessage(const std::list<FrameRenderTracker::Info> & done,sp<AMessage> & msg)4031 size_t MediaCodec::CreateFramesRenderedMessage(
4032         const std::list<FrameRenderTracker::Info> &done, sp<AMessage> &msg) {
4033     size_t index = 0;
4034 
4035     for (std::list<FrameRenderTracker::Info>::const_iterator it = done.cbegin();
4036             it != done.cend(); ++it) {
4037         if (it->getRenderTimeNs() < 0) {
4038             continue; // dropped frame from tracking
4039         }
4040         msg->setInt64(AStringPrintf("%zu-media-time-us", index).c_str(), it->getMediaTimeUs());
4041         msg->setInt64(AStringPrintf("%zu-system-nano", index).c_str(), it->getRenderTimeNs());
4042         ++index;
4043     }
4044     return index;
4045 }
4046 
onReleaseOutputBuffer(const sp<AMessage> & msg)4047 status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) {
4048     size_t index;
4049     CHECK(msg->findSize("index", &index));
4050 
4051     int32_t render;
4052     if (!msg->findInt32("render", &render)) {
4053         render = 0;
4054     }
4055 
4056     if (!isExecuting()) {
4057         return -EINVAL;
4058     }
4059 
4060     if (index >= mPortBuffers[kPortIndexOutput].size()) {
4061         return -ERANGE;
4062     }
4063 
4064     BufferInfo *info = &mPortBuffers[kPortIndexOutput][index];
4065 
4066     if (info->mData == nullptr || !info->mOwnedByClient) {
4067         return -EACCES;
4068     }
4069 
4070     // synchronization boundary for getBufferAndFormat
4071     sp<MediaCodecBuffer> buffer;
4072     {
4073         Mutex::Autolock al(mBufferLock);
4074         info->mOwnedByClient = false;
4075         buffer = info->mData;
4076         info->mData.clear();
4077     }
4078 
4079     if (render && buffer->size() != 0) {
4080         int64_t mediaTimeUs = -1;
4081         buffer->meta()->findInt64("timeUs", &mediaTimeUs);
4082 
4083         int64_t renderTimeNs = 0;
4084         if (!msg->findInt64("timestampNs", &renderTimeNs)) {
4085             // use media timestamp if client did not request a specific render timestamp
4086             ALOGV("using buffer PTS of %lld", (long long)mediaTimeUs);
4087             renderTimeNs = mediaTimeUs * 1000;
4088         }
4089 
4090         if (mSoftRenderer != NULL) {
4091             std::list<FrameRenderTracker::Info> doneFrames = mSoftRenderer->render(
4092                     buffer->data(), buffer->size(), mediaTimeUs, renderTimeNs,
4093                     mPortBuffers[kPortIndexOutput].size(), buffer->format());
4094 
4095             // if we are running, notify rendered frames
4096             if (!doneFrames.empty() && mState == STARTED && mOnFrameRenderedNotification != NULL) {
4097                 sp<AMessage> notify = mOnFrameRenderedNotification->dup();
4098                 sp<AMessage> data = new AMessage;
4099                 if (CreateFramesRenderedMessage(doneFrames, data)) {
4100                     notify->setMessage("data", data);
4101                     notify->post();
4102                 }
4103             }
4104         }
4105         mBufferChannel->renderOutputBuffer(buffer, renderTimeNs);
4106     } else {
4107         mBufferChannel->discardBuffer(buffer);
4108     }
4109 
4110     return OK;
4111 }
4112 
peekNextPortBuffer(int32_t portIndex)4113 MediaCodec::BufferInfo *MediaCodec::peekNextPortBuffer(int32_t portIndex) {
4114     CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
4115 
4116     List<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
4117 
4118     if (availBuffers->empty()) {
4119         return nullptr;
4120     }
4121 
4122     return &mPortBuffers[portIndex][*availBuffers->begin()];
4123 }
4124 
dequeuePortBuffer(int32_t portIndex)4125 ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) {
4126     CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
4127 
4128     BufferInfo *info = peekNextPortBuffer(portIndex);
4129     if (!info) {
4130         return -EAGAIN;
4131     }
4132 
4133     List<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
4134     size_t index = *availBuffers->begin();
4135     CHECK_EQ(info, &mPortBuffers[portIndex][index]);
4136     availBuffers->erase(availBuffers->begin());
4137 
4138     CHECK(!info->mOwnedByClient);
4139     {
4140         Mutex::Autolock al(mBufferLock);
4141         info->mOwnedByClient = true;
4142 
4143         // set image-data
4144         if (info->mData->format() != NULL) {
4145             sp<ABuffer> imageData;
4146             if (info->mData->format()->findBuffer("image-data", &imageData)) {
4147                 info->mData->meta()->setBuffer("image-data", imageData);
4148             }
4149             int32_t left, top, right, bottom;
4150             if (info->mData->format()->findRect("crop", &left, &top, &right, &bottom)) {
4151                 info->mData->meta()->setRect("crop-rect", left, top, right, bottom);
4152             }
4153         }
4154     }
4155 
4156     return index;
4157 }
4158 
connectToSurface(const sp<Surface> & surface)4159 status_t MediaCodec::connectToSurface(const sp<Surface> &surface) {
4160     status_t err = OK;
4161     if (surface != NULL) {
4162         uint64_t oldId, newId;
4163         if (mSurface != NULL
4164                 && surface->getUniqueId(&newId) == NO_ERROR
4165                 && mSurface->getUniqueId(&oldId) == NO_ERROR
4166                 && newId == oldId) {
4167             ALOGI("[%s] connecting to the same surface. Nothing to do.", mComponentName.c_str());
4168             return ALREADY_EXISTS;
4169         }
4170 
4171         err = nativeWindowConnect(surface.get(), "connectToSurface");
4172         if (err == OK) {
4173             // Require a fresh set of buffers after each connect by using a unique generation
4174             // number. Rely on the fact that max supported process id by Linux is 2^22.
4175             // PID is never 0 so we don't have to worry that we use the default generation of 0.
4176             // TODO: come up with a unique scheme if other producers also set the generation number.
4177             static uint32_t mSurfaceGeneration = 0;
4178             uint32_t generation = (getpid() << 10) | (++mSurfaceGeneration & ((1 << 10) - 1));
4179             surface->setGenerationNumber(generation);
4180             ALOGI("[%s] setting surface generation to %u", mComponentName.c_str(), generation);
4181 
4182             // HACK: clear any free buffers. Remove when connect will automatically do this.
4183             // This is needed as the consumer may be holding onto stale frames that it can reattach
4184             // to this surface after disconnect/connect, and those free frames would inherit the new
4185             // generation number. Disconnecting after setting a unique generation prevents this.
4186             nativeWindowDisconnect(surface.get(), "connectToSurface(reconnect)");
4187             err = nativeWindowConnect(surface.get(), "connectToSurface(reconnect)");
4188         }
4189 
4190         if (err != OK) {
4191             ALOGE("nativeWindowConnect returned an error: %s (%d)", strerror(-err), err);
4192         } else {
4193             if (!mAllowFrameDroppingBySurface) {
4194                 disableLegacyBufferDropPostQ(surface);
4195             }
4196         }
4197     }
4198     // do not return ALREADY_EXISTS unless surfaces are the same
4199     return err == ALREADY_EXISTS ? BAD_VALUE : err;
4200 }
4201 
disconnectFromSurface()4202 status_t MediaCodec::disconnectFromSurface() {
4203     status_t err = OK;
4204     if (mSurface != NULL) {
4205         // Resetting generation is not technically needed, but there is no need to keep it either
4206         mSurface->setGenerationNumber(0);
4207         err = nativeWindowDisconnect(mSurface.get(), "disconnectFromSurface");
4208         if (err != OK) {
4209             ALOGW("nativeWindowDisconnect returned an error: %s (%d)", strerror(-err), err);
4210         }
4211         // assume disconnected even on error
4212         mSurface.clear();
4213     }
4214     return err;
4215 }
4216 
handleSetSurface(const sp<Surface> & surface)4217 status_t MediaCodec::handleSetSurface(const sp<Surface> &surface) {
4218     status_t err = OK;
4219     if (mSurface != NULL) {
4220         (void)disconnectFromSurface();
4221     }
4222     if (surface != NULL) {
4223         err = connectToSurface(surface);
4224         if (err == OK) {
4225             mSurface = surface;
4226         }
4227     }
4228     return err;
4229 }
4230 
onInputBufferAvailable()4231 void MediaCodec::onInputBufferAvailable() {
4232     int32_t index;
4233     while ((index = dequeuePortBuffer(kPortIndexInput)) >= 0) {
4234         sp<AMessage> msg = mCallback->dup();
4235         msg->setInt32("callbackID", CB_INPUT_AVAILABLE);
4236         msg->setInt32("index", index);
4237         msg->post();
4238     }
4239 }
4240 
onOutputBufferAvailable()4241 void MediaCodec::onOutputBufferAvailable() {
4242     int32_t index;
4243     while ((index = dequeuePortBuffer(kPortIndexOutput)) >= 0) {
4244         const sp<MediaCodecBuffer> &buffer =
4245             mPortBuffers[kPortIndexOutput][index].mData;
4246         sp<AMessage> msg = mCallback->dup();
4247         msg->setInt32("callbackID", CB_OUTPUT_AVAILABLE);
4248         msg->setInt32("index", index);
4249         msg->setSize("offset", buffer->offset());
4250         msg->setSize("size", buffer->size());
4251 
4252         int64_t timeUs;
4253         CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
4254 
4255         msg->setInt64("timeUs", timeUs);
4256 
4257         statsBufferReceived(timeUs);
4258 
4259         int32_t flags;
4260         CHECK(buffer->meta()->findInt32("flags", &flags));
4261 
4262         msg->setInt32("flags", flags);
4263 
4264         msg->post();
4265     }
4266 }
4267 
onError(status_t err,int32_t actionCode,const char * detail)4268 void MediaCodec::onError(status_t err, int32_t actionCode, const char *detail) {
4269     if (mCallback != NULL) {
4270         sp<AMessage> msg = mCallback->dup();
4271         msg->setInt32("callbackID", CB_ERROR);
4272         msg->setInt32("err", err);
4273         msg->setInt32("actionCode", actionCode);
4274 
4275         if (detail != NULL) {
4276             msg->setString("detail", detail);
4277         }
4278 
4279         msg->post();
4280     }
4281 }
4282 
onOutputFormatChanged()4283 void MediaCodec::onOutputFormatChanged() {
4284     if (mCallback != NULL) {
4285         sp<AMessage> msg = mCallback->dup();
4286         msg->setInt32("callbackID", CB_OUTPUT_FORMAT_CHANGED);
4287         msg->setMessage("format", mOutputFormat);
4288         msg->post();
4289     }
4290 }
4291 
postActivityNotificationIfPossible()4292 void MediaCodec::postActivityNotificationIfPossible() {
4293     if (mActivityNotify == NULL) {
4294         return;
4295     }
4296 
4297     bool isErrorOrOutputChanged =
4298             (mFlags & (kFlagStickyError
4299                     | kFlagOutputBuffersChanged
4300                     | kFlagOutputFormatChanged));
4301 
4302     if (isErrorOrOutputChanged
4303             || !mAvailPortBuffers[kPortIndexInput].empty()
4304             || !mAvailPortBuffers[kPortIndexOutput].empty()) {
4305         mActivityNotify->setInt32("input-buffers",
4306                 mAvailPortBuffers[kPortIndexInput].size());
4307 
4308         if (isErrorOrOutputChanged) {
4309             // we want consumer to dequeue as many times as it can
4310             mActivityNotify->setInt32("output-buffers", INT32_MAX);
4311         } else {
4312             mActivityNotify->setInt32("output-buffers",
4313                     mAvailPortBuffers[kPortIndexOutput].size());
4314         }
4315         mActivityNotify->post();
4316         mActivityNotify.clear();
4317     }
4318 }
4319 
setParameters(const sp<AMessage> & params)4320 status_t MediaCodec::setParameters(const sp<AMessage> &params) {
4321     sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
4322     msg->setMessage("params", params);
4323 
4324     sp<AMessage> response;
4325     return PostAndAwaitResponse(msg, &response);
4326 }
4327 
onSetParameters(const sp<AMessage> & params)4328 status_t MediaCodec::onSetParameters(const sp<AMessage> &params) {
4329     updateLowLatency(params);
4330     mCodec->signalSetParameters(params);
4331 
4332     return OK;
4333 }
4334 
amendOutputFormatWithCodecSpecificData(const sp<MediaCodecBuffer> & buffer)4335 status_t MediaCodec::amendOutputFormatWithCodecSpecificData(
4336         const sp<MediaCodecBuffer> &buffer) {
4337     AString mime;
4338     CHECK(mOutputFormat->findString("mime", &mime));
4339 
4340     if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
4341         // Codec specific data should be SPS and PPS in a single buffer,
4342         // each prefixed by a startcode (0x00 0x00 0x00 0x01).
4343         // We separate the two and put them into the output format
4344         // under the keys "csd-0" and "csd-1".
4345 
4346         unsigned csdIndex = 0;
4347 
4348         const uint8_t *data = buffer->data();
4349         size_t size = buffer->size();
4350 
4351         const uint8_t *nalStart;
4352         size_t nalSize;
4353         while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) {
4354             sp<ABuffer> csd = new ABuffer(nalSize + 4);
4355             memcpy(csd->data(), "\x00\x00\x00\x01", 4);
4356             memcpy(csd->data() + 4, nalStart, nalSize);
4357 
4358             mOutputFormat->setBuffer(
4359                     AStringPrintf("csd-%u", csdIndex).c_str(), csd);
4360 
4361             ++csdIndex;
4362         }
4363 
4364         if (csdIndex != 2) {
4365             return ERROR_MALFORMED;
4366         }
4367     } else {
4368         // For everything else we just stash the codec specific data into
4369         // the output format as a single piece of csd under "csd-0".
4370         sp<ABuffer> csd = new ABuffer(buffer->size());
4371         memcpy(csd->data(), buffer->data(), buffer->size());
4372         csd->setRange(0, buffer->size());
4373         mOutputFormat->setBuffer("csd-0", csd);
4374     }
4375 
4376     return OK;
4377 }
4378 
postPendingRepliesAndDeferredMessages(std::string origin,status_t err)4379 void MediaCodec::postPendingRepliesAndDeferredMessages(
4380         std::string origin, status_t err /* = OK */) {
4381     sp<AMessage> response{new AMessage};
4382     if (err != OK) {
4383         response->setInt32("err", err);
4384     }
4385     postPendingRepliesAndDeferredMessages(origin, response);
4386 }
4387 
postPendingRepliesAndDeferredMessages(std::string origin,const sp<AMessage> & response)4388 void MediaCodec::postPendingRepliesAndDeferredMessages(
4389         std::string origin, const sp<AMessage> &response) {
4390     LOG_ALWAYS_FATAL_IF(
4391             !mReplyID,
4392             "postPendingRepliesAndDeferredMessages: mReplyID == null, from %s following %s",
4393             origin.c_str(),
4394             mLastReplyOrigin.c_str());
4395     mLastReplyOrigin = origin;
4396     response->postReply(mReplyID);
4397     mReplyID.clear();
4398     ALOGV_IF(!mDeferredMessages.empty(),
4399             "posting %zu deferred messages", mDeferredMessages.size());
4400     for (sp<AMessage> msg : mDeferredMessages) {
4401         msg->post();
4402     }
4403     mDeferredMessages.clear();
4404 }
4405 
stateString(State state)4406 std::string MediaCodec::stateString(State state) {
4407     const char *rval = NULL;
4408     char rawbuffer[16]; // room for "%d"
4409 
4410     switch (state) {
4411         case UNINITIALIZED: rval = "UNINITIALIZED"; break;
4412         case INITIALIZING: rval = "INITIALIZING"; break;
4413         case INITIALIZED: rval = "INITIALIZED"; break;
4414         case CONFIGURING: rval = "CONFIGURING"; break;
4415         case CONFIGURED: rval = "CONFIGURED"; break;
4416         case STARTING: rval = "STARTING"; break;
4417         case STARTED: rval = "STARTED"; break;
4418         case FLUSHING: rval = "FLUSHING"; break;
4419         case FLUSHED: rval = "FLUSHED"; break;
4420         case STOPPING: rval = "STOPPING"; break;
4421         case RELEASING: rval = "RELEASING"; break;
4422         default:
4423             snprintf(rawbuffer, sizeof(rawbuffer), "%d", state);
4424             rval = rawbuffer;
4425             break;
4426     }
4427     return rval;
4428 }
4429 
4430 // static
CanFetchLinearBlock(const std::vector<std::string> & names,bool * isCompatible)4431 status_t MediaCodec::CanFetchLinearBlock(
4432         const std::vector<std::string> &names, bool *isCompatible) {
4433     *isCompatible = false;
4434     if (names.size() == 0) {
4435         *isCompatible = true;
4436         return OK;
4437     }
4438     const CodecListCache &cache = GetCodecListCache();
4439     for (const std::string &name : names) {
4440         auto it = cache.mCodecInfoMap.find(name);
4441         if (it == cache.mCodecInfoMap.end()) {
4442             return NAME_NOT_FOUND;
4443         }
4444         const char *owner = it->second->getOwnerName();
4445         if (owner == nullptr || strncmp(owner, "default", 8) == 0) {
4446             *isCompatible = false;
4447             return OK;
4448         } else if (strncmp(owner, "codec2::", 8) != 0) {
4449             return NAME_NOT_FOUND;
4450         }
4451     }
4452     return CCodec::CanFetchLinearBlock(names, kDefaultReadWriteUsage, isCompatible);
4453 }
4454 
4455 // static
FetchLinearBlock(size_t capacity,const std::vector<std::string> & names)4456 std::shared_ptr<C2LinearBlock> MediaCodec::FetchLinearBlock(
4457         size_t capacity, const std::vector<std::string> &names) {
4458     return CCodec::FetchLinearBlock(capacity, kDefaultReadWriteUsage, names);
4459 }
4460 
4461 // static
CanFetchGraphicBlock(const std::vector<std::string> & names,bool * isCompatible)4462 status_t MediaCodec::CanFetchGraphicBlock(
4463         const std::vector<std::string> &names, bool *isCompatible) {
4464     *isCompatible = false;
4465     if (names.size() == 0) {
4466         *isCompatible = true;
4467         return OK;
4468     }
4469     const CodecListCache &cache = GetCodecListCache();
4470     for (const std::string &name : names) {
4471         auto it = cache.mCodecInfoMap.find(name);
4472         if (it == cache.mCodecInfoMap.end()) {
4473             return NAME_NOT_FOUND;
4474         }
4475         const char *owner = it->second->getOwnerName();
4476         if (owner == nullptr || strncmp(owner, "default", 8) == 0) {
4477             *isCompatible = false;
4478             return OK;
4479         } else if (strncmp(owner, "codec2.", 7) != 0) {
4480             return NAME_NOT_FOUND;
4481         }
4482     }
4483     return CCodec::CanFetchGraphicBlock(names, isCompatible);
4484 }
4485 
4486 // static
FetchGraphicBlock(int32_t width,int32_t height,int32_t format,uint64_t usage,const std::vector<std::string> & names)4487 std::shared_ptr<C2GraphicBlock> MediaCodec::FetchGraphicBlock(
4488         int32_t width,
4489         int32_t height,
4490         int32_t format,
4491         uint64_t usage,
4492         const std::vector<std::string> &names) {
4493     return CCodec::FetchGraphicBlock(width, height, format, usage, names);
4494 }
4495 
4496 }  // namespace android
4497