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