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