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