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