MediaCodec.cpp revision 29b7dcf6d3cdb97103467dc8106151c6260c239a
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::getInputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const { 847 sp<AMessage> msg = new AMessage(kWhatGetBuffers, this); 848 msg->setInt32("portIndex", kPortIndexInput); 849 msg->setPointer("buffers", buffers); 850 851 sp<AMessage> response; 852 return PostAndAwaitResponse(msg, &response); 853} 854 855status_t MediaCodec::getOutputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const { 856 sp<AMessage> msg = new AMessage(kWhatGetBuffers, this); 857 msg->setInt32("portIndex", kPortIndexOutput); 858 msg->setPointer("buffers", buffers); 859 860 sp<AMessage> response; 861 return PostAndAwaitResponse(msg, &response); 862} 863 864status_t MediaCodec::getOutputBuffer(size_t index, sp<MediaCodecBuffer> *buffer) { 865 sp<AMessage> format; 866 return getBufferAndFormat(kPortIndexOutput, index, buffer, &format); 867} 868 869status_t MediaCodec::getOutputFormat(size_t index, sp<AMessage> *format) { 870 sp<MediaCodecBuffer> buffer; 871 return getBufferAndFormat(kPortIndexOutput, index, &buffer, format); 872} 873 874status_t MediaCodec::getInputBuffer(size_t index, sp<MediaCodecBuffer> *buffer) { 875 sp<AMessage> format; 876 return getBufferAndFormat(kPortIndexInput, index, buffer, &format); 877} 878 879bool MediaCodec::isExecuting() const { 880 return mState == STARTED || mState == FLUSHED; 881} 882 883status_t MediaCodec::getBufferAndFormat( 884 size_t portIndex, size_t index, 885 sp<MediaCodecBuffer> *buffer, sp<AMessage> *format) { 886 // use mutex instead of a context switch 887 if (mReleasedByResourceManager) { 888 ALOGE("getBufferAndFormat - resource already released"); 889 return DEAD_OBJECT; 890 } 891 892 if (buffer == NULL) { 893 ALOGE("getBufferAndFormat - null MediaCodecBuffer"); 894 return INVALID_OPERATION; 895 } 896 897 if (format == NULL) { 898 ALOGE("getBufferAndFormat - null AMessage"); 899 return INVALID_OPERATION; 900 } 901 902 buffer->clear(); 903 format->clear(); 904 905 if (!isExecuting()) { 906 ALOGE("getBufferAndFormat - not executing"); 907 return INVALID_OPERATION; 908 } 909 910 // we do not want mPortBuffers to change during this section 911 // we also don't want mOwnedByClient to change during this 912 Mutex::Autolock al(mBufferLock); 913 914 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; 915 if (index >= buffers->size()) { 916 ALOGE("getBufferAndFormat - trying to get buffer with " 917 "bad index (index=%zu buffer_size=%zu)", index, buffers->size()); 918 return INVALID_OPERATION; 919 } 920 921 const BufferInfo &info = buffers->itemAt(index); 922 if (!info.mOwnedByClient) { 923 ALOGE("getBufferAndFormat - invalid operation " 924 "(the index %zu is not owned by client)", index); 925 return INVALID_OPERATION; 926 } 927 928 *buffer = info.mData; 929 *format = info.mData->format(); 930 931 return OK; 932} 933 934status_t MediaCodec::flush() { 935 sp<AMessage> msg = new AMessage(kWhatFlush, this); 936 937 sp<AMessage> response; 938 return PostAndAwaitResponse(msg, &response); 939} 940 941status_t MediaCodec::requestIDRFrame() { 942 (new AMessage(kWhatRequestIDRFrame, this))->post(); 943 944 return OK; 945} 946 947void MediaCodec::requestActivityNotification(const sp<AMessage> ¬ify) { 948 sp<AMessage> msg = new AMessage(kWhatRequestActivityNotification, this); 949 msg->setMessage("notify", notify); 950 msg->post(); 951} 952 953//////////////////////////////////////////////////////////////////////////////// 954 955void MediaCodec::cancelPendingDequeueOperations() { 956 if (mFlags & kFlagDequeueInputPending) { 957 PostReplyWithError(mDequeueInputReplyID, INVALID_OPERATION); 958 959 ++mDequeueInputTimeoutGeneration; 960 mDequeueInputReplyID = 0; 961 mFlags &= ~kFlagDequeueInputPending; 962 } 963 964 if (mFlags & kFlagDequeueOutputPending) { 965 PostReplyWithError(mDequeueOutputReplyID, INVALID_OPERATION); 966 967 ++mDequeueOutputTimeoutGeneration; 968 mDequeueOutputReplyID = 0; 969 mFlags &= ~kFlagDequeueOutputPending; 970 } 971} 972 973bool MediaCodec::handleDequeueInputBuffer(const sp<AReplyToken> &replyID, bool newRequest) { 974 if (!isExecuting() || (mFlags & kFlagIsAsync) 975 || (newRequest && (mFlags & kFlagDequeueInputPending))) { 976 PostReplyWithError(replyID, INVALID_OPERATION); 977 return true; 978 } else if (mFlags & kFlagStickyError) { 979 PostReplyWithError(replyID, getStickyError()); 980 return true; 981 } 982 983 ssize_t index = dequeuePortBuffer(kPortIndexInput); 984 985 if (index < 0) { 986 CHECK_EQ(index, -EAGAIN); 987 return false; 988 } 989 990 sp<AMessage> response = new AMessage; 991 response->setSize("index", index); 992 response->postReply(replyID); 993 994 return true; 995} 996 997bool MediaCodec::handleDequeueOutputBuffer(const sp<AReplyToken> &replyID, bool newRequest) { 998 if (!isExecuting() || (mFlags & kFlagIsAsync) 999 || (newRequest && (mFlags & kFlagDequeueOutputPending))) { 1000 PostReplyWithError(replyID, INVALID_OPERATION); 1001 } else if (mFlags & kFlagStickyError) { 1002 PostReplyWithError(replyID, getStickyError()); 1003 } else if (mFlags & kFlagOutputBuffersChanged) { 1004 PostReplyWithError(replyID, INFO_OUTPUT_BUFFERS_CHANGED); 1005 mFlags &= ~kFlagOutputBuffersChanged; 1006 } else if (mFlags & kFlagOutputFormatChanged) { 1007 PostReplyWithError(replyID, INFO_FORMAT_CHANGED); 1008 mFlags &= ~kFlagOutputFormatChanged; 1009 } else { 1010 sp<AMessage> response = new AMessage; 1011 ssize_t index = dequeuePortBuffer(kPortIndexOutput); 1012 1013 if (index < 0) { 1014 CHECK_EQ(index, -EAGAIN); 1015 return false; 1016 } 1017 1018 const sp<MediaCodecBuffer> &buffer = 1019 mPortBuffers[kPortIndexOutput].itemAt(index).mData; 1020 1021 response->setSize("index", index); 1022 response->setSize("offset", buffer->offset()); 1023 response->setSize("size", buffer->size()); 1024 1025 int64_t timeUs; 1026 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 1027 1028 response->setInt64("timeUs", timeUs); 1029 1030 int32_t omxFlags; 1031 CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags)); 1032 1033 uint32_t flags = 0; 1034 if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) { 1035 flags |= BUFFER_FLAG_SYNCFRAME; 1036 } 1037 if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) { 1038 flags |= BUFFER_FLAG_CODECCONFIG; 1039 } 1040 if (omxFlags & OMX_BUFFERFLAG_EOS) { 1041 flags |= BUFFER_FLAG_EOS; 1042 } 1043 1044 response->setInt32("flags", flags); 1045 response->postReply(replyID); 1046 } 1047 1048 return true; 1049} 1050 1051void MediaCodec::onMessageReceived(const sp<AMessage> &msg) { 1052 switch (msg->what()) { 1053 case kWhatCodecNotify: 1054 { 1055 int32_t what; 1056 CHECK(msg->findInt32("what", &what)); 1057 1058 switch (what) { 1059 case CodecBase::kWhatError: 1060 { 1061 int32_t err, actionCode; 1062 CHECK(msg->findInt32("err", &err)); 1063 CHECK(msg->findInt32("actionCode", &actionCode)); 1064 1065 ALOGE("Codec reported err %#x, actionCode %d, while in state %d", 1066 err, actionCode, mState); 1067 if (err == DEAD_OBJECT) { 1068 mFlags |= kFlagSawMediaServerDie; 1069 mFlags &= ~kFlagIsComponentAllocated; 1070 } 1071 1072 bool sendErrorResponse = true; 1073 1074 switch (mState) { 1075 case INITIALIZING: 1076 { 1077 setState(UNINITIALIZED); 1078 break; 1079 } 1080 1081 case CONFIGURING: 1082 { 1083 setState(actionCode == ACTION_CODE_FATAL ? 1084 UNINITIALIZED : INITIALIZED); 1085 break; 1086 } 1087 1088 case STARTING: 1089 { 1090 setState(actionCode == ACTION_CODE_FATAL ? 1091 UNINITIALIZED : CONFIGURED); 1092 break; 1093 } 1094 1095 case RELEASING: 1096 { 1097 // Ignore the error, assuming we'll still get 1098 // the shutdown complete notification. If we 1099 // don't, we'll timeout and force release. 1100 sendErrorResponse = false; 1101 } 1102 // fall-thru 1103 case STOPPING: 1104 { 1105 if (mFlags & kFlagSawMediaServerDie) { 1106 // MediaServer died, there definitely won't 1107 // be a shutdown complete notification after 1108 // all. 1109 1110 // note that we're directly going from 1111 // STOPPING->UNINITIALIZED, instead of the 1112 // usual STOPPING->INITIALIZED state. 1113 setState(UNINITIALIZED); 1114 if (mState == RELEASING) { 1115 mComponentName.clear(); 1116 } 1117 (new AMessage)->postReply(mReplyID); 1118 sendErrorResponse = false; 1119 } 1120 break; 1121 } 1122 1123 case FLUSHING: 1124 { 1125 if (actionCode == ACTION_CODE_FATAL) { 1126 setState(UNINITIALIZED); 1127 } else { 1128 setState( 1129 (mFlags & kFlagIsAsync) ? FLUSHED : STARTED); 1130 } 1131 break; 1132 } 1133 1134 case FLUSHED: 1135 case STARTED: 1136 { 1137 sendErrorResponse = false; 1138 1139 setStickyError(err); 1140 postActivityNotificationIfPossible(); 1141 1142 cancelPendingDequeueOperations(); 1143 1144 if (mFlags & kFlagIsAsync) { 1145 onError(err, actionCode); 1146 } 1147 switch (actionCode) { 1148 case ACTION_CODE_TRANSIENT: 1149 break; 1150 case ACTION_CODE_RECOVERABLE: 1151 setState(INITIALIZED); 1152 break; 1153 default: 1154 setState(UNINITIALIZED); 1155 break; 1156 } 1157 break; 1158 } 1159 1160 default: 1161 { 1162 sendErrorResponse = false; 1163 1164 setStickyError(err); 1165 postActivityNotificationIfPossible(); 1166 1167 // actionCode in an uninitialized state is always fatal. 1168 if (mState == UNINITIALIZED) { 1169 actionCode = ACTION_CODE_FATAL; 1170 } 1171 if (mFlags & kFlagIsAsync) { 1172 onError(err, actionCode); 1173 } 1174 switch (actionCode) { 1175 case ACTION_CODE_TRANSIENT: 1176 break; 1177 case ACTION_CODE_RECOVERABLE: 1178 setState(INITIALIZED); 1179 break; 1180 default: 1181 setState(UNINITIALIZED); 1182 break; 1183 } 1184 break; 1185 } 1186 } 1187 1188 if (sendErrorResponse) { 1189 PostReplyWithError(mReplyID, err); 1190 } 1191 break; 1192 } 1193 1194 case CodecBase::kWhatComponentAllocated: 1195 { 1196 CHECK_EQ(mState, INITIALIZING); 1197 setState(INITIALIZED); 1198 mFlags |= kFlagIsComponentAllocated; 1199 1200 CHECK(msg->findString("componentName", &mComponentName)); 1201 1202 if (mComponentName.startsWith("OMX.google.")) { 1203 mFlags |= kFlagUsesSoftwareRenderer; 1204 } else { 1205 mFlags &= ~kFlagUsesSoftwareRenderer; 1206 } 1207 1208 MediaResource::Type resourceType; 1209 if (mComponentName.endsWith(".secure")) { 1210 mFlags |= kFlagIsSecure; 1211 resourceType = MediaResource::kSecureCodec; 1212 } else { 1213 mFlags &= ~kFlagIsSecure; 1214 resourceType = MediaResource::kNonSecureCodec; 1215 } 1216 1217 if (mIsVideo) { 1218 // audio codec is currently ignored. 1219 addResource(resourceType, MediaResource::kVideoCodec, 1); 1220 } 1221 1222 (new AMessage)->postReply(mReplyID); 1223 break; 1224 } 1225 1226 case CodecBase::kWhatComponentConfigured: 1227 { 1228 if (mState == UNINITIALIZED || mState == INITIALIZED) { 1229 // In case a kWhatError message came in and replied with error, 1230 // we log a warning and ignore. 1231 ALOGW("configure interrupted by error, current state %d", mState); 1232 break; 1233 } 1234 CHECK_EQ(mState, CONFIGURING); 1235 1236 // reset input surface flag 1237 mHaveInputSurface = false; 1238 1239 CHECK(msg->findMessage("input-format", &mInputFormat)); 1240 CHECK(msg->findMessage("output-format", &mOutputFormat)); 1241 ALOGV("[%s] configured as input format: %s, output format: %s", 1242 mComponentName.c_str(), 1243 mInputFormat->debugString(4).c_str(), 1244 mOutputFormat->debugString(4).c_str()); 1245 int32_t usingSwRenderer; 1246 if (mOutputFormat->findInt32("using-sw-renderer", &usingSwRenderer) 1247 && usingSwRenderer) { 1248 mFlags |= kFlagUsesSoftwareRenderer; 1249 } 1250 setState(CONFIGURED); 1251 (new AMessage)->postReply(mReplyID); 1252 break; 1253 } 1254 1255 case CodecBase::kWhatInputSurfaceCreated: 1256 { 1257 // response to initiateCreateInputSurface() 1258 status_t err = NO_ERROR; 1259 sp<AMessage> response = new AMessage; 1260 if (!msg->findInt32("err", &err)) { 1261 sp<RefBase> obj; 1262 msg->findObject("input-surface", &obj); 1263 CHECK(msg->findMessage("input-format", &mInputFormat)); 1264 CHECK(msg->findMessage("output-format", &mOutputFormat)); 1265 ALOGV("[%s] input surface created as input format: %s, output format: %s", 1266 mComponentName.c_str(), 1267 mInputFormat->debugString(4).c_str(), 1268 mOutputFormat->debugString(4).c_str()); 1269 CHECK(obj != NULL); 1270 response->setObject("input-surface", obj); 1271 mHaveInputSurface = true; 1272 } else { 1273 response->setInt32("err", err); 1274 } 1275 response->postReply(mReplyID); 1276 break; 1277 } 1278 1279 case CodecBase::kWhatInputSurfaceAccepted: 1280 { 1281 // response to initiateSetInputSurface() 1282 status_t err = NO_ERROR; 1283 sp<AMessage> response = new AMessage(); 1284 if (!msg->findInt32("err", &err)) { 1285 CHECK(msg->findMessage("input-format", &mInputFormat)); 1286 CHECK(msg->findMessage("output-format", &mOutputFormat)); 1287 mHaveInputSurface = true; 1288 } else { 1289 response->setInt32("err", err); 1290 } 1291 response->postReply(mReplyID); 1292 break; 1293 } 1294 1295 case CodecBase::kWhatSignaledInputEOS: 1296 { 1297 // response to signalEndOfInputStream() 1298 sp<AMessage> response = new AMessage; 1299 status_t err; 1300 if (msg->findInt32("err", &err)) { 1301 response->setInt32("err", err); 1302 } 1303 response->postReply(mReplyID); 1304 break; 1305 } 1306 1307 1308 case CodecBase::kWhatBuffersAllocated: 1309 { 1310 Mutex::Autolock al(mBufferLock); 1311 int32_t portIndex; 1312 CHECK(msg->findInt32("portIndex", &portIndex)); 1313 1314 ALOGV("%s buffers allocated", 1315 portIndex == kPortIndexInput ? "input" : "output"); 1316 1317 CHECK(portIndex == kPortIndexInput 1318 || portIndex == kPortIndexOutput); 1319 1320 mPortBuffers[portIndex].clear(); 1321 mPortBufferArrays[portIndex].clear(); 1322 1323 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; 1324 1325 sp<RefBase> obj; 1326 CHECK(msg->findObject("portDesc", &obj)); 1327 1328 sp<CodecBase::PortDescription> portDesc = 1329 static_cast<CodecBase::PortDescription *>(obj.get()); 1330 1331 size_t numBuffers = portDesc->countBuffers(); 1332 1333 size_t totalSize = 0; 1334 for (size_t i = 0; i < numBuffers; ++i) { 1335 if (portIndex == kPortIndexInput && mCrypto != NULL) { 1336 totalSize += portDesc->bufferAt(i)->capacity(); 1337 } 1338 } 1339 1340 if (totalSize) { 1341 mDealer = new MemoryDealer(totalSize, "MediaCodec"); 1342 } 1343 1344 for (size_t i = 0; i < numBuffers; ++i) { 1345 BufferInfo info; 1346 info.mBufferID = portDesc->bufferIDAt(i); 1347 info.mOwnedByClient = false; 1348 sp<MediaCodecBuffer> buffer = portDesc->bufferAt(i); 1349 if (portIndex == kPortIndexInput && mCrypto != NULL) { 1350 info.mSharedEncryptedBuffer = mDealer->allocate(buffer->capacity()); 1351 buffer = new SharedMemoryBuffer( 1352 mInputFormat, info.mSharedEncryptedBuffer); 1353 } 1354 buffers->push_back(info); 1355 mPortBufferArrays[portIndex].push_back(buffer); 1356 } 1357 1358 if (portIndex == kPortIndexOutput) { 1359 if (mState == STARTING) { 1360 // We're always allocating output buffers after 1361 // allocating input buffers, so this is a good 1362 // indication that now all buffers are allocated. 1363 if (mIsVideo) { 1364 addResource( 1365 MediaResource::kGraphicMemory, 1366 MediaResource::kUnspecifiedSubType, 1367 getGraphicBufferSize()); 1368 } 1369 setState(STARTED); 1370 (new AMessage)->postReply(mReplyID); 1371 } else { 1372 mFlags |= kFlagOutputBuffersChanged; 1373 postActivityNotificationIfPossible(); 1374 } 1375 } 1376 break; 1377 } 1378 1379 case CodecBase::kWhatOutputFramesRendered: 1380 { 1381 // ignore these in all states except running, and check that we have a 1382 // notification set 1383 if (mState == STARTED && mOnFrameRenderedNotification != NULL) { 1384 sp<AMessage> notify = mOnFrameRenderedNotification->dup(); 1385 notify->setMessage("data", msg); 1386 notify->post(); 1387 } 1388 break; 1389 } 1390 1391 case CodecBase::kWhatFillThisBuffer: 1392 { 1393 /* size_t index = */updateBuffers(kPortIndexInput, msg); 1394 1395 if (mState == FLUSHING 1396 || mState == STOPPING 1397 || mState == RELEASING) { 1398 returnBuffersToCodecOnPort(kPortIndexInput); 1399 break; 1400 } 1401 1402 // TODO: hold reference of buffer from downstream when 1403 // mPortBuffers is removed. 1404 1405 if (!mCSD.empty()) { 1406 ssize_t index = dequeuePortBuffer(kPortIndexInput); 1407 CHECK_GE(index, 0); 1408 1409 // If codec specific data had been specified as 1410 // part of the format in the call to configure and 1411 // if there's more csd left, we submit it here 1412 // clients only get access to input buffers once 1413 // this data has been exhausted. 1414 1415 status_t err = queueCSDInputBuffer(index); 1416 1417 if (err != OK) { 1418 ALOGE("queueCSDInputBuffer failed w/ error %d", 1419 err); 1420 1421 setStickyError(err); 1422 postActivityNotificationIfPossible(); 1423 1424 cancelPendingDequeueOperations(); 1425 } 1426 break; 1427 } 1428 1429 if (mFlags & kFlagIsAsync) { 1430 if (!mHaveInputSurface) { 1431 if (mState == FLUSHED) { 1432 mHavePendingInputBuffers = true; 1433 } else { 1434 onInputBufferAvailable(); 1435 } 1436 } 1437 } else if (mFlags & kFlagDequeueInputPending) { 1438 CHECK(handleDequeueInputBuffer(mDequeueInputReplyID)); 1439 1440 ++mDequeueInputTimeoutGeneration; 1441 mFlags &= ~kFlagDequeueInputPending; 1442 mDequeueInputReplyID = 0; 1443 } else { 1444 postActivityNotificationIfPossible(); 1445 } 1446 break; 1447 } 1448 1449 case CodecBase::kWhatDrainThisBuffer: 1450 { 1451 /* size_t index = */updateBuffers(kPortIndexOutput, msg); 1452 1453 if (mState == FLUSHING 1454 || mState == STOPPING 1455 || mState == RELEASING) { 1456 returnBuffersToCodecOnPort(kPortIndexOutput); 1457 break; 1458 } 1459 1460 sp<RefBase> obj; 1461 CHECK(msg->findObject("buffer", &obj)); 1462 sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get()); 1463 // TODO: hold buffer's reference when we remove mPortBuffers 1464 1465 int32_t omxFlags; 1466 CHECK(msg->findInt32("flags", &omxFlags)); 1467 1468 buffer->meta()->setInt32("omxFlags", omxFlags); 1469 if (mOutputFormat != buffer->format()) { 1470 mOutputFormat = buffer->format(); 1471 ALOGV("[%s] output format changed to: %s", 1472 mComponentName.c_str(), mOutputFormat->debugString(4).c_str()); 1473 1474 if (mSoftRenderer == NULL && 1475 mSurface != NULL && 1476 (mFlags & kFlagUsesSoftwareRenderer)) { 1477 AString mime; 1478 CHECK(mOutputFormat->findString("mime", &mime)); 1479 1480 // TODO: propagate color aspects to software renderer to allow better 1481 // color conversion to RGB. For now, just mark dataspace for YUV 1482 // rendering. 1483 int32_t dataSpace; 1484 if (mOutputFormat->findInt32("android._dataspace", &dataSpace)) { 1485 ALOGD("[%s] setting dataspace on output surface to #%x", 1486 mComponentName.c_str(), dataSpace); 1487 int err = native_window_set_buffers_data_space( 1488 mSurface.get(), (android_dataspace)dataSpace); 1489 ALOGW_IF(err != 0, "failed to set dataspace on surface (%d)", err); 1490 } 1491 1492 if (mime.startsWithIgnoreCase("video/")) { 1493 mSoftRenderer = new SoftwareRenderer(mSurface, mRotationDegrees); 1494 } 1495 } 1496 1497 if (mFlags & kFlagIsEncoder) { 1498 // Before we announce the format change we should 1499 // collect codec specific data and amend the output 1500 // format as necessary. 1501 if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) { 1502 status_t err = 1503 amendOutputFormatWithCodecSpecificData(buffer); 1504 1505 if (err != OK) { 1506 ALOGE("Codec spit out malformed codec " 1507 "specific data!"); 1508 } 1509 } 1510 } 1511 1512 if (mFlags & kFlagIsAsync) { 1513 onOutputFormatChanged(); 1514 } else { 1515 mFlags |= kFlagOutputFormatChanged; 1516 postActivityNotificationIfPossible(); 1517 } 1518 1519 // Notify mCrypto of video resolution changes 1520 if (mCrypto != NULL) { 1521 int32_t left, top, right, bottom, width, height; 1522 if (mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) { 1523 mCrypto->notifyResolution(right - left + 1, bottom - top + 1); 1524 } else if (mOutputFormat->findInt32("width", &width) 1525 && mOutputFormat->findInt32("height", &height)) { 1526 mCrypto->notifyResolution(width, height); 1527 } 1528 } 1529 } 1530 1531 if (mFlags & kFlagIsAsync) { 1532 onOutputBufferAvailable(); 1533 } else if (mFlags & kFlagDequeueOutputPending) { 1534 CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID)); 1535 1536 ++mDequeueOutputTimeoutGeneration; 1537 mFlags &= ~kFlagDequeueOutputPending; 1538 mDequeueOutputReplyID = 0; 1539 } else { 1540 postActivityNotificationIfPossible(); 1541 } 1542 1543 break; 1544 } 1545 1546 case CodecBase::kWhatEOS: 1547 { 1548 // We already notify the client of this by using the 1549 // corresponding flag in "onOutputBufferReady". 1550 break; 1551 } 1552 1553 case CodecBase::kWhatShutdownCompleted: 1554 { 1555 if (mState == UNINITIALIZED) { 1556 // Ignore shutdown complete if we're already released. 1557 break; 1558 } 1559 if (mState == STOPPING) { 1560 setState(INITIALIZED); 1561 } else { 1562 CHECK_EQ(mState, RELEASING); 1563 setState(UNINITIALIZED); 1564 mComponentName.clear(); 1565 } 1566 mFlags &= ~kFlagIsComponentAllocated; 1567 1568 mResourceManagerService->removeResource(getId(mResourceManagerClient)); 1569 1570 (new AMessage)->postReply(mReplyID); 1571 break; 1572 } 1573 1574 case CodecBase::kWhatFlushCompleted: 1575 { 1576 if (mState != FLUSHING) { 1577 ALOGW("received FlushCompleted message in state %d", 1578 mState); 1579 break; 1580 } 1581 1582 if (mFlags & kFlagIsAsync) { 1583 setState(FLUSHED); 1584 } else { 1585 setState(STARTED); 1586 mCodec->signalResume(); 1587 } 1588 1589 (new AMessage)->postReply(mReplyID); 1590 break; 1591 } 1592 1593 default: 1594 TRESPASS(); 1595 } 1596 break; 1597 } 1598 1599 case kWhatInit: 1600 { 1601 sp<AReplyToken> replyID; 1602 CHECK(msg->senderAwaitsResponse(&replyID)); 1603 1604 if (mState != UNINITIALIZED) { 1605 PostReplyWithError(replyID, INVALID_OPERATION); 1606 break; 1607 } 1608 1609 mReplyID = replyID; 1610 setState(INITIALIZING); 1611 1612 AString name; 1613 CHECK(msg->findString("name", &name)); 1614 1615 int32_t nameIsType; 1616 int32_t encoder = false; 1617 CHECK(msg->findInt32("nameIsType", &nameIsType)); 1618 if (nameIsType) { 1619 CHECK(msg->findInt32("encoder", &encoder)); 1620 } 1621 1622 sp<AMessage> format = new AMessage; 1623 1624 if (nameIsType) { 1625 format->setString("mime", name.c_str()); 1626 format->setInt32("encoder", encoder); 1627 } else { 1628 format->setString("componentName", name.c_str()); 1629 } 1630 1631 mCodec->initiateAllocateComponent(format); 1632 break; 1633 } 1634 1635 case kWhatSetNotification: 1636 { 1637 sp<AMessage> notify; 1638 if (msg->findMessage("on-frame-rendered", ¬ify)) { 1639 mOnFrameRenderedNotification = notify; 1640 } 1641 break; 1642 } 1643 1644 case kWhatSetCallback: 1645 { 1646 sp<AReplyToken> replyID; 1647 CHECK(msg->senderAwaitsResponse(&replyID)); 1648 1649 if (mState == UNINITIALIZED 1650 || mState == INITIALIZING 1651 || isExecuting()) { 1652 // callback can't be set after codec is executing, 1653 // or before it's initialized (as the callback 1654 // will be cleared when it goes to INITIALIZED) 1655 PostReplyWithError(replyID, INVALID_OPERATION); 1656 break; 1657 } 1658 1659 sp<AMessage> callback; 1660 CHECK(msg->findMessage("callback", &callback)); 1661 1662 mCallback = callback; 1663 1664 if (mCallback != NULL) { 1665 ALOGI("MediaCodec will operate in async mode"); 1666 mFlags |= kFlagIsAsync; 1667 } else { 1668 mFlags &= ~kFlagIsAsync; 1669 } 1670 1671 sp<AMessage> response = new AMessage; 1672 response->postReply(replyID); 1673 break; 1674 } 1675 1676 case kWhatConfigure: 1677 { 1678 sp<AReplyToken> replyID; 1679 CHECK(msg->senderAwaitsResponse(&replyID)); 1680 1681 if (mState != INITIALIZED) { 1682 PostReplyWithError(replyID, INVALID_OPERATION); 1683 break; 1684 } 1685 1686 sp<RefBase> obj; 1687 CHECK(msg->findObject("surface", &obj)); 1688 1689 sp<AMessage> format; 1690 CHECK(msg->findMessage("format", &format)); 1691 1692 int32_t push; 1693 if (msg->findInt32("push-blank-buffers-on-shutdown", &push) && push != 0) { 1694 mFlags |= kFlagPushBlankBuffersOnShutdown; 1695 } 1696 1697 if (obj != NULL) { 1698 format->setObject("native-window", obj); 1699 status_t err = handleSetSurface(static_cast<Surface *>(obj.get())); 1700 if (err != OK) { 1701 PostReplyWithError(replyID, err); 1702 break; 1703 } 1704 } else { 1705 handleSetSurface(NULL); 1706 } 1707 1708 mReplyID = replyID; 1709 setState(CONFIGURING); 1710 1711 void *crypto; 1712 if (!msg->findPointer("crypto", &crypto)) { 1713 crypto = NULL; 1714 } 1715 1716 mCrypto = static_cast<ICrypto *>(crypto); 1717 1718 uint32_t flags; 1719 CHECK(msg->findInt32("flags", (int32_t *)&flags)); 1720 1721 if (flags & CONFIGURE_FLAG_ENCODE) { 1722 format->setInt32("encoder", true); 1723 mFlags |= kFlagIsEncoder; 1724 } 1725 1726 extractCSD(format); 1727 1728 mCodec->initiateConfigureComponent(format); 1729 break; 1730 } 1731 1732 case kWhatSetSurface: 1733 { 1734 sp<AReplyToken> replyID; 1735 CHECK(msg->senderAwaitsResponse(&replyID)); 1736 1737 status_t err = OK; 1738 sp<Surface> surface; 1739 1740 switch (mState) { 1741 case CONFIGURED: 1742 case STARTED: 1743 case FLUSHED: 1744 { 1745 sp<RefBase> obj; 1746 (void)msg->findObject("surface", &obj); 1747 sp<Surface> surface = static_cast<Surface *>(obj.get()); 1748 if (mSurface == NULL) { 1749 // do not support setting surface if it was not set 1750 err = INVALID_OPERATION; 1751 } else if (obj == NULL) { 1752 // do not support unsetting surface 1753 err = BAD_VALUE; 1754 } else { 1755 err = connectToSurface(surface); 1756 if (err == ALREADY_EXISTS) { 1757 // reconnecting to same surface 1758 err = OK; 1759 } else { 1760 if (err == OK) { 1761 if (mFlags & kFlagUsesSoftwareRenderer) { 1762 if (mSoftRenderer != NULL 1763 && (mFlags & kFlagPushBlankBuffersOnShutdown)) { 1764 pushBlankBuffersToNativeWindow(mSurface.get()); 1765 } 1766 mSoftRenderer = new SoftwareRenderer(surface); 1767 // TODO: check if this was successful 1768 } else { 1769 err = mCodec->setSurface(surface); 1770 } 1771 } 1772 if (err == OK) { 1773 (void)disconnectFromSurface(); 1774 mSurface = surface; 1775 } 1776 } 1777 } 1778 break; 1779 } 1780 1781 default: 1782 err = INVALID_OPERATION; 1783 break; 1784 } 1785 1786 PostReplyWithError(replyID, err); 1787 break; 1788 } 1789 1790 case kWhatCreateInputSurface: 1791 case kWhatSetInputSurface: 1792 { 1793 sp<AReplyToken> replyID; 1794 CHECK(msg->senderAwaitsResponse(&replyID)); 1795 1796 // Must be configured, but can't have been started yet. 1797 if (mState != CONFIGURED) { 1798 PostReplyWithError(replyID, INVALID_OPERATION); 1799 break; 1800 } 1801 1802 mReplyID = replyID; 1803 if (msg->what() == kWhatCreateInputSurface) { 1804 mCodec->initiateCreateInputSurface(); 1805 } else { 1806 sp<RefBase> obj; 1807 CHECK(msg->findObject("input-surface", &obj)); 1808 1809 mCodec->initiateSetInputSurface( 1810 static_cast<PersistentSurface *>(obj.get())); 1811 } 1812 break; 1813 } 1814 case kWhatStart: 1815 { 1816 sp<AReplyToken> replyID; 1817 CHECK(msg->senderAwaitsResponse(&replyID)); 1818 1819 if (mState == FLUSHED) { 1820 setState(STARTED); 1821 if (mHavePendingInputBuffers) { 1822 onInputBufferAvailable(); 1823 mHavePendingInputBuffers = false; 1824 } 1825 mCodec->signalResume(); 1826 PostReplyWithError(replyID, OK); 1827 break; 1828 } else if (mState != CONFIGURED) { 1829 PostReplyWithError(replyID, INVALID_OPERATION); 1830 break; 1831 } 1832 1833 mReplyID = replyID; 1834 setState(STARTING); 1835 1836 mCodec->initiateStart(); 1837 break; 1838 } 1839 1840 case kWhatStop: 1841 case kWhatRelease: 1842 { 1843 State targetState = 1844 (msg->what() == kWhatStop) ? INITIALIZED : UNINITIALIZED; 1845 1846 sp<AReplyToken> replyID; 1847 CHECK(msg->senderAwaitsResponse(&replyID)); 1848 1849 // already stopped/released 1850 if (mState == UNINITIALIZED && mReleasedByResourceManager) { 1851 sp<AMessage> response = new AMessage; 1852 response->setInt32("err", OK); 1853 response->postReply(replyID); 1854 break; 1855 } 1856 1857 int32_t reclaimed = 0; 1858 msg->findInt32("reclaimed", &reclaimed); 1859 if (reclaimed) { 1860 mReleasedByResourceManager = true; 1861 1862 int32_t force = 0; 1863 msg->findInt32("force", &force); 1864 if (!force && hasPendingBuffer()) { 1865 ALOGW("Can't reclaim codec right now due to pending buffers."); 1866 1867 // return WOULD_BLOCK to ask resource manager to retry later. 1868 sp<AMessage> response = new AMessage; 1869 response->setInt32("err", WOULD_BLOCK); 1870 response->postReply(replyID); 1871 1872 // notify the async client 1873 if (mFlags & kFlagIsAsync) { 1874 onError(DEAD_OBJECT, ACTION_CODE_FATAL); 1875 } 1876 break; 1877 } 1878 } 1879 1880 bool isReleasingAllocatedComponent = 1881 (mFlags & kFlagIsComponentAllocated) && targetState == UNINITIALIZED; 1882 if (!isReleasingAllocatedComponent // See 1 1883 && mState != INITIALIZED 1884 && mState != CONFIGURED && !isExecuting()) { 1885 // 1) Permit release to shut down the component if allocated. 1886 // 1887 // 2) We may be in "UNINITIALIZED" state already and 1888 // also shutdown the encoder/decoder without the 1889 // client being aware of this if media server died while 1890 // we were being stopped. The client would assume that 1891 // after stop() returned, it would be safe to call release() 1892 // and it should be in this case, no harm to allow a release() 1893 // if we're already uninitialized. 1894 sp<AMessage> response = new AMessage; 1895 // TODO: we shouldn't throw an exception for stop/release. Change this to wait until 1896 // the previous stop/release completes and then reply with OK. 1897 status_t err = mState == targetState ? OK : INVALID_OPERATION; 1898 response->setInt32("err", err); 1899 if (err == OK && targetState == UNINITIALIZED) { 1900 mComponentName.clear(); 1901 } 1902 response->postReply(replyID); 1903 break; 1904 } 1905 1906 // If we're flushing, or we're stopping but received a release 1907 // request, post the reply for the pending call first, and consider 1908 // it done. The reply token will be replaced after this, and we'll 1909 // no longer be able to reply. 1910 if (mState == FLUSHING || mState == STOPPING) { 1911 (new AMessage)->postReply(mReplyID); 1912 } 1913 1914 if (mFlags & kFlagSawMediaServerDie) { 1915 // It's dead, Jim. Don't expect initiateShutdown to yield 1916 // any useful results now... 1917 setState(UNINITIALIZED); 1918 if (targetState == UNINITIALIZED) { 1919 mComponentName.clear(); 1920 } 1921 (new AMessage)->postReply(replyID); 1922 break; 1923 } 1924 1925 // If we already have an error, component may not be able to 1926 // complete the shutdown properly. If we're stopping, post the 1927 // reply now with an error to unblock the client, client can 1928 // release after the failure (instead of ANR). 1929 if (msg->what() == kWhatStop && (mFlags & kFlagStickyError)) { 1930 PostReplyWithError(replyID, getStickyError()); 1931 break; 1932 } 1933 1934 mReplyID = replyID; 1935 setState(msg->what() == kWhatStop ? STOPPING : RELEASING); 1936 1937 mCodec->initiateShutdown( 1938 msg->what() == kWhatStop /* keepComponentAllocated */); 1939 1940 returnBuffersToCodec(reclaimed); 1941 1942 if (mSoftRenderer != NULL && (mFlags & kFlagPushBlankBuffersOnShutdown)) { 1943 pushBlankBuffersToNativeWindow(mSurface.get()); 1944 } 1945 1946 break; 1947 } 1948 1949 case kWhatDequeueInputBuffer: 1950 { 1951 sp<AReplyToken> replyID; 1952 CHECK(msg->senderAwaitsResponse(&replyID)); 1953 1954 if (mFlags & kFlagIsAsync) { 1955 ALOGE("dequeueOutputBuffer can't be used in async mode"); 1956 PostReplyWithError(replyID, INVALID_OPERATION); 1957 break; 1958 } 1959 1960 if (mHaveInputSurface) { 1961 ALOGE("dequeueInputBuffer can't be used with input surface"); 1962 PostReplyWithError(replyID, INVALID_OPERATION); 1963 break; 1964 } 1965 1966 if (handleDequeueInputBuffer(replyID, true /* new request */)) { 1967 break; 1968 } 1969 1970 int64_t timeoutUs; 1971 CHECK(msg->findInt64("timeoutUs", &timeoutUs)); 1972 1973 if (timeoutUs == 0ll) { 1974 PostReplyWithError(replyID, -EAGAIN); 1975 break; 1976 } 1977 1978 mFlags |= kFlagDequeueInputPending; 1979 mDequeueInputReplyID = replyID; 1980 1981 if (timeoutUs > 0ll) { 1982 sp<AMessage> timeoutMsg = 1983 new AMessage(kWhatDequeueInputTimedOut, this); 1984 timeoutMsg->setInt32( 1985 "generation", ++mDequeueInputTimeoutGeneration); 1986 timeoutMsg->post(timeoutUs); 1987 } 1988 break; 1989 } 1990 1991 case kWhatDequeueInputTimedOut: 1992 { 1993 int32_t generation; 1994 CHECK(msg->findInt32("generation", &generation)); 1995 1996 if (generation != mDequeueInputTimeoutGeneration) { 1997 // Obsolete 1998 break; 1999 } 2000 2001 CHECK(mFlags & kFlagDequeueInputPending); 2002 2003 PostReplyWithError(mDequeueInputReplyID, -EAGAIN); 2004 2005 mFlags &= ~kFlagDequeueInputPending; 2006 mDequeueInputReplyID = 0; 2007 break; 2008 } 2009 2010 case kWhatQueueInputBuffer: 2011 { 2012 sp<AReplyToken> replyID; 2013 CHECK(msg->senderAwaitsResponse(&replyID)); 2014 2015 if (!isExecuting()) { 2016 PostReplyWithError(replyID, INVALID_OPERATION); 2017 break; 2018 } else if (mFlags & kFlagStickyError) { 2019 PostReplyWithError(replyID, getStickyError()); 2020 break; 2021 } 2022 2023 status_t err = onQueueInputBuffer(msg); 2024 2025 PostReplyWithError(replyID, err); 2026 break; 2027 } 2028 2029 case kWhatDequeueOutputBuffer: 2030 { 2031 sp<AReplyToken> replyID; 2032 CHECK(msg->senderAwaitsResponse(&replyID)); 2033 2034 if (mFlags & kFlagIsAsync) { 2035 ALOGE("dequeueOutputBuffer can't be used in async mode"); 2036 PostReplyWithError(replyID, INVALID_OPERATION); 2037 break; 2038 } 2039 2040 if (handleDequeueOutputBuffer(replyID, true /* new request */)) { 2041 break; 2042 } 2043 2044 int64_t timeoutUs; 2045 CHECK(msg->findInt64("timeoutUs", &timeoutUs)); 2046 2047 if (timeoutUs == 0ll) { 2048 PostReplyWithError(replyID, -EAGAIN); 2049 break; 2050 } 2051 2052 mFlags |= kFlagDequeueOutputPending; 2053 mDequeueOutputReplyID = replyID; 2054 2055 if (timeoutUs > 0ll) { 2056 sp<AMessage> timeoutMsg = 2057 new AMessage(kWhatDequeueOutputTimedOut, this); 2058 timeoutMsg->setInt32( 2059 "generation", ++mDequeueOutputTimeoutGeneration); 2060 timeoutMsg->post(timeoutUs); 2061 } 2062 break; 2063 } 2064 2065 case kWhatDequeueOutputTimedOut: 2066 { 2067 int32_t generation; 2068 CHECK(msg->findInt32("generation", &generation)); 2069 2070 if (generation != mDequeueOutputTimeoutGeneration) { 2071 // Obsolete 2072 break; 2073 } 2074 2075 CHECK(mFlags & kFlagDequeueOutputPending); 2076 2077 PostReplyWithError(mDequeueOutputReplyID, -EAGAIN); 2078 2079 mFlags &= ~kFlagDequeueOutputPending; 2080 mDequeueOutputReplyID = 0; 2081 break; 2082 } 2083 2084 case kWhatReleaseOutputBuffer: 2085 { 2086 sp<AReplyToken> replyID; 2087 CHECK(msg->senderAwaitsResponse(&replyID)); 2088 2089 if (!isExecuting()) { 2090 PostReplyWithError(replyID, INVALID_OPERATION); 2091 break; 2092 } else if (mFlags & kFlagStickyError) { 2093 PostReplyWithError(replyID, getStickyError()); 2094 break; 2095 } 2096 2097 status_t err = onReleaseOutputBuffer(msg); 2098 2099 PostReplyWithError(replyID, err); 2100 break; 2101 } 2102 2103 case kWhatSignalEndOfInputStream: 2104 { 2105 sp<AReplyToken> replyID; 2106 CHECK(msg->senderAwaitsResponse(&replyID)); 2107 2108 if (!isExecuting() || !mHaveInputSurface) { 2109 PostReplyWithError(replyID, INVALID_OPERATION); 2110 break; 2111 } else if (mFlags & kFlagStickyError) { 2112 PostReplyWithError(replyID, getStickyError()); 2113 break; 2114 } 2115 2116 mReplyID = replyID; 2117 mCodec->signalEndOfInputStream(); 2118 break; 2119 } 2120 2121 case kWhatGetBuffers: 2122 { 2123 sp<AReplyToken> replyID; 2124 CHECK(msg->senderAwaitsResponse(&replyID)); 2125 if (!isExecuting() || (mFlags & kFlagIsAsync)) { 2126 PostReplyWithError(replyID, INVALID_OPERATION); 2127 break; 2128 } else if (mFlags & kFlagStickyError) { 2129 PostReplyWithError(replyID, getStickyError()); 2130 break; 2131 } 2132 2133 int32_t portIndex; 2134 CHECK(msg->findInt32("portIndex", &portIndex)); 2135 2136 Vector<sp<MediaCodecBuffer> > *dstBuffers; 2137 CHECK(msg->findPointer("buffers", (void **)&dstBuffers)); 2138 2139 dstBuffers->clear(); 2140 // If we're using input surface (either non-persistent created by 2141 // createInputSurface(), or persistent set by setInputSurface()), 2142 // give the client an empty input buffers array. 2143 if (portIndex != kPortIndexInput || !mHaveInputSurface) { 2144 const Vector<sp<MediaCodecBuffer>> &srcBuffers = mPortBufferArrays[portIndex]; 2145 2146 for (size_t i = 0; i < srcBuffers.size(); ++i) { 2147 dstBuffers->push_back(srcBuffers[i]); 2148 } 2149 } 2150 2151 (new AMessage)->postReply(replyID); 2152 break; 2153 } 2154 2155 case kWhatFlush: 2156 { 2157 sp<AReplyToken> replyID; 2158 CHECK(msg->senderAwaitsResponse(&replyID)); 2159 2160 if (!isExecuting()) { 2161 PostReplyWithError(replyID, INVALID_OPERATION); 2162 break; 2163 } else if (mFlags & kFlagStickyError) { 2164 PostReplyWithError(replyID, getStickyError()); 2165 break; 2166 } 2167 2168 mReplyID = replyID; 2169 // TODO: skip flushing if already FLUSHED 2170 setState(FLUSHING); 2171 2172 mCodec->signalFlush(); 2173 returnBuffersToCodec(); 2174 break; 2175 } 2176 2177 case kWhatGetInputFormat: 2178 case kWhatGetOutputFormat: 2179 { 2180 sp<AMessage> format = 2181 (msg->what() == kWhatGetOutputFormat ? mOutputFormat : mInputFormat); 2182 2183 sp<AReplyToken> replyID; 2184 CHECK(msg->senderAwaitsResponse(&replyID)); 2185 2186 if ((mState != CONFIGURED && mState != STARTING && 2187 mState != STARTED && mState != FLUSHING && 2188 mState != FLUSHED) 2189 || format == NULL) { 2190 PostReplyWithError(replyID, INVALID_OPERATION); 2191 break; 2192 } else if (mFlags & kFlagStickyError) { 2193 PostReplyWithError(replyID, getStickyError()); 2194 break; 2195 } 2196 2197 sp<AMessage> response = new AMessage; 2198 response->setMessage("format", format); 2199 response->postReply(replyID); 2200 break; 2201 } 2202 2203 case kWhatRequestIDRFrame: 2204 { 2205 mCodec->signalRequestIDRFrame(); 2206 break; 2207 } 2208 2209 case kWhatRequestActivityNotification: 2210 { 2211 CHECK(mActivityNotify == NULL); 2212 CHECK(msg->findMessage("notify", &mActivityNotify)); 2213 2214 postActivityNotificationIfPossible(); 2215 break; 2216 } 2217 2218 case kWhatGetName: 2219 { 2220 sp<AReplyToken> replyID; 2221 CHECK(msg->senderAwaitsResponse(&replyID)); 2222 2223 if (mComponentName.empty()) { 2224 PostReplyWithError(replyID, INVALID_OPERATION); 2225 break; 2226 } 2227 2228 sp<AMessage> response = new AMessage; 2229 response->setString("name", mComponentName.c_str()); 2230 response->postReply(replyID); 2231 break; 2232 } 2233 2234 case kWhatSetParameters: 2235 { 2236 sp<AReplyToken> replyID; 2237 CHECK(msg->senderAwaitsResponse(&replyID)); 2238 2239 sp<AMessage> params; 2240 CHECK(msg->findMessage("params", ¶ms)); 2241 2242 status_t err = onSetParameters(params); 2243 2244 PostReplyWithError(replyID, err); 2245 break; 2246 } 2247 2248 default: 2249 TRESPASS(); 2250 } 2251} 2252 2253void MediaCodec::extractCSD(const sp<AMessage> &format) { 2254 mCSD.clear(); 2255 2256 size_t i = 0; 2257 for (;;) { 2258 sp<ABuffer> csd; 2259 if (!format->findBuffer(AStringPrintf("csd-%u", i).c_str(), &csd)) { 2260 break; 2261 } 2262 if (csd->size() == 0) { 2263 ALOGW("csd-%zu size is 0", i); 2264 } 2265 2266 mCSD.push_back(csd); 2267 ++i; 2268 } 2269 2270 ALOGV("Found %zu pieces of codec specific data.", mCSD.size()); 2271} 2272 2273status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) { 2274 CHECK(!mCSD.empty()); 2275 2276 const BufferInfo *info = 2277 &mPortBuffers[kPortIndexInput].itemAt(bufferIndex); 2278 2279 sp<ABuffer> csd = *mCSD.begin(); 2280 mCSD.erase(mCSD.begin()); 2281 2282 const sp<MediaCodecBuffer> &codecInputData = info->mData; 2283 2284 if (csd->size() > codecInputData->capacity()) { 2285 return -EINVAL; 2286 } 2287 2288 memcpy(codecInputData->data(), csd->data(), csd->size()); 2289 2290 AString errorDetailMsg; 2291 2292 sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this); 2293 msg->setSize("index", bufferIndex); 2294 msg->setSize("offset", 0); 2295 msg->setSize("size", csd->size()); 2296 msg->setInt64("timeUs", 0ll); 2297 msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG); 2298 msg->setPointer("errorDetailMsg", &errorDetailMsg); 2299 2300 return onQueueInputBuffer(msg); 2301} 2302 2303void MediaCodec::setState(State newState) { 2304 if (newState == INITIALIZED || newState == UNINITIALIZED) { 2305 delete mSoftRenderer; 2306 mSoftRenderer = NULL; 2307 2308 mCrypto.clear(); 2309 handleSetSurface(NULL); 2310 2311 mInputFormat.clear(); 2312 mOutputFormat.clear(); 2313 mFlags &= ~kFlagOutputFormatChanged; 2314 mFlags &= ~kFlagOutputBuffersChanged; 2315 mFlags &= ~kFlagStickyError; 2316 mFlags &= ~kFlagIsEncoder; 2317 mFlags &= ~kFlagIsAsync; 2318 mStickyError = OK; 2319 2320 mActivityNotify.clear(); 2321 mCallback.clear(); 2322 } 2323 2324 if (newState == UNINITIALIZED) { 2325 // return any straggling buffers, e.g. if we got here on an error 2326 returnBuffersToCodec(); 2327 2328 // The component is gone, mediaserver's probably back up already 2329 // but should definitely be back up should we try to instantiate 2330 // another component.. and the cycle continues. 2331 mFlags &= ~kFlagSawMediaServerDie; 2332 } 2333 2334 mState = newState; 2335 2336 cancelPendingDequeueOperations(); 2337 2338 updateBatteryStat(); 2339} 2340 2341void MediaCodec::returnBuffersToCodec(bool isReclaim) { 2342 returnBuffersToCodecOnPort(kPortIndexInput, isReclaim); 2343 returnBuffersToCodecOnPort(kPortIndexOutput, isReclaim); 2344} 2345 2346void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex, bool isReclaim) { 2347 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 2348 Mutex::Autolock al(mBufferLock); 2349 2350 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; 2351 2352 for (size_t i = 0; i < buffers->size(); ++i) { 2353 BufferInfo *info = &buffers->editItemAt(i); 2354 2355 if (info->mNotify != NULL) { 2356 sp<AMessage> msg = info->mNotify; 2357 info->mNotify = NULL; 2358 msg->setObject("buffer", (portIndex == kPortIndexInput && mCrypto != NULL) 2359 ? info->mSecureData : info->mData); 2360 if (isReclaim && info->mOwnedByClient) { 2361 ALOGD("port %d buffer %zu still owned by client when codec is reclaimed", 2362 portIndex, i); 2363 } else { 2364 info->mOwnedByClient = false; 2365 info->mData.clear(); 2366 info->mSecureData.clear(); 2367 } 2368 2369 if (portIndex == kPortIndexInput) { 2370 /* no error, just returning buffers */ 2371 msg->setInt32("err", OK); 2372 } 2373 msg->post(); 2374 } 2375 } 2376 2377 mAvailPortBuffers[portIndex].clear(); 2378} 2379 2380size_t MediaCodec::updateBuffers( 2381 int32_t portIndex, const sp<AMessage> &msg) { 2382 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 2383 2384 uint32_t bufferID; 2385 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID)); 2386 sp<RefBase> obj; 2387 CHECK(msg->findObject("buffer", &obj)); 2388 sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get()); 2389 2390 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; 2391 2392 for (size_t i = 0; i < buffers->size(); ++i) { 2393 BufferInfo *info = &buffers->editItemAt(i); 2394 2395 if (info->mBufferID == bufferID) { 2396 CHECK(info->mNotify == NULL); 2397 CHECK(msg->findMessage("reply", &info->mNotify)); 2398 2399 if (portIndex == kPortIndexInput && mCrypto != NULL) { 2400 info->mSecureData = buffer; 2401 info->mData = mPortBufferArrays[portIndex][i]; 2402 } else { 2403 info->mData = buffer; 2404 } 2405 mAvailPortBuffers[portIndex].push_back(i); 2406 2407 return i; 2408 } 2409 } 2410 2411 TRESPASS(); 2412 2413 return 0; 2414} 2415 2416status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) { 2417 size_t index; 2418 size_t offset; 2419 size_t size; 2420 int64_t timeUs; 2421 uint32_t flags; 2422 CHECK(msg->findSize("index", &index)); 2423 CHECK(msg->findSize("offset", &offset)); 2424 CHECK(msg->findInt64("timeUs", &timeUs)); 2425 CHECK(msg->findInt32("flags", (int32_t *)&flags)); 2426 2427 const CryptoPlugin::SubSample *subSamples; 2428 size_t numSubSamples; 2429 const uint8_t *key; 2430 const uint8_t *iv; 2431 CryptoPlugin::Mode mode = CryptoPlugin::kMode_Unencrypted; 2432 2433 // We allow the simpler queueInputBuffer API to be used even in 2434 // secure mode, by fabricating a single unencrypted subSample. 2435 CryptoPlugin::SubSample ss; 2436 CryptoPlugin::Pattern pattern; 2437 2438 if (msg->findSize("size", &size)) { 2439 if (mCrypto != NULL) { 2440 ss.mNumBytesOfClearData = size; 2441 ss.mNumBytesOfEncryptedData = 0; 2442 2443 subSamples = &ss; 2444 numSubSamples = 1; 2445 key = NULL; 2446 iv = NULL; 2447 pattern.mEncryptBlocks = 0; 2448 pattern.mSkipBlocks = 0; 2449 } 2450 } else { 2451 if (mCrypto == NULL) { 2452 return -EINVAL; 2453 } 2454 2455 CHECK(msg->findPointer("subSamples", (void **)&subSamples)); 2456 CHECK(msg->findSize("numSubSamples", &numSubSamples)); 2457 CHECK(msg->findPointer("key", (void **)&key)); 2458 CHECK(msg->findPointer("iv", (void **)&iv)); 2459 CHECK(msg->findInt32("encryptBlocks", (int32_t *)&pattern.mEncryptBlocks)); 2460 CHECK(msg->findInt32("skipBlocks", (int32_t *)&pattern.mSkipBlocks)); 2461 2462 int32_t tmp; 2463 CHECK(msg->findInt32("mode", &tmp)); 2464 2465 mode = (CryptoPlugin::Mode)tmp; 2466 2467 size = 0; 2468 for (size_t i = 0; i < numSubSamples; ++i) { 2469 size += subSamples[i].mNumBytesOfClearData; 2470 size += subSamples[i].mNumBytesOfEncryptedData; 2471 } 2472 } 2473 2474 if (index >= mPortBuffers[kPortIndexInput].size()) { 2475 return -ERANGE; 2476 } 2477 2478 BufferInfo *info = &mPortBuffers[kPortIndexInput].editItemAt(index); 2479 2480 if (info->mNotify == NULL || !info->mOwnedByClient) { 2481 return -EACCES; 2482 } 2483 2484 if (offset + size > info->mData->capacity()) { 2485 return -EINVAL; 2486 } 2487 2488 sp<AMessage> reply = info->mNotify; 2489 info->mData->setRange(offset, size); 2490 2491 sp<MediaCodecBuffer> buffer = info->mData; 2492 if (mCrypto != NULL) { 2493 AString *errorDetailMsg; 2494 CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg)); 2495 2496 void *dst_pointer = nullptr; 2497 ICrypto::DestinationType dst_type = ICrypto::kDestinationTypeOpaqueHandle; 2498 2499 if ((mFlags & kFlagIsSecure) == 0) { 2500 dst_pointer = info->mSecureData->base(); 2501 dst_type = ICrypto::kDestinationTypeVmPointer; 2502 } else { 2503 sp<SecureBuffer> secureData = static_cast<SecureBuffer *>(info->mSecureData.get()); 2504 dst_pointer = secureData->getDestinationPointer(); 2505 dst_type = secureData->getDestinationType(); 2506 } 2507 2508 ssize_t result = mCrypto->decrypt( 2509 dst_type, 2510 key, 2511 iv, 2512 mode, 2513 pattern, 2514 info->mSharedEncryptedBuffer, 2515 offset, 2516 subSamples, 2517 numSubSamples, 2518 dst_pointer, 2519 errorDetailMsg); 2520 2521 if (result < 0) { 2522 return result; 2523 } 2524 2525 info->mSecureData->setRange(0, result); 2526 buffer = info->mSecureData; 2527 } 2528 buffer->meta()->setInt64("timeUs", timeUs); 2529 2530 if (flags & BUFFER_FLAG_EOS) { 2531 buffer->meta()->setInt32("eos", true); 2532 } 2533 2534 if (flags & BUFFER_FLAG_CODECCONFIG) { 2535 buffer->meta()->setInt32("csd", true); 2536 } 2537 2538 // synchronization boundary for getBufferAndFormat 2539 { 2540 Mutex::Autolock al(mBufferLock); 2541 info->mOwnedByClient = false; 2542 } 2543 info->mData.clear(); 2544 info->mSecureData.clear(); 2545 reply->setObject("buffer", buffer); 2546 reply->post(); 2547 2548 info->mNotify = NULL; 2549 2550 return OK; 2551} 2552 2553//static 2554size_t MediaCodec::CreateFramesRenderedMessage( 2555 const std::list<FrameRenderTracker::Info> &done, sp<AMessage> &msg) { 2556 size_t index = 0; 2557 2558 for (std::list<FrameRenderTracker::Info>::const_iterator it = done.cbegin(); 2559 it != done.cend(); ++it) { 2560 if (it->getRenderTimeNs() < 0) { 2561 continue; // dropped frame from tracking 2562 } 2563 msg->setInt64(AStringPrintf("%zu-media-time-us", index).c_str(), it->getMediaTimeUs()); 2564 msg->setInt64(AStringPrintf("%zu-system-nano", index).c_str(), it->getRenderTimeNs()); 2565 ++index; 2566 } 2567 return index; 2568} 2569 2570status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) { 2571 size_t index; 2572 CHECK(msg->findSize("index", &index)); 2573 2574 int32_t render; 2575 if (!msg->findInt32("render", &render)) { 2576 render = 0; 2577 } 2578 2579 if (!isExecuting()) { 2580 return -EINVAL; 2581 } 2582 2583 if (index >= mPortBuffers[kPortIndexOutput].size()) { 2584 return -ERANGE; 2585 } 2586 2587 BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index); 2588 2589 if (info->mNotify == NULL || !info->mOwnedByClient) { 2590 return -EACCES; 2591 } 2592 2593 // synchronization boundary for getBufferAndFormat 2594 { 2595 Mutex::Autolock al(mBufferLock); 2596 info->mOwnedByClient = false; 2597 } 2598 2599 if (render && info->mData != NULL && info->mData->size() != 0) { 2600 info->mNotify->setInt32("render", true); 2601 2602 int64_t mediaTimeUs = -1; 2603 info->mData->meta()->findInt64("timeUs", &mediaTimeUs); 2604 2605 int64_t renderTimeNs = 0; 2606 if (!msg->findInt64("timestampNs", &renderTimeNs)) { 2607 // use media timestamp if client did not request a specific render timestamp 2608 ALOGV("using buffer PTS of %lld", (long long)mediaTimeUs); 2609 renderTimeNs = mediaTimeUs * 1000; 2610 } 2611 info->mNotify->setInt64("timestampNs", renderTimeNs); 2612 2613 if (mSoftRenderer != NULL) { 2614 std::list<FrameRenderTracker::Info> doneFrames = mSoftRenderer->render( 2615 info->mData->data(), info->mData->size(), 2616 mediaTimeUs, renderTimeNs, NULL, info->mData->format()); 2617 2618 // if we are running, notify rendered frames 2619 if (!doneFrames.empty() && mState == STARTED && mOnFrameRenderedNotification != NULL) { 2620 sp<AMessage> notify = mOnFrameRenderedNotification->dup(); 2621 sp<AMessage> data = new AMessage; 2622 if (CreateFramesRenderedMessage(doneFrames, data)) { 2623 notify->setMessage("data", data); 2624 notify->post(); 2625 } 2626 } 2627 } 2628 } 2629 2630 info->mNotify->setObject("buffer", info->mData); 2631 info->mData.clear(); 2632 info->mNotify->post(); 2633 info->mNotify.clear(); 2634 2635 return OK; 2636} 2637 2638ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) { 2639 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 2640 2641 List<size_t> *availBuffers = &mAvailPortBuffers[portIndex]; 2642 2643 if (availBuffers->empty()) { 2644 return -EAGAIN; 2645 } 2646 2647 size_t index = *availBuffers->begin(); 2648 availBuffers->erase(availBuffers->begin()); 2649 2650 BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index); 2651 CHECK(!info->mOwnedByClient); 2652 { 2653 Mutex::Autolock al(mBufferLock); 2654 info->mOwnedByClient = true; 2655 2656 // set image-data 2657 if (info->mData->format() != NULL) { 2658 sp<ABuffer> imageData; 2659 if (info->mData->format()->findBuffer("image-data", &imageData)) { 2660 info->mData->meta()->setBuffer("image-data", imageData); 2661 } 2662 int32_t left, top, right, bottom; 2663 if (info->mData->format()->findRect("crop", &left, &top, &right, &bottom)) { 2664 info->mData->meta()->setRect("crop-rect", left, top, right, bottom); 2665 } 2666 } 2667 } 2668 2669 return index; 2670} 2671 2672status_t MediaCodec::connectToSurface(const sp<Surface> &surface) { 2673 status_t err = OK; 2674 if (surface != NULL) { 2675 uint64_t oldId, newId; 2676 if (mSurface != NULL 2677 && surface->getUniqueId(&newId) == NO_ERROR 2678 && mSurface->getUniqueId(&oldId) == NO_ERROR 2679 && newId == oldId) { 2680 ALOGI("[%s] connecting to the same surface. Nothing to do.", mComponentName.c_str()); 2681 return ALREADY_EXISTS; 2682 } 2683 2684 err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA); 2685 if (err == OK) { 2686 // Require a fresh set of buffers after each connect by using a unique generation 2687 // number. Rely on the fact that max supported process id by Linux is 2^22. 2688 // PID is never 0 so we don't have to worry that we use the default generation of 0. 2689 // TODO: come up with a unique scheme if other producers also set the generation number. 2690 static uint32_t mSurfaceGeneration = 0; 2691 uint32_t generation = (getpid() << 10) | (++mSurfaceGeneration & ((1 << 10) - 1)); 2692 surface->setGenerationNumber(generation); 2693 ALOGI("[%s] setting surface generation to %u", mComponentName.c_str(), generation); 2694 2695 // HACK: clear any free buffers. Remove when connect will automatically do this. 2696 // This is needed as the consumer may be holding onto stale frames that it can reattach 2697 // to this surface after disconnect/connect, and those free frames would inherit the new 2698 // generation number. Disconnecting after setting a unique generation prevents this. 2699 native_window_api_disconnect(surface.get(), NATIVE_WINDOW_API_MEDIA); 2700 err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA); 2701 } 2702 2703 if (err != OK) { 2704 ALOGE("native_window_api_connect returned an error: %s (%d)", strerror(-err), err); 2705 } 2706 } 2707 // do not return ALREADY_EXISTS unless surfaces are the same 2708 return err == ALREADY_EXISTS ? BAD_VALUE : err; 2709} 2710 2711status_t MediaCodec::disconnectFromSurface() { 2712 status_t err = OK; 2713 if (mSurface != NULL) { 2714 // Resetting generation is not technically needed, but there is no need to keep it either 2715 mSurface->setGenerationNumber(0); 2716 err = native_window_api_disconnect(mSurface.get(), NATIVE_WINDOW_API_MEDIA); 2717 if (err != OK) { 2718 ALOGW("native_window_api_disconnect returned an error: %s (%d)", strerror(-err), err); 2719 } 2720 // assume disconnected even on error 2721 mSurface.clear(); 2722 } 2723 return err; 2724} 2725 2726status_t MediaCodec::handleSetSurface(const sp<Surface> &surface) { 2727 status_t err = OK; 2728 if (mSurface != NULL) { 2729 (void)disconnectFromSurface(); 2730 } 2731 if (surface != NULL) { 2732 err = connectToSurface(surface); 2733 if (err == OK) { 2734 mSurface = surface; 2735 } 2736 } 2737 return err; 2738} 2739 2740void MediaCodec::onInputBufferAvailable() { 2741 int32_t index; 2742 while ((index = dequeuePortBuffer(kPortIndexInput)) >= 0) { 2743 sp<AMessage> msg = mCallback->dup(); 2744 msg->setInt32("callbackID", CB_INPUT_AVAILABLE); 2745 msg->setInt32("index", index); 2746 msg->post(); 2747 } 2748} 2749 2750void MediaCodec::onOutputBufferAvailable() { 2751 int32_t index; 2752 while ((index = dequeuePortBuffer(kPortIndexOutput)) >= 0) { 2753 const sp<MediaCodecBuffer> &buffer = 2754 mPortBuffers[kPortIndexOutput].itemAt(index).mData; 2755 sp<AMessage> msg = mCallback->dup(); 2756 msg->setInt32("callbackID", CB_OUTPUT_AVAILABLE); 2757 msg->setInt32("index", index); 2758 msg->setSize("offset", buffer->offset()); 2759 msg->setSize("size", buffer->size()); 2760 2761 int64_t timeUs; 2762 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 2763 2764 msg->setInt64("timeUs", timeUs); 2765 2766 int32_t omxFlags; 2767 CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags)); 2768 2769 uint32_t flags = 0; 2770 if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) { 2771 flags |= BUFFER_FLAG_SYNCFRAME; 2772 } 2773 if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) { 2774 flags |= BUFFER_FLAG_CODECCONFIG; 2775 } 2776 if (omxFlags & OMX_BUFFERFLAG_EOS) { 2777 flags |= BUFFER_FLAG_EOS; 2778 } 2779 2780 msg->setInt32("flags", flags); 2781 2782 msg->post(); 2783 } 2784} 2785 2786void MediaCodec::onError(status_t err, int32_t actionCode, const char *detail) { 2787 if (mCallback != NULL) { 2788 sp<AMessage> msg = mCallback->dup(); 2789 msg->setInt32("callbackID", CB_ERROR); 2790 msg->setInt32("err", err); 2791 msg->setInt32("actionCode", actionCode); 2792 2793 if (detail != NULL) { 2794 msg->setString("detail", detail); 2795 } 2796 2797 msg->post(); 2798 } 2799} 2800 2801void MediaCodec::onOutputFormatChanged() { 2802 if (mCallback != NULL) { 2803 sp<AMessage> msg = mCallback->dup(); 2804 msg->setInt32("callbackID", CB_OUTPUT_FORMAT_CHANGED); 2805 msg->setMessage("format", mOutputFormat); 2806 msg->post(); 2807 } 2808} 2809 2810 2811void MediaCodec::postActivityNotificationIfPossible() { 2812 if (mActivityNotify == NULL) { 2813 return; 2814 } 2815 2816 bool isErrorOrOutputChanged = 2817 (mFlags & (kFlagStickyError 2818 | kFlagOutputBuffersChanged 2819 | kFlagOutputFormatChanged)); 2820 2821 if (isErrorOrOutputChanged 2822 || !mAvailPortBuffers[kPortIndexInput].empty() 2823 || !mAvailPortBuffers[kPortIndexOutput].empty()) { 2824 mActivityNotify->setInt32("input-buffers", 2825 mAvailPortBuffers[kPortIndexInput].size()); 2826 2827 if (isErrorOrOutputChanged) { 2828 // we want consumer to dequeue as many times as it can 2829 mActivityNotify->setInt32("output-buffers", INT32_MAX); 2830 } else { 2831 mActivityNotify->setInt32("output-buffers", 2832 mAvailPortBuffers[kPortIndexOutput].size()); 2833 } 2834 mActivityNotify->post(); 2835 mActivityNotify.clear(); 2836 } 2837} 2838 2839status_t MediaCodec::setParameters(const sp<AMessage> ¶ms) { 2840 sp<AMessage> msg = new AMessage(kWhatSetParameters, this); 2841 msg->setMessage("params", params); 2842 2843 sp<AMessage> response; 2844 return PostAndAwaitResponse(msg, &response); 2845} 2846 2847status_t MediaCodec::onSetParameters(const sp<AMessage> ¶ms) { 2848 mCodec->signalSetParameters(params); 2849 2850 return OK; 2851} 2852 2853status_t MediaCodec::amendOutputFormatWithCodecSpecificData( 2854 const sp<MediaCodecBuffer> &buffer) { 2855 AString mime; 2856 CHECK(mOutputFormat->findString("mime", &mime)); 2857 2858 if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) { 2859 // Codec specific data should be SPS and PPS in a single buffer, 2860 // each prefixed by a startcode (0x00 0x00 0x00 0x01). 2861 // We separate the two and put them into the output format 2862 // under the keys "csd-0" and "csd-1". 2863 2864 unsigned csdIndex = 0; 2865 2866 const uint8_t *data = buffer->data(); 2867 size_t size = buffer->size(); 2868 2869 const uint8_t *nalStart; 2870 size_t nalSize; 2871 while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) { 2872 sp<ABuffer> csd = new ABuffer(nalSize + 4); 2873 memcpy(csd->data(), "\x00\x00\x00\x01", 4); 2874 memcpy(csd->data() + 4, nalStart, nalSize); 2875 2876 mOutputFormat->setBuffer( 2877 AStringPrintf("csd-%u", csdIndex).c_str(), csd); 2878 2879 ++csdIndex; 2880 } 2881 2882 if (csdIndex != 2) { 2883 return ERROR_MALFORMED; 2884 } 2885 } else { 2886 // For everything else we just stash the codec specific data into 2887 // the output format as a single piece of csd under "csd-0". 2888 sp<ABuffer> csd = new ABuffer(buffer->size()); 2889 memcpy(csd->data(), buffer->data(), buffer->size()); 2890 csd->setRange(0, buffer->size()); 2891 mOutputFormat->setBuffer("csd-0", csd); 2892 } 2893 2894 return OK; 2895} 2896 2897void MediaCodec::updateBatteryStat() { 2898 if (!mIsVideo) { 2899 return; 2900 } 2901 2902 if (mState == CONFIGURED && !mBatteryStatNotified) { 2903 BatteryNotifier::getInstance().noteStartVideo(mUid); 2904 mBatteryStatNotified = true; 2905 } else if (mState == UNINITIALIZED && mBatteryStatNotified) { 2906 BatteryNotifier::getInstance().noteStopVideo(mUid); 2907 mBatteryStatNotified = false; 2908 } 2909} 2910 2911} // namespace android 2912