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