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