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