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