MediaCodec.cpp revision 4f59c7e373a7e883f21ba33d44ea7caa86b65b02
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 if (csd->size() == 0) { 2236 ALOGW("csd-%zu size is 0", i); 2237 } 2238 2239 mCSD.push_back(csd); 2240 ++i; 2241 } 2242 2243 ALOGV("Found %zu pieces of codec specific data.", mCSD.size()); 2244} 2245 2246status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) { 2247 CHECK(!mCSD.empty()); 2248 2249 const BufferInfo *info = 2250 &mPortBuffers[kPortIndexInput].itemAt(bufferIndex); 2251 2252 sp<ABuffer> csd = *mCSD.begin(); 2253 mCSD.erase(mCSD.begin()); 2254 2255 const sp<ABuffer> &codecInputData = 2256 (mCrypto != NULL) ? info->mEncryptedData : info->mData; 2257 2258 if (csd->size() > codecInputData->capacity()) { 2259 return -EINVAL; 2260 } 2261 2262 memcpy(codecInputData->data(), csd->data(), csd->size()); 2263 2264 AString errorDetailMsg; 2265 2266 sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this); 2267 msg->setSize("index", bufferIndex); 2268 msg->setSize("offset", 0); 2269 msg->setSize("size", csd->size()); 2270 msg->setInt64("timeUs", 0ll); 2271 msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG); 2272 msg->setPointer("errorDetailMsg", &errorDetailMsg); 2273 2274 return onQueueInputBuffer(msg); 2275} 2276 2277void MediaCodec::setState(State newState) { 2278 if (newState == INITIALIZED || newState == UNINITIALIZED) { 2279 delete mSoftRenderer; 2280 mSoftRenderer = NULL; 2281 2282 mCrypto.clear(); 2283 handleSetSurface(NULL); 2284 2285 mInputFormat.clear(); 2286 mOutputFormat.clear(); 2287 mFlags &= ~kFlagOutputFormatChanged; 2288 mFlags &= ~kFlagOutputBuffersChanged; 2289 mFlags &= ~kFlagStickyError; 2290 mFlags &= ~kFlagIsEncoder; 2291 mFlags &= ~kFlagGatherCodecSpecificData; 2292 mFlags &= ~kFlagIsAsync; 2293 mStickyError = OK; 2294 2295 mActivityNotify.clear(); 2296 mCallback.clear(); 2297 } 2298 2299 if (newState == UNINITIALIZED) { 2300 // return any straggling buffers, e.g. if we got here on an error 2301 returnBuffersToCodec(); 2302 2303 // The component is gone, mediaserver's probably back up already 2304 // but should definitely be back up should we try to instantiate 2305 // another component.. and the cycle continues. 2306 mFlags &= ~kFlagSawMediaServerDie; 2307 } 2308 2309 mState = newState; 2310 2311 cancelPendingDequeueOperations(); 2312 2313 updateBatteryStat(); 2314} 2315 2316void MediaCodec::returnBuffersToCodec(bool isReclaim) { 2317 returnBuffersToCodecOnPort(kPortIndexInput, isReclaim); 2318 returnBuffersToCodecOnPort(kPortIndexOutput, isReclaim); 2319} 2320 2321void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex, bool isReclaim) { 2322 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 2323 Mutex::Autolock al(mBufferLock); 2324 2325 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; 2326 2327 for (size_t i = 0; i < buffers->size(); ++i) { 2328 BufferInfo *info = &buffers->editItemAt(i); 2329 2330 if (info->mNotify != NULL) { 2331 sp<AMessage> msg = info->mNotify; 2332 info->mNotify = NULL; 2333 if (isReclaim && info->mOwnedByClient) { 2334 ALOGD("port %d buffer %zu still owned by client when codec is reclaimed", 2335 portIndex, i); 2336 } else { 2337 info->mMemRef = NULL; 2338 info->mOwnedByClient = false; 2339 } 2340 2341 if (portIndex == kPortIndexInput) { 2342 /* no error, just returning buffers */ 2343 msg->setInt32("err", OK); 2344 } 2345 msg->post(); 2346 } 2347 } 2348 2349 mAvailPortBuffers[portIndex].clear(); 2350} 2351 2352size_t MediaCodec::updateBuffers( 2353 int32_t portIndex, const sp<AMessage> &msg) { 2354 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 2355 2356 uint32_t bufferID; 2357 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID)); 2358 2359 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; 2360 2361 for (size_t i = 0; i < buffers->size(); ++i) { 2362 BufferInfo *info = &buffers->editItemAt(i); 2363 2364 if (info->mBufferID == bufferID) { 2365 CHECK(info->mNotify == NULL); 2366 CHECK(msg->findMessage("reply", &info->mNotify)); 2367 2368 info->mFormat = 2369 (portIndex == kPortIndexInput) ? mInputFormat : mOutputFormat; 2370 mAvailPortBuffers[portIndex].push_back(i); 2371 2372 return i; 2373 } 2374 } 2375 2376 TRESPASS(); 2377 2378 return 0; 2379} 2380 2381status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) { 2382 size_t index; 2383 size_t offset; 2384 size_t size; 2385 int64_t timeUs; 2386 uint32_t flags; 2387 CHECK(msg->findSize("index", &index)); 2388 CHECK(msg->findSize("offset", &offset)); 2389 CHECK(msg->findInt64("timeUs", &timeUs)); 2390 CHECK(msg->findInt32("flags", (int32_t *)&flags)); 2391 2392 const CryptoPlugin::SubSample *subSamples; 2393 size_t numSubSamples; 2394 const uint8_t *key; 2395 const uint8_t *iv; 2396 CryptoPlugin::Mode mode = CryptoPlugin::kMode_Unencrypted; 2397 2398 // We allow the simpler queueInputBuffer API to be used even in 2399 // secure mode, by fabricating a single unencrypted subSample. 2400 CryptoPlugin::SubSample ss; 2401 CryptoPlugin::Pattern pattern; 2402 2403 if (msg->findSize("size", &size)) { 2404 if (mCrypto != NULL) { 2405 ss.mNumBytesOfClearData = size; 2406 ss.mNumBytesOfEncryptedData = 0; 2407 2408 subSamples = &ss; 2409 numSubSamples = 1; 2410 key = NULL; 2411 iv = NULL; 2412 pattern.mEncryptBlocks = 0; 2413 pattern.mSkipBlocks = 0; 2414 } 2415 } else { 2416 if (mCrypto == NULL) { 2417 return -EINVAL; 2418 } 2419 2420 CHECK(msg->findPointer("subSamples", (void **)&subSamples)); 2421 CHECK(msg->findSize("numSubSamples", &numSubSamples)); 2422 CHECK(msg->findPointer("key", (void **)&key)); 2423 CHECK(msg->findPointer("iv", (void **)&iv)); 2424 CHECK(msg->findInt32("encryptBlocks", (int32_t *)&pattern.mEncryptBlocks)); 2425 CHECK(msg->findInt32("skipBlocks", (int32_t *)&pattern.mSkipBlocks)); 2426 2427 int32_t tmp; 2428 CHECK(msg->findInt32("mode", &tmp)); 2429 2430 mode = (CryptoPlugin::Mode)tmp; 2431 2432 size = 0; 2433 for (size_t i = 0; i < numSubSamples; ++i) { 2434 size += subSamples[i].mNumBytesOfClearData; 2435 size += subSamples[i].mNumBytesOfEncryptedData; 2436 } 2437 } 2438 2439 if (index >= mPortBuffers[kPortIndexInput].size()) { 2440 return -ERANGE; 2441 } 2442 2443 BufferInfo *info = &mPortBuffers[kPortIndexInput].editItemAt(index); 2444 2445 if (info->mNotify == NULL || !info->mOwnedByClient) { 2446 return -EACCES; 2447 } 2448 2449 if (offset + size > info->mData->capacity()) { 2450 return -EINVAL; 2451 } 2452 2453 sp<AMessage> reply = info->mNotify; 2454 info->mData->setRange(offset, size); 2455 info->mData->meta()->setInt64("timeUs", timeUs); 2456 2457 if (flags & BUFFER_FLAG_EOS) { 2458 info->mData->meta()->setInt32("eos", true); 2459 } 2460 2461 if (flags & BUFFER_FLAG_CODECCONFIG) { 2462 info->mData->meta()->setInt32("csd", true); 2463 } 2464 2465 if (mCrypto != NULL) { 2466 if (size > info->mEncryptedData->capacity()) { 2467 return -ERANGE; 2468 } 2469 2470 AString *errorDetailMsg; 2471 CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg)); 2472 2473 ssize_t result = mCrypto->decrypt( 2474 (mFlags & kFlagIsSecure) != 0, 2475 key, 2476 iv, 2477 mode, 2478 pattern, 2479 info->mSharedEncryptedBuffer, 2480 offset, 2481 subSamples, 2482 numSubSamples, 2483 info->mData->base(), 2484 errorDetailMsg); 2485 2486 if (result < 0) { 2487 return result; 2488 } 2489 2490 info->mData->setRange(0, result); 2491 } 2492 2493 // synchronization boundary for getBufferAndFormat 2494 { 2495 Mutex::Autolock al(mBufferLock); 2496 info->mOwnedByClient = false; 2497 } 2498 reply->setBuffer("buffer", info->mData); 2499 reply->post(); 2500 2501 info->mNotify = NULL; 2502 2503 return OK; 2504} 2505 2506//static 2507size_t MediaCodec::CreateFramesRenderedMessage( 2508 std::list<FrameRenderTracker::Info> done, sp<AMessage> &msg) { 2509 size_t index = 0; 2510 2511 for (std::list<FrameRenderTracker::Info>::const_iterator it = done.cbegin(); 2512 it != done.cend(); ++it) { 2513 if (it->getRenderTimeNs() < 0) { 2514 continue; // dropped frame from tracking 2515 } 2516 msg->setInt64(AStringPrintf("%zu-media-time-us", index).c_str(), it->getMediaTimeUs()); 2517 msg->setInt64(AStringPrintf("%zu-system-nano", index).c_str(), it->getRenderTimeNs()); 2518 ++index; 2519 } 2520 return index; 2521} 2522 2523status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) { 2524 size_t index; 2525 CHECK(msg->findSize("index", &index)); 2526 2527 int32_t render; 2528 if (!msg->findInt32("render", &render)) { 2529 render = 0; 2530 } 2531 2532 if (!isExecuting()) { 2533 return -EINVAL; 2534 } 2535 2536 if (index >= mPortBuffers[kPortIndexOutput].size()) { 2537 return -ERANGE; 2538 } 2539 2540 BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index); 2541 2542 if (info->mNotify == NULL || !info->mOwnedByClient) { 2543 return -EACCES; 2544 } 2545 2546 // synchronization boundary for getBufferAndFormat 2547 { 2548 Mutex::Autolock al(mBufferLock); 2549 info->mOwnedByClient = false; 2550 } 2551 2552 if (render && info->mData != NULL && info->mData->size() != 0) { 2553 info->mNotify->setInt32("render", true); 2554 2555 int64_t mediaTimeUs = -1; 2556 info->mData->meta()->findInt64("timeUs", &mediaTimeUs); 2557 2558 int64_t renderTimeNs = 0; 2559 if (!msg->findInt64("timestampNs", &renderTimeNs)) { 2560 // use media timestamp if client did not request a specific render timestamp 2561 ALOGV("using buffer PTS of %lld", (long long)mediaTimeUs); 2562 renderTimeNs = mediaTimeUs * 1000; 2563 } 2564 info->mNotify->setInt64("timestampNs", renderTimeNs); 2565 2566 if (mSoftRenderer != NULL) { 2567 std::list<FrameRenderTracker::Info> doneFrames = mSoftRenderer->render( 2568 info->mData->data(), info->mData->size(), 2569 mediaTimeUs, renderTimeNs, NULL, info->mFormat); 2570 2571 // if we are running, notify rendered frames 2572 if (!doneFrames.empty() && mState == STARTED && mOnFrameRenderedNotification != NULL) { 2573 sp<AMessage> notify = mOnFrameRenderedNotification->dup(); 2574 sp<AMessage> data = new AMessage; 2575 if (CreateFramesRenderedMessage(doneFrames, data)) { 2576 notify->setMessage("data", data); 2577 notify->post(); 2578 } 2579 } 2580 } 2581 } 2582 2583 info->mNotify->post(); 2584 info->mNotify = NULL; 2585 2586 return OK; 2587} 2588 2589ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) { 2590 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 2591 2592 List<size_t> *availBuffers = &mAvailPortBuffers[portIndex]; 2593 2594 if (availBuffers->empty()) { 2595 return -EAGAIN; 2596 } 2597 2598 size_t index = *availBuffers->begin(); 2599 availBuffers->erase(availBuffers->begin()); 2600 2601 BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index); 2602 CHECK(!info->mOwnedByClient); 2603 { 2604 Mutex::Autolock al(mBufferLock); 2605 info->mOwnedByClient = true; 2606 2607 // set image-data 2608 if (info->mFormat != NULL) { 2609 sp<ABuffer> imageData; 2610 if (info->mFormat->findBuffer("image-data", &imageData)) { 2611 info->mData->meta()->setBuffer("image-data", imageData); 2612 } 2613 int32_t left, top, right, bottom; 2614 if (info->mFormat->findRect("crop", &left, &top, &right, &bottom)) { 2615 info->mData->meta()->setRect("crop-rect", left, top, right, bottom); 2616 } 2617 } 2618 } 2619 2620 return index; 2621} 2622 2623status_t MediaCodec::connectToSurface(const sp<Surface> &surface) { 2624 status_t err = OK; 2625 if (surface != NULL) { 2626 err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA); 2627 if (err == BAD_VALUE) { 2628 ALOGI("native window already connected. Assuming no change of surface"); 2629 return err; 2630 } else if (err == OK) { 2631 // Require a fresh set of buffers after each connect by using a unique generation 2632 // number. Rely on the fact that max supported process id by Linux is 2^22. 2633 // PID is never 0 so we don't have to worry that we use the default generation of 0. 2634 // TODO: come up with a unique scheme if other producers also set the generation number. 2635 static uint32_t mSurfaceGeneration = 0; 2636 uint32_t generation = (getpid() << 10) | (++mSurfaceGeneration & ((1 << 10) - 1)); 2637 surface->setGenerationNumber(generation); 2638 ALOGI("[%s] setting surface generation to %u", mComponentName.c_str(), generation); 2639 2640 // HACK: clear any free buffers. Remove when connect will automatically do this. 2641 // This is needed as the consumer may be holding onto stale frames that it can reattach 2642 // to this surface after disconnect/connect, and those free frames would inherit the new 2643 // generation number. Disconnecting after setting a unique generation prevents this. 2644 native_window_api_disconnect(surface.get(), NATIVE_WINDOW_API_MEDIA); 2645 err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA); 2646 } 2647 2648 if (err != OK) { 2649 ALOGE("native_window_api_connect returned an error: %s (%d)", strerror(-err), err); 2650 } 2651 } 2652 return err; 2653} 2654 2655status_t MediaCodec::disconnectFromSurface() { 2656 status_t err = OK; 2657 if (mSurface != NULL) { 2658 // Resetting generation is not technically needed, but there is no need to keep it either 2659 mSurface->setGenerationNumber(0); 2660 err = native_window_api_disconnect(mSurface.get(), NATIVE_WINDOW_API_MEDIA); 2661 if (err != OK) { 2662 ALOGW("native_window_api_disconnect returned an error: %s (%d)", strerror(-err), err); 2663 } 2664 // assume disconnected even on error 2665 mSurface.clear(); 2666 } 2667 return err; 2668} 2669 2670status_t MediaCodec::handleSetSurface(const sp<Surface> &surface) { 2671 status_t err = OK; 2672 if (mSurface != NULL) { 2673 (void)disconnectFromSurface(); 2674 } 2675 if (surface != NULL) { 2676 err = connectToSurface(surface); 2677 if (err == OK) { 2678 mSurface = surface; 2679 } 2680 } 2681 return err; 2682} 2683 2684void MediaCodec::onInputBufferAvailable() { 2685 int32_t index; 2686 while ((index = dequeuePortBuffer(kPortIndexInput)) >= 0) { 2687 sp<AMessage> msg = mCallback->dup(); 2688 msg->setInt32("callbackID", CB_INPUT_AVAILABLE); 2689 msg->setInt32("index", index); 2690 msg->post(); 2691 } 2692} 2693 2694void MediaCodec::onOutputBufferAvailable() { 2695 int32_t index; 2696 while ((index = dequeuePortBuffer(kPortIndexOutput)) >= 0) { 2697 const sp<ABuffer> &buffer = 2698 mPortBuffers[kPortIndexOutput].itemAt(index).mData; 2699 sp<AMessage> msg = mCallback->dup(); 2700 msg->setInt32("callbackID", CB_OUTPUT_AVAILABLE); 2701 msg->setInt32("index", index); 2702 msg->setSize("offset", buffer->offset()); 2703 msg->setSize("size", buffer->size()); 2704 2705 int64_t timeUs; 2706 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 2707 2708 msg->setInt64("timeUs", timeUs); 2709 2710 int32_t omxFlags; 2711 CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags)); 2712 2713 uint32_t flags = 0; 2714 if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) { 2715 flags |= BUFFER_FLAG_SYNCFRAME; 2716 } 2717 if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) { 2718 flags |= BUFFER_FLAG_CODECCONFIG; 2719 } 2720 if (omxFlags & OMX_BUFFERFLAG_EOS) { 2721 flags |= BUFFER_FLAG_EOS; 2722 } 2723 2724 msg->setInt32("flags", flags); 2725 2726 msg->post(); 2727 } 2728} 2729 2730void MediaCodec::onError(status_t err, int32_t actionCode, const char *detail) { 2731 if (mCallback != NULL) { 2732 sp<AMessage> msg = mCallback->dup(); 2733 msg->setInt32("callbackID", CB_ERROR); 2734 msg->setInt32("err", err); 2735 msg->setInt32("actionCode", actionCode); 2736 2737 if (detail != NULL) { 2738 msg->setString("detail", detail); 2739 } 2740 2741 msg->post(); 2742 } 2743} 2744 2745void MediaCodec::onOutputFormatChanged() { 2746 if (mCallback != NULL) { 2747 sp<AMessage> msg = mCallback->dup(); 2748 msg->setInt32("callbackID", CB_OUTPUT_FORMAT_CHANGED); 2749 msg->setMessage("format", mOutputFormat); 2750 msg->post(); 2751 } 2752} 2753 2754 2755void MediaCodec::postActivityNotificationIfPossible() { 2756 if (mActivityNotify == NULL) { 2757 return; 2758 } 2759 2760 bool isErrorOrOutputChanged = 2761 (mFlags & (kFlagStickyError 2762 | kFlagOutputBuffersChanged 2763 | kFlagOutputFormatChanged)); 2764 2765 if (isErrorOrOutputChanged 2766 || !mAvailPortBuffers[kPortIndexInput].empty() 2767 || !mAvailPortBuffers[kPortIndexOutput].empty()) { 2768 mActivityNotify->setInt32("input-buffers", 2769 mAvailPortBuffers[kPortIndexInput].size()); 2770 2771 if (isErrorOrOutputChanged) { 2772 // we want consumer to dequeue as many times as it can 2773 mActivityNotify->setInt32("output-buffers", INT32_MAX); 2774 } else { 2775 mActivityNotify->setInt32("output-buffers", 2776 mAvailPortBuffers[kPortIndexOutput].size()); 2777 } 2778 mActivityNotify->post(); 2779 mActivityNotify.clear(); 2780 } 2781} 2782 2783status_t MediaCodec::setParameters(const sp<AMessage> ¶ms) { 2784 sp<AMessage> msg = new AMessage(kWhatSetParameters, this); 2785 msg->setMessage("params", params); 2786 2787 sp<AMessage> response; 2788 return PostAndAwaitResponse(msg, &response); 2789} 2790 2791status_t MediaCodec::onSetParameters(const sp<AMessage> ¶ms) { 2792 mCodec->signalSetParameters(params); 2793 2794 return OK; 2795} 2796 2797status_t MediaCodec::amendOutputFormatWithCodecSpecificData( 2798 const sp<ABuffer> &buffer) { 2799 AString mime; 2800 CHECK(mOutputFormat->findString("mime", &mime)); 2801 2802 if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) { 2803 // Codec specific data should be SPS and PPS in a single buffer, 2804 // each prefixed by a startcode (0x00 0x00 0x00 0x01). 2805 // We separate the two and put them into the output format 2806 // under the keys "csd-0" and "csd-1". 2807 2808 unsigned csdIndex = 0; 2809 2810 const uint8_t *data = buffer->data(); 2811 size_t size = buffer->size(); 2812 2813 const uint8_t *nalStart; 2814 size_t nalSize; 2815 while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) { 2816 sp<ABuffer> csd = new ABuffer(nalSize + 4); 2817 memcpy(csd->data(), "\x00\x00\x00\x01", 4); 2818 memcpy(csd->data() + 4, nalStart, nalSize); 2819 2820 mOutputFormat->setBuffer( 2821 AStringPrintf("csd-%u", csdIndex).c_str(), csd); 2822 2823 ++csdIndex; 2824 } 2825 2826 if (csdIndex != 2) { 2827 return ERROR_MALFORMED; 2828 } 2829 } else { 2830 // For everything else we just stash the codec specific data into 2831 // the output format as a single piece of csd under "csd-0". 2832 mOutputFormat->setBuffer("csd-0", buffer); 2833 } 2834 2835 return OK; 2836} 2837 2838void MediaCodec::updateBatteryStat() { 2839 if (!mIsVideo) { 2840 return; 2841 } 2842 2843 if (mState == CONFIGURED && !mBatteryStatNotified) { 2844 BatteryNotifier::getInstance().noteStartVideo(); 2845 mBatteryStatNotified = true; 2846 } else if (mState == UNINITIALIZED && mBatteryStatNotified) { 2847 BatteryNotifier::getInstance().noteStopVideo(); 2848 mBatteryStatNotified = false; 2849 } 2850} 2851 2852} // namespace android 2853