ACodec.cpp revision 8651c6f5069cca40ef805b800a9730617ff7f9b8
1/* 2 * Copyright (C) 2010 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 "ACodec" 19 20#ifdef __LP64__ 21#define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS 22#endif 23 24#include <inttypes.h> 25#include <utils/Trace.h> 26 27#include <gui/Surface.h> 28 29#include <media/stagefright/ACodec.h> 30 31#include <binder/MemoryDealer.h> 32 33#include <media/stagefright/foundation/hexdump.h> 34#include <media/stagefright/foundation/ABuffer.h> 35#include <media/stagefright/foundation/ADebug.h> 36#include <media/stagefright/foundation/AMessage.h> 37#include <media/stagefright/foundation/AUtils.h> 38 39#include <media/stagefright/BufferProducerWrapper.h> 40#include <media/stagefright/MediaCodecList.h> 41#include <media/stagefright/MediaDefs.h> 42#include <media/stagefright/OMXClient.h> 43#include <media/stagefright/OMXCodec.h> 44#include <media/stagefright/PersistentSurface.h> 45#include <media/hardware/HardwareAPI.h> 46 47#include <OMX_AudioExt.h> 48#include <OMX_VideoExt.h> 49#include <OMX_Component.h> 50#include <OMX_IndexExt.h> 51 52#include "include/avc_utils.h" 53 54namespace android { 55 56// OMX errors are directly mapped into status_t range if 57// there is no corresponding MediaError status code. 58// Use the statusFromOMXError(int32_t omxError) function. 59// 60// Currently this is a direct map. 61// See frameworks/native/include/media/openmax/OMX_Core.h 62// 63// Vendor OMX errors from 0x90000000 - 0x9000FFFF 64// Extension OMX errors from 0x8F000000 - 0x90000000 65// Standard OMX errors from 0x80001000 - 0x80001024 (0x80001024 current) 66// 67 68// returns true if err is a recognized OMX error code. 69// as OMX error is OMX_S32, this is an int32_t type 70static inline bool isOMXError(int32_t err) { 71 return (ERROR_CODEC_MIN <= err && err <= ERROR_CODEC_MAX); 72} 73 74// converts an OMX error to a status_t 75static inline status_t statusFromOMXError(int32_t omxError) { 76 switch (omxError) { 77 case OMX_ErrorInvalidComponentName: 78 case OMX_ErrorComponentNotFound: 79 return NAME_NOT_FOUND; // can trigger illegal argument error for provided names. 80 default: 81 return isOMXError(omxError) ? omxError : 0; // no translation required 82 } 83} 84 85// checks and converts status_t to a non-side-effect status_t 86static inline status_t makeNoSideEffectStatus(status_t err) { 87 switch (err) { 88 // the following errors have side effects and may come 89 // from other code modules. Remap for safety reasons. 90 case INVALID_OPERATION: 91 case DEAD_OBJECT: 92 return UNKNOWN_ERROR; 93 default: 94 return err; 95 } 96} 97 98template<class T> 99static void InitOMXParams(T *params) { 100 params->nSize = sizeof(T); 101 params->nVersion.s.nVersionMajor = 1; 102 params->nVersion.s.nVersionMinor = 0; 103 params->nVersion.s.nRevision = 0; 104 params->nVersion.s.nStep = 0; 105} 106 107struct CodecObserver : public BnOMXObserver { 108 CodecObserver() {} 109 110 void setNotificationMessage(const sp<AMessage> &msg) { 111 mNotify = msg; 112 } 113 114 // from IOMXObserver 115 virtual void onMessage(const omx_message &omx_msg) { 116 sp<AMessage> msg = mNotify->dup(); 117 118 msg->setInt32("type", omx_msg.type); 119 msg->setInt32("node", omx_msg.node); 120 121 switch (omx_msg.type) { 122 case omx_message::EVENT: 123 { 124 msg->setInt32("event", omx_msg.u.event_data.event); 125 msg->setInt32("data1", omx_msg.u.event_data.data1); 126 msg->setInt32("data2", omx_msg.u.event_data.data2); 127 break; 128 } 129 130 case omx_message::EMPTY_BUFFER_DONE: 131 { 132 msg->setInt32("buffer", omx_msg.u.buffer_data.buffer); 133 break; 134 } 135 136 case omx_message::FILL_BUFFER_DONE: 137 { 138 msg->setInt32( 139 "buffer", omx_msg.u.extended_buffer_data.buffer); 140 msg->setInt32( 141 "range_offset", 142 omx_msg.u.extended_buffer_data.range_offset); 143 msg->setInt32( 144 "range_length", 145 omx_msg.u.extended_buffer_data.range_length); 146 msg->setInt32( 147 "flags", 148 omx_msg.u.extended_buffer_data.flags); 149 msg->setInt64( 150 "timestamp", 151 omx_msg.u.extended_buffer_data.timestamp); 152 break; 153 } 154 155 default: 156 TRESPASS(); 157 break; 158 } 159 160 msg->post(); 161 } 162 163protected: 164 virtual ~CodecObserver() {} 165 166private: 167 sp<AMessage> mNotify; 168 169 DISALLOW_EVIL_CONSTRUCTORS(CodecObserver); 170}; 171 172//////////////////////////////////////////////////////////////////////////////// 173 174struct ACodec::BaseState : public AState { 175 BaseState(ACodec *codec, const sp<AState> &parentState = NULL); 176 177protected: 178 enum PortMode { 179 KEEP_BUFFERS, 180 RESUBMIT_BUFFERS, 181 FREE_BUFFERS, 182 }; 183 184 ACodec *mCodec; 185 186 virtual PortMode getPortMode(OMX_U32 portIndex); 187 188 virtual bool onMessageReceived(const sp<AMessage> &msg); 189 190 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 191 192 virtual void onOutputBufferDrained(const sp<AMessage> &msg); 193 virtual void onInputBufferFilled(const sp<AMessage> &msg); 194 195 void postFillThisBuffer(BufferInfo *info); 196 197private: 198 bool onOMXMessage(const sp<AMessage> &msg); 199 200 bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID); 201 202 bool onOMXFillBufferDone( 203 IOMX::buffer_id bufferID, 204 size_t rangeOffset, size_t rangeLength, 205 OMX_U32 flags, 206 int64_t timeUs); 207 208 void getMoreInputDataIfPossible(); 209 210 DISALLOW_EVIL_CONSTRUCTORS(BaseState); 211}; 212 213//////////////////////////////////////////////////////////////////////////////// 214 215struct ACodec::DeathNotifier : public IBinder::DeathRecipient { 216 DeathNotifier(const sp<AMessage> ¬ify) 217 : mNotify(notify) { 218 } 219 220 virtual void binderDied(const wp<IBinder> &) { 221 mNotify->post(); 222 } 223 224protected: 225 virtual ~DeathNotifier() {} 226 227private: 228 sp<AMessage> mNotify; 229 230 DISALLOW_EVIL_CONSTRUCTORS(DeathNotifier); 231}; 232 233struct ACodec::UninitializedState : public ACodec::BaseState { 234 UninitializedState(ACodec *codec); 235 236protected: 237 virtual bool onMessageReceived(const sp<AMessage> &msg); 238 virtual void stateEntered(); 239 240private: 241 void onSetup(const sp<AMessage> &msg); 242 bool onAllocateComponent(const sp<AMessage> &msg); 243 244 sp<DeathNotifier> mDeathNotifier; 245 246 DISALLOW_EVIL_CONSTRUCTORS(UninitializedState); 247}; 248 249//////////////////////////////////////////////////////////////////////////////// 250 251struct ACodec::LoadedState : public ACodec::BaseState { 252 LoadedState(ACodec *codec); 253 254protected: 255 virtual bool onMessageReceived(const sp<AMessage> &msg); 256 virtual void stateEntered(); 257 258private: 259 friend struct ACodec::UninitializedState; 260 261 bool onConfigureComponent(const sp<AMessage> &msg); 262 void onCreateInputSurface(const sp<AMessage> &msg); 263 void onUsePersistentInputSurface(const sp<AMessage> &msg); 264 void onStart(); 265 void onShutdown(bool keepComponentAllocated); 266 267 status_t setupInputSurface(); 268 269 DISALLOW_EVIL_CONSTRUCTORS(LoadedState); 270}; 271 272//////////////////////////////////////////////////////////////////////////////// 273 274struct ACodec::LoadedToIdleState : public ACodec::BaseState { 275 LoadedToIdleState(ACodec *codec); 276 277protected: 278 virtual bool onMessageReceived(const sp<AMessage> &msg); 279 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 280 virtual void stateEntered(); 281 282private: 283 status_t allocateBuffers(); 284 285 DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState); 286}; 287 288//////////////////////////////////////////////////////////////////////////////// 289 290struct ACodec::IdleToExecutingState : public ACodec::BaseState { 291 IdleToExecutingState(ACodec *codec); 292 293protected: 294 virtual bool onMessageReceived(const sp<AMessage> &msg); 295 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 296 virtual void stateEntered(); 297 298private: 299 DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState); 300}; 301 302//////////////////////////////////////////////////////////////////////////////// 303 304struct ACodec::ExecutingState : public ACodec::BaseState { 305 ExecutingState(ACodec *codec); 306 307 void submitRegularOutputBuffers(); 308 void submitOutputMetaBuffers(); 309 void submitOutputBuffers(); 310 311 // Submit output buffers to the decoder, submit input buffers to client 312 // to fill with data. 313 void resume(); 314 315 // Returns true iff input and output buffers are in play. 316 bool active() const { return mActive; } 317 318protected: 319 virtual PortMode getPortMode(OMX_U32 portIndex); 320 virtual bool onMessageReceived(const sp<AMessage> &msg); 321 virtual void stateEntered(); 322 323 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 324 325private: 326 bool mActive; 327 328 DISALLOW_EVIL_CONSTRUCTORS(ExecutingState); 329}; 330 331//////////////////////////////////////////////////////////////////////////////// 332 333struct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState { 334 OutputPortSettingsChangedState(ACodec *codec); 335 336protected: 337 virtual PortMode getPortMode(OMX_U32 portIndex); 338 virtual bool onMessageReceived(const sp<AMessage> &msg); 339 virtual void stateEntered(); 340 341 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 342 343private: 344 DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState); 345}; 346 347//////////////////////////////////////////////////////////////////////////////// 348 349struct ACodec::ExecutingToIdleState : public ACodec::BaseState { 350 ExecutingToIdleState(ACodec *codec); 351 352protected: 353 virtual bool onMessageReceived(const sp<AMessage> &msg); 354 virtual void stateEntered(); 355 356 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 357 358 virtual void onOutputBufferDrained(const sp<AMessage> &msg); 359 virtual void onInputBufferFilled(const sp<AMessage> &msg); 360 361private: 362 void changeStateIfWeOwnAllBuffers(); 363 364 bool mComponentNowIdle; 365 366 DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState); 367}; 368 369//////////////////////////////////////////////////////////////////////////////// 370 371struct ACodec::IdleToLoadedState : public ACodec::BaseState { 372 IdleToLoadedState(ACodec *codec); 373 374protected: 375 virtual bool onMessageReceived(const sp<AMessage> &msg); 376 virtual void stateEntered(); 377 378 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 379 380private: 381 DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState); 382}; 383 384//////////////////////////////////////////////////////////////////////////////// 385 386struct ACodec::FlushingState : public ACodec::BaseState { 387 FlushingState(ACodec *codec); 388 389protected: 390 virtual bool onMessageReceived(const sp<AMessage> &msg); 391 virtual void stateEntered(); 392 393 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 394 395 virtual void onOutputBufferDrained(const sp<AMessage> &msg); 396 virtual void onInputBufferFilled(const sp<AMessage> &msg); 397 398private: 399 bool mFlushComplete[2]; 400 401 void changeStateIfWeOwnAllBuffers(); 402 403 DISALLOW_EVIL_CONSTRUCTORS(FlushingState); 404}; 405 406//////////////////////////////////////////////////////////////////////////////// 407 408ACodec::ACodec() 409 : mQuirks(0), 410 mNode(0), 411 mSentFormat(false), 412 mIsVideo(false), 413 mIsEncoder(false), 414 mUseMetadataOnEncoderOutput(false), 415 mShutdownInProgress(false), 416 mExplicitShutdown(false), 417 mEncoderDelay(0), 418 mEncoderPadding(0), 419 mRotationDegrees(0), 420 mChannelMaskPresent(false), 421 mChannelMask(0), 422 mDequeueCounter(0), 423 mStoreMetaDataInOutputBuffers(false), 424 mMetaDataBuffersToSubmit(0), 425 mRepeatFrameDelayUs(-1ll), 426 mMaxPtsGapUs(-1ll), 427 mMaxFps(-1), 428 mTimePerFrameUs(-1ll), 429 mTimePerCaptureUs(-1ll), 430 mCreateInputBuffersSuspended(false), 431 mTunneled(false) { 432 mUninitializedState = new UninitializedState(this); 433 mLoadedState = new LoadedState(this); 434 mLoadedToIdleState = new LoadedToIdleState(this); 435 mIdleToExecutingState = new IdleToExecutingState(this); 436 mExecutingState = new ExecutingState(this); 437 438 mOutputPortSettingsChangedState = 439 new OutputPortSettingsChangedState(this); 440 441 mExecutingToIdleState = new ExecutingToIdleState(this); 442 mIdleToLoadedState = new IdleToLoadedState(this); 443 mFlushingState = new FlushingState(this); 444 445 mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false; 446 mInputEOSResult = OK; 447 448 changeState(mUninitializedState); 449} 450 451ACodec::~ACodec() { 452} 453 454void ACodec::setNotificationMessage(const sp<AMessage> &msg) { 455 mNotify = msg; 456} 457 458void ACodec::initiateSetup(const sp<AMessage> &msg) { 459 msg->setWhat(kWhatSetup); 460 msg->setTarget(this); 461 msg->post(); 462} 463 464void ACodec::signalSetParameters(const sp<AMessage> ¶ms) { 465 sp<AMessage> msg = new AMessage(kWhatSetParameters, this); 466 msg->setMessage("params", params); 467 msg->post(); 468} 469 470void ACodec::initiateAllocateComponent(const sp<AMessage> &msg) { 471 msg->setWhat(kWhatAllocateComponent); 472 msg->setTarget(this); 473 msg->post(); 474} 475 476void ACodec::initiateConfigureComponent(const sp<AMessage> &msg) { 477 msg->setWhat(kWhatConfigureComponent); 478 msg->setTarget(this); 479 msg->post(); 480} 481 482status_t ACodec::setSurface(const sp<Surface> &surface) { 483 sp<AMessage> msg = new AMessage(kWhatSetSurface, this); 484 msg->setObject("surface", surface); 485 486 sp<AMessage> response; 487 status_t err = msg->postAndAwaitResponse(&response); 488 489 if (err == OK) { 490 (void)response->findInt32("err", &err); 491 } 492 return err; 493} 494 495void ACodec::initiateCreateInputSurface() { 496 (new AMessage(kWhatCreateInputSurface, this))->post(); 497} 498 499void ACodec::initiateUsePersistentInputSurface( 500 const sp<PersistentSurface> &surface) { 501 sp<AMessage> msg = new AMessage(kWhatUsePersistentInputSurface, this); 502 msg->setObject("input-surface", surface); 503 msg->post(); 504} 505 506void ACodec::signalEndOfInputStream() { 507 (new AMessage(kWhatSignalEndOfInputStream, this))->post(); 508} 509 510void ACodec::initiateStart() { 511 (new AMessage(kWhatStart, this))->post(); 512} 513 514void ACodec::signalFlush() { 515 ALOGV("[%s] signalFlush", mComponentName.c_str()); 516 (new AMessage(kWhatFlush, this))->post(); 517} 518 519void ACodec::signalResume() { 520 (new AMessage(kWhatResume, this))->post(); 521} 522 523void ACodec::initiateShutdown(bool keepComponentAllocated) { 524 sp<AMessage> msg = new AMessage(kWhatShutdown, this); 525 msg->setInt32("keepComponentAllocated", keepComponentAllocated); 526 msg->post(); 527 if (!keepComponentAllocated) { 528 // ensure shutdown completes in 3 seconds 529 (new AMessage(kWhatReleaseCodecInstance, this))->post(3000000); 530 } 531} 532 533void ACodec::signalRequestIDRFrame() { 534 (new AMessage(kWhatRequestIDRFrame, this))->post(); 535} 536 537// *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** 538// Some codecs may return input buffers before having them processed. 539// This causes a halt if we already signaled an EOS on the input 540// port. For now keep submitting an output buffer if there was an 541// EOS on the input port, but not yet on the output port. 542void ACodec::signalSubmitOutputMetaDataBufferIfEOS_workaround() { 543 if (mPortEOS[kPortIndexInput] && !mPortEOS[kPortIndexOutput] && 544 mMetaDataBuffersToSubmit > 0) { 545 (new AMessage(kWhatSubmitOutputMetaDataBufferIfEOS, this))->post(); 546 } 547} 548 549status_t ACodec::handleSetSurface(const sp<Surface> &surface) { 550 // allow keeping unset surface 551 if (surface == NULL) { 552 if (mNativeWindow != NULL) { 553 ALOGW("cannot unset a surface"); 554 return INVALID_OPERATION; 555 } 556 return OK; 557 } 558 559 // allow keeping unset surface 560 if (mNativeWindow == NULL) { 561 ALOGW("component was not configured with a surface"); 562 return INVALID_OPERATION; 563 } 564 565 ANativeWindow *nativeWindow = surface.get(); 566 // if we have not yet started the codec, we can simply set the native window 567 if (mBuffers[kPortIndexInput].size() == 0) { 568 mNativeWindow = surface; 569 return OK; 570 } 571 572 // we do not support changing a tunneled surface after start 573 if (mTunneled) { 574 ALOGW("cannot change tunneled surface"); 575 return INVALID_OPERATION; 576 } 577 578 status_t err = setupNativeWindowSizeFormatAndUsage(nativeWindow); 579 if (err != OK) { 580 return err; 581 } 582 583 // get min undequeued count. We cannot switch to a surface that has a higher 584 // undequeued count than we allocated. 585 int minUndequeuedBuffers = 0; 586 err = nativeWindow->query( 587 nativeWindow, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, 588 &minUndequeuedBuffers); 589 if (err != 0) { 590 ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)", 591 strerror(-err), -err); 592 return err; 593 } 594 if (minUndequeuedBuffers > (int)mNumUndequeuedBuffers) { 595 ALOGE("new surface holds onto more buffers (%d) than planned for (%zu)", 596 minUndequeuedBuffers, mNumUndequeuedBuffers); 597 return BAD_VALUE; 598 } 599 600 // we cannot change the number of output buffers while OMX is running 601 // set up surface to the same count 602 Vector<BufferInfo> &buffers = mBuffers[kPortIndexOutput]; 603 ALOGV("setting up surface for %zu buffers", buffers.size()); 604 605 err = native_window_set_buffer_count(nativeWindow, buffers.size()); 606 if (err != 0) { 607 ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), 608 -err); 609 return err; 610 } 611 612 // for meta data mode, we move dequeud buffers to the new surface. 613 // for non-meta mode, we must move all registered buffers 614 for (size_t i = 0; i < buffers.size(); ++i) { 615 const BufferInfo &info = buffers[i]; 616 // skip undequeued buffers for meta data mode 617 if (mStoreMetaDataInOutputBuffers 618 && info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 619 ALOGV("skipping buffer %p", info.mGraphicBuffer->getNativeBuffer()); 620 continue; 621 } 622 ALOGV("attaching buffer %p", info.mGraphicBuffer->getNativeBuffer()); 623 624 err = surface->attachBuffer(info.mGraphicBuffer->getNativeBuffer()); 625 if (err != OK) { 626 ALOGE("failed to attach buffer %p to the new surface: %s (%d)", 627 info.mGraphicBuffer->getNativeBuffer(), 628 strerror(-err), -err); 629 return err; 630 } 631 } 632 633 // cancel undequeued buffers to new surface 634 if (!mStoreMetaDataInOutputBuffers) { 635 for (size_t i = 0; i < buffers.size(); ++i) { 636 const BufferInfo &info = buffers[i]; 637 if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 638 ALOGV("canceling buffer %p", info.mGraphicBuffer->getNativeBuffer()); 639 err = nativeWindow->cancelBuffer( 640 nativeWindow, info.mGraphicBuffer->getNativeBuffer(), -1); 641 if (err != OK) { 642 ALOGE("failed to cancel buffer %p to the new surface: %s (%d)", 643 info.mGraphicBuffer->getNativeBuffer(), 644 strerror(-err), -err); 645 return err; 646 } 647 } 648 } 649 // disallow further allocation 650 (void)surface->getIGraphicBufferProducer()->allowAllocation(false); 651 } 652 653 mNativeWindow = nativeWindow; 654 return OK; 655} 656 657status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) { 658 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 659 660 CHECK(mDealer[portIndex] == NULL); 661 CHECK(mBuffers[portIndex].isEmpty()); 662 663 status_t err; 664 if (mNativeWindow != NULL && portIndex == kPortIndexOutput) { 665 if (mStoreMetaDataInOutputBuffers) { 666 err = allocateOutputMetaDataBuffers(); 667 } else { 668 err = allocateOutputBuffersFromNativeWindow(); 669 } 670 } else { 671 OMX_PARAM_PORTDEFINITIONTYPE def; 672 InitOMXParams(&def); 673 def.nPortIndex = portIndex; 674 675 err = mOMX->getParameter( 676 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 677 678 if (err == OK) { 679 ALOGV("[%s] Allocating %u buffers of size %u on %s port", 680 mComponentName.c_str(), 681 def.nBufferCountActual, def.nBufferSize, 682 portIndex == kPortIndexInput ? "input" : "output"); 683 684 size_t totalSize = def.nBufferCountActual * def.nBufferSize; 685 mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec"); 686 687 for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) { 688 sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize); 689 CHECK(mem.get() != NULL); 690 691 BufferInfo info; 692 info.mStatus = BufferInfo::OWNED_BY_US; 693 694 uint32_t requiresAllocateBufferBit = 695 (portIndex == kPortIndexInput) 696 ? OMXCodec::kRequiresAllocateBufferOnInputPorts 697 : OMXCodec::kRequiresAllocateBufferOnOutputPorts; 698 699 if ((portIndex == kPortIndexInput && (mFlags & kFlagIsSecure)) 700 || mUseMetadataOnEncoderOutput) { 701 mem.clear(); 702 703 void *ptr; 704 err = mOMX->allocateBuffer( 705 mNode, portIndex, def.nBufferSize, &info.mBufferID, 706 &ptr); 707 708 int32_t bufSize = mUseMetadataOnEncoderOutput ? 709 (4 + sizeof(buffer_handle_t)) : def.nBufferSize; 710 711 info.mData = new ABuffer(ptr, bufSize); 712 } else if (mQuirks & requiresAllocateBufferBit) { 713 err = mOMX->allocateBufferWithBackup( 714 mNode, portIndex, mem, &info.mBufferID); 715 } else { 716 err = mOMX->useBuffer(mNode, portIndex, mem, &info.mBufferID); 717 } 718 719 if (mem != NULL) { 720 info.mData = new ABuffer(mem->pointer(), def.nBufferSize); 721 } 722 723 mBuffers[portIndex].push(info); 724 } 725 } 726 } 727 728 if (err != OK) { 729 return err; 730 } 731 732 sp<AMessage> notify = mNotify->dup(); 733 notify->setInt32("what", CodecBase::kWhatBuffersAllocated); 734 735 notify->setInt32("portIndex", portIndex); 736 737 sp<PortDescription> desc = new PortDescription; 738 739 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 740 const BufferInfo &info = mBuffers[portIndex][i]; 741 742 desc->addBuffer(info.mBufferID, info.mData); 743 } 744 745 notify->setObject("portDesc", desc); 746 notify->post(); 747 748 return OK; 749} 750 751status_t ACodec::setNativeWindowSizeFormatAndUsage( 752 ANativeWindow *nativeWindow /* nonnull */, 753 int width, int height, int format, int rotation, int usage) { 754 status_t err = native_window_set_buffers_dimensions(nativeWindow, width, height); 755 if (err != 0) { 756 ALOGE("native_window_set_buffers_dimensions failed: %s (%d)", strerror(-err), -err); 757 return err; 758 } 759 760 err = native_window_set_buffers_format(nativeWindow, format); 761 if (err != 0) { 762 ALOGE("native_window_set_buffers_format failed: %s (%d)", strerror(-err), -err); 763 return err; 764 } 765 766 int transform = 0; 767 if ((rotation % 90) == 0) { 768 switch ((rotation / 90) & 3) { 769 case 1: transform = HAL_TRANSFORM_ROT_90; break; 770 case 2: transform = HAL_TRANSFORM_ROT_180; break; 771 case 3: transform = HAL_TRANSFORM_ROT_270; break; 772 default: transform = 0; break; 773 } 774 } 775 776 err = native_window_set_buffers_transform(nativeWindow, transform); 777 if (err != 0) { 778 ALOGE("native_window_set_buffers_transform failed: %s (%d)", strerror(-err), -err); 779 return err; 780 } 781 782 // Make sure to check whether either Stagefright or the video decoder 783 // requested protected buffers. 784 if (usage & GRALLOC_USAGE_PROTECTED) { 785 // Verify that the ANativeWindow sends images directly to 786 // SurfaceFlinger. 787 int queuesToNativeWindow = 0; 788 err = nativeWindow->query( 789 nativeWindow, NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, &queuesToNativeWindow); 790 if (err != 0) { 791 ALOGE("error authenticating native window: %s (%d)", strerror(-err), -err); 792 return err; 793 } 794 if (queuesToNativeWindow != 1) { 795 ALOGE("native window could not be authenticated"); 796 return PERMISSION_DENIED; 797 } 798 } 799 800 int consumerUsage = 0; 801 err = nativeWindow->query(nativeWindow, NATIVE_WINDOW_CONSUMER_USAGE_BITS, &consumerUsage); 802 if (err != 0) { 803 ALOGW("failed to get consumer usage bits. ignoring"); 804 err = 0; 805 } 806 807 int finalUsage = usage | consumerUsage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP; 808 ALOGV("gralloc usage: %#x(ACodec) + %#x(Consumer) = %#x", usage, consumerUsage, finalUsage); 809 err = native_window_set_usage(nativeWindow, finalUsage); 810 if (err != 0) { 811 ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err); 812 return err; 813 } 814 815 err = native_window_set_scaling_mode( 816 nativeWindow, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); 817 if (err != 0) { 818 ALOGE("native_window_set_scaling_mode failed: %s (%d)", strerror(-err), -err); 819 return err; 820 } 821 822 ALOGD("set up nativeWindow %p for %dx%d, color %#x, rotation %d, usage %#x", 823 nativeWindow, width, height, format, rotation, finalUsage); 824 return OK; 825} 826 827status_t ACodec::setupNativeWindowSizeFormatAndUsage(ANativeWindow *nativeWindow /* nonnull */) { 828 OMX_PARAM_PORTDEFINITIONTYPE def; 829 InitOMXParams(&def); 830 def.nPortIndex = kPortIndexOutput; 831 832 status_t err = mOMX->getParameter( 833 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 834 835 if (err != OK) { 836 return err; 837 } 838 839 OMX_U32 usage = 0; 840 err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage); 841 if (err != 0) { 842 ALOGW("querying usage flags from OMX IL component failed: %d", err); 843 // XXX: Currently this error is logged, but not fatal. 844 usage = 0; 845 } 846 int omxUsage = usage; 847 848 if (mFlags & kFlagIsGrallocUsageProtected) { 849 usage |= GRALLOC_USAGE_PROTECTED; 850 } 851 852 ALOGV("gralloc usage: %#x(OMX) => %#x(ACodec)", omxUsage, usage); 853 return setNativeWindowSizeFormatAndUsage( 854 nativeWindow, 855 def.format.video.nFrameWidth, 856 def.format.video.nFrameHeight, 857 def.format.video.eColorFormat, 858 mRotationDegrees, 859 usage); 860} 861 862status_t ACodec::configureOutputBuffersFromNativeWindow( 863 OMX_U32 *bufferCount, OMX_U32 *bufferSize, 864 OMX_U32 *minUndequeuedBuffers) { 865 OMX_PARAM_PORTDEFINITIONTYPE def; 866 InitOMXParams(&def); 867 def.nPortIndex = kPortIndexOutput; 868 869 status_t err = mOMX->getParameter( 870 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 871 872 if (err == OK) { 873 err = setupNativeWindowSizeFormatAndUsage(mNativeWindow.get()); 874 } 875 if (err != OK) { 876 return err; 877 } 878 879 // Exits here for tunneled video playback codecs -- i.e. skips native window 880 // buffer allocation step as this is managed by the tunneled OMX omponent 881 // itself and explicitly sets def.nBufferCountActual to 0. 882 if (mTunneled) { 883 ALOGV("Tunneled Playback: skipping native window buffer allocation."); 884 def.nBufferCountActual = 0; 885 err = mOMX->setParameter( 886 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 887 888 *minUndequeuedBuffers = 0; 889 *bufferCount = 0; 890 *bufferSize = 0; 891 return err; 892 } 893 894 *minUndequeuedBuffers = 0; 895 err = mNativeWindow->query( 896 mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, 897 (int *)minUndequeuedBuffers); 898 899 if (err != 0) { 900 ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)", 901 strerror(-err), -err); 902 return err; 903 } 904 905 // FIXME: assume that surface is controlled by app (native window 906 // returns the number for the case when surface is not controlled by app) 907 // FIXME2: This means that minUndeqeueudBufs can be 1 larger than reported 908 // For now, try to allocate 1 more buffer, but don't fail if unsuccessful 909 910 // Use conservative allocation while also trying to reduce starvation 911 // 912 // 1. allocate at least nBufferCountMin + minUndequeuedBuffers - that is the 913 // minimum needed for the consumer to be able to work 914 // 2. try to allocate two (2) additional buffers to reduce starvation from 915 // the consumer 916 // plus an extra buffer to account for incorrect minUndequeuedBufs 917 for (OMX_U32 extraBuffers = 2 + 1; /* condition inside loop */; extraBuffers--) { 918 OMX_U32 newBufferCount = 919 def.nBufferCountMin + *minUndequeuedBuffers + extraBuffers; 920 def.nBufferCountActual = newBufferCount; 921 err = mOMX->setParameter( 922 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 923 924 if (err == OK) { 925 *minUndequeuedBuffers += extraBuffers; 926 break; 927 } 928 929 ALOGW("[%s] setting nBufferCountActual to %u failed: %d", 930 mComponentName.c_str(), newBufferCount, err); 931 /* exit condition */ 932 if (extraBuffers == 0) { 933 return err; 934 } 935 } 936 937 err = native_window_set_buffer_count( 938 mNativeWindow.get(), def.nBufferCountActual); 939 940 if (err != 0) { 941 ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), 942 -err); 943 return err; 944 } 945 946 *bufferCount = def.nBufferCountActual; 947 *bufferSize = def.nBufferSize; 948 return err; 949} 950 951status_t ACodec::allocateOutputBuffersFromNativeWindow() { 952 OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers; 953 status_t err = configureOutputBuffersFromNativeWindow( 954 &bufferCount, &bufferSize, &minUndequeuedBuffers); 955 if (err != 0) 956 return err; 957 mNumUndequeuedBuffers = minUndequeuedBuffers; 958 959 if (!mStoreMetaDataInOutputBuffers) { 960 static_cast<Surface*>(mNativeWindow.get()) 961 ->getIGraphicBufferProducer()->allowAllocation(true); 962 } 963 964 ALOGV("[%s] Allocating %u buffers from a native window of size %u on " 965 "output port", 966 mComponentName.c_str(), bufferCount, bufferSize); 967 968 // Dequeue buffers and send them to OMX 969 for (OMX_U32 i = 0; i < bufferCount; i++) { 970 ANativeWindowBuffer *buf; 971 err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf); 972 if (err != 0) { 973 ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err); 974 break; 975 } 976 977 sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false)); 978 BufferInfo info; 979 info.mStatus = BufferInfo::OWNED_BY_US; 980 info.mData = new ABuffer(NULL /* data */, bufferSize /* capacity */); 981 info.mGraphicBuffer = graphicBuffer; 982 mBuffers[kPortIndexOutput].push(info); 983 984 IOMX::buffer_id bufferId; 985 err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer, 986 &bufferId); 987 if (err != 0) { 988 ALOGE("registering GraphicBuffer %u with OMX IL component failed: " 989 "%d", i, err); 990 break; 991 } 992 993 mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId; 994 995 ALOGV("[%s] Registered graphic buffer with ID %u (pointer = %p)", 996 mComponentName.c_str(), 997 bufferId, graphicBuffer.get()); 998 } 999 1000 OMX_U32 cancelStart; 1001 OMX_U32 cancelEnd; 1002 1003 if (err != 0) { 1004 // If an error occurred while dequeuing we need to cancel any buffers 1005 // that were dequeued. 1006 cancelStart = 0; 1007 cancelEnd = mBuffers[kPortIndexOutput].size(); 1008 } else { 1009 // Return the required minimum undequeued buffers to the native window. 1010 cancelStart = bufferCount - minUndequeuedBuffers; 1011 cancelEnd = bufferCount; 1012 } 1013 1014 for (OMX_U32 i = cancelStart; i < cancelEnd; i++) { 1015 BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i); 1016 status_t error = cancelBufferToNativeWindow(info); 1017 if (err == 0) { 1018 err = error; 1019 } 1020 } 1021 1022 if (!mStoreMetaDataInOutputBuffers) { 1023 static_cast<Surface*>(mNativeWindow.get()) 1024 ->getIGraphicBufferProducer()->allowAllocation(false); 1025 } 1026 1027 return err; 1028} 1029 1030status_t ACodec::allocateOutputMetaDataBuffers() { 1031 OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers; 1032 status_t err = configureOutputBuffersFromNativeWindow( 1033 &bufferCount, &bufferSize, &minUndequeuedBuffers); 1034 if (err != 0) 1035 return err; 1036 mNumUndequeuedBuffers = minUndequeuedBuffers; 1037 1038 ALOGV("[%s] Allocating %u meta buffers on output port", 1039 mComponentName.c_str(), bufferCount); 1040 1041 size_t totalSize = bufferCount * 8; 1042 mDealer[kPortIndexOutput] = new MemoryDealer(totalSize, "ACodec"); 1043 1044 // Dequeue buffers and send them to OMX 1045 for (OMX_U32 i = 0; i < bufferCount; i++) { 1046 BufferInfo info; 1047 info.mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 1048 info.mGraphicBuffer = NULL; 1049 info.mDequeuedAt = mDequeueCounter; 1050 1051 sp<IMemory> mem = mDealer[kPortIndexOutput]->allocate( 1052 sizeof(struct VideoDecoderOutputMetaData)); 1053 CHECK(mem.get() != NULL); 1054 info.mData = new ABuffer(mem->pointer(), mem->size()); 1055 1056 // we use useBuffer for metadata regardless of quirks 1057 err = mOMX->useBuffer( 1058 mNode, kPortIndexOutput, mem, &info.mBufferID); 1059 1060 mBuffers[kPortIndexOutput].push(info); 1061 1062 ALOGV("[%s] allocated meta buffer with ID %u (pointer = %p)", 1063 mComponentName.c_str(), info.mBufferID, mem->pointer()); 1064 } 1065 1066 mMetaDataBuffersToSubmit = bufferCount - minUndequeuedBuffers; 1067 return err; 1068} 1069 1070status_t ACodec::submitOutputMetaDataBuffer() { 1071 CHECK(mStoreMetaDataInOutputBuffers); 1072 if (mMetaDataBuffersToSubmit == 0) 1073 return OK; 1074 1075 BufferInfo *info = dequeueBufferFromNativeWindow(); 1076 if (info == NULL) 1077 return ERROR_IO; 1078 1079 ALOGV("[%s] submitting output meta buffer ID %u for graphic buffer %p", 1080 mComponentName.c_str(), info->mBufferID, info->mGraphicBuffer.get()); 1081 1082 --mMetaDataBuffersToSubmit; 1083 CHECK_EQ(mOMX->fillBuffer(mNode, info->mBufferID), 1084 (status_t)OK); 1085 1086 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 1087 return OK; 1088} 1089 1090status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) { 1091 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 1092 1093 ALOGV("[%s] Calling cancelBuffer on buffer %u", 1094 mComponentName.c_str(), info->mBufferID); 1095 1096 int err = mNativeWindow->cancelBuffer( 1097 mNativeWindow.get(), info->mGraphicBuffer.get(), -1); 1098 1099 ALOGW_IF(err != 0, "[%s] can not return buffer %u to native window", 1100 mComponentName.c_str(), info->mBufferID); 1101 1102 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 1103 1104 return err; 1105} 1106 1107ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() { 1108 ANativeWindowBuffer *buf; 1109 CHECK(mNativeWindow.get() != NULL); 1110 1111 if (mTunneled) { 1112 ALOGW("dequeueBufferFromNativeWindow() should not be called in tunnel" 1113 " video playback mode mode!"); 1114 return NULL; 1115 } 1116 1117 if (native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf) != 0) { 1118 ALOGE("dequeueBuffer failed."); 1119 return NULL; 1120 } 1121 1122 BufferInfo *oldest = NULL; 1123 for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) { 1124 BufferInfo *info = 1125 &mBuffers[kPortIndexOutput].editItemAt(i); 1126 1127 if (info->mGraphicBuffer != NULL && 1128 info->mGraphicBuffer->handle == buf->handle) { 1129 CHECK_EQ((int)info->mStatus, 1130 (int)BufferInfo::OWNED_BY_NATIVE_WINDOW); 1131 1132 info->mStatus = BufferInfo::OWNED_BY_US; 1133 1134 return info; 1135 } 1136 1137 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW && 1138 (oldest == NULL || 1139 // avoid potential issues from counter rolling over 1140 mDequeueCounter - info->mDequeuedAt > 1141 mDequeueCounter - oldest->mDequeuedAt)) { 1142 oldest = info; 1143 } 1144 } 1145 1146 if (oldest) { 1147 CHECK(mStoreMetaDataInOutputBuffers); 1148 1149 // discard buffer in LRU info and replace with new buffer 1150 oldest->mGraphicBuffer = new GraphicBuffer(buf, false); 1151 oldest->mStatus = BufferInfo::OWNED_BY_US; 1152 1153 mOMX->updateGraphicBufferInMeta( 1154 mNode, kPortIndexOutput, oldest->mGraphicBuffer, 1155 oldest->mBufferID); 1156 1157 VideoDecoderOutputMetaData *metaData = 1158 reinterpret_cast<VideoDecoderOutputMetaData *>( 1159 oldest->mData->base()); 1160 CHECK_EQ(metaData->eType, kMetadataBufferTypeGrallocSource); 1161 1162 ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)", 1163 (unsigned)(oldest - &mBuffers[kPortIndexOutput][0]), 1164 mDequeueCounter - oldest->mDequeuedAt, 1165 metaData->pHandle, 1166 oldest->mGraphicBuffer->handle, oldest->mData->base()); 1167 1168 return oldest; 1169 } 1170 1171 TRESPASS(); 1172 1173 return NULL; 1174} 1175 1176status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) { 1177 for (size_t i = mBuffers[portIndex].size(); i-- > 0;) { 1178 CHECK_EQ((status_t)OK, freeBuffer(portIndex, i)); 1179 } 1180 1181 mDealer[portIndex].clear(); 1182 1183 return OK; 1184} 1185 1186status_t ACodec::freeOutputBuffersNotOwnedByComponent() { 1187 for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) { 1188 BufferInfo *info = 1189 &mBuffers[kPortIndexOutput].editItemAt(i); 1190 1191 // At this time some buffers may still be with the component 1192 // or being drained. 1193 if (info->mStatus != BufferInfo::OWNED_BY_COMPONENT && 1194 info->mStatus != BufferInfo::OWNED_BY_DOWNSTREAM) { 1195 CHECK_EQ((status_t)OK, freeBuffer(kPortIndexOutput, i)); 1196 } 1197 } 1198 1199 return OK; 1200} 1201 1202status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) { 1203 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 1204 1205 CHECK(info->mStatus == BufferInfo::OWNED_BY_US 1206 || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW); 1207 1208 if (portIndex == kPortIndexOutput && mNativeWindow != NULL 1209 && info->mStatus == BufferInfo::OWNED_BY_US) { 1210 cancelBufferToNativeWindow(info); 1211 } 1212 1213 CHECK_EQ(mOMX->freeBuffer( 1214 mNode, portIndex, info->mBufferID), 1215 (status_t)OK); 1216 1217 mBuffers[portIndex].removeAt(i); 1218 1219 return OK; 1220} 1221 1222ACodec::BufferInfo *ACodec::findBufferByID( 1223 uint32_t portIndex, IOMX::buffer_id bufferID, 1224 ssize_t *index) { 1225 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 1226 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 1227 1228 if (info->mBufferID == bufferID) { 1229 if (index != NULL) { 1230 *index = i; 1231 } 1232 return info; 1233 } 1234 } 1235 1236 TRESPASS(); 1237 1238 return NULL; 1239} 1240 1241status_t ACodec::setComponentRole( 1242 bool isEncoder, const char *mime) { 1243 struct MimeToRole { 1244 const char *mime; 1245 const char *decoderRole; 1246 const char *encoderRole; 1247 }; 1248 1249 static const MimeToRole kMimeToRole[] = { 1250 { MEDIA_MIMETYPE_AUDIO_MPEG, 1251 "audio_decoder.mp3", "audio_encoder.mp3" }, 1252 { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I, 1253 "audio_decoder.mp1", "audio_encoder.mp1" }, 1254 { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II, 1255 "audio_decoder.mp2", "audio_encoder.mp2" }, 1256 { MEDIA_MIMETYPE_AUDIO_AMR_NB, 1257 "audio_decoder.amrnb", "audio_encoder.amrnb" }, 1258 { MEDIA_MIMETYPE_AUDIO_AMR_WB, 1259 "audio_decoder.amrwb", "audio_encoder.amrwb" }, 1260 { MEDIA_MIMETYPE_AUDIO_AAC, 1261 "audio_decoder.aac", "audio_encoder.aac" }, 1262 { MEDIA_MIMETYPE_AUDIO_VORBIS, 1263 "audio_decoder.vorbis", "audio_encoder.vorbis" }, 1264 { MEDIA_MIMETYPE_AUDIO_OPUS, 1265 "audio_decoder.opus", "audio_encoder.opus" }, 1266 { MEDIA_MIMETYPE_AUDIO_G711_MLAW, 1267 "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" }, 1268 { MEDIA_MIMETYPE_AUDIO_G711_ALAW, 1269 "audio_decoder.g711alaw", "audio_encoder.g711alaw" }, 1270 { MEDIA_MIMETYPE_VIDEO_AVC, 1271 "video_decoder.avc", "video_encoder.avc" }, 1272 { MEDIA_MIMETYPE_VIDEO_HEVC, 1273 "video_decoder.hevc", "video_encoder.hevc" }, 1274 { MEDIA_MIMETYPE_VIDEO_MPEG4, 1275 "video_decoder.mpeg4", "video_encoder.mpeg4" }, 1276 { MEDIA_MIMETYPE_VIDEO_H263, 1277 "video_decoder.h263", "video_encoder.h263" }, 1278 { MEDIA_MIMETYPE_VIDEO_VP8, 1279 "video_decoder.vp8", "video_encoder.vp8" }, 1280 { MEDIA_MIMETYPE_VIDEO_VP9, 1281 "video_decoder.vp9", "video_encoder.vp9" }, 1282 { MEDIA_MIMETYPE_AUDIO_RAW, 1283 "audio_decoder.raw", "audio_encoder.raw" }, 1284 { MEDIA_MIMETYPE_AUDIO_FLAC, 1285 "audio_decoder.flac", "audio_encoder.flac" }, 1286 { MEDIA_MIMETYPE_AUDIO_MSGSM, 1287 "audio_decoder.gsm", "audio_encoder.gsm" }, 1288 { MEDIA_MIMETYPE_VIDEO_MPEG2, 1289 "video_decoder.mpeg2", "video_encoder.mpeg2" }, 1290 { MEDIA_MIMETYPE_AUDIO_AC3, 1291 "audio_decoder.ac3", "audio_encoder.ac3" }, 1292 { MEDIA_MIMETYPE_AUDIO_EAC3, 1293 "audio_decoder.eac3", "audio_encoder.eac3" }, 1294 }; 1295 1296 static const size_t kNumMimeToRole = 1297 sizeof(kMimeToRole) / sizeof(kMimeToRole[0]); 1298 1299 size_t i; 1300 for (i = 0; i < kNumMimeToRole; ++i) { 1301 if (!strcasecmp(mime, kMimeToRole[i].mime)) { 1302 break; 1303 } 1304 } 1305 1306 if (i == kNumMimeToRole) { 1307 return ERROR_UNSUPPORTED; 1308 } 1309 1310 const char *role = 1311 isEncoder ? kMimeToRole[i].encoderRole 1312 : kMimeToRole[i].decoderRole; 1313 1314 if (role != NULL) { 1315 OMX_PARAM_COMPONENTROLETYPE roleParams; 1316 InitOMXParams(&roleParams); 1317 1318 strncpy((char *)roleParams.cRole, 1319 role, OMX_MAX_STRINGNAME_SIZE - 1); 1320 1321 roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0'; 1322 1323 status_t err = mOMX->setParameter( 1324 mNode, OMX_IndexParamStandardComponentRole, 1325 &roleParams, sizeof(roleParams)); 1326 1327 if (err != OK) { 1328 ALOGW("[%s] Failed to set standard component role '%s'.", 1329 mComponentName.c_str(), role); 1330 1331 return err; 1332 } 1333 } 1334 1335 return OK; 1336} 1337 1338status_t ACodec::configureCodec( 1339 const char *mime, const sp<AMessage> &msg) { 1340 int32_t encoder; 1341 if (!msg->findInt32("encoder", &encoder)) { 1342 encoder = false; 1343 } 1344 1345 sp<AMessage> inputFormat = new AMessage(); 1346 sp<AMessage> outputFormat = mNotify->dup(); // will use this for kWhatOutputFormatChanged 1347 1348 mIsEncoder = encoder; 1349 1350 1351 status_t err = setComponentRole(encoder /* isEncoder */, mime); 1352 1353 if (err != OK) { 1354 return err; 1355 } 1356 1357 int32_t bitRate = 0; 1358 // FLAC encoder doesn't need a bitrate, other encoders do 1359 if (encoder && strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC) 1360 && !msg->findInt32("bitrate", &bitRate)) { 1361 return INVALID_OPERATION; 1362 } 1363 1364 int32_t storeMeta; 1365 if (encoder 1366 && msg->findInt32("store-metadata-in-buffers", &storeMeta) 1367 && storeMeta != 0) { 1368 err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexInput, OMX_TRUE); 1369 1370 if (err != OK) { 1371 ALOGE("[%s] storeMetaDataInBuffers (input) failed w/ err %d", 1372 mComponentName.c_str(), err); 1373 1374 return err; 1375 } 1376 } 1377 1378 int32_t prependSPSPPS = 0; 1379 if (encoder 1380 && msg->findInt32("prepend-sps-pps-to-idr-frames", &prependSPSPPS) 1381 && prependSPSPPS != 0) { 1382 OMX_INDEXTYPE index; 1383 err = mOMX->getExtensionIndex( 1384 mNode, 1385 "OMX.google.android.index.prependSPSPPSToIDRFrames", 1386 &index); 1387 1388 if (err == OK) { 1389 PrependSPSPPSToIDRFramesParams params; 1390 InitOMXParams(¶ms); 1391 params.bEnable = OMX_TRUE; 1392 1393 err = mOMX->setParameter( 1394 mNode, index, ¶ms, sizeof(params)); 1395 } 1396 1397 if (err != OK) { 1398 ALOGE("Encoder could not be configured to emit SPS/PPS before " 1399 "IDR frames. (err %d)", err); 1400 1401 return err; 1402 } 1403 } 1404 1405 // Only enable metadata mode on encoder output if encoder can prepend 1406 // sps/pps to idr frames, since in metadata mode the bitstream is in an 1407 // opaque handle, to which we don't have access. 1408 int32_t video = !strncasecmp(mime, "video/", 6); 1409 mIsVideo = video; 1410 if (encoder && video) { 1411 OMX_BOOL enable = (OMX_BOOL) (prependSPSPPS 1412 && msg->findInt32("store-metadata-in-buffers-output", &storeMeta) 1413 && storeMeta != 0); 1414 1415 err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, enable); 1416 1417 if (err != OK) { 1418 ALOGE("[%s] storeMetaDataInBuffers (output) failed w/ err %d", 1419 mComponentName.c_str(), err); 1420 mUseMetadataOnEncoderOutput = 0; 1421 } else { 1422 mUseMetadataOnEncoderOutput = enable; 1423 } 1424 1425 if (!msg->findInt64( 1426 "repeat-previous-frame-after", 1427 &mRepeatFrameDelayUs)) { 1428 mRepeatFrameDelayUs = -1ll; 1429 } 1430 1431 if (!msg->findInt64("max-pts-gap-to-encoder", &mMaxPtsGapUs)) { 1432 mMaxPtsGapUs = -1ll; 1433 } 1434 1435 if (!msg->findFloat("max-fps-to-encoder", &mMaxFps)) { 1436 mMaxFps = -1; 1437 } 1438 1439 if (!msg->findInt64("time-lapse", &mTimePerCaptureUs)) { 1440 mTimePerCaptureUs = -1ll; 1441 } 1442 1443 if (!msg->findInt32( 1444 "create-input-buffers-suspended", 1445 (int32_t*)&mCreateInputBuffersSuspended)) { 1446 mCreateInputBuffersSuspended = false; 1447 } 1448 } 1449 1450 // NOTE: we only use native window for video decoders 1451 sp<RefBase> obj; 1452 bool haveNativeWindow = msg->findObject("native-window", &obj) 1453 && obj != NULL && video && !encoder; 1454 mStoreMetaDataInOutputBuffers = false; 1455 if (video && !encoder) { 1456 inputFormat->setInt32("adaptive-playback", false); 1457 1458 int32_t usageProtected; 1459 if (msg->findInt32("protected", &usageProtected) && usageProtected) { 1460 if (!haveNativeWindow) { 1461 ALOGE("protected output buffers must be sent to an ANativeWindow"); 1462 return PERMISSION_DENIED; 1463 } 1464 mFlags |= kFlagIsGrallocUsageProtected; 1465 mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown; 1466 } 1467 } 1468 if (haveNativeWindow) { 1469 sp<ANativeWindow> nativeWindow = 1470 static_cast<ANativeWindow *>(static_cast<Surface *>(obj.get())); 1471 1472 // START of temporary support for automatic FRC - THIS WILL BE REMOVED 1473 int32_t autoFrc; 1474 if (msg->findInt32("auto-frc", &autoFrc)) { 1475 bool enabled = autoFrc; 1476 OMX_CONFIG_BOOLEANTYPE config; 1477 InitOMXParams(&config); 1478 config.bEnabled = (OMX_BOOL)enabled; 1479 status_t temp = mOMX->setConfig( 1480 mNode, (OMX_INDEXTYPE)OMX_IndexConfigAutoFramerateConversion, 1481 &config, sizeof(config)); 1482 if (temp == OK) { 1483 outputFormat->setInt32("auto-frc", enabled); 1484 } else if (enabled) { 1485 ALOGI("codec does not support requested auto-frc (err %d)", temp); 1486 } 1487 } 1488 // END of temporary support for automatic FRC 1489 1490 int32_t tunneled; 1491 if (msg->findInt32("feature-tunneled-playback", &tunneled) && 1492 tunneled != 0) { 1493 ALOGI("Configuring TUNNELED video playback."); 1494 mTunneled = true; 1495 1496 int32_t audioHwSync = 0; 1497 if (!msg->findInt32("audio-hw-sync", &audioHwSync)) { 1498 ALOGW("No Audio HW Sync provided for video tunnel"); 1499 } 1500 err = configureTunneledVideoPlayback(audioHwSync, nativeWindow); 1501 if (err != OK) { 1502 ALOGE("configureTunneledVideoPlayback(%d,%p) failed!", 1503 audioHwSync, nativeWindow.get()); 1504 return err; 1505 } 1506 1507 int32_t maxWidth = 0, maxHeight = 0; 1508 if (msg->findInt32("max-width", &maxWidth) && 1509 msg->findInt32("max-height", &maxHeight)) { 1510 1511 err = mOMX->prepareForAdaptivePlayback( 1512 mNode, kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight); 1513 if (err != OK) { 1514 ALOGW("[%s] prepareForAdaptivePlayback failed w/ err %d", 1515 mComponentName.c_str(), err); 1516 // allow failure 1517 err = OK; 1518 } else { 1519 inputFormat->setInt32("max-width", maxWidth); 1520 inputFormat->setInt32("max-height", maxHeight); 1521 inputFormat->setInt32("adaptive-playback", true); 1522 } 1523 } 1524 } else { 1525 ALOGV("Configuring CPU controlled video playback."); 1526 mTunneled = false; 1527 1528 // Explicity reset the sideband handle of the window for 1529 // non-tunneled video in case the window was previously used 1530 // for a tunneled video playback. 1531 err = native_window_set_sideband_stream(nativeWindow.get(), NULL); 1532 if (err != OK) { 1533 ALOGE("set_sideband_stream(NULL) failed! (err %d).", err); 1534 return err; 1535 } 1536 1537 // Always try to enable dynamic output buffers on native surface 1538 err = mOMX->storeMetaDataInBuffers( 1539 mNode, kPortIndexOutput, OMX_TRUE); 1540 if (err != OK) { 1541 ALOGE("[%s] storeMetaDataInBuffers failed w/ err %d", 1542 mComponentName.c_str(), err); 1543 1544 // if adaptive playback has been requested, try JB fallback 1545 // NOTE: THIS FALLBACK MECHANISM WILL BE REMOVED DUE TO ITS 1546 // LARGE MEMORY REQUIREMENT 1547 1548 // we will not do adaptive playback on software accessed 1549 // surfaces as they never had to respond to changes in the 1550 // crop window, and we don't trust that they will be able to. 1551 int usageBits = 0; 1552 bool canDoAdaptivePlayback; 1553 1554 if (nativeWindow->query( 1555 nativeWindow.get(), 1556 NATIVE_WINDOW_CONSUMER_USAGE_BITS, 1557 &usageBits) != OK) { 1558 canDoAdaptivePlayback = false; 1559 } else { 1560 canDoAdaptivePlayback = 1561 (usageBits & 1562 (GRALLOC_USAGE_SW_READ_MASK | 1563 GRALLOC_USAGE_SW_WRITE_MASK)) == 0; 1564 } 1565 1566 int32_t maxWidth = 0, maxHeight = 0; 1567 if (canDoAdaptivePlayback && 1568 msg->findInt32("max-width", &maxWidth) && 1569 msg->findInt32("max-height", &maxHeight)) { 1570 ALOGV("[%s] prepareForAdaptivePlayback(%dx%d)", 1571 mComponentName.c_str(), maxWidth, maxHeight); 1572 1573 err = mOMX->prepareForAdaptivePlayback( 1574 mNode, kPortIndexOutput, OMX_TRUE, maxWidth, 1575 maxHeight); 1576 ALOGW_IF(err != OK, 1577 "[%s] prepareForAdaptivePlayback failed w/ err %d", 1578 mComponentName.c_str(), err); 1579 1580 if (err == OK) { 1581 inputFormat->setInt32("max-width", maxWidth); 1582 inputFormat->setInt32("max-height", maxHeight); 1583 inputFormat->setInt32("adaptive-playback", true); 1584 } 1585 } 1586 // allow failure 1587 err = OK; 1588 } else { 1589 ALOGV("[%s] storeMetaDataInBuffers succeeded", 1590 mComponentName.c_str()); 1591 mStoreMetaDataInOutputBuffers = true; 1592 inputFormat->setInt32("adaptive-playback", true); 1593 } 1594 1595 int32_t push; 1596 if (msg->findInt32("push-blank-buffers-on-shutdown", &push) 1597 && push != 0) { 1598 mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown; 1599 } 1600 } 1601 1602 int32_t rotationDegrees; 1603 if (msg->findInt32("rotation-degrees", &rotationDegrees)) { 1604 mRotationDegrees = rotationDegrees; 1605 } else { 1606 mRotationDegrees = 0; 1607 } 1608 } 1609 1610 if (video) { 1611 // determine need for software renderer 1612 bool usingSwRenderer = false; 1613 if (haveNativeWindow && mComponentName.startsWith("OMX.google.")) { 1614 usingSwRenderer = true; 1615 haveNativeWindow = false; 1616 } 1617 1618 if (encoder) { 1619 err = setupVideoEncoder(mime, msg); 1620 } else { 1621 err = setupVideoDecoder(mime, msg, haveNativeWindow); 1622 } 1623 1624 if (err != OK) { 1625 return err; 1626 } 1627 1628 if (haveNativeWindow) { 1629 mNativeWindow = static_cast<Surface *>(obj.get()); 1630 CHECK(mNativeWindow != NULL); 1631 } 1632 1633 // initialize native window now to get actual output format 1634 // TODO: this is needed for some encoders even though they don't use native window 1635 CHECK_EQ((status_t)OK, initNativeWindow()); 1636 1637 // fallback for devices that do not handle flex-YUV for native buffers 1638 if (haveNativeWindow) { 1639 int32_t requestedColorFormat = OMX_COLOR_FormatUnused; 1640 if (msg->findInt32("color-format", &requestedColorFormat) && 1641 requestedColorFormat == OMX_COLOR_FormatYUV420Flexible) { 1642 CHECK_EQ(getPortFormat(kPortIndexOutput, outputFormat), (status_t)OK); 1643 int32_t colorFormat = OMX_COLOR_FormatUnused; 1644 OMX_U32 flexibleEquivalent = OMX_COLOR_FormatUnused; 1645 CHECK(outputFormat->findInt32("color-format", &colorFormat)); 1646 ALOGD("[%s] Requested output format %#x and got %#x.", 1647 mComponentName.c_str(), requestedColorFormat, colorFormat); 1648 if (!isFlexibleColorFormat( 1649 mOMX, mNode, colorFormat, haveNativeWindow, &flexibleEquivalent) 1650 || flexibleEquivalent != (OMX_U32)requestedColorFormat) { 1651 // device did not handle flex-YUV request for native window, fall back 1652 // to SW renderer 1653 ALOGI("[%s] Falling back to software renderer", mComponentName.c_str()); 1654 mNativeWindow.clear(); 1655 haveNativeWindow = false; 1656 usingSwRenderer = true; 1657 if (mStoreMetaDataInOutputBuffers) { 1658 err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, OMX_FALSE); 1659 mStoreMetaDataInOutputBuffers = false; 1660 // TODO: implement adaptive-playback support for bytebuffer mode. 1661 // This is done by SW codecs, but most HW codecs don't support it. 1662 inputFormat->setInt32("adaptive-playback", false); 1663 } 1664 if (err == OK) { 1665 err = mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE); 1666 } 1667 if (mFlags & kFlagIsGrallocUsageProtected) { 1668 // fallback is not supported for protected playback 1669 err = PERMISSION_DENIED; 1670 } else if (err == OK) { 1671 err = setupVideoDecoder(mime, msg, false); 1672 } 1673 } 1674 } 1675 } 1676 1677 if (usingSwRenderer) { 1678 outputFormat->setInt32("using-sw-renderer", 1); 1679 } 1680 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) { 1681 int32_t numChannels, sampleRate; 1682 if (!msg->findInt32("channel-count", &numChannels) 1683 || !msg->findInt32("sample-rate", &sampleRate)) { 1684 // Since we did not always check for these, leave them optional 1685 // and have the decoder figure it all out. 1686 err = OK; 1687 } else { 1688 err = setupRawAudioFormat( 1689 encoder ? kPortIndexInput : kPortIndexOutput, 1690 sampleRate, 1691 numChannels); 1692 } 1693 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 1694 int32_t numChannels, sampleRate; 1695 if (!msg->findInt32("channel-count", &numChannels) 1696 || !msg->findInt32("sample-rate", &sampleRate)) { 1697 err = INVALID_OPERATION; 1698 } else { 1699 int32_t isADTS, aacProfile; 1700 int32_t sbrMode; 1701 int32_t maxOutputChannelCount; 1702 int32_t pcmLimiterEnable; 1703 drcParams_t drc; 1704 if (!msg->findInt32("is-adts", &isADTS)) { 1705 isADTS = 0; 1706 } 1707 if (!msg->findInt32("aac-profile", &aacProfile)) { 1708 aacProfile = OMX_AUDIO_AACObjectNull; 1709 } 1710 if (!msg->findInt32("aac-sbr-mode", &sbrMode)) { 1711 sbrMode = -1; 1712 } 1713 1714 if (!msg->findInt32("aac-max-output-channel_count", &maxOutputChannelCount)) { 1715 maxOutputChannelCount = -1; 1716 } 1717 if (!msg->findInt32("aac-pcm-limiter-enable", &pcmLimiterEnable)) { 1718 // value is unknown 1719 pcmLimiterEnable = -1; 1720 } 1721 if (!msg->findInt32("aac-encoded-target-level", &drc.encodedTargetLevel)) { 1722 // value is unknown 1723 drc.encodedTargetLevel = -1; 1724 } 1725 if (!msg->findInt32("aac-drc-cut-level", &drc.drcCut)) { 1726 // value is unknown 1727 drc.drcCut = -1; 1728 } 1729 if (!msg->findInt32("aac-drc-boost-level", &drc.drcBoost)) { 1730 // value is unknown 1731 drc.drcBoost = -1; 1732 } 1733 if (!msg->findInt32("aac-drc-heavy-compression", &drc.heavyCompression)) { 1734 // value is unknown 1735 drc.heavyCompression = -1; 1736 } 1737 if (!msg->findInt32("aac-target-ref-level", &drc.targetRefLevel)) { 1738 // value is unknown 1739 drc.targetRefLevel = -1; 1740 } 1741 1742 err = setupAACCodec( 1743 encoder, numChannels, sampleRate, bitRate, aacProfile, 1744 isADTS != 0, sbrMode, maxOutputChannelCount, drc, 1745 pcmLimiterEnable); 1746 } 1747 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) { 1748 err = setupAMRCodec(encoder, false /* isWAMR */, bitRate); 1749 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) { 1750 err = setupAMRCodec(encoder, true /* isWAMR */, bitRate); 1751 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW) 1752 || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) { 1753 // These are PCM-like formats with a fixed sample rate but 1754 // a variable number of channels. 1755 1756 int32_t numChannels; 1757 if (!msg->findInt32("channel-count", &numChannels)) { 1758 err = INVALID_OPERATION; 1759 } else { 1760 int32_t sampleRate; 1761 if (!msg->findInt32("sample-rate", &sampleRate)) { 1762 sampleRate = 8000; 1763 } 1764 err = setupG711Codec(encoder, sampleRate, numChannels); 1765 } 1766 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) { 1767 int32_t numChannels = 0, sampleRate = 0, compressionLevel = -1; 1768 if (encoder && 1769 (!msg->findInt32("channel-count", &numChannels) 1770 || !msg->findInt32("sample-rate", &sampleRate))) { 1771 ALOGE("missing channel count or sample rate for FLAC encoder"); 1772 err = INVALID_OPERATION; 1773 } else { 1774 if (encoder) { 1775 if (!msg->findInt32( 1776 "complexity", &compressionLevel) && 1777 !msg->findInt32( 1778 "flac-compression-level", &compressionLevel)) { 1779 compressionLevel = 5; // default FLAC compression level 1780 } else if (compressionLevel < 0) { 1781 ALOGW("compression level %d outside [0..8] range, " 1782 "using 0", 1783 compressionLevel); 1784 compressionLevel = 0; 1785 } else if (compressionLevel > 8) { 1786 ALOGW("compression level %d outside [0..8] range, " 1787 "using 8", 1788 compressionLevel); 1789 compressionLevel = 8; 1790 } 1791 } 1792 err = setupFlacCodec( 1793 encoder, numChannels, sampleRate, compressionLevel); 1794 } 1795 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) { 1796 int32_t numChannels, sampleRate; 1797 if (encoder 1798 || !msg->findInt32("channel-count", &numChannels) 1799 || !msg->findInt32("sample-rate", &sampleRate)) { 1800 err = INVALID_OPERATION; 1801 } else { 1802 err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels); 1803 } 1804 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AC3)) { 1805 int32_t numChannels; 1806 int32_t sampleRate; 1807 if (!msg->findInt32("channel-count", &numChannels) 1808 || !msg->findInt32("sample-rate", &sampleRate)) { 1809 err = INVALID_OPERATION; 1810 } else { 1811 err = setupAC3Codec(encoder, numChannels, sampleRate); 1812 } 1813 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_EAC3)) { 1814 int32_t numChannels; 1815 int32_t sampleRate; 1816 if (!msg->findInt32("channel-count", &numChannels) 1817 || !msg->findInt32("sample-rate", &sampleRate)) { 1818 err = INVALID_OPERATION; 1819 } else { 1820 err = setupEAC3Codec(encoder, numChannels, sampleRate); 1821 } 1822 } 1823 1824 if (err != OK) { 1825 return err; 1826 } 1827 1828 if (!msg->findInt32("encoder-delay", &mEncoderDelay)) { 1829 mEncoderDelay = 0; 1830 } 1831 1832 if (!msg->findInt32("encoder-padding", &mEncoderPadding)) { 1833 mEncoderPadding = 0; 1834 } 1835 1836 if (msg->findInt32("channel-mask", &mChannelMask)) { 1837 mChannelMaskPresent = true; 1838 } else { 1839 mChannelMaskPresent = false; 1840 } 1841 1842 int32_t maxInputSize; 1843 if (msg->findInt32("max-input-size", &maxInputSize)) { 1844 err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize); 1845 } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) { 1846 err = setMinBufferSize(kPortIndexInput, 8192); // XXX 1847 } 1848 1849 int32_t priority; 1850 if (msg->findInt32("priority", &priority)) { 1851 err = setPriority(priority); 1852 } 1853 1854 int32_t rateInt = -1; 1855 float rateFloat = -1; 1856 if (!msg->findFloat("operating-rate", &rateFloat)) { 1857 msg->findInt32("operating-rate", &rateInt); 1858 rateFloat = (float)rateInt; // 16MHz (FLINTMAX) is OK for upper bound. 1859 } 1860 if (rateFloat > 0) { 1861 err = setOperatingRate(rateFloat, video); 1862 } 1863 1864 mBaseOutputFormat = outputFormat; 1865 1866 CHECK_EQ(getPortFormat(kPortIndexInput, inputFormat), (status_t)OK); 1867 CHECK_EQ(getPortFormat(kPortIndexOutput, outputFormat), (status_t)OK); 1868 mInputFormat = inputFormat; 1869 mOutputFormat = outputFormat; 1870 1871 return err; 1872} 1873 1874status_t ACodec::setPriority(int32_t priority) { 1875 if (priority < 0) { 1876 return BAD_VALUE; 1877 } 1878 OMX_PARAM_U32TYPE config; 1879 InitOMXParams(&config); 1880 config.nU32 = (OMX_U32)priority; 1881 status_t temp = mOMX->setConfig( 1882 mNode, (OMX_INDEXTYPE)OMX_IndexConfigPriority, 1883 &config, sizeof(config)); 1884 if (temp != OK) { 1885 ALOGI("codec does not support config priority (err %d)", temp); 1886 } 1887 return OK; 1888} 1889 1890status_t ACodec::setOperatingRate(float rateFloat, bool isVideo) { 1891 if (rateFloat < 0) { 1892 return BAD_VALUE; 1893 } 1894 OMX_U32 rate; 1895 if (isVideo) { 1896 if (rateFloat > 65535) { 1897 return BAD_VALUE; 1898 } 1899 rate = (OMX_U32)(rateFloat * 65536.0f + 0.5f); 1900 } else { 1901 if (rateFloat > UINT_MAX) { 1902 return BAD_VALUE; 1903 } 1904 rate = (OMX_U32)(rateFloat); 1905 } 1906 OMX_PARAM_U32TYPE config; 1907 InitOMXParams(&config); 1908 config.nU32 = rate; 1909 status_t err = mOMX->setConfig( 1910 mNode, (OMX_INDEXTYPE)OMX_IndexConfigOperatingRate, 1911 &config, sizeof(config)); 1912 if (err != OK) { 1913 ALOGI("codec does not support config operating rate (err %d)", err); 1914 } 1915 return OK; 1916} 1917 1918status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) { 1919 OMX_PARAM_PORTDEFINITIONTYPE def; 1920 InitOMXParams(&def); 1921 def.nPortIndex = portIndex; 1922 1923 status_t err = mOMX->getParameter( 1924 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1925 1926 if (err != OK) { 1927 return err; 1928 } 1929 1930 if (def.nBufferSize >= size) { 1931 return OK; 1932 } 1933 1934 def.nBufferSize = size; 1935 1936 err = mOMX->setParameter( 1937 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1938 1939 if (err != OK) { 1940 return err; 1941 } 1942 1943 err = mOMX->getParameter( 1944 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1945 1946 if (err != OK) { 1947 return err; 1948 } 1949 1950 CHECK(def.nBufferSize >= size); 1951 1952 return OK; 1953} 1954 1955status_t ACodec::selectAudioPortFormat( 1956 OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) { 1957 OMX_AUDIO_PARAM_PORTFORMATTYPE format; 1958 InitOMXParams(&format); 1959 1960 format.nPortIndex = portIndex; 1961 for (OMX_U32 index = 0;; ++index) { 1962 format.nIndex = index; 1963 1964 status_t err = mOMX->getParameter( 1965 mNode, OMX_IndexParamAudioPortFormat, 1966 &format, sizeof(format)); 1967 1968 if (err != OK) { 1969 return err; 1970 } 1971 1972 if (format.eEncoding == desiredFormat) { 1973 break; 1974 } 1975 } 1976 1977 return mOMX->setParameter( 1978 mNode, OMX_IndexParamAudioPortFormat, &format, sizeof(format)); 1979} 1980 1981status_t ACodec::setupAACCodec( 1982 bool encoder, int32_t numChannels, int32_t sampleRate, 1983 int32_t bitRate, int32_t aacProfile, bool isADTS, int32_t sbrMode, 1984 int32_t maxOutputChannelCount, const drcParams_t& drc, 1985 int32_t pcmLimiterEnable) { 1986 if (encoder && isADTS) { 1987 return -EINVAL; 1988 } 1989 1990 status_t err = setupRawAudioFormat( 1991 encoder ? kPortIndexInput : kPortIndexOutput, 1992 sampleRate, 1993 numChannels); 1994 1995 if (err != OK) { 1996 return err; 1997 } 1998 1999 if (encoder) { 2000 err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC); 2001 2002 if (err != OK) { 2003 return err; 2004 } 2005 2006 OMX_PARAM_PORTDEFINITIONTYPE def; 2007 InitOMXParams(&def); 2008 def.nPortIndex = kPortIndexOutput; 2009 2010 err = mOMX->getParameter( 2011 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2012 2013 if (err != OK) { 2014 return err; 2015 } 2016 2017 def.format.audio.bFlagErrorConcealment = OMX_TRUE; 2018 def.format.audio.eEncoding = OMX_AUDIO_CodingAAC; 2019 2020 err = mOMX->setParameter( 2021 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2022 2023 if (err != OK) { 2024 return err; 2025 } 2026 2027 OMX_AUDIO_PARAM_AACPROFILETYPE profile; 2028 InitOMXParams(&profile); 2029 profile.nPortIndex = kPortIndexOutput; 2030 2031 err = mOMX->getParameter( 2032 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 2033 2034 if (err != OK) { 2035 return err; 2036 } 2037 2038 profile.nChannels = numChannels; 2039 2040 profile.eChannelMode = 2041 (numChannels == 1) 2042 ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo; 2043 2044 profile.nSampleRate = sampleRate; 2045 profile.nBitRate = bitRate; 2046 profile.nAudioBandWidth = 0; 2047 profile.nFrameLength = 0; 2048 profile.nAACtools = OMX_AUDIO_AACToolAll; 2049 profile.nAACERtools = OMX_AUDIO_AACERNone; 2050 profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile; 2051 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF; 2052 switch (sbrMode) { 2053 case 0: 2054 // disable sbr 2055 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR; 2056 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR; 2057 break; 2058 case 1: 2059 // enable single-rate sbr 2060 profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR; 2061 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR; 2062 break; 2063 case 2: 2064 // enable dual-rate sbr 2065 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR; 2066 profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR; 2067 break; 2068 case -1: 2069 // enable both modes -> the codec will decide which mode should be used 2070 profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR; 2071 profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR; 2072 break; 2073 default: 2074 // unsupported sbr mode 2075 return BAD_VALUE; 2076 } 2077 2078 2079 err = mOMX->setParameter( 2080 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 2081 2082 if (err != OK) { 2083 return err; 2084 } 2085 2086 return err; 2087 } 2088 2089 OMX_AUDIO_PARAM_AACPROFILETYPE profile; 2090 InitOMXParams(&profile); 2091 profile.nPortIndex = kPortIndexInput; 2092 2093 err = mOMX->getParameter( 2094 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 2095 2096 if (err != OK) { 2097 return err; 2098 } 2099 2100 profile.nChannels = numChannels; 2101 profile.nSampleRate = sampleRate; 2102 2103 profile.eAACStreamFormat = 2104 isADTS 2105 ? OMX_AUDIO_AACStreamFormatMP4ADTS 2106 : OMX_AUDIO_AACStreamFormatMP4FF; 2107 2108 OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE presentation; 2109 presentation.nMaxOutputChannels = maxOutputChannelCount; 2110 presentation.nDrcCut = drc.drcCut; 2111 presentation.nDrcBoost = drc.drcBoost; 2112 presentation.nHeavyCompression = drc.heavyCompression; 2113 presentation.nTargetReferenceLevel = drc.targetRefLevel; 2114 presentation.nEncodedTargetLevel = drc.encodedTargetLevel; 2115 presentation.nPCMLimiterEnable = pcmLimiterEnable; 2116 2117 status_t res = mOMX->setParameter(mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 2118 if (res == OK) { 2119 // optional parameters, will not cause configuration failure 2120 mOMX->setParameter(mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacPresentation, 2121 &presentation, sizeof(presentation)); 2122 } else { 2123 ALOGW("did not set AudioAndroidAacPresentation due to error %d when setting AudioAac", res); 2124 } 2125 return res; 2126} 2127 2128status_t ACodec::setupAC3Codec( 2129 bool encoder, int32_t numChannels, int32_t sampleRate) { 2130 status_t err = setupRawAudioFormat( 2131 encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels); 2132 2133 if (err != OK) { 2134 return err; 2135 } 2136 2137 if (encoder) { 2138 ALOGW("AC3 encoding is not supported."); 2139 return INVALID_OPERATION; 2140 } 2141 2142 OMX_AUDIO_PARAM_ANDROID_AC3TYPE def; 2143 InitOMXParams(&def); 2144 def.nPortIndex = kPortIndexInput; 2145 2146 err = mOMX->getParameter( 2147 mNode, 2148 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, 2149 &def, 2150 sizeof(def)); 2151 2152 if (err != OK) { 2153 return err; 2154 } 2155 2156 def.nChannels = numChannels; 2157 def.nSampleRate = sampleRate; 2158 2159 return mOMX->setParameter( 2160 mNode, 2161 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, 2162 &def, 2163 sizeof(def)); 2164} 2165 2166status_t ACodec::setupEAC3Codec( 2167 bool encoder, int32_t numChannels, int32_t sampleRate) { 2168 status_t err = setupRawAudioFormat( 2169 encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels); 2170 2171 if (err != OK) { 2172 return err; 2173 } 2174 2175 if (encoder) { 2176 ALOGW("EAC3 encoding is not supported."); 2177 return INVALID_OPERATION; 2178 } 2179 2180 OMX_AUDIO_PARAM_ANDROID_EAC3TYPE def; 2181 InitOMXParams(&def); 2182 def.nPortIndex = kPortIndexInput; 2183 2184 err = mOMX->getParameter( 2185 mNode, 2186 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, 2187 &def, 2188 sizeof(def)); 2189 2190 if (err != OK) { 2191 return err; 2192 } 2193 2194 def.nChannels = numChannels; 2195 def.nSampleRate = sampleRate; 2196 2197 return mOMX->setParameter( 2198 mNode, 2199 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, 2200 &def, 2201 sizeof(def)); 2202} 2203 2204static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate( 2205 bool isAMRWB, int32_t bps) { 2206 if (isAMRWB) { 2207 if (bps <= 6600) { 2208 return OMX_AUDIO_AMRBandModeWB0; 2209 } else if (bps <= 8850) { 2210 return OMX_AUDIO_AMRBandModeWB1; 2211 } else if (bps <= 12650) { 2212 return OMX_AUDIO_AMRBandModeWB2; 2213 } else if (bps <= 14250) { 2214 return OMX_AUDIO_AMRBandModeWB3; 2215 } else if (bps <= 15850) { 2216 return OMX_AUDIO_AMRBandModeWB4; 2217 } else if (bps <= 18250) { 2218 return OMX_AUDIO_AMRBandModeWB5; 2219 } else if (bps <= 19850) { 2220 return OMX_AUDIO_AMRBandModeWB6; 2221 } else if (bps <= 23050) { 2222 return OMX_AUDIO_AMRBandModeWB7; 2223 } 2224 2225 // 23850 bps 2226 return OMX_AUDIO_AMRBandModeWB8; 2227 } else { // AMRNB 2228 if (bps <= 4750) { 2229 return OMX_AUDIO_AMRBandModeNB0; 2230 } else if (bps <= 5150) { 2231 return OMX_AUDIO_AMRBandModeNB1; 2232 } else if (bps <= 5900) { 2233 return OMX_AUDIO_AMRBandModeNB2; 2234 } else if (bps <= 6700) { 2235 return OMX_AUDIO_AMRBandModeNB3; 2236 } else if (bps <= 7400) { 2237 return OMX_AUDIO_AMRBandModeNB4; 2238 } else if (bps <= 7950) { 2239 return OMX_AUDIO_AMRBandModeNB5; 2240 } else if (bps <= 10200) { 2241 return OMX_AUDIO_AMRBandModeNB6; 2242 } 2243 2244 // 12200 bps 2245 return OMX_AUDIO_AMRBandModeNB7; 2246 } 2247} 2248 2249status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) { 2250 OMX_AUDIO_PARAM_AMRTYPE def; 2251 InitOMXParams(&def); 2252 def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput; 2253 2254 status_t err = 2255 mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); 2256 2257 if (err != OK) { 2258 return err; 2259 } 2260 2261 def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF; 2262 def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate); 2263 2264 err = mOMX->setParameter( 2265 mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); 2266 2267 if (err != OK) { 2268 return err; 2269 } 2270 2271 return setupRawAudioFormat( 2272 encoder ? kPortIndexInput : kPortIndexOutput, 2273 isWAMR ? 16000 : 8000 /* sampleRate */, 2274 1 /* numChannels */); 2275} 2276 2277status_t ACodec::setupG711Codec(bool encoder, int32_t sampleRate, int32_t numChannels) { 2278 CHECK(!encoder); // XXX TODO 2279 2280 return setupRawAudioFormat( 2281 kPortIndexInput, sampleRate, numChannels); 2282} 2283 2284status_t ACodec::setupFlacCodec( 2285 bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel) { 2286 2287 if (encoder) { 2288 OMX_AUDIO_PARAM_FLACTYPE def; 2289 InitOMXParams(&def); 2290 def.nPortIndex = kPortIndexOutput; 2291 2292 // configure compression level 2293 status_t err = mOMX->getParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def)); 2294 if (err != OK) { 2295 ALOGE("setupFlacCodec(): Error %d getting OMX_IndexParamAudioFlac parameter", err); 2296 return err; 2297 } 2298 def.nCompressionLevel = compressionLevel; 2299 err = mOMX->setParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def)); 2300 if (err != OK) { 2301 ALOGE("setupFlacCodec(): Error %d setting OMX_IndexParamAudioFlac parameter", err); 2302 return err; 2303 } 2304 } 2305 2306 return setupRawAudioFormat( 2307 encoder ? kPortIndexInput : kPortIndexOutput, 2308 sampleRate, 2309 numChannels); 2310} 2311 2312status_t ACodec::setupRawAudioFormat( 2313 OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) { 2314 OMX_PARAM_PORTDEFINITIONTYPE def; 2315 InitOMXParams(&def); 2316 def.nPortIndex = portIndex; 2317 2318 status_t err = mOMX->getParameter( 2319 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2320 2321 if (err != OK) { 2322 return err; 2323 } 2324 2325 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; 2326 2327 err = mOMX->setParameter( 2328 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2329 2330 if (err != OK) { 2331 return err; 2332 } 2333 2334 OMX_AUDIO_PARAM_PCMMODETYPE pcmParams; 2335 InitOMXParams(&pcmParams); 2336 pcmParams.nPortIndex = portIndex; 2337 2338 err = mOMX->getParameter( 2339 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); 2340 2341 if (err != OK) { 2342 return err; 2343 } 2344 2345 pcmParams.nChannels = numChannels; 2346 pcmParams.eNumData = OMX_NumericalDataSigned; 2347 pcmParams.bInterleaved = OMX_TRUE; 2348 pcmParams.nBitPerSample = 16; 2349 pcmParams.nSamplingRate = sampleRate; 2350 pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear; 2351 2352 if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) { 2353 return OMX_ErrorNone; 2354 } 2355 2356 return mOMX->setParameter( 2357 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); 2358} 2359 2360status_t ACodec::configureTunneledVideoPlayback( 2361 int32_t audioHwSync, const sp<ANativeWindow> &nativeWindow) { 2362 native_handle_t* sidebandHandle; 2363 2364 status_t err = mOMX->configureVideoTunnelMode( 2365 mNode, kPortIndexOutput, OMX_TRUE, audioHwSync, &sidebandHandle); 2366 if (err != OK) { 2367 ALOGE("configureVideoTunnelMode failed! (err %d).", err); 2368 return err; 2369 } 2370 2371 err = native_window_set_sideband_stream(nativeWindow.get(), sidebandHandle); 2372 if (err != OK) { 2373 ALOGE("native_window_set_sideband_stream(%p) failed! (err %d).", 2374 sidebandHandle, err); 2375 return err; 2376 } 2377 2378 return OK; 2379} 2380 2381status_t ACodec::setVideoPortFormatType( 2382 OMX_U32 portIndex, 2383 OMX_VIDEO_CODINGTYPE compressionFormat, 2384 OMX_COLOR_FORMATTYPE colorFormat, 2385 bool usingNativeBuffers) { 2386 OMX_VIDEO_PARAM_PORTFORMATTYPE format; 2387 InitOMXParams(&format); 2388 format.nPortIndex = portIndex; 2389 format.nIndex = 0; 2390 bool found = false; 2391 2392 OMX_U32 index = 0; 2393 for (;;) { 2394 format.nIndex = index; 2395 status_t err = mOMX->getParameter( 2396 mNode, OMX_IndexParamVideoPortFormat, 2397 &format, sizeof(format)); 2398 2399 if (err != OK) { 2400 return err; 2401 } 2402 2403 // substitute back flexible color format to codec supported format 2404 OMX_U32 flexibleEquivalent; 2405 if (compressionFormat == OMX_VIDEO_CodingUnused 2406 && isFlexibleColorFormat( 2407 mOMX, mNode, format.eColorFormat, usingNativeBuffers, &flexibleEquivalent) 2408 && colorFormat == flexibleEquivalent) { 2409 ALOGI("[%s] using color format %#x in place of %#x", 2410 mComponentName.c_str(), format.eColorFormat, colorFormat); 2411 colorFormat = format.eColorFormat; 2412 } 2413 2414 // The following assertion is violated by TI's video decoder. 2415 // CHECK_EQ(format.nIndex, index); 2416 2417 if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) { 2418 if (portIndex == kPortIndexInput 2419 && colorFormat == format.eColorFormat) { 2420 // eCompressionFormat does not seem right. 2421 found = true; 2422 break; 2423 } 2424 if (portIndex == kPortIndexOutput 2425 && compressionFormat == format.eCompressionFormat) { 2426 // eColorFormat does not seem right. 2427 found = true; 2428 break; 2429 } 2430 } 2431 2432 if (format.eCompressionFormat == compressionFormat 2433 && format.eColorFormat == colorFormat) { 2434 found = true; 2435 break; 2436 } 2437 2438 ++index; 2439 } 2440 2441 if (!found) { 2442 return UNKNOWN_ERROR; 2443 } 2444 2445 status_t err = mOMX->setParameter( 2446 mNode, OMX_IndexParamVideoPortFormat, 2447 &format, sizeof(format)); 2448 2449 return err; 2450} 2451 2452// Set optimal output format. OMX component lists output formats in the order 2453// of preference, but this got more complicated since the introduction of flexible 2454// YUV formats. We support a legacy behavior for applications that do not use 2455// surface output, do not specify an output format, but expect a "usable" standard 2456// OMX format. SW readable and standard formats must be flex-YUV. 2457// 2458// Suggested preference order: 2459// - optimal format for texture rendering (mediaplayer behavior) 2460// - optimal SW readable & texture renderable format (flex-YUV support) 2461// - optimal SW readable non-renderable format (flex-YUV bytebuffer support) 2462// - legacy "usable" standard formats 2463// 2464// For legacy support, we prefer a standard format, but will settle for a SW readable 2465// flex-YUV format. 2466status_t ACodec::setSupportedOutputFormat(bool getLegacyFlexibleFormat) { 2467 OMX_VIDEO_PARAM_PORTFORMATTYPE format, legacyFormat; 2468 InitOMXParams(&format); 2469 format.nPortIndex = kPortIndexOutput; 2470 2471 InitOMXParams(&legacyFormat); 2472 // this field will change when we find a suitable legacy format 2473 legacyFormat.eColorFormat = OMX_COLOR_FormatUnused; 2474 2475 for (OMX_U32 index = 0; ; ++index) { 2476 format.nIndex = index; 2477 status_t err = mOMX->getParameter( 2478 mNode, OMX_IndexParamVideoPortFormat, 2479 &format, sizeof(format)); 2480 if (err != OK) { 2481 // no more formats, pick legacy format if found 2482 if (legacyFormat.eColorFormat != OMX_COLOR_FormatUnused) { 2483 memcpy(&format, &legacyFormat, sizeof(format)); 2484 break; 2485 } 2486 return err; 2487 } 2488 if (format.eCompressionFormat != OMX_VIDEO_CodingUnused) { 2489 return OMX_ErrorBadParameter; 2490 } 2491 if (!getLegacyFlexibleFormat) { 2492 break; 2493 } 2494 // standard formats that were exposed to users before 2495 if (format.eColorFormat == OMX_COLOR_FormatYUV420Planar 2496 || format.eColorFormat == OMX_COLOR_FormatYUV420PackedPlanar 2497 || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar 2498 || format.eColorFormat == OMX_COLOR_FormatYUV420PackedSemiPlanar 2499 || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar) { 2500 break; 2501 } 2502 // find best legacy non-standard format 2503 OMX_U32 flexibleEquivalent; 2504 if (legacyFormat.eColorFormat == OMX_COLOR_FormatUnused 2505 && isFlexibleColorFormat( 2506 mOMX, mNode, format.eColorFormat, false /* usingNativeBuffers */, 2507 &flexibleEquivalent) 2508 && flexibleEquivalent == OMX_COLOR_FormatYUV420Flexible) { 2509 memcpy(&legacyFormat, &format, sizeof(format)); 2510 } 2511 } 2512 return mOMX->setParameter( 2513 mNode, OMX_IndexParamVideoPortFormat, 2514 &format, sizeof(format)); 2515} 2516 2517static const struct VideoCodingMapEntry { 2518 const char *mMime; 2519 OMX_VIDEO_CODINGTYPE mVideoCodingType; 2520} kVideoCodingMapEntry[] = { 2521 { MEDIA_MIMETYPE_VIDEO_AVC, OMX_VIDEO_CodingAVC }, 2522 { MEDIA_MIMETYPE_VIDEO_HEVC, OMX_VIDEO_CodingHEVC }, 2523 { MEDIA_MIMETYPE_VIDEO_MPEG4, OMX_VIDEO_CodingMPEG4 }, 2524 { MEDIA_MIMETYPE_VIDEO_H263, OMX_VIDEO_CodingH263 }, 2525 { MEDIA_MIMETYPE_VIDEO_MPEG2, OMX_VIDEO_CodingMPEG2 }, 2526 { MEDIA_MIMETYPE_VIDEO_VP8, OMX_VIDEO_CodingVP8 }, 2527 { MEDIA_MIMETYPE_VIDEO_VP9, OMX_VIDEO_CodingVP9 }, 2528}; 2529 2530static status_t GetVideoCodingTypeFromMime( 2531 const char *mime, OMX_VIDEO_CODINGTYPE *codingType) { 2532 for (size_t i = 0; 2533 i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]); 2534 ++i) { 2535 if (!strcasecmp(mime, kVideoCodingMapEntry[i].mMime)) { 2536 *codingType = kVideoCodingMapEntry[i].mVideoCodingType; 2537 return OK; 2538 } 2539 } 2540 2541 *codingType = OMX_VIDEO_CodingUnused; 2542 2543 return ERROR_UNSUPPORTED; 2544} 2545 2546static status_t GetMimeTypeForVideoCoding( 2547 OMX_VIDEO_CODINGTYPE codingType, AString *mime) { 2548 for (size_t i = 0; 2549 i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]); 2550 ++i) { 2551 if (codingType == kVideoCodingMapEntry[i].mVideoCodingType) { 2552 *mime = kVideoCodingMapEntry[i].mMime; 2553 return OK; 2554 } 2555 } 2556 2557 mime->clear(); 2558 2559 return ERROR_UNSUPPORTED; 2560} 2561 2562status_t ACodec::setupVideoDecoder( 2563 const char *mime, const sp<AMessage> &msg, bool haveNativeWindow) { 2564 int32_t width, height; 2565 if (!msg->findInt32("width", &width) 2566 || !msg->findInt32("height", &height)) { 2567 return INVALID_OPERATION; 2568 } 2569 2570 OMX_VIDEO_CODINGTYPE compressionFormat; 2571 status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat); 2572 2573 if (err != OK) { 2574 return err; 2575 } 2576 2577 err = setVideoPortFormatType( 2578 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused); 2579 2580 if (err != OK) { 2581 return err; 2582 } 2583 2584 int32_t tmp; 2585 if (msg->findInt32("color-format", &tmp)) { 2586 OMX_COLOR_FORMATTYPE colorFormat = 2587 static_cast<OMX_COLOR_FORMATTYPE>(tmp); 2588 err = setVideoPortFormatType( 2589 kPortIndexOutput, OMX_VIDEO_CodingUnused, colorFormat, haveNativeWindow); 2590 if (err != OK) { 2591 ALOGW("[%s] does not support color format %d", 2592 mComponentName.c_str(), colorFormat); 2593 err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */); 2594 } 2595 } else { 2596 err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */); 2597 } 2598 2599 if (err != OK) { 2600 return err; 2601 } 2602 2603 int32_t frameRateInt; 2604 float frameRateFloat; 2605 if (!msg->findFloat("frame-rate", &frameRateFloat)) { 2606 if (!msg->findInt32("frame-rate", &frameRateInt)) { 2607 frameRateInt = -1; 2608 } 2609 frameRateFloat = (float)frameRateInt; 2610 } 2611 2612 err = setVideoFormatOnPort( 2613 kPortIndexInput, width, height, compressionFormat, frameRateFloat); 2614 2615 if (err != OK) { 2616 return err; 2617 } 2618 2619 err = setVideoFormatOnPort( 2620 kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused); 2621 2622 if (err != OK) { 2623 return err; 2624 } 2625 2626 return OK; 2627} 2628 2629status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) { 2630 int32_t tmp; 2631 if (!msg->findInt32("color-format", &tmp)) { 2632 return INVALID_OPERATION; 2633 } 2634 2635 OMX_COLOR_FORMATTYPE colorFormat = 2636 static_cast<OMX_COLOR_FORMATTYPE>(tmp); 2637 2638 status_t err = setVideoPortFormatType( 2639 kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat); 2640 2641 if (err != OK) { 2642 ALOGE("[%s] does not support color format %d", 2643 mComponentName.c_str(), colorFormat); 2644 2645 return err; 2646 } 2647 2648 /* Input port configuration */ 2649 2650 OMX_PARAM_PORTDEFINITIONTYPE def; 2651 InitOMXParams(&def); 2652 2653 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 2654 2655 def.nPortIndex = kPortIndexInput; 2656 2657 err = mOMX->getParameter( 2658 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2659 2660 if (err != OK) { 2661 return err; 2662 } 2663 2664 int32_t width, height, bitrate; 2665 if (!msg->findInt32("width", &width) 2666 || !msg->findInt32("height", &height) 2667 || !msg->findInt32("bitrate", &bitrate)) { 2668 return INVALID_OPERATION; 2669 } 2670 2671 video_def->nFrameWidth = width; 2672 video_def->nFrameHeight = height; 2673 2674 int32_t stride; 2675 if (!msg->findInt32("stride", &stride)) { 2676 stride = width; 2677 } 2678 2679 video_def->nStride = stride; 2680 2681 int32_t sliceHeight; 2682 if (!msg->findInt32("slice-height", &sliceHeight)) { 2683 sliceHeight = height; 2684 } 2685 2686 video_def->nSliceHeight = sliceHeight; 2687 2688 def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2; 2689 2690 float frameRate; 2691 if (!msg->findFloat("frame-rate", &frameRate)) { 2692 int32_t tmp; 2693 if (!msg->findInt32("frame-rate", &tmp)) { 2694 return INVALID_OPERATION; 2695 } 2696 frameRate = (float)tmp; 2697 mTimePerFrameUs = (int64_t) (1000000.0f / frameRate); 2698 } 2699 2700 video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f); 2701 video_def->eCompressionFormat = OMX_VIDEO_CodingUnused; 2702 // this is redundant as it was already set up in setVideoPortFormatType 2703 // FIXME for now skip this only for flexible YUV formats 2704 if (colorFormat != OMX_COLOR_FormatYUV420Flexible) { 2705 video_def->eColorFormat = colorFormat; 2706 } 2707 2708 err = mOMX->setParameter( 2709 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2710 2711 if (err != OK) { 2712 ALOGE("[%s] failed to set input port definition parameters.", 2713 mComponentName.c_str()); 2714 2715 return err; 2716 } 2717 2718 /* Output port configuration */ 2719 2720 OMX_VIDEO_CODINGTYPE compressionFormat; 2721 err = GetVideoCodingTypeFromMime(mime, &compressionFormat); 2722 2723 if (err != OK) { 2724 return err; 2725 } 2726 2727 err = setVideoPortFormatType( 2728 kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused); 2729 2730 if (err != OK) { 2731 ALOGE("[%s] does not support compression format %d", 2732 mComponentName.c_str(), compressionFormat); 2733 2734 return err; 2735 } 2736 2737 def.nPortIndex = kPortIndexOutput; 2738 2739 err = mOMX->getParameter( 2740 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2741 2742 if (err != OK) { 2743 return err; 2744 } 2745 2746 video_def->nFrameWidth = width; 2747 video_def->nFrameHeight = height; 2748 video_def->xFramerate = 0; 2749 video_def->nBitrate = bitrate; 2750 video_def->eCompressionFormat = compressionFormat; 2751 video_def->eColorFormat = OMX_COLOR_FormatUnused; 2752 2753 err = mOMX->setParameter( 2754 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2755 2756 if (err != OK) { 2757 ALOGE("[%s] failed to set output port definition parameters.", 2758 mComponentName.c_str()); 2759 2760 return err; 2761 } 2762 2763 switch (compressionFormat) { 2764 case OMX_VIDEO_CodingMPEG4: 2765 err = setupMPEG4EncoderParameters(msg); 2766 break; 2767 2768 case OMX_VIDEO_CodingH263: 2769 err = setupH263EncoderParameters(msg); 2770 break; 2771 2772 case OMX_VIDEO_CodingAVC: 2773 err = setupAVCEncoderParameters(msg); 2774 break; 2775 2776 case OMX_VIDEO_CodingHEVC: 2777 err = setupHEVCEncoderParameters(msg); 2778 break; 2779 2780 case OMX_VIDEO_CodingVP8: 2781 case OMX_VIDEO_CodingVP9: 2782 err = setupVPXEncoderParameters(msg); 2783 break; 2784 2785 default: 2786 break; 2787 } 2788 2789 ALOGI("setupVideoEncoder succeeded"); 2790 2791 return err; 2792} 2793 2794status_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) { 2795 OMX_VIDEO_PARAM_INTRAREFRESHTYPE params; 2796 InitOMXParams(¶ms); 2797 params.nPortIndex = kPortIndexOutput; 2798 2799 params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode); 2800 2801 if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic || 2802 params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) { 2803 int32_t mbs; 2804 if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) { 2805 return INVALID_OPERATION; 2806 } 2807 params.nCirMBs = mbs; 2808 } 2809 2810 if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive || 2811 params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) { 2812 int32_t mbs; 2813 if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) { 2814 return INVALID_OPERATION; 2815 } 2816 params.nAirMBs = mbs; 2817 2818 int32_t ref; 2819 if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) { 2820 return INVALID_OPERATION; 2821 } 2822 params.nAirRef = ref; 2823 } 2824 2825 status_t err = mOMX->setParameter( 2826 mNode, OMX_IndexParamVideoIntraRefresh, 2827 ¶ms, sizeof(params)); 2828 return err; 2829} 2830 2831static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) { 2832 if (iFramesInterval < 0) { 2833 return 0xFFFFFFFF; 2834 } else if (iFramesInterval == 0) { 2835 return 0; 2836 } 2837 OMX_U32 ret = frameRate * iFramesInterval; 2838 return ret; 2839} 2840 2841static OMX_VIDEO_CONTROLRATETYPE getBitrateMode(const sp<AMessage> &msg) { 2842 int32_t tmp; 2843 if (!msg->findInt32("bitrate-mode", &tmp)) { 2844 return OMX_Video_ControlRateVariable; 2845 } 2846 2847 return static_cast<OMX_VIDEO_CONTROLRATETYPE>(tmp); 2848} 2849 2850status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) { 2851 int32_t bitrate, iFrameInterval; 2852 if (!msg->findInt32("bitrate", &bitrate) 2853 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 2854 return INVALID_OPERATION; 2855 } 2856 2857 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 2858 2859 float frameRate; 2860 if (!msg->findFloat("frame-rate", &frameRate)) { 2861 int32_t tmp; 2862 if (!msg->findInt32("frame-rate", &tmp)) { 2863 return INVALID_OPERATION; 2864 } 2865 frameRate = (float)tmp; 2866 } 2867 2868 OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type; 2869 InitOMXParams(&mpeg4type); 2870 mpeg4type.nPortIndex = kPortIndexOutput; 2871 2872 status_t err = mOMX->getParameter( 2873 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); 2874 2875 if (err != OK) { 2876 return err; 2877 } 2878 2879 mpeg4type.nSliceHeaderSpacing = 0; 2880 mpeg4type.bSVH = OMX_FALSE; 2881 mpeg4type.bGov = OMX_FALSE; 2882 2883 mpeg4type.nAllowedPictureTypes = 2884 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 2885 2886 mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 2887 if (mpeg4type.nPFrames == 0) { 2888 mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 2889 } 2890 mpeg4type.nBFrames = 0; 2891 mpeg4type.nIDCVLCThreshold = 0; 2892 mpeg4type.bACPred = OMX_TRUE; 2893 mpeg4type.nMaxPacketSize = 256; 2894 mpeg4type.nTimeIncRes = 1000; 2895 mpeg4type.nHeaderExtension = 0; 2896 mpeg4type.bReversibleVLC = OMX_FALSE; 2897 2898 int32_t profile; 2899 if (msg->findInt32("profile", &profile)) { 2900 int32_t level; 2901 if (!msg->findInt32("level", &level)) { 2902 return INVALID_OPERATION; 2903 } 2904 2905 err = verifySupportForProfileAndLevel(profile, level); 2906 2907 if (err != OK) { 2908 return err; 2909 } 2910 2911 mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile); 2912 mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level); 2913 } 2914 2915 err = mOMX->setParameter( 2916 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); 2917 2918 if (err != OK) { 2919 return err; 2920 } 2921 2922 err = configureBitrate(bitrate, bitrateMode); 2923 2924 if (err != OK) { 2925 return err; 2926 } 2927 2928 return setupErrorCorrectionParameters(); 2929} 2930 2931status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) { 2932 int32_t bitrate, iFrameInterval; 2933 if (!msg->findInt32("bitrate", &bitrate) 2934 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 2935 return INVALID_OPERATION; 2936 } 2937 2938 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 2939 2940 float frameRate; 2941 if (!msg->findFloat("frame-rate", &frameRate)) { 2942 int32_t tmp; 2943 if (!msg->findInt32("frame-rate", &tmp)) { 2944 return INVALID_OPERATION; 2945 } 2946 frameRate = (float)tmp; 2947 } 2948 2949 OMX_VIDEO_PARAM_H263TYPE h263type; 2950 InitOMXParams(&h263type); 2951 h263type.nPortIndex = kPortIndexOutput; 2952 2953 status_t err = mOMX->getParameter( 2954 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); 2955 2956 if (err != OK) { 2957 return err; 2958 } 2959 2960 h263type.nAllowedPictureTypes = 2961 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 2962 2963 h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 2964 if (h263type.nPFrames == 0) { 2965 h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 2966 } 2967 h263type.nBFrames = 0; 2968 2969 int32_t profile; 2970 if (msg->findInt32("profile", &profile)) { 2971 int32_t level; 2972 if (!msg->findInt32("level", &level)) { 2973 return INVALID_OPERATION; 2974 } 2975 2976 err = verifySupportForProfileAndLevel(profile, level); 2977 2978 if (err != OK) { 2979 return err; 2980 } 2981 2982 h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile); 2983 h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level); 2984 } 2985 2986 h263type.bPLUSPTYPEAllowed = OMX_FALSE; 2987 h263type.bForceRoundingTypeToZero = OMX_FALSE; 2988 h263type.nPictureHeaderRepetition = 0; 2989 h263type.nGOBHeaderInterval = 0; 2990 2991 err = mOMX->setParameter( 2992 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); 2993 2994 if (err != OK) { 2995 return err; 2996 } 2997 2998 err = configureBitrate(bitrate, bitrateMode); 2999 3000 if (err != OK) { 3001 return err; 3002 } 3003 3004 return setupErrorCorrectionParameters(); 3005} 3006 3007// static 3008int /* OMX_VIDEO_AVCLEVELTYPE */ ACodec::getAVCLevelFor( 3009 int width, int height, int rate, int bitrate, 3010 OMX_VIDEO_AVCPROFILETYPE profile) { 3011 // convert bitrate to main/baseline profile kbps equivalent 3012 switch (profile) { 3013 case OMX_VIDEO_AVCProfileHigh10: 3014 bitrate = divUp(bitrate, 3000); break; 3015 case OMX_VIDEO_AVCProfileHigh: 3016 bitrate = divUp(bitrate, 1250); break; 3017 default: 3018 bitrate = divUp(bitrate, 1000); break; 3019 } 3020 3021 // convert size and rate to MBs 3022 width = divUp(width, 16); 3023 height = divUp(height, 16); 3024 int mbs = width * height; 3025 rate *= mbs; 3026 int maxDimension = max(width, height); 3027 3028 static const int limits[][5] = { 3029 /* MBps MB dim bitrate level */ 3030 { 1485, 99, 28, 64, OMX_VIDEO_AVCLevel1 }, 3031 { 1485, 99, 28, 128, OMX_VIDEO_AVCLevel1b }, 3032 { 3000, 396, 56, 192, OMX_VIDEO_AVCLevel11 }, 3033 { 6000, 396, 56, 384, OMX_VIDEO_AVCLevel12 }, 3034 { 11880, 396, 56, 768, OMX_VIDEO_AVCLevel13 }, 3035 { 11880, 396, 56, 2000, OMX_VIDEO_AVCLevel2 }, 3036 { 19800, 792, 79, 4000, OMX_VIDEO_AVCLevel21 }, 3037 { 20250, 1620, 113, 4000, OMX_VIDEO_AVCLevel22 }, 3038 { 40500, 1620, 113, 10000, OMX_VIDEO_AVCLevel3 }, 3039 { 108000, 3600, 169, 14000, OMX_VIDEO_AVCLevel31 }, 3040 { 216000, 5120, 202, 20000, OMX_VIDEO_AVCLevel32 }, 3041 { 245760, 8192, 256, 20000, OMX_VIDEO_AVCLevel4 }, 3042 { 245760, 8192, 256, 50000, OMX_VIDEO_AVCLevel41 }, 3043 { 522240, 8704, 263, 50000, OMX_VIDEO_AVCLevel42 }, 3044 { 589824, 22080, 420, 135000, OMX_VIDEO_AVCLevel5 }, 3045 { 983040, 36864, 543, 240000, OMX_VIDEO_AVCLevel51 }, 3046 { 2073600, 36864, 543, 240000, OMX_VIDEO_AVCLevel52 }, 3047 }; 3048 3049 for (size_t i = 0; i < ARRAY_SIZE(limits); i++) { 3050 const int (&limit)[5] = limits[i]; 3051 if (rate <= limit[0] && mbs <= limit[1] && maxDimension <= limit[2] 3052 && bitrate <= limit[3]) { 3053 return limit[4]; 3054 } 3055 } 3056 return 0; 3057} 3058 3059status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) { 3060 int32_t bitrate, iFrameInterval; 3061 if (!msg->findInt32("bitrate", &bitrate) 3062 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 3063 return INVALID_OPERATION; 3064 } 3065 3066 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 3067 3068 float frameRate; 3069 if (!msg->findFloat("frame-rate", &frameRate)) { 3070 int32_t tmp; 3071 if (!msg->findInt32("frame-rate", &tmp)) { 3072 return INVALID_OPERATION; 3073 } 3074 frameRate = (float)tmp; 3075 } 3076 3077 status_t err = OK; 3078 int32_t intraRefreshMode = 0; 3079 if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) { 3080 err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode); 3081 if (err != OK) { 3082 ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x", 3083 err, intraRefreshMode); 3084 return err; 3085 } 3086 } 3087 3088 OMX_VIDEO_PARAM_AVCTYPE h264type; 3089 InitOMXParams(&h264type); 3090 h264type.nPortIndex = kPortIndexOutput; 3091 3092 err = mOMX->getParameter( 3093 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 3094 3095 if (err != OK) { 3096 return err; 3097 } 3098 3099 h264type.nAllowedPictureTypes = 3100 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 3101 3102 int32_t profile; 3103 if (msg->findInt32("profile", &profile)) { 3104 int32_t level; 3105 if (!msg->findInt32("level", &level)) { 3106 return INVALID_OPERATION; 3107 } 3108 3109 err = verifySupportForProfileAndLevel(profile, level); 3110 3111 if (err != OK) { 3112 return err; 3113 } 3114 3115 h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile); 3116 h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level); 3117 } 3118 3119 // XXX 3120 if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) { 3121 ALOGW("Use baseline profile instead of %d for AVC recording", 3122 h264type.eProfile); 3123 h264type.eProfile = OMX_VIDEO_AVCProfileBaseline; 3124 } 3125 3126 if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) { 3127 h264type.nSliceHeaderSpacing = 0; 3128 h264type.bUseHadamard = OMX_TRUE; 3129 h264type.nRefFrames = 1; 3130 h264type.nBFrames = 0; 3131 h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 3132 if (h264type.nPFrames == 0) { 3133 h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 3134 } 3135 h264type.nRefIdx10ActiveMinus1 = 0; 3136 h264type.nRefIdx11ActiveMinus1 = 0; 3137 h264type.bEntropyCodingCABAC = OMX_FALSE; 3138 h264type.bWeightedPPrediction = OMX_FALSE; 3139 h264type.bconstIpred = OMX_FALSE; 3140 h264type.bDirect8x8Inference = OMX_FALSE; 3141 h264type.bDirectSpatialTemporal = OMX_FALSE; 3142 h264type.nCabacInitIdc = 0; 3143 } 3144 3145 if (h264type.nBFrames != 0) { 3146 h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB; 3147 } 3148 3149 h264type.bEnableUEP = OMX_FALSE; 3150 h264type.bEnableFMO = OMX_FALSE; 3151 h264type.bEnableASO = OMX_FALSE; 3152 h264type.bEnableRS = OMX_FALSE; 3153 h264type.bFrameMBsOnly = OMX_TRUE; 3154 h264type.bMBAFF = OMX_FALSE; 3155 h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; 3156 3157 err = mOMX->setParameter( 3158 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 3159 3160 if (err != OK) { 3161 return err; 3162 } 3163 3164 return configureBitrate(bitrate, bitrateMode); 3165} 3166 3167status_t ACodec::setupHEVCEncoderParameters(const sp<AMessage> &msg) { 3168 int32_t bitrate, iFrameInterval; 3169 if (!msg->findInt32("bitrate", &bitrate) 3170 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 3171 return INVALID_OPERATION; 3172 } 3173 3174 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 3175 3176 float frameRate; 3177 if (!msg->findFloat("frame-rate", &frameRate)) { 3178 int32_t tmp; 3179 if (!msg->findInt32("frame-rate", &tmp)) { 3180 return INVALID_OPERATION; 3181 } 3182 frameRate = (float)tmp; 3183 } 3184 3185 OMX_VIDEO_PARAM_HEVCTYPE hevcType; 3186 InitOMXParams(&hevcType); 3187 hevcType.nPortIndex = kPortIndexOutput; 3188 3189 status_t err = OK; 3190 err = mOMX->getParameter( 3191 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType)); 3192 if (err != OK) { 3193 return err; 3194 } 3195 3196 int32_t profile; 3197 if (msg->findInt32("profile", &profile)) { 3198 int32_t level; 3199 if (!msg->findInt32("level", &level)) { 3200 return INVALID_OPERATION; 3201 } 3202 3203 err = verifySupportForProfileAndLevel(profile, level); 3204 if (err != OK) { 3205 return err; 3206 } 3207 3208 hevcType.eProfile = static_cast<OMX_VIDEO_HEVCPROFILETYPE>(profile); 3209 hevcType.eLevel = static_cast<OMX_VIDEO_HEVCLEVELTYPE>(level); 3210 } 3211 3212 // TODO: Need OMX structure definition for setting iFrameInterval 3213 3214 err = mOMX->setParameter( 3215 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType)); 3216 if (err != OK) { 3217 return err; 3218 } 3219 3220 return configureBitrate(bitrate, bitrateMode); 3221} 3222 3223status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg) { 3224 int32_t bitrate; 3225 int32_t iFrameInterval = 0; 3226 size_t tsLayers = 0; 3227 OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE pattern = 3228 OMX_VIDEO_VPXTemporalLayerPatternNone; 3229 static const uint32_t kVp8LayerRateAlloction 3230 [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] 3231 [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] = { 3232 {100, 100, 100}, // 1 layer 3233 { 60, 100, 100}, // 2 layers {60%, 40%} 3234 { 40, 60, 100}, // 3 layers {40%, 20%, 40%} 3235 }; 3236 if (!msg->findInt32("bitrate", &bitrate)) { 3237 return INVALID_OPERATION; 3238 } 3239 msg->findInt32("i-frame-interval", &iFrameInterval); 3240 3241 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 3242 3243 float frameRate; 3244 if (!msg->findFloat("frame-rate", &frameRate)) { 3245 int32_t tmp; 3246 if (!msg->findInt32("frame-rate", &tmp)) { 3247 return INVALID_OPERATION; 3248 } 3249 frameRate = (float)tmp; 3250 } 3251 3252 AString tsSchema; 3253 if (msg->findString("ts-schema", &tsSchema)) { 3254 if (tsSchema == "webrtc.vp8.1-layer") { 3255 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC; 3256 tsLayers = 1; 3257 } else if (tsSchema == "webrtc.vp8.2-layer") { 3258 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC; 3259 tsLayers = 2; 3260 } else if (tsSchema == "webrtc.vp8.3-layer") { 3261 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC; 3262 tsLayers = 3; 3263 } else { 3264 ALOGW("Unsupported ts-schema [%s]", tsSchema.c_str()); 3265 } 3266 } 3267 3268 OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type; 3269 InitOMXParams(&vp8type); 3270 vp8type.nPortIndex = kPortIndexOutput; 3271 status_t err = mOMX->getParameter( 3272 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder, 3273 &vp8type, sizeof(vp8type)); 3274 3275 if (err == OK) { 3276 if (iFrameInterval > 0) { 3277 vp8type.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate); 3278 } 3279 vp8type.eTemporalPattern = pattern; 3280 vp8type.nTemporalLayerCount = tsLayers; 3281 if (tsLayers > 0) { 3282 for (size_t i = 0; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) { 3283 vp8type.nTemporalLayerBitrateRatio[i] = 3284 kVp8LayerRateAlloction[tsLayers - 1][i]; 3285 } 3286 } 3287 if (bitrateMode == OMX_Video_ControlRateConstant) { 3288 vp8type.nMinQuantizer = 2; 3289 vp8type.nMaxQuantizer = 63; 3290 } 3291 3292 err = mOMX->setParameter( 3293 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder, 3294 &vp8type, sizeof(vp8type)); 3295 if (err != OK) { 3296 ALOGW("Extended VP8 parameters set failed: %d", err); 3297 } 3298 } 3299 3300 return configureBitrate(bitrate, bitrateMode); 3301} 3302 3303status_t ACodec::verifySupportForProfileAndLevel( 3304 int32_t profile, int32_t level) { 3305 OMX_VIDEO_PARAM_PROFILELEVELTYPE params; 3306 InitOMXParams(¶ms); 3307 params.nPortIndex = kPortIndexOutput; 3308 3309 for (params.nProfileIndex = 0;; ++params.nProfileIndex) { 3310 status_t err = mOMX->getParameter( 3311 mNode, 3312 OMX_IndexParamVideoProfileLevelQuerySupported, 3313 ¶ms, 3314 sizeof(params)); 3315 3316 if (err != OK) { 3317 return err; 3318 } 3319 3320 int32_t supportedProfile = static_cast<int32_t>(params.eProfile); 3321 int32_t supportedLevel = static_cast<int32_t>(params.eLevel); 3322 3323 if (profile == supportedProfile && level <= supportedLevel) { 3324 return OK; 3325 } 3326 } 3327} 3328 3329status_t ACodec::configureBitrate( 3330 int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode) { 3331 OMX_VIDEO_PARAM_BITRATETYPE bitrateType; 3332 InitOMXParams(&bitrateType); 3333 bitrateType.nPortIndex = kPortIndexOutput; 3334 3335 status_t err = mOMX->getParameter( 3336 mNode, OMX_IndexParamVideoBitrate, 3337 &bitrateType, sizeof(bitrateType)); 3338 3339 if (err != OK) { 3340 return err; 3341 } 3342 3343 bitrateType.eControlRate = bitrateMode; 3344 bitrateType.nTargetBitrate = bitrate; 3345 3346 return mOMX->setParameter( 3347 mNode, OMX_IndexParamVideoBitrate, 3348 &bitrateType, sizeof(bitrateType)); 3349} 3350 3351status_t ACodec::setupErrorCorrectionParameters() { 3352 OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType; 3353 InitOMXParams(&errorCorrectionType); 3354 errorCorrectionType.nPortIndex = kPortIndexOutput; 3355 3356 status_t err = mOMX->getParameter( 3357 mNode, OMX_IndexParamVideoErrorCorrection, 3358 &errorCorrectionType, sizeof(errorCorrectionType)); 3359 3360 if (err != OK) { 3361 return OK; // Optional feature. Ignore this failure 3362 } 3363 3364 errorCorrectionType.bEnableHEC = OMX_FALSE; 3365 errorCorrectionType.bEnableResync = OMX_TRUE; 3366 errorCorrectionType.nResynchMarkerSpacing = 256; 3367 errorCorrectionType.bEnableDataPartitioning = OMX_FALSE; 3368 errorCorrectionType.bEnableRVLC = OMX_FALSE; 3369 3370 return mOMX->setParameter( 3371 mNode, OMX_IndexParamVideoErrorCorrection, 3372 &errorCorrectionType, sizeof(errorCorrectionType)); 3373} 3374 3375status_t ACodec::setVideoFormatOnPort( 3376 OMX_U32 portIndex, 3377 int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat, 3378 float frameRate) { 3379 OMX_PARAM_PORTDEFINITIONTYPE def; 3380 InitOMXParams(&def); 3381 def.nPortIndex = portIndex; 3382 3383 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 3384 3385 status_t err = mOMX->getParameter( 3386 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 3387 3388 CHECK_EQ(err, (status_t)OK); 3389 3390 if (portIndex == kPortIndexInput) { 3391 // XXX Need a (much) better heuristic to compute input buffer sizes. 3392 const size_t X = 64 * 1024; 3393 if (def.nBufferSize < X) { 3394 def.nBufferSize = X; 3395 } 3396 } 3397 3398 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo); 3399 3400 video_def->nFrameWidth = width; 3401 video_def->nFrameHeight = height; 3402 3403 if (portIndex == kPortIndexInput) { 3404 video_def->eCompressionFormat = compressionFormat; 3405 video_def->eColorFormat = OMX_COLOR_FormatUnused; 3406 if (frameRate >= 0) { 3407 video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f); 3408 } 3409 } 3410 3411 err = mOMX->setParameter( 3412 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 3413 3414 return err; 3415} 3416 3417status_t ACodec::initNativeWindow() { 3418 if (mNativeWindow != NULL) { 3419 return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE); 3420 } 3421 3422 mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE); 3423 return OK; 3424} 3425 3426size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const { 3427 size_t n = 0; 3428 3429 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 3430 const BufferInfo &info = mBuffers[portIndex].itemAt(i); 3431 3432 if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) { 3433 ++n; 3434 } 3435 } 3436 3437 return n; 3438} 3439 3440size_t ACodec::countBuffersOwnedByNativeWindow() const { 3441 size_t n = 0; 3442 3443 for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) { 3444 const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i); 3445 3446 if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 3447 ++n; 3448 } 3449 } 3450 3451 return n; 3452} 3453 3454void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() { 3455 if (mNativeWindow == NULL) { 3456 return; 3457 } 3458 3459 while (countBuffersOwnedByNativeWindow() > mNumUndequeuedBuffers 3460 && dequeueBufferFromNativeWindow() != NULL) { 3461 // these buffers will be submitted as regular buffers; account for this 3462 if (mStoreMetaDataInOutputBuffers && mMetaDataBuffersToSubmit > 0) { 3463 --mMetaDataBuffersToSubmit; 3464 } 3465 } 3466} 3467 3468bool ACodec::allYourBuffersAreBelongToUs( 3469 OMX_U32 portIndex) { 3470 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 3471 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 3472 3473 if (info->mStatus != BufferInfo::OWNED_BY_US 3474 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) { 3475 ALOGV("[%s] Buffer %u on port %u still has status %d", 3476 mComponentName.c_str(), 3477 info->mBufferID, portIndex, info->mStatus); 3478 return false; 3479 } 3480 } 3481 3482 return true; 3483} 3484 3485bool ACodec::allYourBuffersAreBelongToUs() { 3486 return allYourBuffersAreBelongToUs(kPortIndexInput) 3487 && allYourBuffersAreBelongToUs(kPortIndexOutput); 3488} 3489 3490void ACodec::deferMessage(const sp<AMessage> &msg) { 3491 mDeferredQueue.push_back(msg); 3492} 3493 3494void ACodec::processDeferredMessages() { 3495 List<sp<AMessage> > queue = mDeferredQueue; 3496 mDeferredQueue.clear(); 3497 3498 List<sp<AMessage> >::iterator it = queue.begin(); 3499 while (it != queue.end()) { 3500 onMessageReceived(*it++); 3501 } 3502} 3503 3504// static 3505bool ACodec::describeDefaultColorFormat(DescribeColorFormatParams ¶ms) { 3506 MediaImage &image = params.sMediaImage; 3507 memset(&image, 0, sizeof(image)); 3508 3509 image.mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN; 3510 image.mNumPlanes = 0; 3511 3512 const OMX_COLOR_FORMATTYPE fmt = params.eColorFormat; 3513 image.mWidth = params.nFrameWidth; 3514 image.mHeight = params.nFrameHeight; 3515 3516 // only supporting YUV420 3517 if (fmt != OMX_COLOR_FormatYUV420Planar && 3518 fmt != OMX_COLOR_FormatYUV420PackedPlanar && 3519 fmt != OMX_COLOR_FormatYUV420SemiPlanar && 3520 fmt != OMX_COLOR_FormatYUV420PackedSemiPlanar && 3521 fmt != HAL_PIXEL_FORMAT_YV12) { 3522 ALOGW("do not know color format 0x%x = %d", fmt, fmt); 3523 return false; 3524 } 3525 3526 // TEMPORARY FIX for some vendors that advertise sliceHeight as 0 3527 if (params.nStride != 0 && params.nSliceHeight == 0) { 3528 ALOGW("using sliceHeight=%u instead of what codec advertised (=0)", 3529 params.nFrameHeight); 3530 params.nSliceHeight = params.nFrameHeight; 3531 } 3532 3533 // we need stride and slice-height to be non-zero 3534 if (params.nStride == 0 || params.nSliceHeight == 0) { 3535 ALOGW("cannot describe color format 0x%x = %d with stride=%u and sliceHeight=%u", 3536 fmt, fmt, params.nStride, params.nSliceHeight); 3537 return false; 3538 } 3539 3540 // set-up YUV format 3541 image.mType = MediaImage::MEDIA_IMAGE_TYPE_YUV; 3542 image.mNumPlanes = 3; 3543 image.mBitDepth = 8; 3544 image.mPlane[image.Y].mOffset = 0; 3545 image.mPlane[image.Y].mColInc = 1; 3546 image.mPlane[image.Y].mRowInc = params.nStride; 3547 image.mPlane[image.Y].mHorizSubsampling = 1; 3548 image.mPlane[image.Y].mVertSubsampling = 1; 3549 3550 switch ((int)fmt) { 3551 case HAL_PIXEL_FORMAT_YV12: 3552 if (params.bUsingNativeBuffers) { 3553 size_t ystride = align(params.nStride, 16); 3554 size_t cstride = align(params.nStride / 2, 16); 3555 image.mPlane[image.Y].mRowInc = ystride; 3556 3557 image.mPlane[image.V].mOffset = ystride * params.nSliceHeight; 3558 image.mPlane[image.V].mColInc = 1; 3559 image.mPlane[image.V].mRowInc = cstride; 3560 image.mPlane[image.V].mHorizSubsampling = 2; 3561 image.mPlane[image.V].mVertSubsampling = 2; 3562 3563 image.mPlane[image.U].mOffset = image.mPlane[image.V].mOffset 3564 + (cstride * params.nSliceHeight / 2); 3565 image.mPlane[image.U].mColInc = 1; 3566 image.mPlane[image.U].mRowInc = cstride; 3567 image.mPlane[image.U].mHorizSubsampling = 2; 3568 image.mPlane[image.U].mVertSubsampling = 2; 3569 break; 3570 } else { 3571 // fall through as YV12 is used for YUV420Planar by some codecs 3572 } 3573 3574 case OMX_COLOR_FormatYUV420Planar: 3575 case OMX_COLOR_FormatYUV420PackedPlanar: 3576 image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight; 3577 image.mPlane[image.U].mColInc = 1; 3578 image.mPlane[image.U].mRowInc = params.nStride / 2; 3579 image.mPlane[image.U].mHorizSubsampling = 2; 3580 image.mPlane[image.U].mVertSubsampling = 2; 3581 3582 image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset 3583 + (params.nStride * params.nSliceHeight / 4); 3584 image.mPlane[image.V].mColInc = 1; 3585 image.mPlane[image.V].mRowInc = params.nStride / 2; 3586 image.mPlane[image.V].mHorizSubsampling = 2; 3587 image.mPlane[image.V].mVertSubsampling = 2; 3588 break; 3589 3590 case OMX_COLOR_FormatYUV420SemiPlanar: 3591 // FIXME: NV21 for sw-encoder, NV12 for decoder and hw-encoder 3592 case OMX_COLOR_FormatYUV420PackedSemiPlanar: 3593 // NV12 3594 image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight; 3595 image.mPlane[image.U].mColInc = 2; 3596 image.mPlane[image.U].mRowInc = params.nStride; 3597 image.mPlane[image.U].mHorizSubsampling = 2; 3598 image.mPlane[image.U].mVertSubsampling = 2; 3599 3600 image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset + 1; 3601 image.mPlane[image.V].mColInc = 2; 3602 image.mPlane[image.V].mRowInc = params.nStride; 3603 image.mPlane[image.V].mHorizSubsampling = 2; 3604 image.mPlane[image.V].mVertSubsampling = 2; 3605 break; 3606 3607 default: 3608 TRESPASS(); 3609 } 3610 return true; 3611} 3612 3613// static 3614bool ACodec::describeColorFormat( 3615 const sp<IOMX> &omx, IOMX::node_id node, 3616 DescribeColorFormatParams &describeParams) 3617{ 3618 OMX_INDEXTYPE describeColorFormatIndex; 3619 if (omx->getExtensionIndex( 3620 node, "OMX.google.android.index.describeColorFormat", 3621 &describeColorFormatIndex) != OK || 3622 omx->getParameter( 3623 node, describeColorFormatIndex, 3624 &describeParams, sizeof(describeParams)) != OK) { 3625 return describeDefaultColorFormat(describeParams); 3626 } 3627 return describeParams.sMediaImage.mType != 3628 MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN; 3629} 3630 3631// static 3632bool ACodec::isFlexibleColorFormat( 3633 const sp<IOMX> &omx, IOMX::node_id node, 3634 uint32_t colorFormat, bool usingNativeBuffers, OMX_U32 *flexibleEquivalent) { 3635 DescribeColorFormatParams describeParams; 3636 InitOMXParams(&describeParams); 3637 describeParams.eColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat; 3638 // reasonable dummy values 3639 describeParams.nFrameWidth = 128; 3640 describeParams.nFrameHeight = 128; 3641 describeParams.nStride = 128; 3642 describeParams.nSliceHeight = 128; 3643 describeParams.bUsingNativeBuffers = (OMX_BOOL)usingNativeBuffers; 3644 3645 CHECK(flexibleEquivalent != NULL); 3646 3647 if (!describeColorFormat(omx, node, describeParams)) { 3648 return false; 3649 } 3650 3651 const MediaImage &img = describeParams.sMediaImage; 3652 if (img.mType == MediaImage::MEDIA_IMAGE_TYPE_YUV) { 3653 if (img.mNumPlanes != 3 || 3654 img.mPlane[img.Y].mHorizSubsampling != 1 || 3655 img.mPlane[img.Y].mVertSubsampling != 1) { 3656 return false; 3657 } 3658 3659 // YUV 420 3660 if (img.mPlane[img.U].mHorizSubsampling == 2 3661 && img.mPlane[img.U].mVertSubsampling == 2 3662 && img.mPlane[img.V].mHorizSubsampling == 2 3663 && img.mPlane[img.V].mVertSubsampling == 2) { 3664 // possible flexible YUV420 format 3665 if (img.mBitDepth <= 8) { 3666 *flexibleEquivalent = OMX_COLOR_FormatYUV420Flexible; 3667 return true; 3668 } 3669 } 3670 } 3671 return false; 3672} 3673 3674status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> ¬ify) { 3675 // TODO: catch errors an return them instead of using CHECK 3676 OMX_PARAM_PORTDEFINITIONTYPE def; 3677 InitOMXParams(&def); 3678 def.nPortIndex = portIndex; 3679 3680 CHECK_EQ(mOMX->getParameter( 3681 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)), 3682 (status_t)OK); 3683 3684 CHECK_EQ((int)def.eDir, 3685 (int)(portIndex == kPortIndexOutput ? OMX_DirOutput : OMX_DirInput)); 3686 3687 switch (def.eDomain) { 3688 case OMX_PortDomainVideo: 3689 { 3690 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video; 3691 switch ((int)videoDef->eCompressionFormat) { 3692 case OMX_VIDEO_CodingUnused: 3693 { 3694 CHECK(mIsEncoder ^ (portIndex == kPortIndexOutput)); 3695 notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW); 3696 3697 notify->setInt32("stride", videoDef->nStride); 3698 notify->setInt32("slice-height", videoDef->nSliceHeight); 3699 notify->setInt32("color-format", videoDef->eColorFormat); 3700 3701 if (mNativeWindow == NULL) { 3702 DescribeColorFormatParams describeParams; 3703 InitOMXParams(&describeParams); 3704 describeParams.eColorFormat = videoDef->eColorFormat; 3705 describeParams.nFrameWidth = videoDef->nFrameWidth; 3706 describeParams.nFrameHeight = videoDef->nFrameHeight; 3707 describeParams.nStride = videoDef->nStride; 3708 describeParams.nSliceHeight = videoDef->nSliceHeight; 3709 describeParams.bUsingNativeBuffers = OMX_FALSE; 3710 3711 if (describeColorFormat(mOMX, mNode, describeParams)) { 3712 notify->setBuffer( 3713 "image-data", 3714 ABuffer::CreateAsCopy( 3715 &describeParams.sMediaImage, 3716 sizeof(describeParams.sMediaImage))); 3717 3718 MediaImage *img = &describeParams.sMediaImage; 3719 ALOGV("[%s] MediaImage { F(%zux%zu) @%zu+%zu+%zu @%zu+%zu+%zu @%zu+%zu+%zu }", 3720 mComponentName.c_str(), img->mWidth, img->mHeight, 3721 img->mPlane[0].mOffset, img->mPlane[0].mColInc, img->mPlane[0].mRowInc, 3722 img->mPlane[1].mOffset, img->mPlane[1].mColInc, img->mPlane[1].mRowInc, 3723 img->mPlane[2].mOffset, img->mPlane[2].mColInc, img->mPlane[2].mRowInc); 3724 } 3725 } 3726 3727 if (portIndex != kPortIndexOutput) { 3728 // TODO: also get input crop 3729 break; 3730 } 3731 3732 OMX_CONFIG_RECTTYPE rect; 3733 InitOMXParams(&rect); 3734 rect.nPortIndex = portIndex; 3735 3736 if (mOMX->getConfig( 3737 mNode, 3738 (portIndex == kPortIndexOutput ? 3739 OMX_IndexConfigCommonOutputCrop : 3740 OMX_IndexConfigCommonInputCrop), 3741 &rect, sizeof(rect)) != OK) { 3742 rect.nLeft = 0; 3743 rect.nTop = 0; 3744 rect.nWidth = videoDef->nFrameWidth; 3745 rect.nHeight = videoDef->nFrameHeight; 3746 } 3747 3748 CHECK_GE(rect.nLeft, 0); 3749 CHECK_GE(rect.nTop, 0); 3750 CHECK_GE(rect.nWidth, 0u); 3751 CHECK_GE(rect.nHeight, 0u); 3752 CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth); 3753 CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight); 3754 3755 notify->setRect( 3756 "crop", 3757 rect.nLeft, 3758 rect.nTop, 3759 rect.nLeft + rect.nWidth - 1, 3760 rect.nTop + rect.nHeight - 1); 3761 3762 break; 3763 } 3764 3765 case OMX_VIDEO_CodingVP8: 3766 case OMX_VIDEO_CodingVP9: 3767 { 3768 OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type; 3769 InitOMXParams(&vp8type); 3770 vp8type.nPortIndex = kPortIndexOutput; 3771 status_t err = mOMX->getParameter( 3772 mNode, 3773 (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder, 3774 &vp8type, 3775 sizeof(vp8type)); 3776 3777 if (err == OK) { 3778 AString tsSchema = "none"; 3779 if (vp8type.eTemporalPattern 3780 == OMX_VIDEO_VPXTemporalLayerPatternWebRTC) { 3781 switch (vp8type.nTemporalLayerCount) { 3782 case 1: 3783 { 3784 tsSchema = "webrtc.vp8.1-layer"; 3785 break; 3786 } 3787 case 2: 3788 { 3789 tsSchema = "webrtc.vp8.2-layer"; 3790 break; 3791 } 3792 case 3: 3793 { 3794 tsSchema = "webrtc.vp8.3-layer"; 3795 break; 3796 } 3797 default: 3798 { 3799 break; 3800 } 3801 } 3802 } 3803 notify->setString("ts-schema", tsSchema); 3804 } 3805 // Fall through to set up mime. 3806 } 3807 3808 default: 3809 { 3810 CHECK(mIsEncoder ^ (portIndex == kPortIndexInput)); 3811 AString mime; 3812 if (GetMimeTypeForVideoCoding( 3813 videoDef->eCompressionFormat, &mime) != OK) { 3814 notify->setString("mime", "application/octet-stream"); 3815 } else { 3816 notify->setString("mime", mime.c_str()); 3817 } 3818 break; 3819 } 3820 } 3821 notify->setInt32("width", videoDef->nFrameWidth); 3822 notify->setInt32("height", videoDef->nFrameHeight); 3823 ALOGV("[%s] %s format is %s", mComponentName.c_str(), 3824 portIndex == kPortIndexInput ? "input" : "output", 3825 notify->debugString().c_str()); 3826 3827 break; 3828 } 3829 3830 case OMX_PortDomainAudio: 3831 { 3832 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio; 3833 3834 switch ((int)audioDef->eEncoding) { 3835 case OMX_AUDIO_CodingPCM: 3836 { 3837 OMX_AUDIO_PARAM_PCMMODETYPE params; 3838 InitOMXParams(¶ms); 3839 params.nPortIndex = portIndex; 3840 3841 CHECK_EQ(mOMX->getParameter( 3842 mNode, OMX_IndexParamAudioPcm, 3843 ¶ms, sizeof(params)), 3844 (status_t)OK); 3845 3846 CHECK_GT(params.nChannels, 0); 3847 CHECK(params.nChannels == 1 || params.bInterleaved); 3848 CHECK_EQ(params.nBitPerSample, 16u); 3849 3850 CHECK_EQ((int)params.eNumData, 3851 (int)OMX_NumericalDataSigned); 3852 3853 CHECK_EQ((int)params.ePCMMode, 3854 (int)OMX_AUDIO_PCMModeLinear); 3855 3856 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW); 3857 notify->setInt32("channel-count", params.nChannels); 3858 notify->setInt32("sample-rate", params.nSamplingRate); 3859 3860 if (mChannelMaskPresent) { 3861 notify->setInt32("channel-mask", mChannelMask); 3862 } 3863 break; 3864 } 3865 3866 case OMX_AUDIO_CodingAAC: 3867 { 3868 OMX_AUDIO_PARAM_AACPROFILETYPE params; 3869 InitOMXParams(¶ms); 3870 params.nPortIndex = portIndex; 3871 3872 CHECK_EQ(mOMX->getParameter( 3873 mNode, OMX_IndexParamAudioAac, 3874 ¶ms, sizeof(params)), 3875 (status_t)OK); 3876 3877 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC); 3878 notify->setInt32("channel-count", params.nChannels); 3879 notify->setInt32("sample-rate", params.nSampleRate); 3880 break; 3881 } 3882 3883 case OMX_AUDIO_CodingAMR: 3884 { 3885 OMX_AUDIO_PARAM_AMRTYPE params; 3886 InitOMXParams(¶ms); 3887 params.nPortIndex = portIndex; 3888 3889 CHECK_EQ(mOMX->getParameter( 3890 mNode, OMX_IndexParamAudioAmr, 3891 ¶ms, sizeof(params)), 3892 (status_t)OK); 3893 3894 notify->setInt32("channel-count", 1); 3895 if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) { 3896 notify->setString( 3897 "mime", MEDIA_MIMETYPE_AUDIO_AMR_WB); 3898 3899 notify->setInt32("sample-rate", 16000); 3900 } else { 3901 notify->setString( 3902 "mime", MEDIA_MIMETYPE_AUDIO_AMR_NB); 3903 3904 notify->setInt32("sample-rate", 8000); 3905 } 3906 break; 3907 } 3908 3909 case OMX_AUDIO_CodingFLAC: 3910 { 3911 OMX_AUDIO_PARAM_FLACTYPE params; 3912 InitOMXParams(¶ms); 3913 params.nPortIndex = portIndex; 3914 3915 CHECK_EQ(mOMX->getParameter( 3916 mNode, OMX_IndexParamAudioFlac, 3917 ¶ms, sizeof(params)), 3918 (status_t)OK); 3919 3920 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC); 3921 notify->setInt32("channel-count", params.nChannels); 3922 notify->setInt32("sample-rate", params.nSampleRate); 3923 break; 3924 } 3925 3926 case OMX_AUDIO_CodingMP3: 3927 { 3928 OMX_AUDIO_PARAM_MP3TYPE params; 3929 InitOMXParams(¶ms); 3930 params.nPortIndex = portIndex; 3931 3932 CHECK_EQ(mOMX->getParameter( 3933 mNode, OMX_IndexParamAudioMp3, 3934 ¶ms, sizeof(params)), 3935 (status_t)OK); 3936 3937 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MPEG); 3938 notify->setInt32("channel-count", params.nChannels); 3939 notify->setInt32("sample-rate", params.nSampleRate); 3940 break; 3941 } 3942 3943 case OMX_AUDIO_CodingVORBIS: 3944 { 3945 OMX_AUDIO_PARAM_VORBISTYPE params; 3946 InitOMXParams(¶ms); 3947 params.nPortIndex = portIndex; 3948 3949 CHECK_EQ(mOMX->getParameter( 3950 mNode, OMX_IndexParamAudioVorbis, 3951 ¶ms, sizeof(params)), 3952 (status_t)OK); 3953 3954 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_VORBIS); 3955 notify->setInt32("channel-count", params.nChannels); 3956 notify->setInt32("sample-rate", params.nSampleRate); 3957 break; 3958 } 3959 3960 case OMX_AUDIO_CodingAndroidAC3: 3961 { 3962 OMX_AUDIO_PARAM_ANDROID_AC3TYPE params; 3963 InitOMXParams(¶ms); 3964 params.nPortIndex = portIndex; 3965 3966 CHECK_EQ((status_t)OK, mOMX->getParameter( 3967 mNode, 3968 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, 3969 ¶ms, 3970 sizeof(params))); 3971 3972 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3); 3973 notify->setInt32("channel-count", params.nChannels); 3974 notify->setInt32("sample-rate", params.nSampleRate); 3975 break; 3976 } 3977 3978 case OMX_AUDIO_CodingAndroidEAC3: 3979 { 3980 OMX_AUDIO_PARAM_ANDROID_EAC3TYPE params; 3981 InitOMXParams(¶ms); 3982 params.nPortIndex = portIndex; 3983 3984 CHECK_EQ((status_t)OK, mOMX->getParameter( 3985 mNode, 3986 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, 3987 ¶ms, 3988 sizeof(params))); 3989 3990 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_EAC3); 3991 notify->setInt32("channel-count", params.nChannels); 3992 notify->setInt32("sample-rate", params.nSampleRate); 3993 break; 3994 } 3995 3996 case OMX_AUDIO_CodingAndroidOPUS: 3997 { 3998 OMX_AUDIO_PARAM_ANDROID_OPUSTYPE params; 3999 InitOMXParams(¶ms); 4000 params.nPortIndex = portIndex; 4001 4002 CHECK_EQ((status_t)OK, mOMX->getParameter( 4003 mNode, 4004 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus, 4005 ¶ms, 4006 sizeof(params))); 4007 4008 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_OPUS); 4009 notify->setInt32("channel-count", params.nChannels); 4010 notify->setInt32("sample-rate", params.nSampleRate); 4011 break; 4012 } 4013 4014 case OMX_AUDIO_CodingG711: 4015 { 4016 OMX_AUDIO_PARAM_PCMMODETYPE params; 4017 InitOMXParams(¶ms); 4018 params.nPortIndex = portIndex; 4019 4020 CHECK_EQ((status_t)OK, mOMX->getParameter( 4021 mNode, 4022 (OMX_INDEXTYPE)OMX_IndexParamAudioPcm, 4023 ¶ms, 4024 sizeof(params))); 4025 4026 const char *mime = NULL; 4027 if (params.ePCMMode == OMX_AUDIO_PCMModeMULaw) { 4028 mime = MEDIA_MIMETYPE_AUDIO_G711_MLAW; 4029 } else if (params.ePCMMode == OMX_AUDIO_PCMModeALaw) { 4030 mime = MEDIA_MIMETYPE_AUDIO_G711_ALAW; 4031 } else { // params.ePCMMode == OMX_AUDIO_PCMModeLinear 4032 mime = MEDIA_MIMETYPE_AUDIO_RAW; 4033 } 4034 notify->setString("mime", mime); 4035 notify->setInt32("channel-count", params.nChannels); 4036 notify->setInt32("sample-rate", params.nSamplingRate); 4037 break; 4038 } 4039 4040 case OMX_AUDIO_CodingGSMFR: 4041 { 4042 OMX_AUDIO_PARAM_MP3TYPE params; 4043 InitOMXParams(¶ms); 4044 params.nPortIndex = portIndex; 4045 4046 CHECK_EQ(mOMX->getParameter( 4047 mNode, OMX_IndexParamAudioPcm, 4048 ¶ms, sizeof(params)), 4049 (status_t)OK); 4050 4051 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MSGSM); 4052 notify->setInt32("channel-count", params.nChannels); 4053 notify->setInt32("sample-rate", params.nSampleRate); 4054 break; 4055 } 4056 4057 default: 4058 ALOGE("UNKNOWN AUDIO CODING: %d\n", audioDef->eEncoding); 4059 TRESPASS(); 4060 } 4061 break; 4062 } 4063 4064 default: 4065 TRESPASS(); 4066 } 4067 4068 return OK; 4069} 4070 4071void ACodec::sendFormatChange(const sp<AMessage> &reply) { 4072 sp<AMessage> notify = mBaseOutputFormat->dup(); 4073 notify->setInt32("what", kWhatOutputFormatChanged); 4074 4075 CHECK_EQ(getPortFormat(kPortIndexOutput, notify), (status_t)OK); 4076 4077 AString mime; 4078 CHECK(notify->findString("mime", &mime)); 4079 4080 int32_t left, top, right, bottom; 4081 if (mime == MEDIA_MIMETYPE_VIDEO_RAW && 4082 mNativeWindow != NULL && 4083 notify->findRect("crop", &left, &top, &right, &bottom)) { 4084 // notify renderer of the crop change 4085 // NOTE: native window uses extended right-bottom coordinate 4086 reply->setRect("crop", left, top, right + 1, bottom + 1); 4087 } else if (mime == MEDIA_MIMETYPE_AUDIO_RAW && 4088 (mEncoderDelay || mEncoderPadding)) { 4089 int32_t channelCount; 4090 CHECK(notify->findInt32("channel-count", &channelCount)); 4091 size_t frameSize = channelCount * sizeof(int16_t); 4092 if (mSkipCutBuffer != NULL) { 4093 size_t prevbufsize = mSkipCutBuffer->size(); 4094 if (prevbufsize != 0) { 4095 ALOGW("Replacing SkipCutBuffer holding %zu bytes", prevbufsize); 4096 } 4097 } 4098 mSkipCutBuffer = new SkipCutBuffer( 4099 mEncoderDelay * frameSize, 4100 mEncoderPadding * frameSize); 4101 } 4102 4103 notify->post(); 4104 4105 mSentFormat = true; 4106} 4107 4108void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) { 4109 sp<AMessage> notify = mNotify->dup(); 4110 notify->setInt32("what", CodecBase::kWhatError); 4111 ALOGE("signalError(omxError %#x, internalError %d)", error, internalError); 4112 4113 if (internalError == UNKNOWN_ERROR) { // find better error code 4114 const status_t omxStatus = statusFromOMXError(error); 4115 if (omxStatus != 0) { 4116 internalError = omxStatus; 4117 } else { 4118 ALOGW("Invalid OMX error %#x", error); 4119 } 4120 } 4121 notify->setInt32("err", internalError); 4122 notify->setInt32("actionCode", ACTION_CODE_FATAL); // could translate from OMX error. 4123 notify->post(); 4124} 4125 4126status_t ACodec::pushBlankBuffersToNativeWindow() { 4127 status_t err = NO_ERROR; 4128 ANativeWindowBuffer* anb = NULL; 4129 int numBufs = 0; 4130 int minUndequeuedBufs = 0; 4131 4132 // We need to reconnect to the ANativeWindow as a CPU client to ensure that 4133 // no frames get dropped by SurfaceFlinger assuming that these are video 4134 // frames. 4135 err = native_window_api_disconnect(mNativeWindow.get(), 4136 NATIVE_WINDOW_API_MEDIA); 4137 if (err != NO_ERROR) { 4138 ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)", 4139 strerror(-err), -err); 4140 return err; 4141 } 4142 4143 err = native_window_api_connect(mNativeWindow.get(), 4144 NATIVE_WINDOW_API_CPU); 4145 if (err != NO_ERROR) { 4146 ALOGE("error pushing blank frames: api_connect failed: %s (%d)", 4147 strerror(-err), -err); 4148 return err; 4149 } 4150 4151 err = setNativeWindowSizeFormatAndUsage( 4152 mNativeWindow.get(), 1, 1, HAL_PIXEL_FORMAT_RGBX_8888, 0, GRALLOC_USAGE_SW_WRITE_OFTEN); 4153 if (err != NO_ERROR) { 4154 ALOGE("error pushing blank frames: set format failed: %s (%d)", 4155 strerror(-err), -err); 4156 goto error; 4157 } 4158 4159 err = mNativeWindow->query(mNativeWindow.get(), 4160 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs); 4161 if (err != NO_ERROR) { 4162 ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query " 4163 "failed: %s (%d)", strerror(-err), -err); 4164 goto error; 4165 } 4166 4167 numBufs = minUndequeuedBufs + 1; 4168 err = native_window_set_buffer_count(mNativeWindow.get(), numBufs); 4169 if (err != NO_ERROR) { 4170 ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)", 4171 strerror(-err), -err); 4172 goto error; 4173 } 4174 4175 // We push numBufs + 1 buffers to ensure that we've drawn into the same 4176 // buffer twice. This should guarantee that the buffer has been displayed 4177 // on the screen and then been replaced, so an previous video frames are 4178 // guaranteed NOT to be currently displayed. 4179 for (int i = 0; i < numBufs + 1; i++) { 4180 err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &anb); 4181 if (err != NO_ERROR) { 4182 ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)", 4183 strerror(-err), -err); 4184 goto error; 4185 } 4186 4187 sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); 4188 4189 // Fill the buffer with the a 1x1 checkerboard pattern ;) 4190 uint32_t* img = NULL; 4191 err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); 4192 if (err != NO_ERROR) { 4193 ALOGE("error pushing blank frames: lock failed: %s (%d)", 4194 strerror(-err), -err); 4195 goto error; 4196 } 4197 4198 *img = 0; 4199 4200 err = buf->unlock(); 4201 if (err != NO_ERROR) { 4202 ALOGE("error pushing blank frames: unlock failed: %s (%d)", 4203 strerror(-err), -err); 4204 goto error; 4205 } 4206 4207 err = mNativeWindow->queueBuffer(mNativeWindow.get(), 4208 buf->getNativeBuffer(), -1); 4209 if (err != NO_ERROR) { 4210 ALOGE("error pushing blank frames: queueBuffer failed: %s (%d)", 4211 strerror(-err), -err); 4212 goto error; 4213 } 4214 4215 anb = NULL; 4216 } 4217 4218error: 4219 4220 if (err != NO_ERROR) { 4221 // Clean up after an error. 4222 if (anb != NULL) { 4223 mNativeWindow->cancelBuffer(mNativeWindow.get(), anb, -1); 4224 } 4225 4226 native_window_api_disconnect(mNativeWindow.get(), 4227 NATIVE_WINDOW_API_CPU); 4228 native_window_api_connect(mNativeWindow.get(), 4229 NATIVE_WINDOW_API_MEDIA); 4230 4231 return err; 4232 } else { 4233 // Clean up after success. 4234 err = native_window_api_disconnect(mNativeWindow.get(), 4235 NATIVE_WINDOW_API_CPU); 4236 if (err != NO_ERROR) { 4237 ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)", 4238 strerror(-err), -err); 4239 return err; 4240 } 4241 4242 err = native_window_api_connect(mNativeWindow.get(), 4243 NATIVE_WINDOW_API_MEDIA); 4244 if (err != NO_ERROR) { 4245 ALOGE("error pushing blank frames: api_connect failed: %s (%d)", 4246 strerror(-err), -err); 4247 return err; 4248 } 4249 4250 return NO_ERROR; 4251 } 4252} 4253 4254//////////////////////////////////////////////////////////////////////////////// 4255 4256ACodec::PortDescription::PortDescription() { 4257} 4258 4259status_t ACodec::requestIDRFrame() { 4260 if (!mIsEncoder) { 4261 return ERROR_UNSUPPORTED; 4262 } 4263 4264 OMX_CONFIG_INTRAREFRESHVOPTYPE params; 4265 InitOMXParams(¶ms); 4266 4267 params.nPortIndex = kPortIndexOutput; 4268 params.IntraRefreshVOP = OMX_TRUE; 4269 4270 return mOMX->setConfig( 4271 mNode, 4272 OMX_IndexConfigVideoIntraVOPRefresh, 4273 ¶ms, 4274 sizeof(params)); 4275} 4276 4277void ACodec::PortDescription::addBuffer( 4278 IOMX::buffer_id id, const sp<ABuffer> &buffer) { 4279 mBufferIDs.push_back(id); 4280 mBuffers.push_back(buffer); 4281} 4282 4283size_t ACodec::PortDescription::countBuffers() { 4284 return mBufferIDs.size(); 4285} 4286 4287IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const { 4288 return mBufferIDs.itemAt(index); 4289} 4290 4291sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const { 4292 return mBuffers.itemAt(index); 4293} 4294 4295//////////////////////////////////////////////////////////////////////////////// 4296 4297ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState) 4298 : AState(parentState), 4299 mCodec(codec) { 4300} 4301 4302ACodec::BaseState::PortMode ACodec::BaseState::getPortMode( 4303 OMX_U32 /* portIndex */) { 4304 return KEEP_BUFFERS; 4305} 4306 4307bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) { 4308 switch (msg->what()) { 4309 case kWhatInputBufferFilled: 4310 { 4311 onInputBufferFilled(msg); 4312 break; 4313 } 4314 4315 case kWhatOutputBufferDrained: 4316 { 4317 onOutputBufferDrained(msg); 4318 break; 4319 } 4320 4321 case ACodec::kWhatOMXMessage: 4322 { 4323 return onOMXMessage(msg); 4324 } 4325 4326 case ACodec::kWhatSetSurface: 4327 { 4328 sp<AReplyToken> replyID; 4329 CHECK(msg->senderAwaitsResponse(&replyID)); 4330 4331 sp<RefBase> obj; 4332 CHECK(msg->findObject("surface", &obj)); 4333 4334 status_t err = mCodec->handleSetSurface(static_cast<Surface *>(obj.get())); 4335 4336 sp<AMessage> response = new AMessage; 4337 response->setInt32("err", err); 4338 response->postReply(replyID); 4339 break; 4340 } 4341 4342 case ACodec::kWhatCreateInputSurface: 4343 case ACodec::kWhatUsePersistentInputSurface: 4344 case ACodec::kWhatSignalEndOfInputStream: 4345 { 4346 // This may result in an app illegal state exception. 4347 ALOGE("Message 0x%x was not handled", msg->what()); 4348 mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION); 4349 return true; 4350 } 4351 4352 case ACodec::kWhatOMXDied: 4353 { 4354 // This will result in kFlagSawMediaServerDie handling in MediaCodec. 4355 ALOGE("OMX/mediaserver died, signalling error!"); 4356 mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT); 4357 break; 4358 } 4359 4360 case ACodec::kWhatReleaseCodecInstance: 4361 { 4362 ALOGI("[%s] forcing the release of codec", 4363 mCodec->mComponentName.c_str()); 4364 status_t err = mCodec->mOMX->freeNode(mCodec->mNode); 4365 ALOGE_IF("[%s] failed to release codec instance: err=%d", 4366 mCodec->mComponentName.c_str(), err); 4367 sp<AMessage> notify = mCodec->mNotify->dup(); 4368 notify->setInt32("what", CodecBase::kWhatShutdownCompleted); 4369 notify->post(); 4370 break; 4371 } 4372 4373 default: 4374 return false; 4375 } 4376 4377 return true; 4378} 4379 4380bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) { 4381 int32_t type; 4382 CHECK(msg->findInt32("type", &type)); 4383 4384 // there is a possibility that this is an outstanding message for a 4385 // codec that we have already destroyed 4386 if (mCodec->mNode == 0) { 4387 ALOGI("ignoring message as already freed component: %s", 4388 msg->debugString().c_str()); 4389 return true; 4390 } 4391 4392 IOMX::node_id nodeID; 4393 CHECK(msg->findInt32("node", (int32_t*)&nodeID)); 4394 CHECK_EQ(nodeID, mCodec->mNode); 4395 4396 switch (type) { 4397 case omx_message::EVENT: 4398 { 4399 int32_t event, data1, data2; 4400 CHECK(msg->findInt32("event", &event)); 4401 CHECK(msg->findInt32("data1", &data1)); 4402 CHECK(msg->findInt32("data2", &data2)); 4403 4404 if (event == OMX_EventCmdComplete 4405 && data1 == OMX_CommandFlush 4406 && data2 == (int32_t)OMX_ALL) { 4407 // Use of this notification is not consistent across 4408 // implementations. We'll drop this notification and rely 4409 // on flush-complete notifications on the individual port 4410 // indices instead. 4411 4412 return true; 4413 } 4414 4415 return onOMXEvent( 4416 static_cast<OMX_EVENTTYPE>(event), 4417 static_cast<OMX_U32>(data1), 4418 static_cast<OMX_U32>(data2)); 4419 } 4420 4421 case omx_message::EMPTY_BUFFER_DONE: 4422 { 4423 IOMX::buffer_id bufferID; 4424 CHECK(msg->findInt32("buffer", (int32_t*)&bufferID)); 4425 4426 return onOMXEmptyBufferDone(bufferID); 4427 } 4428 4429 case omx_message::FILL_BUFFER_DONE: 4430 { 4431 IOMX::buffer_id bufferID; 4432 CHECK(msg->findInt32("buffer", (int32_t*)&bufferID)); 4433 4434 int32_t rangeOffset, rangeLength, flags; 4435 int64_t timeUs; 4436 4437 CHECK(msg->findInt32("range_offset", &rangeOffset)); 4438 CHECK(msg->findInt32("range_length", &rangeLength)); 4439 CHECK(msg->findInt32("flags", &flags)); 4440 CHECK(msg->findInt64("timestamp", &timeUs)); 4441 4442 return onOMXFillBufferDone( 4443 bufferID, 4444 (size_t)rangeOffset, (size_t)rangeLength, 4445 (OMX_U32)flags, 4446 timeUs); 4447 } 4448 4449 default: 4450 TRESPASS(); 4451 break; 4452 } 4453} 4454 4455bool ACodec::BaseState::onOMXEvent( 4456 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 4457 if (event != OMX_EventError) { 4458 ALOGV("[%s] EVENT(%d, 0x%08x, 0x%08x)", 4459 mCodec->mComponentName.c_str(), event, data1, data2); 4460 4461 return false; 4462 } 4463 4464 ALOGE("[%s] ERROR(0x%08x)", mCodec->mComponentName.c_str(), data1); 4465 4466 // verify OMX component sends back an error we expect. 4467 OMX_ERRORTYPE omxError = (OMX_ERRORTYPE)data1; 4468 if (!isOMXError(omxError)) { 4469 ALOGW("Invalid OMX error %#x", omxError); 4470 omxError = OMX_ErrorUndefined; 4471 } 4472 mCodec->signalError(omxError); 4473 4474 return true; 4475} 4476 4477bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) { 4478 ALOGV("[%s] onOMXEmptyBufferDone %u", 4479 mCodec->mComponentName.c_str(), bufferID); 4480 4481 BufferInfo *info = 4482 mCodec->findBufferByID(kPortIndexInput, bufferID); 4483 4484 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); 4485 info->mStatus = BufferInfo::OWNED_BY_US; 4486 4487 // We're in "store-metadata-in-buffers" mode, the underlying 4488 // OMX component had access to data that's implicitly refcounted 4489 // by this "MediaBuffer" object. Now that the OMX component has 4490 // told us that it's done with the input buffer, we can decrement 4491 // the mediaBuffer's reference count. 4492 info->mData->setMediaBufferBase(NULL); 4493 4494 PortMode mode = getPortMode(kPortIndexInput); 4495 4496 switch (mode) { 4497 case KEEP_BUFFERS: 4498 break; 4499 4500 case RESUBMIT_BUFFERS: 4501 postFillThisBuffer(info); 4502 break; 4503 4504 default: 4505 { 4506 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 4507 TRESPASS(); // Not currently used 4508 break; 4509 } 4510 } 4511 4512 return true; 4513} 4514 4515void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) { 4516 if (mCodec->mPortEOS[kPortIndexInput]) { 4517 return; 4518 } 4519 4520 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 4521 4522 sp<AMessage> notify = mCodec->mNotify->dup(); 4523 notify->setInt32("what", CodecBase::kWhatFillThisBuffer); 4524 notify->setInt32("buffer-id", info->mBufferID); 4525 4526 info->mData->meta()->clear(); 4527 notify->setBuffer("buffer", info->mData); 4528 4529 sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec); 4530 reply->setInt32("buffer-id", info->mBufferID); 4531 4532 notify->setMessage("reply", reply); 4533 4534 notify->post(); 4535 4536 info->mStatus = BufferInfo::OWNED_BY_UPSTREAM; 4537} 4538 4539void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { 4540 IOMX::buffer_id bufferID; 4541 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID)); 4542 sp<ABuffer> buffer; 4543 int32_t err = OK; 4544 bool eos = false; 4545 PortMode mode = getPortMode(kPortIndexInput); 4546 4547 if (!msg->findBuffer("buffer", &buffer)) { 4548 /* these are unfilled buffers returned by client */ 4549 CHECK(msg->findInt32("err", &err)); 4550 4551 if (err == OK) { 4552 /* buffers with no errors are returned on MediaCodec.flush */ 4553 mode = KEEP_BUFFERS; 4554 } else { 4555 ALOGV("[%s] saw error %d instead of an input buffer", 4556 mCodec->mComponentName.c_str(), err); 4557 eos = true; 4558 } 4559 4560 buffer.clear(); 4561 } 4562 4563 int32_t tmp; 4564 if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) { 4565 eos = true; 4566 err = ERROR_END_OF_STREAM; 4567 } 4568 4569 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID); 4570 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM); 4571 4572 info->mStatus = BufferInfo::OWNED_BY_US; 4573 4574 switch (mode) { 4575 case KEEP_BUFFERS: 4576 { 4577 if (eos) { 4578 if (!mCodec->mPortEOS[kPortIndexInput]) { 4579 mCodec->mPortEOS[kPortIndexInput] = true; 4580 mCodec->mInputEOSResult = err; 4581 } 4582 } 4583 break; 4584 } 4585 4586 case RESUBMIT_BUFFERS: 4587 { 4588 if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) { 4589 int64_t timeUs; 4590 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 4591 4592 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME; 4593 4594 int32_t isCSD; 4595 if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) { 4596 flags |= OMX_BUFFERFLAG_CODECCONFIG; 4597 } 4598 4599 if (eos) { 4600 flags |= OMX_BUFFERFLAG_EOS; 4601 } 4602 4603 if (buffer != info->mData) { 4604 ALOGV("[%s] Needs to copy input data for buffer %u. (%p != %p)", 4605 mCodec->mComponentName.c_str(), 4606 bufferID, 4607 buffer.get(), info->mData.get()); 4608 4609 CHECK_LE(buffer->size(), info->mData->capacity()); 4610 memcpy(info->mData->data(), buffer->data(), buffer->size()); 4611 } 4612 4613 if (flags & OMX_BUFFERFLAG_CODECCONFIG) { 4614 ALOGV("[%s] calling emptyBuffer %u w/ codec specific data", 4615 mCodec->mComponentName.c_str(), bufferID); 4616 } else if (flags & OMX_BUFFERFLAG_EOS) { 4617 ALOGV("[%s] calling emptyBuffer %u w/ EOS", 4618 mCodec->mComponentName.c_str(), bufferID); 4619 } else { 4620#if TRACK_BUFFER_TIMING 4621 ALOGI("[%s] calling emptyBuffer %u w/ time %lld us", 4622 mCodec->mComponentName.c_str(), bufferID, (long long)timeUs); 4623#else 4624 ALOGV("[%s] calling emptyBuffer %u w/ time %lld us", 4625 mCodec->mComponentName.c_str(), bufferID, (long long)timeUs); 4626#endif 4627 } 4628 4629#if TRACK_BUFFER_TIMING 4630 ACodec::BufferStats stats; 4631 stats.mEmptyBufferTimeUs = ALooper::GetNowUs(); 4632 stats.mFillBufferDoneTimeUs = -1ll; 4633 mCodec->mBufferStats.add(timeUs, stats); 4634#endif 4635 4636 if (mCodec->mStoreMetaDataInOutputBuffers) { 4637 // try to submit an output buffer for each input buffer 4638 PortMode outputMode = getPortMode(kPortIndexOutput); 4639 4640 ALOGV("MetaDataBuffersToSubmit=%u portMode=%s", 4641 mCodec->mMetaDataBuffersToSubmit, 4642 (outputMode == FREE_BUFFERS ? "FREE" : 4643 outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT")); 4644 if (outputMode == RESUBMIT_BUFFERS) { 4645 mCodec->submitOutputMetaDataBuffer(); 4646 } 4647 } 4648 4649 CHECK_EQ(mCodec->mOMX->emptyBuffer( 4650 mCodec->mNode, 4651 bufferID, 4652 0, 4653 buffer->size(), 4654 flags, 4655 timeUs), 4656 (status_t)OK); 4657 4658 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 4659 4660 if (!eos) { 4661 getMoreInputDataIfPossible(); 4662 } else { 4663 ALOGV("[%s] Signalled EOS on the input port", 4664 mCodec->mComponentName.c_str()); 4665 4666 mCodec->mPortEOS[kPortIndexInput] = true; 4667 mCodec->mInputEOSResult = err; 4668 } 4669 } else if (!mCodec->mPortEOS[kPortIndexInput]) { 4670 if (err != ERROR_END_OF_STREAM) { 4671 ALOGV("[%s] Signalling EOS on the input port " 4672 "due to error %d", 4673 mCodec->mComponentName.c_str(), err); 4674 } else { 4675 ALOGV("[%s] Signalling EOS on the input port", 4676 mCodec->mComponentName.c_str()); 4677 } 4678 4679 ALOGV("[%s] calling emptyBuffer %u signalling EOS", 4680 mCodec->mComponentName.c_str(), bufferID); 4681 4682 CHECK_EQ(mCodec->mOMX->emptyBuffer( 4683 mCodec->mNode, 4684 bufferID, 4685 0, 4686 0, 4687 OMX_BUFFERFLAG_EOS, 4688 0), 4689 (status_t)OK); 4690 4691 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 4692 4693 mCodec->mPortEOS[kPortIndexInput] = true; 4694 mCodec->mInputEOSResult = err; 4695 } 4696 break; 4697 } 4698 4699 default: 4700 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 4701 break; 4702 } 4703} 4704 4705void ACodec::BaseState::getMoreInputDataIfPossible() { 4706 if (mCodec->mPortEOS[kPortIndexInput]) { 4707 return; 4708 } 4709 4710 BufferInfo *eligible = NULL; 4711 4712 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 4713 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 4714 4715#if 0 4716 if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) { 4717 // There's already a "read" pending. 4718 return; 4719 } 4720#endif 4721 4722 if (info->mStatus == BufferInfo::OWNED_BY_US) { 4723 eligible = info; 4724 } 4725 } 4726 4727 if (eligible == NULL) { 4728 return; 4729 } 4730 4731 postFillThisBuffer(eligible); 4732} 4733 4734bool ACodec::BaseState::onOMXFillBufferDone( 4735 IOMX::buffer_id bufferID, 4736 size_t rangeOffset, size_t rangeLength, 4737 OMX_U32 flags, 4738 int64_t timeUs) { 4739 ALOGV("[%s] onOMXFillBufferDone %u time %" PRId64 " us, flags = 0x%08x", 4740 mCodec->mComponentName.c_str(), bufferID, timeUs, flags); 4741 4742 ssize_t index; 4743 4744#if TRACK_BUFFER_TIMING 4745 index = mCodec->mBufferStats.indexOfKey(timeUs); 4746 if (index >= 0) { 4747 ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index); 4748 stats->mFillBufferDoneTimeUs = ALooper::GetNowUs(); 4749 4750 ALOGI("frame PTS %lld: %lld", 4751 timeUs, 4752 stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs); 4753 4754 mCodec->mBufferStats.removeItemsAt(index); 4755 stats = NULL; 4756 } 4757#endif 4758 4759 BufferInfo *info = 4760 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 4761 4762 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); 4763 4764 info->mDequeuedAt = ++mCodec->mDequeueCounter; 4765 info->mStatus = BufferInfo::OWNED_BY_US; 4766 4767 PortMode mode = getPortMode(kPortIndexOutput); 4768 4769 switch (mode) { 4770 case KEEP_BUFFERS: 4771 break; 4772 4773 case RESUBMIT_BUFFERS: 4774 { 4775 if (rangeLength == 0 && (!(flags & OMX_BUFFERFLAG_EOS) 4776 || mCodec->mPortEOS[kPortIndexOutput])) { 4777 ALOGV("[%s] calling fillBuffer %u", 4778 mCodec->mComponentName.c_str(), info->mBufferID); 4779 4780 CHECK_EQ(mCodec->mOMX->fillBuffer( 4781 mCodec->mNode, info->mBufferID), 4782 (status_t)OK); 4783 4784 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 4785 break; 4786 } 4787 4788 sp<AMessage> reply = 4789 new AMessage(kWhatOutputBufferDrained, mCodec); 4790 4791 if (!mCodec->mSentFormat && rangeLength > 0) { 4792 mCodec->sendFormatChange(reply); 4793 } 4794 4795 if (mCodec->mUseMetadataOnEncoderOutput) { 4796 native_handle_t* handle = 4797 *(native_handle_t**)(info->mData->data() + 4); 4798 info->mData->meta()->setPointer("handle", handle); 4799 info->mData->meta()->setInt32("rangeOffset", rangeOffset); 4800 info->mData->meta()->setInt32("rangeLength", rangeLength); 4801 } else { 4802 info->mData->setRange(rangeOffset, rangeLength); 4803 } 4804#if 0 4805 if (mCodec->mNativeWindow == NULL) { 4806 if (IsIDR(info->mData)) { 4807 ALOGI("IDR frame"); 4808 } 4809 } 4810#endif 4811 4812 if (mCodec->mSkipCutBuffer != NULL) { 4813 mCodec->mSkipCutBuffer->submit(info->mData); 4814 } 4815 info->mData->meta()->setInt64("timeUs", timeUs); 4816 4817 sp<AMessage> notify = mCodec->mNotify->dup(); 4818 notify->setInt32("what", CodecBase::kWhatDrainThisBuffer); 4819 notify->setInt32("buffer-id", info->mBufferID); 4820 notify->setBuffer("buffer", info->mData); 4821 notify->setInt32("flags", flags); 4822 4823 reply->setInt32("buffer-id", info->mBufferID); 4824 4825 notify->setMessage("reply", reply); 4826 4827 notify->post(); 4828 4829 info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM; 4830 4831 if (flags & OMX_BUFFERFLAG_EOS) { 4832 ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str()); 4833 4834 sp<AMessage> notify = mCodec->mNotify->dup(); 4835 notify->setInt32("what", CodecBase::kWhatEOS); 4836 notify->setInt32("err", mCodec->mInputEOSResult); 4837 notify->post(); 4838 4839 mCodec->mPortEOS[kPortIndexOutput] = true; 4840 } 4841 break; 4842 } 4843 4844 default: 4845 { 4846 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 4847 4848 CHECK_EQ((status_t)OK, 4849 mCodec->freeBuffer(kPortIndexOutput, index)); 4850 break; 4851 } 4852 } 4853 4854 return true; 4855} 4856 4857void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { 4858 IOMX::buffer_id bufferID; 4859 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID)); 4860 ssize_t index; 4861 BufferInfo *info = 4862 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 4863 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM); 4864 4865 android_native_rect_t crop; 4866 if (msg->findRect("crop", 4867 &crop.left, &crop.top, &crop.right, &crop.bottom)) { 4868 CHECK_EQ(0, native_window_set_crop( 4869 mCodec->mNativeWindow.get(), &crop)); 4870 } 4871 4872 int32_t render; 4873 if (mCodec->mNativeWindow != NULL 4874 && msg->findInt32("render", &render) && render != 0 4875 && info->mData != NULL && info->mData->size() != 0) { 4876 ATRACE_NAME("render"); 4877 // The client wants this buffer to be rendered. 4878 4879 int64_t timestampNs = 0; 4880 if (!msg->findInt64("timestampNs", ×tampNs)) { 4881 // TODO: it seems like we should use the timestamp 4882 // in the (media)buffer as it potentially came from 4883 // an input surface, but we did not propagate it prior to 4884 // API 20. Perhaps check for target SDK version. 4885#if 0 4886 if (info->mData->meta()->findInt64("timeUs", ×tampNs)) { 4887 ALOGV("using buffer PTS of %" PRId64, timestampNs); 4888 timestampNs *= 1000; 4889 } 4890#endif 4891 } 4892 4893 status_t err; 4894 err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs); 4895 if (err != OK) { 4896 ALOGW("failed to set buffer timestamp: %d", err); 4897 } 4898 4899 if ((err = mCodec->mNativeWindow->queueBuffer( 4900 mCodec->mNativeWindow.get(), 4901 info->mGraphicBuffer.get(), -1)) == OK) { 4902 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 4903 } else { 4904 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 4905 info->mStatus = BufferInfo::OWNED_BY_US; 4906 } 4907 } else { 4908 if (mCodec->mNativeWindow != NULL && 4909 (info->mData == NULL || info->mData->size() != 0)) { 4910 ATRACE_NAME("frame-drop"); 4911 } 4912 info->mStatus = BufferInfo::OWNED_BY_US; 4913 } 4914 4915 PortMode mode = getPortMode(kPortIndexOutput); 4916 4917 switch (mode) { 4918 case KEEP_BUFFERS: 4919 { 4920 // XXX fishy, revisit!!! What about the FREE_BUFFERS case below? 4921 4922 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 4923 // We cannot resubmit the buffer we just rendered, dequeue 4924 // the spare instead. 4925 4926 info = mCodec->dequeueBufferFromNativeWindow(); 4927 } 4928 break; 4929 } 4930 4931 case RESUBMIT_BUFFERS: 4932 { 4933 if (!mCodec->mPortEOS[kPortIndexOutput]) { 4934 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 4935 // We cannot resubmit the buffer we just rendered, dequeue 4936 // the spare instead. 4937 4938 info = mCodec->dequeueBufferFromNativeWindow(); 4939 } 4940 4941 if (info != NULL) { 4942 ALOGV("[%s] calling fillBuffer %u", 4943 mCodec->mComponentName.c_str(), info->mBufferID); 4944 4945 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), 4946 (status_t)OK); 4947 4948 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 4949 } 4950 } 4951 break; 4952 } 4953 4954 default: 4955 { 4956 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 4957 4958 CHECK_EQ((status_t)OK, 4959 mCodec->freeBuffer(kPortIndexOutput, index)); 4960 break; 4961 } 4962 } 4963} 4964 4965//////////////////////////////////////////////////////////////////////////////// 4966 4967ACodec::UninitializedState::UninitializedState(ACodec *codec) 4968 : BaseState(codec) { 4969} 4970 4971void ACodec::UninitializedState::stateEntered() { 4972 ALOGV("Now uninitialized"); 4973 4974 if (mDeathNotifier != NULL) { 4975 IInterface::asBinder(mCodec->mOMX)->unlinkToDeath(mDeathNotifier); 4976 mDeathNotifier.clear(); 4977 } 4978 4979 mCodec->mNativeWindow.clear(); 4980 mCodec->mNode = 0; 4981 mCodec->mOMX.clear(); 4982 mCodec->mQuirks = 0; 4983 mCodec->mFlags = 0; 4984 mCodec->mUseMetadataOnEncoderOutput = 0; 4985 mCodec->mComponentName.clear(); 4986} 4987 4988bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) { 4989 bool handled = false; 4990 4991 switch (msg->what()) { 4992 case ACodec::kWhatSetup: 4993 { 4994 onSetup(msg); 4995 4996 handled = true; 4997 break; 4998 } 4999 5000 case ACodec::kWhatAllocateComponent: 5001 { 5002 onAllocateComponent(msg); 5003 handled = true; 5004 break; 5005 } 5006 5007 case ACodec::kWhatShutdown: 5008 { 5009 int32_t keepComponentAllocated; 5010 CHECK(msg->findInt32( 5011 "keepComponentAllocated", &keepComponentAllocated)); 5012 ALOGW_IF(keepComponentAllocated, 5013 "cannot keep component allocated on shutdown in Uninitialized state"); 5014 5015 sp<AMessage> notify = mCodec->mNotify->dup(); 5016 notify->setInt32("what", CodecBase::kWhatShutdownCompleted); 5017 notify->post(); 5018 5019 handled = true; 5020 break; 5021 } 5022 5023 case ACodec::kWhatFlush: 5024 { 5025 sp<AMessage> notify = mCodec->mNotify->dup(); 5026 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 5027 notify->post(); 5028 5029 handled = true; 5030 break; 5031 } 5032 5033 case ACodec::kWhatReleaseCodecInstance: 5034 { 5035 // nothing to do, as we have already signaled shutdown 5036 handled = true; 5037 break; 5038 } 5039 5040 default: 5041 return BaseState::onMessageReceived(msg); 5042 } 5043 5044 return handled; 5045} 5046 5047void ACodec::UninitializedState::onSetup( 5048 const sp<AMessage> &msg) { 5049 if (onAllocateComponent(msg) 5050 && mCodec->mLoadedState->onConfigureComponent(msg)) { 5051 mCodec->mLoadedState->onStart(); 5052 } 5053} 5054 5055bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) { 5056 ALOGV("onAllocateComponent"); 5057 5058 CHECK(mCodec->mNode == 0); 5059 5060 OMXClient client; 5061 if (client.connect() != OK) { 5062 mCodec->signalError(OMX_ErrorUndefined, NO_INIT); 5063 return false; 5064 } 5065 5066 sp<IOMX> omx = client.interface(); 5067 5068 sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec); 5069 5070 mDeathNotifier = new DeathNotifier(notify); 5071 if (IInterface::asBinder(omx)->linkToDeath(mDeathNotifier) != OK) { 5072 // This was a local binder, if it dies so do we, we won't care 5073 // about any notifications in the afterlife. 5074 mDeathNotifier.clear(); 5075 } 5076 5077 Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs; 5078 5079 AString mime; 5080 5081 AString componentName; 5082 uint32_t quirks = 0; 5083 int32_t encoder = false; 5084 if (msg->findString("componentName", &componentName)) { 5085 ssize_t index = matchingCodecs.add(); 5086 OMXCodec::CodecNameAndQuirks *entry = &matchingCodecs.editItemAt(index); 5087 entry->mName = String8(componentName.c_str()); 5088 5089 if (!OMXCodec::findCodecQuirks( 5090 componentName.c_str(), &entry->mQuirks)) { 5091 entry->mQuirks = 0; 5092 } 5093 } else { 5094 CHECK(msg->findString("mime", &mime)); 5095 5096 if (!msg->findInt32("encoder", &encoder)) { 5097 encoder = false; 5098 } 5099 5100 OMXCodec::findMatchingCodecs( 5101 mime.c_str(), 5102 encoder, // createEncoder 5103 NULL, // matchComponentName 5104 0, // flags 5105 &matchingCodecs); 5106 } 5107 5108 sp<CodecObserver> observer = new CodecObserver; 5109 IOMX::node_id node = 0; 5110 5111 status_t err = OMX_ErrorComponentNotFound; 5112 for (size_t matchIndex = 0; matchIndex < matchingCodecs.size(); 5113 ++matchIndex) { 5114 componentName = matchingCodecs.itemAt(matchIndex).mName.string(); 5115 quirks = matchingCodecs.itemAt(matchIndex).mQuirks; 5116 5117 pid_t tid = gettid(); 5118 int prevPriority = androidGetThreadPriority(tid); 5119 androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND); 5120 err = omx->allocateNode(componentName.c_str(), observer, &node); 5121 androidSetThreadPriority(tid, prevPriority); 5122 5123 if (err == OK) { 5124 break; 5125 } else { 5126 ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str()); 5127 } 5128 5129 node = 0; 5130 } 5131 5132 if (node == 0) { 5133 if (!mime.empty()) { 5134 ALOGE("Unable to instantiate a %scoder for type '%s' with err %#x.", 5135 encoder ? "en" : "de", mime.c_str(), err); 5136 } else { 5137 ALOGE("Unable to instantiate codec '%s' with err %#x.", componentName.c_str(), err); 5138 } 5139 5140 mCodec->signalError((OMX_ERRORTYPE)err, makeNoSideEffectStatus(err)); 5141 return false; 5142 } 5143 5144 notify = new AMessage(kWhatOMXMessage, mCodec); 5145 observer->setNotificationMessage(notify); 5146 5147 mCodec->mComponentName = componentName; 5148 mCodec->mFlags = 0; 5149 5150 if (componentName.endsWith(".secure")) { 5151 mCodec->mFlags |= kFlagIsSecure; 5152 mCodec->mFlags |= kFlagIsGrallocUsageProtected; 5153 mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown; 5154 } 5155 5156 mCodec->mQuirks = quirks; 5157 mCodec->mOMX = omx; 5158 mCodec->mNode = node; 5159 5160 { 5161 sp<AMessage> notify = mCodec->mNotify->dup(); 5162 notify->setInt32("what", CodecBase::kWhatComponentAllocated); 5163 notify->setString("componentName", mCodec->mComponentName.c_str()); 5164 notify->post(); 5165 } 5166 5167 mCodec->changeState(mCodec->mLoadedState); 5168 5169 return true; 5170} 5171 5172//////////////////////////////////////////////////////////////////////////////// 5173 5174ACodec::LoadedState::LoadedState(ACodec *codec) 5175 : BaseState(codec) { 5176} 5177 5178void ACodec::LoadedState::stateEntered() { 5179 ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str()); 5180 5181 mCodec->mPortEOS[kPortIndexInput] = 5182 mCodec->mPortEOS[kPortIndexOutput] = false; 5183 5184 mCodec->mInputEOSResult = OK; 5185 5186 mCodec->mDequeueCounter = 0; 5187 mCodec->mMetaDataBuffersToSubmit = 0; 5188 mCodec->mRepeatFrameDelayUs = -1ll; 5189 mCodec->mInputFormat.clear(); 5190 mCodec->mOutputFormat.clear(); 5191 mCodec->mBaseOutputFormat.clear(); 5192 5193 if (mCodec->mShutdownInProgress) { 5194 bool keepComponentAllocated = mCodec->mKeepComponentAllocated; 5195 5196 mCodec->mShutdownInProgress = false; 5197 mCodec->mKeepComponentAllocated = false; 5198 5199 onShutdown(keepComponentAllocated); 5200 } 5201 mCodec->mExplicitShutdown = false; 5202 5203 mCodec->processDeferredMessages(); 5204} 5205 5206void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) { 5207 if (!keepComponentAllocated) { 5208 CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK); 5209 5210 mCodec->changeState(mCodec->mUninitializedState); 5211 } 5212 5213 if (mCodec->mExplicitShutdown) { 5214 sp<AMessage> notify = mCodec->mNotify->dup(); 5215 notify->setInt32("what", CodecBase::kWhatShutdownCompleted); 5216 notify->post(); 5217 mCodec->mExplicitShutdown = false; 5218 } 5219} 5220 5221bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) { 5222 bool handled = false; 5223 5224 switch (msg->what()) { 5225 case ACodec::kWhatConfigureComponent: 5226 { 5227 onConfigureComponent(msg); 5228 handled = true; 5229 break; 5230 } 5231 5232 case ACodec::kWhatCreateInputSurface: 5233 { 5234 onCreateInputSurface(msg); 5235 handled = true; 5236 break; 5237 } 5238 5239 case ACodec::kWhatUsePersistentInputSurface: 5240 { 5241 onUsePersistentInputSurface(msg); 5242 handled = true; 5243 break; 5244 } 5245 5246 case ACodec::kWhatStart: 5247 { 5248 onStart(); 5249 handled = true; 5250 break; 5251 } 5252 5253 case ACodec::kWhatShutdown: 5254 { 5255 int32_t keepComponentAllocated; 5256 CHECK(msg->findInt32( 5257 "keepComponentAllocated", &keepComponentAllocated)); 5258 5259 mCodec->mExplicitShutdown = true; 5260 onShutdown(keepComponentAllocated); 5261 5262 handled = true; 5263 break; 5264 } 5265 5266 case ACodec::kWhatFlush: 5267 { 5268 sp<AMessage> notify = mCodec->mNotify->dup(); 5269 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 5270 notify->post(); 5271 5272 handled = true; 5273 break; 5274 } 5275 5276 default: 5277 return BaseState::onMessageReceived(msg); 5278 } 5279 5280 return handled; 5281} 5282 5283bool ACodec::LoadedState::onConfigureComponent( 5284 const sp<AMessage> &msg) { 5285 ALOGV("onConfigureComponent"); 5286 5287 CHECK(mCodec->mNode != 0); 5288 5289 AString mime; 5290 CHECK(msg->findString("mime", &mime)); 5291 5292 status_t err = mCodec->configureCodec(mime.c_str(), msg); 5293 5294 if (err != OK) { 5295 ALOGE("[%s] configureCodec returning error %d", 5296 mCodec->mComponentName.c_str(), err); 5297 5298 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 5299 return false; 5300 } 5301 5302 { 5303 sp<AMessage> notify = mCodec->mNotify->dup(); 5304 notify->setInt32("what", CodecBase::kWhatComponentConfigured); 5305 notify->setMessage("input-format", mCodec->mInputFormat); 5306 notify->setMessage("output-format", mCodec->mOutputFormat); 5307 notify->post(); 5308 } 5309 5310 return true; 5311} 5312 5313status_t ACodec::LoadedState::setupInputSurface() { 5314 status_t err = OK; 5315 5316 if (mCodec->mRepeatFrameDelayUs > 0ll) { 5317 err = mCodec->mOMX->setInternalOption( 5318 mCodec->mNode, 5319 kPortIndexInput, 5320 IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY, 5321 &mCodec->mRepeatFrameDelayUs, 5322 sizeof(mCodec->mRepeatFrameDelayUs)); 5323 5324 if (err != OK) { 5325 ALOGE("[%s] Unable to configure option to repeat previous " 5326 "frames (err %d)", 5327 mCodec->mComponentName.c_str(), 5328 err); 5329 return err; 5330 } 5331 } 5332 5333 if (mCodec->mMaxPtsGapUs > 0ll) { 5334 err = mCodec->mOMX->setInternalOption( 5335 mCodec->mNode, 5336 kPortIndexInput, 5337 IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP, 5338 &mCodec->mMaxPtsGapUs, 5339 sizeof(mCodec->mMaxPtsGapUs)); 5340 5341 if (err != OK) { 5342 ALOGE("[%s] Unable to configure max timestamp gap (err %d)", 5343 mCodec->mComponentName.c_str(), 5344 err); 5345 return err; 5346 } 5347 } 5348 5349 if (mCodec->mMaxFps > 0) { 5350 err = mCodec->mOMX->setInternalOption( 5351 mCodec->mNode, 5352 kPortIndexInput, 5353 IOMX::INTERNAL_OPTION_MAX_FPS, 5354 &mCodec->mMaxFps, 5355 sizeof(mCodec->mMaxFps)); 5356 5357 if (err != OK) { 5358 ALOGE("[%s] Unable to configure max fps (err %d)", 5359 mCodec->mComponentName.c_str(), 5360 err); 5361 return err; 5362 } 5363 } 5364 5365 if (mCodec->mTimePerCaptureUs > 0ll 5366 && mCodec->mTimePerFrameUs > 0ll) { 5367 int64_t timeLapse[2]; 5368 timeLapse[0] = mCodec->mTimePerFrameUs; 5369 timeLapse[1] = mCodec->mTimePerCaptureUs; 5370 err = mCodec->mOMX->setInternalOption( 5371 mCodec->mNode, 5372 kPortIndexInput, 5373 IOMX::INTERNAL_OPTION_TIME_LAPSE, 5374 &timeLapse[0], 5375 sizeof(timeLapse)); 5376 5377 if (err != OK) { 5378 ALOGE("[%s] Unable to configure time lapse (err %d)", 5379 mCodec->mComponentName.c_str(), 5380 err); 5381 return err; 5382 } 5383 } 5384 5385 if (mCodec->mCreateInputBuffersSuspended) { 5386 bool suspend = true; 5387 err = mCodec->mOMX->setInternalOption( 5388 mCodec->mNode, 5389 kPortIndexInput, 5390 IOMX::INTERNAL_OPTION_SUSPEND, 5391 &suspend, 5392 sizeof(suspend)); 5393 5394 if (err != OK) { 5395 ALOGE("[%s] Unable to configure option to suspend (err %d)", 5396 mCodec->mComponentName.c_str(), 5397 err); 5398 return err; 5399 } 5400 } 5401 5402 return OK; 5403} 5404 5405void ACodec::LoadedState::onCreateInputSurface( 5406 const sp<AMessage> & /* msg */) { 5407 ALOGV("onCreateInputSurface"); 5408 5409 sp<AMessage> notify = mCodec->mNotify->dup(); 5410 notify->setInt32("what", CodecBase::kWhatInputSurfaceCreated); 5411 5412 sp<IGraphicBufferProducer> bufferProducer; 5413 status_t err = mCodec->mOMX->createInputSurface( 5414 mCodec->mNode, kPortIndexInput, &bufferProducer); 5415 5416 if (err == OK) { 5417 err = setupInputSurface(); 5418 } 5419 5420 if (err == OK) { 5421 notify->setObject("input-surface", 5422 new BufferProducerWrapper(bufferProducer)); 5423 } else { 5424 // Can't use mCodec->signalError() here -- MediaCodec won't forward 5425 // the error through because it's in the "configured" state. We 5426 // send a kWhatInputSurfaceCreated with an error value instead. 5427 ALOGE("[%s] onCreateInputSurface returning error %d", 5428 mCodec->mComponentName.c_str(), err); 5429 notify->setInt32("err", err); 5430 } 5431 notify->post(); 5432} 5433 5434void ACodec::LoadedState::onUsePersistentInputSurface( 5435 const sp<AMessage> &msg) { 5436 ALOGV("onUsePersistentInputSurface"); 5437 5438 sp<AMessage> notify = mCodec->mNotify->dup(); 5439 notify->setInt32("what", CodecBase::kWhatInputSurfaceAccepted); 5440 5441 sp<RefBase> obj; 5442 CHECK(msg->findObject("input-surface", &obj)); 5443 sp<PersistentSurface> surface = static_cast<PersistentSurface *>(obj.get()); 5444 5445 status_t err = mCodec->mOMX->usePersistentInputSurface( 5446 mCodec->mNode, kPortIndexInput, surface->getBufferConsumer()); 5447 5448 if (err == OK) { 5449 err = setupInputSurface(); 5450 } 5451 5452 if (err != OK) { 5453 // Can't use mCodec->signalError() here -- MediaCodec won't forward 5454 // the error through because it's in the "configured" state. We 5455 // send a kWhatInputSurfaceAccepted with an error value instead. 5456 ALOGE("[%s] onUsePersistentInputSurface returning error %d", 5457 mCodec->mComponentName.c_str(), err); 5458 notify->setInt32("err", err); 5459 } 5460 notify->post(); 5461} 5462 5463void ACodec::LoadedState::onStart() { 5464 ALOGV("onStart"); 5465 5466 CHECK_EQ(mCodec->mOMX->sendCommand( 5467 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle), 5468 (status_t)OK); 5469 5470 mCodec->changeState(mCodec->mLoadedToIdleState); 5471} 5472 5473//////////////////////////////////////////////////////////////////////////////// 5474 5475ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec) 5476 : BaseState(codec) { 5477} 5478 5479void ACodec::LoadedToIdleState::stateEntered() { 5480 ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str()); 5481 5482 status_t err; 5483 if ((err = allocateBuffers()) != OK) { 5484 ALOGE("Failed to allocate buffers after transitioning to IDLE state " 5485 "(error 0x%08x)", 5486 err); 5487 5488 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 5489 5490 mCodec->changeState(mCodec->mLoadedState); 5491 } 5492} 5493 5494status_t ACodec::LoadedToIdleState::allocateBuffers() { 5495 status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput); 5496 5497 if (err != OK) { 5498 return err; 5499 } 5500 5501 return mCodec->allocateBuffersOnPort(kPortIndexOutput); 5502} 5503 5504bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) { 5505 switch (msg->what()) { 5506 case kWhatSetParameters: 5507 case kWhatShutdown: 5508 { 5509 mCodec->deferMessage(msg); 5510 return true; 5511 } 5512 5513 case kWhatSignalEndOfInputStream: 5514 { 5515 mCodec->onSignalEndOfInputStream(); 5516 return true; 5517 } 5518 5519 case kWhatResume: 5520 { 5521 // We'll be active soon enough. 5522 return true; 5523 } 5524 5525 case kWhatFlush: 5526 { 5527 // We haven't even started yet, so we're flushed alright... 5528 sp<AMessage> notify = mCodec->mNotify->dup(); 5529 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 5530 notify->post(); 5531 return true; 5532 } 5533 5534 default: 5535 return BaseState::onMessageReceived(msg); 5536 } 5537} 5538 5539bool ACodec::LoadedToIdleState::onOMXEvent( 5540 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 5541 switch (event) { 5542 case OMX_EventCmdComplete: 5543 { 5544 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 5545 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); 5546 5547 CHECK_EQ(mCodec->mOMX->sendCommand( 5548 mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting), 5549 (status_t)OK); 5550 5551 mCodec->changeState(mCodec->mIdleToExecutingState); 5552 5553 return true; 5554 } 5555 5556 default: 5557 return BaseState::onOMXEvent(event, data1, data2); 5558 } 5559} 5560 5561//////////////////////////////////////////////////////////////////////////////// 5562 5563ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec) 5564 : BaseState(codec) { 5565} 5566 5567void ACodec::IdleToExecutingState::stateEntered() { 5568 ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str()); 5569} 5570 5571bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) { 5572 switch (msg->what()) { 5573 case kWhatSetParameters: 5574 case kWhatShutdown: 5575 { 5576 mCodec->deferMessage(msg); 5577 return true; 5578 } 5579 5580 case kWhatResume: 5581 { 5582 // We'll be active soon enough. 5583 return true; 5584 } 5585 5586 case kWhatFlush: 5587 { 5588 // We haven't even started yet, so we're flushed alright... 5589 sp<AMessage> notify = mCodec->mNotify->dup(); 5590 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 5591 notify->post(); 5592 5593 return true; 5594 } 5595 5596 case kWhatSignalEndOfInputStream: 5597 { 5598 mCodec->onSignalEndOfInputStream(); 5599 return true; 5600 } 5601 5602 default: 5603 return BaseState::onMessageReceived(msg); 5604 } 5605} 5606 5607bool ACodec::IdleToExecutingState::onOMXEvent( 5608 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 5609 switch (event) { 5610 case OMX_EventCmdComplete: 5611 { 5612 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 5613 CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting); 5614 5615 mCodec->mExecutingState->resume(); 5616 mCodec->changeState(mCodec->mExecutingState); 5617 5618 return true; 5619 } 5620 5621 default: 5622 return BaseState::onOMXEvent(event, data1, data2); 5623 } 5624} 5625 5626//////////////////////////////////////////////////////////////////////////////// 5627 5628ACodec::ExecutingState::ExecutingState(ACodec *codec) 5629 : BaseState(codec), 5630 mActive(false) { 5631} 5632 5633ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode( 5634 OMX_U32 /* portIndex */) { 5635 return RESUBMIT_BUFFERS; 5636} 5637 5638void ACodec::ExecutingState::submitOutputMetaBuffers() { 5639 // submit as many buffers as there are input buffers with the codec 5640 // in case we are in port reconfiguring 5641 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 5642 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 5643 5644 if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) { 5645 if (mCodec->submitOutputMetaDataBuffer() != OK) 5646 break; 5647 } 5648 } 5649 5650 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** 5651 mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround(); 5652} 5653 5654void ACodec::ExecutingState::submitRegularOutputBuffers() { 5655 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) { 5656 BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i); 5657 5658 if (mCodec->mNativeWindow != NULL) { 5659 CHECK(info->mStatus == BufferInfo::OWNED_BY_US 5660 || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW); 5661 5662 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 5663 continue; 5664 } 5665 } else { 5666 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 5667 } 5668 5669 ALOGV("[%s] calling fillBuffer %u", 5670 mCodec->mComponentName.c_str(), info->mBufferID); 5671 5672 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), 5673 (status_t)OK); 5674 5675 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 5676 } 5677} 5678 5679void ACodec::ExecutingState::submitOutputBuffers() { 5680 submitRegularOutputBuffers(); 5681 if (mCodec->mStoreMetaDataInOutputBuffers) { 5682 submitOutputMetaBuffers(); 5683 } 5684} 5685 5686void ACodec::ExecutingState::resume() { 5687 if (mActive) { 5688 ALOGV("[%s] We're already active, no need to resume.", 5689 mCodec->mComponentName.c_str()); 5690 5691 return; 5692 } 5693 5694 submitOutputBuffers(); 5695 5696 // Post all available input buffers 5697 CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u); 5698 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) { 5699 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 5700 if (info->mStatus == BufferInfo::OWNED_BY_US) { 5701 postFillThisBuffer(info); 5702 } 5703 } 5704 5705 mActive = true; 5706} 5707 5708void ACodec::ExecutingState::stateEntered() { 5709 ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str()); 5710 5711 mCodec->processDeferredMessages(); 5712} 5713 5714bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) { 5715 bool handled = false; 5716 5717 switch (msg->what()) { 5718 case kWhatShutdown: 5719 { 5720 int32_t keepComponentAllocated; 5721 CHECK(msg->findInt32( 5722 "keepComponentAllocated", &keepComponentAllocated)); 5723 5724 mCodec->mShutdownInProgress = true; 5725 mCodec->mExplicitShutdown = true; 5726 mCodec->mKeepComponentAllocated = keepComponentAllocated; 5727 5728 mActive = false; 5729 5730 CHECK_EQ(mCodec->mOMX->sendCommand( 5731 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle), 5732 (status_t)OK); 5733 5734 mCodec->changeState(mCodec->mExecutingToIdleState); 5735 5736 handled = true; 5737 break; 5738 } 5739 5740 case kWhatFlush: 5741 { 5742 ALOGV("[%s] ExecutingState flushing now " 5743 "(codec owns %zu/%zu input, %zu/%zu output).", 5744 mCodec->mComponentName.c_str(), 5745 mCodec->countBuffersOwnedByComponent(kPortIndexInput), 5746 mCodec->mBuffers[kPortIndexInput].size(), 5747 mCodec->countBuffersOwnedByComponent(kPortIndexOutput), 5748 mCodec->mBuffers[kPortIndexOutput].size()); 5749 5750 mActive = false; 5751 5752 CHECK_EQ(mCodec->mOMX->sendCommand( 5753 mCodec->mNode, OMX_CommandFlush, OMX_ALL), 5754 (status_t)OK); 5755 5756 mCodec->changeState(mCodec->mFlushingState); 5757 handled = true; 5758 break; 5759 } 5760 5761 case kWhatResume: 5762 { 5763 resume(); 5764 5765 handled = true; 5766 break; 5767 } 5768 5769 case kWhatRequestIDRFrame: 5770 { 5771 status_t err = mCodec->requestIDRFrame(); 5772 if (err != OK) { 5773 ALOGW("Requesting an IDR frame failed."); 5774 } 5775 5776 handled = true; 5777 break; 5778 } 5779 5780 case kWhatSetParameters: 5781 { 5782 sp<AMessage> params; 5783 CHECK(msg->findMessage("params", ¶ms)); 5784 5785 status_t err = mCodec->setParameters(params); 5786 5787 sp<AMessage> reply; 5788 if (msg->findMessage("reply", &reply)) { 5789 reply->setInt32("err", err); 5790 reply->post(); 5791 } 5792 5793 handled = true; 5794 break; 5795 } 5796 5797 case ACodec::kWhatSignalEndOfInputStream: 5798 { 5799 mCodec->onSignalEndOfInputStream(); 5800 handled = true; 5801 break; 5802 } 5803 5804 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** 5805 case kWhatSubmitOutputMetaDataBufferIfEOS: 5806 { 5807 if (mCodec->mPortEOS[kPortIndexInput] && 5808 !mCodec->mPortEOS[kPortIndexOutput]) { 5809 status_t err = mCodec->submitOutputMetaDataBuffer(); 5810 if (err == OK) { 5811 mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround(); 5812 } 5813 } 5814 return true; 5815 } 5816 5817 default: 5818 handled = BaseState::onMessageReceived(msg); 5819 break; 5820 } 5821 5822 return handled; 5823} 5824 5825status_t ACodec::setParameters(const sp<AMessage> ¶ms) { 5826 int32_t videoBitrate; 5827 if (params->findInt32("video-bitrate", &videoBitrate)) { 5828 OMX_VIDEO_CONFIG_BITRATETYPE configParams; 5829 InitOMXParams(&configParams); 5830 configParams.nPortIndex = kPortIndexOutput; 5831 configParams.nEncodeBitrate = videoBitrate; 5832 5833 status_t err = mOMX->setConfig( 5834 mNode, 5835 OMX_IndexConfigVideoBitrate, 5836 &configParams, 5837 sizeof(configParams)); 5838 5839 if (err != OK) { 5840 ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d", 5841 videoBitrate, err); 5842 5843 return err; 5844 } 5845 } 5846 5847 int64_t skipFramesBeforeUs; 5848 if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) { 5849 status_t err = 5850 mOMX->setInternalOption( 5851 mNode, 5852 kPortIndexInput, 5853 IOMX::INTERNAL_OPTION_START_TIME, 5854 &skipFramesBeforeUs, 5855 sizeof(skipFramesBeforeUs)); 5856 5857 if (err != OK) { 5858 ALOGE("Failed to set parameter 'skip-frames-before' (err %d)", err); 5859 return err; 5860 } 5861 } 5862 5863 int32_t dropInputFrames; 5864 if (params->findInt32("drop-input-frames", &dropInputFrames)) { 5865 bool suspend = dropInputFrames != 0; 5866 5867 status_t err = 5868 mOMX->setInternalOption( 5869 mNode, 5870 kPortIndexInput, 5871 IOMX::INTERNAL_OPTION_SUSPEND, 5872 &suspend, 5873 sizeof(suspend)); 5874 5875 if (err != OK) { 5876 ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err); 5877 return err; 5878 } 5879 } 5880 5881 int32_t dummy; 5882 if (params->findInt32("request-sync", &dummy)) { 5883 status_t err = requestIDRFrame(); 5884 5885 if (err != OK) { 5886 ALOGE("Requesting a sync frame failed w/ err %d", err); 5887 return err; 5888 } 5889 } 5890 5891 float rate; 5892 if (params->findFloat("operating-rate", &rate) && rate > 0) { 5893 status_t err = setOperatingRate(rate, mIsVideo); 5894 if (err != OK) { 5895 ALOGE("Failed to set parameter 'operating-rate' (err %d)", err); 5896 return err; 5897 } 5898 } 5899 5900 return OK; 5901} 5902 5903void ACodec::onSignalEndOfInputStream() { 5904 sp<AMessage> notify = mNotify->dup(); 5905 notify->setInt32("what", CodecBase::kWhatSignaledInputEOS); 5906 5907 status_t err = mOMX->signalEndOfInputStream(mNode); 5908 if (err != OK) { 5909 notify->setInt32("err", err); 5910 } 5911 notify->post(); 5912} 5913 5914bool ACodec::ExecutingState::onOMXEvent( 5915 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 5916 switch (event) { 5917 case OMX_EventPortSettingsChanged: 5918 { 5919 CHECK_EQ(data1, (OMX_U32)kPortIndexOutput); 5920 5921 if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) { 5922 mCodec->mMetaDataBuffersToSubmit = 0; 5923 CHECK_EQ(mCodec->mOMX->sendCommand( 5924 mCodec->mNode, 5925 OMX_CommandPortDisable, kPortIndexOutput), 5926 (status_t)OK); 5927 5928 mCodec->freeOutputBuffersNotOwnedByComponent(); 5929 5930 mCodec->changeState(mCodec->mOutputPortSettingsChangedState); 5931 } else if (data2 == OMX_IndexConfigCommonOutputCrop) { 5932 mCodec->mSentFormat = false; 5933 } else { 5934 ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08x", 5935 mCodec->mComponentName.c_str(), data2); 5936 } 5937 5938 return true; 5939 } 5940 5941 case OMX_EventBufferFlag: 5942 { 5943 return true; 5944 } 5945 5946 default: 5947 return BaseState::onOMXEvent(event, data1, data2); 5948 } 5949} 5950 5951//////////////////////////////////////////////////////////////////////////////// 5952 5953ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState( 5954 ACodec *codec) 5955 : BaseState(codec) { 5956} 5957 5958ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode( 5959 OMX_U32 portIndex) { 5960 if (portIndex == kPortIndexOutput) { 5961 return FREE_BUFFERS; 5962 } 5963 5964 CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput); 5965 5966 return RESUBMIT_BUFFERS; 5967} 5968 5969bool ACodec::OutputPortSettingsChangedState::onMessageReceived( 5970 const sp<AMessage> &msg) { 5971 bool handled = false; 5972 5973 switch (msg->what()) { 5974 case kWhatFlush: 5975 case kWhatShutdown: 5976 case kWhatResume: 5977 case kWhatSetParameters: 5978 { 5979 if (msg->what() == kWhatResume) { 5980 ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str()); 5981 } 5982 5983 mCodec->deferMessage(msg); 5984 handled = true; 5985 break; 5986 } 5987 5988 default: 5989 handled = BaseState::onMessageReceived(msg); 5990 break; 5991 } 5992 5993 return handled; 5994} 5995 5996void ACodec::OutputPortSettingsChangedState::stateEntered() { 5997 ALOGV("[%s] Now handling output port settings change", 5998 mCodec->mComponentName.c_str()); 5999} 6000 6001bool ACodec::OutputPortSettingsChangedState::onOMXEvent( 6002 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 6003 switch (event) { 6004 case OMX_EventCmdComplete: 6005 { 6006 if (data1 == (OMX_U32)OMX_CommandPortDisable) { 6007 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput); 6008 6009 ALOGV("[%s] Output port now disabled.", 6010 mCodec->mComponentName.c_str()); 6011 6012 CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty()); 6013 mCodec->mDealer[kPortIndexOutput].clear(); 6014 6015 CHECK_EQ(mCodec->mOMX->sendCommand( 6016 mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput), 6017 (status_t)OK); 6018 6019 status_t err; 6020 if ((err = mCodec->allocateBuffersOnPort( 6021 kPortIndexOutput)) != OK) { 6022 ALOGE("Failed to allocate output port buffers after " 6023 "port reconfiguration (error 0x%08x)", 6024 err); 6025 6026 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6027 6028 // This is technically not correct, but appears to be 6029 // the only way to free the component instance. 6030 // Controlled transitioning from excecuting->idle 6031 // and idle->loaded seem impossible probably because 6032 // the output port never finishes re-enabling. 6033 mCodec->mShutdownInProgress = true; 6034 mCodec->mKeepComponentAllocated = false; 6035 mCodec->changeState(mCodec->mLoadedState); 6036 } 6037 6038 return true; 6039 } else if (data1 == (OMX_U32)OMX_CommandPortEnable) { 6040 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput); 6041 6042 mCodec->mSentFormat = false; 6043 6044 ALOGV("[%s] Output port now reenabled.", 6045 mCodec->mComponentName.c_str()); 6046 6047 if (mCodec->mExecutingState->active()) { 6048 mCodec->mExecutingState->submitOutputBuffers(); 6049 } 6050 6051 mCodec->changeState(mCodec->mExecutingState); 6052 6053 return true; 6054 } 6055 6056 return false; 6057 } 6058 6059 default: 6060 return false; 6061 } 6062} 6063 6064//////////////////////////////////////////////////////////////////////////////// 6065 6066ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec) 6067 : BaseState(codec), 6068 mComponentNowIdle(false) { 6069} 6070 6071bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) { 6072 bool handled = false; 6073 6074 switch (msg->what()) { 6075 case kWhatFlush: 6076 { 6077 // Don't send me a flush request if you previously wanted me 6078 // to shutdown. 6079 TRESPASS(); 6080 break; 6081 } 6082 6083 case kWhatShutdown: 6084 { 6085 // We're already doing that... 6086 6087 handled = true; 6088 break; 6089 } 6090 6091 default: 6092 handled = BaseState::onMessageReceived(msg); 6093 break; 6094 } 6095 6096 return handled; 6097} 6098 6099void ACodec::ExecutingToIdleState::stateEntered() { 6100 ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str()); 6101 6102 mComponentNowIdle = false; 6103 mCodec->mSentFormat = false; 6104} 6105 6106bool ACodec::ExecutingToIdleState::onOMXEvent( 6107 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 6108 switch (event) { 6109 case OMX_EventCmdComplete: 6110 { 6111 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 6112 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); 6113 6114 mComponentNowIdle = true; 6115 6116 changeStateIfWeOwnAllBuffers(); 6117 6118 return true; 6119 } 6120 6121 case OMX_EventPortSettingsChanged: 6122 case OMX_EventBufferFlag: 6123 { 6124 // We're shutting down and don't care about this anymore. 6125 return true; 6126 } 6127 6128 default: 6129 return BaseState::onOMXEvent(event, data1, data2); 6130 } 6131} 6132 6133void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() { 6134 if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) { 6135 CHECK_EQ(mCodec->mOMX->sendCommand( 6136 mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded), 6137 (status_t)OK); 6138 6139 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK); 6140 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK); 6141 6142 if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown) 6143 && mCodec->mNativeWindow != NULL) { 6144 // We push enough 1x1 blank buffers to ensure that one of 6145 // them has made it to the display. This allows the OMX 6146 // component teardown to zero out any protected buffers 6147 // without the risk of scanning out one of those buffers. 6148 mCodec->pushBlankBuffersToNativeWindow(); 6149 } 6150 6151 mCodec->changeState(mCodec->mIdleToLoadedState); 6152 } 6153} 6154 6155void ACodec::ExecutingToIdleState::onInputBufferFilled( 6156 const sp<AMessage> &msg) { 6157 BaseState::onInputBufferFilled(msg); 6158 6159 changeStateIfWeOwnAllBuffers(); 6160} 6161 6162void ACodec::ExecutingToIdleState::onOutputBufferDrained( 6163 const sp<AMessage> &msg) { 6164 BaseState::onOutputBufferDrained(msg); 6165 6166 changeStateIfWeOwnAllBuffers(); 6167} 6168 6169//////////////////////////////////////////////////////////////////////////////// 6170 6171ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec) 6172 : BaseState(codec) { 6173} 6174 6175bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) { 6176 bool handled = false; 6177 6178 switch (msg->what()) { 6179 case kWhatShutdown: 6180 { 6181 // We're already doing that... 6182 6183 handled = true; 6184 break; 6185 } 6186 6187 case kWhatFlush: 6188 { 6189 // Don't send me a flush request if you previously wanted me 6190 // to shutdown. 6191 TRESPASS(); 6192 break; 6193 } 6194 6195 default: 6196 handled = BaseState::onMessageReceived(msg); 6197 break; 6198 } 6199 6200 return handled; 6201} 6202 6203void ACodec::IdleToLoadedState::stateEntered() { 6204 ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str()); 6205} 6206 6207bool ACodec::IdleToLoadedState::onOMXEvent( 6208 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 6209 switch (event) { 6210 case OMX_EventCmdComplete: 6211 { 6212 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 6213 CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded); 6214 6215 mCodec->changeState(mCodec->mLoadedState); 6216 6217 return true; 6218 } 6219 6220 default: 6221 return BaseState::onOMXEvent(event, data1, data2); 6222 } 6223} 6224 6225//////////////////////////////////////////////////////////////////////////////// 6226 6227ACodec::FlushingState::FlushingState(ACodec *codec) 6228 : BaseState(codec) { 6229} 6230 6231void ACodec::FlushingState::stateEntered() { 6232 ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str()); 6233 6234 mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false; 6235} 6236 6237bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) { 6238 bool handled = false; 6239 6240 switch (msg->what()) { 6241 case kWhatShutdown: 6242 { 6243 mCodec->deferMessage(msg); 6244 break; 6245 } 6246 6247 case kWhatFlush: 6248 { 6249 // We're already doing this right now. 6250 handled = true; 6251 break; 6252 } 6253 6254 default: 6255 handled = BaseState::onMessageReceived(msg); 6256 break; 6257 } 6258 6259 return handled; 6260} 6261 6262bool ACodec::FlushingState::onOMXEvent( 6263 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 6264 ALOGV("[%s] FlushingState onOMXEvent(%u,%d)", 6265 mCodec->mComponentName.c_str(), event, (OMX_S32)data1); 6266 6267 switch (event) { 6268 case OMX_EventCmdComplete: 6269 { 6270 CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush); 6271 6272 if (data2 == kPortIndexInput || data2 == kPortIndexOutput) { 6273 CHECK(!mFlushComplete[data2]); 6274 mFlushComplete[data2] = true; 6275 6276 if (mFlushComplete[kPortIndexInput] 6277 && mFlushComplete[kPortIndexOutput]) { 6278 changeStateIfWeOwnAllBuffers(); 6279 } 6280 } else { 6281 CHECK_EQ(data2, OMX_ALL); 6282 CHECK(mFlushComplete[kPortIndexInput]); 6283 CHECK(mFlushComplete[kPortIndexOutput]); 6284 6285 changeStateIfWeOwnAllBuffers(); 6286 } 6287 6288 return true; 6289 } 6290 6291 case OMX_EventPortSettingsChanged: 6292 { 6293 sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec); 6294 msg->setInt32("type", omx_message::EVENT); 6295 msg->setInt32("node", mCodec->mNode); 6296 msg->setInt32("event", event); 6297 msg->setInt32("data1", data1); 6298 msg->setInt32("data2", data2); 6299 6300 ALOGV("[%s] Deferring OMX_EventPortSettingsChanged", 6301 mCodec->mComponentName.c_str()); 6302 6303 mCodec->deferMessage(msg); 6304 6305 return true; 6306 } 6307 6308 default: 6309 return BaseState::onOMXEvent(event, data1, data2); 6310 } 6311 6312 return true; 6313} 6314 6315void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) { 6316 BaseState::onOutputBufferDrained(msg); 6317 6318 changeStateIfWeOwnAllBuffers(); 6319} 6320 6321void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) { 6322 BaseState::onInputBufferFilled(msg); 6323 6324 changeStateIfWeOwnAllBuffers(); 6325} 6326 6327void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() { 6328 if (mFlushComplete[kPortIndexInput] 6329 && mFlushComplete[kPortIndexOutput] 6330 && mCodec->allYourBuffersAreBelongToUs()) { 6331 // We now own all buffers except possibly those still queued with 6332 // the native window for rendering. Let's get those back as well. 6333 mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs(); 6334 6335 sp<AMessage> notify = mCodec->mNotify->dup(); 6336 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 6337 notify->post(); 6338 6339 mCodec->mPortEOS[kPortIndexInput] = 6340 mCodec->mPortEOS[kPortIndexOutput] = false; 6341 6342 mCodec->mInputEOSResult = OK; 6343 6344 if (mCodec->mSkipCutBuffer != NULL) { 6345 mCodec->mSkipCutBuffer->clear(); 6346 } 6347 6348 mCodec->changeState(mCodec->mExecutingState); 6349 } 6350} 6351 6352} // namespace android 6353