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