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