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