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