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