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