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