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