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