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> ¬ify);
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> ¬ify)
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> ¬ify);
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> ¬ify) : 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> ¬ify) {
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> ¬ify) {
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> ¬ify) {
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", ¬ify)) {
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", ¶ms));
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> ¶ms) {
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> ¶ms) {
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