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