ACodec.cpp revision 6f8f2c88c6351218d249c8676ed351fb17c6e17f
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17//#define LOG_NDEBUG 0 18#define LOG_TAG "ACodec" 19 20#ifdef __LP64__ 21#define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS 22#endif 23 24#include <inttypes.h> 25#include <utils/Trace.h> 26 27#include <gui/Surface.h> 28 29#include <media/stagefright/ACodec.h> 30 31#include <media/stagefright/foundation/avc_utils.h> 32#include <media/stagefright/foundation/hexdump.h> 33#include <media/stagefright/foundation/ABuffer.h> 34#include <media/stagefright/foundation/ADebug.h> 35#include <media/stagefright/foundation/AMessage.h> 36#include <media/stagefright/foundation/AUtils.h> 37 38#include <media/stagefright/BufferProducerWrapper.h> 39#include <media/stagefright/MediaCodec.h> 40#include <media/stagefright/MediaDefs.h> 41#include <media/stagefright/OMXClient.h> 42#include <media/stagefright/PersistentSurface.h> 43#include <media/stagefright/SurfaceUtils.h> 44#include <media/hardware/HardwareAPI.h> 45#include <media/MediaBufferHolder.h> 46#include <media/OMXBuffer.h> 47#include <media/omx/1.0/WOmxNode.h> 48 49#include <hidlmemory/mapping.h> 50 51#include <media/openmax/OMX_AudioExt.h> 52#include <media/openmax/OMX_VideoExt.h> 53#include <media/openmax/OMX_Component.h> 54#include <media/openmax/OMX_IndexExt.h> 55#include <media/openmax/OMX_AsString.h> 56 57#include "include/ACodecBufferChannel.h" 58#include "include/DataConverter.h" 59#include "include/SecureBuffer.h" 60#include "include/SharedMemoryBuffer.h" 61#include <media/stagefright/omx/OMXUtils.h> 62 63namespace android { 64 65using binder::Status; 66 67enum { 68 kMaxIndicesToCheck = 32, // used when enumerating supported formats and profiles 69}; 70 71// OMX errors are directly mapped into status_t range if 72// there is no corresponding MediaError status code. 73// Use the statusFromOMXError(int32_t omxError) function. 74// 75// Currently this is a direct map. 76// See frameworks/native/include/media/openmax/OMX_Core.h 77// 78// Vendor OMX errors from 0x90000000 - 0x9000FFFF 79// Extension OMX errors from 0x8F000000 - 0x90000000 80// Standard OMX errors from 0x80001000 - 0x80001024 (0x80001024 current) 81// 82 83// returns true if err is a recognized OMX error code. 84// as OMX error is OMX_S32, this is an int32_t type 85static inline bool isOMXError(int32_t err) { 86 return (ERROR_CODEC_MIN <= err && err <= ERROR_CODEC_MAX); 87} 88 89// converts an OMX error to a status_t 90static inline status_t statusFromOMXError(int32_t omxError) { 91 switch (omxError) { 92 case OMX_ErrorInvalidComponentName: 93 case OMX_ErrorComponentNotFound: 94 return NAME_NOT_FOUND; // can trigger illegal argument error for provided names. 95 default: 96 return isOMXError(omxError) ? omxError : 0; // no translation required 97 } 98} 99 100static inline status_t statusFromBinderStatus(const Status &status) { 101 if (status.isOk()) { 102 return OK; 103 } 104 status_t err; 105 if ((err = status.serviceSpecificErrorCode()) != OK) { 106 return err; 107 } 108 if ((err = status.transactionError()) != OK) { 109 return err; 110 } 111 // Other exception 112 return UNKNOWN_ERROR; 113} 114 115// checks and converts status_t to a non-side-effect status_t 116static inline status_t makeNoSideEffectStatus(status_t err) { 117 switch (err) { 118 // the following errors have side effects and may come 119 // from other code modules. Remap for safety reasons. 120 case INVALID_OPERATION: 121 case DEAD_OBJECT: 122 return UNKNOWN_ERROR; 123 default: 124 return err; 125 } 126} 127 128static OMX_VIDEO_CONTROLRATETYPE getVideoBitrateMode(const sp<AMessage> &msg) { 129 int32_t tmp; 130 if (msg->findInt32("bitrate-mode", &tmp)) { 131 // explicitly translate from MediaCodecInfo.EncoderCapabilities. 132 // BITRATE_MODE_* into OMX bitrate mode. 133 switch (tmp) { 134 //BITRATE_MODE_CQ 135 case 0: return OMX_Video_ControlRateConstantQuality; 136 //BITRATE_MODE_VBR 137 case 1: return OMX_Video_ControlRateVariable; 138 //BITRATE_MODE_CBR 139 case 2: return OMX_Video_ControlRateConstant; 140 default: break; 141 } 142 } 143 return OMX_Video_ControlRateVariable; 144} 145 146static bool findVideoBitrateControlInfo(const sp<AMessage> &msg, 147 OMX_VIDEO_CONTROLRATETYPE *mode, int32_t *bitrate, int32_t *quality) { 148 *mode = getVideoBitrateMode(msg); 149 bool isCQ = (*mode == OMX_Video_ControlRateConstantQuality); 150 return (!isCQ && msg->findInt32("bitrate", bitrate)) 151 || (isCQ && msg->findInt32("quality", quality)); 152} 153 154struct MessageList : public RefBase { 155 MessageList() { 156 } 157 virtual ~MessageList() { 158 } 159 std::list<sp<AMessage> > &getList() { return mList; } 160private: 161 std::list<sp<AMessage> > mList; 162 163 DISALLOW_EVIL_CONSTRUCTORS(MessageList); 164}; 165 166static sp<DataConverter> getCopyConverter() { 167 static pthread_once_t once = PTHREAD_ONCE_INIT; // const-inited 168 static sp<DataConverter> sCopyConverter; // zero-inited 169 pthread_once(&once, [](){ sCopyConverter = new DataConverter(); }); 170 return sCopyConverter; 171} 172 173struct CodecObserver : public BnOMXObserver { 174 CodecObserver() {} 175 176 void setNotificationMessage(const sp<AMessage> &msg) { 177 mNotify = msg; 178 } 179 180 // from IOMXObserver 181 virtual void onMessages(const std::list<omx_message> &messages) { 182 if (messages.empty()) { 183 return; 184 } 185 186 sp<AMessage> notify = mNotify->dup(); 187 sp<MessageList> msgList = new MessageList(); 188 for (std::list<omx_message>::const_iterator it = messages.cbegin(); 189 it != messages.cend(); ++it) { 190 const omx_message &omx_msg = *it; 191 192 sp<AMessage> msg = new AMessage; 193 msg->setInt32("type", omx_msg.type); 194 switch (omx_msg.type) { 195 case omx_message::EVENT: 196 { 197 msg->setInt32("event", omx_msg.u.event_data.event); 198 msg->setInt32("data1", omx_msg.u.event_data.data1); 199 msg->setInt32("data2", omx_msg.u.event_data.data2); 200 break; 201 } 202 203 case omx_message::EMPTY_BUFFER_DONE: 204 { 205 msg->setInt32("buffer", omx_msg.u.buffer_data.buffer); 206 msg->setInt32("fence_fd", omx_msg.fenceFd); 207 break; 208 } 209 210 case omx_message::FILL_BUFFER_DONE: 211 { 212 msg->setInt32( 213 "buffer", omx_msg.u.extended_buffer_data.buffer); 214 msg->setInt32( 215 "range_offset", 216 omx_msg.u.extended_buffer_data.range_offset); 217 msg->setInt32( 218 "range_length", 219 omx_msg.u.extended_buffer_data.range_length); 220 msg->setInt32( 221 "flags", 222 omx_msg.u.extended_buffer_data.flags); 223 msg->setInt64( 224 "timestamp", 225 omx_msg.u.extended_buffer_data.timestamp); 226 msg->setInt32( 227 "fence_fd", omx_msg.fenceFd); 228 break; 229 } 230 231 case omx_message::FRAME_RENDERED: 232 { 233 msg->setInt64( 234 "media_time_us", omx_msg.u.render_data.timestamp); 235 msg->setInt64( 236 "system_nano", omx_msg.u.render_data.nanoTime); 237 break; 238 } 239 240 default: 241 ALOGE("Unrecognized message type: %d", omx_msg.type); 242 break; 243 } 244 msgList->getList().push_back(msg); 245 } 246 notify->setObject("messages", msgList); 247 notify->post(); 248 } 249 250protected: 251 virtual ~CodecObserver() {} 252 253private: 254 sp<AMessage> mNotify; 255 256 DISALLOW_EVIL_CONSTRUCTORS(CodecObserver); 257}; 258 259//////////////////////////////////////////////////////////////////////////////// 260 261struct ACodec::BaseState : public AState { 262 explicit BaseState(ACodec *codec, const sp<AState> &parentState = NULL); 263 264protected: 265 enum PortMode { 266 KEEP_BUFFERS, 267 RESUBMIT_BUFFERS, 268 FREE_BUFFERS, 269 }; 270 271 ACodec *mCodec; 272 273 virtual PortMode getPortMode(OMX_U32 portIndex); 274 275 virtual void stateExited(); 276 virtual bool onMessageReceived(const sp<AMessage> &msg); 277 278 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 279 280 virtual void onOutputBufferDrained(const sp<AMessage> &msg); 281 virtual void onInputBufferFilled(const sp<AMessage> &msg); 282 283 void postFillThisBuffer(BufferInfo *info); 284 285private: 286 // Handles an OMX message. Returns true iff message was handled. 287 bool onOMXMessage(const sp<AMessage> &msg); 288 289 // Handles a list of messages. Returns true iff messages were handled. 290 bool onOMXMessageList(const sp<AMessage> &msg); 291 292 // returns true iff this message is for this component and the component is alive 293 bool checkOMXMessage(const sp<AMessage> &msg); 294 295 bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID, int fenceFd); 296 297 bool onOMXFillBufferDone( 298 IOMX::buffer_id bufferID, 299 size_t rangeOffset, size_t rangeLength, 300 OMX_U32 flags, 301 int64_t timeUs, 302 int fenceFd); 303 304 virtual bool onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano); 305 306 void getMoreInputDataIfPossible(); 307 308 DISALLOW_EVIL_CONSTRUCTORS(BaseState); 309}; 310 311//////////////////////////////////////////////////////////////////////////////// 312 313struct ACodec::DeathNotifier : 314 public IBinder::DeathRecipient, 315 public ::android::hardware::hidl_death_recipient { 316 explicit DeathNotifier(const sp<AMessage> ¬ify) 317 : mNotify(notify) { 318 } 319 320 virtual void binderDied(const wp<IBinder> &) { 321 mNotify->post(); 322 } 323 324 virtual void serviceDied( 325 uint64_t /* cookie */, 326 const wp<::android::hidl::base::V1_0::IBase>& /* who */) { 327 mNotify->post(); 328 } 329 330protected: 331 virtual ~DeathNotifier() {} 332 333private: 334 sp<AMessage> mNotify; 335 336 DISALLOW_EVIL_CONSTRUCTORS(DeathNotifier); 337}; 338 339struct ACodec::UninitializedState : public ACodec::BaseState { 340 explicit UninitializedState(ACodec *codec); 341 342protected: 343 virtual bool onMessageReceived(const sp<AMessage> &msg); 344 virtual void stateEntered(); 345 346private: 347 void onSetup(const sp<AMessage> &msg); 348 bool onAllocateComponent(const sp<AMessage> &msg); 349 350 sp<DeathNotifier> mDeathNotifier; 351 352 DISALLOW_EVIL_CONSTRUCTORS(UninitializedState); 353}; 354 355//////////////////////////////////////////////////////////////////////////////// 356 357struct ACodec::LoadedState : public ACodec::BaseState { 358 explicit LoadedState(ACodec *codec); 359 360protected: 361 virtual bool onMessageReceived(const sp<AMessage> &msg); 362 virtual void stateEntered(); 363 364private: 365 friend struct ACodec::UninitializedState; 366 367 bool onConfigureComponent(const sp<AMessage> &msg); 368 void onCreateInputSurface(const sp<AMessage> &msg); 369 void onSetInputSurface(const sp<AMessage> &msg); 370 void onStart(); 371 void onShutdown(bool keepComponentAllocated); 372 373 status_t setupInputSurface(); 374 375 DISALLOW_EVIL_CONSTRUCTORS(LoadedState); 376}; 377 378//////////////////////////////////////////////////////////////////////////////// 379 380struct ACodec::LoadedToIdleState : public ACodec::BaseState { 381 explicit LoadedToIdleState(ACodec *codec); 382 383protected: 384 virtual bool onMessageReceived(const sp<AMessage> &msg); 385 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 386 virtual void stateEntered(); 387 388private: 389 status_t allocateBuffers(); 390 391 DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState); 392}; 393 394//////////////////////////////////////////////////////////////////////////////// 395 396struct ACodec::IdleToExecutingState : public ACodec::BaseState { 397 explicit IdleToExecutingState(ACodec *codec); 398 399protected: 400 virtual bool onMessageReceived(const sp<AMessage> &msg); 401 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 402 virtual void stateEntered(); 403 404private: 405 DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState); 406}; 407 408//////////////////////////////////////////////////////////////////////////////// 409 410struct ACodec::ExecutingState : public ACodec::BaseState { 411 explicit ExecutingState(ACodec *codec); 412 413 void submitRegularOutputBuffers(); 414 void submitOutputMetaBuffers(); 415 void submitOutputBuffers(); 416 417 // Submit output buffers to the decoder, submit input buffers to client 418 // to fill with data. 419 void resume(); 420 421 // Returns true iff input and output buffers are in play. 422 bool active() const { return mActive; } 423 424protected: 425 virtual PortMode getPortMode(OMX_U32 portIndex); 426 virtual bool onMessageReceived(const sp<AMessage> &msg); 427 virtual void stateEntered(); 428 429 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 430 virtual bool onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano); 431 432private: 433 bool mActive; 434 435 DISALLOW_EVIL_CONSTRUCTORS(ExecutingState); 436}; 437 438//////////////////////////////////////////////////////////////////////////////// 439 440struct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState { 441 explicit OutputPortSettingsChangedState(ACodec *codec); 442 443protected: 444 virtual PortMode getPortMode(OMX_U32 portIndex); 445 virtual bool onMessageReceived(const sp<AMessage> &msg); 446 virtual void stateEntered(); 447 448 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 449 virtual bool onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano); 450 451private: 452 DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState); 453}; 454 455//////////////////////////////////////////////////////////////////////////////// 456 457struct ACodec::ExecutingToIdleState : public ACodec::BaseState { 458 explicit ExecutingToIdleState(ACodec *codec); 459 460protected: 461 virtual bool onMessageReceived(const sp<AMessage> &msg); 462 virtual void stateEntered(); 463 464 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 465 466 virtual void onOutputBufferDrained(const sp<AMessage> &msg); 467 virtual void onInputBufferFilled(const sp<AMessage> &msg); 468 469private: 470 void changeStateIfWeOwnAllBuffers(); 471 472 bool mComponentNowIdle; 473 474 DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState); 475}; 476 477//////////////////////////////////////////////////////////////////////////////// 478 479struct ACodec::IdleToLoadedState : public ACodec::BaseState { 480 explicit IdleToLoadedState(ACodec *codec); 481 482protected: 483 virtual bool onMessageReceived(const sp<AMessage> &msg); 484 virtual void stateEntered(); 485 486 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 487 488private: 489 DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState); 490}; 491 492//////////////////////////////////////////////////////////////////////////////// 493 494struct ACodec::FlushingState : public ACodec::BaseState { 495 explicit FlushingState(ACodec *codec); 496 497protected: 498 virtual bool onMessageReceived(const sp<AMessage> &msg); 499 virtual void stateEntered(); 500 501 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 502 503 virtual void onOutputBufferDrained(const sp<AMessage> &msg); 504 virtual void onInputBufferFilled(const sp<AMessage> &msg); 505 506private: 507 bool mFlushComplete[2]; 508 509 void changeStateIfWeOwnAllBuffers(); 510 511 DISALLOW_EVIL_CONSTRUCTORS(FlushingState); 512}; 513 514//////////////////////////////////////////////////////////////////////////////// 515 516void ACodec::BufferInfo::setWriteFence(int fenceFd, const char *dbg) { 517 if (mFenceFd >= 0) { 518 ALOGW("OVERWRITE OF %s fence %d by write fence %d in %s", 519 mIsReadFence ? "read" : "write", mFenceFd, fenceFd, dbg); 520 } 521 mFenceFd = fenceFd; 522 mIsReadFence = false; 523} 524 525void ACodec::BufferInfo::setReadFence(int fenceFd, const char *dbg) { 526 if (mFenceFd >= 0) { 527 ALOGW("OVERWRITE OF %s fence %d by read fence %d in %s", 528 mIsReadFence ? "read" : "write", mFenceFd, fenceFd, dbg); 529 } 530 mFenceFd = fenceFd; 531 mIsReadFence = true; 532} 533 534void ACodec::BufferInfo::checkWriteFence(const char *dbg) { 535 if (mFenceFd >= 0 && mIsReadFence) { 536 ALOGD("REUSING read fence %d as write fence in %s", mFenceFd, dbg); 537 } 538} 539 540void ACodec::BufferInfo::checkReadFence(const char *dbg) { 541 if (mFenceFd >= 0 && !mIsReadFence) { 542 ALOGD("REUSING write fence %d as read fence in %s", mFenceFd, dbg); 543 } 544} 545 546//////////////////////////////////////////////////////////////////////////////// 547 548ACodec::ACodec() 549 : mSampleRate(0), 550 mNodeGeneration(0), 551 mUsingNativeWindow(false), 552 mNativeWindowUsageBits(0), 553 mLastNativeWindowDataSpace(HAL_DATASPACE_UNKNOWN), 554 mIsVideo(false), 555 mIsImage(false), 556 mIsEncoder(false), 557 mFatalError(false), 558 mShutdownInProgress(false), 559 mExplicitShutdown(false), 560 mIsLegacyVP9Decoder(false), 561 mEncoderDelay(0), 562 mEncoderPadding(0), 563 mRotationDegrees(0), 564 mChannelMaskPresent(false), 565 mChannelMask(0), 566 mDequeueCounter(0), 567 mMetadataBuffersToSubmit(0), 568 mNumUndequeuedBuffers(0), 569 mRepeatFrameDelayUs(-1ll), 570 mMaxPtsGapUs(-1ll), 571 mMaxFps(-1), 572 mFps(-1.0), 573 mCaptureFps(-1.0), 574 mCreateInputBuffersSuspended(false), 575 mLatency(0), 576 mTunneled(false), 577 mDescribeColorAspectsIndex((OMX_INDEXTYPE)0), 578 mDescribeHDRStaticInfoIndex((OMX_INDEXTYPE)0), 579 mStateGeneration(0), 580 mVendorExtensionsStatus(kExtensionsUnchecked) { 581 memset(&mLastHDRStaticInfo, 0, sizeof(mLastHDRStaticInfo)); 582 583 mUninitializedState = new UninitializedState(this); 584 mLoadedState = new LoadedState(this); 585 mLoadedToIdleState = new LoadedToIdleState(this); 586 mIdleToExecutingState = new IdleToExecutingState(this); 587 mExecutingState = new ExecutingState(this); 588 589 mOutputPortSettingsChangedState = 590 new OutputPortSettingsChangedState(this); 591 592 mExecutingToIdleState = new ExecutingToIdleState(this); 593 mIdleToLoadedState = new IdleToLoadedState(this); 594 mFlushingState = new FlushingState(this); 595 596 mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false; 597 mInputEOSResult = OK; 598 599 mPortMode[kPortIndexInput] = IOMX::kPortModePresetByteBuffer; 600 mPortMode[kPortIndexOutput] = IOMX::kPortModePresetByteBuffer; 601 602 memset(&mLastNativeWindowCrop, 0, sizeof(mLastNativeWindowCrop)); 603 604 changeState(mUninitializedState); 605} 606 607ACodec::~ACodec() { 608} 609 610void ACodec::initiateSetup(const sp<AMessage> &msg) { 611 msg->setWhat(kWhatSetup); 612 msg->setTarget(this); 613 msg->post(); 614} 615 616std::shared_ptr<BufferChannelBase> ACodec::getBufferChannel() { 617 if (!mBufferChannel) { 618 mBufferChannel = std::make_shared<ACodecBufferChannel>( 619 new AMessage(kWhatInputBufferFilled, this), 620 new AMessage(kWhatOutputBufferDrained, this)); 621 } 622 return mBufferChannel; 623} 624 625void ACodec::signalSetParameters(const sp<AMessage> ¶ms) { 626 sp<AMessage> msg = new AMessage(kWhatSetParameters, this); 627 msg->setMessage("params", params); 628 msg->post(); 629} 630 631void ACodec::initiateAllocateComponent(const sp<AMessage> &msg) { 632 msg->setWhat(kWhatAllocateComponent); 633 msg->setTarget(this); 634 msg->post(); 635} 636 637void ACodec::initiateConfigureComponent(const sp<AMessage> &msg) { 638 msg->setWhat(kWhatConfigureComponent); 639 msg->setTarget(this); 640 msg->post(); 641} 642 643status_t ACodec::setSurface(const sp<Surface> &surface) { 644 sp<AMessage> msg = new AMessage(kWhatSetSurface, this); 645 msg->setObject("surface", surface); 646 647 sp<AMessage> response; 648 status_t err = msg->postAndAwaitResponse(&response); 649 650 if (err == OK) { 651 (void)response->findInt32("err", &err); 652 } 653 return err; 654} 655 656void ACodec::initiateCreateInputSurface() { 657 (new AMessage(kWhatCreateInputSurface, this))->post(); 658} 659 660void ACodec::initiateSetInputSurface( 661 const sp<PersistentSurface> &surface) { 662 sp<AMessage> msg = new AMessage(kWhatSetInputSurface, this); 663 msg->setObject("input-surface", surface); 664 msg->post(); 665} 666 667void ACodec::signalEndOfInputStream() { 668 (new AMessage(kWhatSignalEndOfInputStream, this))->post(); 669} 670 671void ACodec::initiateStart() { 672 (new AMessage(kWhatStart, this))->post(); 673} 674 675void ACodec::signalFlush() { 676 ALOGV("[%s] signalFlush", mComponentName.c_str()); 677 (new AMessage(kWhatFlush, this))->post(); 678} 679 680void ACodec::signalResume() { 681 (new AMessage(kWhatResume, this))->post(); 682} 683 684void ACodec::initiateShutdown(bool keepComponentAllocated) { 685 sp<AMessage> msg = new AMessage(kWhatShutdown, this); 686 msg->setInt32("keepComponentAllocated", keepComponentAllocated); 687 msg->post(); 688 if (!keepComponentAllocated) { 689 // ensure shutdown completes in 3 seconds 690 (new AMessage(kWhatReleaseCodecInstance, this))->post(3000000); 691 } 692} 693 694void ACodec::signalRequestIDRFrame() { 695 (new AMessage(kWhatRequestIDRFrame, this))->post(); 696} 697 698// *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** 699// Some codecs may return input buffers before having them processed. 700// This causes a halt if we already signaled an EOS on the input 701// port. For now keep submitting an output buffer if there was an 702// EOS on the input port, but not yet on the output port. 703void ACodec::signalSubmitOutputMetadataBufferIfEOS_workaround() { 704 if (mPortEOS[kPortIndexInput] && !mPortEOS[kPortIndexOutput] && 705 mMetadataBuffersToSubmit > 0) { 706 (new AMessage(kWhatSubmitOutputMetadataBufferIfEOS, this))->post(); 707 } 708} 709 710status_t ACodec::handleSetSurface(const sp<Surface> &surface) { 711 // allow keeping unset surface 712 if (surface == NULL) { 713 if (mNativeWindow != NULL) { 714 ALOGW("cannot unset a surface"); 715 return INVALID_OPERATION; 716 } 717 return OK; 718 } 719 720 // cannot switch from bytebuffers to surface 721 if (mNativeWindow == NULL) { 722 ALOGW("component was not configured with a surface"); 723 return INVALID_OPERATION; 724 } 725 726 ANativeWindow *nativeWindow = surface.get(); 727 // if we have not yet started the codec, we can simply set the native window 728 if (mBuffers[kPortIndexInput].size() == 0) { 729 mNativeWindow = surface; 730 return OK; 731 } 732 733 // we do not support changing a tunneled surface after start 734 if (mTunneled) { 735 ALOGW("cannot change tunneled surface"); 736 return INVALID_OPERATION; 737 } 738 739 int usageBits = 0; 740 // no need to reconnect as we will not dequeue all buffers 741 status_t err = setupNativeWindowSizeFormatAndUsage( 742 nativeWindow, &usageBits, !storingMetadataInDecodedBuffers()); 743 if (err != OK) { 744 return err; 745 } 746 747 int ignoredFlags = kVideoGrallocUsage; 748 // New output surface is not allowed to add new usage flag except ignored ones. 749 if ((usageBits & ~(mNativeWindowUsageBits | ignoredFlags)) != 0) { 750 ALOGW("cannot change usage from %#x to %#x", mNativeWindowUsageBits, usageBits); 751 return BAD_VALUE; 752 } 753 754 // get min undequeued count. We cannot switch to a surface that has a higher 755 // undequeued count than we allocated. 756 int minUndequeuedBuffers = 0; 757 err = nativeWindow->query( 758 nativeWindow, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, 759 &minUndequeuedBuffers); 760 if (err != 0) { 761 ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)", 762 strerror(-err), -err); 763 return err; 764 } 765 if (minUndequeuedBuffers > (int)mNumUndequeuedBuffers) { 766 ALOGE("new surface holds onto more buffers (%d) than planned for (%zu)", 767 minUndequeuedBuffers, mNumUndequeuedBuffers); 768 return BAD_VALUE; 769 } 770 771 // we cannot change the number of output buffers while OMX is running 772 // set up surface to the same count 773 Vector<BufferInfo> &buffers = mBuffers[kPortIndexOutput]; 774 ALOGV("setting up surface for %zu buffers", buffers.size()); 775 776 err = native_window_set_buffer_count(nativeWindow, buffers.size()); 777 if (err != 0) { 778 ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), 779 -err); 780 return err; 781 } 782 783 // need to enable allocation when attaching 784 surface->getIGraphicBufferProducer()->allowAllocation(true); 785 786 // for meta data mode, we move dequeud buffers to the new surface. 787 // for non-meta mode, we must move all registered buffers 788 for (size_t i = 0; i < buffers.size(); ++i) { 789 const BufferInfo &info = buffers[i]; 790 // skip undequeued buffers for meta data mode 791 if (storingMetadataInDecodedBuffers() 792 && info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 793 ALOGV("skipping buffer"); 794 continue; 795 } 796 ALOGV("attaching buffer %p", info.mGraphicBuffer->getNativeBuffer()); 797 798 err = surface->attachBuffer(info.mGraphicBuffer->getNativeBuffer()); 799 if (err != OK) { 800 ALOGE("failed to attach buffer %p to the new surface: %s (%d)", 801 info.mGraphicBuffer->getNativeBuffer(), 802 strerror(-err), -err); 803 return err; 804 } 805 } 806 807 // cancel undequeued buffers to new surface 808 if (!storingMetadataInDecodedBuffers()) { 809 for (size_t i = 0; i < buffers.size(); ++i) { 810 BufferInfo &info = buffers.editItemAt(i); 811 if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 812 ALOGV("canceling buffer %p", info.mGraphicBuffer->getNativeBuffer()); 813 err = nativeWindow->cancelBuffer( 814 nativeWindow, info.mGraphicBuffer->getNativeBuffer(), info.mFenceFd); 815 info.mFenceFd = -1; 816 if (err != OK) { 817 ALOGE("failed to cancel buffer %p to the new surface: %s (%d)", 818 info.mGraphicBuffer->getNativeBuffer(), 819 strerror(-err), -err); 820 return err; 821 } 822 } 823 } 824 // disallow further allocation 825 (void)surface->getIGraphicBufferProducer()->allowAllocation(false); 826 } 827 828 // push blank buffers to previous window if requested 829 if (mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown) { 830 pushBlankBuffersToNativeWindow(mNativeWindow.get()); 831 } 832 833 mNativeWindow = nativeWindow; 834 mNativeWindowUsageBits = usageBits; 835 return OK; 836} 837 838status_t ACodec::setPortMode(int32_t portIndex, IOMX::PortMode mode) { 839 status_t err = mOMXNode->setPortMode(portIndex, mode); 840 if (err != OK) { 841 ALOGE("[%s] setPortMode on %s to %s failed w/ err %d", 842 mComponentName.c_str(), 843 portIndex == kPortIndexInput ? "input" : "output", 844 asString(mode), 845 err); 846 return err; 847 } 848 849 mPortMode[portIndex] = mode; 850 return OK; 851} 852 853status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) { 854 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 855 856 CHECK(mAllocator[portIndex] == NULL); 857 CHECK(mBuffers[portIndex].isEmpty()); 858 859 status_t err; 860 if (mNativeWindow != NULL && portIndex == kPortIndexOutput) { 861 if (storingMetadataInDecodedBuffers()) { 862 err = allocateOutputMetadataBuffers(); 863 } else { 864 err = allocateOutputBuffersFromNativeWindow(); 865 } 866 } else { 867 OMX_PARAM_PORTDEFINITIONTYPE def; 868 InitOMXParams(&def); 869 def.nPortIndex = portIndex; 870 871 err = mOMXNode->getParameter( 872 OMX_IndexParamPortDefinition, &def, sizeof(def)); 873 874 if (err == OK) { 875 const IOMX::PortMode &mode = mPortMode[portIndex]; 876 size_t bufSize = def.nBufferSize; 877 // Always allocate VideoNativeMetadata if using ANWBuffer. 878 // OMX might use gralloc source internally, but we don't share 879 // metadata buffer with OMX, OMX has its own headers. 880 if (mode == IOMX::kPortModeDynamicANWBuffer) { 881 bufSize = sizeof(VideoNativeMetadata); 882 } else if (mode == IOMX::kPortModeDynamicNativeHandle) { 883 bufSize = sizeof(VideoNativeHandleMetadata); 884 } 885 886 size_t conversionBufferSize = 0; 887 888 sp<DataConverter> converter = mConverter[portIndex]; 889 if (converter != NULL) { 890 // here we assume sane conversions of max 4:1, so result fits in int32 891 if (portIndex == kPortIndexInput) { 892 conversionBufferSize = converter->sourceSize(bufSize); 893 } else { 894 conversionBufferSize = converter->targetSize(bufSize); 895 } 896 } 897 898 size_t alignment = 32; // This is the value currently returned by 899 // MemoryDealer::getAllocationAlignment(). 900 // TODO: Fix this when Treble has 901 // MemoryHeap/MemoryDealer. 902 903 ALOGV("[%s] Allocating %u buffers of size %zu (from %u using %s) on %s port", 904 mComponentName.c_str(), 905 def.nBufferCountActual, bufSize, def.nBufferSize, asString(mode), 906 portIndex == kPortIndexInput ? "input" : "output"); 907 908 // verify buffer sizes to avoid overflow in align() 909 if (bufSize == 0 || max(bufSize, conversionBufferSize) > kMaxCodecBufferSize) { 910 ALOGE("b/22885421"); 911 return NO_MEMORY; 912 } 913 914 // don't modify bufSize as OMX may not expect it to increase after negotiation 915 size_t alignedSize = align(bufSize, alignment); 916 size_t alignedConvSize = align(conversionBufferSize, alignment); 917 if (def.nBufferCountActual > SIZE_MAX / (alignedSize + alignedConvSize)) { 918 ALOGE("b/22885421"); 919 return NO_MEMORY; 920 } 921 922 if (mode != IOMX::kPortModePresetSecureBuffer) { 923 mAllocator[portIndex] = TAllocator::getService("ashmem"); 924 if (mAllocator[portIndex] == nullptr) { 925 ALOGE("hidl allocator on port %d is null", 926 (int)portIndex); 927 return NO_MEMORY; 928 } 929 // TODO: When Treble has MemoryHeap/MemoryDealer, we should 930 // specify the heap size to be 931 // def.nBufferCountActual * (alignedSize + alignedConvSize). 932 } 933 934 const sp<AMessage> &format = 935 portIndex == kPortIndexInput ? mInputFormat : mOutputFormat; 936 for (OMX_U32 i = 0; i < def.nBufferCountActual && err == OK; ++i) { 937 hidl_memory hidlMemToken; 938 sp<TMemory> hidlMem; 939 sp<IMemory> mem; 940 941 BufferInfo info; 942 info.mStatus = BufferInfo::OWNED_BY_US; 943 info.mFenceFd = -1; 944 info.mRenderInfo = NULL; 945 info.mGraphicBuffer = NULL; 946 info.mNewGraphicBuffer = false; 947 948 if (mode == IOMX::kPortModePresetSecureBuffer) { 949 void *ptr = NULL; 950 sp<NativeHandle> native_handle; 951 err = mOMXNode->allocateSecureBuffer( 952 portIndex, bufSize, &info.mBufferID, 953 &ptr, &native_handle); 954 955 info.mData = (native_handle == NULL) 956 ? new SecureBuffer(format, ptr, bufSize) 957 : new SecureBuffer(format, native_handle, bufSize); 958 info.mCodecData = info.mData; 959 } else { 960 bool success; 961 auto transStatus = mAllocator[portIndex]->allocate( 962 bufSize, 963 [&success, &hidlMemToken]( 964 bool s, 965 hidl_memory const& m) { 966 success = s; 967 hidlMemToken = m; 968 }); 969 970 if (!transStatus.isOk()) { 971 ALOGE("hidl's AshmemAllocator failed at the " 972 "transport: %s", 973 transStatus.description().c_str()); 974 return NO_MEMORY; 975 } 976 if (!success) { 977 return NO_MEMORY; 978 } 979 hidlMem = mapMemory(hidlMemToken); 980 if (hidlMem == nullptr) { 981 return NO_MEMORY; 982 } 983 err = mOMXNode->useBuffer( 984 portIndex, hidlMemToken, &info.mBufferID); 985 986 if (mode == IOMX::kPortModeDynamicANWBuffer) { 987 VideoNativeMetadata* metaData = (VideoNativeMetadata*)( 988 (void*)hidlMem->getPointer()); 989 metaData->nFenceFd = -1; 990 } 991 992 info.mCodecData = new SharedMemoryBuffer( 993 format, hidlMem); 994 info.mCodecRef = hidlMem; 995 996 // if we require conversion, allocate conversion buffer for client use; 997 // otherwise, reuse codec buffer 998 if (mConverter[portIndex] != NULL) { 999 CHECK_GT(conversionBufferSize, (size_t)0); 1000 bool success; 1001 mAllocator[portIndex]->allocate( 1002 conversionBufferSize, 1003 [&success, &hidlMemToken]( 1004 bool s, 1005 hidl_memory const& m) { 1006 success = s; 1007 hidlMemToken = m; 1008 }); 1009 if (!success) { 1010 return NO_MEMORY; 1011 } 1012 hidlMem = mapMemory(hidlMemToken); 1013 if (hidlMem == nullptr) { 1014 return NO_MEMORY; 1015 } 1016 info.mData = new SharedMemoryBuffer(format, hidlMem); 1017 info.mMemRef = hidlMem; 1018 } else { 1019 info.mData = info.mCodecData; 1020 info.mMemRef = info.mCodecRef; 1021 } 1022 } 1023 1024 mBuffers[portIndex].push(info); 1025 } 1026 } 1027 } 1028 1029 if (err != OK) { 1030 return err; 1031 } 1032 1033 std::vector<ACodecBufferChannel::BufferAndId> array(mBuffers[portIndex].size()); 1034 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 1035 array[i] = {mBuffers[portIndex][i].mData, mBuffers[portIndex][i].mBufferID}; 1036 } 1037 if (portIndex == kPortIndexInput) { 1038 mBufferChannel->setInputBufferArray(array); 1039 } else if (portIndex == kPortIndexOutput) { 1040 mBufferChannel->setOutputBufferArray(array); 1041 } else { 1042 TRESPASS(); 1043 } 1044 1045 return OK; 1046} 1047 1048status_t ACodec::setupNativeWindowSizeFormatAndUsage( 1049 ANativeWindow *nativeWindow /* nonnull */, int *finalUsage /* nonnull */, 1050 bool reconnect) { 1051 OMX_PARAM_PORTDEFINITIONTYPE def; 1052 InitOMXParams(&def); 1053 def.nPortIndex = kPortIndexOutput; 1054 1055 status_t err = mOMXNode->getParameter( 1056 OMX_IndexParamPortDefinition, &def, sizeof(def)); 1057 1058 if (err != OK) { 1059 return err; 1060 } 1061 1062 OMX_INDEXTYPE index; 1063 err = mOMXNode->getExtensionIndex( 1064 "OMX.google.android.index.AndroidNativeBufferConsumerUsage", 1065 &index); 1066 1067 if (err != OK) { 1068 // allow failure 1069 err = OK; 1070 } else { 1071 int usageBits = 0; 1072 if (nativeWindow->query( 1073 nativeWindow, 1074 NATIVE_WINDOW_CONSUMER_USAGE_BITS, 1075 &usageBits) == OK) { 1076 OMX_PARAM_U32TYPE params; 1077 InitOMXParams(¶ms); 1078 params.nPortIndex = kPortIndexOutput; 1079 params.nU32 = (OMX_U32)usageBits; 1080 1081 err = mOMXNode->setParameter(index, ¶ms, sizeof(params)); 1082 1083 if (err != OK) { 1084 ALOGE("Fail to set AndroidNativeBufferConsumerUsage: %d", err); 1085 return err; 1086 } 1087 } 1088 } 1089 1090 OMX_U32 usage = 0; 1091 err = mOMXNode->getGraphicBufferUsage(kPortIndexOutput, &usage); 1092 if (err != 0) { 1093 ALOGW("querying usage flags from OMX IL component failed: %d", err); 1094 // XXX: Currently this error is logged, but not fatal. 1095 usage = 0; 1096 } 1097 int omxUsage = usage; 1098 1099 if (mFlags & kFlagIsGrallocUsageProtected) { 1100 usage |= GRALLOC_USAGE_PROTECTED; 1101 } 1102 1103 usage |= kVideoGrallocUsage; 1104 *finalUsage = usage; 1105 1106 memset(&mLastNativeWindowCrop, 0, sizeof(mLastNativeWindowCrop)); 1107 mLastNativeWindowDataSpace = HAL_DATASPACE_UNKNOWN; 1108 1109 ALOGV("gralloc usage: %#x(OMX) => %#x(ACodec)", omxUsage, usage); 1110 return setNativeWindowSizeFormatAndUsage( 1111 nativeWindow, 1112 def.format.video.nFrameWidth, 1113 def.format.video.nFrameHeight, 1114 def.format.video.eColorFormat, 1115 mRotationDegrees, 1116 usage, 1117 reconnect); 1118} 1119 1120status_t ACodec::configureOutputBuffersFromNativeWindow( 1121 OMX_U32 *bufferCount, OMX_U32 *bufferSize, 1122 OMX_U32 *minUndequeuedBuffers, bool preregister) { 1123 1124 OMX_PARAM_PORTDEFINITIONTYPE def; 1125 InitOMXParams(&def); 1126 def.nPortIndex = kPortIndexOutput; 1127 1128 status_t err = mOMXNode->getParameter( 1129 OMX_IndexParamPortDefinition, &def, sizeof(def)); 1130 1131 if (err == OK) { 1132 err = setupNativeWindowSizeFormatAndUsage( 1133 mNativeWindow.get(), &mNativeWindowUsageBits, 1134 preregister && !mTunneled /* reconnect */); 1135 } 1136 if (err != OK) { 1137 mNativeWindowUsageBits = 0; 1138 return err; 1139 } 1140 1141 // Exits here for tunneled video playback codecs -- i.e. skips native window 1142 // buffer allocation step as this is managed by the tunneled OMX omponent 1143 // itself and explicitly sets def.nBufferCountActual to 0. 1144 if (mTunneled) { 1145 ALOGV("Tunneled Playback: skipping native window buffer allocation."); 1146 def.nBufferCountActual = 0; 1147 err = mOMXNode->setParameter( 1148 OMX_IndexParamPortDefinition, &def, sizeof(def)); 1149 1150 *minUndequeuedBuffers = 0; 1151 *bufferCount = 0; 1152 *bufferSize = 0; 1153 return err; 1154 } 1155 1156 *minUndequeuedBuffers = 0; 1157 err = mNativeWindow->query( 1158 mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, 1159 (int *)minUndequeuedBuffers); 1160 1161 if (err != 0) { 1162 ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)", 1163 strerror(-err), -err); 1164 return err; 1165 } 1166 1167 // FIXME: assume that surface is controlled by app (native window 1168 // returns the number for the case when surface is not controlled by app) 1169 // FIXME2: This means that minUndeqeueudBufs can be 1 larger than reported 1170 // For now, try to allocate 1 more buffer, but don't fail if unsuccessful 1171 1172 // Use conservative allocation while also trying to reduce starvation 1173 // 1174 // 1. allocate at least nBufferCountMin + minUndequeuedBuffers - that is the 1175 // minimum needed for the consumer to be able to work 1176 // 2. try to allocate two (2) additional buffers to reduce starvation from 1177 // the consumer 1178 // plus an extra buffer to account for incorrect minUndequeuedBufs 1179 for (OMX_U32 extraBuffers = 2 + 1; /* condition inside loop */; extraBuffers--) { 1180 OMX_U32 newBufferCount = 1181 def.nBufferCountMin + *minUndequeuedBuffers + extraBuffers; 1182 def.nBufferCountActual = newBufferCount; 1183 err = mOMXNode->setParameter( 1184 OMX_IndexParamPortDefinition, &def, sizeof(def)); 1185 1186 if (err == OK) { 1187 *minUndequeuedBuffers += extraBuffers; 1188 break; 1189 } 1190 1191 ALOGW("[%s] setting nBufferCountActual to %u failed: %d", 1192 mComponentName.c_str(), newBufferCount, err); 1193 /* exit condition */ 1194 if (extraBuffers == 0) { 1195 return err; 1196 } 1197 } 1198 1199 err = native_window_set_buffer_count( 1200 mNativeWindow.get(), def.nBufferCountActual); 1201 1202 if (err != 0) { 1203 ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), 1204 -err); 1205 return err; 1206 } 1207 1208 *bufferCount = def.nBufferCountActual; 1209 *bufferSize = def.nBufferSize; 1210 return err; 1211} 1212 1213status_t ACodec::allocateOutputBuffersFromNativeWindow() { 1214 // This method only handles the non-metadata mode (or simulating legacy 1215 // mode with metadata, which is transparent to ACodec). 1216 CHECK(!storingMetadataInDecodedBuffers()); 1217 1218 OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers; 1219 status_t err = configureOutputBuffersFromNativeWindow( 1220 &bufferCount, &bufferSize, &minUndequeuedBuffers, true /* preregister */); 1221 if (err != 0) 1222 return err; 1223 mNumUndequeuedBuffers = minUndequeuedBuffers; 1224 1225 static_cast<Surface*>(mNativeWindow.get()) 1226 ->getIGraphicBufferProducer()->allowAllocation(true); 1227 1228 ALOGV("[%s] Allocating %u buffers from a native window of size %u on " 1229 "output port", 1230 mComponentName.c_str(), bufferCount, bufferSize); 1231 1232 // Dequeue buffers and send them to OMX 1233 for (OMX_U32 i = 0; i < bufferCount; i++) { 1234 ANativeWindowBuffer *buf; 1235 int fenceFd; 1236 err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf, &fenceFd); 1237 if (err != 0) { 1238 ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err); 1239 break; 1240 } 1241 1242 sp<GraphicBuffer> graphicBuffer(GraphicBuffer::from(buf)); 1243 BufferInfo info; 1244 info.mStatus = BufferInfo::OWNED_BY_US; 1245 info.mFenceFd = fenceFd; 1246 info.mIsReadFence = false; 1247 info.mRenderInfo = NULL; 1248 info.mGraphicBuffer = graphicBuffer; 1249 info.mNewGraphicBuffer = false; 1250 1251 // TODO: We shouln't need to create MediaCodecBuffer. In metadata mode 1252 // OMX doesn't use the shared memory buffer, but some code still 1253 // access info.mData. Create an ABuffer as a placeholder. 1254 info.mData = new MediaCodecBuffer(mOutputFormat, new ABuffer(bufferSize)); 1255 info.mCodecData = info.mData; 1256 1257 mBuffers[kPortIndexOutput].push(info); 1258 1259 IOMX::buffer_id bufferId; 1260 err = mOMXNode->useBuffer(kPortIndexOutput, graphicBuffer, &bufferId); 1261 if (err != 0) { 1262 ALOGE("registering GraphicBuffer %u with OMX IL component failed: " 1263 "%d", i, err); 1264 break; 1265 } 1266 1267 mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId; 1268 1269 ALOGV("[%s] Registered graphic buffer with ID %u (pointer = %p)", 1270 mComponentName.c_str(), 1271 bufferId, graphicBuffer.get()); 1272 } 1273 1274 OMX_U32 cancelStart; 1275 OMX_U32 cancelEnd; 1276 1277 if (err != OK) { 1278 // If an error occurred while dequeuing we need to cancel any buffers 1279 // that were dequeued. Also cancel all if we're in legacy metadata mode. 1280 cancelStart = 0; 1281 cancelEnd = mBuffers[kPortIndexOutput].size(); 1282 } else { 1283 // Return the required minimum undequeued buffers to the native window. 1284 cancelStart = bufferCount - minUndequeuedBuffers; 1285 cancelEnd = bufferCount; 1286 } 1287 1288 for (OMX_U32 i = cancelStart; i < cancelEnd; i++) { 1289 BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i); 1290 if (info->mStatus == BufferInfo::OWNED_BY_US) { 1291 status_t error = cancelBufferToNativeWindow(info); 1292 if (err == 0) { 1293 err = error; 1294 } 1295 } 1296 } 1297 1298 static_cast<Surface*>(mNativeWindow.get()) 1299 ->getIGraphicBufferProducer()->allowAllocation(false); 1300 1301 return err; 1302} 1303 1304status_t ACodec::allocateOutputMetadataBuffers() { 1305 CHECK(storingMetadataInDecodedBuffers()); 1306 1307 OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers; 1308 status_t err = configureOutputBuffersFromNativeWindow( 1309 &bufferCount, &bufferSize, &minUndequeuedBuffers, 1310 false /* preregister */); 1311 if (err != OK) 1312 return err; 1313 mNumUndequeuedBuffers = minUndequeuedBuffers; 1314 1315 ALOGV("[%s] Allocating %u meta buffers on output port", 1316 mComponentName.c_str(), bufferCount); 1317 1318 for (OMX_U32 i = 0; i < bufferCount; i++) { 1319 BufferInfo info; 1320 info.mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 1321 info.mFenceFd = -1; 1322 info.mRenderInfo = NULL; 1323 info.mGraphicBuffer = NULL; 1324 info.mNewGraphicBuffer = false; 1325 info.mDequeuedAt = mDequeueCounter; 1326 1327 info.mData = new MediaCodecBuffer(mOutputFormat, new ABuffer(bufferSize)); 1328 1329 // Initialize fence fd to -1 to avoid warning in freeBuffer(). 1330 ((VideoNativeMetadata *)info.mData->base())->nFenceFd = -1; 1331 1332 info.mCodecData = info.mData; 1333 1334 err = mOMXNode->useBuffer(kPortIndexOutput, OMXBuffer::sPreset, &info.mBufferID); 1335 mBuffers[kPortIndexOutput].push(info); 1336 1337 ALOGV("[%s] allocated meta buffer with ID %u", 1338 mComponentName.c_str(), info.mBufferID); 1339 } 1340 1341 mMetadataBuffersToSubmit = bufferCount - minUndequeuedBuffers; 1342 return err; 1343} 1344 1345status_t ACodec::submitOutputMetadataBuffer() { 1346 CHECK(storingMetadataInDecodedBuffers()); 1347 if (mMetadataBuffersToSubmit == 0) 1348 return OK; 1349 1350 BufferInfo *info = dequeueBufferFromNativeWindow(); 1351 if (info == NULL) { 1352 return ERROR_IO; 1353 } 1354 1355 ALOGV("[%s] submitting output meta buffer ID %u for graphic buffer %p", 1356 mComponentName.c_str(), info->mBufferID, info->mGraphicBuffer->handle); 1357 1358 --mMetadataBuffersToSubmit; 1359 info->checkWriteFence("submitOutputMetadataBuffer"); 1360 return fillBuffer(info); 1361} 1362 1363status_t ACodec::waitForFence(int fd, const char *dbg ) { 1364 status_t res = OK; 1365 if (fd >= 0) { 1366 sp<Fence> fence = new Fence(fd); 1367 res = fence->wait(IOMX::kFenceTimeoutMs); 1368 ALOGW_IF(res != OK, "FENCE TIMEOUT for %d in %s", fd, dbg); 1369 } 1370 return res; 1371} 1372 1373// static 1374const char *ACodec::_asString(BufferInfo::Status s) { 1375 switch (s) { 1376 case BufferInfo::OWNED_BY_US: return "OUR"; 1377 case BufferInfo::OWNED_BY_COMPONENT: return "COMPONENT"; 1378 case BufferInfo::OWNED_BY_UPSTREAM: return "UPSTREAM"; 1379 case BufferInfo::OWNED_BY_DOWNSTREAM: return "DOWNSTREAM"; 1380 case BufferInfo::OWNED_BY_NATIVE_WINDOW: return "SURFACE"; 1381 case BufferInfo::UNRECOGNIZED: return "UNRECOGNIZED"; 1382 default: return "?"; 1383 } 1384} 1385 1386void ACodec::dumpBuffers(OMX_U32 portIndex) { 1387 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 1388 ALOGI("[%s] %s port has %zu buffers:", mComponentName.c_str(), 1389 portIndex == kPortIndexInput ? "input" : "output", mBuffers[portIndex].size()); 1390 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 1391 const BufferInfo &info = mBuffers[portIndex][i]; 1392 ALOGI(" slot %2zu: #%8u %p/%p %s(%d) dequeued:%u", 1393 i, info.mBufferID, info.mGraphicBuffer.get(), 1394 info.mGraphicBuffer == NULL ? NULL : info.mGraphicBuffer->getNativeBuffer(), 1395 _asString(info.mStatus), info.mStatus, info.mDequeuedAt); 1396 } 1397} 1398 1399status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) { 1400 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 1401 1402 ALOGV("[%s] Calling cancelBuffer on buffer %u", 1403 mComponentName.c_str(), info->mBufferID); 1404 1405 info->checkWriteFence("cancelBufferToNativeWindow"); 1406 int err = mNativeWindow->cancelBuffer( 1407 mNativeWindow.get(), info->mGraphicBuffer.get(), info->mFenceFd); 1408 info->mFenceFd = -1; 1409 1410 ALOGW_IF(err != 0, "[%s] can not return buffer %u to native window", 1411 mComponentName.c_str(), info->mBufferID); 1412 // change ownership even if cancelBuffer fails 1413 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 1414 1415 return err; 1416} 1417 1418void ACodec::updateRenderInfoForDequeuedBuffer( 1419 ANativeWindowBuffer *buf, int fenceFd, BufferInfo *info) { 1420 1421 info->mRenderInfo = 1422 mRenderTracker.updateInfoForDequeuedBuffer( 1423 buf, fenceFd, info - &mBuffers[kPortIndexOutput][0]); 1424 1425 // check for any fences already signaled 1426 notifyOfRenderedFrames(false /* dropIncomplete */, info->mRenderInfo); 1427} 1428 1429void ACodec::onFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) { 1430 if (mRenderTracker.onFrameRendered(mediaTimeUs, systemNano) != OK) { 1431 mRenderTracker.dumpRenderQueue(); 1432 } 1433} 1434 1435void ACodec::notifyOfRenderedFrames(bool dropIncomplete, FrameRenderTracker::Info *until) { 1436 std::list<FrameRenderTracker::Info> done = 1437 mRenderTracker.checkFencesAndGetRenderedFrames(until, dropIncomplete); 1438 1439 // unlink untracked frames 1440 for (std::list<FrameRenderTracker::Info>::const_iterator it = done.cbegin(); 1441 it != done.cend(); ++it) { 1442 ssize_t index = it->getIndex(); 1443 if (index >= 0 && (size_t)index < mBuffers[kPortIndexOutput].size()) { 1444 mBuffers[kPortIndexOutput].editItemAt(index).mRenderInfo = NULL; 1445 } else if (index >= 0) { 1446 // THIS SHOULD NEVER HAPPEN 1447 ALOGE("invalid index %zd in %zu", index, mBuffers[kPortIndexOutput].size()); 1448 } 1449 } 1450 1451 mCallback->onOutputFramesRendered(done); 1452} 1453 1454ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() { 1455 ANativeWindowBuffer *buf; 1456 CHECK(mNativeWindow.get() != NULL); 1457 1458 if (mTunneled) { 1459 ALOGW("dequeueBufferFromNativeWindow() should not be called in tunnel" 1460 " video playback mode mode!"); 1461 return NULL; 1462 } 1463 1464 if (mFatalError) { 1465 ALOGW("not dequeuing from native window due to fatal error"); 1466 return NULL; 1467 } 1468 1469 int fenceFd = -1; 1470 do { 1471 status_t err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf, &fenceFd); 1472 if (err != 0) { 1473 ALOGE("dequeueBuffer failed: %s(%d).", asString(err), err); 1474 return NULL; 1475 } 1476 1477 bool stale = false; 1478 for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) { 1479 i--; 1480 BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i); 1481 1482 if (info->mGraphicBuffer != NULL && 1483 info->mGraphicBuffer->handle == buf->handle) { 1484 // Since consumers can attach buffers to BufferQueues, it is possible 1485 // that a known yet stale buffer can return from a surface that we 1486 // once used. We can simply ignore this as we have already dequeued 1487 // this buffer properly. NOTE: this does not eliminate all cases, 1488 // e.g. it is possible that we have queued the valid buffer to the 1489 // NW, and a stale copy of the same buffer gets dequeued - which will 1490 // be treated as the valid buffer by ACodec. 1491 if (info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) { 1492 ALOGI("dequeued stale buffer %p. discarding", buf); 1493 stale = true; 1494 break; 1495 } 1496 1497 ALOGV("dequeued buffer #%u with age %u, graphicBuffer %p", 1498 (unsigned)(info - &mBuffers[kPortIndexOutput][0]), 1499 mDequeueCounter - info->mDequeuedAt, 1500 info->mGraphicBuffer->handle); 1501 1502 info->mStatus = BufferInfo::OWNED_BY_US; 1503 info->setWriteFence(fenceFd, "dequeueBufferFromNativeWindow"); 1504 updateRenderInfoForDequeuedBuffer(buf, fenceFd, info); 1505 return info; 1506 } 1507 } 1508 1509 // It is also possible to receive a previously unregistered buffer 1510 // in non-meta mode. These should be treated as stale buffers. The 1511 // same is possible in meta mode, in which case, it will be treated 1512 // as a normal buffer, which is not desirable. 1513 // TODO: fix this. 1514 if (!stale && !storingMetadataInDecodedBuffers()) { 1515 ALOGI("dequeued unrecognized (stale) buffer %p. discarding", buf); 1516 stale = true; 1517 } 1518 if (stale) { 1519 // TODO: detach stale buffer, but there is no API yet to do it. 1520 buf = NULL; 1521 } 1522 } while (buf == NULL); 1523 1524 // get oldest undequeued buffer 1525 BufferInfo *oldest = NULL; 1526 for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) { 1527 i--; 1528 BufferInfo *info = 1529 &mBuffers[kPortIndexOutput].editItemAt(i); 1530 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW && 1531 (oldest == NULL || 1532 // avoid potential issues from counter rolling over 1533 mDequeueCounter - info->mDequeuedAt > 1534 mDequeueCounter - oldest->mDequeuedAt)) { 1535 oldest = info; 1536 } 1537 } 1538 1539 // it is impossible dequeue a buffer when there are no buffers with ANW 1540 CHECK(oldest != NULL); 1541 // it is impossible to dequeue an unknown buffer in non-meta mode, as the 1542 // while loop above does not complete 1543 CHECK(storingMetadataInDecodedBuffers()); 1544 1545 // discard buffer in LRU info and replace with new buffer 1546 oldest->mGraphicBuffer = GraphicBuffer::from(buf); 1547 oldest->mNewGraphicBuffer = true; 1548 oldest->mStatus = BufferInfo::OWNED_BY_US; 1549 oldest->setWriteFence(fenceFd, "dequeueBufferFromNativeWindow for oldest"); 1550 mRenderTracker.untrackFrame(oldest->mRenderInfo); 1551 oldest->mRenderInfo = NULL; 1552 1553 ALOGV("replaced oldest buffer #%u with age %u, graphicBuffer %p", 1554 (unsigned)(oldest - &mBuffers[kPortIndexOutput][0]), 1555 mDequeueCounter - oldest->mDequeuedAt, 1556 oldest->mGraphicBuffer->handle); 1557 1558 updateRenderInfoForDequeuedBuffer(buf, fenceFd, oldest); 1559 return oldest; 1560} 1561 1562status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) { 1563 if (portIndex == kPortIndexInput) { 1564 mBufferChannel->setInputBufferArray({}); 1565 } else { 1566 mBufferChannel->setOutputBufferArray({}); 1567 } 1568 1569 status_t err = OK; 1570 for (size_t i = mBuffers[portIndex].size(); i > 0;) { 1571 i--; 1572 status_t err2 = freeBuffer(portIndex, i); 1573 if (err == OK) { 1574 err = err2; 1575 } 1576 } 1577 1578 mAllocator[portIndex].clear(); 1579 return err; 1580} 1581 1582status_t ACodec::freeOutputBuffersNotOwnedByComponent() { 1583 status_t err = OK; 1584 for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) { 1585 i--; 1586 BufferInfo *info = 1587 &mBuffers[kPortIndexOutput].editItemAt(i); 1588 1589 // At this time some buffers may still be with the component 1590 // or being drained. 1591 if (info->mStatus != BufferInfo::OWNED_BY_COMPONENT && 1592 info->mStatus != BufferInfo::OWNED_BY_DOWNSTREAM) { 1593 status_t err2 = freeBuffer(kPortIndexOutput, i); 1594 if (err == OK) { 1595 err = err2; 1596 } 1597 } 1598 } 1599 1600 return err; 1601} 1602 1603status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) { 1604 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 1605 status_t err = OK; 1606 1607 // there should not be any fences in the metadata 1608 if (mPortMode[portIndex] == IOMX::kPortModeDynamicANWBuffer && info->mCodecData != NULL 1609 && info->mCodecData->size() >= sizeof(VideoNativeMetadata)) { 1610 int fenceFd = ((VideoNativeMetadata *)info->mCodecData->base())->nFenceFd; 1611 if (fenceFd >= 0) { 1612 ALOGW("unreleased fence (%d) in %s metadata buffer %zu", 1613 fenceFd, portIndex == kPortIndexInput ? "input" : "output", i); 1614 } 1615 } 1616 1617 switch (info->mStatus) { 1618 case BufferInfo::OWNED_BY_US: 1619 if (portIndex == kPortIndexOutput && mNativeWindow != NULL) { 1620 (void)cancelBufferToNativeWindow(info); 1621 } 1622 // fall through 1623 1624 case BufferInfo::OWNED_BY_NATIVE_WINDOW: 1625 err = mOMXNode->freeBuffer(portIndex, info->mBufferID); 1626 break; 1627 1628 default: 1629 ALOGE("trying to free buffer not owned by us or ANW (%d)", info->mStatus); 1630 err = FAILED_TRANSACTION; 1631 break; 1632 } 1633 1634 if (info->mFenceFd >= 0) { 1635 ::close(info->mFenceFd); 1636 } 1637 1638 if (portIndex == kPortIndexOutput) { 1639 mRenderTracker.untrackFrame(info->mRenderInfo, i); 1640 info->mRenderInfo = NULL; 1641 } 1642 1643 // remove buffer even if mOMXNode->freeBuffer fails 1644 mBuffers[portIndex].removeAt(i); 1645 return err; 1646} 1647 1648ACodec::BufferInfo *ACodec::findBufferByID( 1649 uint32_t portIndex, IOMX::buffer_id bufferID, ssize_t *index) { 1650 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 1651 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 1652 1653 if (info->mBufferID == bufferID) { 1654 if (index != NULL) { 1655 *index = i; 1656 } 1657 return info; 1658 } 1659 } 1660 1661 ALOGE("Could not find buffer with ID %u", bufferID); 1662 return NULL; 1663} 1664 1665status_t ACodec::fillBuffer(BufferInfo *info) { 1666 status_t err; 1667 // Even in dynamic ANW buffer mode, if the graphic buffer is not changing, 1668 // send sPreset instead of the same graphic buffer, so that OMX server 1669 // side doesn't update the meta. In theory it should make no difference, 1670 // however when the same buffer is parcelled again, a new handle could be 1671 // created on server side, and some decoder doesn't recognize the handle 1672 // even if it's the same buffer. 1673 if (!storingMetadataInDecodedBuffers() || !info->mNewGraphicBuffer) { 1674 err = mOMXNode->fillBuffer( 1675 info->mBufferID, OMXBuffer::sPreset, info->mFenceFd); 1676 } else { 1677 err = mOMXNode->fillBuffer( 1678 info->mBufferID, info->mGraphicBuffer, info->mFenceFd); 1679 } 1680 1681 info->mNewGraphicBuffer = false; 1682 info->mFenceFd = -1; 1683 if (err == OK) { 1684 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 1685 } 1686 return err; 1687} 1688 1689status_t ACodec::setComponentRole( 1690 bool isEncoder, const char *mime) { 1691 const char *role = GetComponentRole(isEncoder, mime); 1692 if (role == NULL) { 1693 return BAD_VALUE; 1694 } 1695 status_t err = SetComponentRole(mOMXNode, role); 1696 if (err != OK) { 1697 ALOGW("[%s] Failed to set standard component role '%s'.", 1698 mComponentName.c_str(), role); 1699 } 1700 return err; 1701} 1702 1703status_t ACodec::configureCodec( 1704 const char *mime, const sp<AMessage> &msg) { 1705 int32_t encoder; 1706 if (!msg->findInt32("encoder", &encoder)) { 1707 encoder = false; 1708 } 1709 1710 sp<AMessage> inputFormat = new AMessage; 1711 sp<AMessage> outputFormat = new AMessage; 1712 mConfigFormat = msg; 1713 1714 mIsEncoder = encoder; 1715 mIsVideo = !strncasecmp(mime, "video/", 6); 1716 mIsImage = !strncasecmp(mime, "image/", 6); 1717 1718 mPortMode[kPortIndexInput] = IOMX::kPortModePresetByteBuffer; 1719 mPortMode[kPortIndexOutput] = IOMX::kPortModePresetByteBuffer; 1720 1721 status_t err = setComponentRole(encoder /* isEncoder */, mime); 1722 1723 if (err != OK) { 1724 return err; 1725 } 1726 1727 OMX_VIDEO_CONTROLRATETYPE bitrateMode; 1728 int32_t bitrate = 0, quality; 1729 // FLAC encoder or video encoder in constant quality mode doesn't need a 1730 // bitrate, other encoders do. 1731 if (encoder) { 1732 if (mIsVideo || mIsImage) { 1733 if (!findVideoBitrateControlInfo(msg, &bitrateMode, &bitrate, &quality)) { 1734 return INVALID_OPERATION; 1735 } 1736 } else if (strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC) 1737 && !msg->findInt32("bitrate", &bitrate)) { 1738 return INVALID_OPERATION; 1739 } 1740 } 1741 1742 // propagate bitrate to the output so that the muxer has it 1743 if (encoder && msg->findInt32("bitrate", &bitrate)) { 1744 // Technically ISO spec says that 'bitrate' should be 0 for VBR even though it is the 1745 // average bitrate. We've been setting both bitrate and max-bitrate to this same value. 1746 outputFormat->setInt32("bitrate", bitrate); 1747 outputFormat->setInt32("max-bitrate", bitrate); 1748 } 1749 1750 int32_t storeMeta; 1751 if (encoder 1752 && msg->findInt32("android._input-metadata-buffer-type", &storeMeta) 1753 && storeMeta != kMetadataBufferTypeInvalid) { 1754 IOMX::PortMode mode; 1755 if (storeMeta == kMetadataBufferTypeNativeHandleSource) { 1756 mode = IOMX::kPortModeDynamicNativeHandle; 1757 } else if (storeMeta == kMetadataBufferTypeANWBuffer || 1758 storeMeta == kMetadataBufferTypeGrallocSource) { 1759 mode = IOMX::kPortModeDynamicANWBuffer; 1760 } else { 1761 return BAD_VALUE; 1762 } 1763 err = setPortMode(kPortIndexInput, mode); 1764 if (err != OK) { 1765 return err; 1766 } 1767 1768 uint32_t usageBits; 1769 if (mOMXNode->getParameter( 1770 (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits, 1771 &usageBits, sizeof(usageBits)) == OK) { 1772 inputFormat->setInt32( 1773 "using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN)); 1774 } 1775 } 1776 1777 int32_t prependSPSPPS = 0; 1778 if (encoder 1779 && msg->findInt32("prepend-sps-pps-to-idr-frames", &prependSPSPPS) 1780 && prependSPSPPS != 0) { 1781 OMX_INDEXTYPE index; 1782 err = mOMXNode->getExtensionIndex( 1783 "OMX.google.android.index.prependSPSPPSToIDRFrames", &index); 1784 1785 if (err == OK) { 1786 PrependSPSPPSToIDRFramesParams params; 1787 InitOMXParams(¶ms); 1788 params.bEnable = OMX_TRUE; 1789 1790 err = mOMXNode->setParameter(index, ¶ms, sizeof(params)); 1791 } 1792 1793 if (err != OK) { 1794 ALOGE("Encoder could not be configured to emit SPS/PPS before " 1795 "IDR frames. (err %d)", err); 1796 1797 return err; 1798 } 1799 } 1800 1801 // Only enable metadata mode on encoder output if encoder can prepend 1802 // sps/pps to idr frames, since in metadata mode the bitstream is in an 1803 // opaque handle, to which we don't have access. 1804 if (encoder && mIsVideo) { 1805 OMX_BOOL enable = (OMX_BOOL) (prependSPSPPS 1806 && msg->findInt32("android._store-metadata-in-buffers-output", &storeMeta) 1807 && storeMeta != 0); 1808 if (mFlags & kFlagIsSecure) { 1809 enable = OMX_TRUE; 1810 } 1811 1812 err = setPortMode(kPortIndexOutput, enable ? 1813 IOMX::kPortModePresetSecureBuffer : IOMX::kPortModePresetByteBuffer); 1814 if (err != OK) { 1815 return err; 1816 } 1817 1818 if (!msg->findInt64( 1819 "repeat-previous-frame-after", 1820 &mRepeatFrameDelayUs)) { 1821 mRepeatFrameDelayUs = -1ll; 1822 } 1823 1824 // only allow 32-bit value, since we pass it as U32 to OMX. 1825 if (!msg->findInt64("max-pts-gap-to-encoder", &mMaxPtsGapUs)) { 1826 mMaxPtsGapUs = -1ll; 1827 } else if (mMaxPtsGapUs > INT32_MAX || mMaxPtsGapUs < 0) { 1828 ALOGW("Unsupported value for max pts gap %lld", (long long) mMaxPtsGapUs); 1829 mMaxPtsGapUs = -1ll; 1830 } 1831 1832 if (!msg->findFloat("max-fps-to-encoder", &mMaxFps)) { 1833 mMaxFps = -1; 1834 } 1835 1836 if (!msg->findDouble("time-lapse-fps", &mCaptureFps)) { 1837 mCaptureFps = -1.0; 1838 } 1839 1840 if (!msg->findInt32( 1841 "create-input-buffers-suspended", 1842 (int32_t*)&mCreateInputBuffersSuspended)) { 1843 mCreateInputBuffersSuspended = false; 1844 } 1845 } 1846 1847 // NOTE: we only use native window for video decoders 1848 sp<RefBase> obj; 1849 bool haveNativeWindow = msg->findObject("native-window", &obj) 1850 && obj != NULL && mIsVideo && !encoder; 1851 mUsingNativeWindow = haveNativeWindow; 1852 if (mIsVideo && !encoder) { 1853 inputFormat->setInt32("adaptive-playback", false); 1854 1855 int32_t usageProtected; 1856 if (msg->findInt32("protected", &usageProtected) && usageProtected) { 1857 if (!haveNativeWindow) { 1858 ALOGE("protected output buffers must be sent to an ANativeWindow"); 1859 return PERMISSION_DENIED; 1860 } 1861 mFlags |= kFlagIsGrallocUsageProtected; 1862 mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown; 1863 } 1864 } 1865 if (mFlags & kFlagIsSecure) { 1866 // use native_handles for secure input buffers 1867 err = setPortMode(kPortIndexInput, IOMX::kPortModePresetSecureBuffer); 1868 1869 if (err != OK) { 1870 ALOGI("falling back to non-native_handles"); 1871 setPortMode(kPortIndexInput, IOMX::kPortModePresetByteBuffer); 1872 err = OK; // ignore error for now 1873 } 1874 } 1875 if (haveNativeWindow) { 1876 sp<ANativeWindow> nativeWindow = 1877 static_cast<ANativeWindow *>(static_cast<Surface *>(obj.get())); 1878 1879 // START of temporary support for automatic FRC - THIS WILL BE REMOVED 1880 int32_t autoFrc; 1881 if (msg->findInt32("auto-frc", &autoFrc)) { 1882 bool enabled = autoFrc; 1883 OMX_CONFIG_BOOLEANTYPE config; 1884 InitOMXParams(&config); 1885 config.bEnabled = (OMX_BOOL)enabled; 1886 status_t temp = mOMXNode->setConfig( 1887 (OMX_INDEXTYPE)OMX_IndexConfigAutoFramerateConversion, 1888 &config, sizeof(config)); 1889 if (temp == OK) { 1890 outputFormat->setInt32("auto-frc", enabled); 1891 } else if (enabled) { 1892 ALOGI("codec does not support requested auto-frc (err %d)", temp); 1893 } 1894 } 1895 // END of temporary support for automatic FRC 1896 1897 int32_t tunneled; 1898 if (msg->findInt32("feature-tunneled-playback", &tunneled) && 1899 tunneled != 0) { 1900 ALOGI("Configuring TUNNELED video playback."); 1901 mTunneled = true; 1902 1903 int32_t audioHwSync = 0; 1904 if (!msg->findInt32("audio-hw-sync", &audioHwSync)) { 1905 ALOGW("No Audio HW Sync provided for video tunnel"); 1906 } 1907 err = configureTunneledVideoPlayback(audioHwSync, nativeWindow); 1908 if (err != OK) { 1909 ALOGE("configureTunneledVideoPlayback(%d,%p) failed!", 1910 audioHwSync, nativeWindow.get()); 1911 return err; 1912 } 1913 1914 int32_t maxWidth = 0, maxHeight = 0; 1915 if (msg->findInt32("max-width", &maxWidth) && 1916 msg->findInt32("max-height", &maxHeight)) { 1917 1918 err = mOMXNode->prepareForAdaptivePlayback( 1919 kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight); 1920 if (err != OK) { 1921 ALOGW("[%s] prepareForAdaptivePlayback failed w/ err %d", 1922 mComponentName.c_str(), err); 1923 // allow failure 1924 err = OK; 1925 } else { 1926 inputFormat->setInt32("max-width", maxWidth); 1927 inputFormat->setInt32("max-height", maxHeight); 1928 inputFormat->setInt32("adaptive-playback", true); 1929 } 1930 } 1931 } else { 1932 ALOGV("Configuring CPU controlled video playback."); 1933 mTunneled = false; 1934 1935 // Explicity reset the sideband handle of the window for 1936 // non-tunneled video in case the window was previously used 1937 // for a tunneled video playback. 1938 err = native_window_set_sideband_stream(nativeWindow.get(), NULL); 1939 if (err != OK) { 1940 ALOGE("set_sideband_stream(NULL) failed! (err %d).", err); 1941 return err; 1942 } 1943 1944 err = setPortMode(kPortIndexOutput, IOMX::kPortModeDynamicANWBuffer); 1945 if (err != OK) { 1946 // if adaptive playback has been requested, try JB fallback 1947 // NOTE: THIS FALLBACK MECHANISM WILL BE REMOVED DUE TO ITS 1948 // LARGE MEMORY REQUIREMENT 1949 1950 // we will not do adaptive playback on software accessed 1951 // surfaces as they never had to respond to changes in the 1952 // crop window, and we don't trust that they will be able to. 1953 int usageBits = 0; 1954 bool canDoAdaptivePlayback; 1955 1956 if (nativeWindow->query( 1957 nativeWindow.get(), 1958 NATIVE_WINDOW_CONSUMER_USAGE_BITS, 1959 &usageBits) != OK) { 1960 canDoAdaptivePlayback = false; 1961 } else { 1962 canDoAdaptivePlayback = 1963 (usageBits & 1964 (GRALLOC_USAGE_SW_READ_MASK | 1965 GRALLOC_USAGE_SW_WRITE_MASK)) == 0; 1966 } 1967 1968 int32_t maxWidth = 0, maxHeight = 0; 1969 if (canDoAdaptivePlayback && 1970 msg->findInt32("max-width", &maxWidth) && 1971 msg->findInt32("max-height", &maxHeight)) { 1972 ALOGV("[%s] prepareForAdaptivePlayback(%dx%d)", 1973 mComponentName.c_str(), maxWidth, maxHeight); 1974 1975 err = mOMXNode->prepareForAdaptivePlayback( 1976 kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight); 1977 ALOGW_IF(err != OK, 1978 "[%s] prepareForAdaptivePlayback failed w/ err %d", 1979 mComponentName.c_str(), err); 1980 1981 if (err == OK) { 1982 inputFormat->setInt32("max-width", maxWidth); 1983 inputFormat->setInt32("max-height", maxHeight); 1984 inputFormat->setInt32("adaptive-playback", true); 1985 } 1986 } 1987 // allow failure 1988 err = OK; 1989 } else { 1990 ALOGV("[%s] setPortMode on output to %s succeeded", 1991 mComponentName.c_str(), asString(IOMX::kPortModeDynamicANWBuffer)); 1992 CHECK(storingMetadataInDecodedBuffers()); 1993 inputFormat->setInt32("adaptive-playback", true); 1994 } 1995 1996 int32_t push; 1997 if (msg->findInt32("push-blank-buffers-on-shutdown", &push) 1998 && push != 0) { 1999 mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown; 2000 } 2001 } 2002 2003 int32_t rotationDegrees; 2004 if (msg->findInt32("rotation-degrees", &rotationDegrees)) { 2005 mRotationDegrees = rotationDegrees; 2006 } else { 2007 mRotationDegrees = 0; 2008 } 2009 } 2010 2011 AudioEncoding pcmEncoding = kAudioEncodingPcm16bit; 2012 (void)msg->findInt32("pcm-encoding", (int32_t*)&pcmEncoding); 2013 // invalid encodings will default to PCM-16bit in setupRawAudioFormat. 2014 2015 if (mIsVideo || mIsImage) { 2016 // determine need for software renderer 2017 bool usingSwRenderer = false; 2018 if (haveNativeWindow && mComponentName.startsWith("OMX.google.")) { 2019 usingSwRenderer = true; 2020 haveNativeWindow = false; 2021 (void)setPortMode(kPortIndexOutput, IOMX::kPortModePresetByteBuffer); 2022 } else if (haveNativeWindow && !storingMetadataInDecodedBuffers()) { 2023 err = setPortMode(kPortIndexOutput, IOMX::kPortModePresetANWBuffer); 2024 if (err != OK) { 2025 return err; 2026 } 2027 } 2028 2029 if (encoder) { 2030 err = setupVideoEncoder(mime, msg, outputFormat, inputFormat); 2031 } else { 2032 err = setupVideoDecoder(mime, msg, haveNativeWindow, usingSwRenderer, outputFormat); 2033 } 2034 2035 if (err != OK) { 2036 return err; 2037 } 2038 2039 if (haveNativeWindow) { 2040 mNativeWindow = static_cast<Surface *>(obj.get()); 2041 2042 // fallback for devices that do not handle flex-YUV for native buffers 2043 int32_t requestedColorFormat = OMX_COLOR_FormatUnused; 2044 if (msg->findInt32("color-format", &requestedColorFormat) && 2045 requestedColorFormat == OMX_COLOR_FormatYUV420Flexible) { 2046 status_t err = getPortFormat(kPortIndexOutput, outputFormat); 2047 if (err != OK) { 2048 return err; 2049 } 2050 int32_t colorFormat = OMX_COLOR_FormatUnused; 2051 OMX_U32 flexibleEquivalent = OMX_COLOR_FormatUnused; 2052 if (!outputFormat->findInt32("color-format", &colorFormat)) { 2053 ALOGE("ouptut port did not have a color format (wrong domain?)"); 2054 return BAD_VALUE; 2055 } 2056 ALOGD("[%s] Requested output format %#x and got %#x.", 2057 mComponentName.c_str(), requestedColorFormat, colorFormat); 2058 if (!IsFlexibleColorFormat( 2059 mOMXNode, colorFormat, haveNativeWindow, &flexibleEquivalent) 2060 || flexibleEquivalent != (OMX_U32)requestedColorFormat) { 2061 // device did not handle flex-YUV request for native window, fall back 2062 // to SW renderer 2063 ALOGI("[%s] Falling back to software renderer", mComponentName.c_str()); 2064 mNativeWindow.clear(); 2065 mNativeWindowUsageBits = 0; 2066 haveNativeWindow = false; 2067 usingSwRenderer = true; 2068 // TODO: implement adaptive-playback support for bytebuffer mode. 2069 // This is done by SW codecs, but most HW codecs don't support it. 2070 err = setPortMode(kPortIndexOutput, IOMX::kPortModePresetByteBuffer); 2071 inputFormat->setInt32("adaptive-playback", false); 2072 if (mFlags & kFlagIsGrallocUsageProtected) { 2073 // fallback is not supported for protected playback 2074 err = PERMISSION_DENIED; 2075 } else if (err == OK) { 2076 err = setupVideoDecoder( 2077 mime, msg, haveNativeWindow, usingSwRenderer, outputFormat); 2078 } 2079 } 2080 } 2081 } 2082 2083 if (usingSwRenderer) { 2084 outputFormat->setInt32("using-sw-renderer", 1); 2085 } 2086 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) { 2087 int32_t numChannels, sampleRate; 2088 if (!msg->findInt32("channel-count", &numChannels) 2089 || !msg->findInt32("sample-rate", &sampleRate)) { 2090 // Since we did not always check for these, leave them optional 2091 // and have the decoder figure it all out. 2092 err = OK; 2093 } else { 2094 err = setupRawAudioFormat( 2095 encoder ? kPortIndexInput : kPortIndexOutput, 2096 sampleRate, 2097 numChannels); 2098 } 2099 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 2100 int32_t numChannels, sampleRate; 2101 if (!msg->findInt32("channel-count", &numChannels) 2102 || !msg->findInt32("sample-rate", &sampleRate)) { 2103 err = INVALID_OPERATION; 2104 } else { 2105 int32_t isADTS, aacProfile; 2106 int32_t sbrMode; 2107 int32_t maxOutputChannelCount; 2108 int32_t pcmLimiterEnable; 2109 drcParams_t drc; 2110 if (!msg->findInt32("is-adts", &isADTS)) { 2111 isADTS = 0; 2112 } 2113 if (!msg->findInt32("aac-profile", &aacProfile)) { 2114 aacProfile = OMX_AUDIO_AACObjectNull; 2115 } 2116 if (!msg->findInt32("aac-sbr-mode", &sbrMode)) { 2117 sbrMode = -1; 2118 } 2119 2120 if (!msg->findInt32("aac-max-output-channel_count", &maxOutputChannelCount)) { 2121 maxOutputChannelCount = -1; 2122 } 2123 if (!msg->findInt32("aac-pcm-limiter-enable", &pcmLimiterEnable)) { 2124 // value is unknown 2125 pcmLimiterEnable = -1; 2126 } 2127 if (!msg->findInt32("aac-encoded-target-level", &drc.encodedTargetLevel)) { 2128 // value is unknown 2129 drc.encodedTargetLevel = -1; 2130 } 2131 if (!msg->findInt32("aac-drc-cut-level", &drc.drcCut)) { 2132 // value is unknown 2133 drc.drcCut = -1; 2134 } 2135 if (!msg->findInt32("aac-drc-boost-level", &drc.drcBoost)) { 2136 // value is unknown 2137 drc.drcBoost = -1; 2138 } 2139 if (!msg->findInt32("aac-drc-heavy-compression", &drc.heavyCompression)) { 2140 // value is unknown 2141 drc.heavyCompression = -1; 2142 } 2143 if (!msg->findInt32("aac-target-ref-level", &drc.targetRefLevel)) { 2144 // value is unknown 2145 drc.targetRefLevel = -1; 2146 } 2147 if (!msg->findInt32("aac-drc-effect-type", &drc.effectType)) { 2148 // value is unknown 2149 drc.effectType = -2; // valid values are -1 and over 2150 } 2151 2152 err = setupAACCodec( 2153 encoder, numChannels, sampleRate, bitrate, aacProfile, 2154 isADTS != 0, sbrMode, maxOutputChannelCount, drc, 2155 pcmLimiterEnable); 2156 } 2157 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) { 2158 err = setupAMRCodec(encoder, false /* isWAMR */, bitrate); 2159 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) { 2160 err = setupAMRCodec(encoder, true /* isWAMR */, bitrate); 2161 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW) 2162 || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) { 2163 // These are PCM-like formats with a fixed sample rate but 2164 // a variable number of channels. 2165 2166 int32_t numChannels; 2167 if (!msg->findInt32("channel-count", &numChannels)) { 2168 err = INVALID_OPERATION; 2169 } else { 2170 int32_t sampleRate; 2171 if (!msg->findInt32("sample-rate", &sampleRate)) { 2172 sampleRate = 8000; 2173 } 2174 err = setupG711Codec(encoder, sampleRate, numChannels); 2175 } 2176 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) { 2177 int32_t numChannels = 0, sampleRate = 0, compressionLevel = -1; 2178 if (encoder && 2179 (!msg->findInt32("channel-count", &numChannels) 2180 || !msg->findInt32("sample-rate", &sampleRate))) { 2181 ALOGE("missing channel count or sample rate for FLAC encoder"); 2182 err = INVALID_OPERATION; 2183 } else { 2184 if (encoder) { 2185 if (!msg->findInt32( 2186 "complexity", &compressionLevel) && 2187 !msg->findInt32( 2188 "flac-compression-level", &compressionLevel)) { 2189 compressionLevel = 5; // default FLAC compression level 2190 } else if (compressionLevel < 0) { 2191 ALOGW("compression level %d outside [0..8] range, " 2192 "using 0", 2193 compressionLevel); 2194 compressionLevel = 0; 2195 } else if (compressionLevel > 8) { 2196 ALOGW("compression level %d outside [0..8] range, " 2197 "using 8", 2198 compressionLevel); 2199 compressionLevel = 8; 2200 } 2201 } 2202 err = setupFlacCodec( 2203 encoder, numChannels, sampleRate, compressionLevel); 2204 } 2205 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) { 2206 int32_t numChannels, sampleRate; 2207 if (encoder 2208 || !msg->findInt32("channel-count", &numChannels) 2209 || !msg->findInt32("sample-rate", &sampleRate)) { 2210 err = INVALID_OPERATION; 2211 } else { 2212 err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels, pcmEncoding); 2213 } 2214 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AC3)) { 2215 int32_t numChannels; 2216 int32_t sampleRate; 2217 if (!msg->findInt32("channel-count", &numChannels) 2218 || !msg->findInt32("sample-rate", &sampleRate)) { 2219 err = INVALID_OPERATION; 2220 } else { 2221 err = setupAC3Codec(encoder, numChannels, sampleRate); 2222 } 2223 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_EAC3)) { 2224 int32_t numChannels; 2225 int32_t sampleRate; 2226 if (!msg->findInt32("channel-count", &numChannels) 2227 || !msg->findInt32("sample-rate", &sampleRate)) { 2228 err = INVALID_OPERATION; 2229 } else { 2230 err = setupEAC3Codec(encoder, numChannels, sampleRate); 2231 } 2232 } 2233 2234 if (err != OK) { 2235 return err; 2236 } 2237 2238 if (!msg->findInt32("encoder-delay", &mEncoderDelay)) { 2239 mEncoderDelay = 0; 2240 } 2241 2242 if (!msg->findInt32("encoder-padding", &mEncoderPadding)) { 2243 mEncoderPadding = 0; 2244 } 2245 2246 if (msg->findInt32("channel-mask", &mChannelMask)) { 2247 mChannelMaskPresent = true; 2248 } else { 2249 mChannelMaskPresent = false; 2250 } 2251 2252 int32_t maxInputSize; 2253 if (msg->findInt32("max-input-size", &maxInputSize)) { 2254 err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize); 2255 err = OK; // ignore error 2256 } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) { 2257 err = setMinBufferSize(kPortIndexInput, 8192); // XXX 2258 err = OK; // ignore error 2259 } 2260 2261 int32_t priority; 2262 if (msg->findInt32("priority", &priority)) { 2263 err = setPriority(priority); 2264 err = OK; // ignore error 2265 } 2266 2267 int32_t rateInt = -1; 2268 float rateFloat = -1; 2269 if (!msg->findFloat("operating-rate", &rateFloat)) { 2270 msg->findInt32("operating-rate", &rateInt); 2271 rateFloat = (float)rateInt; // 16MHz (FLINTMAX) is OK for upper bound. 2272 } 2273 if (rateFloat > 0) { 2274 err = setOperatingRate(rateFloat, mIsVideo); 2275 err = OK; // ignore errors 2276 } 2277 2278 if (err == OK) { 2279 err = setVendorParameters(msg); 2280 if (err != OK) { 2281 return err; 2282 } 2283 } 2284 2285 // NOTE: both mBaseOutputFormat and mOutputFormat are outputFormat to signal first frame. 2286 mBaseOutputFormat = outputFormat; 2287 mLastOutputFormat.clear(); 2288 2289 err = getPortFormat(kPortIndexInput, inputFormat); 2290 if (err == OK) { 2291 err = getPortFormat(kPortIndexOutput, outputFormat); 2292 if (err == OK) { 2293 mInputFormat = inputFormat; 2294 mOutputFormat = outputFormat; 2295 } 2296 } 2297 2298 // create data converters if needed 2299 if (!mIsVideo && !mIsImage && err == OK) { 2300 AudioEncoding codecPcmEncoding = kAudioEncodingPcm16bit; 2301 if (encoder) { 2302 (void)mInputFormat->findInt32("pcm-encoding", (int32_t*)&codecPcmEncoding); 2303 mConverter[kPortIndexInput] = AudioConverter::Create(pcmEncoding, codecPcmEncoding); 2304 if (mConverter[kPortIndexInput] != NULL) { 2305 mInputFormat->setInt32("pcm-encoding", pcmEncoding); 2306 } 2307 } else { 2308 (void)mOutputFormat->findInt32("pcm-encoding", (int32_t*)&codecPcmEncoding); 2309 mConverter[kPortIndexOutput] = AudioConverter::Create(codecPcmEncoding, pcmEncoding); 2310 if (mConverter[kPortIndexOutput] != NULL) { 2311 mOutputFormat->setInt32("pcm-encoding", pcmEncoding); 2312 } 2313 } 2314 } 2315 2316 return err; 2317} 2318 2319status_t ACodec::setLatency(uint32_t latency) { 2320 OMX_PARAM_U32TYPE config; 2321 InitOMXParams(&config); 2322 config.nPortIndex = kPortIndexInput; 2323 config.nU32 = (OMX_U32)latency; 2324 status_t err = mOMXNode->setConfig( 2325 (OMX_INDEXTYPE)OMX_IndexConfigLatency, 2326 &config, sizeof(config)); 2327 return err; 2328} 2329 2330status_t ACodec::getLatency(uint32_t *latency) { 2331 OMX_PARAM_U32TYPE config; 2332 InitOMXParams(&config); 2333 config.nPortIndex = kPortIndexInput; 2334 status_t err = mOMXNode->getConfig( 2335 (OMX_INDEXTYPE)OMX_IndexConfigLatency, 2336 &config, sizeof(config)); 2337 if (err == OK) { 2338 *latency = config.nU32; 2339 } 2340 return err; 2341} 2342 2343status_t ACodec::setPriority(int32_t priority) { 2344 if (priority < 0) { 2345 return BAD_VALUE; 2346 } 2347 OMX_PARAM_U32TYPE config; 2348 InitOMXParams(&config); 2349 config.nU32 = (OMX_U32)priority; 2350 status_t temp = mOMXNode->setConfig( 2351 (OMX_INDEXTYPE)OMX_IndexConfigPriority, 2352 &config, sizeof(config)); 2353 if (temp != OK) { 2354 ALOGI("codec does not support config priority (err %d)", temp); 2355 } 2356 return OK; 2357} 2358 2359status_t ACodec::setOperatingRate(float rateFloat, bool isVideo) { 2360 if (rateFloat < 0) { 2361 return BAD_VALUE; 2362 } 2363 OMX_U32 rate; 2364 if (isVideo) { 2365 if (rateFloat > 65535) { 2366 return BAD_VALUE; 2367 } 2368 rate = (OMX_U32)(rateFloat * 65536.0f + 0.5f); 2369 } else { 2370 if (rateFloat > UINT_MAX) { 2371 return BAD_VALUE; 2372 } 2373 rate = (OMX_U32)(rateFloat); 2374 } 2375 OMX_PARAM_U32TYPE config; 2376 InitOMXParams(&config); 2377 config.nU32 = rate; 2378 status_t err = mOMXNode->setConfig( 2379 (OMX_INDEXTYPE)OMX_IndexConfigOperatingRate, 2380 &config, sizeof(config)); 2381 if (err != OK) { 2382 ALOGI("codec does not support config operating rate (err %d)", err); 2383 } 2384 return OK; 2385} 2386 2387status_t ACodec::getIntraRefreshPeriod(uint32_t *intraRefreshPeriod) { 2388 OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params; 2389 InitOMXParams(¶ms); 2390 params.nPortIndex = kPortIndexOutput; 2391 status_t err = mOMXNode->getConfig( 2392 (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, ¶ms, sizeof(params)); 2393 if (err == OK) { 2394 *intraRefreshPeriod = params.nRefreshPeriod; 2395 return OK; 2396 } 2397 2398 // Fallback to query through standard OMX index. 2399 OMX_VIDEO_PARAM_INTRAREFRESHTYPE refreshParams; 2400 InitOMXParams(&refreshParams); 2401 refreshParams.nPortIndex = kPortIndexOutput; 2402 refreshParams.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic; 2403 err = mOMXNode->getParameter( 2404 OMX_IndexParamVideoIntraRefresh, &refreshParams, sizeof(refreshParams)); 2405 if (err != OK || refreshParams.nCirMBs == 0) { 2406 *intraRefreshPeriod = 0; 2407 return OK; 2408 } 2409 2410 // Calculate period based on width and height 2411 uint32_t width, height; 2412 OMX_PARAM_PORTDEFINITIONTYPE def; 2413 InitOMXParams(&def); 2414 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 2415 def.nPortIndex = kPortIndexOutput; 2416 err = mOMXNode->getParameter( 2417 OMX_IndexParamPortDefinition, &def, sizeof(def)); 2418 if (err != OK) { 2419 *intraRefreshPeriod = 0; 2420 return err; 2421 } 2422 width = video_def->nFrameWidth; 2423 height = video_def->nFrameHeight; 2424 // Use H.264/AVC MacroBlock size 16x16 2425 *intraRefreshPeriod = divUp((divUp(width, 16u) * divUp(height, 16u)), refreshParams.nCirMBs); 2426 2427 return OK; 2428} 2429 2430status_t ACodec::setIntraRefreshPeriod(uint32_t intraRefreshPeriod, bool inConfigure) { 2431 OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params; 2432 InitOMXParams(¶ms); 2433 params.nPortIndex = kPortIndexOutput; 2434 params.nRefreshPeriod = intraRefreshPeriod; 2435 status_t err = mOMXNode->setConfig( 2436 (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, ¶ms, sizeof(params)); 2437 if (err == OK) { 2438 return OK; 2439 } 2440 2441 // Only in configure state, a component could invoke setParameter. 2442 if (!inConfigure) { 2443 return INVALID_OPERATION; 2444 } else { 2445 ALOGI("[%s] try falling back to Cyclic", mComponentName.c_str()); 2446 } 2447 2448 OMX_VIDEO_PARAM_INTRAREFRESHTYPE refreshParams; 2449 InitOMXParams(&refreshParams); 2450 refreshParams.nPortIndex = kPortIndexOutput; 2451 refreshParams.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic; 2452 2453 if (intraRefreshPeriod == 0) { 2454 // 0 means disable intra refresh. 2455 refreshParams.nCirMBs = 0; 2456 } else { 2457 // Calculate macroblocks that need to be intra coded base on width and height 2458 uint32_t width, height; 2459 OMX_PARAM_PORTDEFINITIONTYPE def; 2460 InitOMXParams(&def); 2461 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 2462 def.nPortIndex = kPortIndexOutput; 2463 err = mOMXNode->getParameter( 2464 OMX_IndexParamPortDefinition, &def, sizeof(def)); 2465 if (err != OK) { 2466 return err; 2467 } 2468 width = video_def->nFrameWidth; 2469 height = video_def->nFrameHeight; 2470 // Use H.264/AVC MacroBlock size 16x16 2471 refreshParams.nCirMBs = divUp((divUp(width, 16u) * divUp(height, 16u)), intraRefreshPeriod); 2472 } 2473 2474 err = mOMXNode->setParameter( 2475 OMX_IndexParamVideoIntraRefresh, 2476 &refreshParams, sizeof(refreshParams)); 2477 if (err != OK) { 2478 return err; 2479 } 2480 2481 return OK; 2482} 2483 2484status_t ACodec::configureTemporalLayers( 2485 const sp<AMessage> &msg, bool inConfigure, sp<AMessage> &outputFormat) { 2486 if (!mIsVideo || !mIsEncoder) { 2487 return INVALID_OPERATION; 2488 } 2489 2490 AString tsSchema; 2491 if (!msg->findString("ts-schema", &tsSchema)) { 2492 return OK; 2493 } 2494 2495 unsigned int numLayers = 0; 2496 unsigned int numBLayers = 0; 2497 int tags; 2498 char dummy; 2499 OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE pattern = 2500 OMX_VIDEO_AndroidTemporalLayeringPatternNone; 2501 if (sscanf(tsSchema.c_str(), "webrtc.vp8.%u-layer%c", &numLayers, &dummy) == 1 2502 && numLayers > 0) { 2503 pattern = OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC; 2504 } else if ((tags = sscanf(tsSchema.c_str(), "android.generic.%u%c%u%c", 2505 &numLayers, &dummy, &numBLayers, &dummy)) 2506 && (tags == 1 || (tags == 3 && dummy == '+')) 2507 && numLayers > 0 && numLayers < UINT32_MAX - numBLayers) { 2508 numLayers += numBLayers; 2509 pattern = OMX_VIDEO_AndroidTemporalLayeringPatternAndroid; 2510 } else { 2511 ALOGI("Ignoring unsupported ts-schema [%s]", tsSchema.c_str()); 2512 return BAD_VALUE; 2513 } 2514 2515 OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE layerParams; 2516 InitOMXParams(&layerParams); 2517 layerParams.nPortIndex = kPortIndexOutput; 2518 2519 status_t err = mOMXNode->getParameter( 2520 (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering, 2521 &layerParams, sizeof(layerParams)); 2522 2523 if (err != OK) { 2524 return err; 2525 } else if (!(layerParams.eSupportedPatterns & pattern)) { 2526 return BAD_VALUE; 2527 } 2528 2529 numLayers = min(numLayers, layerParams.nLayerCountMax); 2530 numBLayers = min(numBLayers, layerParams.nBLayerCountMax); 2531 2532 if (!inConfigure) { 2533 OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE layerConfig; 2534 InitOMXParams(&layerConfig); 2535 layerConfig.nPortIndex = kPortIndexOutput; 2536 layerConfig.ePattern = pattern; 2537 layerConfig.nPLayerCountActual = numLayers - numBLayers; 2538 layerConfig.nBLayerCountActual = numBLayers; 2539 layerConfig.bBitrateRatiosSpecified = OMX_FALSE; 2540 2541 err = mOMXNode->setConfig( 2542 (OMX_INDEXTYPE)OMX_IndexConfigAndroidVideoTemporalLayering, 2543 &layerConfig, sizeof(layerConfig)); 2544 } else { 2545 layerParams.ePattern = pattern; 2546 layerParams.nPLayerCountActual = numLayers - numBLayers; 2547 layerParams.nBLayerCountActual = numBLayers; 2548 layerParams.bBitrateRatiosSpecified = OMX_FALSE; 2549 2550 err = mOMXNode->setParameter( 2551 (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering, 2552 &layerParams, sizeof(layerParams)); 2553 } 2554 2555 AString configSchema; 2556 if (pattern == OMX_VIDEO_AndroidTemporalLayeringPatternAndroid) { 2557 configSchema = AStringPrintf("android.generic.%u+%u", numLayers - numBLayers, numBLayers); 2558 } else if (pattern == OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC) { 2559 configSchema = AStringPrintf("webrtc.vp8.%u", numLayers); 2560 } 2561 2562 if (err != OK) { 2563 ALOGW("Failed to set temporal layers to %s (requested %s)", 2564 configSchema.c_str(), tsSchema.c_str()); 2565 return err; 2566 } 2567 2568 err = mOMXNode->getParameter( 2569 (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering, 2570 &layerParams, sizeof(layerParams)); 2571 2572 if (err == OK) { 2573 ALOGD("Temporal layers requested:%s configured:%s got:%s(%u: P=%u, B=%u)", 2574 tsSchema.c_str(), configSchema.c_str(), 2575 asString(layerParams.ePattern), layerParams.ePattern, 2576 layerParams.nPLayerCountActual, layerParams.nBLayerCountActual); 2577 2578 if (outputFormat.get() == mOutputFormat.get()) { 2579 mOutputFormat = mOutputFormat->dup(); // trigger an output format change event 2580 } 2581 // assume we got what we configured 2582 outputFormat->setString("ts-schema", configSchema); 2583 } 2584 return err; 2585} 2586 2587status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) { 2588 OMX_PARAM_PORTDEFINITIONTYPE def; 2589 InitOMXParams(&def); 2590 def.nPortIndex = portIndex; 2591 2592 status_t err = mOMXNode->getParameter( 2593 OMX_IndexParamPortDefinition, &def, sizeof(def)); 2594 2595 if (err != OK) { 2596 return err; 2597 } 2598 2599 if (def.nBufferSize >= size) { 2600 return OK; 2601 } 2602 2603 def.nBufferSize = size; 2604 2605 err = mOMXNode->setParameter( 2606 OMX_IndexParamPortDefinition, &def, sizeof(def)); 2607 2608 if (err != OK) { 2609 return err; 2610 } 2611 2612 err = mOMXNode->getParameter( 2613 OMX_IndexParamPortDefinition, &def, sizeof(def)); 2614 2615 if (err != OK) { 2616 return err; 2617 } 2618 2619 if (def.nBufferSize < size) { 2620 ALOGE("failed to set min buffer size to %zu (is still %u)", size, def.nBufferSize); 2621 return FAILED_TRANSACTION; 2622 } 2623 2624 return OK; 2625} 2626 2627status_t ACodec::selectAudioPortFormat( 2628 OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) { 2629 OMX_AUDIO_PARAM_PORTFORMATTYPE format; 2630 InitOMXParams(&format); 2631 2632 format.nPortIndex = portIndex; 2633 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { 2634 format.nIndex = index; 2635 status_t err = mOMXNode->getParameter( 2636 OMX_IndexParamAudioPortFormat, &format, sizeof(format)); 2637 2638 if (err != OK) { 2639 return err; 2640 } 2641 2642 if (format.eEncoding == desiredFormat) { 2643 break; 2644 } 2645 2646 if (index == kMaxIndicesToCheck) { 2647 ALOGW("[%s] stopping checking formats after %u: %s(%x)", 2648 mComponentName.c_str(), index, 2649 asString(format.eEncoding), format.eEncoding); 2650 return ERROR_UNSUPPORTED; 2651 } 2652 } 2653 2654 return mOMXNode->setParameter( 2655 OMX_IndexParamAudioPortFormat, &format, sizeof(format)); 2656} 2657 2658status_t ACodec::setupAACCodec( 2659 bool encoder, int32_t numChannels, int32_t sampleRate, 2660 int32_t bitRate, int32_t aacProfile, bool isADTS, int32_t sbrMode, 2661 int32_t maxOutputChannelCount, const drcParams_t& drc, 2662 int32_t pcmLimiterEnable) { 2663 if (encoder && isADTS) { 2664 return -EINVAL; 2665 } 2666 2667 status_t err = setupRawAudioFormat( 2668 encoder ? kPortIndexInput : kPortIndexOutput, 2669 sampleRate, 2670 numChannels); 2671 2672 if (err != OK) { 2673 return err; 2674 } 2675 2676 if (encoder) { 2677 err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC); 2678 2679 if (err != OK) { 2680 return err; 2681 } 2682 2683 OMX_PARAM_PORTDEFINITIONTYPE def; 2684 InitOMXParams(&def); 2685 def.nPortIndex = kPortIndexOutput; 2686 2687 err = mOMXNode->getParameter( 2688 OMX_IndexParamPortDefinition, &def, sizeof(def)); 2689 2690 if (err != OK) { 2691 return err; 2692 } 2693 2694 def.format.audio.bFlagErrorConcealment = OMX_TRUE; 2695 def.format.audio.eEncoding = OMX_AUDIO_CodingAAC; 2696 2697 err = mOMXNode->setParameter( 2698 OMX_IndexParamPortDefinition, &def, sizeof(def)); 2699 2700 if (err != OK) { 2701 return err; 2702 } 2703 2704 OMX_AUDIO_PARAM_AACPROFILETYPE profile; 2705 InitOMXParams(&profile); 2706 profile.nPortIndex = kPortIndexOutput; 2707 2708 err = mOMXNode->getParameter( 2709 OMX_IndexParamAudioAac, &profile, sizeof(profile)); 2710 2711 if (err != OK) { 2712 return err; 2713 } 2714 2715 profile.nChannels = numChannels; 2716 2717 profile.eChannelMode = 2718 (numChannels == 1) 2719 ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo; 2720 2721 profile.nSampleRate = sampleRate; 2722 profile.nBitRate = bitRate; 2723 profile.nAudioBandWidth = 0; 2724 profile.nFrameLength = 0; 2725 profile.nAACtools = OMX_AUDIO_AACToolAll; 2726 profile.nAACERtools = OMX_AUDIO_AACERNone; 2727 profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile; 2728 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF; 2729 switch (sbrMode) { 2730 case 0: 2731 // disable sbr 2732 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR; 2733 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR; 2734 break; 2735 case 1: 2736 // enable single-rate sbr 2737 profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR; 2738 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR; 2739 break; 2740 case 2: 2741 // enable dual-rate sbr 2742 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR; 2743 profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR; 2744 break; 2745 case -1: 2746 // enable both modes -> the codec will decide which mode should be used 2747 profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR; 2748 profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR; 2749 break; 2750 default: 2751 // unsupported sbr mode 2752 return BAD_VALUE; 2753 } 2754 2755 2756 err = mOMXNode->setParameter( 2757 OMX_IndexParamAudioAac, &profile, sizeof(profile)); 2758 2759 if (err != OK) { 2760 return err; 2761 } 2762 2763 return err; 2764 } 2765 2766 OMX_AUDIO_PARAM_AACPROFILETYPE profile; 2767 InitOMXParams(&profile); 2768 profile.nPortIndex = kPortIndexInput; 2769 2770 err = mOMXNode->getParameter( 2771 OMX_IndexParamAudioAac, &profile, sizeof(profile)); 2772 2773 if (err != OK) { 2774 return err; 2775 } 2776 2777 profile.nChannels = numChannels; 2778 profile.nSampleRate = sampleRate; 2779 2780 profile.eAACStreamFormat = 2781 isADTS 2782 ? OMX_AUDIO_AACStreamFormatMP4ADTS 2783 : OMX_AUDIO_AACStreamFormatMP4FF; 2784 2785 OMX_AUDIO_PARAM_ANDROID_AACDRCPRESENTATIONTYPE presentation; 2786 InitOMXParams(&presentation); 2787 presentation.nMaxOutputChannels = maxOutputChannelCount; 2788 presentation.nDrcCut = drc.drcCut; 2789 presentation.nDrcBoost = drc.drcBoost; 2790 presentation.nHeavyCompression = drc.heavyCompression; 2791 presentation.nTargetReferenceLevel = drc.targetRefLevel; 2792 presentation.nEncodedTargetLevel = drc.encodedTargetLevel; 2793 presentation.nPCMLimiterEnable = pcmLimiterEnable; 2794 presentation.nDrcEffectType = drc.effectType; 2795 2796 status_t res = mOMXNode->setParameter( 2797 OMX_IndexParamAudioAac, &profile, sizeof(profile)); 2798 if (res == OK) { 2799 // optional parameters, will not cause configuration failure 2800 if (mOMXNode->setParameter( 2801 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacDrcPresentation, 2802 &presentation, sizeof(presentation)) == ERROR_UNSUPPORTED) { 2803 // prior to 9.0 we used a different config structure and index 2804 OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE presentation8; 2805 InitOMXParams(&presentation8); 2806 presentation8.nMaxOutputChannels = presentation.nMaxOutputChannels; 2807 presentation8.nDrcCut = presentation.nDrcCut; 2808 presentation8.nDrcBoost = presentation.nDrcBoost; 2809 presentation8.nHeavyCompression = presentation.nHeavyCompression; 2810 presentation8.nTargetReferenceLevel = presentation.nTargetReferenceLevel; 2811 presentation8.nEncodedTargetLevel = presentation.nEncodedTargetLevel; 2812 presentation8.nPCMLimiterEnable = presentation.nPCMLimiterEnable; 2813 (void)mOMXNode->setParameter( 2814 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacPresentation, 2815 &presentation8, sizeof(presentation8)); 2816 } 2817 } else { 2818 ALOGW("did not set AudioAndroidAacPresentation due to error %d when setting AudioAac", res); 2819 } 2820 mSampleRate = sampleRate; 2821 return res; 2822} 2823 2824status_t ACodec::setupAC3Codec( 2825 bool encoder, int32_t numChannels, int32_t sampleRate) { 2826 status_t err = setupRawAudioFormat( 2827 encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels); 2828 2829 if (err != OK) { 2830 return err; 2831 } 2832 2833 if (encoder) { 2834 ALOGW("AC3 encoding is not supported."); 2835 return INVALID_OPERATION; 2836 } 2837 2838 OMX_AUDIO_PARAM_ANDROID_AC3TYPE def; 2839 InitOMXParams(&def); 2840 def.nPortIndex = kPortIndexInput; 2841 2842 err = mOMXNode->getParameter( 2843 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, &def, sizeof(def)); 2844 2845 if (err != OK) { 2846 return err; 2847 } 2848 2849 def.nChannels = numChannels; 2850 def.nSampleRate = sampleRate; 2851 2852 return mOMXNode->setParameter( 2853 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, &def, sizeof(def)); 2854} 2855 2856status_t ACodec::setupEAC3Codec( 2857 bool encoder, int32_t numChannels, int32_t sampleRate) { 2858 status_t err = setupRawAudioFormat( 2859 encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels); 2860 2861 if (err != OK) { 2862 return err; 2863 } 2864 2865 if (encoder) { 2866 ALOGW("EAC3 encoding is not supported."); 2867 return INVALID_OPERATION; 2868 } 2869 2870 OMX_AUDIO_PARAM_ANDROID_EAC3TYPE def; 2871 InitOMXParams(&def); 2872 def.nPortIndex = kPortIndexInput; 2873 2874 err = mOMXNode->getParameter( 2875 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, &def, sizeof(def)); 2876 2877 if (err != OK) { 2878 return err; 2879 } 2880 2881 def.nChannels = numChannels; 2882 def.nSampleRate = sampleRate; 2883 2884 return mOMXNode->setParameter( 2885 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, &def, sizeof(def)); 2886} 2887 2888static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate( 2889 bool isAMRWB, int32_t bps) { 2890 if (isAMRWB) { 2891 if (bps <= 6600) { 2892 return OMX_AUDIO_AMRBandModeWB0; 2893 } else if (bps <= 8850) { 2894 return OMX_AUDIO_AMRBandModeWB1; 2895 } else if (bps <= 12650) { 2896 return OMX_AUDIO_AMRBandModeWB2; 2897 } else if (bps <= 14250) { 2898 return OMX_AUDIO_AMRBandModeWB3; 2899 } else if (bps <= 15850) { 2900 return OMX_AUDIO_AMRBandModeWB4; 2901 } else if (bps <= 18250) { 2902 return OMX_AUDIO_AMRBandModeWB5; 2903 } else if (bps <= 19850) { 2904 return OMX_AUDIO_AMRBandModeWB6; 2905 } else if (bps <= 23050) { 2906 return OMX_AUDIO_AMRBandModeWB7; 2907 } 2908 2909 // 23850 bps 2910 return OMX_AUDIO_AMRBandModeWB8; 2911 } else { // AMRNB 2912 if (bps <= 4750) { 2913 return OMX_AUDIO_AMRBandModeNB0; 2914 } else if (bps <= 5150) { 2915 return OMX_AUDIO_AMRBandModeNB1; 2916 } else if (bps <= 5900) { 2917 return OMX_AUDIO_AMRBandModeNB2; 2918 } else if (bps <= 6700) { 2919 return OMX_AUDIO_AMRBandModeNB3; 2920 } else if (bps <= 7400) { 2921 return OMX_AUDIO_AMRBandModeNB4; 2922 } else if (bps <= 7950) { 2923 return OMX_AUDIO_AMRBandModeNB5; 2924 } else if (bps <= 10200) { 2925 return OMX_AUDIO_AMRBandModeNB6; 2926 } 2927 2928 // 12200 bps 2929 return OMX_AUDIO_AMRBandModeNB7; 2930 } 2931} 2932 2933status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) { 2934 OMX_AUDIO_PARAM_AMRTYPE def; 2935 InitOMXParams(&def); 2936 def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput; 2937 2938 status_t err = mOMXNode->getParameter( 2939 OMX_IndexParamAudioAmr, &def, sizeof(def)); 2940 2941 if (err != OK) { 2942 return err; 2943 } 2944 2945 def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF; 2946 def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate); 2947 2948 err = mOMXNode->setParameter( 2949 OMX_IndexParamAudioAmr, &def, sizeof(def)); 2950 2951 if (err != OK) { 2952 return err; 2953 } 2954 2955 return setupRawAudioFormat( 2956 encoder ? kPortIndexInput : kPortIndexOutput, 2957 isWAMR ? 16000 : 8000 /* sampleRate */, 2958 1 /* numChannels */); 2959} 2960 2961status_t ACodec::setupG711Codec(bool encoder, int32_t sampleRate, int32_t numChannels) { 2962 if (encoder) { 2963 return INVALID_OPERATION; 2964 } 2965 2966 return setupRawAudioFormat( 2967 kPortIndexInput, sampleRate, numChannels); 2968} 2969 2970status_t ACodec::setupFlacCodec( 2971 bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel) { 2972 2973 if (encoder) { 2974 OMX_AUDIO_PARAM_FLACTYPE def; 2975 InitOMXParams(&def); 2976 def.nPortIndex = kPortIndexOutput; 2977 2978 // configure compression level 2979 status_t err = mOMXNode->getParameter(OMX_IndexParamAudioFlac, &def, sizeof(def)); 2980 if (err != OK) { 2981 ALOGE("setupFlacCodec(): Error %d getting OMX_IndexParamAudioFlac parameter", err); 2982 return err; 2983 } 2984 def.nCompressionLevel = compressionLevel; 2985 err = mOMXNode->setParameter(OMX_IndexParamAudioFlac, &def, sizeof(def)); 2986 if (err != OK) { 2987 ALOGE("setupFlacCodec(): Error %d setting OMX_IndexParamAudioFlac parameter", err); 2988 return err; 2989 } 2990 } 2991 2992 return setupRawAudioFormat( 2993 encoder ? kPortIndexInput : kPortIndexOutput, 2994 sampleRate, 2995 numChannels); 2996} 2997 2998status_t ACodec::setupRawAudioFormat( 2999 OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels, AudioEncoding encoding) { 3000 OMX_PARAM_PORTDEFINITIONTYPE def; 3001 InitOMXParams(&def); 3002 def.nPortIndex = portIndex; 3003 3004 status_t err = mOMXNode->getParameter( 3005 OMX_IndexParamPortDefinition, &def, sizeof(def)); 3006 3007 if (err != OK) { 3008 return err; 3009 } 3010 3011 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; 3012 3013 err = mOMXNode->setParameter( 3014 OMX_IndexParamPortDefinition, &def, sizeof(def)); 3015 3016 if (err != OK) { 3017 return err; 3018 } 3019 3020 OMX_AUDIO_PARAM_PCMMODETYPE pcmParams; 3021 InitOMXParams(&pcmParams); 3022 pcmParams.nPortIndex = portIndex; 3023 3024 err = mOMXNode->getParameter( 3025 OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); 3026 3027 if (err != OK) { 3028 return err; 3029 } 3030 3031 pcmParams.nChannels = numChannels; 3032 switch (encoding) { 3033 case kAudioEncodingPcm8bit: 3034 pcmParams.eNumData = OMX_NumericalDataUnsigned; 3035 pcmParams.nBitPerSample = 8; 3036 break; 3037 case kAudioEncodingPcmFloat: 3038 pcmParams.eNumData = OMX_NumericalDataFloat; 3039 pcmParams.nBitPerSample = 32; 3040 break; 3041 case kAudioEncodingPcm16bit: 3042 pcmParams.eNumData = OMX_NumericalDataSigned; 3043 pcmParams.nBitPerSample = 16; 3044 break; 3045 default: 3046 return BAD_VALUE; 3047 } 3048 pcmParams.bInterleaved = OMX_TRUE; 3049 pcmParams.nSamplingRate = sampleRate; 3050 pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear; 3051 3052 if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) { 3053 return OMX_ErrorNone; 3054 } 3055 3056 err = mOMXNode->setParameter( 3057 OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); 3058 // if we could not set up raw format to non-16-bit, try with 16-bit 3059 // NOTE: we will also verify this via readback, in case codec ignores these fields 3060 if (err != OK && encoding != kAudioEncodingPcm16bit) { 3061 pcmParams.eNumData = OMX_NumericalDataSigned; 3062 pcmParams.nBitPerSample = 16; 3063 err = mOMXNode->setParameter( 3064 OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); 3065 } 3066 return err; 3067} 3068 3069status_t ACodec::configureTunneledVideoPlayback( 3070 int32_t audioHwSync, const sp<ANativeWindow> &nativeWindow) { 3071 native_handle_t* sidebandHandle; 3072 3073 status_t err = mOMXNode->configureVideoTunnelMode( 3074 kPortIndexOutput, OMX_TRUE, audioHwSync, &sidebandHandle); 3075 if (err != OK) { 3076 ALOGE("configureVideoTunnelMode failed! (err %d).", err); 3077 return err; 3078 } 3079 3080 err = native_window_set_sideband_stream(nativeWindow.get(), sidebandHandle); 3081 if (err != OK) { 3082 ALOGE("native_window_set_sideband_stream(%p) failed! (err %d).", 3083 sidebandHandle, err); 3084 return err; 3085 } 3086 3087 return OK; 3088} 3089 3090status_t ACodec::setVideoPortFormatType( 3091 OMX_U32 portIndex, 3092 OMX_VIDEO_CODINGTYPE compressionFormat, 3093 OMX_COLOR_FORMATTYPE colorFormat, 3094 bool usingNativeBuffers) { 3095 OMX_VIDEO_PARAM_PORTFORMATTYPE format; 3096 InitOMXParams(&format); 3097 format.nPortIndex = portIndex; 3098 format.nIndex = 0; 3099 bool found = false; 3100 3101 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { 3102 format.nIndex = index; 3103 status_t err = mOMXNode->getParameter( 3104 OMX_IndexParamVideoPortFormat, 3105 &format, sizeof(format)); 3106 3107 if (err != OK) { 3108 return err; 3109 } 3110 3111 // substitute back flexible color format to codec supported format 3112 OMX_U32 flexibleEquivalent; 3113 if (compressionFormat == OMX_VIDEO_CodingUnused 3114 && IsFlexibleColorFormat( 3115 mOMXNode, format.eColorFormat, usingNativeBuffers, &flexibleEquivalent) 3116 && colorFormat == flexibleEquivalent) { 3117 ALOGI("[%s] using color format %#x in place of %#x", 3118 mComponentName.c_str(), format.eColorFormat, colorFormat); 3119 colorFormat = format.eColorFormat; 3120 } 3121 3122 // The following assertion is violated by TI's video decoder. 3123 // CHECK_EQ(format.nIndex, index); 3124 3125 if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) { 3126 if (portIndex == kPortIndexInput 3127 && colorFormat == format.eColorFormat) { 3128 // eCompressionFormat does not seem right. 3129 found = true; 3130 break; 3131 } 3132 if (portIndex == kPortIndexOutput 3133 && compressionFormat == format.eCompressionFormat) { 3134 // eColorFormat does not seem right. 3135 found = true; 3136 break; 3137 } 3138 } 3139 3140 if (format.eCompressionFormat == compressionFormat 3141 && format.eColorFormat == colorFormat) { 3142 found = true; 3143 break; 3144 } 3145 3146 if (index == kMaxIndicesToCheck) { 3147 ALOGW("[%s] stopping checking formats after %u: %s(%x)/%s(%x)", 3148 mComponentName.c_str(), index, 3149 asString(format.eCompressionFormat), format.eCompressionFormat, 3150 asString(format.eColorFormat), format.eColorFormat); 3151 } 3152 } 3153 3154 if (!found) { 3155 return UNKNOWN_ERROR; 3156 } 3157 3158 status_t err = mOMXNode->setParameter( 3159 OMX_IndexParamVideoPortFormat, &format, sizeof(format)); 3160 3161 return err; 3162} 3163 3164// Set optimal output format. OMX component lists output formats in the order 3165// of preference, but this got more complicated since the introduction of flexible 3166// YUV formats. We support a legacy behavior for applications that do not use 3167// surface output, do not specify an output format, but expect a "usable" standard 3168// OMX format. SW readable and standard formats must be flex-YUV. 3169// 3170// Suggested preference order: 3171// - optimal format for texture rendering (mediaplayer behavior) 3172// - optimal SW readable & texture renderable format (flex-YUV support) 3173// - optimal SW readable non-renderable format (flex-YUV bytebuffer support) 3174// - legacy "usable" standard formats 3175// 3176// For legacy support, we prefer a standard format, but will settle for a SW readable 3177// flex-YUV format. 3178status_t ACodec::setSupportedOutputFormat(bool getLegacyFlexibleFormat) { 3179 OMX_VIDEO_PARAM_PORTFORMATTYPE format, legacyFormat; 3180 InitOMXParams(&format); 3181 format.nPortIndex = kPortIndexOutput; 3182 3183 InitOMXParams(&legacyFormat); 3184 // this field will change when we find a suitable legacy format 3185 legacyFormat.eColorFormat = OMX_COLOR_FormatUnused; 3186 3187 for (OMX_U32 index = 0; ; ++index) { 3188 format.nIndex = index; 3189 status_t err = mOMXNode->getParameter( 3190 OMX_IndexParamVideoPortFormat, &format, sizeof(format)); 3191 if (err != OK) { 3192 // no more formats, pick legacy format if found 3193 if (legacyFormat.eColorFormat != OMX_COLOR_FormatUnused) { 3194 memcpy(&format, &legacyFormat, sizeof(format)); 3195 break; 3196 } 3197 return err; 3198 } 3199 if (format.eCompressionFormat != OMX_VIDEO_CodingUnused) { 3200 return OMX_ErrorBadParameter; 3201 } 3202 if (!getLegacyFlexibleFormat) { 3203 break; 3204 } 3205 // standard formats that were exposed to users before 3206 if (format.eColorFormat == OMX_COLOR_FormatYUV420Planar 3207 || format.eColorFormat == OMX_COLOR_FormatYUV420PackedPlanar 3208 || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar 3209 || format.eColorFormat == OMX_COLOR_FormatYUV420PackedSemiPlanar 3210 || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar) { 3211 break; 3212 } 3213 // find best legacy non-standard format 3214 OMX_U32 flexibleEquivalent; 3215 if (legacyFormat.eColorFormat == OMX_COLOR_FormatUnused 3216 && IsFlexibleColorFormat( 3217 mOMXNode, format.eColorFormat, false /* usingNativeBuffers */, 3218 &flexibleEquivalent) 3219 && flexibleEquivalent == OMX_COLOR_FormatYUV420Flexible) { 3220 memcpy(&legacyFormat, &format, sizeof(format)); 3221 } 3222 } 3223 return mOMXNode->setParameter( 3224 OMX_IndexParamVideoPortFormat, &format, sizeof(format)); 3225} 3226 3227static const struct VideoCodingMapEntry { 3228 const char *mMime; 3229 OMX_VIDEO_CODINGTYPE mVideoCodingType; 3230} kVideoCodingMapEntry[] = { 3231 { MEDIA_MIMETYPE_VIDEO_AVC, OMX_VIDEO_CodingAVC }, 3232 { MEDIA_MIMETYPE_VIDEO_HEVC, OMX_VIDEO_CodingHEVC }, 3233 { MEDIA_MIMETYPE_VIDEO_MPEG4, OMX_VIDEO_CodingMPEG4 }, 3234 { MEDIA_MIMETYPE_VIDEO_H263, OMX_VIDEO_CodingH263 }, 3235 { MEDIA_MIMETYPE_VIDEO_MPEG2, OMX_VIDEO_CodingMPEG2 }, 3236 { MEDIA_MIMETYPE_VIDEO_VP8, OMX_VIDEO_CodingVP8 }, 3237 { MEDIA_MIMETYPE_VIDEO_VP9, OMX_VIDEO_CodingVP9 }, 3238 { MEDIA_MIMETYPE_VIDEO_DOLBY_VISION, OMX_VIDEO_CodingDolbyVision }, 3239 { MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC, OMX_VIDEO_CodingImageHEIC }, 3240}; 3241 3242static status_t GetVideoCodingTypeFromMime( 3243 const char *mime, OMX_VIDEO_CODINGTYPE *codingType) { 3244 for (size_t i = 0; 3245 i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]); 3246 ++i) { 3247 if (!strcasecmp(mime, kVideoCodingMapEntry[i].mMime)) { 3248 *codingType = kVideoCodingMapEntry[i].mVideoCodingType; 3249 return OK; 3250 } 3251 } 3252 3253 *codingType = OMX_VIDEO_CodingUnused; 3254 3255 return ERROR_UNSUPPORTED; 3256} 3257 3258static status_t GetMimeTypeForVideoCoding( 3259 OMX_VIDEO_CODINGTYPE codingType, AString *mime) { 3260 for (size_t i = 0; 3261 i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]); 3262 ++i) { 3263 if (codingType == kVideoCodingMapEntry[i].mVideoCodingType) { 3264 *mime = kVideoCodingMapEntry[i].mMime; 3265 return OK; 3266 } 3267 } 3268 3269 mime->clear(); 3270 3271 return ERROR_UNSUPPORTED; 3272} 3273 3274status_t ACodec::setPortBufferNum(OMX_U32 portIndex, int bufferNum) { 3275 OMX_PARAM_PORTDEFINITIONTYPE def; 3276 InitOMXParams(&def); 3277 def.nPortIndex = portIndex; 3278 status_t err; 3279 ALOGD("Setting [%s] %s port buffer number: %d", mComponentName.c_str(), 3280 portIndex == kPortIndexInput ? "input" : "output", bufferNum); 3281 err = mOMXNode->getParameter( 3282 OMX_IndexParamPortDefinition, &def, sizeof(def)); 3283 if (err != OK) { 3284 return err; 3285 } 3286 def.nBufferCountActual = bufferNum; 3287 err = mOMXNode->setParameter( 3288 OMX_IndexParamPortDefinition, &def, sizeof(def)); 3289 if (err != OK) { 3290 // Component could reject this request. 3291 ALOGW("Fail to set [%s] %s port buffer number: %d", mComponentName.c_str(), 3292 portIndex == kPortIndexInput ? "input" : "output", bufferNum); 3293 } 3294 return OK; 3295} 3296 3297status_t ACodec::setupVideoDecoder( 3298 const char *mime, const sp<AMessage> &msg, bool haveNativeWindow, 3299 bool usingSwRenderer, sp<AMessage> &outputFormat) { 3300 int32_t width, height; 3301 if (!msg->findInt32("width", &width) 3302 || !msg->findInt32("height", &height)) { 3303 return INVALID_OPERATION; 3304 } 3305 3306 OMX_VIDEO_CODINGTYPE compressionFormat; 3307 status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat); 3308 3309 if (err != OK) { 3310 return err; 3311 } 3312 3313 if (compressionFormat == OMX_VIDEO_CodingHEVC) { 3314 int32_t profile; 3315 if (msg->findInt32("profile", &profile)) { 3316 // verify if Main10 profile is supported at all, and fail 3317 // immediately if it's not supported. 3318 if (profile == OMX_VIDEO_HEVCProfileMain10 || 3319 profile == OMX_VIDEO_HEVCProfileMain10HDR10) { 3320 err = verifySupportForProfileAndLevel( 3321 kPortIndexInput, profile, 0); 3322 if (err != OK) { 3323 return err; 3324 } 3325 } 3326 } 3327 } 3328 3329 if (compressionFormat == OMX_VIDEO_CodingVP9) { 3330 OMX_VIDEO_PARAM_PROFILELEVELTYPE params; 3331 InitOMXParams(¶ms); 3332 params.nPortIndex = kPortIndexInput; 3333 // Check if VP9 decoder advertises supported profiles. 3334 params.nProfileIndex = 0; 3335 status_t err = mOMXNode->getParameter( 3336 OMX_IndexParamVideoProfileLevelQuerySupported, 3337 ¶ms, sizeof(params)); 3338 mIsLegacyVP9Decoder = err != OK; 3339 } 3340 3341 err = setVideoPortFormatType( 3342 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused); 3343 3344 if (err != OK) { 3345 return err; 3346 } 3347 3348 int32_t tmp; 3349 if (msg->findInt32("color-format", &tmp)) { 3350 OMX_COLOR_FORMATTYPE colorFormat = 3351 static_cast<OMX_COLOR_FORMATTYPE>(tmp); 3352 err = setVideoPortFormatType( 3353 kPortIndexOutput, OMX_VIDEO_CodingUnused, colorFormat, haveNativeWindow); 3354 if (err != OK) { 3355 ALOGW("[%s] does not support color format %d", 3356 mComponentName.c_str(), colorFormat); 3357 err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */); 3358 } 3359 } else { 3360 err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */); 3361 } 3362 3363 if (err != OK) { 3364 return err; 3365 } 3366 3367 // Set the component input buffer number to be |tmp|. If succeed, 3368 // component will set input port buffer number to be |tmp|. If fail, 3369 // component will keep the same buffer number as before. 3370 if (msg->findInt32("android._num-input-buffers", &tmp)) { 3371 err = setPortBufferNum(kPortIndexInput, tmp); 3372 if (err != OK) 3373 return err; 3374 } 3375 3376 // Set the component output buffer number to be |tmp|. If succeed, 3377 // component will set output port buffer number to be |tmp|. If fail, 3378 // component will keep the same buffer number as before. 3379 if (msg->findInt32("android._num-output-buffers", &tmp)) { 3380 err = setPortBufferNum(kPortIndexOutput, tmp); 3381 if (err != OK) 3382 return err; 3383 } 3384 3385 int32_t frameRateInt; 3386 float frameRateFloat; 3387 if (!msg->findFloat("frame-rate", &frameRateFloat)) { 3388 if (!msg->findInt32("frame-rate", &frameRateInt)) { 3389 frameRateInt = -1; 3390 } 3391 frameRateFloat = (float)frameRateInt; 3392 } 3393 3394 err = setVideoFormatOnPort( 3395 kPortIndexInput, width, height, compressionFormat, frameRateFloat); 3396 3397 if (err != OK) { 3398 return err; 3399 } 3400 3401 err = setVideoFormatOnPort( 3402 kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused); 3403 3404 if (err != OK) { 3405 return err; 3406 } 3407 3408 err = setColorAspectsForVideoDecoder( 3409 width, height, haveNativeWindow | usingSwRenderer, msg, outputFormat); 3410 if (err == ERROR_UNSUPPORTED) { // support is optional 3411 err = OK; 3412 } 3413 3414 if (err != OK) { 3415 return err; 3416 } 3417 3418 err = setHDRStaticInfoForVideoCodec(kPortIndexOutput, msg, outputFormat); 3419 if (err == ERROR_UNSUPPORTED) { // support is optional 3420 err = OK; 3421 } 3422 return err; 3423} 3424 3425status_t ACodec::initDescribeColorAspectsIndex() { 3426 status_t err = mOMXNode->getExtensionIndex( 3427 "OMX.google.android.index.describeColorAspects", &mDescribeColorAspectsIndex); 3428 if (err != OK) { 3429 mDescribeColorAspectsIndex = (OMX_INDEXTYPE)0; 3430 } 3431 return err; 3432} 3433 3434status_t ACodec::setCodecColorAspects(DescribeColorAspectsParams ¶ms, bool verify) { 3435 status_t err = ERROR_UNSUPPORTED; 3436 if (mDescribeColorAspectsIndex) { 3437 err = mOMXNode->setConfig(mDescribeColorAspectsIndex, ¶ms, sizeof(params)); 3438 } 3439 ALOGV("[%s] setting color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)", 3440 mComponentName.c_str(), 3441 params.sAspects.mRange, asString(params.sAspects.mRange), 3442 params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries), 3443 params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs), 3444 params.sAspects.mTransfer, asString(params.sAspects.mTransfer), 3445 err, asString(err)); 3446 3447 if (verify && err == OK) { 3448 err = getCodecColorAspects(params); 3449 } 3450 3451 ALOGW_IF(err == ERROR_UNSUPPORTED && mDescribeColorAspectsIndex, 3452 "[%s] setting color aspects failed even though codec advertises support", 3453 mComponentName.c_str()); 3454 return err; 3455} 3456 3457status_t ACodec::setColorAspectsForVideoDecoder( 3458 int32_t width, int32_t height, bool usingNativeWindow, 3459 const sp<AMessage> &configFormat, sp<AMessage> &outputFormat) { 3460 DescribeColorAspectsParams params; 3461 InitOMXParams(¶ms); 3462 params.nPortIndex = kPortIndexOutput; 3463 3464 getColorAspectsFromFormat(configFormat, params.sAspects); 3465 if (usingNativeWindow) { 3466 setDefaultCodecColorAspectsIfNeeded(params.sAspects, width, height); 3467 // The default aspects will be set back to the output format during the 3468 // getFormat phase of configure(). Set non-Unspecified values back into the 3469 // format, in case component does not support this enumeration. 3470 setColorAspectsIntoFormat(params.sAspects, outputFormat); 3471 } 3472 3473 (void)initDescribeColorAspectsIndex(); 3474 3475 // communicate color aspects to codec 3476 return setCodecColorAspects(params); 3477} 3478 3479status_t ACodec::getCodecColorAspects(DescribeColorAspectsParams ¶ms) { 3480 status_t err = ERROR_UNSUPPORTED; 3481 if (mDescribeColorAspectsIndex) { 3482 err = mOMXNode->getConfig(mDescribeColorAspectsIndex, ¶ms, sizeof(params)); 3483 } 3484 ALOGV("[%s] got color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)", 3485 mComponentName.c_str(), 3486 params.sAspects.mRange, asString(params.sAspects.mRange), 3487 params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries), 3488 params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs), 3489 params.sAspects.mTransfer, asString(params.sAspects.mTransfer), 3490 err, asString(err)); 3491 if (params.bRequestingDataSpace) { 3492 ALOGV("for dataspace %#x", params.nDataSpace); 3493 } 3494 if (err == ERROR_UNSUPPORTED && mDescribeColorAspectsIndex 3495 && !params.bRequestingDataSpace && !params.bDataSpaceChanged) { 3496 ALOGW("[%s] getting color aspects failed even though codec advertises support", 3497 mComponentName.c_str()); 3498 } 3499 return err; 3500} 3501 3502status_t ACodec::getInputColorAspectsForVideoEncoder(sp<AMessage> &format) { 3503 DescribeColorAspectsParams params; 3504 InitOMXParams(¶ms); 3505 params.nPortIndex = kPortIndexInput; 3506 status_t err = getCodecColorAspects(params); 3507 if (err == OK) { 3508 // we only set encoder input aspects if codec supports them 3509 setColorAspectsIntoFormat(params.sAspects, format, true /* force */); 3510 } 3511 return err; 3512} 3513 3514status_t ACodec::getDataSpace( 3515 DescribeColorAspectsParams ¶ms, android_dataspace *dataSpace /* nonnull */, 3516 bool tryCodec) { 3517 status_t err = OK; 3518 if (tryCodec) { 3519 // request dataspace guidance from codec. 3520 params.bRequestingDataSpace = OMX_TRUE; 3521 err = getCodecColorAspects(params); 3522 params.bRequestingDataSpace = OMX_FALSE; 3523 if (err == OK && params.nDataSpace != HAL_DATASPACE_UNKNOWN) { 3524 *dataSpace = (android_dataspace)params.nDataSpace; 3525 return err; 3526 } else if (err == ERROR_UNSUPPORTED) { 3527 // ignore not-implemented error for dataspace requests 3528 err = OK; 3529 } 3530 } 3531 3532 // this returns legacy versions if available 3533 *dataSpace = getDataSpaceForColorAspects(params.sAspects, true /* mayexpand */); 3534 ALOGV("[%s] using color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) " 3535 "and dataspace %#x", 3536 mComponentName.c_str(), 3537 params.sAspects.mRange, asString(params.sAspects.mRange), 3538 params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries), 3539 params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs), 3540 params.sAspects.mTransfer, asString(params.sAspects.mTransfer), 3541 *dataSpace); 3542 return err; 3543} 3544 3545 3546status_t ACodec::getColorAspectsAndDataSpaceForVideoDecoder( 3547 int32_t width, int32_t height, const sp<AMessage> &configFormat, sp<AMessage> &outputFormat, 3548 android_dataspace *dataSpace) { 3549 DescribeColorAspectsParams params; 3550 InitOMXParams(¶ms); 3551 params.nPortIndex = kPortIndexOutput; 3552 3553 // reset default format and get resulting format 3554 getColorAspectsFromFormat(configFormat, params.sAspects); 3555 if (dataSpace != NULL) { 3556 setDefaultCodecColorAspectsIfNeeded(params.sAspects, width, height); 3557 } 3558 status_t err = setCodecColorAspects(params, true /* readBack */); 3559 3560 // we always set specified aspects for decoders 3561 setColorAspectsIntoFormat(params.sAspects, outputFormat); 3562 3563 if (dataSpace != NULL) { 3564 status_t res = getDataSpace(params, dataSpace, err == OK /* tryCodec */); 3565 if (err == OK) { 3566 err = res; 3567 } 3568 } 3569 3570 return err; 3571} 3572 3573// initial video encoder setup for bytebuffer mode 3574status_t ACodec::setColorAspectsForVideoEncoder( 3575 const sp<AMessage> &configFormat, sp<AMessage> &outputFormat, sp<AMessage> &inputFormat) { 3576 // copy config to output format as this is not exposed via getFormat 3577 copyColorConfig(configFormat, outputFormat); 3578 3579 DescribeColorAspectsParams params; 3580 InitOMXParams(¶ms); 3581 params.nPortIndex = kPortIndexInput; 3582 getColorAspectsFromFormat(configFormat, params.sAspects); 3583 3584 (void)initDescribeColorAspectsIndex(); 3585 3586 int32_t usingRecorder; 3587 if (configFormat->findInt32("android._using-recorder", &usingRecorder) && usingRecorder) { 3588 android_dataspace dataSpace = HAL_DATASPACE_BT709; 3589 int32_t width, height; 3590 if (configFormat->findInt32("width", &width) 3591 && configFormat->findInt32("height", &height)) { 3592 setDefaultCodecColorAspectsIfNeeded(params.sAspects, width, height); 3593 status_t err = getDataSpace( 3594 params, &dataSpace, mDescribeColorAspectsIndex /* tryCodec */); 3595 if (err != OK) { 3596 return err; 3597 } 3598 setColorAspectsIntoFormat(params.sAspects, outputFormat); 3599 } 3600 inputFormat->setInt32("android._dataspace", (int32_t)dataSpace); 3601 } 3602 3603 // communicate color aspects to codec, but do not allow change of the platform aspects 3604 ColorAspects origAspects = params.sAspects; 3605 for (int triesLeft = 2; --triesLeft >= 0; ) { 3606 status_t err = setCodecColorAspects(params, true /* readBack */); 3607 if (err != OK 3608 || !ColorUtils::checkIfAspectsChangedAndUnspecifyThem( 3609 params.sAspects, origAspects, true /* usePlatformAspects */)) { 3610 return err; 3611 } 3612 ALOGW_IF(triesLeft == 0, "[%s] Codec repeatedly changed requested ColorAspects.", 3613 mComponentName.c_str()); 3614 } 3615 return OK; 3616} 3617 3618status_t ACodec::setHDRStaticInfoForVideoCodec( 3619 OMX_U32 portIndex, const sp<AMessage> &configFormat, sp<AMessage> &outputFormat) { 3620 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 3621 3622 DescribeHDRStaticInfoParams params; 3623 InitOMXParams(¶ms); 3624 params.nPortIndex = portIndex; 3625 3626 HDRStaticInfo *info = ¶ms.sInfo; 3627 if (getHDRStaticInfoFromFormat(configFormat, info)) { 3628 setHDRStaticInfoIntoFormat(params.sInfo, outputFormat); 3629 } 3630 3631 (void)initDescribeHDRStaticInfoIndex(); 3632 3633 // communicate HDR static Info to codec 3634 return setHDRStaticInfo(params); 3635} 3636 3637// subsequent initial video encoder setup for surface mode 3638status_t ACodec::setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace( 3639 android_dataspace *dataSpace /* nonnull */) { 3640 DescribeColorAspectsParams params; 3641 InitOMXParams(¶ms); 3642 params.nPortIndex = kPortIndexInput; 3643 ColorAspects &aspects = params.sAspects; 3644 3645 // reset default format and store resulting format into both input and output formats 3646 getColorAspectsFromFormat(mConfigFormat, aspects); 3647 int32_t width, height; 3648 if (mInputFormat->findInt32("width", &width) && mInputFormat->findInt32("height", &height)) { 3649 setDefaultCodecColorAspectsIfNeeded(aspects, width, height); 3650 } 3651 setColorAspectsIntoFormat(aspects, mInputFormat); 3652 setColorAspectsIntoFormat(aspects, mOutputFormat); 3653 3654 // communicate color aspects to codec, but do not allow any change 3655 ColorAspects origAspects = aspects; 3656 status_t err = OK; 3657 for (int triesLeft = 2; mDescribeColorAspectsIndex && --triesLeft >= 0; ) { 3658 status_t err = setCodecColorAspects(params, true /* readBack */); 3659 if (err != OK || !ColorUtils::checkIfAspectsChangedAndUnspecifyThem(aspects, origAspects)) { 3660 break; 3661 } 3662 ALOGW_IF(triesLeft == 0, "[%s] Codec repeatedly changed requested ColorAspects.", 3663 mComponentName.c_str()); 3664 } 3665 3666 *dataSpace = HAL_DATASPACE_BT709; 3667 aspects = origAspects; // restore desired color aspects 3668 status_t res = getDataSpace( 3669 params, dataSpace, err == OK && mDescribeColorAspectsIndex /* tryCodec */); 3670 if (err == OK) { 3671 err = res; 3672 } 3673 mInputFormat->setInt32("android._dataspace", (int32_t)*dataSpace); 3674 mInputFormat->setBuffer( 3675 "android._color-aspects", ABuffer::CreateAsCopy(&aspects, sizeof(aspects))); 3676 3677 // update input format with codec supported color aspects (basically set unsupported 3678 // aspects to Unspecified) 3679 if (err == OK) { 3680 (void)getInputColorAspectsForVideoEncoder(mInputFormat); 3681 } 3682 3683 ALOGV("set default color aspects, updated input format to %s, output format to %s", 3684 mInputFormat->debugString(4).c_str(), mOutputFormat->debugString(4).c_str()); 3685 3686 return err; 3687} 3688 3689status_t ACodec::getHDRStaticInfoForVideoCodec(OMX_U32 portIndex, sp<AMessage> &format) { 3690 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 3691 DescribeHDRStaticInfoParams params; 3692 InitOMXParams(¶ms); 3693 params.nPortIndex = portIndex; 3694 3695 status_t err = getHDRStaticInfo(params); 3696 if (err == OK) { 3697 // we only set decodec output HDRStaticInfo if codec supports them 3698 setHDRStaticInfoIntoFormat(params.sInfo, format); 3699 } 3700 return err; 3701} 3702 3703status_t ACodec::initDescribeHDRStaticInfoIndex() { 3704 status_t err = mOMXNode->getExtensionIndex( 3705 "OMX.google.android.index.describeHDRStaticInfo", &mDescribeHDRStaticInfoIndex); 3706 if (err != OK) { 3707 mDescribeHDRStaticInfoIndex = (OMX_INDEXTYPE)0; 3708 } 3709 return err; 3710} 3711 3712status_t ACodec::setHDRStaticInfo(const DescribeHDRStaticInfoParams ¶ms) { 3713 status_t err = ERROR_UNSUPPORTED; 3714 if (mDescribeHDRStaticInfoIndex) { 3715 err = mOMXNode->setConfig(mDescribeHDRStaticInfoIndex, ¶ms, sizeof(params)); 3716 } 3717 3718 const HDRStaticInfo *info = ¶ms.sInfo; 3719 ALOGV("[%s] setting HDRStaticInfo (R: %u %u, G: %u %u, B: %u, %u, W: %u, %u, " 3720 "MaxDispL: %u, MinDispL: %u, MaxContentL: %u, MaxFrameAvgL: %u)", 3721 mComponentName.c_str(), 3722 info->sType1.mR.x, info->sType1.mR.y, info->sType1.mG.x, info->sType1.mG.y, 3723 info->sType1.mB.x, info->sType1.mB.y, info->sType1.mW.x, info->sType1.mW.y, 3724 info->sType1.mMaxDisplayLuminance, info->sType1.mMinDisplayLuminance, 3725 info->sType1.mMaxContentLightLevel, info->sType1.mMaxFrameAverageLightLevel); 3726 3727 ALOGW_IF(err == ERROR_UNSUPPORTED && mDescribeHDRStaticInfoIndex, 3728 "[%s] setting HDRStaticInfo failed even though codec advertises support", 3729 mComponentName.c_str()); 3730 return err; 3731} 3732 3733status_t ACodec::getHDRStaticInfo(DescribeHDRStaticInfoParams ¶ms) { 3734 status_t err = ERROR_UNSUPPORTED; 3735 if (mDescribeHDRStaticInfoIndex) { 3736 err = mOMXNode->getConfig(mDescribeHDRStaticInfoIndex, ¶ms, sizeof(params)); 3737 } 3738 3739 ALOGW_IF(err == ERROR_UNSUPPORTED && mDescribeHDRStaticInfoIndex, 3740 "[%s] getting HDRStaticInfo failed even though codec advertises support", 3741 mComponentName.c_str()); 3742 return err; 3743} 3744 3745status_t ACodec::setupVideoEncoder( 3746 const char *mime, const sp<AMessage> &msg, 3747 sp<AMessage> &outputFormat, sp<AMessage> &inputFormat) { 3748 int32_t tmp; 3749 if (!msg->findInt32("color-format", &tmp)) { 3750 return INVALID_OPERATION; 3751 } 3752 3753 OMX_COLOR_FORMATTYPE colorFormat = 3754 static_cast<OMX_COLOR_FORMATTYPE>(tmp); 3755 3756 status_t err = setVideoPortFormatType( 3757 kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat); 3758 3759 if (err != OK) { 3760 ALOGE("[%s] does not support color format %d", 3761 mComponentName.c_str(), colorFormat); 3762 3763 return err; 3764 } 3765 3766 /* Input port configuration */ 3767 3768 OMX_PARAM_PORTDEFINITIONTYPE def; 3769 InitOMXParams(&def); 3770 3771 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 3772 3773 def.nPortIndex = kPortIndexInput; 3774 3775 err = mOMXNode->getParameter( 3776 OMX_IndexParamPortDefinition, &def, sizeof(def)); 3777 3778 if (err != OK) { 3779 return err; 3780 } 3781 3782 OMX_VIDEO_CONTROLRATETYPE bitrateMode; 3783 int32_t width, height, bitrate = 0, quality; 3784 if (!msg->findInt32("width", &width) 3785 || !msg->findInt32("height", &height) 3786 || !findVideoBitrateControlInfo( 3787 msg, &bitrateMode, &bitrate, &quality)) { 3788 return INVALID_OPERATION; 3789 } 3790 3791 video_def->nFrameWidth = width; 3792 video_def->nFrameHeight = height; 3793 3794 int32_t stride; 3795 if (!msg->findInt32("stride", &stride)) { 3796 stride = width; 3797 } 3798 3799 video_def->nStride = stride; 3800 3801 int32_t sliceHeight; 3802 if (!msg->findInt32("slice-height", &sliceHeight)) { 3803 sliceHeight = height; 3804 } 3805 3806 video_def->nSliceHeight = sliceHeight; 3807 3808 def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2; 3809 3810 float framerate; 3811 if (!msg->findFloat("frame-rate", &framerate)) { 3812 int32_t tmp; 3813 if (!msg->findInt32("frame-rate", &tmp)) { 3814 return INVALID_OPERATION; 3815 } 3816 mFps = (double)tmp; 3817 } else { 3818 mFps = (double)framerate; 3819 } 3820 // propagate framerate to the output so that the muxer has it 3821 outputFormat->setInt32("frame-rate", (int32_t)mFps); 3822 3823 video_def->xFramerate = (OMX_U32)(mFps * 65536); 3824 video_def->eCompressionFormat = OMX_VIDEO_CodingUnused; 3825 // this is redundant as it was already set up in setVideoPortFormatType 3826 // FIXME for now skip this only for flexible YUV formats 3827 if (colorFormat != OMX_COLOR_FormatYUV420Flexible) { 3828 video_def->eColorFormat = colorFormat; 3829 } 3830 3831 err = mOMXNode->setParameter( 3832 OMX_IndexParamPortDefinition, &def, sizeof(def)); 3833 3834 if (err != OK) { 3835 ALOGE("[%s] failed to set input port definition parameters.", 3836 mComponentName.c_str()); 3837 3838 return err; 3839 } 3840 3841 /* Output port configuration */ 3842 3843 OMX_VIDEO_CODINGTYPE compressionFormat; 3844 err = GetVideoCodingTypeFromMime(mime, &compressionFormat); 3845 3846 if (err != OK) { 3847 return err; 3848 } 3849 3850 err = setVideoPortFormatType( 3851 kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused); 3852 3853 if (err != OK) { 3854 ALOGE("[%s] does not support compression format %d", 3855 mComponentName.c_str(), compressionFormat); 3856 3857 return err; 3858 } 3859 3860 def.nPortIndex = kPortIndexOutput; 3861 3862 err = mOMXNode->getParameter( 3863 OMX_IndexParamPortDefinition, &def, sizeof(def)); 3864 3865 if (err != OK) { 3866 return err; 3867 } 3868 3869 video_def->nFrameWidth = width; 3870 video_def->nFrameHeight = height; 3871 video_def->xFramerate = 0; 3872 video_def->nBitrate = bitrate; 3873 video_def->eCompressionFormat = compressionFormat; 3874 video_def->eColorFormat = OMX_COLOR_FormatUnused; 3875 3876 err = mOMXNode->setParameter( 3877 OMX_IndexParamPortDefinition, &def, sizeof(def)); 3878 3879 if (err != OK) { 3880 ALOGE("[%s] failed to set output port definition parameters.", 3881 mComponentName.c_str()); 3882 3883 return err; 3884 } 3885 3886 int32_t intraRefreshPeriod = 0; 3887 if (msg->findInt32("intra-refresh-period", &intraRefreshPeriod) 3888 && intraRefreshPeriod >= 0) { 3889 err = setIntraRefreshPeriod((uint32_t)intraRefreshPeriod, true); 3890 if (err != OK) { 3891 ALOGI("[%s] failed setIntraRefreshPeriod. Failure is fine since this key is optional", 3892 mComponentName.c_str()); 3893 err = OK; 3894 } 3895 } 3896 3897 configureEncoderLatency(msg); 3898 3899 switch (compressionFormat) { 3900 case OMX_VIDEO_CodingMPEG4: 3901 err = setupMPEG4EncoderParameters(msg); 3902 break; 3903 3904 case OMX_VIDEO_CodingH263: 3905 err = setupH263EncoderParameters(msg); 3906 break; 3907 3908 case OMX_VIDEO_CodingAVC: 3909 err = setupAVCEncoderParameters(msg); 3910 break; 3911 3912 case OMX_VIDEO_CodingHEVC: 3913 case OMX_VIDEO_CodingImageHEIC: 3914 err = setupHEVCEncoderParameters(msg, outputFormat); 3915 break; 3916 3917 case OMX_VIDEO_CodingVP8: 3918 case OMX_VIDEO_CodingVP9: 3919 err = setupVPXEncoderParameters(msg, outputFormat); 3920 break; 3921 3922 default: 3923 break; 3924 } 3925 3926 if (err != OK) { 3927 return err; 3928 } 3929 3930 // Set up color aspects on input, but propagate them to the output format, as they will 3931 // not be read back from encoder. 3932 err = setColorAspectsForVideoEncoder(msg, outputFormat, inputFormat); 3933 if (err == ERROR_UNSUPPORTED) { 3934 ALOGI("[%s] cannot encode color aspects. Ignoring.", mComponentName.c_str()); 3935 err = OK; 3936 } 3937 3938 if (err != OK) { 3939 return err; 3940 } 3941 3942 err = setHDRStaticInfoForVideoCodec(kPortIndexInput, msg, outputFormat); 3943 if (err == ERROR_UNSUPPORTED) { // support is optional 3944 ALOGI("[%s] cannot encode HDR static metadata. Ignoring.", mComponentName.c_str()); 3945 err = OK; 3946 } 3947 3948 if (err != OK) { 3949 return err; 3950 } 3951 3952 switch (compressionFormat) { 3953 case OMX_VIDEO_CodingAVC: 3954 case OMX_VIDEO_CodingHEVC: 3955 err = configureTemporalLayers(msg, true /* inConfigure */, outputFormat); 3956 if (err != OK) { 3957 err = OK; // ignore failure 3958 } 3959 break; 3960 3961 case OMX_VIDEO_CodingVP8: 3962 case OMX_VIDEO_CodingVP9: 3963 // TODO: do we need to support android.generic layering? webrtc layering is 3964 // already set up in setupVPXEncoderParameters. 3965 break; 3966 3967 default: 3968 break; 3969 } 3970 3971 if (err == OK) { 3972 ALOGI("setupVideoEncoder succeeded"); 3973 } 3974 3975 return err; 3976} 3977 3978status_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) { 3979 OMX_VIDEO_PARAM_INTRAREFRESHTYPE params; 3980 InitOMXParams(¶ms); 3981 params.nPortIndex = kPortIndexOutput; 3982 3983 params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode); 3984 3985 if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic || 3986 params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) { 3987 int32_t mbs; 3988 if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) { 3989 return INVALID_OPERATION; 3990 } 3991 params.nCirMBs = mbs; 3992 } 3993 3994 if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive || 3995 params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) { 3996 int32_t mbs; 3997 if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) { 3998 return INVALID_OPERATION; 3999 } 4000 params.nAirMBs = mbs; 4001 4002 int32_t ref; 4003 if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) { 4004 return INVALID_OPERATION; 4005 } 4006 params.nAirRef = ref; 4007 } 4008 4009 status_t err = mOMXNode->setParameter( 4010 OMX_IndexParamVideoIntraRefresh, ¶ms, sizeof(params)); 4011 return err; 4012} 4013 4014static OMX_U32 setPFramesSpacing( 4015 float iFramesInterval /* seconds */, int32_t frameRate, uint32_t BFramesSpacing = 0) { 4016 // BFramesSpacing is the number of B frames between I/P frames 4017 // PFramesSpacing (the value to be returned) is the number of P frames between I frames 4018 // 4019 // keyFrameInterval = ((PFramesSpacing + 1) * BFramesSpacing) + PFramesSpacing + 1 4020 // ^^^ ^^^ ^^^ 4021 // number of B frames number of P I frame 4022 // 4023 // = (PFramesSpacing + 1) * (BFramesSpacing + 1) 4024 // 4025 // E.g. 4026 // I P I : I-interval: 8, nPFrames 1, nBFrames 3 4027 // BBB BBB 4028 4029 if (iFramesInterval < 0) { // just 1 key frame 4030 return 0xFFFFFFFE; // don't use maxint as key-frame-interval calculation will add 1 4031 } else if (iFramesInterval == 0) { // just key frames 4032 return 0; 4033 } 4034 4035 // round down as key-frame-interval is an upper limit 4036 uint32_t keyFrameInterval = uint32_t(frameRate * iFramesInterval); 4037 OMX_U32 ret = keyFrameInterval / (BFramesSpacing + 1); 4038 return ret > 0 ? ret - 1 : 0; 4039} 4040 4041status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) { 4042 int32_t bitrate; 4043 float iFrameInterval; 4044 if (!msg->findInt32("bitrate", &bitrate) 4045 || !msg->findAsFloat("i-frame-interval", &iFrameInterval)) { 4046 return INVALID_OPERATION; 4047 } 4048 4049 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getVideoBitrateMode(msg); 4050 4051 float frameRate; 4052 if (!msg->findFloat("frame-rate", &frameRate)) { 4053 int32_t tmp; 4054 if (!msg->findInt32("frame-rate", &tmp)) { 4055 return INVALID_OPERATION; 4056 } 4057 frameRate = (float)tmp; 4058 } 4059 4060 OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type; 4061 InitOMXParams(&mpeg4type); 4062 mpeg4type.nPortIndex = kPortIndexOutput; 4063 4064 status_t err = mOMXNode->getParameter( 4065 OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); 4066 4067 if (err != OK) { 4068 return err; 4069 } 4070 4071 mpeg4type.nSliceHeaderSpacing = 0; 4072 mpeg4type.bSVH = OMX_FALSE; 4073 mpeg4type.bGov = OMX_FALSE; 4074 4075 mpeg4type.nAllowedPictureTypes = 4076 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 4077 4078 mpeg4type.nBFrames = 0; 4079 mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, mpeg4type.nBFrames); 4080 if (mpeg4type.nPFrames == 0) { 4081 mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 4082 } 4083 mpeg4type.nIDCVLCThreshold = 0; 4084 mpeg4type.bACPred = OMX_TRUE; 4085 mpeg4type.nMaxPacketSize = 256; 4086 mpeg4type.nTimeIncRes = 1000; 4087 mpeg4type.nHeaderExtension = 0; 4088 mpeg4type.bReversibleVLC = OMX_FALSE; 4089 4090 int32_t profile; 4091 if (msg->findInt32("profile", &profile)) { 4092 int32_t level; 4093 if (!msg->findInt32("level", &level)) { 4094 return INVALID_OPERATION; 4095 } 4096 4097 err = verifySupportForProfileAndLevel(kPortIndexOutput, profile, level); 4098 4099 if (err != OK) { 4100 return err; 4101 } 4102 4103 mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile); 4104 mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level); 4105 } 4106 4107 err = mOMXNode->setParameter( 4108 OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); 4109 4110 if (err != OK) { 4111 return err; 4112 } 4113 4114 err = configureBitrate(bitrateMode, bitrate); 4115 4116 if (err != OK) { 4117 return err; 4118 } 4119 4120 return setupErrorCorrectionParameters(); 4121} 4122 4123status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) { 4124 int32_t bitrate; 4125 float iFrameInterval; 4126 if (!msg->findInt32("bitrate", &bitrate) 4127 || !msg->findAsFloat("i-frame-interval", &iFrameInterval)) { 4128 return INVALID_OPERATION; 4129 } 4130 4131 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getVideoBitrateMode(msg); 4132 4133 float frameRate; 4134 if (!msg->findFloat("frame-rate", &frameRate)) { 4135 int32_t tmp; 4136 if (!msg->findInt32("frame-rate", &tmp)) { 4137 return INVALID_OPERATION; 4138 } 4139 frameRate = (float)tmp; 4140 } 4141 4142 OMX_VIDEO_PARAM_H263TYPE h263type; 4143 InitOMXParams(&h263type); 4144 h263type.nPortIndex = kPortIndexOutput; 4145 4146 status_t err = mOMXNode->getParameter( 4147 OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); 4148 4149 if (err != OK) { 4150 return err; 4151 } 4152 4153 h263type.nAllowedPictureTypes = 4154 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 4155 4156 h263type.nBFrames = 0; 4157 h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h263type.nBFrames); 4158 if (h263type.nPFrames == 0) { 4159 h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 4160 } 4161 4162 int32_t profile; 4163 if (msg->findInt32("profile", &profile)) { 4164 int32_t level; 4165 if (!msg->findInt32("level", &level)) { 4166 return INVALID_OPERATION; 4167 } 4168 4169 err = verifySupportForProfileAndLevel(kPortIndexOutput, profile, level); 4170 4171 if (err != OK) { 4172 return err; 4173 } 4174 4175 h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile); 4176 h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level); 4177 } 4178 4179 h263type.bPLUSPTYPEAllowed = OMX_FALSE; 4180 h263type.bForceRoundingTypeToZero = OMX_FALSE; 4181 h263type.nPictureHeaderRepetition = 0; 4182 h263type.nGOBHeaderInterval = 0; 4183 4184 err = mOMXNode->setParameter( 4185 OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); 4186 4187 if (err != OK) { 4188 return err; 4189 } 4190 4191 err = configureBitrate(bitrateMode, bitrate); 4192 4193 if (err != OK) { 4194 return err; 4195 } 4196 4197 return setupErrorCorrectionParameters(); 4198} 4199 4200// static 4201int /* OMX_VIDEO_AVCLEVELTYPE */ ACodec::getAVCLevelFor( 4202 int width, int height, int rate, int bitrate, 4203 OMX_VIDEO_AVCPROFILEEXTTYPE profile) { 4204 // convert bitrate to main/baseline profile kbps equivalent 4205 switch ((uint32_t)profile) { 4206 case OMX_VIDEO_AVCProfileHigh10: 4207 bitrate = divUp(bitrate, 3000); break; 4208 case OMX_VIDEO_AVCProfileConstrainedHigh: 4209 case OMX_VIDEO_AVCProfileHigh: 4210 bitrate = divUp(bitrate, 1250); break; 4211 default: 4212 bitrate = divUp(bitrate, 1000); break; 4213 } 4214 4215 // convert size and rate to MBs 4216 width = divUp(width, 16); 4217 height = divUp(height, 16); 4218 int mbs = width * height; 4219 rate *= mbs; 4220 int maxDimension = max(width, height); 4221 4222 static const int limits[][5] = { 4223 /* MBps MB dim bitrate level */ 4224 { 1485, 99, 28, 64, OMX_VIDEO_AVCLevel1 }, 4225 { 1485, 99, 28, 128, OMX_VIDEO_AVCLevel1b }, 4226 { 3000, 396, 56, 192, OMX_VIDEO_AVCLevel11 }, 4227 { 6000, 396, 56, 384, OMX_VIDEO_AVCLevel12 }, 4228 { 11880, 396, 56, 768, OMX_VIDEO_AVCLevel13 }, 4229 { 11880, 396, 56, 2000, OMX_VIDEO_AVCLevel2 }, 4230 { 19800, 792, 79, 4000, OMX_VIDEO_AVCLevel21 }, 4231 { 20250, 1620, 113, 4000, OMX_VIDEO_AVCLevel22 }, 4232 { 40500, 1620, 113, 10000, OMX_VIDEO_AVCLevel3 }, 4233 { 108000, 3600, 169, 14000, OMX_VIDEO_AVCLevel31 }, 4234 { 216000, 5120, 202, 20000, OMX_VIDEO_AVCLevel32 }, 4235 { 245760, 8192, 256, 20000, OMX_VIDEO_AVCLevel4 }, 4236 { 245760, 8192, 256, 50000, OMX_VIDEO_AVCLevel41 }, 4237 { 522240, 8704, 263, 50000, OMX_VIDEO_AVCLevel42 }, 4238 { 589824, 22080, 420, 135000, OMX_VIDEO_AVCLevel5 }, 4239 { 983040, 36864, 543, 240000, OMX_VIDEO_AVCLevel51 }, 4240 { 2073600, 36864, 543, 240000, OMX_VIDEO_AVCLevel52 }, 4241 }; 4242 4243 for (size_t i = 0; i < ARRAY_SIZE(limits); i++) { 4244 const int (&limit)[5] = limits[i]; 4245 if (rate <= limit[0] && mbs <= limit[1] && maxDimension <= limit[2] 4246 && bitrate <= limit[3]) { 4247 return limit[4]; 4248 } 4249 } 4250 return 0; 4251} 4252 4253status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) { 4254 int32_t bitrate; 4255 float iFrameInterval; 4256 if (!msg->findInt32("bitrate", &bitrate) 4257 || !msg->findAsFloat("i-frame-interval", &iFrameInterval)) { 4258 return INVALID_OPERATION; 4259 } 4260 4261 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getVideoBitrateMode(msg); 4262 4263 float frameRate; 4264 if (!msg->findFloat("frame-rate", &frameRate)) { 4265 int32_t tmp; 4266 if (!msg->findInt32("frame-rate", &tmp)) { 4267 return INVALID_OPERATION; 4268 } 4269 frameRate = (float)tmp; 4270 } 4271 4272 status_t err = OK; 4273 int32_t intraRefreshMode = 0; 4274 if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) { 4275 err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode); 4276 if (err != OK) { 4277 ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x", 4278 err, intraRefreshMode); 4279 return err; 4280 } 4281 } 4282 4283 OMX_VIDEO_PARAM_AVCTYPE h264type; 4284 InitOMXParams(&h264type); 4285 h264type.nPortIndex = kPortIndexOutput; 4286 4287 err = mOMXNode->getParameter( 4288 OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 4289 4290 if (err != OK) { 4291 return err; 4292 } 4293 4294 h264type.nAllowedPictureTypes = 4295 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 4296 4297 int32_t profile; 4298 if (msg->findInt32("profile", &profile)) { 4299 int32_t level; 4300 if (!msg->findInt32("level", &level)) { 4301 return INVALID_OPERATION; 4302 } 4303 4304 err = verifySupportForProfileAndLevel(kPortIndexOutput, profile, level); 4305 4306 if (err != OK) { 4307 return err; 4308 } 4309 4310 h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile); 4311 h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level); 4312 } else { 4313 h264type.eProfile = OMX_VIDEO_AVCProfileBaseline; 4314#if 0 /* DON'T YET DEFAULT TO HIGHEST PROFILE */ 4315 // Use largest supported profile for AVC recording if profile is not specified. 4316 for (OMX_VIDEO_AVCPROFILETYPE profile : { 4317 OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCProfileMain }) { 4318 if (verifySupportForProfileAndLevel(kPortIndexOutput, profile, 0) == OK) { 4319 h264type.eProfile = profile; 4320 break; 4321 } 4322 } 4323#endif 4324 } 4325 4326 ALOGI("setupAVCEncoderParameters with [profile: %s] [level: %s]", 4327 asString(h264type.eProfile), asString(h264type.eLevel)); 4328 4329 if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) { 4330 h264type.nSliceHeaderSpacing = 0; 4331 h264type.bUseHadamard = OMX_TRUE; 4332 h264type.nRefFrames = 1; 4333 h264type.nBFrames = 0; 4334 h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h264type.nBFrames); 4335 if (h264type.nPFrames == 0) { 4336 h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 4337 } 4338 h264type.nRefIdx10ActiveMinus1 = 0; 4339 h264type.nRefIdx11ActiveMinus1 = 0; 4340 h264type.bEntropyCodingCABAC = OMX_FALSE; 4341 h264type.bWeightedPPrediction = OMX_FALSE; 4342 h264type.bconstIpred = OMX_FALSE; 4343 h264type.bDirect8x8Inference = OMX_FALSE; 4344 h264type.bDirectSpatialTemporal = OMX_FALSE; 4345 h264type.nCabacInitIdc = 0; 4346 } else if (h264type.eProfile == OMX_VIDEO_AVCProfileMain || 4347 h264type.eProfile == OMX_VIDEO_AVCProfileHigh) { 4348 h264type.nSliceHeaderSpacing = 0; 4349 h264type.bUseHadamard = OMX_TRUE; 4350 h264type.nRefFrames = 2; 4351 h264type.nBFrames = mLatency == 0 ? 1 : std::min(1U, mLatency - 1); 4352 4353 // disable B-frames until MPEG4Writer can guarantee finalizing files with B-frames 4354 h264type.nRefFrames = 1; 4355 h264type.nBFrames = 0; 4356 4357 h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h264type.nBFrames); 4358 h264type.nAllowedPictureTypes = 4359 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 4360 h264type.nRefIdx10ActiveMinus1 = 0; 4361 h264type.nRefIdx11ActiveMinus1 = 0; 4362 h264type.bEntropyCodingCABAC = OMX_TRUE; 4363 h264type.bWeightedPPrediction = OMX_TRUE; 4364 h264type.bconstIpred = OMX_TRUE; 4365 h264type.bDirect8x8Inference = OMX_TRUE; 4366 h264type.bDirectSpatialTemporal = OMX_TRUE; 4367 h264type.nCabacInitIdc = 1; 4368 } 4369 4370 if (h264type.nBFrames != 0) { 4371 h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB; 4372 } 4373 4374 h264type.bEnableUEP = OMX_FALSE; 4375 h264type.bEnableFMO = OMX_FALSE; 4376 h264type.bEnableASO = OMX_FALSE; 4377 h264type.bEnableRS = OMX_FALSE; 4378 h264type.bFrameMBsOnly = OMX_TRUE; 4379 h264type.bMBAFF = OMX_FALSE; 4380 h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; 4381 4382 err = mOMXNode->setParameter( 4383 OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 4384 4385 if (err != OK) { 4386 return err; 4387 } 4388 4389 // TRICKY: if we are enabling temporal layering as well, some codecs may not support layering 4390 // when B-frames are enabled. Detect this now so we can disable B frames if temporal layering 4391 // is preferred. 4392 AString tsSchema; 4393 int32_t preferBFrames = (int32_t)false; 4394 if (msg->findString("ts-schema", &tsSchema) 4395 && (!msg->findInt32("android._prefer-b-frames", &preferBFrames) || !preferBFrames)) { 4396 OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE layering; 4397 InitOMXParams(&layering); 4398 layering.nPortIndex = kPortIndexOutput; 4399 if (mOMXNode->getParameter( 4400 (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering, 4401 &layering, sizeof(layering)) == OK 4402 && layering.eSupportedPatterns 4403 && layering.nBLayerCountMax == 0) { 4404 h264type.nBFrames = 0; 4405 h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h264type.nBFrames); 4406 h264type.nAllowedPictureTypes &= ~OMX_VIDEO_PictureTypeB; 4407 ALOGI("disabling B-frames"); 4408 err = mOMXNode->setParameter( 4409 OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 4410 4411 if (err != OK) { 4412 return err; 4413 } 4414 } 4415 } 4416 4417 return configureBitrate(bitrateMode, bitrate); 4418} 4419 4420status_t ACodec::configureImageGrid( 4421 const sp<AMessage> &msg, sp<AMessage> &outputFormat) { 4422 int32_t tileWidth, tileHeight, gridRows, gridCols; 4423 if (!msg->findInt32("tile-width", &tileWidth) || 4424 !msg->findInt32("tile-height", &tileHeight) || 4425 !msg->findInt32("grid-rows", &gridRows) || 4426 !msg->findInt32("grid-cols", &gridCols)) { 4427 return OK; 4428 } 4429 4430 OMX_VIDEO_PARAM_ANDROID_IMAGEGRIDTYPE gridType; 4431 InitOMXParams(&gridType); 4432 gridType.nPortIndex = kPortIndexOutput; 4433 gridType.bEnabled = OMX_TRUE; 4434 gridType.nTileWidth = tileWidth; 4435 gridType.nTileHeight = tileHeight; 4436 gridType.nGridRows = gridRows; 4437 gridType.nGridCols = gridCols; 4438 4439 status_t err = mOMXNode->setParameter( 4440 (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidImageGrid, 4441 &gridType, sizeof(gridType)); 4442 4443 // for video encoders, grid config is only a hint. 4444 if (!mIsImage) { 4445 return OK; 4446 } 4447 4448 // image encoders must support grid config. 4449 if (err != OK) { 4450 return err; 4451 } 4452 4453 // query to get the image encoder's real grid config as it might be 4454 // different from the requested, and transfer that to the output. 4455 err = mOMXNode->getParameter( 4456 (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidImageGrid, 4457 &gridType, sizeof(gridType)); 4458 4459 if (err == OK && gridType.bEnabled) { 4460 outputFormat->setInt32("tile-width", gridType.nTileWidth); 4461 outputFormat->setInt32("tile-height", gridType.nTileHeight); 4462 outputFormat->setInt32("grid-rows", gridType.nGridRows); 4463 outputFormat->setInt32("grid-cols", gridType.nGridCols); 4464 } 4465 4466 return err; 4467} 4468 4469status_t ACodec::setupHEVCEncoderParameters( 4470 const sp<AMessage> &msg, sp<AMessage> &outputFormat) { 4471 OMX_VIDEO_CONTROLRATETYPE bitrateMode; 4472 int32_t bitrate, quality; 4473 if (!findVideoBitrateControlInfo(msg, &bitrateMode, &bitrate, &quality)) { 4474 return INVALID_OPERATION; 4475 } 4476 4477 OMX_VIDEO_PARAM_HEVCTYPE hevcType; 4478 InitOMXParams(&hevcType); 4479 hevcType.nPortIndex = kPortIndexOutput; 4480 4481 status_t err = OK; 4482 err = mOMXNode->getParameter( 4483 (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType)); 4484 if (err != OK) { 4485 return err; 4486 } 4487 4488 int32_t profile; 4489 if (msg->findInt32("profile", &profile)) { 4490 int32_t level; 4491 if (!msg->findInt32("level", &level)) { 4492 return INVALID_OPERATION; 4493 } 4494 4495 err = verifySupportForProfileAndLevel(kPortIndexOutput, profile, level); 4496 if (err != OK) { 4497 return err; 4498 } 4499 4500 hevcType.eProfile = static_cast<OMX_VIDEO_HEVCPROFILETYPE>(profile); 4501 hevcType.eLevel = static_cast<OMX_VIDEO_HEVCLEVELTYPE>(level); 4502 } 4503 // TODO: finer control? 4504 if (mIsImage) { 4505 hevcType.nKeyFrameInterval = 1; 4506 } else { 4507 float iFrameInterval; 4508 if (!msg->findAsFloat("i-frame-interval", &iFrameInterval)) { 4509 return INVALID_OPERATION; 4510 } 4511 4512 float frameRate; 4513 if (!msg->findFloat("frame-rate", &frameRate)) { 4514 int32_t tmp; 4515 if (!msg->findInt32("frame-rate", &tmp)) { 4516 return INVALID_OPERATION; 4517 } 4518 frameRate = (float)tmp; 4519 } 4520 4521 hevcType.nKeyFrameInterval = 4522 setPFramesSpacing(iFrameInterval, frameRate) + 1; 4523 } 4524 4525 4526 err = mOMXNode->setParameter( 4527 (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType)); 4528 if (err != OK) { 4529 return err; 4530 } 4531 4532 err = configureImageGrid(msg, outputFormat); 4533 4534 if (err != OK) { 4535 return err; 4536 } 4537 4538 return configureBitrate(bitrateMode, bitrate, quality); 4539} 4540 4541status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg, sp<AMessage> &outputFormat) { 4542 int32_t bitrate; 4543 float iFrameInterval = 0; 4544 size_t tsLayers = 0; 4545 OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE pattern = 4546 OMX_VIDEO_VPXTemporalLayerPatternNone; 4547 static const uint32_t kVp8LayerRateAlloction 4548 [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] 4549 [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] = { 4550 {100, 100, 100}, // 1 layer 4551 { 60, 100, 100}, // 2 layers {60%, 40%} 4552 { 40, 60, 100}, // 3 layers {40%, 20%, 40%} 4553 }; 4554 if (!msg->findInt32("bitrate", &bitrate)) { 4555 return INVALID_OPERATION; 4556 } 4557 msg->findAsFloat("i-frame-interval", &iFrameInterval); 4558 4559 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getVideoBitrateMode(msg); 4560 4561 float frameRate; 4562 if (!msg->findFloat("frame-rate", &frameRate)) { 4563 int32_t tmp; 4564 if (!msg->findInt32("frame-rate", &tmp)) { 4565 return INVALID_OPERATION; 4566 } 4567 frameRate = (float)tmp; 4568 } 4569 4570 AString tsSchema; 4571 OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE tsType = 4572 OMX_VIDEO_AndroidTemporalLayeringPatternNone; 4573 4574 if (msg->findString("ts-schema", &tsSchema)) { 4575 unsigned int numLayers = 0; 4576 unsigned int numBLayers = 0; 4577 int tags; 4578 char dummy; 4579 if (sscanf(tsSchema.c_str(), "webrtc.vp8.%u-layer%c", &numLayers, &dummy) == 1 4580 && numLayers > 0) { 4581 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC; 4582 tsType = OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC; 4583 tsLayers = numLayers; 4584 } else if ((tags = sscanf(tsSchema.c_str(), "android.generic.%u%c%u%c", 4585 &numLayers, &dummy, &numBLayers, &dummy)) 4586 && (tags == 1 || (tags == 3 && dummy == '+')) 4587 && numLayers > 0 && numLayers < UINT32_MAX - numBLayers) { 4588 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC; 4589 // VPX does not have a concept of B-frames, so just count all layers 4590 tsType = OMX_VIDEO_AndroidTemporalLayeringPatternAndroid; 4591 tsLayers = numLayers + numBLayers; 4592 } else { 4593 ALOGW("Ignoring unsupported ts-schema [%s]", tsSchema.c_str()); 4594 } 4595 tsLayers = min(tsLayers, (size_t)OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS); 4596 } 4597 4598 OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type; 4599 InitOMXParams(&vp8type); 4600 vp8type.nPortIndex = kPortIndexOutput; 4601 status_t err = mOMXNode->getParameter( 4602 (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder, 4603 &vp8type, sizeof(vp8type)); 4604 4605 if (err == OK) { 4606 if (iFrameInterval > 0) { 4607 vp8type.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate) + 1; 4608 } 4609 vp8type.eTemporalPattern = pattern; 4610 vp8type.nTemporalLayerCount = tsLayers; 4611 if (tsLayers > 0) { 4612 for (size_t i = 0; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) { 4613 vp8type.nTemporalLayerBitrateRatio[i] = 4614 kVp8LayerRateAlloction[tsLayers - 1][i]; 4615 } 4616 } 4617 if (bitrateMode == OMX_Video_ControlRateConstant) { 4618 vp8type.nMinQuantizer = 2; 4619 vp8type.nMaxQuantizer = 63; 4620 } 4621 4622 err = mOMXNode->setParameter( 4623 (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder, 4624 &vp8type, sizeof(vp8type)); 4625 if (err != OK) { 4626 ALOGW("Extended VP8 parameters set failed: %d", err); 4627 } else if (tsType == OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC) { 4628 // advertise even single layer WebRTC layering, as it is defined 4629 outputFormat->setString("ts-schema", AStringPrintf("webrtc.vp8.%u-layer", tsLayers)); 4630 } else if (tsLayers > 0) { 4631 // tsType == OMX_VIDEO_AndroidTemporalLayeringPatternAndroid 4632 outputFormat->setString("ts-schema", AStringPrintf("android.generic.%u", tsLayers)); 4633 } 4634 } 4635 4636 return configureBitrate(bitrateMode, bitrate); 4637} 4638 4639status_t ACodec::verifySupportForProfileAndLevel( 4640 OMX_U32 portIndex, int32_t profile, int32_t level) { 4641 OMX_VIDEO_PARAM_PROFILELEVELTYPE params; 4642 InitOMXParams(¶ms); 4643 params.nPortIndex = portIndex; 4644 4645 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { 4646 params.nProfileIndex = index; 4647 status_t err = mOMXNode->getParameter( 4648 OMX_IndexParamVideoProfileLevelQuerySupported, 4649 ¶ms, sizeof(params)); 4650 4651 if (err != OK) { 4652 return err; 4653 } 4654 4655 int32_t supportedProfile = static_cast<int32_t>(params.eProfile); 4656 int32_t supportedLevel = static_cast<int32_t>(params.eLevel); 4657 4658 if (profile == supportedProfile && level <= supportedLevel) { 4659 return OK; 4660 } 4661 4662 if (index == kMaxIndicesToCheck) { 4663 ALOGW("[%s] stopping checking profiles after %u: %x/%x", 4664 mComponentName.c_str(), index, 4665 params.eProfile, params.eLevel); 4666 } 4667 } 4668 return ERROR_UNSUPPORTED; 4669} 4670 4671status_t ACodec::configureBitrate( 4672 OMX_VIDEO_CONTROLRATETYPE bitrateMode, int32_t bitrate, int32_t quality) { 4673 OMX_VIDEO_PARAM_BITRATETYPE bitrateType; 4674 InitOMXParams(&bitrateType); 4675 bitrateType.nPortIndex = kPortIndexOutput; 4676 4677 status_t err = mOMXNode->getParameter( 4678 OMX_IndexParamVideoBitrate, &bitrateType, sizeof(bitrateType)); 4679 4680 if (err != OK) { 4681 return err; 4682 } 4683 4684 bitrateType.eControlRate = bitrateMode; 4685 4686 // write it out explicitly even if it's a union 4687 if (bitrateMode == OMX_Video_ControlRateConstantQuality) { 4688 bitrateType.nQualityFactor = quality; 4689 } else { 4690 bitrateType.nTargetBitrate = bitrate; 4691 } 4692 4693 return mOMXNode->setParameter( 4694 OMX_IndexParamVideoBitrate, &bitrateType, sizeof(bitrateType)); 4695} 4696 4697void ACodec::configureEncoderLatency(const sp<AMessage> &msg) { 4698 if (!mIsEncoder || !mIsVideo) { 4699 return; 4700 } 4701 4702 int32_t latency = 0, bitrateMode; 4703 if (msg->findInt32("latency", &latency) && latency > 0) { 4704 status_t err = setLatency(latency); 4705 if (err != OK) { 4706 ALOGW("[%s] failed setLatency. Failure is fine since this key is optional", 4707 mComponentName.c_str()); 4708 err = OK; 4709 } else { 4710 mLatency = latency; 4711 } 4712 } else if ((!msg->findInt32("bitrate-mode", &bitrateMode) && 4713 bitrateMode == OMX_Video_ControlRateConstant)) { 4714 // default the latency to be 1 if latency key is not specified or unsupported and bitrateMode 4715 // is CBR. 4716 mLatency = 1; 4717 } 4718} 4719 4720status_t ACodec::setupErrorCorrectionParameters() { 4721 OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType; 4722 InitOMXParams(&errorCorrectionType); 4723 errorCorrectionType.nPortIndex = kPortIndexOutput; 4724 4725 status_t err = mOMXNode->getParameter( 4726 OMX_IndexParamVideoErrorCorrection, 4727 &errorCorrectionType, sizeof(errorCorrectionType)); 4728 4729 if (err != OK) { 4730 return OK; // Optional feature. Ignore this failure 4731 } 4732 4733 errorCorrectionType.bEnableHEC = OMX_FALSE; 4734 errorCorrectionType.bEnableResync = OMX_TRUE; 4735 errorCorrectionType.nResynchMarkerSpacing = 256; 4736 errorCorrectionType.bEnableDataPartitioning = OMX_FALSE; 4737 errorCorrectionType.bEnableRVLC = OMX_FALSE; 4738 4739 return mOMXNode->setParameter( 4740 OMX_IndexParamVideoErrorCorrection, 4741 &errorCorrectionType, sizeof(errorCorrectionType)); 4742} 4743 4744status_t ACodec::setVideoFormatOnPort( 4745 OMX_U32 portIndex, 4746 int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat, 4747 float frameRate) { 4748 OMX_PARAM_PORTDEFINITIONTYPE def; 4749 InitOMXParams(&def); 4750 def.nPortIndex = portIndex; 4751 4752 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 4753 4754 status_t err = mOMXNode->getParameter( 4755 OMX_IndexParamPortDefinition, &def, sizeof(def)); 4756 if (err != OK) { 4757 return err; 4758 } 4759 4760 if (portIndex == kPortIndexInput) { 4761 // XXX Need a (much) better heuristic to compute input buffer sizes. 4762 const size_t X = 64 * 1024; 4763 if (def.nBufferSize < X) { 4764 def.nBufferSize = X; 4765 } 4766 } 4767 4768 if (def.eDomain != OMX_PortDomainVideo) { 4769 ALOGE("expected video port, got %s(%d)", asString(def.eDomain), def.eDomain); 4770 return FAILED_TRANSACTION; 4771 } 4772 4773 video_def->nFrameWidth = width; 4774 video_def->nFrameHeight = height; 4775 4776 if (portIndex == kPortIndexInput) { 4777 video_def->eCompressionFormat = compressionFormat; 4778 video_def->eColorFormat = OMX_COLOR_FormatUnused; 4779 if (frameRate >= 0) { 4780 video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f); 4781 } 4782 } 4783 4784 err = mOMXNode->setParameter( 4785 OMX_IndexParamPortDefinition, &def, sizeof(def)); 4786 4787 return err; 4788} 4789 4790size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const { 4791 size_t n = 0; 4792 4793 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 4794 const BufferInfo &info = mBuffers[portIndex].itemAt(i); 4795 4796 if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) { 4797 ++n; 4798 } 4799 } 4800 4801 return n; 4802} 4803 4804size_t ACodec::countBuffersOwnedByNativeWindow() const { 4805 size_t n = 0; 4806 4807 for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) { 4808 const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i); 4809 4810 if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 4811 ++n; 4812 } 4813 } 4814 4815 return n; 4816} 4817 4818void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() { 4819 if (mNativeWindow == NULL) { 4820 return; 4821 } 4822 4823 while (countBuffersOwnedByNativeWindow() > mNumUndequeuedBuffers 4824 && dequeueBufferFromNativeWindow() != NULL) { 4825 // these buffers will be submitted as regular buffers; account for this 4826 if (storingMetadataInDecodedBuffers() && mMetadataBuffersToSubmit > 0) { 4827 --mMetadataBuffersToSubmit; 4828 } 4829 } 4830} 4831 4832bool ACodec::allYourBuffersAreBelongToUs( 4833 OMX_U32 portIndex) { 4834 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 4835 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 4836 4837 if (info->mStatus != BufferInfo::OWNED_BY_US 4838 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) { 4839 ALOGV("[%s] Buffer %u on port %u still has status %d", 4840 mComponentName.c_str(), 4841 info->mBufferID, portIndex, info->mStatus); 4842 return false; 4843 } 4844 } 4845 4846 return true; 4847} 4848 4849bool ACodec::allYourBuffersAreBelongToUs() { 4850 return allYourBuffersAreBelongToUs(kPortIndexInput) 4851 && allYourBuffersAreBelongToUs(kPortIndexOutput); 4852} 4853 4854void ACodec::deferMessage(const sp<AMessage> &msg) { 4855 mDeferredQueue.push_back(msg); 4856} 4857 4858void ACodec::processDeferredMessages() { 4859 List<sp<AMessage> > queue = mDeferredQueue; 4860 mDeferredQueue.clear(); 4861 4862 List<sp<AMessage> >::iterator it = queue.begin(); 4863 while (it != queue.end()) { 4864 onMessageReceived(*it++); 4865 } 4866} 4867 4868status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> ¬ify) { 4869 const char *niceIndex = portIndex == kPortIndexInput ? "input" : "output"; 4870 OMX_PARAM_PORTDEFINITIONTYPE def; 4871 InitOMXParams(&def); 4872 def.nPortIndex = portIndex; 4873 4874 status_t err = mOMXNode->getParameter(OMX_IndexParamPortDefinition, &def, sizeof(def)); 4875 if (err != OK) { 4876 return err; 4877 } 4878 4879 if (def.eDir != (portIndex == kPortIndexOutput ? OMX_DirOutput : OMX_DirInput)) { 4880 ALOGE("unexpected dir: %s(%d) on %s port", asString(def.eDir), def.eDir, niceIndex); 4881 return BAD_VALUE; 4882 } 4883 4884 switch (def.eDomain) { 4885 case OMX_PortDomainVideo: 4886 { 4887 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video; 4888 switch ((int)videoDef->eCompressionFormat) { 4889 case OMX_VIDEO_CodingUnused: 4890 { 4891 CHECK(mIsEncoder ^ (portIndex == kPortIndexOutput)); 4892 notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW); 4893 4894 notify->setInt32("stride", videoDef->nStride); 4895 notify->setInt32("slice-height", videoDef->nSliceHeight); 4896 notify->setInt32("color-format", videoDef->eColorFormat); 4897 4898 if (mNativeWindow == NULL) { 4899 DescribeColorFormat2Params describeParams; 4900 InitOMXParams(&describeParams); 4901 describeParams.eColorFormat = videoDef->eColorFormat; 4902 describeParams.nFrameWidth = videoDef->nFrameWidth; 4903 describeParams.nFrameHeight = videoDef->nFrameHeight; 4904 describeParams.nStride = videoDef->nStride; 4905 describeParams.nSliceHeight = videoDef->nSliceHeight; 4906 describeParams.bUsingNativeBuffers = OMX_FALSE; 4907 4908 if (DescribeColorFormat(mOMXNode, describeParams)) { 4909 notify->setBuffer( 4910 "image-data", 4911 ABuffer::CreateAsCopy( 4912 &describeParams.sMediaImage, 4913 sizeof(describeParams.sMediaImage))); 4914 4915 MediaImage2 &img = describeParams.sMediaImage; 4916 MediaImage2::PlaneInfo *plane = img.mPlane; 4917 ALOGV("[%s] MediaImage { F(%ux%u) @%u+%d+%d @%u+%d+%d @%u+%d+%d }", 4918 mComponentName.c_str(), img.mWidth, img.mHeight, 4919 plane[0].mOffset, plane[0].mColInc, plane[0].mRowInc, 4920 plane[1].mOffset, plane[1].mColInc, plane[1].mRowInc, 4921 plane[2].mOffset, plane[2].mColInc, plane[2].mRowInc); 4922 } 4923 } 4924 4925 int32_t width = (int32_t)videoDef->nFrameWidth; 4926 int32_t height = (int32_t)videoDef->nFrameHeight; 4927 4928 if (portIndex == kPortIndexOutput) { 4929 OMX_CONFIG_RECTTYPE rect; 4930 InitOMXParams(&rect); 4931 rect.nPortIndex = portIndex; 4932 4933 if (mOMXNode->getConfig( 4934 (portIndex == kPortIndexOutput ? 4935 OMX_IndexConfigCommonOutputCrop : 4936 OMX_IndexConfigCommonInputCrop), 4937 &rect, sizeof(rect)) != OK) { 4938 rect.nLeft = 0; 4939 rect.nTop = 0; 4940 rect.nWidth = videoDef->nFrameWidth; 4941 rect.nHeight = videoDef->nFrameHeight; 4942 } 4943 4944 if (rect.nLeft < 0 || rect.nTop < 0 || 4945 rect.nWidth == 0 || rect.nHeight == 0 || 4946 rect.nLeft + rect.nWidth > videoDef->nFrameWidth || 4947 rect.nTop + rect.nHeight > videoDef->nFrameHeight) { 4948 ALOGE("Wrong cropped rect (%d, %d, %u, %u) vs. frame (%u, %u)", 4949 rect.nLeft, rect.nTop, 4950 rect.nWidth, rect.nHeight, 4951 videoDef->nFrameWidth, videoDef->nFrameHeight); 4952 return BAD_VALUE; 4953 } 4954 4955 notify->setRect( 4956 "crop", 4957 rect.nLeft, 4958 rect.nTop, 4959 rect.nLeft + rect.nWidth - 1, 4960 rect.nTop + rect.nHeight - 1); 4961 4962 width = rect.nWidth; 4963 height = rect.nHeight; 4964 4965 android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN; 4966 (void)getColorAspectsAndDataSpaceForVideoDecoder( 4967 width, height, mConfigFormat, notify, 4968 mUsingNativeWindow ? &dataSpace : NULL); 4969 if (mUsingNativeWindow) { 4970 notify->setInt32("android._dataspace", dataSpace); 4971 } 4972 (void)getHDRStaticInfoForVideoCodec(kPortIndexOutput, notify); 4973 } else { 4974 (void)getInputColorAspectsForVideoEncoder(notify); 4975 if (mConfigFormat->contains("hdr-static-info")) { 4976 (void)getHDRStaticInfoForVideoCodec(kPortIndexInput, notify); 4977 } 4978 uint32_t latency = 0; 4979 if (mIsEncoder && !mIsImage && 4980 getLatency(&latency) == OK && latency > 0) { 4981 notify->setInt32("latency", latency); 4982 } 4983 } 4984 4985 break; 4986 } 4987 4988 case OMX_VIDEO_CodingVP8: 4989 case OMX_VIDEO_CodingVP9: 4990 { 4991 OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type; 4992 InitOMXParams(&vp8type); 4993 vp8type.nPortIndex = kPortIndexOutput; 4994 status_t err = mOMXNode->getParameter( 4995 (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder, 4996 &vp8type, 4997 sizeof(vp8type)); 4998 4999 if (err == OK) { 5000 if (vp8type.eTemporalPattern == OMX_VIDEO_VPXTemporalLayerPatternWebRTC 5001 && vp8type.nTemporalLayerCount > 0 5002 && vp8type.nTemporalLayerCount 5003 <= OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS) { 5004 // advertise as android.generic if we configured for android.generic 5005 AString origSchema; 5006 if (notify->findString("ts-schema", &origSchema) 5007 && origSchema.startsWith("android.generic")) { 5008 notify->setString("ts-schema", AStringPrintf( 5009 "android.generic.%u", vp8type.nTemporalLayerCount)); 5010 } else { 5011 notify->setString("ts-schema", AStringPrintf( 5012 "webrtc.vp8.%u-layer", vp8type.nTemporalLayerCount)); 5013 } 5014 } 5015 } 5016 // Fall through to set up mime. 5017 } 5018 5019 default: 5020 { 5021 if (mIsEncoder ^ (portIndex == kPortIndexOutput)) { 5022 // should be CodingUnused 5023 ALOGE("Raw port video compression format is %s(%d)", 5024 asString(videoDef->eCompressionFormat), 5025 videoDef->eCompressionFormat); 5026 return BAD_VALUE; 5027 } 5028 AString mime; 5029 if (GetMimeTypeForVideoCoding( 5030 videoDef->eCompressionFormat, &mime) != OK) { 5031 notify->setString("mime", "application/octet-stream"); 5032 } else { 5033 notify->setString("mime", mime.c_str()); 5034 } 5035 uint32_t intraRefreshPeriod = 0; 5036 if (mIsEncoder && !mIsImage && 5037 getIntraRefreshPeriod(&intraRefreshPeriod) == OK 5038 && intraRefreshPeriod > 0) { 5039 notify->setInt32("intra-refresh-period", intraRefreshPeriod); 5040 } 5041 break; 5042 } 5043 } 5044 notify->setInt32("width", videoDef->nFrameWidth); 5045 notify->setInt32("height", videoDef->nFrameHeight); 5046 ALOGV("[%s] %s format is %s", mComponentName.c_str(), 5047 portIndex == kPortIndexInput ? "input" : "output", 5048 notify->debugString().c_str()); 5049 5050 break; 5051 } 5052 5053 case OMX_PortDomainAudio: 5054 { 5055 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio; 5056 5057 switch ((int)audioDef->eEncoding) { 5058 case OMX_AUDIO_CodingPCM: 5059 { 5060 OMX_AUDIO_PARAM_PCMMODETYPE params; 5061 InitOMXParams(¶ms); 5062 params.nPortIndex = portIndex; 5063 5064 err = mOMXNode->getParameter( 5065 OMX_IndexParamAudioPcm, ¶ms, sizeof(params)); 5066 if (err != OK) { 5067 return err; 5068 } 5069 5070 if (params.nChannels <= 0 5071 || (params.nChannels != 1 && !params.bInterleaved) 5072 || params.ePCMMode != OMX_AUDIO_PCMModeLinear) { 5073 ALOGE("unsupported PCM port: %u channels%s, %u-bit", 5074 params.nChannels, 5075 params.bInterleaved ? " interleaved" : "", 5076 params.nBitPerSample); 5077 return FAILED_TRANSACTION; 5078 } 5079 5080 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW); 5081 notify->setInt32("channel-count", params.nChannels); 5082 notify->setInt32("sample-rate", params.nSamplingRate); 5083 5084 AudioEncoding encoding = kAudioEncodingPcm16bit; 5085 if (params.eNumData == OMX_NumericalDataUnsigned 5086 && params.nBitPerSample == 8u) { 5087 encoding = kAudioEncodingPcm8bit; 5088 } else if (params.eNumData == OMX_NumericalDataFloat 5089 && params.nBitPerSample == 32u) { 5090 encoding = kAudioEncodingPcmFloat; 5091 } else if (params.nBitPerSample != 16u 5092 || params.eNumData != OMX_NumericalDataSigned) { 5093 ALOGE("unsupported PCM port: %s(%d), %s(%d) mode ", 5094 asString(params.eNumData), params.eNumData, 5095 asString(params.ePCMMode), params.ePCMMode); 5096 return FAILED_TRANSACTION; 5097 } 5098 notify->setInt32("pcm-encoding", encoding); 5099 5100 if (mChannelMaskPresent) { 5101 notify->setInt32("channel-mask", mChannelMask); 5102 } 5103 break; 5104 } 5105 5106 case OMX_AUDIO_CodingAAC: 5107 { 5108 OMX_AUDIO_PARAM_AACPROFILETYPE params; 5109 InitOMXParams(¶ms); 5110 params.nPortIndex = portIndex; 5111 5112 err = mOMXNode->getParameter( 5113 OMX_IndexParamAudioAac, ¶ms, sizeof(params)); 5114 if (err != OK) { 5115 return err; 5116 } 5117 5118 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC); 5119 notify->setInt32("channel-count", params.nChannels); 5120 notify->setInt32("sample-rate", params.nSampleRate); 5121 break; 5122 } 5123 5124 case OMX_AUDIO_CodingAMR: 5125 { 5126 OMX_AUDIO_PARAM_AMRTYPE params; 5127 InitOMXParams(¶ms); 5128 params.nPortIndex = portIndex; 5129 5130 err = mOMXNode->getParameter( 5131 OMX_IndexParamAudioAmr, ¶ms, sizeof(params)); 5132 if (err != OK) { 5133 return err; 5134 } 5135 5136 notify->setInt32("channel-count", 1); 5137 if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) { 5138 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_WB); 5139 notify->setInt32("sample-rate", 16000); 5140 } else { 5141 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB); 5142 notify->setInt32("sample-rate", 8000); 5143 } 5144 break; 5145 } 5146 5147 case OMX_AUDIO_CodingFLAC: 5148 { 5149 OMX_AUDIO_PARAM_FLACTYPE params; 5150 InitOMXParams(¶ms); 5151 params.nPortIndex = portIndex; 5152 5153 err = mOMXNode->getParameter( 5154 OMX_IndexParamAudioFlac, ¶ms, sizeof(params)); 5155 if (err != OK) { 5156 return err; 5157 } 5158 5159 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC); 5160 notify->setInt32("channel-count", params.nChannels); 5161 notify->setInt32("sample-rate", params.nSampleRate); 5162 break; 5163 } 5164 5165 case OMX_AUDIO_CodingMP3: 5166 { 5167 OMX_AUDIO_PARAM_MP3TYPE params; 5168 InitOMXParams(¶ms); 5169 params.nPortIndex = portIndex; 5170 5171 err = mOMXNode->getParameter( 5172 OMX_IndexParamAudioMp3, ¶ms, sizeof(params)); 5173 if (err != OK) { 5174 return err; 5175 } 5176 5177 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MPEG); 5178 notify->setInt32("channel-count", params.nChannels); 5179 notify->setInt32("sample-rate", params.nSampleRate); 5180 break; 5181 } 5182 5183 case OMX_AUDIO_CodingVORBIS: 5184 { 5185 OMX_AUDIO_PARAM_VORBISTYPE params; 5186 InitOMXParams(¶ms); 5187 params.nPortIndex = portIndex; 5188 5189 err = mOMXNode->getParameter( 5190 OMX_IndexParamAudioVorbis, ¶ms, sizeof(params)); 5191 if (err != OK) { 5192 return err; 5193 } 5194 5195 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_VORBIS); 5196 notify->setInt32("channel-count", params.nChannels); 5197 notify->setInt32("sample-rate", params.nSampleRate); 5198 break; 5199 } 5200 5201 case OMX_AUDIO_CodingAndroidAC3: 5202 { 5203 OMX_AUDIO_PARAM_ANDROID_AC3TYPE params; 5204 InitOMXParams(¶ms); 5205 params.nPortIndex = portIndex; 5206 5207 err = mOMXNode->getParameter( 5208 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, 5209 ¶ms, sizeof(params)); 5210 if (err != OK) { 5211 return err; 5212 } 5213 5214 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3); 5215 notify->setInt32("channel-count", params.nChannels); 5216 notify->setInt32("sample-rate", params.nSampleRate); 5217 break; 5218 } 5219 5220 case OMX_AUDIO_CodingAndroidEAC3: 5221 { 5222 OMX_AUDIO_PARAM_ANDROID_EAC3TYPE params; 5223 InitOMXParams(¶ms); 5224 params.nPortIndex = portIndex; 5225 5226 err = mOMXNode->getParameter( 5227 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, 5228 ¶ms, sizeof(params)); 5229 if (err != OK) { 5230 return err; 5231 } 5232 5233 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_EAC3); 5234 notify->setInt32("channel-count", params.nChannels); 5235 notify->setInt32("sample-rate", params.nSampleRate); 5236 break; 5237 } 5238 5239 case OMX_AUDIO_CodingAndroidOPUS: 5240 { 5241 OMX_AUDIO_PARAM_ANDROID_OPUSTYPE params; 5242 InitOMXParams(¶ms); 5243 params.nPortIndex = portIndex; 5244 5245 err = mOMXNode->getParameter( 5246 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus, 5247 ¶ms, sizeof(params)); 5248 if (err != OK) { 5249 return err; 5250 } 5251 5252 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_OPUS); 5253 notify->setInt32("channel-count", params.nChannels); 5254 notify->setInt32("sample-rate", params.nSampleRate); 5255 break; 5256 } 5257 5258 case OMX_AUDIO_CodingG711: 5259 { 5260 OMX_AUDIO_PARAM_PCMMODETYPE params; 5261 InitOMXParams(¶ms); 5262 params.nPortIndex = portIndex; 5263 5264 err = mOMXNode->getParameter( 5265 (OMX_INDEXTYPE)OMX_IndexParamAudioPcm, ¶ms, sizeof(params)); 5266 if (err != OK) { 5267 return err; 5268 } 5269 5270 const char *mime = NULL; 5271 if (params.ePCMMode == OMX_AUDIO_PCMModeMULaw) { 5272 mime = MEDIA_MIMETYPE_AUDIO_G711_MLAW; 5273 } else if (params.ePCMMode == OMX_AUDIO_PCMModeALaw) { 5274 mime = MEDIA_MIMETYPE_AUDIO_G711_ALAW; 5275 } else { // params.ePCMMode == OMX_AUDIO_PCMModeLinear 5276 mime = MEDIA_MIMETYPE_AUDIO_RAW; 5277 } 5278 notify->setString("mime", mime); 5279 notify->setInt32("channel-count", params.nChannels); 5280 notify->setInt32("sample-rate", params.nSamplingRate); 5281 notify->setInt32("pcm-encoding", kAudioEncodingPcm16bit); 5282 break; 5283 } 5284 5285 case OMX_AUDIO_CodingGSMFR: 5286 { 5287 OMX_AUDIO_PARAM_PCMMODETYPE params; 5288 InitOMXParams(¶ms); 5289 params.nPortIndex = portIndex; 5290 5291 err = mOMXNode->getParameter( 5292 OMX_IndexParamAudioPcm, ¶ms, sizeof(params)); 5293 if (err != OK) { 5294 return err; 5295 } 5296 5297 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MSGSM); 5298 notify->setInt32("channel-count", params.nChannels); 5299 notify->setInt32("sample-rate", params.nSamplingRate); 5300 break; 5301 } 5302 5303 default: 5304 ALOGE("Unsupported audio coding: %s(%d)\n", 5305 asString(audioDef->eEncoding), audioDef->eEncoding); 5306 return BAD_TYPE; 5307 } 5308 break; 5309 } 5310 5311 default: 5312 ALOGE("Unsupported domain: %s(%d)", asString(def.eDomain), def.eDomain); 5313 return BAD_TYPE; 5314 } 5315 5316 return getVendorParameters(portIndex, notify); 5317} 5318 5319void ACodec::onDataSpaceChanged(android_dataspace dataSpace, const ColorAspects &aspects) { 5320 // aspects are normally communicated in ColorAspects 5321 int32_t range, standard, transfer; 5322 convertCodecColorAspectsToPlatformAspects(aspects, &range, &standard, &transfer); 5323 5324 // if some aspects are unspecified, use dataspace fields 5325 if (range == 0) { 5326 range = (dataSpace & HAL_DATASPACE_RANGE_MASK) >> HAL_DATASPACE_RANGE_SHIFT; 5327 } 5328 if (standard == 0) { 5329 standard = (dataSpace & HAL_DATASPACE_STANDARD_MASK) >> HAL_DATASPACE_STANDARD_SHIFT; 5330 } 5331 if (transfer == 0) { 5332 transfer = (dataSpace & HAL_DATASPACE_TRANSFER_MASK) >> HAL_DATASPACE_TRANSFER_SHIFT; 5333 } 5334 5335 mOutputFormat = mOutputFormat->dup(); // trigger an output format changed event 5336 if (range != 0) { 5337 mOutputFormat->setInt32("color-range", range); 5338 } 5339 if (standard != 0) { 5340 mOutputFormat->setInt32("color-standard", standard); 5341 } 5342 if (transfer != 0) { 5343 mOutputFormat->setInt32("color-transfer", transfer); 5344 } 5345 5346 ALOGD("dataspace changed to %#x (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) " 5347 "(R:%d(%s), S:%d(%s), T:%d(%s))", 5348 dataSpace, 5349 aspects.mRange, asString(aspects.mRange), 5350 aspects.mPrimaries, asString(aspects.mPrimaries), 5351 aspects.mMatrixCoeffs, asString(aspects.mMatrixCoeffs), 5352 aspects.mTransfer, asString(aspects.mTransfer), 5353 range, asString((ColorRange)range), 5354 standard, asString((ColorStandard)standard), 5355 transfer, asString((ColorTransfer)transfer)); 5356} 5357 5358void ACodec::onOutputFormatChanged(sp<const AMessage> expectedFormat) { 5359 // store new output format, at the same time mark that this is no longer the first frame 5360 mOutputFormat = mBaseOutputFormat->dup(); 5361 5362 if (getPortFormat(kPortIndexOutput, mOutputFormat) != OK) { 5363 ALOGE("[%s] Failed to get port format to send format change", mComponentName.c_str()); 5364 return; 5365 } 5366 5367 if (expectedFormat != NULL) { 5368 sp<const AMessage> changes = expectedFormat->changesFrom(mOutputFormat); 5369 sp<const AMessage> to = mOutputFormat->changesFrom(expectedFormat); 5370 if (changes->countEntries() != 0 || to->countEntries() != 0) { 5371 ALOGW("[%s] BAD CODEC: Output format changed unexpectedly from (diff) %s to (diff) %s", 5372 mComponentName.c_str(), 5373 changes->debugString(4).c_str(), to->debugString(4).c_str()); 5374 } 5375 } 5376 5377 if (!mIsVideo && !mIsEncoder) { 5378 AudioEncoding pcmEncoding = kAudioEncodingPcm16bit; 5379 (void)mConfigFormat->findInt32("pcm-encoding", (int32_t*)&pcmEncoding); 5380 AudioEncoding codecPcmEncoding = kAudioEncodingPcm16bit; 5381 (void)mOutputFormat->findInt32("pcm-encoding", (int32_t*)&pcmEncoding); 5382 5383 mConverter[kPortIndexOutput] = AudioConverter::Create(codecPcmEncoding, pcmEncoding); 5384 if (mConverter[kPortIndexOutput] != NULL) { 5385 mOutputFormat->setInt32("pcm-encoding", pcmEncoding); 5386 } 5387 } 5388 5389 if (mTunneled) { 5390 sendFormatChange(); 5391 } 5392} 5393 5394void ACodec::sendFormatChange() { 5395 AString mime; 5396 CHECK(mOutputFormat->findString("mime", &mime)); 5397 5398 if (mime == MEDIA_MIMETYPE_AUDIO_RAW && (mEncoderDelay || mEncoderPadding)) { 5399 int32_t channelCount, sampleRate; 5400 CHECK(mOutputFormat->findInt32("channel-count", &channelCount)); 5401 CHECK(mOutputFormat->findInt32("sample-rate", &sampleRate)); 5402 if (mSampleRate != 0 && sampleRate != 0) { 5403 // avoiding 32-bit overflows in intermediate values 5404 mEncoderDelay = (int32_t)((((int64_t)mEncoderDelay) * sampleRate) / mSampleRate); 5405 mEncoderPadding = (int32_t)((((int64_t)mEncoderPadding) * sampleRate) / mSampleRate); 5406 mSampleRate = sampleRate; 5407 } 5408 if (mSkipCutBuffer != NULL) { 5409 size_t prevbufsize = mSkipCutBuffer->size(); 5410 if (prevbufsize != 0) { 5411 ALOGW("Replacing SkipCutBuffer holding %zu bytes", prevbufsize); 5412 } 5413 } 5414 mSkipCutBuffer = new SkipCutBuffer(mEncoderDelay, mEncoderPadding, channelCount); 5415 } 5416 5417 // mLastOutputFormat is not used when tunneled; doing this just to stay consistent 5418 mLastOutputFormat = mOutputFormat; 5419} 5420 5421void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) { 5422 ALOGE("signalError(omxError %#x, internalError %d)", error, internalError); 5423 5424 if (internalError == UNKNOWN_ERROR) { // find better error code 5425 const status_t omxStatus = statusFromOMXError(error); 5426 if (omxStatus != 0) { 5427 internalError = omxStatus; 5428 } else { 5429 ALOGW("Invalid OMX error %#x", error); 5430 } 5431 } 5432 5433 mFatalError = true; 5434 mCallback->onError(internalError, ACTION_CODE_FATAL); 5435} 5436 5437status_t ACodec::requestIDRFrame() { 5438 if (!mIsEncoder) { 5439 return ERROR_UNSUPPORTED; 5440 } 5441 5442 OMX_CONFIG_INTRAREFRESHVOPTYPE params; 5443 InitOMXParams(¶ms); 5444 5445 params.nPortIndex = kPortIndexOutput; 5446 params.IntraRefreshVOP = OMX_TRUE; 5447 5448 return mOMXNode->setConfig( 5449 OMX_IndexConfigVideoIntraVOPRefresh, 5450 ¶ms, 5451 sizeof(params)); 5452} 5453 5454//////////////////////////////////////////////////////////////////////////////// 5455 5456ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState) 5457 : AState(parentState), 5458 mCodec(codec) { 5459} 5460 5461ACodec::BaseState::PortMode ACodec::BaseState::getPortMode( 5462 OMX_U32 /* portIndex */) { 5463 return KEEP_BUFFERS; 5464} 5465 5466void ACodec::BaseState::stateExited() { 5467 ++mCodec->mStateGeneration; 5468} 5469 5470bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) { 5471 switch (msg->what()) { 5472 case kWhatInputBufferFilled: 5473 { 5474 onInputBufferFilled(msg); 5475 break; 5476 } 5477 5478 case kWhatOutputBufferDrained: 5479 { 5480 onOutputBufferDrained(msg); 5481 break; 5482 } 5483 5484 case ACodec::kWhatOMXMessageList: 5485 { 5486 return checkOMXMessage(msg) ? onOMXMessageList(msg) : true; 5487 } 5488 5489 case ACodec::kWhatOMXMessageItem: 5490 { 5491 // no need to check as we already did it for kWhatOMXMessageList 5492 return onOMXMessage(msg); 5493 } 5494 5495 case ACodec::kWhatOMXMessage: 5496 { 5497 return checkOMXMessage(msg) ? onOMXMessage(msg) : true; 5498 } 5499 5500 case ACodec::kWhatSetSurface: 5501 { 5502 sp<AReplyToken> replyID; 5503 CHECK(msg->senderAwaitsResponse(&replyID)); 5504 5505 sp<RefBase> obj; 5506 CHECK(msg->findObject("surface", &obj)); 5507 5508 status_t err = mCodec->handleSetSurface(static_cast<Surface *>(obj.get())); 5509 5510 sp<AMessage> response = new AMessage; 5511 response->setInt32("err", err); 5512 response->postReply(replyID); 5513 break; 5514 } 5515 5516 case ACodec::kWhatCreateInputSurface: 5517 case ACodec::kWhatSetInputSurface: 5518 case ACodec::kWhatSignalEndOfInputStream: 5519 { 5520 // This may result in an app illegal state exception. 5521 ALOGE("Message 0x%x was not handled", msg->what()); 5522 mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION); 5523 return true; 5524 } 5525 5526 case ACodec::kWhatOMXDied: 5527 { 5528 // This will result in kFlagSawMediaServerDie handling in MediaCodec. 5529 ALOGE("OMX/mediaserver died, signalling error!"); 5530 mCodec->mGraphicBufferSource.clear(); 5531 mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT); 5532 break; 5533 } 5534 5535 case ACodec::kWhatReleaseCodecInstance: 5536 { 5537 ALOGI("[%s] forcing the release of codec", 5538 mCodec->mComponentName.c_str()); 5539 status_t err = mCodec->mOMXNode->freeNode(); 5540 ALOGE_IF("[%s] failed to release codec instance: err=%d", 5541 mCodec->mComponentName.c_str(), err); 5542 mCodec->mCallback->onReleaseCompleted(); 5543 5544 mCodec->changeState(mCodec->mUninitializedState); 5545 break; 5546 } 5547 5548 case ACodec::kWhatForceStateTransition: 5549 { 5550 ALOGV("Already transitioned --- ignore"); 5551 break; 5552 } 5553 5554 default: 5555 return false; 5556 } 5557 5558 return true; 5559} 5560 5561bool ACodec::BaseState::checkOMXMessage(const sp<AMessage> &msg) { 5562 // there is a possibility that this is an outstanding message for a 5563 // codec that we have already destroyed 5564 if (mCodec->mOMXNode == NULL) { 5565 ALOGI("ignoring message as already freed component: %s", 5566 msg->debugString().c_str()); 5567 return false; 5568 } 5569 5570 int32_t generation; 5571 CHECK(msg->findInt32("generation", (int32_t*)&generation)); 5572 if (generation != mCodec->mNodeGeneration) { 5573 ALOGW("Unexpected message for component: %s, gen %u, cur %u", 5574 msg->debugString().c_str(), generation, mCodec->mNodeGeneration); 5575 return false; 5576 } 5577 return true; 5578} 5579 5580bool ACodec::BaseState::onOMXMessageList(const sp<AMessage> &msg) { 5581 sp<RefBase> obj; 5582 CHECK(msg->findObject("messages", &obj)); 5583 sp<MessageList> msgList = static_cast<MessageList *>(obj.get()); 5584 5585 bool receivedRenderedEvents = false; 5586 for (std::list<sp<AMessage>>::const_iterator it = msgList->getList().cbegin(); 5587 it != msgList->getList().cend(); ++it) { 5588 (*it)->setWhat(ACodec::kWhatOMXMessageItem); 5589 mCodec->handleMessage(*it); 5590 int32_t type; 5591 CHECK((*it)->findInt32("type", &type)); 5592 if (type == omx_message::FRAME_RENDERED) { 5593 receivedRenderedEvents = true; 5594 } 5595 } 5596 5597 if (receivedRenderedEvents) { 5598 // NOTE: all buffers are rendered in this case 5599 mCodec->notifyOfRenderedFrames(); 5600 } 5601 return true; 5602} 5603 5604bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) { 5605 int32_t type; 5606 CHECK(msg->findInt32("type", &type)); 5607 5608 switch (type) { 5609 case omx_message::EVENT: 5610 { 5611 int32_t event, data1, data2; 5612 CHECK(msg->findInt32("event", &event)); 5613 CHECK(msg->findInt32("data1", &data1)); 5614 CHECK(msg->findInt32("data2", &data2)); 5615 5616 if (event == OMX_EventCmdComplete 5617 && data1 == OMX_CommandFlush 5618 && data2 == (int32_t)OMX_ALL) { 5619 // Use of this notification is not consistent across 5620 // implementations. We'll drop this notification and rely 5621 // on flush-complete notifications on the individual port 5622 // indices instead. 5623 5624 return true; 5625 } 5626 5627 return onOMXEvent( 5628 static_cast<OMX_EVENTTYPE>(event), 5629 static_cast<OMX_U32>(data1), 5630 static_cast<OMX_U32>(data2)); 5631 } 5632 5633 case omx_message::EMPTY_BUFFER_DONE: 5634 { 5635 IOMX::buffer_id bufferID; 5636 int32_t fenceFd; 5637 5638 CHECK(msg->findInt32("buffer", (int32_t*)&bufferID)); 5639 CHECK(msg->findInt32("fence_fd", &fenceFd)); 5640 5641 return onOMXEmptyBufferDone(bufferID, fenceFd); 5642 } 5643 5644 case omx_message::FILL_BUFFER_DONE: 5645 { 5646 IOMX::buffer_id bufferID; 5647 CHECK(msg->findInt32("buffer", (int32_t*)&bufferID)); 5648 5649 int32_t rangeOffset, rangeLength, flags, fenceFd; 5650 int64_t timeUs; 5651 5652 CHECK(msg->findInt32("range_offset", &rangeOffset)); 5653 CHECK(msg->findInt32("range_length", &rangeLength)); 5654 CHECK(msg->findInt32("flags", &flags)); 5655 CHECK(msg->findInt64("timestamp", &timeUs)); 5656 CHECK(msg->findInt32("fence_fd", &fenceFd)); 5657 5658 return onOMXFillBufferDone( 5659 bufferID, 5660 (size_t)rangeOffset, (size_t)rangeLength, 5661 (OMX_U32)flags, 5662 timeUs, 5663 fenceFd); 5664 } 5665 5666 case omx_message::FRAME_RENDERED: 5667 { 5668 int64_t mediaTimeUs, systemNano; 5669 5670 CHECK(msg->findInt64("media_time_us", &mediaTimeUs)); 5671 CHECK(msg->findInt64("system_nano", &systemNano)); 5672 5673 return onOMXFrameRendered( 5674 mediaTimeUs, systemNano); 5675 } 5676 5677 default: 5678 ALOGE("Unexpected message type: %d", type); 5679 return false; 5680 } 5681} 5682 5683bool ACodec::BaseState::onOMXFrameRendered( 5684 int64_t mediaTimeUs __unused, nsecs_t systemNano __unused) { 5685 // ignore outside of Executing and PortSettingsChanged states 5686 return true; 5687} 5688 5689bool ACodec::BaseState::onOMXEvent( 5690 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 5691 if (event == OMX_EventDataSpaceChanged) { 5692 ColorAspects aspects = ColorUtils::unpackToColorAspects(data2); 5693 5694 mCodec->onDataSpaceChanged((android_dataspace)data1, aspects); 5695 return true; 5696 } 5697 5698 if (event != OMX_EventError) { 5699 ALOGV("[%s] EVENT(%d, 0x%08x, 0x%08x)", 5700 mCodec->mComponentName.c_str(), event, data1, data2); 5701 5702 return false; 5703 } 5704 5705 ALOGE("[%s] ERROR(0x%08x)", mCodec->mComponentName.c_str(), data1); 5706 5707 // verify OMX component sends back an error we expect. 5708 OMX_ERRORTYPE omxError = (OMX_ERRORTYPE)data1; 5709 if (!isOMXError(omxError)) { 5710 ALOGW("Invalid OMX error %#x", omxError); 5711 omxError = OMX_ErrorUndefined; 5712 } 5713 mCodec->signalError(omxError); 5714 5715 return true; 5716} 5717 5718bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID, int fenceFd) { 5719 ALOGV("[%s] onOMXEmptyBufferDone %u", 5720 mCodec->mComponentName.c_str(), bufferID); 5721 5722 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID); 5723 BufferInfo::Status status = BufferInfo::getSafeStatus(info); 5724 if (status != BufferInfo::OWNED_BY_COMPONENT) { 5725 ALOGE("Wrong ownership in EBD: %s(%d) buffer #%u", _asString(status), status, bufferID); 5726 mCodec->dumpBuffers(kPortIndexInput); 5727 if (fenceFd >= 0) { 5728 ::close(fenceFd); 5729 } 5730 return false; 5731 } 5732 info->mStatus = BufferInfo::OWNED_BY_US; 5733 5734 // input buffers cannot take fences, so wait for any fence now 5735 (void)mCodec->waitForFence(fenceFd, "onOMXEmptyBufferDone"); 5736 fenceFd = -1; 5737 5738 // still save fence for completeness 5739 info->setWriteFence(fenceFd, "onOMXEmptyBufferDone"); 5740 5741 // We're in "store-metadata-in-buffers" mode, the underlying 5742 // OMX component had access to data that's implicitly refcounted 5743 // by this "MediaBuffer" object. Now that the OMX component has 5744 // told us that it's done with the input buffer, we can decrement 5745 // the mediaBuffer's reference count. 5746 info->mData->meta()->setObject("mediaBufferHolder", sp<MediaBufferHolder>(nullptr)); 5747 5748 PortMode mode = getPortMode(kPortIndexInput); 5749 5750 switch (mode) { 5751 case KEEP_BUFFERS: 5752 break; 5753 5754 case RESUBMIT_BUFFERS: 5755 postFillThisBuffer(info); 5756 break; 5757 5758 case FREE_BUFFERS: 5759 default: 5760 ALOGE("SHOULD NOT REACH HERE: cannot free empty output buffers"); 5761 return false; 5762 } 5763 5764 return true; 5765} 5766 5767void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) { 5768 if (mCodec->mPortEOS[kPortIndexInput]) { 5769 return; 5770 } 5771 5772 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 5773 5774 info->mData->setFormat(mCodec->mInputFormat); 5775 mCodec->mBufferChannel->fillThisBuffer(info->mBufferID); 5776 info->mData.clear(); 5777 info->mStatus = BufferInfo::OWNED_BY_UPSTREAM; 5778} 5779 5780void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { 5781 IOMX::buffer_id bufferID; 5782 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID)); 5783 sp<MediaCodecBuffer> buffer; 5784 int32_t err = OK; 5785 bool eos = false; 5786 PortMode mode = getPortMode(kPortIndexInput); 5787 int32_t discarded = 0; 5788 if (msg->findInt32("discarded", &discarded) && discarded) { 5789 // these are unfilled buffers returned by client 5790 // buffers are returned on MediaCodec.flush 5791 mode = KEEP_BUFFERS; 5792 } 5793 sp<RefBase> obj; 5794 CHECK(msg->findObject("buffer", &obj)); 5795 buffer = static_cast<MediaCodecBuffer *>(obj.get()); 5796 5797 int32_t tmp; 5798 if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) { 5799 eos = true; 5800 err = ERROR_END_OF_STREAM; 5801 } 5802 5803 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID); 5804 BufferInfo::Status status = BufferInfo::getSafeStatus(info); 5805 if (status != BufferInfo::OWNED_BY_UPSTREAM) { 5806 ALOGE("Wrong ownership in IBF: %s(%d) buffer #%u", _asString(status), status, bufferID); 5807 mCodec->dumpBuffers(kPortIndexInput); 5808 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 5809 return; 5810 } 5811 5812 info->mStatus = BufferInfo::OWNED_BY_US; 5813 info->mData = buffer; 5814 5815 switch (mode) { 5816 case KEEP_BUFFERS: 5817 { 5818 if (eos) { 5819 if (!mCodec->mPortEOS[kPortIndexInput]) { 5820 mCodec->mPortEOS[kPortIndexInput] = true; 5821 mCodec->mInputEOSResult = err; 5822 } 5823 } 5824 break; 5825 } 5826 5827 case RESUBMIT_BUFFERS: 5828 { 5829 if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) { 5830 // Do not send empty input buffer w/o EOS to the component. 5831 if (buffer->size() == 0 && !eos) { 5832 postFillThisBuffer(info); 5833 break; 5834 } 5835 5836 int64_t timeUs; 5837 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 5838 5839 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME; 5840 5841 int32_t isCSD = 0; 5842 if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) { 5843 if (mCodec->mIsLegacyVP9Decoder) { 5844 ALOGV("[%s] is legacy VP9 decoder. Ignore %u codec specific data", 5845 mCodec->mComponentName.c_str(), bufferID); 5846 postFillThisBuffer(info); 5847 break; 5848 } 5849 flags |= OMX_BUFFERFLAG_CODECCONFIG; 5850 } 5851 5852 if (eos) { 5853 flags |= OMX_BUFFERFLAG_EOS; 5854 } 5855 5856 size_t size = buffer->size(); 5857 size_t offset = buffer->offset(); 5858 if (buffer->base() != info->mCodecData->base()) { 5859 ALOGV("[%s] Needs to copy input data for buffer %u. (%p != %p)", 5860 mCodec->mComponentName.c_str(), 5861 bufferID, 5862 buffer->base(), info->mCodecData->base()); 5863 5864 sp<DataConverter> converter = mCodec->mConverter[kPortIndexInput]; 5865 if (converter == NULL || isCSD) { 5866 converter = getCopyConverter(); 5867 } 5868 status_t err = converter->convert(buffer, info->mCodecData); 5869 if (err != OK) { 5870 mCodec->signalError(OMX_ErrorUndefined, err); 5871 return; 5872 } 5873 size = info->mCodecData->size(); 5874 } else { 5875 info->mCodecData->setRange(offset, size); 5876 } 5877 5878 if (flags & OMX_BUFFERFLAG_CODECCONFIG) { 5879 ALOGV("[%s] calling emptyBuffer %u w/ codec specific data", 5880 mCodec->mComponentName.c_str(), bufferID); 5881 } else if (flags & OMX_BUFFERFLAG_EOS) { 5882 ALOGV("[%s] calling emptyBuffer %u w/ EOS", 5883 mCodec->mComponentName.c_str(), bufferID); 5884 } else { 5885#if TRACK_BUFFER_TIMING 5886 ALOGI("[%s] calling emptyBuffer %u w/ time %lld us", 5887 mCodec->mComponentName.c_str(), bufferID, (long long)timeUs); 5888#else 5889 ALOGV("[%s] calling emptyBuffer %u w/ time %lld us", 5890 mCodec->mComponentName.c_str(), bufferID, (long long)timeUs); 5891#endif 5892 } 5893 5894#if TRACK_BUFFER_TIMING 5895 ACodec::BufferStats stats; 5896 stats.mEmptyBufferTimeUs = ALooper::GetNowUs(); 5897 stats.mFillBufferDoneTimeUs = -1ll; 5898 mCodec->mBufferStats.add(timeUs, stats); 5899#endif 5900 5901 if (mCodec->storingMetadataInDecodedBuffers()) { 5902 // try to submit an output buffer for each input buffer 5903 PortMode outputMode = getPortMode(kPortIndexOutput); 5904 5905 ALOGV("MetadataBuffersToSubmit=%u portMode=%s", 5906 mCodec->mMetadataBuffersToSubmit, 5907 (outputMode == FREE_BUFFERS ? "FREE" : 5908 outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT")); 5909 if (outputMode == RESUBMIT_BUFFERS) { 5910 mCodec->submitOutputMetadataBuffer(); 5911 } 5912 } 5913 info->checkReadFence("onInputBufferFilled"); 5914 5915 status_t err2 = OK; 5916 switch (mCodec->mPortMode[kPortIndexInput]) { 5917 case IOMX::kPortModePresetByteBuffer: 5918 case IOMX::kPortModePresetANWBuffer: 5919 case IOMX::kPortModePresetSecureBuffer: 5920 { 5921 err2 = mCodec->mOMXNode->emptyBuffer( 5922 bufferID, info->mCodecData, flags, timeUs, info->mFenceFd); 5923 } 5924 break; 5925#ifndef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS 5926 case IOMX::kPortModeDynamicNativeHandle: 5927 if (info->mCodecData->size() >= sizeof(VideoNativeHandleMetadata)) { 5928 VideoNativeHandleMetadata *vnhmd = 5929 (VideoNativeHandleMetadata*)info->mCodecData->base(); 5930 sp<NativeHandle> handle = NativeHandle::create( 5931 vnhmd->pHandle, false /* ownsHandle */); 5932 err2 = mCodec->mOMXNode->emptyBuffer( 5933 bufferID, handle, flags, timeUs, info->mFenceFd); 5934 } 5935 break; 5936 case IOMX::kPortModeDynamicANWBuffer: 5937 if (info->mCodecData->size() >= sizeof(VideoNativeMetadata)) { 5938 VideoNativeMetadata *vnmd = (VideoNativeMetadata*)info->mCodecData->base(); 5939 sp<GraphicBuffer> graphicBuffer = GraphicBuffer::from(vnmd->pBuffer); 5940 err2 = mCodec->mOMXNode->emptyBuffer( 5941 bufferID, graphicBuffer, flags, timeUs, info->mFenceFd); 5942 } 5943 break; 5944#endif 5945 default: 5946 ALOGW("Can't marshall %s data in %zu sized buffers in %zu-bit mode", 5947 asString(mCodec->mPortMode[kPortIndexInput]), 5948 info->mCodecData->size(), 5949 sizeof(buffer_handle_t) * 8); 5950 err2 = ERROR_UNSUPPORTED; 5951 break; 5952 } 5953 5954 info->mFenceFd = -1; 5955 if (err2 != OK) { 5956 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2)); 5957 return; 5958 } 5959 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 5960 // Hold the reference while component is using the buffer. 5961 info->mData = buffer; 5962 5963 if (!eos && err == OK) { 5964 getMoreInputDataIfPossible(); 5965 } else { 5966 ALOGV("[%s] Signalled EOS (%d) on the input port", 5967 mCodec->mComponentName.c_str(), err); 5968 5969 mCodec->mPortEOS[kPortIndexInput] = true; 5970 mCodec->mInputEOSResult = err; 5971 } 5972 } else if (!mCodec->mPortEOS[kPortIndexInput]) { 5973 if (err != OK && err != ERROR_END_OF_STREAM) { 5974 ALOGV("[%s] Signalling EOS on the input port due to error %d", 5975 mCodec->mComponentName.c_str(), err); 5976 } else { 5977 ALOGV("[%s] Signalling EOS on the input port", 5978 mCodec->mComponentName.c_str()); 5979 } 5980 5981 ALOGV("[%s] calling emptyBuffer %u signalling EOS", 5982 mCodec->mComponentName.c_str(), bufferID); 5983 5984 info->checkReadFence("onInputBufferFilled"); 5985 status_t err2 = mCodec->mOMXNode->emptyBuffer( 5986 bufferID, OMXBuffer::sPreset, OMX_BUFFERFLAG_EOS, 0, info->mFenceFd); 5987 info->mFenceFd = -1; 5988 if (err2 != OK) { 5989 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2)); 5990 return; 5991 } 5992 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 5993 5994 mCodec->mPortEOS[kPortIndexInput] = true; 5995 mCodec->mInputEOSResult = err; 5996 } 5997 break; 5998 } 5999 6000 case FREE_BUFFERS: 6001 break; 6002 6003 default: 6004 ALOGE("invalid port mode: %d", mode); 6005 break; 6006 } 6007} 6008 6009void ACodec::BaseState::getMoreInputDataIfPossible() { 6010 if (mCodec->mPortEOS[kPortIndexInput]) { 6011 return; 6012 } 6013 6014 BufferInfo *eligible = NULL; 6015 6016 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 6017 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 6018 6019#if 0 6020 if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) { 6021 // There's already a "read" pending. 6022 return; 6023 } 6024#endif 6025 6026 if (info->mStatus == BufferInfo::OWNED_BY_US) { 6027 eligible = info; 6028 } 6029 } 6030 6031 if (eligible == NULL) { 6032 return; 6033 } 6034 6035 postFillThisBuffer(eligible); 6036} 6037 6038bool ACodec::BaseState::onOMXFillBufferDone( 6039 IOMX::buffer_id bufferID, 6040 size_t rangeOffset, size_t rangeLength, 6041 OMX_U32 flags, 6042 int64_t timeUs, 6043 int fenceFd) { 6044 ALOGV("[%s] onOMXFillBufferDone %u time %" PRId64 " us, flags = 0x%08x", 6045 mCodec->mComponentName.c_str(), bufferID, timeUs, flags); 6046 6047 ssize_t index; 6048 status_t err= OK; 6049 6050#if TRACK_BUFFER_TIMING 6051 index = mCodec->mBufferStats.indexOfKey(timeUs); 6052 if (index >= 0) { 6053 ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index); 6054 stats->mFillBufferDoneTimeUs = ALooper::GetNowUs(); 6055 6056 ALOGI("frame PTS %lld: %lld", 6057 timeUs, 6058 stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs); 6059 6060 mCodec->mBufferStats.removeItemsAt(index); 6061 stats = NULL; 6062 } 6063#endif 6064 6065 BufferInfo *info = 6066 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 6067 BufferInfo::Status status = BufferInfo::getSafeStatus(info); 6068 if (status != BufferInfo::OWNED_BY_COMPONENT) { 6069 ALOGE("Wrong ownership in FBD: %s(%d) buffer #%u", _asString(status), status, bufferID); 6070 mCodec->dumpBuffers(kPortIndexOutput); 6071 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6072 if (fenceFd >= 0) { 6073 ::close(fenceFd); 6074 } 6075 return true; 6076 } 6077 6078 info->mDequeuedAt = ++mCodec->mDequeueCounter; 6079 info->mStatus = BufferInfo::OWNED_BY_US; 6080 6081 if (info->mRenderInfo != NULL) { 6082 // The fence for an emptied buffer must have signaled, but there still could be queued 6083 // or out-of-order dequeued buffers in the render queue prior to this buffer. Drop these, 6084 // as we will soon requeue this buffer to the surface. While in theory we could still keep 6085 // track of buffers that are requeued to the surface, it is better to add support to the 6086 // buffer-queue to notify us of released buffers and their fences (in the future). 6087 mCodec->notifyOfRenderedFrames(true /* dropIncomplete */); 6088 } 6089 6090 // byte buffers cannot take fences, so wait for any fence now 6091 if (mCodec->mNativeWindow == NULL) { 6092 (void)mCodec->waitForFence(fenceFd, "onOMXFillBufferDone"); 6093 fenceFd = -1; 6094 } 6095 info->setReadFence(fenceFd, "onOMXFillBufferDone"); 6096 6097 PortMode mode = getPortMode(kPortIndexOutput); 6098 6099 switch (mode) { 6100 case KEEP_BUFFERS: 6101 break; 6102 6103 case RESUBMIT_BUFFERS: 6104 { 6105 if (rangeLength == 0 && (!(flags & OMX_BUFFERFLAG_EOS) 6106 || mCodec->mPortEOS[kPortIndexOutput])) { 6107 ALOGV("[%s] calling fillBuffer %u", 6108 mCodec->mComponentName.c_str(), info->mBufferID); 6109 6110 err = mCodec->fillBuffer(info); 6111 if (err != OK) { 6112 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6113 return true; 6114 } 6115 break; 6116 } 6117 6118 sp<MediaCodecBuffer> buffer = info->mData; 6119 6120 if (mCodec->mOutputFormat != mCodec->mLastOutputFormat && rangeLength > 0) { 6121 // pretend that output format has changed on the first frame (we used to do this) 6122 if (mCodec->mBaseOutputFormat == mCodec->mOutputFormat) { 6123 mCodec->onOutputFormatChanged(mCodec->mOutputFormat); 6124 } 6125 mCodec->sendFormatChange(); 6126 } 6127 buffer->setFormat(mCodec->mOutputFormat); 6128 6129 if (mCodec->usingSecureBufferOnEncoderOutput()) { 6130 native_handle_t *handle = NULL; 6131 sp<SecureBuffer> secureBuffer = static_cast<SecureBuffer *>(buffer.get()); 6132 if (secureBuffer != NULL) { 6133#ifdef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS 6134 // handle is only valid on 32-bit/mediaserver process 6135 handle = NULL; 6136#else 6137 handle = (native_handle_t *)secureBuffer->getDestinationPointer(); 6138#endif 6139 } 6140 buffer->meta()->setPointer("handle", handle); 6141 buffer->meta()->setInt32("rangeOffset", rangeOffset); 6142 buffer->meta()->setInt32("rangeLength", rangeLength); 6143 } else if (buffer->base() == info->mCodecData->base()) { 6144 buffer->setRange(rangeOffset, rangeLength); 6145 } else { 6146 info->mCodecData->setRange(rangeOffset, rangeLength); 6147 // in this case we know that mConverter is not null 6148 status_t err = mCodec->mConverter[kPortIndexOutput]->convert( 6149 info->mCodecData, buffer); 6150 if (err != OK) { 6151 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6152 return true; 6153 } 6154 } 6155#if 0 6156 if (mCodec->mNativeWindow == NULL) { 6157 if (IsIDR(info->mData->data(), info->mData->size())) { 6158 ALOGI("IDR frame"); 6159 } 6160 } 6161#endif 6162 6163 if (mCodec->mSkipCutBuffer != NULL) { 6164 mCodec->mSkipCutBuffer->submit(buffer); 6165 } 6166 buffer->meta()->setInt64("timeUs", timeUs); 6167 6168 info->mData.clear(); 6169 6170 mCodec->mBufferChannel->drainThisBuffer(info->mBufferID, flags); 6171 6172 info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM; 6173 6174 if (flags & OMX_BUFFERFLAG_EOS) { 6175 ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str()); 6176 6177 mCodec->mCallback->onEos(mCodec->mInputEOSResult); 6178 mCodec->mPortEOS[kPortIndexOutput] = true; 6179 } 6180 break; 6181 } 6182 6183 case FREE_BUFFERS: 6184 err = mCodec->freeBuffer(kPortIndexOutput, index); 6185 if (err != OK) { 6186 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6187 return true; 6188 } 6189 break; 6190 6191 default: 6192 ALOGE("Invalid port mode: %d", mode); 6193 return false; 6194 } 6195 6196 return true; 6197} 6198 6199void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { 6200 IOMX::buffer_id bufferID; 6201 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID)); 6202 sp<RefBase> obj; 6203 CHECK(msg->findObject("buffer", &obj)); 6204 sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get()); 6205 int32_t discarded = 0; 6206 msg->findInt32("discarded", &discarded); 6207 6208 ssize_t index; 6209 BufferInfo *info = mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 6210 BufferInfo::Status status = BufferInfo::getSafeStatus(info); 6211 if (status != BufferInfo::OWNED_BY_DOWNSTREAM) { 6212 ALOGE("Wrong ownership in OBD: %s(%d) buffer #%u", _asString(status), status, bufferID); 6213 mCodec->dumpBuffers(kPortIndexOutput); 6214 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6215 return; 6216 } 6217 info->mData = buffer; 6218 int32_t render; 6219 if (mCodec->mNativeWindow != NULL 6220 && msg->findInt32("render", &render) && render != 0 6221 && !discarded && buffer->size() != 0) { 6222 ATRACE_NAME("render"); 6223 // The client wants this buffer to be rendered. 6224 6225 android_native_rect_t crop; 6226 if (buffer->format()->findRect("crop", &crop.left, &crop.top, &crop.right, &crop.bottom)) { 6227 // NOTE: native window uses extended right-bottom coordinate 6228 ++crop.right; 6229 ++crop.bottom; 6230 if (memcmp(&crop, &mCodec->mLastNativeWindowCrop, sizeof(crop)) != 0) { 6231 mCodec->mLastNativeWindowCrop = crop; 6232 status_t err = native_window_set_crop(mCodec->mNativeWindow.get(), &crop); 6233 ALOGW_IF(err != NO_ERROR, "failed to set crop: %d", err); 6234 } 6235 } 6236 6237 int32_t dataSpace; 6238 if (buffer->format()->findInt32("android._dataspace", &dataSpace) 6239 && dataSpace != mCodec->mLastNativeWindowDataSpace) { 6240 status_t err = native_window_set_buffers_data_space( 6241 mCodec->mNativeWindow.get(), (android_dataspace)dataSpace); 6242 mCodec->mLastNativeWindowDataSpace = dataSpace; 6243 ALOGW_IF(err != NO_ERROR, "failed to set dataspace: %d", err); 6244 } 6245 if (buffer->format()->contains("hdr-static-info")) { 6246 HDRStaticInfo info; 6247 if (ColorUtils::getHDRStaticInfoFromFormat(buffer->format(), &info) 6248 && memcmp(&mCodec->mLastHDRStaticInfo, &info, sizeof(info))) { 6249 setNativeWindowHdrMetadata(mCodec->mNativeWindow.get(), &info); 6250 mCodec->mLastHDRStaticInfo = info; 6251 } 6252 } 6253 6254 // save buffers sent to the surface so we can get render time when they return 6255 int64_t mediaTimeUs = -1; 6256 buffer->meta()->findInt64("timeUs", &mediaTimeUs); 6257 if (mediaTimeUs >= 0) { 6258 mCodec->mRenderTracker.onFrameQueued( 6259 mediaTimeUs, info->mGraphicBuffer, new Fence(::dup(info->mFenceFd))); 6260 } 6261 6262 int64_t timestampNs = 0; 6263 if (!msg->findInt64("timestampNs", ×tampNs)) { 6264 // use media timestamp if client did not request a specific render timestamp 6265 if (buffer->meta()->findInt64("timeUs", ×tampNs)) { 6266 ALOGV("using buffer PTS of %lld", (long long)timestampNs); 6267 timestampNs *= 1000; 6268 } 6269 } 6270 6271 status_t err; 6272 err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs); 6273 ALOGW_IF(err != NO_ERROR, "failed to set buffer timestamp: %d", err); 6274 6275 info->checkReadFence("onOutputBufferDrained before queueBuffer"); 6276 err = mCodec->mNativeWindow->queueBuffer( 6277 mCodec->mNativeWindow.get(), info->mGraphicBuffer.get(), info->mFenceFd); 6278 info->mFenceFd = -1; 6279 if (err == OK) { 6280 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 6281 } else { 6282 ALOGE("queueBuffer failed in onOutputBufferDrained: %d", err); 6283 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6284 info->mStatus = BufferInfo::OWNED_BY_US; 6285 // keeping read fence as write fence to avoid clobbering 6286 info->mIsReadFence = false; 6287 } 6288 } else { 6289 if (mCodec->mNativeWindow != NULL && (discarded || buffer->size() != 0)) { 6290 // move read fence into write fence to avoid clobbering 6291 info->mIsReadFence = false; 6292 ATRACE_NAME("frame-drop"); 6293 } 6294 info->mStatus = BufferInfo::OWNED_BY_US; 6295 } 6296 6297 PortMode mode = getPortMode(kPortIndexOutput); 6298 6299 switch (mode) { 6300 case KEEP_BUFFERS: 6301 { 6302 // XXX fishy, revisit!!! What about the FREE_BUFFERS case below? 6303 6304 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 6305 // We cannot resubmit the buffer we just rendered, dequeue 6306 // the spare instead. 6307 6308 info = mCodec->dequeueBufferFromNativeWindow(); 6309 } 6310 break; 6311 } 6312 6313 case RESUBMIT_BUFFERS: 6314 { 6315 if (!mCodec->mPortEOS[kPortIndexOutput]) { 6316 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 6317 // We cannot resubmit the buffer we just rendered, dequeue 6318 // the spare instead. 6319 6320 info = mCodec->dequeueBufferFromNativeWindow(); 6321 } 6322 6323 if (info != NULL) { 6324 ALOGV("[%s] calling fillBuffer %u", 6325 mCodec->mComponentName.c_str(), info->mBufferID); 6326 info->checkWriteFence("onOutputBufferDrained::RESUBMIT_BUFFERS"); 6327 status_t err = mCodec->fillBuffer(info); 6328 if (err != OK) { 6329 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6330 } 6331 } 6332 } 6333 break; 6334 } 6335 6336 case FREE_BUFFERS: 6337 { 6338 status_t err = mCodec->freeBuffer(kPortIndexOutput, index); 6339 if (err != OK) { 6340 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6341 } 6342 break; 6343 } 6344 6345 default: 6346 ALOGE("Invalid port mode: %d", mode); 6347 return; 6348 } 6349} 6350 6351//////////////////////////////////////////////////////////////////////////////// 6352 6353ACodec::UninitializedState::UninitializedState(ACodec *codec) 6354 : BaseState(codec) { 6355} 6356 6357void ACodec::UninitializedState::stateEntered() { 6358 ALOGV("Now uninitialized"); 6359 6360 if (mDeathNotifier != NULL) { 6361 if (mCodec->mOMXNode != NULL) { 6362 auto tOmxNode = mCodec->mOMXNode->getHalInterface(); 6363 tOmxNode->unlinkToDeath(mDeathNotifier); 6364 } 6365 mDeathNotifier.clear(); 6366 } 6367 6368 mCodec->mUsingNativeWindow = false; 6369 mCodec->mNativeWindow.clear(); 6370 mCodec->mNativeWindowUsageBits = 0; 6371 mCodec->mOMX.clear(); 6372 mCodec->mOMXNode.clear(); 6373 mCodec->mFlags = 0; 6374 mCodec->mPortMode[kPortIndexInput] = IOMX::kPortModePresetByteBuffer; 6375 mCodec->mPortMode[kPortIndexOutput] = IOMX::kPortModePresetByteBuffer; 6376 mCodec->mConverter[0].clear(); 6377 mCodec->mConverter[1].clear(); 6378 mCodec->mComponentName.clear(); 6379} 6380 6381bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) { 6382 bool handled = false; 6383 6384 switch (msg->what()) { 6385 case ACodec::kWhatSetup: 6386 { 6387 onSetup(msg); 6388 6389 handled = true; 6390 break; 6391 } 6392 6393 case ACodec::kWhatAllocateComponent: 6394 { 6395 onAllocateComponent(msg); 6396 handled = true; 6397 break; 6398 } 6399 6400 case ACodec::kWhatShutdown: 6401 { 6402 int32_t keepComponentAllocated; 6403 CHECK(msg->findInt32( 6404 "keepComponentAllocated", &keepComponentAllocated)); 6405 ALOGW_IF(keepComponentAllocated, 6406 "cannot keep component allocated on shutdown in Uninitialized state"); 6407 if (keepComponentAllocated) { 6408 mCodec->mCallback->onStopCompleted(); 6409 } else { 6410 mCodec->mCallback->onReleaseCompleted(); 6411 } 6412 handled = true; 6413 break; 6414 } 6415 6416 case ACodec::kWhatFlush: 6417 { 6418 mCodec->mCallback->onFlushCompleted(); 6419 handled = true; 6420 break; 6421 } 6422 6423 case ACodec::kWhatReleaseCodecInstance: 6424 { 6425 // nothing to do, as we have already signaled shutdown 6426 handled = true; 6427 break; 6428 } 6429 6430 default: 6431 return BaseState::onMessageReceived(msg); 6432 } 6433 6434 return handled; 6435} 6436 6437void ACodec::UninitializedState::onSetup( 6438 const sp<AMessage> &msg) { 6439 if (onAllocateComponent(msg) 6440 && mCodec->mLoadedState->onConfigureComponent(msg)) { 6441 mCodec->mLoadedState->onStart(); 6442 } 6443} 6444 6445bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) { 6446 ALOGV("onAllocateComponent"); 6447 6448 CHECK(mCodec->mOMXNode == NULL); 6449 6450 sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec); 6451 6452 sp<RefBase> obj; 6453 CHECK(msg->findObject("codecInfo", &obj)); 6454 sp<MediaCodecInfo> info = (MediaCodecInfo *)obj.get(); 6455 if (info == nullptr) { 6456 ALOGE("Unexpected nullptr for codec information"); 6457 mCodec->signalError(OMX_ErrorUndefined, UNKNOWN_ERROR); 6458 return false; 6459 } 6460 AString owner = (info->getOwnerName() == nullptr) ? "default" : info->getOwnerName(); 6461 6462 AString componentName; 6463 CHECK(msg->findString("componentName", &componentName)); 6464 6465 sp<CodecObserver> observer = new CodecObserver; 6466 sp<IOMX> omx; 6467 sp<IOMXNode> omxNode; 6468 6469 status_t err = NAME_NOT_FOUND; 6470 OMXClient client; 6471 if (client.connect(owner.c_str()) != OK) { 6472 mCodec->signalError(OMX_ErrorUndefined, NO_INIT); 6473 return false; 6474 } 6475 omx = client.interface(); 6476 6477 pid_t tid = gettid(); 6478 int prevPriority = androidGetThreadPriority(tid); 6479 androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND); 6480 err = omx->allocateNode(componentName.c_str(), observer, &omxNode); 6481 androidSetThreadPriority(tid, prevPriority); 6482 6483 if (err != OK) { 6484 ALOGE("Unable to instantiate codec '%s' with err %#x.", componentName.c_str(), err); 6485 6486 mCodec->signalError((OMX_ERRORTYPE)err, makeNoSideEffectStatus(err)); 6487 return false; 6488 } 6489 6490 mDeathNotifier = new DeathNotifier(notify); 6491 auto tOmxNode = omxNode->getHalInterface(); 6492 if (!tOmxNode->linkToDeath(mDeathNotifier, 0)) { 6493 mDeathNotifier.clear(); 6494 } 6495 6496 notify = new AMessage(kWhatOMXMessageList, mCodec); 6497 notify->setInt32("generation", ++mCodec->mNodeGeneration); 6498 observer->setNotificationMessage(notify); 6499 6500 mCodec->mComponentName = componentName; 6501 mCodec->mRenderTracker.setComponentName(componentName); 6502 mCodec->mFlags = 0; 6503 6504 if (componentName.endsWith(".secure")) { 6505 mCodec->mFlags |= kFlagIsSecure; 6506 mCodec->mFlags |= kFlagIsGrallocUsageProtected; 6507 mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown; 6508 } 6509 6510 mCodec->mOMX = omx; 6511 mCodec->mOMXNode = omxNode; 6512 mCodec->mCallback->onComponentAllocated(mCodec->mComponentName.c_str()); 6513 mCodec->changeState(mCodec->mLoadedState); 6514 6515 return true; 6516} 6517 6518//////////////////////////////////////////////////////////////////////////////// 6519 6520ACodec::LoadedState::LoadedState(ACodec *codec) 6521 : BaseState(codec) { 6522} 6523 6524void ACodec::LoadedState::stateEntered() { 6525 ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str()); 6526 6527 mCodec->mPortEOS[kPortIndexInput] = 6528 mCodec->mPortEOS[kPortIndexOutput] = false; 6529 6530 mCodec->mInputEOSResult = OK; 6531 6532 mCodec->mDequeueCounter = 0; 6533 mCodec->mMetadataBuffersToSubmit = 0; 6534 mCodec->mRepeatFrameDelayUs = -1ll; 6535 mCodec->mInputFormat.clear(); 6536 mCodec->mOutputFormat.clear(); 6537 mCodec->mBaseOutputFormat.clear(); 6538 mCodec->mGraphicBufferSource.clear(); 6539 6540 if (mCodec->mShutdownInProgress) { 6541 bool keepComponentAllocated = mCodec->mKeepComponentAllocated; 6542 6543 mCodec->mShutdownInProgress = false; 6544 mCodec->mKeepComponentAllocated = false; 6545 6546 onShutdown(keepComponentAllocated); 6547 } 6548 mCodec->mExplicitShutdown = false; 6549 6550 mCodec->processDeferredMessages(); 6551} 6552 6553void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) { 6554 if (!keepComponentAllocated) { 6555 (void)mCodec->mOMXNode->freeNode(); 6556 6557 mCodec->changeState(mCodec->mUninitializedState); 6558 } 6559 6560 if (mCodec->mExplicitShutdown) { 6561 if (keepComponentAllocated) { 6562 mCodec->mCallback->onStopCompleted(); 6563 } else { 6564 mCodec->mCallback->onReleaseCompleted(); 6565 } 6566 mCodec->mExplicitShutdown = false; 6567 } 6568} 6569 6570bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) { 6571 bool handled = false; 6572 6573 switch (msg->what()) { 6574 case ACodec::kWhatConfigureComponent: 6575 { 6576 onConfigureComponent(msg); 6577 handled = true; 6578 break; 6579 } 6580 6581 case ACodec::kWhatCreateInputSurface: 6582 { 6583 onCreateInputSurface(msg); 6584 handled = true; 6585 break; 6586 } 6587 6588 case ACodec::kWhatSetInputSurface: 6589 { 6590 onSetInputSurface(msg); 6591 handled = true; 6592 break; 6593 } 6594 6595 case ACodec::kWhatStart: 6596 { 6597 onStart(); 6598 handled = true; 6599 break; 6600 } 6601 6602 case ACodec::kWhatShutdown: 6603 { 6604 int32_t keepComponentAllocated; 6605 CHECK(msg->findInt32( 6606 "keepComponentAllocated", &keepComponentAllocated)); 6607 6608 mCodec->mExplicitShutdown = true; 6609 onShutdown(keepComponentAllocated); 6610 6611 handled = true; 6612 break; 6613 } 6614 6615 case ACodec::kWhatFlush: 6616 { 6617 mCodec->mCallback->onFlushCompleted(); 6618 handled = true; 6619 break; 6620 } 6621 6622 default: 6623 return BaseState::onMessageReceived(msg); 6624 } 6625 6626 return handled; 6627} 6628 6629bool ACodec::LoadedState::onConfigureComponent( 6630 const sp<AMessage> &msg) { 6631 ALOGV("onConfigureComponent"); 6632 6633 CHECK(mCodec->mOMXNode != NULL); 6634 6635 status_t err = OK; 6636 AString mime; 6637 if (!msg->findString("mime", &mime)) { 6638 err = BAD_VALUE; 6639 } else { 6640 err = mCodec->configureCodec(mime.c_str(), msg); 6641 } 6642 if (err != OK) { 6643 ALOGE("[%s] configureCodec returning error %d", 6644 mCodec->mComponentName.c_str(), err); 6645 6646 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6647 return false; 6648 } 6649 6650 mCodec->mCallback->onComponentConfigured(mCodec->mInputFormat, mCodec->mOutputFormat); 6651 6652 return true; 6653} 6654 6655status_t ACodec::LoadedState::setupInputSurface() { 6656 if (mCodec->mGraphicBufferSource == NULL) { 6657 return BAD_VALUE; 6658 } 6659 6660 android_dataspace dataSpace; 6661 status_t err = 6662 mCodec->setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace(&dataSpace); 6663 if (err != OK) { 6664 ALOGE("Failed to get default data space"); 6665 return err; 6666 } 6667 6668 err = statusFromBinderStatus( 6669 mCodec->mGraphicBufferSource->configure(mCodec->mOMXNode, dataSpace)); 6670 if (err != OK) { 6671 ALOGE("[%s] Unable to configure for node (err %d)", 6672 mCodec->mComponentName.c_str(), err); 6673 return err; 6674 } 6675 6676 if (mCodec->mRepeatFrameDelayUs > 0ll) { 6677 err = statusFromBinderStatus( 6678 mCodec->mGraphicBufferSource->setRepeatPreviousFrameDelayUs( 6679 mCodec->mRepeatFrameDelayUs)); 6680 6681 if (err != OK) { 6682 ALOGE("[%s] Unable to configure option to repeat previous " 6683 "frames (err %d)", 6684 mCodec->mComponentName.c_str(), err); 6685 return err; 6686 } 6687 } 6688 6689 if (mCodec->mMaxPtsGapUs > 0ll) { 6690 OMX_PARAM_U32TYPE maxPtsGapParams; 6691 InitOMXParams(&maxPtsGapParams); 6692 maxPtsGapParams.nPortIndex = kPortIndexInput; 6693 maxPtsGapParams.nU32 = (uint32_t) mCodec->mMaxPtsGapUs; 6694 6695 err = mCodec->mOMXNode->setParameter( 6696 (OMX_INDEXTYPE)OMX_IndexParamMaxFrameDurationForBitrateControl, 6697 &maxPtsGapParams, sizeof(maxPtsGapParams)); 6698 6699 if (err != OK) { 6700 ALOGE("[%s] Unable to configure max timestamp gap (err %d)", 6701 mCodec->mComponentName.c_str(), err); 6702 return err; 6703 } 6704 } 6705 6706 if (mCodec->mMaxFps > 0) { 6707 err = statusFromBinderStatus( 6708 mCodec->mGraphicBufferSource->setMaxFps(mCodec->mMaxFps)); 6709 6710 if (err != OK) { 6711 ALOGE("[%s] Unable to configure max fps (err %d)", 6712 mCodec->mComponentName.c_str(), err); 6713 return err; 6714 } 6715 } 6716 6717 if (mCodec->mCaptureFps > 0. && mCodec->mFps > 0.) { 6718 err = statusFromBinderStatus( 6719 mCodec->mGraphicBufferSource->setTimeLapseConfig( 6720 mCodec->mFps, mCodec->mCaptureFps)); 6721 6722 if (err != OK) { 6723 ALOGE("[%s] Unable to configure time lapse (err %d)", 6724 mCodec->mComponentName.c_str(), err); 6725 return err; 6726 } 6727 } 6728 6729 if (mCodec->mCreateInputBuffersSuspended) { 6730 err = statusFromBinderStatus( 6731 mCodec->mGraphicBufferSource->setSuspend(true, -1)); 6732 6733 if (err != OK) { 6734 ALOGE("[%s] Unable to configure option to suspend (err %d)", 6735 mCodec->mComponentName.c_str(), err); 6736 return err; 6737 } 6738 } 6739 6740 uint32_t usageBits; 6741 if (mCodec->mOMXNode->getParameter( 6742 (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits, 6743 &usageBits, sizeof(usageBits)) == OK) { 6744 mCodec->mInputFormat->setInt32( 6745 "using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN)); 6746 } 6747 6748 sp<ABuffer> colorAspectsBuffer; 6749 if (mCodec->mInputFormat->findBuffer("android._color-aspects", &colorAspectsBuffer)) { 6750 if (colorAspectsBuffer->size() != sizeof(ColorAspects)) { 6751 return INVALID_OPERATION; 6752 } 6753 6754 err = statusFromBinderStatus( 6755 mCodec->mGraphicBufferSource->setColorAspects(ColorUtils::packToU32( 6756 *(ColorAspects *)colorAspectsBuffer->base()))); 6757 6758 if (err != OK) { 6759 ALOGE("[%s] Unable to configure color aspects (err %d)", 6760 mCodec->mComponentName.c_str(), err); 6761 return err; 6762 } 6763 } 6764 return OK; 6765} 6766 6767void ACodec::LoadedState::onCreateInputSurface( 6768 const sp<AMessage> & /* msg */) { 6769 ALOGV("onCreateInputSurface"); 6770 6771 sp<IGraphicBufferProducer> bufferProducer; 6772 status_t err = mCodec->mOMX->createInputSurface( 6773 &bufferProducer, &mCodec->mGraphicBufferSource); 6774 6775 if (err == OK) { 6776 err = setupInputSurface(); 6777 } 6778 6779 if (err == OK) { 6780 mCodec->mCallback->onInputSurfaceCreated( 6781 mCodec->mInputFormat, 6782 mCodec->mOutputFormat, 6783 new BufferProducerWrapper(bufferProducer)); 6784 } else { 6785 // Can't use mCodec->signalError() here -- MediaCodec won't forward 6786 // the error through because it's in the "configured" state. We 6787 // send a kWhatInputSurfaceCreated with an error value instead. 6788 ALOGE("[%s] onCreateInputSurface returning error %d", 6789 mCodec->mComponentName.c_str(), err); 6790 mCodec->mCallback->onInputSurfaceCreationFailed(err); 6791 } 6792} 6793 6794void ACodec::LoadedState::onSetInputSurface(const sp<AMessage> &msg) { 6795 ALOGV("onSetInputSurface"); 6796 6797 sp<RefBase> obj; 6798 CHECK(msg->findObject("input-surface", &obj)); 6799 if (obj == NULL) { 6800 ALOGE("[%s] NULL input surface", mCodec->mComponentName.c_str()); 6801 mCodec->mCallback->onInputSurfaceDeclined(BAD_VALUE); 6802 return; 6803 } 6804 6805 sp<PersistentSurface> surface = static_cast<PersistentSurface *>(obj.get()); 6806 mCodec->mGraphicBufferSource = surface->getBufferSource(); 6807 status_t err = setupInputSurface(); 6808 6809 if (err == OK) { 6810 mCodec->mCallback->onInputSurfaceAccepted( 6811 mCodec->mInputFormat, mCodec->mOutputFormat); 6812 } else { 6813 // Can't use mCodec->signalError() here -- MediaCodec won't forward 6814 // the error through because it's in the "configured" state. We 6815 // send a kWhatInputSurfaceAccepted with an error value instead. 6816 ALOGE("[%s] onSetInputSurface returning error %d", 6817 mCodec->mComponentName.c_str(), err); 6818 mCodec->mCallback->onInputSurfaceDeclined(err); 6819 } 6820} 6821 6822void ACodec::LoadedState::onStart() { 6823 ALOGV("onStart"); 6824 6825 status_t err = mCodec->mOMXNode->sendCommand(OMX_CommandStateSet, OMX_StateIdle); 6826 if (err != OK) { 6827 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6828 } else { 6829 mCodec->changeState(mCodec->mLoadedToIdleState); 6830 } 6831} 6832 6833//////////////////////////////////////////////////////////////////////////////// 6834 6835ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec) 6836 : BaseState(codec) { 6837} 6838 6839void ACodec::LoadedToIdleState::stateEntered() { 6840 ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str()); 6841 6842 status_t err; 6843 if ((err = allocateBuffers()) != OK) { 6844 ALOGE("Failed to allocate buffers after transitioning to IDLE state " 6845 "(error 0x%08x)", 6846 err); 6847 6848 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6849 6850 mCodec->mOMXNode->sendCommand( 6851 OMX_CommandStateSet, OMX_StateLoaded); 6852 if (mCodec->allYourBuffersAreBelongToUs(kPortIndexInput)) { 6853 mCodec->freeBuffersOnPort(kPortIndexInput); 6854 } 6855 if (mCodec->allYourBuffersAreBelongToUs(kPortIndexOutput)) { 6856 mCodec->freeBuffersOnPort(kPortIndexOutput); 6857 } 6858 6859 mCodec->changeState(mCodec->mLoadedState); 6860 } 6861} 6862 6863status_t ACodec::LoadedToIdleState::allocateBuffers() { 6864 status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput); 6865 if (err != OK) { 6866 return err; 6867 } 6868 6869 err = mCodec->allocateBuffersOnPort(kPortIndexOutput); 6870 if (err != OK) { 6871 return err; 6872 } 6873 6874 mCodec->mCallback->onStartCompleted(); 6875 6876 return OK; 6877} 6878 6879bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) { 6880 switch (msg->what()) { 6881 case kWhatSetParameters: 6882 case kWhatShutdown: 6883 { 6884 mCodec->deferMessage(msg); 6885 return true; 6886 } 6887 6888 case kWhatSignalEndOfInputStream: 6889 { 6890 mCodec->onSignalEndOfInputStream(); 6891 return true; 6892 } 6893 6894 case kWhatResume: 6895 { 6896 // We'll be active soon enough. 6897 return true; 6898 } 6899 6900 case kWhatFlush: 6901 { 6902 // We haven't even started yet, so we're flushed alright... 6903 mCodec->mCallback->onFlushCompleted(); 6904 return true; 6905 } 6906 6907 default: 6908 return BaseState::onMessageReceived(msg); 6909 } 6910} 6911 6912bool ACodec::LoadedToIdleState::onOMXEvent( 6913 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 6914 switch (event) { 6915 case OMX_EventCmdComplete: 6916 { 6917 status_t err = OK; 6918 if (data1 != (OMX_U32)OMX_CommandStateSet 6919 || data2 != (OMX_U32)OMX_StateIdle) { 6920 ALOGE("Unexpected command completion in LoadedToIdleState: %s(%u) %s(%u)", 6921 asString((OMX_COMMANDTYPE)data1), data1, 6922 asString((OMX_STATETYPE)data2), data2); 6923 err = FAILED_TRANSACTION; 6924 } 6925 6926 if (err == OK) { 6927 err = mCodec->mOMXNode->sendCommand( 6928 OMX_CommandStateSet, OMX_StateExecuting); 6929 } 6930 6931 if (err != OK) { 6932 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6933 } else { 6934 mCodec->changeState(mCodec->mIdleToExecutingState); 6935 } 6936 6937 return true; 6938 } 6939 6940 default: 6941 return BaseState::onOMXEvent(event, data1, data2); 6942 } 6943} 6944 6945//////////////////////////////////////////////////////////////////////////////// 6946 6947ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec) 6948 : BaseState(codec) { 6949} 6950 6951void ACodec::IdleToExecutingState::stateEntered() { 6952 ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str()); 6953} 6954 6955bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) { 6956 switch (msg->what()) { 6957 case kWhatSetParameters: 6958 case kWhatShutdown: 6959 { 6960 mCodec->deferMessage(msg); 6961 return true; 6962 } 6963 6964 case kWhatResume: 6965 { 6966 // We'll be active soon enough. 6967 return true; 6968 } 6969 6970 case kWhatFlush: 6971 { 6972 // We haven't even started yet, so we're flushed alright... 6973 mCodec->mCallback->onFlushCompleted(); 6974 return true; 6975 } 6976 6977 case kWhatSignalEndOfInputStream: 6978 { 6979 mCodec->onSignalEndOfInputStream(); 6980 return true; 6981 } 6982 6983 default: 6984 return BaseState::onMessageReceived(msg); 6985 } 6986} 6987 6988bool ACodec::IdleToExecutingState::onOMXEvent( 6989 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 6990 switch (event) { 6991 case OMX_EventCmdComplete: 6992 { 6993 if (data1 != (OMX_U32)OMX_CommandStateSet 6994 || data2 != (OMX_U32)OMX_StateExecuting) { 6995 ALOGE("Unexpected command completion in IdleToExecutingState: %s(%u) %s(%u)", 6996 asString((OMX_COMMANDTYPE)data1), data1, 6997 asString((OMX_STATETYPE)data2), data2); 6998 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6999 return true; 7000 } 7001 7002 mCodec->mExecutingState->resume(); 7003 mCodec->changeState(mCodec->mExecutingState); 7004 7005 return true; 7006 } 7007 7008 default: 7009 return BaseState::onOMXEvent(event, data1, data2); 7010 } 7011} 7012 7013//////////////////////////////////////////////////////////////////////////////// 7014 7015ACodec::ExecutingState::ExecutingState(ACodec *codec) 7016 : BaseState(codec), 7017 mActive(false) { 7018} 7019 7020ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode( 7021 OMX_U32 /* portIndex */) { 7022 return RESUBMIT_BUFFERS; 7023} 7024 7025void ACodec::ExecutingState::submitOutputMetaBuffers() { 7026 // submit as many buffers as there are input buffers with the codec 7027 // in case we are in port reconfiguring 7028 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 7029 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 7030 7031 if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) { 7032 if (mCodec->submitOutputMetadataBuffer() != OK) 7033 break; 7034 } 7035 } 7036 7037 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** 7038 mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround(); 7039} 7040 7041void ACodec::ExecutingState::submitRegularOutputBuffers() { 7042 bool failed = false; 7043 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) { 7044 BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i); 7045 7046 if (mCodec->mNativeWindow != NULL) { 7047 if (info->mStatus != BufferInfo::OWNED_BY_US 7048 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) { 7049 ALOGE("buffers should be owned by us or the surface"); 7050 failed = true; 7051 break; 7052 } 7053 7054 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 7055 continue; 7056 } 7057 } else { 7058 if (info->mStatus != BufferInfo::OWNED_BY_US) { 7059 ALOGE("buffers should be owned by us"); 7060 failed = true; 7061 break; 7062 } 7063 } 7064 7065 ALOGV("[%s] calling fillBuffer %u", mCodec->mComponentName.c_str(), info->mBufferID); 7066 7067 info->checkWriteFence("submitRegularOutputBuffers"); 7068 status_t err = mCodec->fillBuffer(info); 7069 if (err != OK) { 7070 failed = true; 7071 break; 7072 } 7073 } 7074 7075 if (failed) { 7076 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 7077 } 7078} 7079 7080void ACodec::ExecutingState::submitOutputBuffers() { 7081 submitRegularOutputBuffers(); 7082 if (mCodec->storingMetadataInDecodedBuffers()) { 7083 submitOutputMetaBuffers(); 7084 } 7085} 7086 7087void ACodec::ExecutingState::resume() { 7088 if (mActive) { 7089 ALOGV("[%s] We're already active, no need to resume.", mCodec->mComponentName.c_str()); 7090 return; 7091 } 7092 7093 submitOutputBuffers(); 7094 7095 // Post all available input buffers 7096 if (mCodec->mBuffers[kPortIndexInput].size() == 0u) { 7097 ALOGW("[%s] we don't have any input buffers to resume", mCodec->mComponentName.c_str()); 7098 } 7099 7100 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) { 7101 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 7102 if (info->mStatus == BufferInfo::OWNED_BY_US) { 7103 postFillThisBuffer(info); 7104 } 7105 } 7106 7107 mActive = true; 7108} 7109 7110void ACodec::ExecutingState::stateEntered() { 7111 ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str()); 7112 mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC)); 7113 mCodec->processDeferredMessages(); 7114} 7115 7116bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) { 7117 bool handled = false; 7118 7119 switch (msg->what()) { 7120 case kWhatShutdown: 7121 { 7122 int32_t keepComponentAllocated; 7123 CHECK(msg->findInt32( 7124 "keepComponentAllocated", &keepComponentAllocated)); 7125 7126 mCodec->mShutdownInProgress = true; 7127 mCodec->mExplicitShutdown = true; 7128 mCodec->mKeepComponentAllocated = keepComponentAllocated; 7129 7130 mActive = false; 7131 7132 status_t err = mCodec->mOMXNode->sendCommand( 7133 OMX_CommandStateSet, OMX_StateIdle); 7134 if (err != OK) { 7135 if (keepComponentAllocated) { 7136 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 7137 } 7138 // TODO: do some recovery here. 7139 } else { 7140 mCodec->changeState(mCodec->mExecutingToIdleState); 7141 } 7142 7143 handled = true; 7144 break; 7145 } 7146 7147 case kWhatFlush: 7148 { 7149 ALOGV("[%s] ExecutingState flushing now " 7150 "(codec owns %zu/%zu input, %zu/%zu output).", 7151 mCodec->mComponentName.c_str(), 7152 mCodec->countBuffersOwnedByComponent(kPortIndexInput), 7153 mCodec->mBuffers[kPortIndexInput].size(), 7154 mCodec->countBuffersOwnedByComponent(kPortIndexOutput), 7155 mCodec->mBuffers[kPortIndexOutput].size()); 7156 7157 mActive = false; 7158 7159 status_t err = mCodec->mOMXNode->sendCommand(OMX_CommandFlush, OMX_ALL); 7160 if (err != OK) { 7161 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 7162 } else { 7163 mCodec->changeState(mCodec->mFlushingState); 7164 } 7165 7166 handled = true; 7167 break; 7168 } 7169 7170 case kWhatResume: 7171 { 7172 resume(); 7173 7174 handled = true; 7175 break; 7176 } 7177 7178 case kWhatRequestIDRFrame: 7179 { 7180 status_t err = mCodec->requestIDRFrame(); 7181 if (err != OK) { 7182 ALOGW("Requesting an IDR frame failed."); 7183 } 7184 7185 handled = true; 7186 break; 7187 } 7188 7189 case kWhatSetParameters: 7190 { 7191 sp<AMessage> params; 7192 CHECK(msg->findMessage("params", ¶ms)); 7193 7194 status_t err = mCodec->setParameters(params); 7195 7196 sp<AMessage> reply; 7197 if (msg->findMessage("reply", &reply)) { 7198 reply->setInt32("err", err); 7199 reply->post(); 7200 } 7201 7202 handled = true; 7203 break; 7204 } 7205 7206 case ACodec::kWhatSignalEndOfInputStream: 7207 { 7208 mCodec->onSignalEndOfInputStream(); 7209 handled = true; 7210 break; 7211 } 7212 7213 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** 7214 case kWhatSubmitOutputMetadataBufferIfEOS: 7215 { 7216 if (mCodec->mPortEOS[kPortIndexInput] && 7217 !mCodec->mPortEOS[kPortIndexOutput]) { 7218 status_t err = mCodec->submitOutputMetadataBuffer(); 7219 if (err == OK) { 7220 mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround(); 7221 } 7222 } 7223 return true; 7224 } 7225 7226 default: 7227 handled = BaseState::onMessageReceived(msg); 7228 break; 7229 } 7230 7231 return handled; 7232} 7233 7234status_t ACodec::setParameters(const sp<AMessage> ¶ms) { 7235 int32_t videoBitrate; 7236 if (params->findInt32("video-bitrate", &videoBitrate)) { 7237 OMX_VIDEO_CONFIG_BITRATETYPE configParams; 7238 InitOMXParams(&configParams); 7239 configParams.nPortIndex = kPortIndexOutput; 7240 configParams.nEncodeBitrate = videoBitrate; 7241 7242 status_t err = mOMXNode->setConfig( 7243 OMX_IndexConfigVideoBitrate, 7244 &configParams, 7245 sizeof(configParams)); 7246 7247 if (err != OK) { 7248 ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d", 7249 videoBitrate, err); 7250 7251 return err; 7252 } 7253 } 7254 7255 int64_t timeOffsetUs; 7256 if (params->findInt64("time-offset-us", &timeOffsetUs)) { 7257 if (mGraphicBufferSource == NULL) { 7258 ALOGE("[%s] Invalid to set input buffer time offset without surface", 7259 mComponentName.c_str()); 7260 return INVALID_OPERATION; 7261 } 7262 7263 status_t err = statusFromBinderStatus( 7264 mGraphicBufferSource->setTimeOffsetUs(timeOffsetUs)); 7265 7266 if (err != OK) { 7267 ALOGE("[%s] Unable to set input buffer time offset (err %d)", 7268 mComponentName.c_str(), 7269 err); 7270 return err; 7271 } 7272 } 7273 7274 int64_t skipFramesBeforeUs; 7275 if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) { 7276 if (mGraphicBufferSource == NULL) { 7277 ALOGE("[%s] Invalid to set start time without surface", 7278 mComponentName.c_str()); 7279 return INVALID_OPERATION; 7280 } 7281 7282 status_t err = statusFromBinderStatus( 7283 mGraphicBufferSource->setStartTimeUs(skipFramesBeforeUs)); 7284 7285 if (err != OK) { 7286 ALOGE("Failed to set parameter 'skip-frames-before' (err %d)", err); 7287 return err; 7288 } 7289 } 7290 7291 int32_t dropInputFrames; 7292 if (params->findInt32("drop-input-frames", &dropInputFrames)) { 7293 if (mGraphicBufferSource == NULL) { 7294 ALOGE("[%s] Invalid to set suspend without surface", 7295 mComponentName.c_str()); 7296 return INVALID_OPERATION; 7297 } 7298 7299 int64_t suspendStartTimeUs = -1; 7300 (void) params->findInt64("drop-start-time-us", &suspendStartTimeUs); 7301 status_t err = statusFromBinderStatus( 7302 mGraphicBufferSource->setSuspend(dropInputFrames != 0, suspendStartTimeUs)); 7303 7304 if (err != OK) { 7305 ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err); 7306 return err; 7307 } 7308 } 7309 7310 int64_t stopTimeUs; 7311 if (params->findInt64("stop-time-us", &stopTimeUs)) { 7312 if (mGraphicBufferSource == NULL) { 7313 ALOGE("[%s] Invalid to set stop time without surface", 7314 mComponentName.c_str()); 7315 return INVALID_OPERATION; 7316 } 7317 status_t err = statusFromBinderStatus( 7318 mGraphicBufferSource->setStopTimeUs(stopTimeUs)); 7319 7320 if (err != OK) { 7321 ALOGE("Failed to set parameter 'stop-time-us' (err %d)", err); 7322 return err; 7323 } 7324 7325 int64_t stopTimeOffsetUs; 7326 err = statusFromBinderStatus( 7327 mGraphicBufferSource->getStopTimeOffsetUs(&stopTimeOffsetUs)); 7328 7329 if (err != OK) { 7330 ALOGE("Failed to get stop time offset (err %d)", err); 7331 return err; 7332 } 7333 mInputFormat->setInt64("android._stop-time-offset-us", stopTimeOffsetUs); 7334 } 7335 7336 int32_t dummy; 7337 if (params->findInt32("request-sync", &dummy)) { 7338 status_t err = requestIDRFrame(); 7339 7340 if (err != OK) { 7341 ALOGE("Requesting a sync frame failed w/ err %d", err); 7342 return err; 7343 } 7344 } 7345 7346 int32_t rateInt = -1; 7347 float rateFloat = -1; 7348 if (!params->findFloat("operating-rate", &rateFloat)) { 7349 params->findInt32("operating-rate", &rateInt); 7350 rateFloat = (float) rateInt; // 16MHz (FLINTMAX) is OK for upper bound. 7351 } 7352 if (rateFloat > 0) { 7353 status_t err = setOperatingRate(rateFloat, mIsVideo); 7354 if (err != OK) { 7355 ALOGI("Failed to set parameter 'operating-rate' (err %d)", err); 7356 } 7357 } 7358 7359 int32_t intraRefreshPeriod = 0; 7360 if (params->findInt32("intra-refresh-period", &intraRefreshPeriod) 7361 && intraRefreshPeriod > 0) { 7362 status_t err = setIntraRefreshPeriod(intraRefreshPeriod, false); 7363 if (err != OK) { 7364 ALOGI("[%s] failed setIntraRefreshPeriod. Failure is fine since this key is optional", 7365 mComponentName.c_str()); 7366 err = OK; 7367 } 7368 } 7369 7370 int32_t latency = 0; 7371 if (params->findInt32("latency", &latency) && latency > 0) { 7372 status_t err = setLatency(latency); 7373 if (err != OK) { 7374 ALOGI("[%s] failed setLatency. Failure is fine since this key is optional", 7375 mComponentName.c_str()); 7376 err = OK; 7377 } 7378 } 7379 7380 // Ignore errors as failure is expected for codecs that aren't video encoders. 7381 (void)configureTemporalLayers(params, false /* inConfigure */, mOutputFormat); 7382 7383 return setVendorParameters(params); 7384} 7385 7386// Removes trailing tags matching |tag| from |key| (e.g. a settings name). |minLength| specifies 7387// the minimum number of characters to keep in |key| (even if it has trailing tags). 7388// (Used to remove trailing 'value' tags in settings names, e.g. to normalize 7389// 'vendor.settingsX.value' to 'vendor.settingsX') 7390static void removeTrailingTags(char *key, size_t minLength, const char *tag) { 7391 size_t length = strlen(key); 7392 size_t tagLength = strlen(tag); 7393 while (length > minLength + tagLength 7394 && !strcmp(key + length - tagLength, tag) 7395 && key[length - tagLength - 1] == '.') { 7396 length -= tagLength + 1; 7397 key[length] = '\0'; 7398 } 7399} 7400 7401/** 7402 * Struct encompassing a vendor extension config structure and a potential error status (in case 7403 * the structure is null). Used to iterate through vendor extensions. 7404 */ 7405struct VendorExtension { 7406 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *config; // structure does not own config 7407 status_t status; 7408 7409 // create based on an error status 7410 VendorExtension(status_t s_ = NO_INIT) : config(nullptr), status(s_) { } 7411 7412 // create based on a successfully retrieved config structure 7413 VendorExtension(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *c_) : config(c_), status(OK) { } 7414}; 7415 7416// class VendorExtensions; 7417/** 7418 * Forward iterator to enumerate vendor extensions supported by an OMX component. 7419 */ 7420class VendorExtensionIterator { 7421//private: 7422 static constexpr size_t kLastIndex = ~(size_t)0; // last index marker 7423 7424 sp<IOMXNode> mNode; // component 7425 size_t mIndex; // current android extension index 7426 std::unique_ptr<uint8_t[]> mBacking; // current extension's backing 7427 VendorExtension mCurrent; // current extension 7428 7429 VendorExtensionIterator(const sp<IOMXNode> &node, size_t index) 7430 : mNode(node), 7431 mIndex(index) { 7432 mCurrent = retrieve(); 7433 } 7434 7435 friend class VendorExtensions; 7436 7437public: 7438 // copy constructor 7439 VendorExtensionIterator(const VendorExtensionIterator &it) 7440 : VendorExtensionIterator(it.mNode, it.mIndex) { } 7441 7442 // retrieves the current extension pointed to by this iterator 7443 VendorExtension retrieve() { 7444 if (mIndex == kLastIndex) { 7445 return NO_INIT; 7446 } 7447 7448 // try with one param first, then retry if extension needs more than 1 param 7449 for (size_t paramSizeUsed = 1;; ) { 7450 if (paramSizeUsed > OMX_MAX_ANDROID_VENDOR_PARAMCOUNT) { 7451 return BAD_VALUE; // this prevents overflow in the following formula 7452 } 7453 7454 size_t size = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE) + 7455 (paramSizeUsed - 1) * sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE::param); 7456 mBacking.reset(new uint8_t[size]); 7457 if (!mBacking) { 7458 return NO_MEMORY; 7459 } 7460 7461 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *config = 7462 reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(mBacking.get()); 7463 7464 InitOMXParams(config); 7465 config->nSize = size; 7466 config->nIndex = mIndex; 7467 config->nParamSizeUsed = paramSizeUsed; 7468 status_t err = mNode->getConfig( 7469 (OMX_INDEXTYPE)OMX_IndexConfigAndroidVendorExtension, config, size); 7470 if (err == OK && config->nParamCount > paramSizeUsed && paramSizeUsed == 1) { 7471 // reallocate if we need a bigger config 7472 paramSizeUsed = config->nParamCount; 7473 continue; 7474 } else if (err == NOT_ENOUGH_DATA 7475 || (err != OK && mIndex == 0)) { 7476 // stop iterator on no-more signal, or if index is not at all supported 7477 mIndex = kLastIndex; 7478 return NO_INIT; 7479 } else if (err != OK) { 7480 return err; 7481 } else if (paramSizeUsed != config->nParamSizeUsed) { 7482 return BAD_VALUE; // component shall not modify size of nParam 7483 } 7484 7485 return config; 7486 } 7487 } 7488 7489 // returns extension pointed to by this iterator 7490 VendorExtension operator*() { 7491 return mCurrent; 7492 } 7493 7494 // prefix increment: move to next extension 7495 VendorExtensionIterator &operator++() { // prefix 7496 if (mIndex != kLastIndex) { 7497 ++mIndex; 7498 mCurrent = retrieve(); 7499 } 7500 return *this; 7501 } 7502 7503 // iterator equality operators 7504 bool operator==(const VendorExtensionIterator &o) { 7505 return mNode == o.mNode && mIndex == o.mIndex; 7506 } 7507 7508 bool operator!=(const VendorExtensionIterator &o) { 7509 return !(*this == o); 7510 } 7511}; 7512 7513/** 7514 * Iterable container for vendor extensions provided by a component 7515 */ 7516class VendorExtensions { 7517//private: 7518 sp<IOMXNode> mNode; 7519 7520public: 7521 VendorExtensions(const sp<IOMXNode> &node) 7522 : mNode(node) { 7523 } 7524 7525 VendorExtensionIterator begin() { 7526 return VendorExtensionIterator(mNode, 0); 7527 } 7528 7529 VendorExtensionIterator end() { 7530 return VendorExtensionIterator(mNode, VendorExtensionIterator::kLastIndex); 7531 } 7532}; 7533 7534status_t ACodec::setVendorParameters(const sp<AMessage> ¶ms) { 7535 std::map<std::string, std::string> vendorKeys; // maps reduced name to actual name 7536 constexpr char prefix[] = "vendor."; 7537 constexpr size_t prefixLength = sizeof(prefix) - 1; 7538 // longest possible vendor param name 7539 char reducedKey[OMX_MAX_STRINGNAME_SIZE + OMX_MAX_STRINGVALUE_SIZE]; 7540 7541 // identify all vendor keys to speed up search later and to detect vendor keys 7542 for (size_t i = params->countEntries(); i; --i) { 7543 AMessage::Type keyType; 7544 const char* key = params->getEntryNameAt(i - 1, &keyType); 7545 if (key != nullptr && !strncmp(key, prefix, prefixLength) 7546 // it is safe to limit format keys to the max vendor param size as we only 7547 // shorten parameter names by removing any trailing 'value' tags, and we 7548 // already remove the vendor prefix. 7549 && strlen(key + prefixLength) < sizeof(reducedKey) 7550 && (keyType == AMessage::kTypeInt32 7551 || keyType == AMessage::kTypeInt64 7552 || keyType == AMessage::kTypeString)) { 7553 strcpy(reducedKey, key + prefixLength); 7554 removeTrailingTags(reducedKey, 0, "value"); 7555 auto existingKey = vendorKeys.find(reducedKey); 7556 if (existingKey != vendorKeys.end()) { 7557 ALOGW("[%s] vendor parameter '%s' aliases parameter '%s'", 7558 mComponentName.c_str(), key, existingKey->second.c_str()); 7559 // ignore for now 7560 } 7561 vendorKeys.emplace(reducedKey, key); 7562 } 7563 } 7564 7565 // don't bother component if we don't have vendor extensions as they may not have implemented 7566 // the android vendor extension support, which will lead to unnecessary OMX failure logs. 7567 if (vendorKeys.empty()) { 7568 return OK; 7569 } 7570 7571 char key[sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE::cName) + 7572 sizeof(OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE::cKey)]; 7573 7574 status_t finalError = OK; 7575 7576 // don't try again if component does not have vendor extensions 7577 if (mVendorExtensionsStatus == kExtensionsNone) { 7578 return OK; 7579 } 7580 7581 for (VendorExtension ext : VendorExtensions(mOMXNode)) { 7582 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *config = ext.config; 7583 if (config == nullptr) { 7584 return ext.status; 7585 } 7586 7587 mVendorExtensionsStatus = kExtensionsExist; 7588 7589 config->cName[sizeof(config->cName) - 1] = '\0'; // null-terminate name 7590 strcpy(key, (const char *)config->cName); 7591 size_t nameLength = strlen(key); 7592 key[nameLength] = '.'; 7593 7594 // don't set vendor extension if client has not provided any of its parameters 7595 // or if client simply unsets parameters that are already unset 7596 bool needToSet = false; 7597 for (size_t paramIndex = 0; paramIndex < config->nParamCount; ++paramIndex) { 7598 // null-terminate param key 7599 config->param[paramIndex].cKey[sizeof(config->param[0].cKey) - 1] = '\0'; 7600 strcpy(key + nameLength + 1, (const char *)config->param[paramIndex].cKey); 7601 removeTrailingTags(key, nameLength, "value"); 7602 auto existingKey = vendorKeys.find(key); 7603 7604 // don't touch (e.g. change) parameters that are not specified by client 7605 if (existingKey == vendorKeys.end()) { 7606 continue; 7607 } 7608 7609 bool wasSet = config->param[paramIndex].bSet; 7610 switch (config->param[paramIndex].eValueType) { 7611 case OMX_AndroidVendorValueInt32: 7612 { 7613 int32_t value; 7614 config->param[paramIndex].bSet = 7615 (OMX_BOOL)params->findInt32(existingKey->second.c_str(), &value); 7616 if (config->param[paramIndex].bSet) { 7617 config->param[paramIndex].nInt32 = value; 7618 } 7619 break; 7620 } 7621 case OMX_AndroidVendorValueInt64: 7622 { 7623 int64_t value; 7624 config->param[paramIndex].bSet = 7625 (OMX_BOOL)params->findAsInt64(existingKey->second.c_str(), &value); 7626 if (config->param[paramIndex].bSet) { 7627 config->param[paramIndex].nInt64 = value; 7628 } 7629 break; 7630 } 7631 case OMX_AndroidVendorValueString: 7632 { 7633 AString value; 7634 config->param[paramIndex].bSet = 7635 (OMX_BOOL)params->findString(existingKey->second.c_str(), &value); 7636 if (config->param[paramIndex].bSet) { 7637 size_t dstSize = sizeof(config->param[paramIndex].cString); 7638 strncpy((char *)config->param[paramIndex].cString, value.c_str(), dstSize - 1); 7639 // null terminate value 7640 config->param[paramIndex].cString[dstSize - 1] = '\0'; 7641 } 7642 break; 7643 } 7644 default: 7645 ALOGW("[%s] vendor parameter '%s' is not a supported value", 7646 mComponentName.c_str(), key); 7647 continue; 7648 } 7649 if (config->param[paramIndex].bSet || wasSet) { 7650 needToSet = true; 7651 } 7652 } 7653 7654 if (needToSet) { 7655 status_t err = mOMXNode->setConfig( 7656 (OMX_INDEXTYPE)OMX_IndexConfigAndroidVendorExtension, 7657 config, config->nSize); 7658 if (err != OK) { 7659 key[nameLength] = '\0'; 7660 ALOGW("[%s] failed to set vendor extension '%s'", mComponentName.c_str(), key); 7661 // try to set each extension, and return first failure 7662 if (finalError == OK) { 7663 finalError = err; 7664 } 7665 } 7666 } 7667 } 7668 7669 if (mVendorExtensionsStatus == kExtensionsUnchecked) { 7670 mVendorExtensionsStatus = kExtensionsNone; 7671 } 7672 7673 return finalError; 7674} 7675 7676status_t ACodec::getVendorParameters(OMX_U32 portIndex, sp<AMessage> &format) { 7677 constexpr char prefix[] = "vendor."; 7678 constexpr size_t prefixLength = sizeof(prefix) - 1; 7679 char key[sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE::cName) + 7680 sizeof(OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE::cKey) + prefixLength]; 7681 strcpy(key, prefix); 7682 7683 // don't try again if component does not have vendor extensions 7684 if (mVendorExtensionsStatus == kExtensionsNone) { 7685 return OK; 7686 } 7687 7688 for (VendorExtension ext : VendorExtensions(mOMXNode)) { 7689 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *config = ext.config; 7690 if (config == nullptr) { 7691 return ext.status; 7692 } 7693 7694 mVendorExtensionsStatus = kExtensionsExist; 7695 7696 if (config->eDir != (portIndex == kPortIndexInput ? OMX_DirInput : OMX_DirOutput)) { 7697 continue; 7698 } 7699 7700 config->cName[sizeof(config->cName) - 1] = '\0'; // null-terminate name 7701 strcpy(key + prefixLength, (const char *)config->cName); 7702 size_t nameLength = strlen(key); 7703 key[nameLength] = '.'; 7704 7705 for (size_t paramIndex = 0; paramIndex < config->nParamCount; ++paramIndex) { 7706 // null-terminate param key 7707 config->param[paramIndex].cKey[sizeof(config->param[0].cKey) - 1] = '\0'; 7708 strcpy(key + nameLength + 1, (const char *)config->param[paramIndex].cKey); 7709 removeTrailingTags(key, nameLength, "value"); 7710 if (config->param[paramIndex].bSet) { 7711 switch (config->param[paramIndex].eValueType) { 7712 case OMX_AndroidVendorValueInt32: 7713 { 7714 format->setInt32(key, config->param[paramIndex].nInt32); 7715 break; 7716 } 7717 case OMX_AndroidVendorValueInt64: 7718 { 7719 format->setInt64(key, config->param[paramIndex].nInt64); 7720 break; 7721 } 7722 case OMX_AndroidVendorValueString: 7723 { 7724 config->param[paramIndex].cString[OMX_MAX_STRINGVALUE_SIZE - 1] = '\0'; 7725 format->setString(key, (const char *)config->param[paramIndex].cString); 7726 break; 7727 } 7728 default: 7729 ALOGW("vendor parameter %s is not a supported value", key); 7730 continue; 7731 } 7732 } 7733 } 7734 } 7735 7736 if (mVendorExtensionsStatus == kExtensionsUnchecked) { 7737 mVendorExtensionsStatus = kExtensionsNone; 7738 } 7739 7740 return OK; 7741} 7742 7743void ACodec::onSignalEndOfInputStream() { 7744 status_t err = INVALID_OPERATION; 7745 if (mGraphicBufferSource != NULL) { 7746 err = statusFromBinderStatus(mGraphicBufferSource->signalEndOfInputStream()); 7747 } 7748 mCallback->onSignaledInputEOS(err); 7749} 7750 7751void ACodec::forceStateTransition(int generation) { 7752 if (generation != mStateGeneration) { 7753 ALOGV("Ignoring stale force state transition message: #%d (now #%d)", 7754 generation, mStateGeneration); 7755 return; 7756 } 7757 ALOGE("State machine stuck"); 7758 // Error must have already been signalled to the client. 7759 7760 // Deferred messages will be handled at LoadedState at the end of the 7761 // transition. 7762 mShutdownInProgress = true; 7763 // No shutdown complete callback at the end of the transition. 7764 mExplicitShutdown = false; 7765 mKeepComponentAllocated = true; 7766 7767 status_t err = mOMXNode->sendCommand(OMX_CommandStateSet, OMX_StateIdle); 7768 if (err != OK) { 7769 // TODO: do some recovery here. 7770 } else { 7771 changeState(mExecutingToIdleState); 7772 } 7773} 7774 7775bool ACodec::ExecutingState::onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) { 7776 mCodec->onFrameRendered(mediaTimeUs, systemNano); 7777 return true; 7778} 7779 7780bool ACodec::ExecutingState::onOMXEvent( 7781 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 7782 switch (event) { 7783 case OMX_EventPortSettingsChanged: 7784 { 7785 CHECK_EQ(data1, (OMX_U32)kPortIndexOutput); 7786 7787 mCodec->onOutputFormatChanged(); 7788 7789 if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) { 7790 mCodec->mMetadataBuffersToSubmit = 0; 7791 CHECK_EQ(mCodec->mOMXNode->sendCommand( 7792 OMX_CommandPortDisable, kPortIndexOutput), 7793 (status_t)OK); 7794 7795 mCodec->freeOutputBuffersNotOwnedByComponent(); 7796 7797 mCodec->changeState(mCodec->mOutputPortSettingsChangedState); 7798 } else if (data2 != OMX_IndexConfigCommonOutputCrop 7799 && data2 != OMX_IndexConfigAndroidIntraRefresh) { 7800 ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08x", 7801 mCodec->mComponentName.c_str(), data2); 7802 } 7803 7804 return true; 7805 } 7806 7807 case OMX_EventBufferFlag: 7808 { 7809 return true; 7810 } 7811 7812 default: 7813 return BaseState::onOMXEvent(event, data1, data2); 7814 } 7815} 7816 7817//////////////////////////////////////////////////////////////////////////////// 7818 7819ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState( 7820 ACodec *codec) 7821 : BaseState(codec) { 7822} 7823 7824ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode( 7825 OMX_U32 portIndex) { 7826 if (portIndex == kPortIndexOutput) { 7827 return FREE_BUFFERS; 7828 } 7829 7830 CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput); 7831 7832 return RESUBMIT_BUFFERS; 7833} 7834 7835bool ACodec::OutputPortSettingsChangedState::onMessageReceived( 7836 const sp<AMessage> &msg) { 7837 bool handled = false; 7838 7839 switch (msg->what()) { 7840 case kWhatFlush: 7841 case kWhatShutdown: { 7842 if (mCodec->mFatalError) { 7843 sp<AMessage> msg = new AMessage(ACodec::kWhatForceStateTransition, mCodec); 7844 msg->setInt32("generation", mCodec->mStateGeneration); 7845 msg->post(3000000); 7846 } 7847 // fall-through 7848 } 7849 case kWhatResume: 7850 case kWhatSetParameters: 7851 { 7852 if (msg->what() == kWhatResume) { 7853 ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str()); 7854 } 7855 7856 mCodec->deferMessage(msg); 7857 handled = true; 7858 break; 7859 } 7860 7861 case kWhatForceStateTransition: 7862 { 7863 int32_t generation = 0; 7864 CHECK(msg->findInt32("generation", &generation)); 7865 mCodec->forceStateTransition(generation); 7866 7867 handled = true; 7868 break; 7869 } 7870 7871 default: 7872 handled = BaseState::onMessageReceived(msg); 7873 break; 7874 } 7875 7876 return handled; 7877} 7878 7879void ACodec::OutputPortSettingsChangedState::stateEntered() { 7880 ALOGV("[%s] Now handling output port settings change", 7881 mCodec->mComponentName.c_str()); 7882} 7883 7884bool ACodec::OutputPortSettingsChangedState::onOMXFrameRendered( 7885 int64_t mediaTimeUs, nsecs_t systemNano) { 7886 mCodec->onFrameRendered(mediaTimeUs, systemNano); 7887 return true; 7888} 7889 7890bool ACodec::OutputPortSettingsChangedState::onOMXEvent( 7891 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 7892 switch (event) { 7893 case OMX_EventCmdComplete: 7894 { 7895 if (data1 == (OMX_U32)OMX_CommandPortDisable) { 7896 if (data2 != (OMX_U32)kPortIndexOutput) { 7897 ALOGW("ignoring EventCmdComplete CommandPortDisable for port %u", data2); 7898 return false; 7899 } 7900 7901 ALOGV("[%s] Output port now disabled.", mCodec->mComponentName.c_str()); 7902 7903 status_t err = OK; 7904 if (!mCodec->mBuffers[kPortIndexOutput].isEmpty()) { 7905 ALOGE("disabled port should be empty, but has %zu buffers", 7906 mCodec->mBuffers[kPortIndexOutput].size()); 7907 err = FAILED_TRANSACTION; 7908 } else { 7909 mCodec->mAllocator[kPortIndexOutput].clear(); 7910 } 7911 7912 if (err == OK) { 7913 err = mCodec->mOMXNode->sendCommand( 7914 OMX_CommandPortEnable, kPortIndexOutput); 7915 } 7916 7917 if (err == OK) { 7918 err = mCodec->allocateBuffersOnPort(kPortIndexOutput); 7919 ALOGE_IF(err != OK, "Failed to allocate output port buffers after port " 7920 "reconfiguration: (%d)", err); 7921 mCodec->mCallback->onOutputBuffersChanged(); 7922 } 7923 7924 if (err != OK) { 7925 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 7926 ALOGE("Error occurred while disabling the output port"); 7927 } 7928 7929 return true; 7930 } else if (data1 == (OMX_U32)OMX_CommandPortEnable) { 7931 if (data2 != (OMX_U32)kPortIndexOutput) { 7932 ALOGW("ignoring EventCmdComplete OMX_CommandPortEnable for port %u", data2); 7933 return false; 7934 } 7935 7936 ALOGV("[%s] Output port now reenabled.", mCodec->mComponentName.c_str()); 7937 7938 if (mCodec->mExecutingState->active()) { 7939 mCodec->mExecutingState->submitOutputBuffers(); 7940 } 7941 7942 mCodec->changeState(mCodec->mExecutingState); 7943 7944 return true; 7945 } 7946 7947 return false; 7948 } 7949 7950 default: 7951 return BaseState::onOMXEvent(event, data1, data2); 7952 } 7953} 7954 7955//////////////////////////////////////////////////////////////////////////////// 7956 7957ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec) 7958 : BaseState(codec), 7959 mComponentNowIdle(false) { 7960} 7961 7962bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) { 7963 bool handled = false; 7964 7965 switch (msg->what()) { 7966 case kWhatFlush: 7967 { 7968 // Don't send me a flush request if you previously wanted me 7969 // to shutdown. 7970 ALOGW("Ignoring flush request in ExecutingToIdleState"); 7971 break; 7972 } 7973 7974 case kWhatShutdown: 7975 { 7976 mCodec->deferMessage(msg); 7977 handled = true; 7978 break; 7979 } 7980 7981 default: 7982 handled = BaseState::onMessageReceived(msg); 7983 break; 7984 } 7985 7986 return handled; 7987} 7988 7989void ACodec::ExecutingToIdleState::stateEntered() { 7990 ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str()); 7991 7992 mComponentNowIdle = false; 7993 mCodec->mLastOutputFormat.clear(); 7994} 7995 7996bool ACodec::ExecutingToIdleState::onOMXEvent( 7997 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 7998 switch (event) { 7999 case OMX_EventCmdComplete: 8000 { 8001 if (data1 != (OMX_U32)OMX_CommandStateSet 8002 || data2 != (OMX_U32)OMX_StateIdle) { 8003 ALOGE("Unexpected command completion in ExecutingToIdleState: %s(%u) %s(%u)", 8004 asString((OMX_COMMANDTYPE)data1), data1, 8005 asString((OMX_STATETYPE)data2), data2); 8006 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 8007 return true; 8008 } 8009 8010 mComponentNowIdle = true; 8011 8012 changeStateIfWeOwnAllBuffers(); 8013 8014 return true; 8015 } 8016 8017 case OMX_EventPortSettingsChanged: 8018 case OMX_EventBufferFlag: 8019 { 8020 // We're shutting down and don't care about this anymore. 8021 return true; 8022 } 8023 8024 default: 8025 return BaseState::onOMXEvent(event, data1, data2); 8026 } 8027} 8028 8029void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() { 8030 if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) { 8031 status_t err = mCodec->mOMXNode->sendCommand( 8032 OMX_CommandStateSet, OMX_StateLoaded); 8033 if (err == OK) { 8034 err = mCodec->freeBuffersOnPort(kPortIndexInput); 8035 status_t err2 = mCodec->freeBuffersOnPort(kPortIndexOutput); 8036 if (err == OK) { 8037 err = err2; 8038 } 8039 } 8040 8041 if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown) 8042 && mCodec->mNativeWindow != NULL) { 8043 // We push enough 1x1 blank buffers to ensure that one of 8044 // them has made it to the display. This allows the OMX 8045 // component teardown to zero out any protected buffers 8046 // without the risk of scanning out one of those buffers. 8047 pushBlankBuffersToNativeWindow(mCodec->mNativeWindow.get()); 8048 } 8049 8050 if (err != OK) { 8051 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 8052 return; 8053 } 8054 8055 mCodec->changeState(mCodec->mIdleToLoadedState); 8056 } 8057} 8058 8059void ACodec::ExecutingToIdleState::onInputBufferFilled( 8060 const sp<AMessage> &msg) { 8061 BaseState::onInputBufferFilled(msg); 8062 8063 changeStateIfWeOwnAllBuffers(); 8064} 8065 8066void ACodec::ExecutingToIdleState::onOutputBufferDrained( 8067 const sp<AMessage> &msg) { 8068 BaseState::onOutputBufferDrained(msg); 8069 8070 changeStateIfWeOwnAllBuffers(); 8071} 8072 8073//////////////////////////////////////////////////////////////////////////////// 8074 8075ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec) 8076 : BaseState(codec) { 8077} 8078 8079bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) { 8080 bool handled = false; 8081 8082 switch (msg->what()) { 8083 case kWhatShutdown: 8084 { 8085 mCodec->deferMessage(msg); 8086 handled = true; 8087 break; 8088 } 8089 8090 case kWhatFlush: 8091 { 8092 // Don't send me a flush request if you previously wanted me 8093 // to shutdown. 8094 ALOGE("Got flush request in IdleToLoadedState"); 8095 break; 8096 } 8097 8098 default: 8099 handled = BaseState::onMessageReceived(msg); 8100 break; 8101 } 8102 8103 return handled; 8104} 8105 8106void ACodec::IdleToLoadedState::stateEntered() { 8107 ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str()); 8108} 8109 8110bool ACodec::IdleToLoadedState::onOMXEvent( 8111 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 8112 switch (event) { 8113 case OMX_EventCmdComplete: 8114 { 8115 if (data1 != (OMX_U32)OMX_CommandStateSet 8116 || data2 != (OMX_U32)OMX_StateLoaded) { 8117 ALOGE("Unexpected command completion in IdleToLoadedState: %s(%u) %s(%u)", 8118 asString((OMX_COMMANDTYPE)data1), data1, 8119 asString((OMX_STATETYPE)data2), data2); 8120 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 8121 return true; 8122 } 8123 8124 mCodec->changeState(mCodec->mLoadedState); 8125 8126 return true; 8127 } 8128 8129 default: 8130 return BaseState::onOMXEvent(event, data1, data2); 8131 } 8132} 8133 8134//////////////////////////////////////////////////////////////////////////////// 8135 8136ACodec::FlushingState::FlushingState(ACodec *codec) 8137 : BaseState(codec) { 8138} 8139 8140void ACodec::FlushingState::stateEntered() { 8141 ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str()); 8142 8143 mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false; 8144} 8145 8146bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) { 8147 bool handled = false; 8148 8149 switch (msg->what()) { 8150 case kWhatShutdown: 8151 { 8152 mCodec->deferMessage(msg); 8153 if (mCodec->mFatalError) { 8154 sp<AMessage> msg = new AMessage(ACodec::kWhatForceStateTransition, mCodec); 8155 msg->setInt32("generation", mCodec->mStateGeneration); 8156 msg->post(3000000); 8157 } 8158 break; 8159 } 8160 8161 case kWhatFlush: 8162 { 8163 // We're already doing this right now. 8164 handled = true; 8165 break; 8166 } 8167 8168 case kWhatForceStateTransition: 8169 { 8170 int32_t generation = 0; 8171 CHECK(msg->findInt32("generation", &generation)); 8172 mCodec->forceStateTransition(generation); 8173 8174 handled = true; 8175 break; 8176 } 8177 8178 default: 8179 handled = BaseState::onMessageReceived(msg); 8180 break; 8181 } 8182 8183 return handled; 8184} 8185 8186bool ACodec::FlushingState::onOMXEvent( 8187 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 8188 ALOGV("[%s] FlushingState onOMXEvent(%u,%d)", 8189 mCodec->mComponentName.c_str(), event, (OMX_S32)data1); 8190 8191 switch (event) { 8192 case OMX_EventCmdComplete: 8193 { 8194 if (data1 != (OMX_U32)OMX_CommandFlush) { 8195 ALOGE("unexpected EventCmdComplete %s(%d) data2:%d in FlushingState", 8196 asString((OMX_COMMANDTYPE)data1), data1, data2); 8197 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 8198 return true; 8199 } 8200 8201 if (data2 == kPortIndexInput || data2 == kPortIndexOutput) { 8202 if (mFlushComplete[data2]) { 8203 ALOGW("Flush already completed for %s port", 8204 data2 == kPortIndexInput ? "input" : "output"); 8205 return true; 8206 } 8207 mFlushComplete[data2] = true; 8208 8209 if (mFlushComplete[kPortIndexInput] && mFlushComplete[kPortIndexOutput]) { 8210 changeStateIfWeOwnAllBuffers(); 8211 } 8212 } else if (data2 == OMX_ALL) { 8213 if (!mFlushComplete[kPortIndexInput] || !mFlushComplete[kPortIndexOutput]) { 8214 ALOGW("received flush complete event for OMX_ALL before ports have been" 8215 "flushed (%d/%d)", 8216 mFlushComplete[kPortIndexInput], mFlushComplete[kPortIndexOutput]); 8217 return false; 8218 } 8219 8220 changeStateIfWeOwnAllBuffers(); 8221 } else { 8222 ALOGW("data2 not OMX_ALL but %u in EventCmdComplete CommandFlush", data2); 8223 } 8224 8225 return true; 8226 } 8227 8228 case OMX_EventPortSettingsChanged: 8229 { 8230 sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec); 8231 msg->setInt32("type", omx_message::EVENT); 8232 msg->setInt32("generation", mCodec->mNodeGeneration); 8233 msg->setInt32("event", event); 8234 msg->setInt32("data1", data1); 8235 msg->setInt32("data2", data2); 8236 8237 ALOGV("[%s] Deferring OMX_EventPortSettingsChanged", 8238 mCodec->mComponentName.c_str()); 8239 8240 mCodec->deferMessage(msg); 8241 8242 return true; 8243 } 8244 8245 default: 8246 return BaseState::onOMXEvent(event, data1, data2); 8247 } 8248 8249 return true; 8250} 8251 8252void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) { 8253 BaseState::onOutputBufferDrained(msg); 8254 8255 changeStateIfWeOwnAllBuffers(); 8256} 8257 8258void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) { 8259 BaseState::onInputBufferFilled(msg); 8260 8261 changeStateIfWeOwnAllBuffers(); 8262} 8263 8264void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() { 8265 if (mFlushComplete[kPortIndexInput] 8266 && mFlushComplete[kPortIndexOutput] 8267 && mCodec->allYourBuffersAreBelongToUs()) { 8268 // We now own all buffers except possibly those still queued with 8269 // the native window for rendering. Let's get those back as well. 8270 mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs(); 8271 8272 mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC)); 8273 8274 mCodec->mCallback->onFlushCompleted(); 8275 8276 mCodec->mPortEOS[kPortIndexInput] = 8277 mCodec->mPortEOS[kPortIndexOutput] = false; 8278 8279 mCodec->mInputEOSResult = OK; 8280 8281 if (mCodec->mSkipCutBuffer != NULL) { 8282 mCodec->mSkipCutBuffer->clear(); 8283 } 8284 8285 mCodec->changeState(mCodec->mExecutingState); 8286 } 8287} 8288 8289status_t ACodec::queryCapabilities( 8290 const char* owner, const char* name, const char* mime, bool isEncoder, 8291 MediaCodecInfo::CapabilitiesWriter* caps) { 8292 const char *role = GetComponentRole(isEncoder, mime); 8293 if (role == NULL) { 8294 return BAD_VALUE; 8295 } 8296 8297 OMXClient client; 8298 status_t err = client.connect(owner); 8299 if (err != OK) { 8300 return err; 8301 } 8302 8303 sp<IOMX> omx = client.interface(); 8304 sp<CodecObserver> observer = new CodecObserver; 8305 sp<IOMXNode> omxNode; 8306 8307 err = omx->allocateNode(name, observer, &omxNode); 8308 if (err != OK) { 8309 client.disconnect(); 8310 return err; 8311 } 8312 8313 err = SetComponentRole(omxNode, role); 8314 if (err != OK) { 8315 omxNode->freeNode(); 8316 client.disconnect(); 8317 return err; 8318 } 8319 8320 bool isVideo = strncasecmp(mime, "video/", 6) == 0; 8321 bool isImage = strncasecmp(mime, "image/", 6) == 0; 8322 8323 if (isVideo || isImage) { 8324 OMX_VIDEO_PARAM_PROFILELEVELTYPE param; 8325 InitOMXParams(¶m); 8326 param.nPortIndex = isEncoder ? kPortIndexOutput : kPortIndexInput; 8327 8328 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { 8329 param.nProfileIndex = index; 8330 status_t err = omxNode->getParameter( 8331 OMX_IndexParamVideoProfileLevelQuerySupported, 8332 ¶m, sizeof(param)); 8333 if (err != OK) { 8334 break; 8335 } 8336 caps->addProfileLevel(param.eProfile, param.eLevel); 8337 8338 // AVC components may not list the constrained profiles explicitly, but 8339 // decoders that support a profile also support its constrained version. 8340 // Encoders must explicitly support constrained profiles. 8341 if (!isEncoder && strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC) == 0) { 8342 if (param.eProfile == OMX_VIDEO_AVCProfileHigh) { 8343 caps->addProfileLevel(OMX_VIDEO_AVCProfileConstrainedHigh, param.eLevel); 8344 } else if (param.eProfile == OMX_VIDEO_AVCProfileBaseline) { 8345 caps->addProfileLevel(OMX_VIDEO_AVCProfileConstrainedBaseline, param.eLevel); 8346 } 8347 } 8348 8349 if (index == kMaxIndicesToCheck) { 8350 ALOGW("[%s] stopping checking profiles after %u: %x/%x", 8351 name, index, 8352 param.eProfile, param.eLevel); 8353 } 8354 } 8355 8356 // Color format query 8357 // return colors in the order reported by the OMX component 8358 // prefix "flexible" standard ones with the flexible equivalent 8359 OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat; 8360 InitOMXParams(&portFormat); 8361 portFormat.nPortIndex = isEncoder ? kPortIndexInput : kPortIndexOutput; 8362 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { 8363 portFormat.nIndex = index; 8364 status_t err = omxNode->getParameter( 8365 OMX_IndexParamVideoPortFormat, 8366 &portFormat, sizeof(portFormat)); 8367 if (err != OK) { 8368 break; 8369 } 8370 8371 OMX_U32 flexibleEquivalent; 8372 if (IsFlexibleColorFormat( 8373 omxNode, portFormat.eColorFormat, false /* usingNativeWindow */, 8374 &flexibleEquivalent)) { 8375 caps->addColorFormat(flexibleEquivalent); 8376 } 8377 caps->addColorFormat(portFormat.eColorFormat); 8378 8379 if (index == kMaxIndicesToCheck) { 8380 ALOGW("[%s] stopping checking formats after %u: %s(%x)", 8381 name, index, 8382 asString(portFormat.eColorFormat), portFormat.eColorFormat); 8383 } 8384 } 8385 } else if (strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC) == 0) { 8386 // More audio codecs if they have profiles. 8387 OMX_AUDIO_PARAM_ANDROID_PROFILETYPE param; 8388 InitOMXParams(¶m); 8389 param.nPortIndex = isEncoder ? kPortIndexOutput : kPortIndexInput; 8390 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { 8391 param.nProfileIndex = index; 8392 status_t err = omxNode->getParameter( 8393 (OMX_INDEXTYPE)OMX_IndexParamAudioProfileQuerySupported, 8394 ¶m, sizeof(param)); 8395 if (err != OK) { 8396 break; 8397 } 8398 // For audio, level is ignored. 8399 caps->addProfileLevel(param.eProfile, 0 /* level */); 8400 8401 if (index == kMaxIndicesToCheck) { 8402 ALOGW("[%s] stopping checking profiles after %u: %x", 8403 name, index, 8404 param.eProfile); 8405 } 8406 } 8407 8408 // NOTE: Without Android extensions, OMX does not provide a way to query 8409 // AAC profile support 8410 if (param.nProfileIndex == 0) { 8411 ALOGW("component %s doesn't support profile query.", name); 8412 } 8413 } 8414 8415 if (isVideo && !isEncoder) { 8416 native_handle_t *sidebandHandle = NULL; 8417 if (omxNode->configureVideoTunnelMode( 8418 kPortIndexOutput, OMX_TRUE, 0, &sidebandHandle) == OK) { 8419 // tunneled playback includes adaptive playback 8420 caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback 8421 | MediaCodecInfo::Capabilities::kFlagSupportsTunneledPlayback); 8422 } else if (omxNode->setPortMode( 8423 kPortIndexOutput, IOMX::kPortModeDynamicANWBuffer) == OK || 8424 omxNode->prepareForAdaptivePlayback( 8425 kPortIndexOutput, OMX_TRUE, 8426 1280 /* width */, 720 /* height */) == OK) { 8427 caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback); 8428 } 8429 } 8430 8431 if (isVideo && isEncoder) { 8432 OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params; 8433 InitOMXParams(¶ms); 8434 params.nPortIndex = kPortIndexOutput; 8435 // TODO: should we verify if fallback is supported? 8436 if (omxNode->getConfig( 8437 (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, 8438 ¶ms, sizeof(params)) == OK) { 8439 caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsIntraRefresh); 8440 } 8441 } 8442 8443 omxNode->freeNode(); 8444 client.disconnect(); 8445 return OK; 8446} 8447 8448// These are supposed be equivalent to the logic in 8449// "audio_channel_out_mask_from_count". 8450//static 8451status_t ACodec::getOMXChannelMapping(size_t numChannels, OMX_AUDIO_CHANNELTYPE map[]) { 8452 switch (numChannels) { 8453 case 1: 8454 map[0] = OMX_AUDIO_ChannelCF; 8455 break; 8456 case 2: 8457 map[0] = OMX_AUDIO_ChannelLF; 8458 map[1] = OMX_AUDIO_ChannelRF; 8459 break; 8460 case 3: 8461 map[0] = OMX_AUDIO_ChannelLF; 8462 map[1] = OMX_AUDIO_ChannelRF; 8463 map[2] = OMX_AUDIO_ChannelCF; 8464 break; 8465 case 4: 8466 map[0] = OMX_AUDIO_ChannelLF; 8467 map[1] = OMX_AUDIO_ChannelRF; 8468 map[2] = OMX_AUDIO_ChannelLR; 8469 map[3] = OMX_AUDIO_ChannelRR; 8470 break; 8471 case 5: 8472 map[0] = OMX_AUDIO_ChannelLF; 8473 map[1] = OMX_AUDIO_ChannelRF; 8474 map[2] = OMX_AUDIO_ChannelCF; 8475 map[3] = OMX_AUDIO_ChannelLR; 8476 map[4] = OMX_AUDIO_ChannelRR; 8477 break; 8478 case 6: 8479 map[0] = OMX_AUDIO_ChannelLF; 8480 map[1] = OMX_AUDIO_ChannelRF; 8481 map[2] = OMX_AUDIO_ChannelCF; 8482 map[3] = OMX_AUDIO_ChannelLFE; 8483 map[4] = OMX_AUDIO_ChannelLR; 8484 map[5] = OMX_AUDIO_ChannelRR; 8485 break; 8486 case 7: 8487 map[0] = OMX_AUDIO_ChannelLF; 8488 map[1] = OMX_AUDIO_ChannelRF; 8489 map[2] = OMX_AUDIO_ChannelCF; 8490 map[3] = OMX_AUDIO_ChannelLFE; 8491 map[4] = OMX_AUDIO_ChannelLR; 8492 map[5] = OMX_AUDIO_ChannelRR; 8493 map[6] = OMX_AUDIO_ChannelCS; 8494 break; 8495 case 8: 8496 map[0] = OMX_AUDIO_ChannelLF; 8497 map[1] = OMX_AUDIO_ChannelRF; 8498 map[2] = OMX_AUDIO_ChannelCF; 8499 map[3] = OMX_AUDIO_ChannelLFE; 8500 map[4] = OMX_AUDIO_ChannelLR; 8501 map[5] = OMX_AUDIO_ChannelRR; 8502 map[6] = OMX_AUDIO_ChannelLS; 8503 map[7] = OMX_AUDIO_ChannelRS; 8504 break; 8505 default: 8506 return -EINVAL; 8507 } 8508 8509 return OK; 8510} 8511 8512} // namespace android 8513