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