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