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