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