MediaCodec.cpp revision ad60a0f6cd9012507f8086fe741236d12d280ef3
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 1343 size_t totalSize = 0; 1344 for (size_t i = 0; i < numBuffers; ++i) { 1345 if (portIndex == kPortIndexInput && mCrypto != NULL) { 1346 totalSize += portDesc->bufferAt(i)->capacity(); 1347 } 1348 } 1349 1350 if (totalSize) { 1351 mDealer = new MemoryDealer(totalSize, "MediaCodec"); 1352 } 1353 1354 for (size_t i = 0; i < numBuffers; ++i) { 1355 BufferInfo info; 1356 info.mBufferID = portDesc->bufferIDAt(i); 1357 info.mOwnedByClient = false; 1358 sp<MediaCodecBuffer> buffer = portDesc->bufferAt(i); 1359 if (portIndex == kPortIndexInput && mCrypto != NULL) { 1360 info.mSharedEncryptedBuffer = mDealer->allocate(buffer->capacity()); 1361 buffer = new SharedMemoryBuffer( 1362 mInputFormat, info.mSharedEncryptedBuffer); 1363 } 1364 buffers->push_back(info); 1365 mPortBufferArrays[portIndex].push_back(buffer); 1366 } 1367 1368 if (portIndex == kPortIndexOutput) { 1369 if (mState == STARTING) { 1370 // We're always allocating output buffers after 1371 // allocating input buffers, so this is a good 1372 // indication that now all buffers are allocated. 1373 if (mIsVideo) { 1374 addResource( 1375 MediaResource::kGraphicMemory, 1376 MediaResource::kUnspecifiedSubType, 1377 getGraphicBufferSize()); 1378 } 1379 setState(STARTED); 1380 (new AMessage)->postReply(mReplyID); 1381 } else { 1382 mFlags |= kFlagOutputBuffersChanged; 1383 postActivityNotificationIfPossible(); 1384 } 1385 } 1386 break; 1387 } 1388 1389 case CodecBase::kWhatOutputFramesRendered: 1390 { 1391 // ignore these in all states except running, and check that we have a 1392 // notification set 1393 if (mState == STARTED && mOnFrameRenderedNotification != NULL) { 1394 sp<AMessage> notify = mOnFrameRenderedNotification->dup(); 1395 notify->setMessage("data", msg); 1396 notify->post(); 1397 } 1398 break; 1399 } 1400 1401 case CodecBase::kWhatFillThisBuffer: 1402 { 1403 /* size_t index = */updateBuffers(kPortIndexInput, msg); 1404 1405 if (mState == FLUSHING 1406 || mState == STOPPING 1407 || mState == RELEASING) { 1408 returnBuffersToCodecOnPort(kPortIndexInput); 1409 break; 1410 } 1411 1412 // TODO: hold reference of buffer from downstream when 1413 // mPortBuffers is removed. 1414 1415 if (!mCSD.empty()) { 1416 ssize_t index = dequeuePortBuffer(kPortIndexInput); 1417 CHECK_GE(index, 0); 1418 1419 // If codec specific data had been specified as 1420 // part of the format in the call to configure and 1421 // if there's more csd left, we submit it here 1422 // clients only get access to input buffers once 1423 // this data has been exhausted. 1424 1425 status_t err = queueCSDInputBuffer(index); 1426 1427 if (err != OK) { 1428 ALOGE("queueCSDInputBuffer failed w/ error %d", 1429 err); 1430 1431 setStickyError(err); 1432 postActivityNotificationIfPossible(); 1433 1434 cancelPendingDequeueOperations(); 1435 } 1436 break; 1437 } 1438 1439 if (mFlags & kFlagIsAsync) { 1440 if (!mHaveInputSurface) { 1441 if (mState == FLUSHED) { 1442 mHavePendingInputBuffers = true; 1443 } else { 1444 onInputBufferAvailable(); 1445 } 1446 } 1447 } else if (mFlags & kFlagDequeueInputPending) { 1448 CHECK(handleDequeueInputBuffer(mDequeueInputReplyID)); 1449 1450 ++mDequeueInputTimeoutGeneration; 1451 mFlags &= ~kFlagDequeueInputPending; 1452 mDequeueInputReplyID = 0; 1453 } else { 1454 postActivityNotificationIfPossible(); 1455 } 1456 break; 1457 } 1458 1459 case CodecBase::kWhatDrainThisBuffer: 1460 { 1461 /* size_t index = */updateBuffers(kPortIndexOutput, msg); 1462 1463 if (mState == FLUSHING 1464 || mState == STOPPING 1465 || mState == RELEASING) { 1466 returnBuffersToCodecOnPort(kPortIndexOutput); 1467 break; 1468 } 1469 1470 sp<RefBase> obj; 1471 CHECK(msg->findObject("buffer", &obj)); 1472 sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get()); 1473 // TODO: hold buffer's reference when we remove mPortBuffers 1474 1475 int32_t omxFlags; 1476 CHECK(msg->findInt32("flags", &omxFlags)); 1477 1478 buffer->meta()->setInt32("omxFlags", omxFlags); 1479 if (mOutputFormat != buffer->format()) { 1480 mOutputFormat = buffer->format(); 1481 ALOGV("[%s] output format changed to: %s", 1482 mComponentName.c_str(), mOutputFormat->debugString(4).c_str()); 1483 1484 if (mSoftRenderer == NULL && 1485 mSurface != NULL && 1486 (mFlags & kFlagUsesSoftwareRenderer)) { 1487 AString mime; 1488 CHECK(mOutputFormat->findString("mime", &mime)); 1489 1490 // TODO: propagate color aspects to software renderer to allow better 1491 // color conversion to RGB. For now, just mark dataspace for YUV 1492 // rendering. 1493 int32_t dataSpace; 1494 if (mOutputFormat->findInt32("android._dataspace", &dataSpace)) { 1495 ALOGD("[%s] setting dataspace on output surface to #%x", 1496 mComponentName.c_str(), dataSpace); 1497 int err = native_window_set_buffers_data_space( 1498 mSurface.get(), (android_dataspace)dataSpace); 1499 ALOGW_IF(err != 0, "failed to set dataspace on surface (%d)", err); 1500 } 1501 1502 if (mime.startsWithIgnoreCase("video/")) { 1503 mSoftRenderer = new SoftwareRenderer(mSurface, mRotationDegrees); 1504 } 1505 } 1506 1507 if (mFlags & kFlagIsEncoder) { 1508 // Before we announce the format change we should 1509 // collect codec specific data and amend the output 1510 // format as necessary. 1511 if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) { 1512 status_t err = 1513 amendOutputFormatWithCodecSpecificData(buffer); 1514 1515 if (err != OK) { 1516 ALOGE("Codec spit out malformed codec " 1517 "specific data!"); 1518 } 1519 } 1520 } 1521 1522 if (mFlags & kFlagIsAsync) { 1523 onOutputFormatChanged(); 1524 } else { 1525 mFlags |= kFlagOutputFormatChanged; 1526 postActivityNotificationIfPossible(); 1527 } 1528 1529 // Notify mCrypto of video resolution changes 1530 if (mCrypto != NULL) { 1531 int32_t left, top, right, bottom, width, height; 1532 if (mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) { 1533 mCrypto->notifyResolution(right - left + 1, bottom - top + 1); 1534 } else if (mOutputFormat->findInt32("width", &width) 1535 && mOutputFormat->findInt32("height", &height)) { 1536 mCrypto->notifyResolution(width, height); 1537 } 1538 } 1539 } 1540 1541 if (mFlags & kFlagIsAsync) { 1542 onOutputBufferAvailable(); 1543 } else if (mFlags & kFlagDequeueOutputPending) { 1544 CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID)); 1545 1546 ++mDequeueOutputTimeoutGeneration; 1547 mFlags &= ~kFlagDequeueOutputPending; 1548 mDequeueOutputReplyID = 0; 1549 } else { 1550 postActivityNotificationIfPossible(); 1551 } 1552 1553 break; 1554 } 1555 1556 case CodecBase::kWhatEOS: 1557 { 1558 // We already notify the client of this by using the 1559 // corresponding flag in "onOutputBufferReady". 1560 break; 1561 } 1562 1563 case CodecBase::kWhatShutdownCompleted: 1564 { 1565 if (mState == UNINITIALIZED) { 1566 // Ignore shutdown complete if we're already released. 1567 break; 1568 } 1569 if (mState == STOPPING) { 1570 setState(INITIALIZED); 1571 } else { 1572 CHECK_EQ(mState, RELEASING); 1573 setState(UNINITIALIZED); 1574 mComponentName.clear(); 1575 } 1576 mFlags &= ~kFlagIsComponentAllocated; 1577 1578 mResourceManagerService->removeResource(getId(mResourceManagerClient)); 1579 1580 (new AMessage)->postReply(mReplyID); 1581 break; 1582 } 1583 1584 case CodecBase::kWhatFlushCompleted: 1585 { 1586 if (mState != FLUSHING) { 1587 ALOGW("received FlushCompleted message in state %d", 1588 mState); 1589 break; 1590 } 1591 1592 if (mFlags & kFlagIsAsync) { 1593 setState(FLUSHED); 1594 } else { 1595 setState(STARTED); 1596 mCodec->signalResume(); 1597 } 1598 1599 (new AMessage)->postReply(mReplyID); 1600 break; 1601 } 1602 1603 default: 1604 TRESPASS(); 1605 } 1606 break; 1607 } 1608 1609 case kWhatInit: 1610 { 1611 sp<AReplyToken> replyID; 1612 CHECK(msg->senderAwaitsResponse(&replyID)); 1613 1614 if (mState != UNINITIALIZED) { 1615 PostReplyWithError(replyID, INVALID_OPERATION); 1616 break; 1617 } 1618 1619 mReplyID = replyID; 1620 setState(INITIALIZING); 1621 1622 AString name; 1623 CHECK(msg->findString("name", &name)); 1624 1625 int32_t nameIsType; 1626 int32_t encoder = false; 1627 CHECK(msg->findInt32("nameIsType", &nameIsType)); 1628 if (nameIsType) { 1629 CHECK(msg->findInt32("encoder", &encoder)); 1630 } 1631 1632 sp<AMessage> format = new AMessage; 1633 1634 if (nameIsType) { 1635 format->setString("mime", name.c_str()); 1636 format->setInt32("encoder", encoder); 1637 } else { 1638 format->setString("componentName", name.c_str()); 1639 } 1640 1641 mCodec->initiateAllocateComponent(format); 1642 break; 1643 } 1644 1645 case kWhatSetNotification: 1646 { 1647 sp<AMessage> notify; 1648 if (msg->findMessage("on-frame-rendered", ¬ify)) { 1649 mOnFrameRenderedNotification = notify; 1650 } 1651 break; 1652 } 1653 1654 case kWhatSetCallback: 1655 { 1656 sp<AReplyToken> replyID; 1657 CHECK(msg->senderAwaitsResponse(&replyID)); 1658 1659 if (mState == UNINITIALIZED 1660 || mState == INITIALIZING 1661 || isExecuting()) { 1662 // callback can't be set after codec is executing, 1663 // or before it's initialized (as the callback 1664 // will be cleared when it goes to INITIALIZED) 1665 PostReplyWithError(replyID, INVALID_OPERATION); 1666 break; 1667 } 1668 1669 sp<AMessage> callback; 1670 CHECK(msg->findMessage("callback", &callback)); 1671 1672 mCallback = callback; 1673 1674 if (mCallback != NULL) { 1675 ALOGI("MediaCodec will operate in async mode"); 1676 mFlags |= kFlagIsAsync; 1677 } else { 1678 mFlags &= ~kFlagIsAsync; 1679 } 1680 1681 sp<AMessage> response = new AMessage; 1682 response->postReply(replyID); 1683 break; 1684 } 1685 1686 case kWhatConfigure: 1687 { 1688 sp<AReplyToken> replyID; 1689 CHECK(msg->senderAwaitsResponse(&replyID)); 1690 1691 if (mState != INITIALIZED) { 1692 PostReplyWithError(replyID, INVALID_OPERATION); 1693 break; 1694 } 1695 1696 sp<RefBase> obj; 1697 CHECK(msg->findObject("surface", &obj)); 1698 1699 sp<AMessage> format; 1700 CHECK(msg->findMessage("format", &format)); 1701 1702 int32_t push; 1703 if (msg->findInt32("push-blank-buffers-on-shutdown", &push) && push != 0) { 1704 mFlags |= kFlagPushBlankBuffersOnShutdown; 1705 } 1706 1707 if (obj != NULL) { 1708 format->setObject("native-window", obj); 1709 status_t err = handleSetSurface(static_cast<Surface *>(obj.get())); 1710 if (err != OK) { 1711 PostReplyWithError(replyID, err); 1712 break; 1713 } 1714 } else { 1715 handleSetSurface(NULL); 1716 } 1717 1718 mReplyID = replyID; 1719 setState(CONFIGURING); 1720 1721 void *crypto; 1722 if (!msg->findPointer("crypto", &crypto)) { 1723 crypto = NULL; 1724 } 1725 1726 mCrypto = static_cast<ICrypto *>(crypto); 1727 1728 uint32_t flags; 1729 CHECK(msg->findInt32("flags", (int32_t *)&flags)); 1730 1731 if (flags & CONFIGURE_FLAG_ENCODE) { 1732 format->setInt32("encoder", true); 1733 mFlags |= kFlagIsEncoder; 1734 } 1735 1736 extractCSD(format); 1737 1738 mCodec->initiateConfigureComponent(format); 1739 break; 1740 } 1741 1742 case kWhatSetSurface: 1743 { 1744 sp<AReplyToken> replyID; 1745 CHECK(msg->senderAwaitsResponse(&replyID)); 1746 1747 status_t err = OK; 1748 sp<Surface> surface; 1749 1750 switch (mState) { 1751 case CONFIGURED: 1752 case STARTED: 1753 case FLUSHED: 1754 { 1755 sp<RefBase> obj; 1756 (void)msg->findObject("surface", &obj); 1757 sp<Surface> surface = static_cast<Surface *>(obj.get()); 1758 if (mSurface == NULL) { 1759 // do not support setting surface if it was not set 1760 err = INVALID_OPERATION; 1761 } else if (obj == NULL) { 1762 // do not support unsetting surface 1763 err = BAD_VALUE; 1764 } else { 1765 err = connectToSurface(surface); 1766 if (err == ALREADY_EXISTS) { 1767 // reconnecting to same surface 1768 err = OK; 1769 } else { 1770 if (err == OK) { 1771 if (mFlags & kFlagUsesSoftwareRenderer) { 1772 if (mSoftRenderer != NULL 1773 && (mFlags & kFlagPushBlankBuffersOnShutdown)) { 1774 pushBlankBuffersToNativeWindow(mSurface.get()); 1775 } 1776 mSoftRenderer = new SoftwareRenderer(surface); 1777 // TODO: check if this was successful 1778 } else { 1779 err = mCodec->setSurface(surface); 1780 } 1781 } 1782 if (err == OK) { 1783 (void)disconnectFromSurface(); 1784 mSurface = surface; 1785 } 1786 } 1787 } 1788 break; 1789 } 1790 1791 default: 1792 err = INVALID_OPERATION; 1793 break; 1794 } 1795 1796 PostReplyWithError(replyID, err); 1797 break; 1798 } 1799 1800 case kWhatCreateInputSurface: 1801 case kWhatSetInputSurface: 1802 { 1803 sp<AReplyToken> replyID; 1804 CHECK(msg->senderAwaitsResponse(&replyID)); 1805 1806 // Must be configured, but can't have been started yet. 1807 if (mState != CONFIGURED) { 1808 PostReplyWithError(replyID, INVALID_OPERATION); 1809 break; 1810 } 1811 1812 mReplyID = replyID; 1813 if (msg->what() == kWhatCreateInputSurface) { 1814 mCodec->initiateCreateInputSurface(); 1815 } else { 1816 sp<RefBase> obj; 1817 CHECK(msg->findObject("input-surface", &obj)); 1818 1819 mCodec->initiateSetInputSurface( 1820 static_cast<PersistentSurface *>(obj.get())); 1821 } 1822 break; 1823 } 1824 case kWhatStart: 1825 { 1826 sp<AReplyToken> replyID; 1827 CHECK(msg->senderAwaitsResponse(&replyID)); 1828 1829 if (mState == FLUSHED) { 1830 setState(STARTED); 1831 if (mHavePendingInputBuffers) { 1832 onInputBufferAvailable(); 1833 mHavePendingInputBuffers = false; 1834 } 1835 mCodec->signalResume(); 1836 PostReplyWithError(replyID, OK); 1837 break; 1838 } else if (mState != CONFIGURED) { 1839 PostReplyWithError(replyID, INVALID_OPERATION); 1840 break; 1841 } 1842 1843 mReplyID = replyID; 1844 setState(STARTING); 1845 1846 mCodec->initiateStart(); 1847 break; 1848 } 1849 1850 case kWhatStop: 1851 case kWhatRelease: 1852 { 1853 State targetState = 1854 (msg->what() == kWhatStop) ? INITIALIZED : UNINITIALIZED; 1855 1856 sp<AReplyToken> replyID; 1857 CHECK(msg->senderAwaitsResponse(&replyID)); 1858 1859 // already stopped/released 1860 if (mState == UNINITIALIZED && mReleasedByResourceManager) { 1861 sp<AMessage> response = new AMessage; 1862 response->setInt32("err", OK); 1863 response->postReply(replyID); 1864 break; 1865 } 1866 1867 int32_t reclaimed = 0; 1868 msg->findInt32("reclaimed", &reclaimed); 1869 if (reclaimed) { 1870 mReleasedByResourceManager = true; 1871 1872 int32_t force = 0; 1873 msg->findInt32("force", &force); 1874 if (!force && hasPendingBuffer()) { 1875 ALOGW("Can't reclaim codec right now due to pending buffers."); 1876 1877 // return WOULD_BLOCK to ask resource manager to retry later. 1878 sp<AMessage> response = new AMessage; 1879 response->setInt32("err", WOULD_BLOCK); 1880 response->postReply(replyID); 1881 1882 // notify the async client 1883 if (mFlags & kFlagIsAsync) { 1884 onError(DEAD_OBJECT, ACTION_CODE_FATAL); 1885 } 1886 break; 1887 } 1888 } 1889 1890 bool isReleasingAllocatedComponent = 1891 (mFlags & kFlagIsComponentAllocated) && targetState == UNINITIALIZED; 1892 if (!isReleasingAllocatedComponent // See 1 1893 && mState != INITIALIZED 1894 && mState != CONFIGURED && !isExecuting()) { 1895 // 1) Permit release to shut down the component if allocated. 1896 // 1897 // 2) We may be in "UNINITIALIZED" state already and 1898 // also shutdown the encoder/decoder without the 1899 // client being aware of this if media server died while 1900 // we were being stopped. The client would assume that 1901 // after stop() returned, it would be safe to call release() 1902 // and it should be in this case, no harm to allow a release() 1903 // if we're already uninitialized. 1904 sp<AMessage> response = new AMessage; 1905 // TODO: we shouldn't throw an exception for stop/release. Change this to wait until 1906 // the previous stop/release completes and then reply with OK. 1907 status_t err = mState == targetState ? OK : INVALID_OPERATION; 1908 response->setInt32("err", err); 1909 if (err == OK && targetState == UNINITIALIZED) { 1910 mComponentName.clear(); 1911 } 1912 response->postReply(replyID); 1913 break; 1914 } 1915 1916 // If we're flushing, or we're stopping but received a release 1917 // request, post the reply for the pending call first, and consider 1918 // it done. The reply token will be replaced after this, and we'll 1919 // no longer be able to reply. 1920 if (mState == FLUSHING || mState == STOPPING) { 1921 (new AMessage)->postReply(mReplyID); 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 // If we already have an error, component may not be able to 1936 // complete the shutdown properly. If we're stopping, post the 1937 // reply now with an error to unblock the client, client can 1938 // release after the failure (instead of ANR). 1939 if (msg->what() == kWhatStop && (mFlags & kFlagStickyError)) { 1940 PostReplyWithError(replyID, getStickyError()); 1941 break; 1942 } 1943 1944 mReplyID = replyID; 1945 setState(msg->what() == kWhatStop ? STOPPING : RELEASING); 1946 1947 mCodec->initiateShutdown( 1948 msg->what() == kWhatStop /* keepComponentAllocated */); 1949 1950 returnBuffersToCodec(reclaimed); 1951 1952 if (mSoftRenderer != NULL && (mFlags & kFlagPushBlankBuffersOnShutdown)) { 1953 pushBlankBuffersToNativeWindow(mSurface.get()); 1954 } 1955 1956 break; 1957 } 1958 1959 case kWhatDequeueInputBuffer: 1960 { 1961 sp<AReplyToken> replyID; 1962 CHECK(msg->senderAwaitsResponse(&replyID)); 1963 1964 if (mFlags & kFlagIsAsync) { 1965 ALOGE("dequeueOutputBuffer can't be used in async mode"); 1966 PostReplyWithError(replyID, INVALID_OPERATION); 1967 break; 1968 } 1969 1970 if (mHaveInputSurface) { 1971 ALOGE("dequeueInputBuffer can't be used with input surface"); 1972 PostReplyWithError(replyID, INVALID_OPERATION); 1973 break; 1974 } 1975 1976 if (handleDequeueInputBuffer(replyID, true /* new request */)) { 1977 break; 1978 } 1979 1980 int64_t timeoutUs; 1981 CHECK(msg->findInt64("timeoutUs", &timeoutUs)); 1982 1983 if (timeoutUs == 0ll) { 1984 PostReplyWithError(replyID, -EAGAIN); 1985 break; 1986 } 1987 1988 mFlags |= kFlagDequeueInputPending; 1989 mDequeueInputReplyID = replyID; 1990 1991 if (timeoutUs > 0ll) { 1992 sp<AMessage> timeoutMsg = 1993 new AMessage(kWhatDequeueInputTimedOut, this); 1994 timeoutMsg->setInt32( 1995 "generation", ++mDequeueInputTimeoutGeneration); 1996 timeoutMsg->post(timeoutUs); 1997 } 1998 break; 1999 } 2000 2001 case kWhatDequeueInputTimedOut: 2002 { 2003 int32_t generation; 2004 CHECK(msg->findInt32("generation", &generation)); 2005 2006 if (generation != mDequeueInputTimeoutGeneration) { 2007 // Obsolete 2008 break; 2009 } 2010 2011 CHECK(mFlags & kFlagDequeueInputPending); 2012 2013 PostReplyWithError(mDequeueInputReplyID, -EAGAIN); 2014 2015 mFlags &= ~kFlagDequeueInputPending; 2016 mDequeueInputReplyID = 0; 2017 break; 2018 } 2019 2020 case kWhatQueueInputBuffer: 2021 { 2022 sp<AReplyToken> replyID; 2023 CHECK(msg->senderAwaitsResponse(&replyID)); 2024 2025 if (!isExecuting()) { 2026 PostReplyWithError(replyID, INVALID_OPERATION); 2027 break; 2028 } else if (mFlags & kFlagStickyError) { 2029 PostReplyWithError(replyID, getStickyError()); 2030 break; 2031 } 2032 2033 status_t err = onQueueInputBuffer(msg); 2034 2035 PostReplyWithError(replyID, err); 2036 break; 2037 } 2038 2039 case kWhatDequeueOutputBuffer: 2040 { 2041 sp<AReplyToken> replyID; 2042 CHECK(msg->senderAwaitsResponse(&replyID)); 2043 2044 if (mFlags & kFlagIsAsync) { 2045 ALOGE("dequeueOutputBuffer can't be used in async mode"); 2046 PostReplyWithError(replyID, INVALID_OPERATION); 2047 break; 2048 } 2049 2050 if (handleDequeueOutputBuffer(replyID, true /* new request */)) { 2051 break; 2052 } 2053 2054 int64_t timeoutUs; 2055 CHECK(msg->findInt64("timeoutUs", &timeoutUs)); 2056 2057 if (timeoutUs == 0ll) { 2058 PostReplyWithError(replyID, -EAGAIN); 2059 break; 2060 } 2061 2062 mFlags |= kFlagDequeueOutputPending; 2063 mDequeueOutputReplyID = replyID; 2064 2065 if (timeoutUs > 0ll) { 2066 sp<AMessage> timeoutMsg = 2067 new AMessage(kWhatDequeueOutputTimedOut, this); 2068 timeoutMsg->setInt32( 2069 "generation", ++mDequeueOutputTimeoutGeneration); 2070 timeoutMsg->post(timeoutUs); 2071 } 2072 break; 2073 } 2074 2075 case kWhatDequeueOutputTimedOut: 2076 { 2077 int32_t generation; 2078 CHECK(msg->findInt32("generation", &generation)); 2079 2080 if (generation != mDequeueOutputTimeoutGeneration) { 2081 // Obsolete 2082 break; 2083 } 2084 2085 CHECK(mFlags & kFlagDequeueOutputPending); 2086 2087 PostReplyWithError(mDequeueOutputReplyID, -EAGAIN); 2088 2089 mFlags &= ~kFlagDequeueOutputPending; 2090 mDequeueOutputReplyID = 0; 2091 break; 2092 } 2093 2094 case kWhatReleaseOutputBuffer: 2095 { 2096 sp<AReplyToken> replyID; 2097 CHECK(msg->senderAwaitsResponse(&replyID)); 2098 2099 if (!isExecuting()) { 2100 PostReplyWithError(replyID, INVALID_OPERATION); 2101 break; 2102 } else if (mFlags & kFlagStickyError) { 2103 PostReplyWithError(replyID, getStickyError()); 2104 break; 2105 } 2106 2107 status_t err = onReleaseOutputBuffer(msg); 2108 2109 PostReplyWithError(replyID, err); 2110 break; 2111 } 2112 2113 case kWhatSignalEndOfInputStream: 2114 { 2115 sp<AReplyToken> replyID; 2116 CHECK(msg->senderAwaitsResponse(&replyID)); 2117 2118 if (!isExecuting() || !mHaveInputSurface) { 2119 PostReplyWithError(replyID, INVALID_OPERATION); 2120 break; 2121 } else if (mFlags & kFlagStickyError) { 2122 PostReplyWithError(replyID, getStickyError()); 2123 break; 2124 } 2125 2126 mReplyID = replyID; 2127 mCodec->signalEndOfInputStream(); 2128 break; 2129 } 2130 2131 case kWhatGetBuffers: 2132 { 2133 sp<AReplyToken> replyID; 2134 CHECK(msg->senderAwaitsResponse(&replyID)); 2135 // Unfortunately widevine legacy source requires knowing all of the 2136 // codec input buffers, so we have to provide them even in async mode. 2137 int32_t widevine = 0; 2138 msg->findInt32("widevine", &widevine); 2139 2140 if (!isExecuting() || ((mFlags & kFlagIsAsync) && !widevine)) { 2141 PostReplyWithError(replyID, INVALID_OPERATION); 2142 break; 2143 } else if (mFlags & kFlagStickyError) { 2144 PostReplyWithError(replyID, getStickyError()); 2145 break; 2146 } 2147 2148 int32_t portIndex; 2149 CHECK(msg->findInt32("portIndex", &portIndex)); 2150 2151 Vector<sp<MediaCodecBuffer> > *dstBuffers; 2152 CHECK(msg->findPointer("buffers", (void **)&dstBuffers)); 2153 2154 dstBuffers->clear(); 2155 // If we're using input surface (either non-persistent created by 2156 // createInputSurface(), or persistent set by setInputSurface()), 2157 // give the client an empty input buffers array. 2158 if (portIndex != kPortIndexInput || !mHaveInputSurface) { 2159 const Vector<sp<MediaCodecBuffer>> &srcBuffers = mPortBufferArrays[portIndex]; 2160 2161 for (size_t i = 0; i < srcBuffers.size(); ++i) { 2162 dstBuffers->push_back(srcBuffers[i]); 2163 } 2164 } 2165 2166 (new AMessage)->postReply(replyID); 2167 break; 2168 } 2169 2170 case kWhatFlush: 2171 { 2172 sp<AReplyToken> replyID; 2173 CHECK(msg->senderAwaitsResponse(&replyID)); 2174 2175 if (!isExecuting()) { 2176 PostReplyWithError(replyID, INVALID_OPERATION); 2177 break; 2178 } else if (mFlags & kFlagStickyError) { 2179 PostReplyWithError(replyID, getStickyError()); 2180 break; 2181 } 2182 2183 mReplyID = replyID; 2184 // TODO: skip flushing if already FLUSHED 2185 setState(FLUSHING); 2186 2187 mCodec->signalFlush(); 2188 returnBuffersToCodec(); 2189 break; 2190 } 2191 2192 case kWhatGetInputFormat: 2193 case kWhatGetOutputFormat: 2194 { 2195 sp<AMessage> format = 2196 (msg->what() == kWhatGetOutputFormat ? mOutputFormat : mInputFormat); 2197 2198 sp<AReplyToken> replyID; 2199 CHECK(msg->senderAwaitsResponse(&replyID)); 2200 2201 if ((mState != CONFIGURED && mState != STARTING && 2202 mState != STARTED && mState != FLUSHING && 2203 mState != FLUSHED) 2204 || format == NULL) { 2205 PostReplyWithError(replyID, INVALID_OPERATION); 2206 break; 2207 } else if (mFlags & kFlagStickyError) { 2208 PostReplyWithError(replyID, getStickyError()); 2209 break; 2210 } 2211 2212 sp<AMessage> response = new AMessage; 2213 response->setMessage("format", format); 2214 response->postReply(replyID); 2215 break; 2216 } 2217 2218 case kWhatRequestIDRFrame: 2219 { 2220 mCodec->signalRequestIDRFrame(); 2221 break; 2222 } 2223 2224 case kWhatRequestActivityNotification: 2225 { 2226 CHECK(mActivityNotify == NULL); 2227 CHECK(msg->findMessage("notify", &mActivityNotify)); 2228 2229 postActivityNotificationIfPossible(); 2230 break; 2231 } 2232 2233 case kWhatGetName: 2234 { 2235 sp<AReplyToken> replyID; 2236 CHECK(msg->senderAwaitsResponse(&replyID)); 2237 2238 if (mComponentName.empty()) { 2239 PostReplyWithError(replyID, INVALID_OPERATION); 2240 break; 2241 } 2242 2243 sp<AMessage> response = new AMessage; 2244 response->setString("name", mComponentName.c_str()); 2245 response->postReply(replyID); 2246 break; 2247 } 2248 2249 case kWhatSetParameters: 2250 { 2251 sp<AReplyToken> replyID; 2252 CHECK(msg->senderAwaitsResponse(&replyID)); 2253 2254 sp<AMessage> params; 2255 CHECK(msg->findMessage("params", ¶ms)); 2256 2257 status_t err = onSetParameters(params); 2258 2259 PostReplyWithError(replyID, err); 2260 break; 2261 } 2262 2263 default: 2264 TRESPASS(); 2265 } 2266} 2267 2268void MediaCodec::extractCSD(const sp<AMessage> &format) { 2269 mCSD.clear(); 2270 2271 size_t i = 0; 2272 for (;;) { 2273 sp<ABuffer> csd; 2274 if (!format->findBuffer(AStringPrintf("csd-%u", i).c_str(), &csd)) { 2275 break; 2276 } 2277 if (csd->size() == 0) { 2278 ALOGW("csd-%zu size is 0", i); 2279 } 2280 2281 mCSD.push_back(csd); 2282 ++i; 2283 } 2284 2285 ALOGV("Found %zu pieces of codec specific data.", mCSD.size()); 2286} 2287 2288status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) { 2289 CHECK(!mCSD.empty()); 2290 2291 const BufferInfo *info = 2292 &mPortBuffers[kPortIndexInput].itemAt(bufferIndex); 2293 2294 sp<ABuffer> csd = *mCSD.begin(); 2295 mCSD.erase(mCSD.begin()); 2296 2297 const sp<MediaCodecBuffer> &codecInputData = info->mData; 2298 2299 if (csd->size() > codecInputData->capacity()) { 2300 return -EINVAL; 2301 } 2302 2303 memcpy(codecInputData->data(), csd->data(), csd->size()); 2304 2305 AString errorDetailMsg; 2306 2307 sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this); 2308 msg->setSize("index", bufferIndex); 2309 msg->setSize("offset", 0); 2310 msg->setSize("size", csd->size()); 2311 msg->setInt64("timeUs", 0ll); 2312 msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG); 2313 msg->setPointer("errorDetailMsg", &errorDetailMsg); 2314 2315 return onQueueInputBuffer(msg); 2316} 2317 2318void MediaCodec::setState(State newState) { 2319 if (newState == INITIALIZED || newState == UNINITIALIZED) { 2320 delete mSoftRenderer; 2321 mSoftRenderer = NULL; 2322 2323 mCrypto.clear(); 2324 handleSetSurface(NULL); 2325 2326 mInputFormat.clear(); 2327 mOutputFormat.clear(); 2328 mFlags &= ~kFlagOutputFormatChanged; 2329 mFlags &= ~kFlagOutputBuffersChanged; 2330 mFlags &= ~kFlagStickyError; 2331 mFlags &= ~kFlagIsEncoder; 2332 mFlags &= ~kFlagIsAsync; 2333 mStickyError = OK; 2334 2335 mActivityNotify.clear(); 2336 mCallback.clear(); 2337 } 2338 2339 if (newState == UNINITIALIZED) { 2340 // return any straggling buffers, e.g. if we got here on an error 2341 returnBuffersToCodec(); 2342 2343 // The component is gone, mediaserver's probably back up already 2344 // but should definitely be back up should we try to instantiate 2345 // another component.. and the cycle continues. 2346 mFlags &= ~kFlagSawMediaServerDie; 2347 } 2348 2349 mState = newState; 2350 2351 cancelPendingDequeueOperations(); 2352 2353 updateBatteryStat(); 2354} 2355 2356void MediaCodec::returnBuffersToCodec(bool isReclaim) { 2357 returnBuffersToCodecOnPort(kPortIndexInput, isReclaim); 2358 returnBuffersToCodecOnPort(kPortIndexOutput, isReclaim); 2359} 2360 2361void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex, bool isReclaim) { 2362 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 2363 Mutex::Autolock al(mBufferLock); 2364 2365 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; 2366 2367 for (size_t i = 0; i < buffers->size(); ++i) { 2368 BufferInfo *info = &buffers->editItemAt(i); 2369 2370 if (info->mNotify != NULL) { 2371 sp<AMessage> msg = info->mNotify; 2372 info->mNotify = NULL; 2373 msg->setObject("buffer", (portIndex == kPortIndexInput && mCrypto != NULL) 2374 ? info->mSecureData : info->mData); 2375 if (isReclaim && info->mOwnedByClient) { 2376 ALOGD("port %d buffer %zu still owned by client when codec is reclaimed", 2377 portIndex, i); 2378 } else { 2379 info->mOwnedByClient = false; 2380 info->mData.clear(); 2381 info->mSecureData.clear(); 2382 } 2383 2384 if (portIndex == kPortIndexInput) { 2385 /* no error, just returning buffers */ 2386 msg->setInt32("err", OK); 2387 } 2388 msg->post(); 2389 } 2390 } 2391 2392 mAvailPortBuffers[portIndex].clear(); 2393} 2394 2395size_t MediaCodec::updateBuffers( 2396 int32_t portIndex, const sp<AMessage> &msg) { 2397 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 2398 2399 uint32_t bufferID; 2400 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID)); 2401 sp<RefBase> obj; 2402 CHECK(msg->findObject("buffer", &obj)); 2403 sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get()); 2404 2405 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; 2406 2407 for (size_t i = 0; i < buffers->size(); ++i) { 2408 BufferInfo *info = &buffers->editItemAt(i); 2409 2410 if (info->mBufferID == bufferID) { 2411 CHECK(info->mNotify == NULL); 2412 CHECK(msg->findMessage("reply", &info->mNotify)); 2413 2414 if (portIndex == kPortIndexInput && mCrypto != NULL) { 2415 info->mSecureData = buffer; 2416 info->mData = mPortBufferArrays[portIndex][i]; 2417 } else { 2418 info->mData = buffer; 2419 } 2420 mAvailPortBuffers[portIndex].push_back(i); 2421 2422 return i; 2423 } 2424 } 2425 2426 TRESPASS(); 2427 2428 return 0; 2429} 2430 2431status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) { 2432 size_t index; 2433 size_t offset; 2434 size_t size; 2435 int64_t timeUs; 2436 uint32_t flags; 2437 CHECK(msg->findSize("index", &index)); 2438 CHECK(msg->findSize("offset", &offset)); 2439 CHECK(msg->findInt64("timeUs", &timeUs)); 2440 CHECK(msg->findInt32("flags", (int32_t *)&flags)); 2441 2442 const CryptoPlugin::SubSample *subSamples; 2443 size_t numSubSamples; 2444 const uint8_t *key; 2445 const uint8_t *iv; 2446 CryptoPlugin::Mode mode = CryptoPlugin::kMode_Unencrypted; 2447 2448 // We allow the simpler queueInputBuffer API to be used even in 2449 // secure mode, by fabricating a single unencrypted subSample. 2450 CryptoPlugin::SubSample ss; 2451 CryptoPlugin::Pattern pattern; 2452 2453 if (msg->findSize("size", &size)) { 2454 if (mCrypto != NULL) { 2455 ss.mNumBytesOfClearData = size; 2456 ss.mNumBytesOfEncryptedData = 0; 2457 2458 subSamples = &ss; 2459 numSubSamples = 1; 2460 key = NULL; 2461 iv = NULL; 2462 pattern.mEncryptBlocks = 0; 2463 pattern.mSkipBlocks = 0; 2464 } 2465 } else { 2466 if (mCrypto == NULL) { 2467 return -EINVAL; 2468 } 2469 2470 CHECK(msg->findPointer("subSamples", (void **)&subSamples)); 2471 CHECK(msg->findSize("numSubSamples", &numSubSamples)); 2472 CHECK(msg->findPointer("key", (void **)&key)); 2473 CHECK(msg->findPointer("iv", (void **)&iv)); 2474 CHECK(msg->findInt32("encryptBlocks", (int32_t *)&pattern.mEncryptBlocks)); 2475 CHECK(msg->findInt32("skipBlocks", (int32_t *)&pattern.mSkipBlocks)); 2476 2477 int32_t tmp; 2478 CHECK(msg->findInt32("mode", &tmp)); 2479 2480 mode = (CryptoPlugin::Mode)tmp; 2481 2482 size = 0; 2483 for (size_t i = 0; i < numSubSamples; ++i) { 2484 size += subSamples[i].mNumBytesOfClearData; 2485 size += subSamples[i].mNumBytesOfEncryptedData; 2486 } 2487 } 2488 2489 if (index >= mPortBuffers[kPortIndexInput].size()) { 2490 return -ERANGE; 2491 } 2492 2493 BufferInfo *info = &mPortBuffers[kPortIndexInput].editItemAt(index); 2494 2495 if (info->mNotify == NULL || !info->mOwnedByClient) { 2496 return -EACCES; 2497 } 2498 2499 if (offset + size > info->mData->capacity()) { 2500 return -EINVAL; 2501 } 2502 2503 sp<AMessage> reply = info->mNotify; 2504 info->mData->setRange(offset, size); 2505 2506 sp<MediaCodecBuffer> buffer = info->mData; 2507 if (mCrypto != NULL) { 2508 AString *errorDetailMsg; 2509 CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg)); 2510 2511 void *dst_pointer = nullptr; 2512 ICrypto::DestinationType dst_type = ICrypto::kDestinationTypeOpaqueHandle; 2513 2514 if ((mFlags & kFlagIsSecure) == 0) { 2515 dst_pointer = info->mSecureData->base(); 2516 dst_type = ICrypto::kDestinationTypeVmPointer; 2517 } else { 2518 sp<SecureBuffer> secureData = static_cast<SecureBuffer *>(info->mSecureData.get()); 2519 dst_pointer = secureData->getDestinationPointer(); 2520 dst_type = secureData->getDestinationType(); 2521 } 2522 2523 ssize_t result = mCrypto->decrypt( 2524 dst_type, 2525 key, 2526 iv, 2527 mode, 2528 pattern, 2529 info->mSharedEncryptedBuffer, 2530 offset, 2531 subSamples, 2532 numSubSamples, 2533 dst_pointer, 2534 errorDetailMsg); 2535 2536 if (result < 0) { 2537 return result; 2538 } 2539 2540 info->mSecureData->setRange(0, result); 2541 buffer = info->mSecureData; 2542 } 2543 buffer->meta()->setInt64("timeUs", timeUs); 2544 2545 if (flags & BUFFER_FLAG_EOS) { 2546 buffer->meta()->setInt32("eos", true); 2547 } 2548 2549 if (flags & BUFFER_FLAG_CODECCONFIG) { 2550 buffer->meta()->setInt32("csd", true); 2551 } 2552 2553 // synchronization boundary for getBufferAndFormat 2554 { 2555 Mutex::Autolock al(mBufferLock); 2556 info->mOwnedByClient = false; 2557 } 2558 info->mData.clear(); 2559 info->mSecureData.clear(); 2560 reply->setObject("buffer", buffer); 2561 reply->post(); 2562 2563 info->mNotify = NULL; 2564 2565 return OK; 2566} 2567 2568//static 2569size_t MediaCodec::CreateFramesRenderedMessage( 2570 const std::list<FrameRenderTracker::Info> &done, sp<AMessage> &msg) { 2571 size_t index = 0; 2572 2573 for (std::list<FrameRenderTracker::Info>::const_iterator it = done.cbegin(); 2574 it != done.cend(); ++it) { 2575 if (it->getRenderTimeNs() < 0) { 2576 continue; // dropped frame from tracking 2577 } 2578 msg->setInt64(AStringPrintf("%zu-media-time-us", index).c_str(), it->getMediaTimeUs()); 2579 msg->setInt64(AStringPrintf("%zu-system-nano", index).c_str(), it->getRenderTimeNs()); 2580 ++index; 2581 } 2582 return index; 2583} 2584 2585status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) { 2586 size_t index; 2587 CHECK(msg->findSize("index", &index)); 2588 2589 int32_t render; 2590 if (!msg->findInt32("render", &render)) { 2591 render = 0; 2592 } 2593 2594 if (!isExecuting()) { 2595 return -EINVAL; 2596 } 2597 2598 if (index >= mPortBuffers[kPortIndexOutput].size()) { 2599 return -ERANGE; 2600 } 2601 2602 BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index); 2603 2604 if (info->mNotify == NULL || !info->mOwnedByClient) { 2605 return -EACCES; 2606 } 2607 2608 // synchronization boundary for getBufferAndFormat 2609 { 2610 Mutex::Autolock al(mBufferLock); 2611 info->mOwnedByClient = false; 2612 } 2613 2614 if (render && info->mData != NULL && info->mData->size() != 0) { 2615 info->mNotify->setInt32("render", true); 2616 2617 int64_t mediaTimeUs = -1; 2618 info->mData->meta()->findInt64("timeUs", &mediaTimeUs); 2619 2620 int64_t renderTimeNs = 0; 2621 if (!msg->findInt64("timestampNs", &renderTimeNs)) { 2622 // use media timestamp if client did not request a specific render timestamp 2623 ALOGV("using buffer PTS of %lld", (long long)mediaTimeUs); 2624 renderTimeNs = mediaTimeUs * 1000; 2625 } 2626 info->mNotify->setInt64("timestampNs", renderTimeNs); 2627 2628 if (mSoftRenderer != NULL) { 2629 std::list<FrameRenderTracker::Info> doneFrames = mSoftRenderer->render( 2630 info->mData->data(), info->mData->size(), 2631 mediaTimeUs, renderTimeNs, NULL, info->mData->format()); 2632 2633 // if we are running, notify rendered frames 2634 if (!doneFrames.empty() && mState == STARTED && mOnFrameRenderedNotification != NULL) { 2635 sp<AMessage> notify = mOnFrameRenderedNotification->dup(); 2636 sp<AMessage> data = new AMessage; 2637 if (CreateFramesRenderedMessage(doneFrames, data)) { 2638 notify->setMessage("data", data); 2639 notify->post(); 2640 } 2641 } 2642 } 2643 } 2644 2645 info->mNotify->setObject("buffer", info->mData); 2646 info->mData.clear(); 2647 info->mNotify->post(); 2648 info->mNotify.clear(); 2649 2650 return OK; 2651} 2652 2653ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) { 2654 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 2655 2656 List<size_t> *availBuffers = &mAvailPortBuffers[portIndex]; 2657 2658 if (availBuffers->empty()) { 2659 return -EAGAIN; 2660 } 2661 2662 size_t index = *availBuffers->begin(); 2663 availBuffers->erase(availBuffers->begin()); 2664 2665 BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index); 2666 CHECK(!info->mOwnedByClient); 2667 { 2668 Mutex::Autolock al(mBufferLock); 2669 info->mOwnedByClient = true; 2670 2671 // set image-data 2672 if (info->mData->format() != NULL) { 2673 sp<ABuffer> imageData; 2674 if (info->mData->format()->findBuffer("image-data", &imageData)) { 2675 info->mData->meta()->setBuffer("image-data", imageData); 2676 } 2677 int32_t left, top, right, bottom; 2678 if (info->mData->format()->findRect("crop", &left, &top, &right, &bottom)) { 2679 info->mData->meta()->setRect("crop-rect", left, top, right, bottom); 2680 } 2681 } 2682 } 2683 2684 return index; 2685} 2686 2687status_t MediaCodec::connectToSurface(const sp<Surface> &surface) { 2688 status_t err = OK; 2689 if (surface != NULL) { 2690 uint64_t oldId, newId; 2691 if (mSurface != NULL 2692 && surface->getUniqueId(&newId) == NO_ERROR 2693 && mSurface->getUniqueId(&oldId) == NO_ERROR 2694 && newId == oldId) { 2695 ALOGI("[%s] connecting to the same surface. Nothing to do.", mComponentName.c_str()); 2696 return ALREADY_EXISTS; 2697 } 2698 2699 err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA); 2700 if (err == OK) { 2701 // Require a fresh set of buffers after each connect by using a unique generation 2702 // number. Rely on the fact that max supported process id by Linux is 2^22. 2703 // PID is never 0 so we don't have to worry that we use the default generation of 0. 2704 // TODO: come up with a unique scheme if other producers also set the generation number. 2705 static uint32_t mSurfaceGeneration = 0; 2706 uint32_t generation = (getpid() << 10) | (++mSurfaceGeneration & ((1 << 10) - 1)); 2707 surface->setGenerationNumber(generation); 2708 ALOGI("[%s] setting surface generation to %u", mComponentName.c_str(), generation); 2709 2710 // HACK: clear any free buffers. Remove when connect will automatically do this. 2711 // This is needed as the consumer may be holding onto stale frames that it can reattach 2712 // to this surface after disconnect/connect, and those free frames would inherit the new 2713 // generation number. Disconnecting after setting a unique generation prevents this. 2714 native_window_api_disconnect(surface.get(), NATIVE_WINDOW_API_MEDIA); 2715 err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA); 2716 } 2717 2718 if (err != OK) { 2719 ALOGE("native_window_api_connect returned an error: %s (%d)", strerror(-err), err); 2720 } 2721 } 2722 // do not return ALREADY_EXISTS unless surfaces are the same 2723 return err == ALREADY_EXISTS ? BAD_VALUE : err; 2724} 2725 2726status_t MediaCodec::disconnectFromSurface() { 2727 status_t err = OK; 2728 if (mSurface != NULL) { 2729 // Resetting generation is not technically needed, but there is no need to keep it either 2730 mSurface->setGenerationNumber(0); 2731 err = native_window_api_disconnect(mSurface.get(), NATIVE_WINDOW_API_MEDIA); 2732 if (err != OK) { 2733 ALOGW("native_window_api_disconnect returned an error: %s (%d)", strerror(-err), err); 2734 } 2735 // assume disconnected even on error 2736 mSurface.clear(); 2737 } 2738 return err; 2739} 2740 2741status_t MediaCodec::handleSetSurface(const sp<Surface> &surface) { 2742 status_t err = OK; 2743 if (mSurface != NULL) { 2744 (void)disconnectFromSurface(); 2745 } 2746 if (surface != NULL) { 2747 err = connectToSurface(surface); 2748 if (err == OK) { 2749 mSurface = surface; 2750 } 2751 } 2752 return err; 2753} 2754 2755void MediaCodec::onInputBufferAvailable() { 2756 int32_t index; 2757 while ((index = dequeuePortBuffer(kPortIndexInput)) >= 0) { 2758 sp<AMessage> msg = mCallback->dup(); 2759 msg->setInt32("callbackID", CB_INPUT_AVAILABLE); 2760 msg->setInt32("index", index); 2761 msg->post(); 2762 } 2763} 2764 2765void MediaCodec::onOutputBufferAvailable() { 2766 int32_t index; 2767 while ((index = dequeuePortBuffer(kPortIndexOutput)) >= 0) { 2768 const sp<MediaCodecBuffer> &buffer = 2769 mPortBuffers[kPortIndexOutput].itemAt(index).mData; 2770 sp<AMessage> msg = mCallback->dup(); 2771 msg->setInt32("callbackID", CB_OUTPUT_AVAILABLE); 2772 msg->setInt32("index", index); 2773 msg->setSize("offset", buffer->offset()); 2774 msg->setSize("size", buffer->size()); 2775 2776 int64_t timeUs; 2777 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 2778 2779 msg->setInt64("timeUs", timeUs); 2780 2781 int32_t omxFlags; 2782 CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags)); 2783 2784 uint32_t flags = 0; 2785 if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) { 2786 flags |= BUFFER_FLAG_SYNCFRAME; 2787 } 2788 if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) { 2789 flags |= BUFFER_FLAG_CODECCONFIG; 2790 } 2791 if (omxFlags & OMX_BUFFERFLAG_EOS) { 2792 flags |= BUFFER_FLAG_EOS; 2793 } 2794 2795 msg->setInt32("flags", flags); 2796 2797 msg->post(); 2798 } 2799} 2800 2801void MediaCodec::onError(status_t err, int32_t actionCode, const char *detail) { 2802 if (mCallback != NULL) { 2803 sp<AMessage> msg = mCallback->dup(); 2804 msg->setInt32("callbackID", CB_ERROR); 2805 msg->setInt32("err", err); 2806 msg->setInt32("actionCode", actionCode); 2807 2808 if (detail != NULL) { 2809 msg->setString("detail", detail); 2810 } 2811 2812 msg->post(); 2813 } 2814} 2815 2816void MediaCodec::onOutputFormatChanged() { 2817 if (mCallback != NULL) { 2818 sp<AMessage> msg = mCallback->dup(); 2819 msg->setInt32("callbackID", CB_OUTPUT_FORMAT_CHANGED); 2820 msg->setMessage("format", mOutputFormat); 2821 msg->post(); 2822 } 2823} 2824 2825 2826void MediaCodec::postActivityNotificationIfPossible() { 2827 if (mActivityNotify == NULL) { 2828 return; 2829 } 2830 2831 bool isErrorOrOutputChanged = 2832 (mFlags & (kFlagStickyError 2833 | kFlagOutputBuffersChanged 2834 | kFlagOutputFormatChanged)); 2835 2836 if (isErrorOrOutputChanged 2837 || !mAvailPortBuffers[kPortIndexInput].empty() 2838 || !mAvailPortBuffers[kPortIndexOutput].empty()) { 2839 mActivityNotify->setInt32("input-buffers", 2840 mAvailPortBuffers[kPortIndexInput].size()); 2841 2842 if (isErrorOrOutputChanged) { 2843 // we want consumer to dequeue as many times as it can 2844 mActivityNotify->setInt32("output-buffers", INT32_MAX); 2845 } else { 2846 mActivityNotify->setInt32("output-buffers", 2847 mAvailPortBuffers[kPortIndexOutput].size()); 2848 } 2849 mActivityNotify->post(); 2850 mActivityNotify.clear(); 2851 } 2852} 2853 2854status_t MediaCodec::setParameters(const sp<AMessage> ¶ms) { 2855 sp<AMessage> msg = new AMessage(kWhatSetParameters, this); 2856 msg->setMessage("params", params); 2857 2858 sp<AMessage> response; 2859 return PostAndAwaitResponse(msg, &response); 2860} 2861 2862status_t MediaCodec::onSetParameters(const sp<AMessage> ¶ms) { 2863 mCodec->signalSetParameters(params); 2864 2865 return OK; 2866} 2867 2868status_t MediaCodec::amendOutputFormatWithCodecSpecificData( 2869 const sp<MediaCodecBuffer> &buffer) { 2870 AString mime; 2871 CHECK(mOutputFormat->findString("mime", &mime)); 2872 2873 if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) { 2874 // Codec specific data should be SPS and PPS in a single buffer, 2875 // each prefixed by a startcode (0x00 0x00 0x00 0x01). 2876 // We separate the two and put them into the output format 2877 // under the keys "csd-0" and "csd-1". 2878 2879 unsigned csdIndex = 0; 2880 2881 const uint8_t *data = buffer->data(); 2882 size_t size = buffer->size(); 2883 2884 const uint8_t *nalStart; 2885 size_t nalSize; 2886 while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) { 2887 sp<ABuffer> csd = new ABuffer(nalSize + 4); 2888 memcpy(csd->data(), "\x00\x00\x00\x01", 4); 2889 memcpy(csd->data() + 4, nalStart, nalSize); 2890 2891 mOutputFormat->setBuffer( 2892 AStringPrintf("csd-%u", csdIndex).c_str(), csd); 2893 2894 ++csdIndex; 2895 } 2896 2897 if (csdIndex != 2) { 2898 return ERROR_MALFORMED; 2899 } 2900 } else { 2901 // For everything else we just stash the codec specific data into 2902 // the output format as a single piece of csd under "csd-0". 2903 sp<ABuffer> csd = new ABuffer(buffer->size()); 2904 memcpy(csd->data(), buffer->data(), buffer->size()); 2905 csd->setRange(0, buffer->size()); 2906 mOutputFormat->setBuffer("csd-0", csd); 2907 } 2908 2909 return OK; 2910} 2911 2912void MediaCodec::updateBatteryStat() { 2913 if (!mIsVideo) { 2914 return; 2915 } 2916 2917 if (mState == CONFIGURED && !mBatteryStatNotified) { 2918 BatteryNotifier::getInstance().noteStartVideo(mUid); 2919 mBatteryStatNotified = true; 2920 } else if (mState == UNINITIALIZED && mBatteryStatNotified) { 2921 BatteryNotifier::getInstance().noteStopVideo(mUid); 2922 mBatteryStatNotified = false; 2923 } 2924} 2925 2926} // namespace android 2927