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