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