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