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