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