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