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