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