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