ACodec.cpp revision deb14ec33bc481809b465959882736e2262b667a
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 2148 err = setupAACCodec( 2149 encoder, numChannels, sampleRate, bitrate, aacProfile, 2150 isADTS != 0, sbrMode, maxOutputChannelCount, drc, 2151 pcmLimiterEnable); 2152 } 2153 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) { 2154 err = setupAMRCodec(encoder, false /* isWAMR */, bitrate); 2155 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) { 2156 err = setupAMRCodec(encoder, true /* isWAMR */, bitrate); 2157 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW) 2158 || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) { 2159 // These are PCM-like formats with a fixed sample rate but 2160 // a variable number of channels. 2161 2162 int32_t numChannels; 2163 if (!msg->findInt32("channel-count", &numChannels)) { 2164 err = INVALID_OPERATION; 2165 } else { 2166 int32_t sampleRate; 2167 if (!msg->findInt32("sample-rate", &sampleRate)) { 2168 sampleRate = 8000; 2169 } 2170 err = setupG711Codec(encoder, sampleRate, numChannels); 2171 } 2172 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) { 2173 int32_t numChannels = 0, sampleRate = 0, compressionLevel = -1; 2174 if (encoder && 2175 (!msg->findInt32("channel-count", &numChannels) 2176 || !msg->findInt32("sample-rate", &sampleRate))) { 2177 ALOGE("missing channel count or sample rate for FLAC encoder"); 2178 err = INVALID_OPERATION; 2179 } else { 2180 if (encoder) { 2181 if (!msg->findInt32( 2182 "complexity", &compressionLevel) && 2183 !msg->findInt32( 2184 "flac-compression-level", &compressionLevel)) { 2185 compressionLevel = 5; // default FLAC compression level 2186 } else if (compressionLevel < 0) { 2187 ALOGW("compression level %d outside [0..8] range, " 2188 "using 0", 2189 compressionLevel); 2190 compressionLevel = 0; 2191 } else if (compressionLevel > 8) { 2192 ALOGW("compression level %d outside [0..8] range, " 2193 "using 8", 2194 compressionLevel); 2195 compressionLevel = 8; 2196 } 2197 } 2198 err = setupFlacCodec( 2199 encoder, numChannels, sampleRate, compressionLevel); 2200 } 2201 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) { 2202 int32_t numChannels, sampleRate; 2203 if (encoder 2204 || !msg->findInt32("channel-count", &numChannels) 2205 || !msg->findInt32("sample-rate", &sampleRate)) { 2206 err = INVALID_OPERATION; 2207 } else { 2208 err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels, pcmEncoding); 2209 } 2210 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AC3)) { 2211 int32_t numChannels; 2212 int32_t sampleRate; 2213 if (!msg->findInt32("channel-count", &numChannels) 2214 || !msg->findInt32("sample-rate", &sampleRate)) { 2215 err = INVALID_OPERATION; 2216 } else { 2217 err = setupAC3Codec(encoder, numChannels, sampleRate); 2218 } 2219 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_EAC3)) { 2220 int32_t numChannels; 2221 int32_t sampleRate; 2222 if (!msg->findInt32("channel-count", &numChannels) 2223 || !msg->findInt32("sample-rate", &sampleRate)) { 2224 err = INVALID_OPERATION; 2225 } else { 2226 err = setupEAC3Codec(encoder, numChannels, sampleRate); 2227 } 2228 } 2229 2230 if (err != OK) { 2231 return err; 2232 } 2233 2234 if (!msg->findInt32("encoder-delay", &mEncoderDelay)) { 2235 mEncoderDelay = 0; 2236 } 2237 2238 if (!msg->findInt32("encoder-padding", &mEncoderPadding)) { 2239 mEncoderPadding = 0; 2240 } 2241 2242 if (msg->findInt32("channel-mask", &mChannelMask)) { 2243 mChannelMaskPresent = true; 2244 } else { 2245 mChannelMaskPresent = false; 2246 } 2247 2248 int32_t maxInputSize; 2249 if (msg->findInt32("max-input-size", &maxInputSize)) { 2250 err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize); 2251 err = OK; // ignore error 2252 } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) { 2253 err = setMinBufferSize(kPortIndexInput, 8192); // XXX 2254 err = OK; // ignore error 2255 } 2256 2257 int32_t priority; 2258 if (msg->findInt32("priority", &priority)) { 2259 err = setPriority(priority); 2260 err = OK; // ignore error 2261 } 2262 2263 int32_t rateInt = -1; 2264 float rateFloat = -1; 2265 if (!msg->findFloat("operating-rate", &rateFloat)) { 2266 msg->findInt32("operating-rate", &rateInt); 2267 rateFloat = (float)rateInt; // 16MHz (FLINTMAX) is OK for upper bound. 2268 } 2269 if (rateFloat > 0) { 2270 err = setOperatingRate(rateFloat, mIsVideo); 2271 err = OK; // ignore errors 2272 } 2273 2274 if (err == OK) { 2275 err = setVendorParameters(msg); 2276 if (err != OK) { 2277 return err; 2278 } 2279 } 2280 2281 // NOTE: both mBaseOutputFormat and mOutputFormat are outputFormat to signal first frame. 2282 mBaseOutputFormat = outputFormat; 2283 mLastOutputFormat.clear(); 2284 2285 err = getPortFormat(kPortIndexInput, inputFormat); 2286 if (err == OK) { 2287 err = getPortFormat(kPortIndexOutput, outputFormat); 2288 if (err == OK) { 2289 mInputFormat = inputFormat; 2290 mOutputFormat = outputFormat; 2291 } 2292 } 2293 2294 // create data converters if needed 2295 if (!mIsVideo && !mIsImage && err == OK) { 2296 AudioEncoding codecPcmEncoding = kAudioEncodingPcm16bit; 2297 if (encoder) { 2298 (void)mInputFormat->findInt32("pcm-encoding", (int32_t*)&codecPcmEncoding); 2299 mConverter[kPortIndexInput] = AudioConverter::Create(pcmEncoding, codecPcmEncoding); 2300 if (mConverter[kPortIndexInput] != NULL) { 2301 mInputFormat->setInt32("pcm-encoding", pcmEncoding); 2302 } 2303 } else { 2304 (void)mOutputFormat->findInt32("pcm-encoding", (int32_t*)&codecPcmEncoding); 2305 mConverter[kPortIndexOutput] = AudioConverter::Create(codecPcmEncoding, pcmEncoding); 2306 if (mConverter[kPortIndexOutput] != NULL) { 2307 mOutputFormat->setInt32("pcm-encoding", pcmEncoding); 2308 } 2309 } 2310 } 2311 2312 return err; 2313} 2314 2315status_t ACodec::setLatency(uint32_t latency) { 2316 OMX_PARAM_U32TYPE config; 2317 InitOMXParams(&config); 2318 config.nPortIndex = kPortIndexInput; 2319 config.nU32 = (OMX_U32)latency; 2320 status_t err = mOMXNode->setConfig( 2321 (OMX_INDEXTYPE)OMX_IndexConfigLatency, 2322 &config, sizeof(config)); 2323 return err; 2324} 2325 2326status_t ACodec::getLatency(uint32_t *latency) { 2327 OMX_PARAM_U32TYPE config; 2328 InitOMXParams(&config); 2329 config.nPortIndex = kPortIndexInput; 2330 status_t err = mOMXNode->getConfig( 2331 (OMX_INDEXTYPE)OMX_IndexConfigLatency, 2332 &config, sizeof(config)); 2333 if (err == OK) { 2334 *latency = config.nU32; 2335 } 2336 return err; 2337} 2338 2339status_t ACodec::setPriority(int32_t priority) { 2340 if (priority < 0) { 2341 return BAD_VALUE; 2342 } 2343 OMX_PARAM_U32TYPE config; 2344 InitOMXParams(&config); 2345 config.nU32 = (OMX_U32)priority; 2346 status_t temp = mOMXNode->setConfig( 2347 (OMX_INDEXTYPE)OMX_IndexConfigPriority, 2348 &config, sizeof(config)); 2349 if (temp != OK) { 2350 ALOGI("codec does not support config priority (err %d)", temp); 2351 } 2352 return OK; 2353} 2354 2355status_t ACodec::setOperatingRate(float rateFloat, bool isVideo) { 2356 if (rateFloat < 0) { 2357 return BAD_VALUE; 2358 } 2359 OMX_U32 rate; 2360 if (isVideo) { 2361 if (rateFloat > 65535) { 2362 return BAD_VALUE; 2363 } 2364 rate = (OMX_U32)(rateFloat * 65536.0f + 0.5f); 2365 } else { 2366 if (rateFloat > UINT_MAX) { 2367 return BAD_VALUE; 2368 } 2369 rate = (OMX_U32)(rateFloat); 2370 } 2371 OMX_PARAM_U32TYPE config; 2372 InitOMXParams(&config); 2373 config.nU32 = rate; 2374 status_t err = mOMXNode->setConfig( 2375 (OMX_INDEXTYPE)OMX_IndexConfigOperatingRate, 2376 &config, sizeof(config)); 2377 if (err != OK) { 2378 ALOGI("codec does not support config operating rate (err %d)", err); 2379 } 2380 return OK; 2381} 2382 2383status_t ACodec::getIntraRefreshPeriod(uint32_t *intraRefreshPeriod) { 2384 OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params; 2385 InitOMXParams(¶ms); 2386 params.nPortIndex = kPortIndexOutput; 2387 status_t err = mOMXNode->getConfig( 2388 (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, ¶ms, sizeof(params)); 2389 if (err == OK) { 2390 *intraRefreshPeriod = params.nRefreshPeriod; 2391 return OK; 2392 } 2393 2394 // Fallback to query through standard OMX index. 2395 OMX_VIDEO_PARAM_INTRAREFRESHTYPE refreshParams; 2396 InitOMXParams(&refreshParams); 2397 refreshParams.nPortIndex = kPortIndexOutput; 2398 refreshParams.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic; 2399 err = mOMXNode->getParameter( 2400 OMX_IndexParamVideoIntraRefresh, &refreshParams, sizeof(refreshParams)); 2401 if (err != OK || refreshParams.nCirMBs == 0) { 2402 *intraRefreshPeriod = 0; 2403 return OK; 2404 } 2405 2406 // Calculate period based on width and height 2407 uint32_t width, height; 2408 OMX_PARAM_PORTDEFINITIONTYPE def; 2409 InitOMXParams(&def); 2410 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 2411 def.nPortIndex = kPortIndexOutput; 2412 err = mOMXNode->getParameter( 2413 OMX_IndexParamPortDefinition, &def, sizeof(def)); 2414 if (err != OK) { 2415 *intraRefreshPeriod = 0; 2416 return err; 2417 } 2418 width = video_def->nFrameWidth; 2419 height = video_def->nFrameHeight; 2420 // Use H.264/AVC MacroBlock size 16x16 2421 *intraRefreshPeriod = divUp((divUp(width, 16u) * divUp(height, 16u)), refreshParams.nCirMBs); 2422 2423 return OK; 2424} 2425 2426status_t ACodec::setIntraRefreshPeriod(uint32_t intraRefreshPeriod, bool inConfigure) { 2427 OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params; 2428 InitOMXParams(¶ms); 2429 params.nPortIndex = kPortIndexOutput; 2430 params.nRefreshPeriod = intraRefreshPeriod; 2431 status_t err = mOMXNode->setConfig( 2432 (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, ¶ms, sizeof(params)); 2433 if (err == OK) { 2434 return OK; 2435 } 2436 2437 // Only in configure state, a component could invoke setParameter. 2438 if (!inConfigure) { 2439 return INVALID_OPERATION; 2440 } else { 2441 ALOGI("[%s] try falling back to Cyclic", mComponentName.c_str()); 2442 } 2443 2444 OMX_VIDEO_PARAM_INTRAREFRESHTYPE refreshParams; 2445 InitOMXParams(&refreshParams); 2446 refreshParams.nPortIndex = kPortIndexOutput; 2447 refreshParams.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic; 2448 2449 if (intraRefreshPeriod == 0) { 2450 // 0 means disable intra refresh. 2451 refreshParams.nCirMBs = 0; 2452 } else { 2453 // Calculate macroblocks that need to be intra coded base on width and height 2454 uint32_t width, height; 2455 OMX_PARAM_PORTDEFINITIONTYPE def; 2456 InitOMXParams(&def); 2457 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 2458 def.nPortIndex = kPortIndexOutput; 2459 err = mOMXNode->getParameter( 2460 OMX_IndexParamPortDefinition, &def, sizeof(def)); 2461 if (err != OK) { 2462 return err; 2463 } 2464 width = video_def->nFrameWidth; 2465 height = video_def->nFrameHeight; 2466 // Use H.264/AVC MacroBlock size 16x16 2467 refreshParams.nCirMBs = divUp((divUp(width, 16u) * divUp(height, 16u)), intraRefreshPeriod); 2468 } 2469 2470 err = mOMXNode->setParameter( 2471 OMX_IndexParamVideoIntraRefresh, 2472 &refreshParams, sizeof(refreshParams)); 2473 if (err != OK) { 2474 return err; 2475 } 2476 2477 return OK; 2478} 2479 2480status_t ACodec::configureTemporalLayers( 2481 const sp<AMessage> &msg, bool inConfigure, sp<AMessage> &outputFormat) { 2482 if (!mIsVideo || !mIsEncoder) { 2483 return INVALID_OPERATION; 2484 } 2485 2486 AString tsSchema; 2487 if (!msg->findString("ts-schema", &tsSchema)) { 2488 return OK; 2489 } 2490 2491 unsigned int numLayers = 0; 2492 unsigned int numBLayers = 0; 2493 int tags; 2494 char dummy; 2495 OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE pattern = 2496 OMX_VIDEO_AndroidTemporalLayeringPatternNone; 2497 if (sscanf(tsSchema.c_str(), "webrtc.vp8.%u-layer%c", &numLayers, &dummy) == 1 2498 && numLayers > 0) { 2499 pattern = OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC; 2500 } else if ((tags = sscanf(tsSchema.c_str(), "android.generic.%u%c%u%c", 2501 &numLayers, &dummy, &numBLayers, &dummy)) 2502 && (tags == 1 || (tags == 3 && dummy == '+')) 2503 && numLayers > 0 && numLayers < UINT32_MAX - numBLayers) { 2504 numLayers += numBLayers; 2505 pattern = OMX_VIDEO_AndroidTemporalLayeringPatternAndroid; 2506 } else { 2507 ALOGI("Ignoring unsupported ts-schema [%s]", tsSchema.c_str()); 2508 return BAD_VALUE; 2509 } 2510 2511 OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE layerParams; 2512 InitOMXParams(&layerParams); 2513 layerParams.nPortIndex = kPortIndexOutput; 2514 2515 status_t err = mOMXNode->getParameter( 2516 (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering, 2517 &layerParams, sizeof(layerParams)); 2518 2519 if (err != OK) { 2520 return err; 2521 } else if (!(layerParams.eSupportedPatterns & pattern)) { 2522 return BAD_VALUE; 2523 } 2524 2525 numLayers = min(numLayers, layerParams.nLayerCountMax); 2526 numBLayers = min(numBLayers, layerParams.nBLayerCountMax); 2527 2528 if (!inConfigure) { 2529 OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE layerConfig; 2530 InitOMXParams(&layerConfig); 2531 layerConfig.nPortIndex = kPortIndexOutput; 2532 layerConfig.ePattern = pattern; 2533 layerConfig.nPLayerCountActual = numLayers - numBLayers; 2534 layerConfig.nBLayerCountActual = numBLayers; 2535 layerConfig.bBitrateRatiosSpecified = OMX_FALSE; 2536 2537 err = mOMXNode->setConfig( 2538 (OMX_INDEXTYPE)OMX_IndexConfigAndroidVideoTemporalLayering, 2539 &layerConfig, sizeof(layerConfig)); 2540 } else { 2541 layerParams.ePattern = pattern; 2542 layerParams.nPLayerCountActual = numLayers - numBLayers; 2543 layerParams.nBLayerCountActual = numBLayers; 2544 layerParams.bBitrateRatiosSpecified = OMX_FALSE; 2545 2546 err = mOMXNode->setParameter( 2547 (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering, 2548 &layerParams, sizeof(layerParams)); 2549 } 2550 2551 AString configSchema; 2552 if (pattern == OMX_VIDEO_AndroidTemporalLayeringPatternAndroid) { 2553 configSchema = AStringPrintf("android.generic.%u+%u", numLayers - numBLayers, numBLayers); 2554 } else if (pattern == OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC) { 2555 configSchema = AStringPrintf("webrtc.vp8.%u", numLayers); 2556 } 2557 2558 if (err != OK) { 2559 ALOGW("Failed to set temporal layers to %s (requested %s)", 2560 configSchema.c_str(), tsSchema.c_str()); 2561 return err; 2562 } 2563 2564 err = mOMXNode->getParameter( 2565 (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering, 2566 &layerParams, sizeof(layerParams)); 2567 2568 if (err == OK) { 2569 ALOGD("Temporal layers requested:%s configured:%s got:%s(%u: P=%u, B=%u)", 2570 tsSchema.c_str(), configSchema.c_str(), 2571 asString(layerParams.ePattern), layerParams.ePattern, 2572 layerParams.nPLayerCountActual, layerParams.nBLayerCountActual); 2573 2574 if (outputFormat.get() == mOutputFormat.get()) { 2575 mOutputFormat = mOutputFormat->dup(); // trigger an output format change event 2576 } 2577 // assume we got what we configured 2578 outputFormat->setString("ts-schema", configSchema); 2579 } 2580 return err; 2581} 2582 2583status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) { 2584 OMX_PARAM_PORTDEFINITIONTYPE def; 2585 InitOMXParams(&def); 2586 def.nPortIndex = portIndex; 2587 2588 status_t err = mOMXNode->getParameter( 2589 OMX_IndexParamPortDefinition, &def, sizeof(def)); 2590 2591 if (err != OK) { 2592 return err; 2593 } 2594 2595 if (def.nBufferSize >= size) { 2596 return OK; 2597 } 2598 2599 def.nBufferSize = size; 2600 2601 err = mOMXNode->setParameter( 2602 OMX_IndexParamPortDefinition, &def, sizeof(def)); 2603 2604 if (err != OK) { 2605 return err; 2606 } 2607 2608 err = mOMXNode->getParameter( 2609 OMX_IndexParamPortDefinition, &def, sizeof(def)); 2610 2611 if (err != OK) { 2612 return err; 2613 } 2614 2615 if (def.nBufferSize < size) { 2616 ALOGE("failed to set min buffer size to %zu (is still %u)", size, def.nBufferSize); 2617 return FAILED_TRANSACTION; 2618 } 2619 2620 return OK; 2621} 2622 2623status_t ACodec::selectAudioPortFormat( 2624 OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) { 2625 OMX_AUDIO_PARAM_PORTFORMATTYPE format; 2626 InitOMXParams(&format); 2627 2628 format.nPortIndex = portIndex; 2629 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { 2630 format.nIndex = index; 2631 status_t err = mOMXNode->getParameter( 2632 OMX_IndexParamAudioPortFormat, &format, sizeof(format)); 2633 2634 if (err != OK) { 2635 return err; 2636 } 2637 2638 if (format.eEncoding == desiredFormat) { 2639 break; 2640 } 2641 2642 if (index == kMaxIndicesToCheck) { 2643 ALOGW("[%s] stopping checking formats after %u: %s(%x)", 2644 mComponentName.c_str(), index, 2645 asString(format.eEncoding), format.eEncoding); 2646 return ERROR_UNSUPPORTED; 2647 } 2648 } 2649 2650 return mOMXNode->setParameter( 2651 OMX_IndexParamAudioPortFormat, &format, sizeof(format)); 2652} 2653 2654status_t ACodec::setupAACCodec( 2655 bool encoder, int32_t numChannels, int32_t sampleRate, 2656 int32_t bitRate, int32_t aacProfile, bool isADTS, int32_t sbrMode, 2657 int32_t maxOutputChannelCount, const drcParams_t& drc, 2658 int32_t pcmLimiterEnable) { 2659 if (encoder && isADTS) { 2660 return -EINVAL; 2661 } 2662 2663 status_t err = setupRawAudioFormat( 2664 encoder ? kPortIndexInput : kPortIndexOutput, 2665 sampleRate, 2666 numChannels); 2667 2668 if (err != OK) { 2669 return err; 2670 } 2671 2672 if (encoder) { 2673 err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC); 2674 2675 if (err != OK) { 2676 return err; 2677 } 2678 2679 OMX_PARAM_PORTDEFINITIONTYPE def; 2680 InitOMXParams(&def); 2681 def.nPortIndex = kPortIndexOutput; 2682 2683 err = mOMXNode->getParameter( 2684 OMX_IndexParamPortDefinition, &def, sizeof(def)); 2685 2686 if (err != OK) { 2687 return err; 2688 } 2689 2690 def.format.audio.bFlagErrorConcealment = OMX_TRUE; 2691 def.format.audio.eEncoding = OMX_AUDIO_CodingAAC; 2692 2693 err = mOMXNode->setParameter( 2694 OMX_IndexParamPortDefinition, &def, sizeof(def)); 2695 2696 if (err != OK) { 2697 return err; 2698 } 2699 2700 OMX_AUDIO_PARAM_AACPROFILETYPE profile; 2701 InitOMXParams(&profile); 2702 profile.nPortIndex = kPortIndexOutput; 2703 2704 err = mOMXNode->getParameter( 2705 OMX_IndexParamAudioAac, &profile, sizeof(profile)); 2706 2707 if (err != OK) { 2708 return err; 2709 } 2710 2711 profile.nChannels = numChannels; 2712 2713 profile.eChannelMode = 2714 (numChannels == 1) 2715 ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo; 2716 2717 profile.nSampleRate = sampleRate; 2718 profile.nBitRate = bitRate; 2719 profile.nAudioBandWidth = 0; 2720 profile.nFrameLength = 0; 2721 profile.nAACtools = OMX_AUDIO_AACToolAll; 2722 profile.nAACERtools = OMX_AUDIO_AACERNone; 2723 profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile; 2724 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF; 2725 switch (sbrMode) { 2726 case 0: 2727 // disable sbr 2728 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR; 2729 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR; 2730 break; 2731 case 1: 2732 // enable single-rate sbr 2733 profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR; 2734 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR; 2735 break; 2736 case 2: 2737 // enable dual-rate sbr 2738 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR; 2739 profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR; 2740 break; 2741 case -1: 2742 // enable both modes -> the codec will decide which mode should be used 2743 profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR; 2744 profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR; 2745 break; 2746 default: 2747 // unsupported sbr mode 2748 return BAD_VALUE; 2749 } 2750 2751 2752 err = mOMXNode->setParameter( 2753 OMX_IndexParamAudioAac, &profile, sizeof(profile)); 2754 2755 if (err != OK) { 2756 return err; 2757 } 2758 2759 return err; 2760 } 2761 2762 OMX_AUDIO_PARAM_AACPROFILETYPE profile; 2763 InitOMXParams(&profile); 2764 profile.nPortIndex = kPortIndexInput; 2765 2766 err = mOMXNode->getParameter( 2767 OMX_IndexParamAudioAac, &profile, sizeof(profile)); 2768 2769 if (err != OK) { 2770 return err; 2771 } 2772 2773 profile.nChannels = numChannels; 2774 profile.nSampleRate = sampleRate; 2775 2776 profile.eAACStreamFormat = 2777 isADTS 2778 ? OMX_AUDIO_AACStreamFormatMP4ADTS 2779 : OMX_AUDIO_AACStreamFormatMP4FF; 2780 2781 OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE presentation; 2782 InitOMXParams(&presentation); 2783 presentation.nMaxOutputChannels = maxOutputChannelCount; 2784 presentation.nDrcCut = drc.drcCut; 2785 presentation.nDrcBoost = drc.drcBoost; 2786 presentation.nHeavyCompression = drc.heavyCompression; 2787 presentation.nTargetReferenceLevel = drc.targetRefLevel; 2788 presentation.nEncodedTargetLevel = drc.encodedTargetLevel; 2789 presentation.nPCMLimiterEnable = pcmLimiterEnable; 2790 2791 status_t res = mOMXNode->setParameter( 2792 OMX_IndexParamAudioAac, &profile, sizeof(profile)); 2793 if (res == OK) { 2794 // optional parameters, will not cause configuration failure 2795 mOMXNode->setParameter( 2796 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacPresentation, 2797 &presentation, sizeof(presentation)); 2798 } else { 2799 ALOGW("did not set AudioAndroidAacPresentation due to error %d when setting AudioAac", res); 2800 } 2801 mSampleRate = sampleRate; 2802 return res; 2803} 2804 2805status_t ACodec::setupAC3Codec( 2806 bool encoder, int32_t numChannels, int32_t sampleRate) { 2807 status_t err = setupRawAudioFormat( 2808 encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels); 2809 2810 if (err != OK) { 2811 return err; 2812 } 2813 2814 if (encoder) { 2815 ALOGW("AC3 encoding is not supported."); 2816 return INVALID_OPERATION; 2817 } 2818 2819 OMX_AUDIO_PARAM_ANDROID_AC3TYPE def; 2820 InitOMXParams(&def); 2821 def.nPortIndex = kPortIndexInput; 2822 2823 err = mOMXNode->getParameter( 2824 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, &def, sizeof(def)); 2825 2826 if (err != OK) { 2827 return err; 2828 } 2829 2830 def.nChannels = numChannels; 2831 def.nSampleRate = sampleRate; 2832 2833 return mOMXNode->setParameter( 2834 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, &def, sizeof(def)); 2835} 2836 2837status_t ACodec::setupEAC3Codec( 2838 bool encoder, int32_t numChannels, int32_t sampleRate) { 2839 status_t err = setupRawAudioFormat( 2840 encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels); 2841 2842 if (err != OK) { 2843 return err; 2844 } 2845 2846 if (encoder) { 2847 ALOGW("EAC3 encoding is not supported."); 2848 return INVALID_OPERATION; 2849 } 2850 2851 OMX_AUDIO_PARAM_ANDROID_EAC3TYPE def; 2852 InitOMXParams(&def); 2853 def.nPortIndex = kPortIndexInput; 2854 2855 err = mOMXNode->getParameter( 2856 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, &def, sizeof(def)); 2857 2858 if (err != OK) { 2859 return err; 2860 } 2861 2862 def.nChannels = numChannels; 2863 def.nSampleRate = sampleRate; 2864 2865 return mOMXNode->setParameter( 2866 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, &def, sizeof(def)); 2867} 2868 2869static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate( 2870 bool isAMRWB, int32_t bps) { 2871 if (isAMRWB) { 2872 if (bps <= 6600) { 2873 return OMX_AUDIO_AMRBandModeWB0; 2874 } else if (bps <= 8850) { 2875 return OMX_AUDIO_AMRBandModeWB1; 2876 } else if (bps <= 12650) { 2877 return OMX_AUDIO_AMRBandModeWB2; 2878 } else if (bps <= 14250) { 2879 return OMX_AUDIO_AMRBandModeWB3; 2880 } else if (bps <= 15850) { 2881 return OMX_AUDIO_AMRBandModeWB4; 2882 } else if (bps <= 18250) { 2883 return OMX_AUDIO_AMRBandModeWB5; 2884 } else if (bps <= 19850) { 2885 return OMX_AUDIO_AMRBandModeWB6; 2886 } else if (bps <= 23050) { 2887 return OMX_AUDIO_AMRBandModeWB7; 2888 } 2889 2890 // 23850 bps 2891 return OMX_AUDIO_AMRBandModeWB8; 2892 } else { // AMRNB 2893 if (bps <= 4750) { 2894 return OMX_AUDIO_AMRBandModeNB0; 2895 } else if (bps <= 5150) { 2896 return OMX_AUDIO_AMRBandModeNB1; 2897 } else if (bps <= 5900) { 2898 return OMX_AUDIO_AMRBandModeNB2; 2899 } else if (bps <= 6700) { 2900 return OMX_AUDIO_AMRBandModeNB3; 2901 } else if (bps <= 7400) { 2902 return OMX_AUDIO_AMRBandModeNB4; 2903 } else if (bps <= 7950) { 2904 return OMX_AUDIO_AMRBandModeNB5; 2905 } else if (bps <= 10200) { 2906 return OMX_AUDIO_AMRBandModeNB6; 2907 } 2908 2909 // 12200 bps 2910 return OMX_AUDIO_AMRBandModeNB7; 2911 } 2912} 2913 2914status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) { 2915 OMX_AUDIO_PARAM_AMRTYPE def; 2916 InitOMXParams(&def); 2917 def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput; 2918 2919 status_t err = mOMXNode->getParameter( 2920 OMX_IndexParamAudioAmr, &def, sizeof(def)); 2921 2922 if (err != OK) { 2923 return err; 2924 } 2925 2926 def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF; 2927 def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate); 2928 2929 err = mOMXNode->setParameter( 2930 OMX_IndexParamAudioAmr, &def, sizeof(def)); 2931 2932 if (err != OK) { 2933 return err; 2934 } 2935 2936 return setupRawAudioFormat( 2937 encoder ? kPortIndexInput : kPortIndexOutput, 2938 isWAMR ? 16000 : 8000 /* sampleRate */, 2939 1 /* numChannels */); 2940} 2941 2942status_t ACodec::setupG711Codec(bool encoder, int32_t sampleRate, int32_t numChannels) { 2943 if (encoder) { 2944 return INVALID_OPERATION; 2945 } 2946 2947 return setupRawAudioFormat( 2948 kPortIndexInput, sampleRate, numChannels); 2949} 2950 2951status_t ACodec::setupFlacCodec( 2952 bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel) { 2953 2954 if (encoder) { 2955 OMX_AUDIO_PARAM_FLACTYPE def; 2956 InitOMXParams(&def); 2957 def.nPortIndex = kPortIndexOutput; 2958 2959 // configure compression level 2960 status_t err = mOMXNode->getParameter(OMX_IndexParamAudioFlac, &def, sizeof(def)); 2961 if (err != OK) { 2962 ALOGE("setupFlacCodec(): Error %d getting OMX_IndexParamAudioFlac parameter", err); 2963 return err; 2964 } 2965 def.nCompressionLevel = compressionLevel; 2966 err = mOMXNode->setParameter(OMX_IndexParamAudioFlac, &def, sizeof(def)); 2967 if (err != OK) { 2968 ALOGE("setupFlacCodec(): Error %d setting OMX_IndexParamAudioFlac parameter", err); 2969 return err; 2970 } 2971 } 2972 2973 return setupRawAudioFormat( 2974 encoder ? kPortIndexInput : kPortIndexOutput, 2975 sampleRate, 2976 numChannels); 2977} 2978 2979status_t ACodec::setupRawAudioFormat( 2980 OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels, AudioEncoding encoding) { 2981 OMX_PARAM_PORTDEFINITIONTYPE def; 2982 InitOMXParams(&def); 2983 def.nPortIndex = portIndex; 2984 2985 status_t err = mOMXNode->getParameter( 2986 OMX_IndexParamPortDefinition, &def, sizeof(def)); 2987 2988 if (err != OK) { 2989 return err; 2990 } 2991 2992 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; 2993 2994 err = mOMXNode->setParameter( 2995 OMX_IndexParamPortDefinition, &def, sizeof(def)); 2996 2997 if (err != OK) { 2998 return err; 2999 } 3000 3001 OMX_AUDIO_PARAM_PCMMODETYPE pcmParams; 3002 InitOMXParams(&pcmParams); 3003 pcmParams.nPortIndex = portIndex; 3004 3005 err = mOMXNode->getParameter( 3006 OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); 3007 3008 if (err != OK) { 3009 return err; 3010 } 3011 3012 pcmParams.nChannels = numChannels; 3013 switch (encoding) { 3014 case kAudioEncodingPcm8bit: 3015 pcmParams.eNumData = OMX_NumericalDataUnsigned; 3016 pcmParams.nBitPerSample = 8; 3017 break; 3018 case kAudioEncodingPcmFloat: 3019 pcmParams.eNumData = OMX_NumericalDataFloat; 3020 pcmParams.nBitPerSample = 32; 3021 break; 3022 case kAudioEncodingPcm16bit: 3023 pcmParams.eNumData = OMX_NumericalDataSigned; 3024 pcmParams.nBitPerSample = 16; 3025 break; 3026 default: 3027 return BAD_VALUE; 3028 } 3029 pcmParams.bInterleaved = OMX_TRUE; 3030 pcmParams.nSamplingRate = sampleRate; 3031 pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear; 3032 3033 if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) { 3034 return OMX_ErrorNone; 3035 } 3036 3037 err = mOMXNode->setParameter( 3038 OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); 3039 // if we could not set up raw format to non-16-bit, try with 16-bit 3040 // NOTE: we will also verify this via readback, in case codec ignores these fields 3041 if (err != OK && encoding != kAudioEncodingPcm16bit) { 3042 pcmParams.eNumData = OMX_NumericalDataSigned; 3043 pcmParams.nBitPerSample = 16; 3044 err = mOMXNode->setParameter( 3045 OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); 3046 } 3047 return err; 3048} 3049 3050status_t ACodec::configureTunneledVideoPlayback( 3051 int32_t audioHwSync, const sp<ANativeWindow> &nativeWindow) { 3052 native_handle_t* sidebandHandle; 3053 3054 status_t err = mOMXNode->configureVideoTunnelMode( 3055 kPortIndexOutput, OMX_TRUE, audioHwSync, &sidebandHandle); 3056 if (err != OK) { 3057 ALOGE("configureVideoTunnelMode failed! (err %d).", err); 3058 return err; 3059 } 3060 3061 err = native_window_set_sideband_stream(nativeWindow.get(), sidebandHandle); 3062 if (err != OK) { 3063 ALOGE("native_window_set_sideband_stream(%p) failed! (err %d).", 3064 sidebandHandle, err); 3065 return err; 3066 } 3067 3068 return OK; 3069} 3070 3071status_t ACodec::setVideoPortFormatType( 3072 OMX_U32 portIndex, 3073 OMX_VIDEO_CODINGTYPE compressionFormat, 3074 OMX_COLOR_FORMATTYPE colorFormat, 3075 bool usingNativeBuffers) { 3076 OMX_VIDEO_PARAM_PORTFORMATTYPE format; 3077 InitOMXParams(&format); 3078 format.nPortIndex = portIndex; 3079 format.nIndex = 0; 3080 bool found = false; 3081 3082 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { 3083 format.nIndex = index; 3084 status_t err = mOMXNode->getParameter( 3085 OMX_IndexParamVideoPortFormat, 3086 &format, sizeof(format)); 3087 3088 if (err != OK) { 3089 return err; 3090 } 3091 3092 // substitute back flexible color format to codec supported format 3093 OMX_U32 flexibleEquivalent; 3094 if (compressionFormat == OMX_VIDEO_CodingUnused 3095 && IsFlexibleColorFormat( 3096 mOMXNode, format.eColorFormat, usingNativeBuffers, &flexibleEquivalent) 3097 && colorFormat == flexibleEquivalent) { 3098 ALOGI("[%s] using color format %#x in place of %#x", 3099 mComponentName.c_str(), format.eColorFormat, colorFormat); 3100 colorFormat = format.eColorFormat; 3101 } 3102 3103 // The following assertion is violated by TI's video decoder. 3104 // CHECK_EQ(format.nIndex, index); 3105 3106 if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) { 3107 if (portIndex == kPortIndexInput 3108 && colorFormat == format.eColorFormat) { 3109 // eCompressionFormat does not seem right. 3110 found = true; 3111 break; 3112 } 3113 if (portIndex == kPortIndexOutput 3114 && compressionFormat == format.eCompressionFormat) { 3115 // eColorFormat does not seem right. 3116 found = true; 3117 break; 3118 } 3119 } 3120 3121 if (format.eCompressionFormat == compressionFormat 3122 && format.eColorFormat == colorFormat) { 3123 found = true; 3124 break; 3125 } 3126 3127 if (index == kMaxIndicesToCheck) { 3128 ALOGW("[%s] stopping checking formats after %u: %s(%x)/%s(%x)", 3129 mComponentName.c_str(), index, 3130 asString(format.eCompressionFormat), format.eCompressionFormat, 3131 asString(format.eColorFormat), format.eColorFormat); 3132 } 3133 } 3134 3135 if (!found) { 3136 return UNKNOWN_ERROR; 3137 } 3138 3139 status_t err = mOMXNode->setParameter( 3140 OMX_IndexParamVideoPortFormat, &format, sizeof(format)); 3141 3142 return err; 3143} 3144 3145// Set optimal output format. OMX component lists output formats in the order 3146// of preference, but this got more complicated since the introduction of flexible 3147// YUV formats. We support a legacy behavior for applications that do not use 3148// surface output, do not specify an output format, but expect a "usable" standard 3149// OMX format. SW readable and standard formats must be flex-YUV. 3150// 3151// Suggested preference order: 3152// - optimal format for texture rendering (mediaplayer behavior) 3153// - optimal SW readable & texture renderable format (flex-YUV support) 3154// - optimal SW readable non-renderable format (flex-YUV bytebuffer support) 3155// - legacy "usable" standard formats 3156// 3157// For legacy support, we prefer a standard format, but will settle for a SW readable 3158// flex-YUV format. 3159status_t ACodec::setSupportedOutputFormat(bool getLegacyFlexibleFormat) { 3160 OMX_VIDEO_PARAM_PORTFORMATTYPE format, legacyFormat; 3161 InitOMXParams(&format); 3162 format.nPortIndex = kPortIndexOutput; 3163 3164 InitOMXParams(&legacyFormat); 3165 // this field will change when we find a suitable legacy format 3166 legacyFormat.eColorFormat = OMX_COLOR_FormatUnused; 3167 3168 for (OMX_U32 index = 0; ; ++index) { 3169 format.nIndex = index; 3170 status_t err = mOMXNode->getParameter( 3171 OMX_IndexParamVideoPortFormat, &format, sizeof(format)); 3172 if (err != OK) { 3173 // no more formats, pick legacy format if found 3174 if (legacyFormat.eColorFormat != OMX_COLOR_FormatUnused) { 3175 memcpy(&format, &legacyFormat, sizeof(format)); 3176 break; 3177 } 3178 return err; 3179 } 3180 if (format.eCompressionFormat != OMX_VIDEO_CodingUnused) { 3181 return OMX_ErrorBadParameter; 3182 } 3183 if (!getLegacyFlexibleFormat) { 3184 break; 3185 } 3186 // standard formats that were exposed to users before 3187 if (format.eColorFormat == OMX_COLOR_FormatYUV420Planar 3188 || format.eColorFormat == OMX_COLOR_FormatYUV420PackedPlanar 3189 || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar 3190 || format.eColorFormat == OMX_COLOR_FormatYUV420PackedSemiPlanar 3191 || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar) { 3192 break; 3193 } 3194 // find best legacy non-standard format 3195 OMX_U32 flexibleEquivalent; 3196 if (legacyFormat.eColorFormat == OMX_COLOR_FormatUnused 3197 && IsFlexibleColorFormat( 3198 mOMXNode, format.eColorFormat, false /* usingNativeBuffers */, 3199 &flexibleEquivalent) 3200 && flexibleEquivalent == OMX_COLOR_FormatYUV420Flexible) { 3201 memcpy(&legacyFormat, &format, sizeof(format)); 3202 } 3203 } 3204 return mOMXNode->setParameter( 3205 OMX_IndexParamVideoPortFormat, &format, sizeof(format)); 3206} 3207 3208static const struct VideoCodingMapEntry { 3209 const char *mMime; 3210 OMX_VIDEO_CODINGTYPE mVideoCodingType; 3211} kVideoCodingMapEntry[] = { 3212 { MEDIA_MIMETYPE_VIDEO_AVC, OMX_VIDEO_CodingAVC }, 3213 { MEDIA_MIMETYPE_VIDEO_HEVC, OMX_VIDEO_CodingHEVC }, 3214 { MEDIA_MIMETYPE_VIDEO_MPEG4, OMX_VIDEO_CodingMPEG4 }, 3215 { MEDIA_MIMETYPE_VIDEO_H263, OMX_VIDEO_CodingH263 }, 3216 { MEDIA_MIMETYPE_VIDEO_MPEG2, OMX_VIDEO_CodingMPEG2 }, 3217 { MEDIA_MIMETYPE_VIDEO_VP8, OMX_VIDEO_CodingVP8 }, 3218 { MEDIA_MIMETYPE_VIDEO_VP9, OMX_VIDEO_CodingVP9 }, 3219 { MEDIA_MIMETYPE_VIDEO_DOLBY_VISION, OMX_VIDEO_CodingDolbyVision }, 3220 { MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC, OMX_VIDEO_CodingImageHEIC }, 3221}; 3222 3223static status_t GetVideoCodingTypeFromMime( 3224 const char *mime, OMX_VIDEO_CODINGTYPE *codingType) { 3225 for (size_t i = 0; 3226 i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]); 3227 ++i) { 3228 if (!strcasecmp(mime, kVideoCodingMapEntry[i].mMime)) { 3229 *codingType = kVideoCodingMapEntry[i].mVideoCodingType; 3230 return OK; 3231 } 3232 } 3233 3234 *codingType = OMX_VIDEO_CodingUnused; 3235 3236 return ERROR_UNSUPPORTED; 3237} 3238 3239static status_t GetMimeTypeForVideoCoding( 3240 OMX_VIDEO_CODINGTYPE codingType, AString *mime) { 3241 for (size_t i = 0; 3242 i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]); 3243 ++i) { 3244 if (codingType == kVideoCodingMapEntry[i].mVideoCodingType) { 3245 *mime = kVideoCodingMapEntry[i].mMime; 3246 return OK; 3247 } 3248 } 3249 3250 mime->clear(); 3251 3252 return ERROR_UNSUPPORTED; 3253} 3254 3255status_t ACodec::setPortBufferNum(OMX_U32 portIndex, int bufferNum) { 3256 OMX_PARAM_PORTDEFINITIONTYPE def; 3257 InitOMXParams(&def); 3258 def.nPortIndex = portIndex; 3259 status_t err; 3260 ALOGD("Setting [%s] %s port buffer number: %d", mComponentName.c_str(), 3261 portIndex == kPortIndexInput ? "input" : "output", bufferNum); 3262 err = mOMXNode->getParameter( 3263 OMX_IndexParamPortDefinition, &def, sizeof(def)); 3264 if (err != OK) { 3265 return err; 3266 } 3267 def.nBufferCountActual = bufferNum; 3268 err = mOMXNode->setParameter( 3269 OMX_IndexParamPortDefinition, &def, sizeof(def)); 3270 if (err != OK) { 3271 // Component could reject this request. 3272 ALOGW("Fail to set [%s] %s port buffer number: %d", mComponentName.c_str(), 3273 portIndex == kPortIndexInput ? "input" : "output", bufferNum); 3274 } 3275 return OK; 3276} 3277 3278status_t ACodec::setupVideoDecoder( 3279 const char *mime, const sp<AMessage> &msg, bool haveNativeWindow, 3280 bool usingSwRenderer, sp<AMessage> &outputFormat) { 3281 int32_t width, height; 3282 if (!msg->findInt32("width", &width) 3283 || !msg->findInt32("height", &height)) { 3284 return INVALID_OPERATION; 3285 } 3286 3287 OMX_VIDEO_CODINGTYPE compressionFormat; 3288 status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat); 3289 3290 if (err != OK) { 3291 return err; 3292 } 3293 3294 if (compressionFormat == OMX_VIDEO_CodingHEVC) { 3295 int32_t profile; 3296 if (msg->findInt32("profile", &profile)) { 3297 // verify if Main10 profile is supported at all, and fail 3298 // immediately if it's not supported. 3299 if (profile == OMX_VIDEO_HEVCProfileMain10 || 3300 profile == OMX_VIDEO_HEVCProfileMain10HDR10) { 3301 err = verifySupportForProfileAndLevel( 3302 kPortIndexInput, profile, 0); 3303 if (err != OK) { 3304 return err; 3305 } 3306 } 3307 } 3308 } 3309 3310 if (compressionFormat == OMX_VIDEO_CodingVP9) { 3311 OMX_VIDEO_PARAM_PROFILELEVELTYPE params; 3312 InitOMXParams(¶ms); 3313 params.nPortIndex = kPortIndexInput; 3314 // Check if VP9 decoder advertises supported profiles. 3315 params.nProfileIndex = 0; 3316 status_t err = mOMXNode->getParameter( 3317 OMX_IndexParamVideoProfileLevelQuerySupported, 3318 ¶ms, sizeof(params)); 3319 mIsLegacyVP9Decoder = err != OK; 3320 } 3321 3322 err = setVideoPortFormatType( 3323 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused); 3324 3325 if (err != OK) { 3326 return err; 3327 } 3328 3329 int32_t tmp; 3330 if (msg->findInt32("color-format", &tmp)) { 3331 OMX_COLOR_FORMATTYPE colorFormat = 3332 static_cast<OMX_COLOR_FORMATTYPE>(tmp); 3333 err = setVideoPortFormatType( 3334 kPortIndexOutput, OMX_VIDEO_CodingUnused, colorFormat, haveNativeWindow); 3335 if (err != OK) { 3336 ALOGW("[%s] does not support color format %d", 3337 mComponentName.c_str(), colorFormat); 3338 err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */); 3339 } 3340 } else { 3341 err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */); 3342 } 3343 3344 if (err != OK) { 3345 return err; 3346 } 3347 3348 // Set the component input buffer number to be |tmp|. If succeed, 3349 // component will set input port buffer number to be |tmp|. If fail, 3350 // component will keep the same buffer number as before. 3351 if (msg->findInt32("android._num-input-buffers", &tmp)) { 3352 err = setPortBufferNum(kPortIndexInput, tmp); 3353 if (err != OK) 3354 return err; 3355 } 3356 3357 // Set the component output buffer number to be |tmp|. If succeed, 3358 // component will set output port buffer number to be |tmp|. If fail, 3359 // component will keep the same buffer number as before. 3360 if (msg->findInt32("android._num-output-buffers", &tmp)) { 3361 err = setPortBufferNum(kPortIndexOutput, tmp); 3362 if (err != OK) 3363 return err; 3364 } 3365 3366 int32_t frameRateInt; 3367 float frameRateFloat; 3368 if (!msg->findFloat("frame-rate", &frameRateFloat)) { 3369 if (!msg->findInt32("frame-rate", &frameRateInt)) { 3370 frameRateInt = -1; 3371 } 3372 frameRateFloat = (float)frameRateInt; 3373 } 3374 3375 err = setVideoFormatOnPort( 3376 kPortIndexInput, width, height, compressionFormat, frameRateFloat); 3377 3378 if (err != OK) { 3379 return err; 3380 } 3381 3382 err = setVideoFormatOnPort( 3383 kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused); 3384 3385 if (err != OK) { 3386 return err; 3387 } 3388 3389 err = setColorAspectsForVideoDecoder( 3390 width, height, haveNativeWindow | usingSwRenderer, msg, outputFormat); 3391 if (err == ERROR_UNSUPPORTED) { // support is optional 3392 err = OK; 3393 } 3394 3395 if (err != OK) { 3396 return err; 3397 } 3398 3399 err = setHDRStaticInfoForVideoCodec(kPortIndexOutput, msg, outputFormat); 3400 if (err == ERROR_UNSUPPORTED) { // support is optional 3401 err = OK; 3402 } 3403 return err; 3404} 3405 3406status_t ACodec::initDescribeColorAspectsIndex() { 3407 status_t err = mOMXNode->getExtensionIndex( 3408 "OMX.google.android.index.describeColorAspects", &mDescribeColorAspectsIndex); 3409 if (err != OK) { 3410 mDescribeColorAspectsIndex = (OMX_INDEXTYPE)0; 3411 } 3412 return err; 3413} 3414 3415status_t ACodec::setCodecColorAspects(DescribeColorAspectsParams ¶ms, bool verify) { 3416 status_t err = ERROR_UNSUPPORTED; 3417 if (mDescribeColorAspectsIndex) { 3418 err = mOMXNode->setConfig(mDescribeColorAspectsIndex, ¶ms, sizeof(params)); 3419 } 3420 ALOGV("[%s] setting color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)", 3421 mComponentName.c_str(), 3422 params.sAspects.mRange, asString(params.sAspects.mRange), 3423 params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries), 3424 params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs), 3425 params.sAspects.mTransfer, asString(params.sAspects.mTransfer), 3426 err, asString(err)); 3427 3428 if (verify && err == OK) { 3429 err = getCodecColorAspects(params); 3430 } 3431 3432 ALOGW_IF(err == ERROR_UNSUPPORTED && mDescribeColorAspectsIndex, 3433 "[%s] setting color aspects failed even though codec advertises support", 3434 mComponentName.c_str()); 3435 return err; 3436} 3437 3438status_t ACodec::setColorAspectsForVideoDecoder( 3439 int32_t width, int32_t height, bool usingNativeWindow, 3440 const sp<AMessage> &configFormat, sp<AMessage> &outputFormat) { 3441 DescribeColorAspectsParams params; 3442 InitOMXParams(¶ms); 3443 params.nPortIndex = kPortIndexOutput; 3444 3445 getColorAspectsFromFormat(configFormat, params.sAspects); 3446 if (usingNativeWindow) { 3447 setDefaultCodecColorAspectsIfNeeded(params.sAspects, width, height); 3448 // The default aspects will be set back to the output format during the 3449 // getFormat phase of configure(). Set non-Unspecified values back into the 3450 // format, in case component does not support this enumeration. 3451 setColorAspectsIntoFormat(params.sAspects, outputFormat); 3452 } 3453 3454 (void)initDescribeColorAspectsIndex(); 3455 3456 // communicate color aspects to codec 3457 return setCodecColorAspects(params); 3458} 3459 3460status_t ACodec::getCodecColorAspects(DescribeColorAspectsParams ¶ms) { 3461 status_t err = ERROR_UNSUPPORTED; 3462 if (mDescribeColorAspectsIndex) { 3463 err = mOMXNode->getConfig(mDescribeColorAspectsIndex, ¶ms, sizeof(params)); 3464 } 3465 ALOGV("[%s] got color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)", 3466 mComponentName.c_str(), 3467 params.sAspects.mRange, asString(params.sAspects.mRange), 3468 params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries), 3469 params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs), 3470 params.sAspects.mTransfer, asString(params.sAspects.mTransfer), 3471 err, asString(err)); 3472 if (params.bRequestingDataSpace) { 3473 ALOGV("for dataspace %#x", params.nDataSpace); 3474 } 3475 if (err == ERROR_UNSUPPORTED && mDescribeColorAspectsIndex 3476 && !params.bRequestingDataSpace && !params.bDataSpaceChanged) { 3477 ALOGW("[%s] getting color aspects failed even though codec advertises support", 3478 mComponentName.c_str()); 3479 } 3480 return err; 3481} 3482 3483status_t ACodec::getInputColorAspectsForVideoEncoder(sp<AMessage> &format) { 3484 DescribeColorAspectsParams params; 3485 InitOMXParams(¶ms); 3486 params.nPortIndex = kPortIndexInput; 3487 status_t err = getCodecColorAspects(params); 3488 if (err == OK) { 3489 // we only set encoder input aspects if codec supports them 3490 setColorAspectsIntoFormat(params.sAspects, format, true /* force */); 3491 } 3492 return err; 3493} 3494 3495status_t ACodec::getDataSpace( 3496 DescribeColorAspectsParams ¶ms, android_dataspace *dataSpace /* nonnull */, 3497 bool tryCodec) { 3498 status_t err = OK; 3499 if (tryCodec) { 3500 // request dataspace guidance from codec. 3501 params.bRequestingDataSpace = OMX_TRUE; 3502 err = getCodecColorAspects(params); 3503 params.bRequestingDataSpace = OMX_FALSE; 3504 if (err == OK && params.nDataSpace != HAL_DATASPACE_UNKNOWN) { 3505 *dataSpace = (android_dataspace)params.nDataSpace; 3506 return err; 3507 } else if (err == ERROR_UNSUPPORTED) { 3508 // ignore not-implemented error for dataspace requests 3509 err = OK; 3510 } 3511 } 3512 3513 // this returns legacy versions if available 3514 *dataSpace = getDataSpaceForColorAspects(params.sAspects, true /* mayexpand */); 3515 ALOGV("[%s] using color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) " 3516 "and dataspace %#x", 3517 mComponentName.c_str(), 3518 params.sAspects.mRange, asString(params.sAspects.mRange), 3519 params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries), 3520 params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs), 3521 params.sAspects.mTransfer, asString(params.sAspects.mTransfer), 3522 *dataSpace); 3523 return err; 3524} 3525 3526 3527status_t ACodec::getColorAspectsAndDataSpaceForVideoDecoder( 3528 int32_t width, int32_t height, const sp<AMessage> &configFormat, sp<AMessage> &outputFormat, 3529 android_dataspace *dataSpace) { 3530 DescribeColorAspectsParams params; 3531 InitOMXParams(¶ms); 3532 params.nPortIndex = kPortIndexOutput; 3533 3534 // reset default format and get resulting format 3535 getColorAspectsFromFormat(configFormat, params.sAspects); 3536 if (dataSpace != NULL) { 3537 setDefaultCodecColorAspectsIfNeeded(params.sAspects, width, height); 3538 } 3539 status_t err = setCodecColorAspects(params, true /* readBack */); 3540 3541 // we always set specified aspects for decoders 3542 setColorAspectsIntoFormat(params.sAspects, outputFormat); 3543 3544 if (dataSpace != NULL) { 3545 status_t res = getDataSpace(params, dataSpace, err == OK /* tryCodec */); 3546 if (err == OK) { 3547 err = res; 3548 } 3549 } 3550 3551 return err; 3552} 3553 3554// initial video encoder setup for bytebuffer mode 3555status_t ACodec::setColorAspectsForVideoEncoder( 3556 const sp<AMessage> &configFormat, sp<AMessage> &outputFormat, sp<AMessage> &inputFormat) { 3557 // copy config to output format as this is not exposed via getFormat 3558 copyColorConfig(configFormat, outputFormat); 3559 3560 DescribeColorAspectsParams params; 3561 InitOMXParams(¶ms); 3562 params.nPortIndex = kPortIndexInput; 3563 getColorAspectsFromFormat(configFormat, params.sAspects); 3564 3565 (void)initDescribeColorAspectsIndex(); 3566 3567 int32_t usingRecorder; 3568 if (configFormat->findInt32("android._using-recorder", &usingRecorder) && usingRecorder) { 3569 android_dataspace dataSpace = HAL_DATASPACE_BT709; 3570 int32_t width, height; 3571 if (configFormat->findInt32("width", &width) 3572 && configFormat->findInt32("height", &height)) { 3573 setDefaultCodecColorAspectsIfNeeded(params.sAspects, width, height); 3574 status_t err = getDataSpace( 3575 params, &dataSpace, mDescribeColorAspectsIndex /* tryCodec */); 3576 if (err != OK) { 3577 return err; 3578 } 3579 setColorAspectsIntoFormat(params.sAspects, outputFormat); 3580 } 3581 inputFormat->setInt32("android._dataspace", (int32_t)dataSpace); 3582 } 3583 3584 // communicate color aspects to codec, but do not allow change of the platform aspects 3585 ColorAspects origAspects = params.sAspects; 3586 for (int triesLeft = 2; --triesLeft >= 0; ) { 3587 status_t err = setCodecColorAspects(params, true /* readBack */); 3588 if (err != OK 3589 || !ColorUtils::checkIfAspectsChangedAndUnspecifyThem( 3590 params.sAspects, origAspects, true /* usePlatformAspects */)) { 3591 return err; 3592 } 3593 ALOGW_IF(triesLeft == 0, "[%s] Codec repeatedly changed requested ColorAspects.", 3594 mComponentName.c_str()); 3595 } 3596 return OK; 3597} 3598 3599status_t ACodec::setHDRStaticInfoForVideoCodec( 3600 OMX_U32 portIndex, const sp<AMessage> &configFormat, sp<AMessage> &outputFormat) { 3601 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 3602 3603 DescribeHDRStaticInfoParams params; 3604 InitOMXParams(¶ms); 3605 params.nPortIndex = portIndex; 3606 3607 HDRStaticInfo *info = ¶ms.sInfo; 3608 if (getHDRStaticInfoFromFormat(configFormat, info)) { 3609 setHDRStaticInfoIntoFormat(params.sInfo, outputFormat); 3610 } 3611 3612 (void)initDescribeHDRStaticInfoIndex(); 3613 3614 // communicate HDR static Info to codec 3615 return setHDRStaticInfo(params); 3616} 3617 3618// subsequent initial video encoder setup for surface mode 3619status_t ACodec::setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace( 3620 android_dataspace *dataSpace /* nonnull */) { 3621 DescribeColorAspectsParams params; 3622 InitOMXParams(¶ms); 3623 params.nPortIndex = kPortIndexInput; 3624 ColorAspects &aspects = params.sAspects; 3625 3626 // reset default format and store resulting format into both input and output formats 3627 getColorAspectsFromFormat(mConfigFormat, aspects); 3628 int32_t width, height; 3629 if (mInputFormat->findInt32("width", &width) && mInputFormat->findInt32("height", &height)) { 3630 setDefaultCodecColorAspectsIfNeeded(aspects, width, height); 3631 } 3632 setColorAspectsIntoFormat(aspects, mInputFormat); 3633 setColorAspectsIntoFormat(aspects, mOutputFormat); 3634 3635 // communicate color aspects to codec, but do not allow any change 3636 ColorAspects origAspects = aspects; 3637 status_t err = OK; 3638 for (int triesLeft = 2; mDescribeColorAspectsIndex && --triesLeft >= 0; ) { 3639 status_t err = setCodecColorAspects(params, true /* readBack */); 3640 if (err != OK || !ColorUtils::checkIfAspectsChangedAndUnspecifyThem(aspects, origAspects)) { 3641 break; 3642 } 3643 ALOGW_IF(triesLeft == 0, "[%s] Codec repeatedly changed requested ColorAspects.", 3644 mComponentName.c_str()); 3645 } 3646 3647 *dataSpace = HAL_DATASPACE_BT709; 3648 aspects = origAspects; // restore desired color aspects 3649 status_t res = getDataSpace( 3650 params, dataSpace, err == OK && mDescribeColorAspectsIndex /* tryCodec */); 3651 if (err == OK) { 3652 err = res; 3653 } 3654 mInputFormat->setInt32("android._dataspace", (int32_t)*dataSpace); 3655 mInputFormat->setBuffer( 3656 "android._color-aspects", ABuffer::CreateAsCopy(&aspects, sizeof(aspects))); 3657 3658 // update input format with codec supported color aspects (basically set unsupported 3659 // aspects to Unspecified) 3660 if (err == OK) { 3661 (void)getInputColorAspectsForVideoEncoder(mInputFormat); 3662 } 3663 3664 ALOGV("set default color aspects, updated input format to %s, output format to %s", 3665 mInputFormat->debugString(4).c_str(), mOutputFormat->debugString(4).c_str()); 3666 3667 return err; 3668} 3669 3670status_t ACodec::getHDRStaticInfoForVideoCodec(OMX_U32 portIndex, sp<AMessage> &format) { 3671 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 3672 DescribeHDRStaticInfoParams params; 3673 InitOMXParams(¶ms); 3674 params.nPortIndex = portIndex; 3675 3676 status_t err = getHDRStaticInfo(params); 3677 if (err == OK) { 3678 // we only set decodec output HDRStaticInfo if codec supports them 3679 setHDRStaticInfoIntoFormat(params.sInfo, format); 3680 } 3681 return err; 3682} 3683 3684status_t ACodec::initDescribeHDRStaticInfoIndex() { 3685 status_t err = mOMXNode->getExtensionIndex( 3686 "OMX.google.android.index.describeHDRStaticInfo", &mDescribeHDRStaticInfoIndex); 3687 if (err != OK) { 3688 mDescribeHDRStaticInfoIndex = (OMX_INDEXTYPE)0; 3689 } 3690 return err; 3691} 3692 3693status_t ACodec::setHDRStaticInfo(const DescribeHDRStaticInfoParams ¶ms) { 3694 status_t err = ERROR_UNSUPPORTED; 3695 if (mDescribeHDRStaticInfoIndex) { 3696 err = mOMXNode->setConfig(mDescribeHDRStaticInfoIndex, ¶ms, sizeof(params)); 3697 } 3698 3699 const HDRStaticInfo *info = ¶ms.sInfo; 3700 ALOGV("[%s] setting HDRStaticInfo (R: %u %u, G: %u %u, B: %u, %u, W: %u, %u, " 3701 "MaxDispL: %u, MinDispL: %u, MaxContentL: %u, MaxFrameAvgL: %u)", 3702 mComponentName.c_str(), 3703 info->sType1.mR.x, info->sType1.mR.y, info->sType1.mG.x, info->sType1.mG.y, 3704 info->sType1.mB.x, info->sType1.mB.y, info->sType1.mW.x, info->sType1.mW.y, 3705 info->sType1.mMaxDisplayLuminance, info->sType1.mMinDisplayLuminance, 3706 info->sType1.mMaxContentLightLevel, info->sType1.mMaxFrameAverageLightLevel); 3707 3708 ALOGW_IF(err == ERROR_UNSUPPORTED && mDescribeHDRStaticInfoIndex, 3709 "[%s] setting HDRStaticInfo failed even though codec advertises support", 3710 mComponentName.c_str()); 3711 return err; 3712} 3713 3714status_t ACodec::getHDRStaticInfo(DescribeHDRStaticInfoParams ¶ms) { 3715 status_t err = ERROR_UNSUPPORTED; 3716 if (mDescribeHDRStaticInfoIndex) { 3717 err = mOMXNode->getConfig(mDescribeHDRStaticInfoIndex, ¶ms, sizeof(params)); 3718 } 3719 3720 ALOGW_IF(err == ERROR_UNSUPPORTED && mDescribeHDRStaticInfoIndex, 3721 "[%s] getting HDRStaticInfo failed even though codec advertises support", 3722 mComponentName.c_str()); 3723 return err; 3724} 3725 3726status_t ACodec::setupVideoEncoder( 3727 const char *mime, const sp<AMessage> &msg, 3728 sp<AMessage> &outputFormat, sp<AMessage> &inputFormat) { 3729 int32_t tmp; 3730 if (!msg->findInt32("color-format", &tmp)) { 3731 return INVALID_OPERATION; 3732 } 3733 3734 OMX_COLOR_FORMATTYPE colorFormat = 3735 static_cast<OMX_COLOR_FORMATTYPE>(tmp); 3736 3737 status_t err = setVideoPortFormatType( 3738 kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat); 3739 3740 if (err != OK) { 3741 ALOGE("[%s] does not support color format %d", 3742 mComponentName.c_str(), colorFormat); 3743 3744 return err; 3745 } 3746 3747 /* Input port configuration */ 3748 3749 OMX_PARAM_PORTDEFINITIONTYPE def; 3750 InitOMXParams(&def); 3751 3752 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 3753 3754 def.nPortIndex = kPortIndexInput; 3755 3756 err = mOMXNode->getParameter( 3757 OMX_IndexParamPortDefinition, &def, sizeof(def)); 3758 3759 if (err != OK) { 3760 return err; 3761 } 3762 3763 OMX_VIDEO_CONTROLRATETYPE bitrateMode; 3764 int32_t width, height, bitrate = 0, quality; 3765 if (!msg->findInt32("width", &width) 3766 || !msg->findInt32("height", &height) 3767 || !findVideoBitrateControlInfo( 3768 msg, &bitrateMode, &bitrate, &quality)) { 3769 return INVALID_OPERATION; 3770 } 3771 3772 video_def->nFrameWidth = width; 3773 video_def->nFrameHeight = height; 3774 3775 int32_t stride; 3776 if (!msg->findInt32("stride", &stride)) { 3777 stride = width; 3778 } 3779 3780 video_def->nStride = stride; 3781 3782 int32_t sliceHeight; 3783 if (!msg->findInt32("slice-height", &sliceHeight)) { 3784 sliceHeight = height; 3785 } 3786 3787 video_def->nSliceHeight = sliceHeight; 3788 3789 def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2; 3790 3791 float framerate; 3792 if (!msg->findFloat("frame-rate", &framerate)) { 3793 int32_t tmp; 3794 if (!msg->findInt32("frame-rate", &tmp)) { 3795 return INVALID_OPERATION; 3796 } 3797 mFps = (double)tmp; 3798 } else { 3799 mFps = (double)framerate; 3800 } 3801 // propagate framerate to the output so that the muxer has it 3802 outputFormat->setInt32("frame-rate", (int32_t)mFps); 3803 3804 video_def->xFramerate = (OMX_U32)(mFps * 65536); 3805 video_def->eCompressionFormat = OMX_VIDEO_CodingUnused; 3806 // this is redundant as it was already set up in setVideoPortFormatType 3807 // FIXME for now skip this only for flexible YUV formats 3808 if (colorFormat != OMX_COLOR_FormatYUV420Flexible) { 3809 video_def->eColorFormat = colorFormat; 3810 } 3811 3812 err = mOMXNode->setParameter( 3813 OMX_IndexParamPortDefinition, &def, sizeof(def)); 3814 3815 if (err != OK) { 3816 ALOGE("[%s] failed to set input port definition parameters.", 3817 mComponentName.c_str()); 3818 3819 return err; 3820 } 3821 3822 /* Output port configuration */ 3823 3824 OMX_VIDEO_CODINGTYPE compressionFormat; 3825 err = GetVideoCodingTypeFromMime(mime, &compressionFormat); 3826 3827 if (err != OK) { 3828 return err; 3829 } 3830 3831 err = setVideoPortFormatType( 3832 kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused); 3833 3834 if (err != OK) { 3835 ALOGE("[%s] does not support compression format %d", 3836 mComponentName.c_str(), compressionFormat); 3837 3838 return err; 3839 } 3840 3841 def.nPortIndex = kPortIndexOutput; 3842 3843 err = mOMXNode->getParameter( 3844 OMX_IndexParamPortDefinition, &def, sizeof(def)); 3845 3846 if (err != OK) { 3847 return err; 3848 } 3849 3850 video_def->nFrameWidth = width; 3851 video_def->nFrameHeight = height; 3852 video_def->xFramerate = 0; 3853 video_def->nBitrate = bitrate; 3854 video_def->eCompressionFormat = compressionFormat; 3855 video_def->eColorFormat = OMX_COLOR_FormatUnused; 3856 3857 err = mOMXNode->setParameter( 3858 OMX_IndexParamPortDefinition, &def, sizeof(def)); 3859 3860 if (err != OK) { 3861 ALOGE("[%s] failed to set output port definition parameters.", 3862 mComponentName.c_str()); 3863 3864 return err; 3865 } 3866 3867 int32_t intraRefreshPeriod = 0; 3868 if (msg->findInt32("intra-refresh-period", &intraRefreshPeriod) 3869 && intraRefreshPeriod >= 0) { 3870 err = setIntraRefreshPeriod((uint32_t)intraRefreshPeriod, true); 3871 if (err != OK) { 3872 ALOGI("[%s] failed setIntraRefreshPeriod. Failure is fine since this key is optional", 3873 mComponentName.c_str()); 3874 err = OK; 3875 } 3876 } 3877 3878 configureEncoderLatency(msg); 3879 3880 switch (compressionFormat) { 3881 case OMX_VIDEO_CodingMPEG4: 3882 err = setupMPEG4EncoderParameters(msg); 3883 break; 3884 3885 case OMX_VIDEO_CodingH263: 3886 err = setupH263EncoderParameters(msg); 3887 break; 3888 3889 case OMX_VIDEO_CodingAVC: 3890 err = setupAVCEncoderParameters(msg); 3891 break; 3892 3893 case OMX_VIDEO_CodingHEVC: 3894 case OMX_VIDEO_CodingImageHEIC: 3895 err = setupHEVCEncoderParameters(msg, outputFormat); 3896 break; 3897 3898 case OMX_VIDEO_CodingVP8: 3899 case OMX_VIDEO_CodingVP9: 3900 err = setupVPXEncoderParameters(msg, outputFormat); 3901 break; 3902 3903 default: 3904 break; 3905 } 3906 3907 if (err != OK) { 3908 return err; 3909 } 3910 3911 // Set up color aspects on input, but propagate them to the output format, as they will 3912 // not be read back from encoder. 3913 err = setColorAspectsForVideoEncoder(msg, outputFormat, inputFormat); 3914 if (err == ERROR_UNSUPPORTED) { 3915 ALOGI("[%s] cannot encode color aspects. Ignoring.", mComponentName.c_str()); 3916 err = OK; 3917 } 3918 3919 if (err != OK) { 3920 return err; 3921 } 3922 3923 err = setHDRStaticInfoForVideoCodec(kPortIndexInput, msg, outputFormat); 3924 if (err == ERROR_UNSUPPORTED) { // support is optional 3925 ALOGI("[%s] cannot encode HDR static metadata. Ignoring.", mComponentName.c_str()); 3926 err = OK; 3927 } 3928 3929 if (err != OK) { 3930 return err; 3931 } 3932 3933 switch (compressionFormat) { 3934 case OMX_VIDEO_CodingAVC: 3935 case OMX_VIDEO_CodingHEVC: 3936 err = configureTemporalLayers(msg, true /* inConfigure */, outputFormat); 3937 if (err != OK) { 3938 err = OK; // ignore failure 3939 } 3940 break; 3941 3942 case OMX_VIDEO_CodingVP8: 3943 case OMX_VIDEO_CodingVP9: 3944 // TODO: do we need to support android.generic layering? webrtc layering is 3945 // already set up in setupVPXEncoderParameters. 3946 break; 3947 3948 default: 3949 break; 3950 } 3951 3952 if (err == OK) { 3953 ALOGI("setupVideoEncoder succeeded"); 3954 } 3955 3956 return err; 3957} 3958 3959status_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) { 3960 OMX_VIDEO_PARAM_INTRAREFRESHTYPE params; 3961 InitOMXParams(¶ms); 3962 params.nPortIndex = kPortIndexOutput; 3963 3964 params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode); 3965 3966 if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic || 3967 params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) { 3968 int32_t mbs; 3969 if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) { 3970 return INVALID_OPERATION; 3971 } 3972 params.nCirMBs = mbs; 3973 } 3974 3975 if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive || 3976 params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) { 3977 int32_t mbs; 3978 if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) { 3979 return INVALID_OPERATION; 3980 } 3981 params.nAirMBs = mbs; 3982 3983 int32_t ref; 3984 if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) { 3985 return INVALID_OPERATION; 3986 } 3987 params.nAirRef = ref; 3988 } 3989 3990 status_t err = mOMXNode->setParameter( 3991 OMX_IndexParamVideoIntraRefresh, ¶ms, sizeof(params)); 3992 return err; 3993} 3994 3995static OMX_U32 setPFramesSpacing( 3996 float iFramesInterval /* seconds */, int32_t frameRate, uint32_t BFramesSpacing = 0) { 3997 // BFramesSpacing is the number of B frames between I/P frames 3998 // PFramesSpacing (the value to be returned) is the number of P frames between I frames 3999 // 4000 // keyFrameInterval = ((PFramesSpacing + 1) * BFramesSpacing) + PFramesSpacing + 1 4001 // ^^^ ^^^ ^^^ 4002 // number of B frames number of P I frame 4003 // 4004 // = (PFramesSpacing + 1) * (BFramesSpacing + 1) 4005 // 4006 // E.g. 4007 // I P I : I-interval: 8, nPFrames 1, nBFrames 3 4008 // BBB BBB 4009 4010 if (iFramesInterval < 0) { // just 1 key frame 4011 return 0xFFFFFFFE; // don't use maxint as key-frame-interval calculation will add 1 4012 } else if (iFramesInterval == 0) { // just key frames 4013 return 0; 4014 } 4015 4016 // round down as key-frame-interval is an upper limit 4017 uint32_t keyFrameInterval = uint32_t(frameRate * iFramesInterval); 4018 OMX_U32 ret = keyFrameInterval / (BFramesSpacing + 1); 4019 return ret > 0 ? ret - 1 : 0; 4020} 4021 4022status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) { 4023 int32_t bitrate; 4024 float iFrameInterval; 4025 if (!msg->findInt32("bitrate", &bitrate) 4026 || !msg->findAsFloat("i-frame-interval", &iFrameInterval)) { 4027 return INVALID_OPERATION; 4028 } 4029 4030 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getVideoBitrateMode(msg); 4031 4032 float frameRate; 4033 if (!msg->findFloat("frame-rate", &frameRate)) { 4034 int32_t tmp; 4035 if (!msg->findInt32("frame-rate", &tmp)) { 4036 return INVALID_OPERATION; 4037 } 4038 frameRate = (float)tmp; 4039 } 4040 4041 OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type; 4042 InitOMXParams(&mpeg4type); 4043 mpeg4type.nPortIndex = kPortIndexOutput; 4044 4045 status_t err = mOMXNode->getParameter( 4046 OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); 4047 4048 if (err != OK) { 4049 return err; 4050 } 4051 4052 mpeg4type.nSliceHeaderSpacing = 0; 4053 mpeg4type.bSVH = OMX_FALSE; 4054 mpeg4type.bGov = OMX_FALSE; 4055 4056 mpeg4type.nAllowedPictureTypes = 4057 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 4058 4059 mpeg4type.nBFrames = 0; 4060 mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, mpeg4type.nBFrames); 4061 if (mpeg4type.nPFrames == 0) { 4062 mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 4063 } 4064 mpeg4type.nIDCVLCThreshold = 0; 4065 mpeg4type.bACPred = OMX_TRUE; 4066 mpeg4type.nMaxPacketSize = 256; 4067 mpeg4type.nTimeIncRes = 1000; 4068 mpeg4type.nHeaderExtension = 0; 4069 mpeg4type.bReversibleVLC = OMX_FALSE; 4070 4071 int32_t profile; 4072 if (msg->findInt32("profile", &profile)) { 4073 int32_t level; 4074 if (!msg->findInt32("level", &level)) { 4075 return INVALID_OPERATION; 4076 } 4077 4078 err = verifySupportForProfileAndLevel(kPortIndexOutput, profile, level); 4079 4080 if (err != OK) { 4081 return err; 4082 } 4083 4084 mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile); 4085 mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level); 4086 } 4087 4088 err = mOMXNode->setParameter( 4089 OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); 4090 4091 if (err != OK) { 4092 return err; 4093 } 4094 4095 err = configureBitrate(bitrateMode, bitrate); 4096 4097 if (err != OK) { 4098 return err; 4099 } 4100 4101 return setupErrorCorrectionParameters(); 4102} 4103 4104status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) { 4105 int32_t bitrate; 4106 float iFrameInterval; 4107 if (!msg->findInt32("bitrate", &bitrate) 4108 || !msg->findAsFloat("i-frame-interval", &iFrameInterval)) { 4109 return INVALID_OPERATION; 4110 } 4111 4112 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getVideoBitrateMode(msg); 4113 4114 float frameRate; 4115 if (!msg->findFloat("frame-rate", &frameRate)) { 4116 int32_t tmp; 4117 if (!msg->findInt32("frame-rate", &tmp)) { 4118 return INVALID_OPERATION; 4119 } 4120 frameRate = (float)tmp; 4121 } 4122 4123 OMX_VIDEO_PARAM_H263TYPE h263type; 4124 InitOMXParams(&h263type); 4125 h263type.nPortIndex = kPortIndexOutput; 4126 4127 status_t err = mOMXNode->getParameter( 4128 OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); 4129 4130 if (err != OK) { 4131 return err; 4132 } 4133 4134 h263type.nAllowedPictureTypes = 4135 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 4136 4137 h263type.nBFrames = 0; 4138 h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h263type.nBFrames); 4139 if (h263type.nPFrames == 0) { 4140 h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 4141 } 4142 4143 int32_t profile; 4144 if (msg->findInt32("profile", &profile)) { 4145 int32_t level; 4146 if (!msg->findInt32("level", &level)) { 4147 return INVALID_OPERATION; 4148 } 4149 4150 err = verifySupportForProfileAndLevel(kPortIndexOutput, profile, level); 4151 4152 if (err != OK) { 4153 return err; 4154 } 4155 4156 h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile); 4157 h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level); 4158 } 4159 4160 h263type.bPLUSPTYPEAllowed = OMX_FALSE; 4161 h263type.bForceRoundingTypeToZero = OMX_FALSE; 4162 h263type.nPictureHeaderRepetition = 0; 4163 h263type.nGOBHeaderInterval = 0; 4164 4165 err = mOMXNode->setParameter( 4166 OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); 4167 4168 if (err != OK) { 4169 return err; 4170 } 4171 4172 err = configureBitrate(bitrateMode, bitrate); 4173 4174 if (err != OK) { 4175 return err; 4176 } 4177 4178 return setupErrorCorrectionParameters(); 4179} 4180 4181// static 4182int /* OMX_VIDEO_AVCLEVELTYPE */ ACodec::getAVCLevelFor( 4183 int width, int height, int rate, int bitrate, 4184 OMX_VIDEO_AVCPROFILEEXTTYPE profile) { 4185 // convert bitrate to main/baseline profile kbps equivalent 4186 switch ((uint32_t)profile) { 4187 case OMX_VIDEO_AVCProfileHigh10: 4188 bitrate = divUp(bitrate, 3000); break; 4189 case OMX_VIDEO_AVCProfileConstrainedHigh: 4190 case OMX_VIDEO_AVCProfileHigh: 4191 bitrate = divUp(bitrate, 1250); break; 4192 default: 4193 bitrate = divUp(bitrate, 1000); break; 4194 } 4195 4196 // convert size and rate to MBs 4197 width = divUp(width, 16); 4198 height = divUp(height, 16); 4199 int mbs = width * height; 4200 rate *= mbs; 4201 int maxDimension = max(width, height); 4202 4203 static const int limits[][5] = { 4204 /* MBps MB dim bitrate level */ 4205 { 1485, 99, 28, 64, OMX_VIDEO_AVCLevel1 }, 4206 { 1485, 99, 28, 128, OMX_VIDEO_AVCLevel1b }, 4207 { 3000, 396, 56, 192, OMX_VIDEO_AVCLevel11 }, 4208 { 6000, 396, 56, 384, OMX_VIDEO_AVCLevel12 }, 4209 { 11880, 396, 56, 768, OMX_VIDEO_AVCLevel13 }, 4210 { 11880, 396, 56, 2000, OMX_VIDEO_AVCLevel2 }, 4211 { 19800, 792, 79, 4000, OMX_VIDEO_AVCLevel21 }, 4212 { 20250, 1620, 113, 4000, OMX_VIDEO_AVCLevel22 }, 4213 { 40500, 1620, 113, 10000, OMX_VIDEO_AVCLevel3 }, 4214 { 108000, 3600, 169, 14000, OMX_VIDEO_AVCLevel31 }, 4215 { 216000, 5120, 202, 20000, OMX_VIDEO_AVCLevel32 }, 4216 { 245760, 8192, 256, 20000, OMX_VIDEO_AVCLevel4 }, 4217 { 245760, 8192, 256, 50000, OMX_VIDEO_AVCLevel41 }, 4218 { 522240, 8704, 263, 50000, OMX_VIDEO_AVCLevel42 }, 4219 { 589824, 22080, 420, 135000, OMX_VIDEO_AVCLevel5 }, 4220 { 983040, 36864, 543, 240000, OMX_VIDEO_AVCLevel51 }, 4221 { 2073600, 36864, 543, 240000, OMX_VIDEO_AVCLevel52 }, 4222 }; 4223 4224 for (size_t i = 0; i < ARRAY_SIZE(limits); i++) { 4225 const int (&limit)[5] = limits[i]; 4226 if (rate <= limit[0] && mbs <= limit[1] && maxDimension <= limit[2] 4227 && bitrate <= limit[3]) { 4228 return limit[4]; 4229 } 4230 } 4231 return 0; 4232} 4233 4234status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) { 4235 int32_t bitrate; 4236 float iFrameInterval; 4237 if (!msg->findInt32("bitrate", &bitrate) 4238 || !msg->findAsFloat("i-frame-interval", &iFrameInterval)) { 4239 return INVALID_OPERATION; 4240 } 4241 4242 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getVideoBitrateMode(msg); 4243 4244 float frameRate; 4245 if (!msg->findFloat("frame-rate", &frameRate)) { 4246 int32_t tmp; 4247 if (!msg->findInt32("frame-rate", &tmp)) { 4248 return INVALID_OPERATION; 4249 } 4250 frameRate = (float)tmp; 4251 } 4252 4253 status_t err = OK; 4254 int32_t intraRefreshMode = 0; 4255 if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) { 4256 err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode); 4257 if (err != OK) { 4258 ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x", 4259 err, intraRefreshMode); 4260 return err; 4261 } 4262 } 4263 4264 OMX_VIDEO_PARAM_AVCTYPE h264type; 4265 InitOMXParams(&h264type); 4266 h264type.nPortIndex = kPortIndexOutput; 4267 4268 err = mOMXNode->getParameter( 4269 OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 4270 4271 if (err != OK) { 4272 return err; 4273 } 4274 4275 h264type.nAllowedPictureTypes = 4276 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 4277 4278 int32_t profile; 4279 if (msg->findInt32("profile", &profile)) { 4280 int32_t level; 4281 if (!msg->findInt32("level", &level)) { 4282 return INVALID_OPERATION; 4283 } 4284 4285 err = verifySupportForProfileAndLevel(kPortIndexOutput, profile, level); 4286 4287 if (err != OK) { 4288 return err; 4289 } 4290 4291 h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile); 4292 h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level); 4293 } else { 4294 h264type.eProfile = OMX_VIDEO_AVCProfileBaseline; 4295#if 0 /* DON'T YET DEFAULT TO HIGHEST PROFILE */ 4296 // Use largest supported profile for AVC recording if profile is not specified. 4297 for (OMX_VIDEO_AVCPROFILETYPE profile : { 4298 OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCProfileMain }) { 4299 if (verifySupportForProfileAndLevel(kPortIndexOutput, profile, 0) == OK) { 4300 h264type.eProfile = profile; 4301 break; 4302 } 4303 } 4304#endif 4305 } 4306 4307 ALOGI("setupAVCEncoderParameters with [profile: %s] [level: %s]", 4308 asString(h264type.eProfile), asString(h264type.eLevel)); 4309 4310 if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) { 4311 h264type.nSliceHeaderSpacing = 0; 4312 h264type.bUseHadamard = OMX_TRUE; 4313 h264type.nRefFrames = 1; 4314 h264type.nBFrames = 0; 4315 h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h264type.nBFrames); 4316 if (h264type.nPFrames == 0) { 4317 h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 4318 } 4319 h264type.nRefIdx10ActiveMinus1 = 0; 4320 h264type.nRefIdx11ActiveMinus1 = 0; 4321 h264type.bEntropyCodingCABAC = OMX_FALSE; 4322 h264type.bWeightedPPrediction = OMX_FALSE; 4323 h264type.bconstIpred = OMX_FALSE; 4324 h264type.bDirect8x8Inference = OMX_FALSE; 4325 h264type.bDirectSpatialTemporal = OMX_FALSE; 4326 h264type.nCabacInitIdc = 0; 4327 } else if (h264type.eProfile == OMX_VIDEO_AVCProfileMain || 4328 h264type.eProfile == OMX_VIDEO_AVCProfileHigh) { 4329 h264type.nSliceHeaderSpacing = 0; 4330 h264type.bUseHadamard = OMX_TRUE; 4331 h264type.nRefFrames = 2; 4332 h264type.nBFrames = mLatency == 0 ? 1 : std::min(1U, mLatency - 1); 4333 4334 // disable B-frames until MPEG4Writer can guarantee finalizing files with B-frames 4335 h264type.nRefFrames = 1; 4336 h264type.nBFrames = 0; 4337 4338 h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h264type.nBFrames); 4339 h264type.nAllowedPictureTypes = 4340 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 4341 h264type.nRefIdx10ActiveMinus1 = 0; 4342 h264type.nRefIdx11ActiveMinus1 = 0; 4343 h264type.bEntropyCodingCABAC = OMX_TRUE; 4344 h264type.bWeightedPPrediction = OMX_TRUE; 4345 h264type.bconstIpred = OMX_TRUE; 4346 h264type.bDirect8x8Inference = OMX_TRUE; 4347 h264type.bDirectSpatialTemporal = OMX_TRUE; 4348 h264type.nCabacInitIdc = 1; 4349 } 4350 4351 if (h264type.nBFrames != 0) { 4352 h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB; 4353 } 4354 4355 h264type.bEnableUEP = OMX_FALSE; 4356 h264type.bEnableFMO = OMX_FALSE; 4357 h264type.bEnableASO = OMX_FALSE; 4358 h264type.bEnableRS = OMX_FALSE; 4359 h264type.bFrameMBsOnly = OMX_TRUE; 4360 h264type.bMBAFF = OMX_FALSE; 4361 h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; 4362 4363 err = mOMXNode->setParameter( 4364 OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 4365 4366 if (err != OK) { 4367 return err; 4368 } 4369 4370 // TRICKY: if we are enabling temporal layering as well, some codecs may not support layering 4371 // when B-frames are enabled. Detect this now so we can disable B frames if temporal layering 4372 // is preferred. 4373 AString tsSchema; 4374 int32_t preferBFrames = (int32_t)false; 4375 if (msg->findString("ts-schema", &tsSchema) 4376 && (!msg->findInt32("android._prefer-b-frames", &preferBFrames) || !preferBFrames)) { 4377 OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE layering; 4378 InitOMXParams(&layering); 4379 layering.nPortIndex = kPortIndexOutput; 4380 if (mOMXNode->getParameter( 4381 (OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering, 4382 &layering, sizeof(layering)) == OK 4383 && layering.eSupportedPatterns 4384 && layering.nBLayerCountMax == 0) { 4385 h264type.nBFrames = 0; 4386 h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate, h264type.nBFrames); 4387 h264type.nAllowedPictureTypes &= ~OMX_VIDEO_PictureTypeB; 4388 ALOGI("disabling B-frames"); 4389 err = mOMXNode->setParameter( 4390 OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 4391 4392 if (err != OK) { 4393 return err; 4394 } 4395 } 4396 } 4397 4398 return configureBitrate(bitrateMode, bitrate); 4399} 4400 4401status_t ACodec::configureImageGrid( 4402 const sp<AMessage> &msg, sp<AMessage> &outputFormat) { 4403 int32_t tileWidth, tileHeight, gridRows, gridCols; 4404 if (!msg->findInt32("tile-width", &tileWidth) || 4405 !msg->findInt32("tile-height", &tileHeight) || 4406 !msg->findInt32("grid-rows", &gridRows) || 4407 !msg->findInt32("grid-cols", &gridCols)) { 4408 return OK; 4409 } 4410 4411 OMX_VIDEO_PARAM_ANDROID_IMAGEGRIDTYPE gridType; 4412 InitOMXParams(&gridType); 4413 gridType.nPortIndex = kPortIndexOutput; 4414 gridType.bEnabled = OMX_TRUE; 4415 gridType.nTileWidth = tileWidth; 4416 gridType.nTileHeight = tileHeight; 4417 gridType.nGridRows = gridRows; 4418 gridType.nGridCols = gridCols; 4419 4420 status_t err = mOMXNode->setParameter( 4421 (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidImageGrid, 4422 &gridType, sizeof(gridType)); 4423 4424 // for video encoders, grid config is only a hint. 4425 if (!mIsImage) { 4426 return OK; 4427 } 4428 4429 // image encoders must support grid config. 4430 if (err != OK) { 4431 return err; 4432 } 4433 4434 // query to get the image encoder's real grid config as it might be 4435 // different from the requested, and transfer that to the output. 4436 err = mOMXNode->getParameter( 4437 (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidImageGrid, 4438 &gridType, sizeof(gridType)); 4439 4440 if (err == OK && gridType.bEnabled) { 4441 outputFormat->setInt32("tile-width", gridType.nTileWidth); 4442 outputFormat->setInt32("tile-height", gridType.nTileHeight); 4443 outputFormat->setInt32("grid-rows", gridType.nGridRows); 4444 outputFormat->setInt32("grid-cols", gridType.nGridCols); 4445 } 4446 4447 return err; 4448} 4449 4450status_t ACodec::setupHEVCEncoderParameters( 4451 const sp<AMessage> &msg, sp<AMessage> &outputFormat) { 4452 OMX_VIDEO_CONTROLRATETYPE bitrateMode; 4453 int32_t bitrate, quality; 4454 if (!findVideoBitrateControlInfo(msg, &bitrateMode, &bitrate, &quality)) { 4455 return INVALID_OPERATION; 4456 } 4457 4458 OMX_VIDEO_PARAM_HEVCTYPE hevcType; 4459 InitOMXParams(&hevcType); 4460 hevcType.nPortIndex = kPortIndexOutput; 4461 4462 status_t err = OK; 4463 err = mOMXNode->getParameter( 4464 (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType)); 4465 if (err != OK) { 4466 return err; 4467 } 4468 4469 int32_t profile; 4470 if (msg->findInt32("profile", &profile)) { 4471 int32_t level; 4472 if (!msg->findInt32("level", &level)) { 4473 return INVALID_OPERATION; 4474 } 4475 4476 err = verifySupportForProfileAndLevel(kPortIndexOutput, profile, level); 4477 if (err != OK) { 4478 return err; 4479 } 4480 4481 hevcType.eProfile = static_cast<OMX_VIDEO_HEVCPROFILETYPE>(profile); 4482 hevcType.eLevel = static_cast<OMX_VIDEO_HEVCLEVELTYPE>(level); 4483 } 4484 // TODO: finer control? 4485 if (mIsImage) { 4486 hevcType.nKeyFrameInterval = 1; 4487 } else { 4488 float iFrameInterval; 4489 if (!msg->findAsFloat("i-frame-interval", &iFrameInterval)) { 4490 return INVALID_OPERATION; 4491 } 4492 4493 float frameRate; 4494 if (!msg->findFloat("frame-rate", &frameRate)) { 4495 int32_t tmp; 4496 if (!msg->findInt32("frame-rate", &tmp)) { 4497 return INVALID_OPERATION; 4498 } 4499 frameRate = (float)tmp; 4500 } 4501 4502 hevcType.nKeyFrameInterval = 4503 setPFramesSpacing(iFrameInterval, frameRate) + 1; 4504 } 4505 4506 4507 err = mOMXNode->setParameter( 4508 (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType)); 4509 if (err != OK) { 4510 return err; 4511 } 4512 4513 err = configureImageGrid(msg, outputFormat); 4514 4515 if (err != OK) { 4516 return err; 4517 } 4518 4519 return configureBitrate(bitrateMode, bitrate, quality); 4520} 4521 4522status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg, sp<AMessage> &outputFormat) { 4523 int32_t bitrate; 4524 float iFrameInterval = 0; 4525 size_t tsLayers = 0; 4526 OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE pattern = 4527 OMX_VIDEO_VPXTemporalLayerPatternNone; 4528 static const uint32_t kVp8LayerRateAlloction 4529 [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] 4530 [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] = { 4531 {100, 100, 100}, // 1 layer 4532 { 60, 100, 100}, // 2 layers {60%, 40%} 4533 { 40, 60, 100}, // 3 layers {40%, 20%, 40%} 4534 }; 4535 if (!msg->findInt32("bitrate", &bitrate)) { 4536 return INVALID_OPERATION; 4537 } 4538 msg->findAsFloat("i-frame-interval", &iFrameInterval); 4539 4540 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getVideoBitrateMode(msg); 4541 4542 float frameRate; 4543 if (!msg->findFloat("frame-rate", &frameRate)) { 4544 int32_t tmp; 4545 if (!msg->findInt32("frame-rate", &tmp)) { 4546 return INVALID_OPERATION; 4547 } 4548 frameRate = (float)tmp; 4549 } 4550 4551 AString tsSchema; 4552 OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE tsType = 4553 OMX_VIDEO_AndroidTemporalLayeringPatternNone; 4554 4555 if (msg->findString("ts-schema", &tsSchema)) { 4556 unsigned int numLayers = 0; 4557 unsigned int numBLayers = 0; 4558 int tags; 4559 char dummy; 4560 if (sscanf(tsSchema.c_str(), "webrtc.vp8.%u-layer%c", &numLayers, &dummy) == 1 4561 && numLayers > 0) { 4562 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC; 4563 tsType = OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC; 4564 tsLayers = numLayers; 4565 } else if ((tags = sscanf(tsSchema.c_str(), "android.generic.%u%c%u%c", 4566 &numLayers, &dummy, &numBLayers, &dummy)) 4567 && (tags == 1 || (tags == 3 && dummy == '+')) 4568 && numLayers > 0 && numLayers < UINT32_MAX - numBLayers) { 4569 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC; 4570 // VPX does not have a concept of B-frames, so just count all layers 4571 tsType = OMX_VIDEO_AndroidTemporalLayeringPatternAndroid; 4572 tsLayers = numLayers + numBLayers; 4573 } else { 4574 ALOGW("Ignoring unsupported ts-schema [%s]", tsSchema.c_str()); 4575 } 4576 tsLayers = min(tsLayers, (size_t)OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS); 4577 } 4578 4579 OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type; 4580 InitOMXParams(&vp8type); 4581 vp8type.nPortIndex = kPortIndexOutput; 4582 status_t err = mOMXNode->getParameter( 4583 (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder, 4584 &vp8type, sizeof(vp8type)); 4585 4586 if (err == OK) { 4587 if (iFrameInterval > 0) { 4588 vp8type.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate) + 1; 4589 } 4590 vp8type.eTemporalPattern = pattern; 4591 vp8type.nTemporalLayerCount = tsLayers; 4592 if (tsLayers > 0) { 4593 for (size_t i = 0; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) { 4594 vp8type.nTemporalLayerBitrateRatio[i] = 4595 kVp8LayerRateAlloction[tsLayers - 1][i]; 4596 } 4597 } 4598 if (bitrateMode == OMX_Video_ControlRateConstant) { 4599 vp8type.nMinQuantizer = 2; 4600 vp8type.nMaxQuantizer = 63; 4601 } 4602 4603 err = mOMXNode->setParameter( 4604 (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder, 4605 &vp8type, sizeof(vp8type)); 4606 if (err != OK) { 4607 ALOGW("Extended VP8 parameters set failed: %d", err); 4608 } else if (tsType == OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC) { 4609 // advertise even single layer WebRTC layering, as it is defined 4610 outputFormat->setString("ts-schema", AStringPrintf("webrtc.vp8.%u-layer", tsLayers)); 4611 } else if (tsLayers > 0) { 4612 // tsType == OMX_VIDEO_AndroidTemporalLayeringPatternAndroid 4613 outputFormat->setString("ts-schema", AStringPrintf("android.generic.%u", tsLayers)); 4614 } 4615 } 4616 4617 return configureBitrate(bitrateMode, bitrate); 4618} 4619 4620status_t ACodec::verifySupportForProfileAndLevel( 4621 OMX_U32 portIndex, int32_t profile, int32_t level) { 4622 OMX_VIDEO_PARAM_PROFILELEVELTYPE params; 4623 InitOMXParams(¶ms); 4624 params.nPortIndex = portIndex; 4625 4626 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { 4627 params.nProfileIndex = index; 4628 status_t err = mOMXNode->getParameter( 4629 OMX_IndexParamVideoProfileLevelQuerySupported, 4630 ¶ms, sizeof(params)); 4631 4632 if (err != OK) { 4633 return err; 4634 } 4635 4636 int32_t supportedProfile = static_cast<int32_t>(params.eProfile); 4637 int32_t supportedLevel = static_cast<int32_t>(params.eLevel); 4638 4639 if (profile == supportedProfile && level <= supportedLevel) { 4640 return OK; 4641 } 4642 4643 if (index == kMaxIndicesToCheck) { 4644 ALOGW("[%s] stopping checking profiles after %u: %x/%x", 4645 mComponentName.c_str(), index, 4646 params.eProfile, params.eLevel); 4647 } 4648 } 4649 return ERROR_UNSUPPORTED; 4650} 4651 4652status_t ACodec::configureBitrate( 4653 OMX_VIDEO_CONTROLRATETYPE bitrateMode, int32_t bitrate, int32_t quality) { 4654 OMX_VIDEO_PARAM_BITRATETYPE bitrateType; 4655 InitOMXParams(&bitrateType); 4656 bitrateType.nPortIndex = kPortIndexOutput; 4657 4658 status_t err = mOMXNode->getParameter( 4659 OMX_IndexParamVideoBitrate, &bitrateType, sizeof(bitrateType)); 4660 4661 if (err != OK) { 4662 return err; 4663 } 4664 4665 bitrateType.eControlRate = bitrateMode; 4666 4667 // write it out explicitly even if it's a union 4668 if (bitrateMode == OMX_Video_ControlRateConstantQuality) { 4669 bitrateType.nQualityFactor = quality; 4670 } else { 4671 bitrateType.nTargetBitrate = bitrate; 4672 } 4673 4674 return mOMXNode->setParameter( 4675 OMX_IndexParamVideoBitrate, &bitrateType, sizeof(bitrateType)); 4676} 4677 4678void ACodec::configureEncoderLatency(const sp<AMessage> &msg) { 4679 if (!mIsEncoder || !mIsVideo) { 4680 return; 4681 } 4682 4683 int32_t latency = 0, bitrateMode; 4684 if (msg->findInt32("latency", &latency) && latency > 0) { 4685 status_t err = setLatency(latency); 4686 if (err != OK) { 4687 ALOGW("[%s] failed setLatency. Failure is fine since this key is optional", 4688 mComponentName.c_str()); 4689 err = OK; 4690 } else { 4691 mLatency = latency; 4692 } 4693 } else if ((!msg->findInt32("bitrate-mode", &bitrateMode) && 4694 bitrateMode == OMX_Video_ControlRateConstant)) { 4695 // default the latency to be 1 if latency key is not specified or unsupported and bitrateMode 4696 // is CBR. 4697 mLatency = 1; 4698 } 4699} 4700 4701status_t ACodec::setupErrorCorrectionParameters() { 4702 OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType; 4703 InitOMXParams(&errorCorrectionType); 4704 errorCorrectionType.nPortIndex = kPortIndexOutput; 4705 4706 status_t err = mOMXNode->getParameter( 4707 OMX_IndexParamVideoErrorCorrection, 4708 &errorCorrectionType, sizeof(errorCorrectionType)); 4709 4710 if (err != OK) { 4711 return OK; // Optional feature. Ignore this failure 4712 } 4713 4714 errorCorrectionType.bEnableHEC = OMX_FALSE; 4715 errorCorrectionType.bEnableResync = OMX_TRUE; 4716 errorCorrectionType.nResynchMarkerSpacing = 256; 4717 errorCorrectionType.bEnableDataPartitioning = OMX_FALSE; 4718 errorCorrectionType.bEnableRVLC = OMX_FALSE; 4719 4720 return mOMXNode->setParameter( 4721 OMX_IndexParamVideoErrorCorrection, 4722 &errorCorrectionType, sizeof(errorCorrectionType)); 4723} 4724 4725status_t ACodec::setVideoFormatOnPort( 4726 OMX_U32 portIndex, 4727 int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat, 4728 float frameRate) { 4729 OMX_PARAM_PORTDEFINITIONTYPE def; 4730 InitOMXParams(&def); 4731 def.nPortIndex = portIndex; 4732 4733 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 4734 4735 status_t err = mOMXNode->getParameter( 4736 OMX_IndexParamPortDefinition, &def, sizeof(def)); 4737 if (err != OK) { 4738 return err; 4739 } 4740 4741 if (portIndex == kPortIndexInput) { 4742 // XXX Need a (much) better heuristic to compute input buffer sizes. 4743 const size_t X = 64 * 1024; 4744 if (def.nBufferSize < X) { 4745 def.nBufferSize = X; 4746 } 4747 } 4748 4749 if (def.eDomain != OMX_PortDomainVideo) { 4750 ALOGE("expected video port, got %s(%d)", asString(def.eDomain), def.eDomain); 4751 return FAILED_TRANSACTION; 4752 } 4753 4754 video_def->nFrameWidth = width; 4755 video_def->nFrameHeight = height; 4756 4757 if (portIndex == kPortIndexInput) { 4758 video_def->eCompressionFormat = compressionFormat; 4759 video_def->eColorFormat = OMX_COLOR_FormatUnused; 4760 if (frameRate >= 0) { 4761 video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f); 4762 } 4763 } 4764 4765 err = mOMXNode->setParameter( 4766 OMX_IndexParamPortDefinition, &def, sizeof(def)); 4767 4768 return err; 4769} 4770 4771size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const { 4772 size_t n = 0; 4773 4774 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 4775 const BufferInfo &info = mBuffers[portIndex].itemAt(i); 4776 4777 if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) { 4778 ++n; 4779 } 4780 } 4781 4782 return n; 4783} 4784 4785size_t ACodec::countBuffersOwnedByNativeWindow() const { 4786 size_t n = 0; 4787 4788 for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) { 4789 const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i); 4790 4791 if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 4792 ++n; 4793 } 4794 } 4795 4796 return n; 4797} 4798 4799void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() { 4800 if (mNativeWindow == NULL) { 4801 return; 4802 } 4803 4804 while (countBuffersOwnedByNativeWindow() > mNumUndequeuedBuffers 4805 && dequeueBufferFromNativeWindow() != NULL) { 4806 // these buffers will be submitted as regular buffers; account for this 4807 if (storingMetadataInDecodedBuffers() && mMetadataBuffersToSubmit > 0) { 4808 --mMetadataBuffersToSubmit; 4809 } 4810 } 4811} 4812 4813bool ACodec::allYourBuffersAreBelongToUs( 4814 OMX_U32 portIndex) { 4815 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 4816 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 4817 4818 if (info->mStatus != BufferInfo::OWNED_BY_US 4819 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) { 4820 ALOGV("[%s] Buffer %u on port %u still has status %d", 4821 mComponentName.c_str(), 4822 info->mBufferID, portIndex, info->mStatus); 4823 return false; 4824 } 4825 } 4826 4827 return true; 4828} 4829 4830bool ACodec::allYourBuffersAreBelongToUs() { 4831 return allYourBuffersAreBelongToUs(kPortIndexInput) 4832 && allYourBuffersAreBelongToUs(kPortIndexOutput); 4833} 4834 4835void ACodec::deferMessage(const sp<AMessage> &msg) { 4836 mDeferredQueue.push_back(msg); 4837} 4838 4839void ACodec::processDeferredMessages() { 4840 List<sp<AMessage> > queue = mDeferredQueue; 4841 mDeferredQueue.clear(); 4842 4843 List<sp<AMessage> >::iterator it = queue.begin(); 4844 while (it != queue.end()) { 4845 onMessageReceived(*it++); 4846 } 4847} 4848 4849status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> ¬ify) { 4850 const char *niceIndex = portIndex == kPortIndexInput ? "input" : "output"; 4851 OMX_PARAM_PORTDEFINITIONTYPE def; 4852 InitOMXParams(&def); 4853 def.nPortIndex = portIndex; 4854 4855 status_t err = mOMXNode->getParameter(OMX_IndexParamPortDefinition, &def, sizeof(def)); 4856 if (err != OK) { 4857 return err; 4858 } 4859 4860 if (def.eDir != (portIndex == kPortIndexOutput ? OMX_DirOutput : OMX_DirInput)) { 4861 ALOGE("unexpected dir: %s(%d) on %s port", asString(def.eDir), def.eDir, niceIndex); 4862 return BAD_VALUE; 4863 } 4864 4865 switch (def.eDomain) { 4866 case OMX_PortDomainVideo: 4867 { 4868 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video; 4869 switch ((int)videoDef->eCompressionFormat) { 4870 case OMX_VIDEO_CodingUnused: 4871 { 4872 CHECK(mIsEncoder ^ (portIndex == kPortIndexOutput)); 4873 notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW); 4874 4875 notify->setInt32("stride", videoDef->nStride); 4876 notify->setInt32("slice-height", videoDef->nSliceHeight); 4877 notify->setInt32("color-format", videoDef->eColorFormat); 4878 4879 if (mNativeWindow == NULL) { 4880 DescribeColorFormat2Params describeParams; 4881 InitOMXParams(&describeParams); 4882 describeParams.eColorFormat = videoDef->eColorFormat; 4883 describeParams.nFrameWidth = videoDef->nFrameWidth; 4884 describeParams.nFrameHeight = videoDef->nFrameHeight; 4885 describeParams.nStride = videoDef->nStride; 4886 describeParams.nSliceHeight = videoDef->nSliceHeight; 4887 describeParams.bUsingNativeBuffers = OMX_FALSE; 4888 4889 if (DescribeColorFormat(mOMXNode, describeParams)) { 4890 notify->setBuffer( 4891 "image-data", 4892 ABuffer::CreateAsCopy( 4893 &describeParams.sMediaImage, 4894 sizeof(describeParams.sMediaImage))); 4895 4896 MediaImage2 &img = describeParams.sMediaImage; 4897 MediaImage2::PlaneInfo *plane = img.mPlane; 4898 ALOGV("[%s] MediaImage { F(%ux%u) @%u+%d+%d @%u+%d+%d @%u+%d+%d }", 4899 mComponentName.c_str(), img.mWidth, img.mHeight, 4900 plane[0].mOffset, plane[0].mColInc, plane[0].mRowInc, 4901 plane[1].mOffset, plane[1].mColInc, plane[1].mRowInc, 4902 plane[2].mOffset, plane[2].mColInc, plane[2].mRowInc); 4903 } 4904 } 4905 4906 int32_t width = (int32_t)videoDef->nFrameWidth; 4907 int32_t height = (int32_t)videoDef->nFrameHeight; 4908 4909 if (portIndex == kPortIndexOutput) { 4910 OMX_CONFIG_RECTTYPE rect; 4911 InitOMXParams(&rect); 4912 rect.nPortIndex = portIndex; 4913 4914 if (mOMXNode->getConfig( 4915 (portIndex == kPortIndexOutput ? 4916 OMX_IndexConfigCommonOutputCrop : 4917 OMX_IndexConfigCommonInputCrop), 4918 &rect, sizeof(rect)) != OK) { 4919 rect.nLeft = 0; 4920 rect.nTop = 0; 4921 rect.nWidth = videoDef->nFrameWidth; 4922 rect.nHeight = videoDef->nFrameHeight; 4923 } 4924 4925 if (rect.nLeft < 0 || rect.nTop < 0 || 4926 rect.nWidth == 0 || rect.nHeight == 0 || 4927 rect.nLeft + rect.nWidth > videoDef->nFrameWidth || 4928 rect.nTop + rect.nHeight > videoDef->nFrameHeight) { 4929 ALOGE("Wrong cropped rect (%d, %d, %u, %u) vs. frame (%u, %u)", 4930 rect.nLeft, rect.nTop, 4931 rect.nWidth, rect.nHeight, 4932 videoDef->nFrameWidth, videoDef->nFrameHeight); 4933 return BAD_VALUE; 4934 } 4935 4936 notify->setRect( 4937 "crop", 4938 rect.nLeft, 4939 rect.nTop, 4940 rect.nLeft + rect.nWidth - 1, 4941 rect.nTop + rect.nHeight - 1); 4942 4943 width = rect.nWidth; 4944 height = rect.nHeight; 4945 4946 android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN; 4947 (void)getColorAspectsAndDataSpaceForVideoDecoder( 4948 width, height, mConfigFormat, notify, 4949 mUsingNativeWindow ? &dataSpace : NULL); 4950 if (mUsingNativeWindow) { 4951 notify->setInt32("android._dataspace", dataSpace); 4952 } 4953 (void)getHDRStaticInfoForVideoCodec(kPortIndexOutput, notify); 4954 } else { 4955 (void)getInputColorAspectsForVideoEncoder(notify); 4956 if (mConfigFormat->contains("hdr-static-info")) { 4957 (void)getHDRStaticInfoForVideoCodec(kPortIndexInput, notify); 4958 } 4959 uint32_t latency = 0; 4960 if (mIsEncoder && !mIsImage && 4961 getLatency(&latency) == OK && latency > 0) { 4962 notify->setInt32("latency", latency); 4963 } 4964 } 4965 4966 break; 4967 } 4968 4969 case OMX_VIDEO_CodingVP8: 4970 case OMX_VIDEO_CodingVP9: 4971 { 4972 OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type; 4973 InitOMXParams(&vp8type); 4974 vp8type.nPortIndex = kPortIndexOutput; 4975 status_t err = mOMXNode->getParameter( 4976 (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder, 4977 &vp8type, 4978 sizeof(vp8type)); 4979 4980 if (err == OK) { 4981 if (vp8type.eTemporalPattern == OMX_VIDEO_VPXTemporalLayerPatternWebRTC 4982 && vp8type.nTemporalLayerCount > 0 4983 && vp8type.nTemporalLayerCount 4984 <= OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS) { 4985 // advertise as android.generic if we configured for android.generic 4986 AString origSchema; 4987 if (notify->findString("ts-schema", &origSchema) 4988 && origSchema.startsWith("android.generic")) { 4989 notify->setString("ts-schema", AStringPrintf( 4990 "android.generic.%u", vp8type.nTemporalLayerCount)); 4991 } else { 4992 notify->setString("ts-schema", AStringPrintf( 4993 "webrtc.vp8.%u-layer", vp8type.nTemporalLayerCount)); 4994 } 4995 } 4996 } 4997 // Fall through to set up mime. 4998 } 4999 5000 default: 5001 { 5002 if (mIsEncoder ^ (portIndex == kPortIndexOutput)) { 5003 // should be CodingUnused 5004 ALOGE("Raw port video compression format is %s(%d)", 5005 asString(videoDef->eCompressionFormat), 5006 videoDef->eCompressionFormat); 5007 return BAD_VALUE; 5008 } 5009 AString mime; 5010 if (GetMimeTypeForVideoCoding( 5011 videoDef->eCompressionFormat, &mime) != OK) { 5012 notify->setString("mime", "application/octet-stream"); 5013 } else { 5014 notify->setString("mime", mime.c_str()); 5015 } 5016 uint32_t intraRefreshPeriod = 0; 5017 if (mIsEncoder && !mIsImage && 5018 getIntraRefreshPeriod(&intraRefreshPeriod) == OK 5019 && intraRefreshPeriod > 0) { 5020 notify->setInt32("intra-refresh-period", intraRefreshPeriod); 5021 } 5022 break; 5023 } 5024 } 5025 notify->setInt32("width", videoDef->nFrameWidth); 5026 notify->setInt32("height", videoDef->nFrameHeight); 5027 ALOGV("[%s] %s format is %s", mComponentName.c_str(), 5028 portIndex == kPortIndexInput ? "input" : "output", 5029 notify->debugString().c_str()); 5030 5031 break; 5032 } 5033 5034 case OMX_PortDomainAudio: 5035 { 5036 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio; 5037 5038 switch ((int)audioDef->eEncoding) { 5039 case OMX_AUDIO_CodingPCM: 5040 { 5041 OMX_AUDIO_PARAM_PCMMODETYPE params; 5042 InitOMXParams(¶ms); 5043 params.nPortIndex = portIndex; 5044 5045 err = mOMXNode->getParameter( 5046 OMX_IndexParamAudioPcm, ¶ms, sizeof(params)); 5047 if (err != OK) { 5048 return err; 5049 } 5050 5051 if (params.nChannels <= 0 5052 || (params.nChannels != 1 && !params.bInterleaved) 5053 || params.ePCMMode != OMX_AUDIO_PCMModeLinear) { 5054 ALOGE("unsupported PCM port: %u channels%s, %u-bit", 5055 params.nChannels, 5056 params.bInterleaved ? " interleaved" : "", 5057 params.nBitPerSample); 5058 return FAILED_TRANSACTION; 5059 } 5060 5061 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW); 5062 notify->setInt32("channel-count", params.nChannels); 5063 notify->setInt32("sample-rate", params.nSamplingRate); 5064 5065 AudioEncoding encoding = kAudioEncodingPcm16bit; 5066 if (params.eNumData == OMX_NumericalDataUnsigned 5067 && params.nBitPerSample == 8u) { 5068 encoding = kAudioEncodingPcm8bit; 5069 } else if (params.eNumData == OMX_NumericalDataFloat 5070 && params.nBitPerSample == 32u) { 5071 encoding = kAudioEncodingPcmFloat; 5072 } else if (params.nBitPerSample != 16u 5073 || params.eNumData != OMX_NumericalDataSigned) { 5074 ALOGE("unsupported PCM port: %s(%d), %s(%d) mode ", 5075 asString(params.eNumData), params.eNumData, 5076 asString(params.ePCMMode), params.ePCMMode); 5077 return FAILED_TRANSACTION; 5078 } 5079 notify->setInt32("pcm-encoding", encoding); 5080 5081 if (mChannelMaskPresent) { 5082 notify->setInt32("channel-mask", mChannelMask); 5083 } 5084 break; 5085 } 5086 5087 case OMX_AUDIO_CodingAAC: 5088 { 5089 OMX_AUDIO_PARAM_AACPROFILETYPE params; 5090 InitOMXParams(¶ms); 5091 params.nPortIndex = portIndex; 5092 5093 err = mOMXNode->getParameter( 5094 OMX_IndexParamAudioAac, ¶ms, sizeof(params)); 5095 if (err != OK) { 5096 return err; 5097 } 5098 5099 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC); 5100 notify->setInt32("channel-count", params.nChannels); 5101 notify->setInt32("sample-rate", params.nSampleRate); 5102 break; 5103 } 5104 5105 case OMX_AUDIO_CodingAMR: 5106 { 5107 OMX_AUDIO_PARAM_AMRTYPE params; 5108 InitOMXParams(¶ms); 5109 params.nPortIndex = portIndex; 5110 5111 err = mOMXNode->getParameter( 5112 OMX_IndexParamAudioAmr, ¶ms, sizeof(params)); 5113 if (err != OK) { 5114 return err; 5115 } 5116 5117 notify->setInt32("channel-count", 1); 5118 if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) { 5119 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_WB); 5120 notify->setInt32("sample-rate", 16000); 5121 } else { 5122 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB); 5123 notify->setInt32("sample-rate", 8000); 5124 } 5125 break; 5126 } 5127 5128 case OMX_AUDIO_CodingFLAC: 5129 { 5130 OMX_AUDIO_PARAM_FLACTYPE params; 5131 InitOMXParams(¶ms); 5132 params.nPortIndex = portIndex; 5133 5134 err = mOMXNode->getParameter( 5135 OMX_IndexParamAudioFlac, ¶ms, sizeof(params)); 5136 if (err != OK) { 5137 return err; 5138 } 5139 5140 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC); 5141 notify->setInt32("channel-count", params.nChannels); 5142 notify->setInt32("sample-rate", params.nSampleRate); 5143 break; 5144 } 5145 5146 case OMX_AUDIO_CodingMP3: 5147 { 5148 OMX_AUDIO_PARAM_MP3TYPE params; 5149 InitOMXParams(¶ms); 5150 params.nPortIndex = portIndex; 5151 5152 err = mOMXNode->getParameter( 5153 OMX_IndexParamAudioMp3, ¶ms, sizeof(params)); 5154 if (err != OK) { 5155 return err; 5156 } 5157 5158 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MPEG); 5159 notify->setInt32("channel-count", params.nChannels); 5160 notify->setInt32("sample-rate", params.nSampleRate); 5161 break; 5162 } 5163 5164 case OMX_AUDIO_CodingVORBIS: 5165 { 5166 OMX_AUDIO_PARAM_VORBISTYPE params; 5167 InitOMXParams(¶ms); 5168 params.nPortIndex = portIndex; 5169 5170 err = mOMXNode->getParameter( 5171 OMX_IndexParamAudioVorbis, ¶ms, sizeof(params)); 5172 if (err != OK) { 5173 return err; 5174 } 5175 5176 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_VORBIS); 5177 notify->setInt32("channel-count", params.nChannels); 5178 notify->setInt32("sample-rate", params.nSampleRate); 5179 break; 5180 } 5181 5182 case OMX_AUDIO_CodingAndroidAC3: 5183 { 5184 OMX_AUDIO_PARAM_ANDROID_AC3TYPE params; 5185 InitOMXParams(¶ms); 5186 params.nPortIndex = portIndex; 5187 5188 err = mOMXNode->getParameter( 5189 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, 5190 ¶ms, sizeof(params)); 5191 if (err != OK) { 5192 return err; 5193 } 5194 5195 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3); 5196 notify->setInt32("channel-count", params.nChannels); 5197 notify->setInt32("sample-rate", params.nSampleRate); 5198 break; 5199 } 5200 5201 case OMX_AUDIO_CodingAndroidEAC3: 5202 { 5203 OMX_AUDIO_PARAM_ANDROID_EAC3TYPE params; 5204 InitOMXParams(¶ms); 5205 params.nPortIndex = portIndex; 5206 5207 err = mOMXNode->getParameter( 5208 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, 5209 ¶ms, sizeof(params)); 5210 if (err != OK) { 5211 return err; 5212 } 5213 5214 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_EAC3); 5215 notify->setInt32("channel-count", params.nChannels); 5216 notify->setInt32("sample-rate", params.nSampleRate); 5217 break; 5218 } 5219 5220 case OMX_AUDIO_CodingAndroidOPUS: 5221 { 5222 OMX_AUDIO_PARAM_ANDROID_OPUSTYPE params; 5223 InitOMXParams(¶ms); 5224 params.nPortIndex = portIndex; 5225 5226 err = mOMXNode->getParameter( 5227 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus, 5228 ¶ms, sizeof(params)); 5229 if (err != OK) { 5230 return err; 5231 } 5232 5233 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_OPUS); 5234 notify->setInt32("channel-count", params.nChannels); 5235 notify->setInt32("sample-rate", params.nSampleRate); 5236 break; 5237 } 5238 5239 case OMX_AUDIO_CodingG711: 5240 { 5241 OMX_AUDIO_PARAM_PCMMODETYPE params; 5242 InitOMXParams(¶ms); 5243 params.nPortIndex = portIndex; 5244 5245 err = mOMXNode->getParameter( 5246 (OMX_INDEXTYPE)OMX_IndexParamAudioPcm, ¶ms, sizeof(params)); 5247 if (err != OK) { 5248 return err; 5249 } 5250 5251 const char *mime = NULL; 5252 if (params.ePCMMode == OMX_AUDIO_PCMModeMULaw) { 5253 mime = MEDIA_MIMETYPE_AUDIO_G711_MLAW; 5254 } else if (params.ePCMMode == OMX_AUDIO_PCMModeALaw) { 5255 mime = MEDIA_MIMETYPE_AUDIO_G711_ALAW; 5256 } else { // params.ePCMMode == OMX_AUDIO_PCMModeLinear 5257 mime = MEDIA_MIMETYPE_AUDIO_RAW; 5258 } 5259 notify->setString("mime", mime); 5260 notify->setInt32("channel-count", params.nChannels); 5261 notify->setInt32("sample-rate", params.nSamplingRate); 5262 notify->setInt32("pcm-encoding", kAudioEncodingPcm16bit); 5263 break; 5264 } 5265 5266 case OMX_AUDIO_CodingGSMFR: 5267 { 5268 OMX_AUDIO_PARAM_PCMMODETYPE params; 5269 InitOMXParams(¶ms); 5270 params.nPortIndex = portIndex; 5271 5272 err = mOMXNode->getParameter( 5273 OMX_IndexParamAudioPcm, ¶ms, sizeof(params)); 5274 if (err != OK) { 5275 return err; 5276 } 5277 5278 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MSGSM); 5279 notify->setInt32("channel-count", params.nChannels); 5280 notify->setInt32("sample-rate", params.nSamplingRate); 5281 break; 5282 } 5283 5284 default: 5285 ALOGE("Unsupported audio coding: %s(%d)\n", 5286 asString(audioDef->eEncoding), audioDef->eEncoding); 5287 return BAD_TYPE; 5288 } 5289 break; 5290 } 5291 5292 default: 5293 ALOGE("Unsupported domain: %s(%d)", asString(def.eDomain), def.eDomain); 5294 return BAD_TYPE; 5295 } 5296 5297 return getVendorParameters(portIndex, notify); 5298} 5299 5300void ACodec::onDataSpaceChanged(android_dataspace dataSpace, const ColorAspects &aspects) { 5301 // aspects are normally communicated in ColorAspects 5302 int32_t range, standard, transfer; 5303 convertCodecColorAspectsToPlatformAspects(aspects, &range, &standard, &transfer); 5304 5305 // if some aspects are unspecified, use dataspace fields 5306 if (range != 0) { 5307 range = (dataSpace & HAL_DATASPACE_RANGE_MASK) >> HAL_DATASPACE_RANGE_SHIFT; 5308 } 5309 if (standard != 0) { 5310 standard = (dataSpace & HAL_DATASPACE_STANDARD_MASK) >> HAL_DATASPACE_STANDARD_SHIFT; 5311 } 5312 if (transfer != 0) { 5313 transfer = (dataSpace & HAL_DATASPACE_TRANSFER_MASK) >> HAL_DATASPACE_TRANSFER_SHIFT; 5314 } 5315 5316 mOutputFormat = mOutputFormat->dup(); // trigger an output format changed event 5317 if (range != 0) { 5318 mOutputFormat->setInt32("color-range", range); 5319 } 5320 if (standard != 0) { 5321 mOutputFormat->setInt32("color-standard", standard); 5322 } 5323 if (transfer != 0) { 5324 mOutputFormat->setInt32("color-transfer", transfer); 5325 } 5326 5327 ALOGD("dataspace changed to %#x (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) " 5328 "(R:%d(%s), S:%d(%s), T:%d(%s))", 5329 dataSpace, 5330 aspects.mRange, asString(aspects.mRange), 5331 aspects.mPrimaries, asString(aspects.mPrimaries), 5332 aspects.mMatrixCoeffs, asString(aspects.mMatrixCoeffs), 5333 aspects.mTransfer, asString(aspects.mTransfer), 5334 range, asString((ColorRange)range), 5335 standard, asString((ColorStandard)standard), 5336 transfer, asString((ColorTransfer)transfer)); 5337} 5338 5339void ACodec::onOutputFormatChanged(sp<const AMessage> expectedFormat) { 5340 // store new output format, at the same time mark that this is no longer the first frame 5341 mOutputFormat = mBaseOutputFormat->dup(); 5342 5343 if (getPortFormat(kPortIndexOutput, mOutputFormat) != OK) { 5344 ALOGE("[%s] Failed to get port format to send format change", mComponentName.c_str()); 5345 return; 5346 } 5347 5348 if (expectedFormat != NULL) { 5349 sp<const AMessage> changes = expectedFormat->changesFrom(mOutputFormat); 5350 sp<const AMessage> to = mOutputFormat->changesFrom(expectedFormat); 5351 if (changes->countEntries() != 0 || to->countEntries() != 0) { 5352 ALOGW("[%s] BAD CODEC: Output format changed unexpectedly from (diff) %s to (diff) %s", 5353 mComponentName.c_str(), 5354 changes->debugString(4).c_str(), to->debugString(4).c_str()); 5355 } 5356 } 5357 5358 if (!mIsVideo && !mIsEncoder) { 5359 AudioEncoding pcmEncoding = kAudioEncodingPcm16bit; 5360 (void)mConfigFormat->findInt32("pcm-encoding", (int32_t*)&pcmEncoding); 5361 AudioEncoding codecPcmEncoding = kAudioEncodingPcm16bit; 5362 (void)mOutputFormat->findInt32("pcm-encoding", (int32_t*)&pcmEncoding); 5363 5364 mConverter[kPortIndexOutput] = AudioConverter::Create(codecPcmEncoding, pcmEncoding); 5365 if (mConverter[kPortIndexOutput] != NULL) { 5366 mOutputFormat->setInt32("pcm-encoding", pcmEncoding); 5367 } 5368 } 5369 5370 if (mTunneled) { 5371 sendFormatChange(); 5372 } 5373} 5374 5375void ACodec::sendFormatChange() { 5376 AString mime; 5377 CHECK(mOutputFormat->findString("mime", &mime)); 5378 5379 if (mime == MEDIA_MIMETYPE_AUDIO_RAW && (mEncoderDelay || mEncoderPadding)) { 5380 int32_t channelCount, sampleRate; 5381 CHECK(mOutputFormat->findInt32("channel-count", &channelCount)); 5382 CHECK(mOutputFormat->findInt32("sample-rate", &sampleRate)); 5383 if (mSampleRate != 0 && sampleRate != 0) { 5384 // avoiding 32-bit overflows in intermediate values 5385 mEncoderDelay = (int32_t)((((int64_t)mEncoderDelay) * sampleRate) / mSampleRate); 5386 mEncoderPadding = (int32_t)((((int64_t)mEncoderPadding) * sampleRate) / mSampleRate); 5387 mSampleRate = sampleRate; 5388 } 5389 if (mSkipCutBuffer != NULL) { 5390 size_t prevbufsize = mSkipCutBuffer->size(); 5391 if (prevbufsize != 0) { 5392 ALOGW("Replacing SkipCutBuffer holding %zu bytes", prevbufsize); 5393 } 5394 } 5395 mSkipCutBuffer = new SkipCutBuffer(mEncoderDelay, mEncoderPadding, channelCount); 5396 } 5397 5398 // mLastOutputFormat is not used when tunneled; doing this just to stay consistent 5399 mLastOutputFormat = mOutputFormat; 5400} 5401 5402void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) { 5403 ALOGE("signalError(omxError %#x, internalError %d)", error, internalError); 5404 5405 if (internalError == UNKNOWN_ERROR) { // find better error code 5406 const status_t omxStatus = statusFromOMXError(error); 5407 if (omxStatus != 0) { 5408 internalError = omxStatus; 5409 } else { 5410 ALOGW("Invalid OMX error %#x", error); 5411 } 5412 } 5413 5414 mFatalError = true; 5415 mCallback->onError(internalError, ACTION_CODE_FATAL); 5416} 5417 5418status_t ACodec::requestIDRFrame() { 5419 if (!mIsEncoder) { 5420 return ERROR_UNSUPPORTED; 5421 } 5422 5423 OMX_CONFIG_INTRAREFRESHVOPTYPE params; 5424 InitOMXParams(¶ms); 5425 5426 params.nPortIndex = kPortIndexOutput; 5427 params.IntraRefreshVOP = OMX_TRUE; 5428 5429 return mOMXNode->setConfig( 5430 OMX_IndexConfigVideoIntraVOPRefresh, 5431 ¶ms, 5432 sizeof(params)); 5433} 5434 5435//////////////////////////////////////////////////////////////////////////////// 5436 5437ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState) 5438 : AState(parentState), 5439 mCodec(codec) { 5440} 5441 5442ACodec::BaseState::PortMode ACodec::BaseState::getPortMode( 5443 OMX_U32 /* portIndex */) { 5444 return KEEP_BUFFERS; 5445} 5446 5447void ACodec::BaseState::stateExited() { 5448 ++mCodec->mStateGeneration; 5449} 5450 5451bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) { 5452 switch (msg->what()) { 5453 case kWhatInputBufferFilled: 5454 { 5455 onInputBufferFilled(msg); 5456 break; 5457 } 5458 5459 case kWhatOutputBufferDrained: 5460 { 5461 onOutputBufferDrained(msg); 5462 break; 5463 } 5464 5465 case ACodec::kWhatOMXMessageList: 5466 { 5467 return checkOMXMessage(msg) ? onOMXMessageList(msg) : true; 5468 } 5469 5470 case ACodec::kWhatOMXMessageItem: 5471 { 5472 // no need to check as we already did it for kWhatOMXMessageList 5473 return onOMXMessage(msg); 5474 } 5475 5476 case ACodec::kWhatOMXMessage: 5477 { 5478 return checkOMXMessage(msg) ? onOMXMessage(msg) : true; 5479 } 5480 5481 case ACodec::kWhatSetSurface: 5482 { 5483 sp<AReplyToken> replyID; 5484 CHECK(msg->senderAwaitsResponse(&replyID)); 5485 5486 sp<RefBase> obj; 5487 CHECK(msg->findObject("surface", &obj)); 5488 5489 status_t err = mCodec->handleSetSurface(static_cast<Surface *>(obj.get())); 5490 5491 sp<AMessage> response = new AMessage; 5492 response->setInt32("err", err); 5493 response->postReply(replyID); 5494 break; 5495 } 5496 5497 case ACodec::kWhatCreateInputSurface: 5498 case ACodec::kWhatSetInputSurface: 5499 case ACodec::kWhatSignalEndOfInputStream: 5500 { 5501 // This may result in an app illegal state exception. 5502 ALOGE("Message 0x%x was not handled", msg->what()); 5503 mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION); 5504 return true; 5505 } 5506 5507 case ACodec::kWhatOMXDied: 5508 { 5509 // This will result in kFlagSawMediaServerDie handling in MediaCodec. 5510 ALOGE("OMX/mediaserver died, signalling error!"); 5511 mCodec->mGraphicBufferSource.clear(); 5512 mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT); 5513 break; 5514 } 5515 5516 case ACodec::kWhatReleaseCodecInstance: 5517 { 5518 ALOGI("[%s] forcing the release of codec", 5519 mCodec->mComponentName.c_str()); 5520 status_t err = mCodec->mOMXNode->freeNode(); 5521 ALOGE_IF("[%s] failed to release codec instance: err=%d", 5522 mCodec->mComponentName.c_str(), err); 5523 mCodec->mCallback->onReleaseCompleted(); 5524 5525 mCodec->changeState(mCodec->mUninitializedState); 5526 break; 5527 } 5528 5529 case ACodec::kWhatForceStateTransition: 5530 { 5531 ALOGV("Already transitioned --- ignore"); 5532 break; 5533 } 5534 5535 default: 5536 return false; 5537 } 5538 5539 return true; 5540} 5541 5542bool ACodec::BaseState::checkOMXMessage(const sp<AMessage> &msg) { 5543 // there is a possibility that this is an outstanding message for a 5544 // codec that we have already destroyed 5545 if (mCodec->mOMXNode == NULL) { 5546 ALOGI("ignoring message as already freed component: %s", 5547 msg->debugString().c_str()); 5548 return false; 5549 } 5550 5551 int32_t generation; 5552 CHECK(msg->findInt32("generation", (int32_t*)&generation)); 5553 if (generation != mCodec->mNodeGeneration) { 5554 ALOGW("Unexpected message for component: %s, gen %u, cur %u", 5555 msg->debugString().c_str(), generation, mCodec->mNodeGeneration); 5556 return false; 5557 } 5558 return true; 5559} 5560 5561bool ACodec::BaseState::onOMXMessageList(const sp<AMessage> &msg) { 5562 sp<RefBase> obj; 5563 CHECK(msg->findObject("messages", &obj)); 5564 sp<MessageList> msgList = static_cast<MessageList *>(obj.get()); 5565 5566 bool receivedRenderedEvents = false; 5567 for (std::list<sp<AMessage>>::const_iterator it = msgList->getList().cbegin(); 5568 it != msgList->getList().cend(); ++it) { 5569 (*it)->setWhat(ACodec::kWhatOMXMessageItem); 5570 mCodec->handleMessage(*it); 5571 int32_t type; 5572 CHECK((*it)->findInt32("type", &type)); 5573 if (type == omx_message::FRAME_RENDERED) { 5574 receivedRenderedEvents = true; 5575 } 5576 } 5577 5578 if (receivedRenderedEvents) { 5579 // NOTE: all buffers are rendered in this case 5580 mCodec->notifyOfRenderedFrames(); 5581 } 5582 return true; 5583} 5584 5585bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) { 5586 int32_t type; 5587 CHECK(msg->findInt32("type", &type)); 5588 5589 switch (type) { 5590 case omx_message::EVENT: 5591 { 5592 int32_t event, data1, data2; 5593 CHECK(msg->findInt32("event", &event)); 5594 CHECK(msg->findInt32("data1", &data1)); 5595 CHECK(msg->findInt32("data2", &data2)); 5596 5597 if (event == OMX_EventCmdComplete 5598 && data1 == OMX_CommandFlush 5599 && data2 == (int32_t)OMX_ALL) { 5600 // Use of this notification is not consistent across 5601 // implementations. We'll drop this notification and rely 5602 // on flush-complete notifications on the individual port 5603 // indices instead. 5604 5605 return true; 5606 } 5607 5608 return onOMXEvent( 5609 static_cast<OMX_EVENTTYPE>(event), 5610 static_cast<OMX_U32>(data1), 5611 static_cast<OMX_U32>(data2)); 5612 } 5613 5614 case omx_message::EMPTY_BUFFER_DONE: 5615 { 5616 IOMX::buffer_id bufferID; 5617 int32_t fenceFd; 5618 5619 CHECK(msg->findInt32("buffer", (int32_t*)&bufferID)); 5620 CHECK(msg->findInt32("fence_fd", &fenceFd)); 5621 5622 return onOMXEmptyBufferDone(bufferID, fenceFd); 5623 } 5624 5625 case omx_message::FILL_BUFFER_DONE: 5626 { 5627 IOMX::buffer_id bufferID; 5628 CHECK(msg->findInt32("buffer", (int32_t*)&bufferID)); 5629 5630 int32_t rangeOffset, rangeLength, flags, fenceFd; 5631 int64_t timeUs; 5632 5633 CHECK(msg->findInt32("range_offset", &rangeOffset)); 5634 CHECK(msg->findInt32("range_length", &rangeLength)); 5635 CHECK(msg->findInt32("flags", &flags)); 5636 CHECK(msg->findInt64("timestamp", &timeUs)); 5637 CHECK(msg->findInt32("fence_fd", &fenceFd)); 5638 5639 return onOMXFillBufferDone( 5640 bufferID, 5641 (size_t)rangeOffset, (size_t)rangeLength, 5642 (OMX_U32)flags, 5643 timeUs, 5644 fenceFd); 5645 } 5646 5647 case omx_message::FRAME_RENDERED: 5648 { 5649 int64_t mediaTimeUs, systemNano; 5650 5651 CHECK(msg->findInt64("media_time_us", &mediaTimeUs)); 5652 CHECK(msg->findInt64("system_nano", &systemNano)); 5653 5654 return onOMXFrameRendered( 5655 mediaTimeUs, systemNano); 5656 } 5657 5658 default: 5659 ALOGE("Unexpected message type: %d", type); 5660 return false; 5661 } 5662} 5663 5664bool ACodec::BaseState::onOMXFrameRendered( 5665 int64_t mediaTimeUs __unused, nsecs_t systemNano __unused) { 5666 // ignore outside of Executing and PortSettingsChanged states 5667 return true; 5668} 5669 5670bool ACodec::BaseState::onOMXEvent( 5671 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 5672 if (event == OMX_EventDataSpaceChanged) { 5673 ColorAspects aspects = ColorUtils::unpackToColorAspects(data2); 5674 5675 mCodec->onDataSpaceChanged((android_dataspace)data1, aspects); 5676 return true; 5677 } 5678 5679 if (event != OMX_EventError) { 5680 ALOGV("[%s] EVENT(%d, 0x%08x, 0x%08x)", 5681 mCodec->mComponentName.c_str(), event, data1, data2); 5682 5683 return false; 5684 } 5685 5686 ALOGE("[%s] ERROR(0x%08x)", mCodec->mComponentName.c_str(), data1); 5687 5688 // verify OMX component sends back an error we expect. 5689 OMX_ERRORTYPE omxError = (OMX_ERRORTYPE)data1; 5690 if (!isOMXError(omxError)) { 5691 ALOGW("Invalid OMX error %#x", omxError); 5692 omxError = OMX_ErrorUndefined; 5693 } 5694 mCodec->signalError(omxError); 5695 5696 return true; 5697} 5698 5699bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID, int fenceFd) { 5700 ALOGV("[%s] onOMXEmptyBufferDone %u", 5701 mCodec->mComponentName.c_str(), bufferID); 5702 5703 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID); 5704 BufferInfo::Status status = BufferInfo::getSafeStatus(info); 5705 if (status != BufferInfo::OWNED_BY_COMPONENT) { 5706 ALOGE("Wrong ownership in EBD: %s(%d) buffer #%u", _asString(status), status, bufferID); 5707 mCodec->dumpBuffers(kPortIndexInput); 5708 if (fenceFd >= 0) { 5709 ::close(fenceFd); 5710 } 5711 return false; 5712 } 5713 info->mStatus = BufferInfo::OWNED_BY_US; 5714 5715 // input buffers cannot take fences, so wait for any fence now 5716 (void)mCodec->waitForFence(fenceFd, "onOMXEmptyBufferDone"); 5717 fenceFd = -1; 5718 5719 // still save fence for completeness 5720 info->setWriteFence(fenceFd, "onOMXEmptyBufferDone"); 5721 5722 // We're in "store-metadata-in-buffers" mode, the underlying 5723 // OMX component had access to data that's implicitly refcounted 5724 // by this "MediaBuffer" object. Now that the OMX component has 5725 // told us that it's done with the input buffer, we can decrement 5726 // the mediaBuffer's reference count. 5727 info->mData->meta()->setObject("mediaBufferHolder", sp<MediaBufferHolder>(nullptr)); 5728 5729 PortMode mode = getPortMode(kPortIndexInput); 5730 5731 switch (mode) { 5732 case KEEP_BUFFERS: 5733 break; 5734 5735 case RESUBMIT_BUFFERS: 5736 postFillThisBuffer(info); 5737 break; 5738 5739 case FREE_BUFFERS: 5740 default: 5741 ALOGE("SHOULD NOT REACH HERE: cannot free empty output buffers"); 5742 return false; 5743 } 5744 5745 return true; 5746} 5747 5748void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) { 5749 if (mCodec->mPortEOS[kPortIndexInput]) { 5750 return; 5751 } 5752 5753 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 5754 5755 info->mData->setFormat(mCodec->mInputFormat); 5756 mCodec->mBufferChannel->fillThisBuffer(info->mBufferID); 5757 info->mData.clear(); 5758 info->mStatus = BufferInfo::OWNED_BY_UPSTREAM; 5759} 5760 5761void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { 5762 IOMX::buffer_id bufferID; 5763 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID)); 5764 sp<MediaCodecBuffer> buffer; 5765 int32_t err = OK; 5766 bool eos = false; 5767 PortMode mode = getPortMode(kPortIndexInput); 5768 int32_t discarded = 0; 5769 if (msg->findInt32("discarded", &discarded) && discarded) { 5770 // these are unfilled buffers returned by client 5771 // buffers are returned on MediaCodec.flush 5772 mode = KEEP_BUFFERS; 5773 } 5774 sp<RefBase> obj; 5775 CHECK(msg->findObject("buffer", &obj)); 5776 buffer = static_cast<MediaCodecBuffer *>(obj.get()); 5777 5778 int32_t tmp; 5779 if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) { 5780 eos = true; 5781 err = ERROR_END_OF_STREAM; 5782 } 5783 5784 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID); 5785 BufferInfo::Status status = BufferInfo::getSafeStatus(info); 5786 if (status != BufferInfo::OWNED_BY_UPSTREAM) { 5787 ALOGE("Wrong ownership in IBF: %s(%d) buffer #%u", _asString(status), status, bufferID); 5788 mCodec->dumpBuffers(kPortIndexInput); 5789 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 5790 return; 5791 } 5792 5793 info->mStatus = BufferInfo::OWNED_BY_US; 5794 info->mData = buffer; 5795 5796 switch (mode) { 5797 case KEEP_BUFFERS: 5798 { 5799 if (eos) { 5800 if (!mCodec->mPortEOS[kPortIndexInput]) { 5801 mCodec->mPortEOS[kPortIndexInput] = true; 5802 mCodec->mInputEOSResult = err; 5803 } 5804 } 5805 break; 5806 } 5807 5808 case RESUBMIT_BUFFERS: 5809 { 5810 if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) { 5811 // Do not send empty input buffer w/o EOS to the component. 5812 if (buffer->size() == 0 && !eos) { 5813 postFillThisBuffer(info); 5814 break; 5815 } 5816 5817 int64_t timeUs; 5818 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 5819 5820 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME; 5821 5822 int32_t isCSD = 0; 5823 if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) { 5824 if (mCodec->mIsLegacyVP9Decoder) { 5825 ALOGV("[%s] is legacy VP9 decoder. Ignore %u codec specific data", 5826 mCodec->mComponentName.c_str(), bufferID); 5827 postFillThisBuffer(info); 5828 break; 5829 } 5830 flags |= OMX_BUFFERFLAG_CODECCONFIG; 5831 } 5832 5833 if (eos) { 5834 flags |= OMX_BUFFERFLAG_EOS; 5835 } 5836 5837 size_t size = buffer->size(); 5838 size_t offset = buffer->offset(); 5839 if (buffer->base() != info->mCodecData->base()) { 5840 ALOGV("[%s] Needs to copy input data for buffer %u. (%p != %p)", 5841 mCodec->mComponentName.c_str(), 5842 bufferID, 5843 buffer->base(), info->mCodecData->base()); 5844 5845 sp<DataConverter> converter = mCodec->mConverter[kPortIndexInput]; 5846 if (converter == NULL || isCSD) { 5847 converter = getCopyConverter(); 5848 } 5849 status_t err = converter->convert(buffer, info->mCodecData); 5850 if (err != OK) { 5851 mCodec->signalError(OMX_ErrorUndefined, err); 5852 return; 5853 } 5854 size = info->mCodecData->size(); 5855 } else { 5856 info->mCodecData->setRange(offset, size); 5857 } 5858 5859 if (flags & OMX_BUFFERFLAG_CODECCONFIG) { 5860 ALOGV("[%s] calling emptyBuffer %u w/ codec specific data", 5861 mCodec->mComponentName.c_str(), bufferID); 5862 } else if (flags & OMX_BUFFERFLAG_EOS) { 5863 ALOGV("[%s] calling emptyBuffer %u w/ EOS", 5864 mCodec->mComponentName.c_str(), bufferID); 5865 } else { 5866#if TRACK_BUFFER_TIMING 5867 ALOGI("[%s] calling emptyBuffer %u w/ time %lld us", 5868 mCodec->mComponentName.c_str(), bufferID, (long long)timeUs); 5869#else 5870 ALOGV("[%s] calling emptyBuffer %u w/ time %lld us", 5871 mCodec->mComponentName.c_str(), bufferID, (long long)timeUs); 5872#endif 5873 } 5874 5875#if TRACK_BUFFER_TIMING 5876 ACodec::BufferStats stats; 5877 stats.mEmptyBufferTimeUs = ALooper::GetNowUs(); 5878 stats.mFillBufferDoneTimeUs = -1ll; 5879 mCodec->mBufferStats.add(timeUs, stats); 5880#endif 5881 5882 if (mCodec->storingMetadataInDecodedBuffers()) { 5883 // try to submit an output buffer for each input buffer 5884 PortMode outputMode = getPortMode(kPortIndexOutput); 5885 5886 ALOGV("MetadataBuffersToSubmit=%u portMode=%s", 5887 mCodec->mMetadataBuffersToSubmit, 5888 (outputMode == FREE_BUFFERS ? "FREE" : 5889 outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT")); 5890 if (outputMode == RESUBMIT_BUFFERS) { 5891 mCodec->submitOutputMetadataBuffer(); 5892 } 5893 } 5894 info->checkReadFence("onInputBufferFilled"); 5895 5896 status_t err2 = OK; 5897 switch (mCodec->mPortMode[kPortIndexInput]) { 5898 case IOMX::kPortModePresetByteBuffer: 5899 case IOMX::kPortModePresetANWBuffer: 5900 case IOMX::kPortModePresetSecureBuffer: 5901 { 5902 err2 = mCodec->mOMXNode->emptyBuffer( 5903 bufferID, info->mCodecData, flags, timeUs, info->mFenceFd); 5904 } 5905 break; 5906#ifndef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS 5907 case IOMX::kPortModeDynamicNativeHandle: 5908 if (info->mCodecData->size() >= sizeof(VideoNativeHandleMetadata)) { 5909 VideoNativeHandleMetadata *vnhmd = 5910 (VideoNativeHandleMetadata*)info->mCodecData->base(); 5911 sp<NativeHandle> handle = NativeHandle::create( 5912 vnhmd->pHandle, false /* ownsHandle */); 5913 err2 = mCodec->mOMXNode->emptyBuffer( 5914 bufferID, handle, flags, timeUs, info->mFenceFd); 5915 } 5916 break; 5917 case IOMX::kPortModeDynamicANWBuffer: 5918 if (info->mCodecData->size() >= sizeof(VideoNativeMetadata)) { 5919 VideoNativeMetadata *vnmd = (VideoNativeMetadata*)info->mCodecData->base(); 5920 sp<GraphicBuffer> graphicBuffer = GraphicBuffer::from(vnmd->pBuffer); 5921 err2 = mCodec->mOMXNode->emptyBuffer( 5922 bufferID, graphicBuffer, flags, timeUs, info->mFenceFd); 5923 } 5924 break; 5925#endif 5926 default: 5927 ALOGW("Can't marshall %s data in %zu sized buffers in %zu-bit mode", 5928 asString(mCodec->mPortMode[kPortIndexInput]), 5929 info->mCodecData->size(), 5930 sizeof(buffer_handle_t) * 8); 5931 err2 = ERROR_UNSUPPORTED; 5932 break; 5933 } 5934 5935 info->mFenceFd = -1; 5936 if (err2 != OK) { 5937 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2)); 5938 return; 5939 } 5940 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 5941 // Hold the reference while component is using the buffer. 5942 info->mData = buffer; 5943 5944 if (!eos && err == OK) { 5945 getMoreInputDataIfPossible(); 5946 } else { 5947 ALOGV("[%s] Signalled EOS (%d) on the input port", 5948 mCodec->mComponentName.c_str(), err); 5949 5950 mCodec->mPortEOS[kPortIndexInput] = true; 5951 mCodec->mInputEOSResult = err; 5952 } 5953 } else if (!mCodec->mPortEOS[kPortIndexInput]) { 5954 if (err != OK && err != ERROR_END_OF_STREAM) { 5955 ALOGV("[%s] Signalling EOS on the input port due to error %d", 5956 mCodec->mComponentName.c_str(), err); 5957 } else { 5958 ALOGV("[%s] Signalling EOS on the input port", 5959 mCodec->mComponentName.c_str()); 5960 } 5961 5962 ALOGV("[%s] calling emptyBuffer %u signalling EOS", 5963 mCodec->mComponentName.c_str(), bufferID); 5964 5965 info->checkReadFence("onInputBufferFilled"); 5966 status_t err2 = mCodec->mOMXNode->emptyBuffer( 5967 bufferID, OMXBuffer::sPreset, OMX_BUFFERFLAG_EOS, 0, info->mFenceFd); 5968 info->mFenceFd = -1; 5969 if (err2 != OK) { 5970 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2)); 5971 return; 5972 } 5973 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 5974 5975 mCodec->mPortEOS[kPortIndexInput] = true; 5976 mCodec->mInputEOSResult = err; 5977 } 5978 break; 5979 } 5980 5981 case FREE_BUFFERS: 5982 break; 5983 5984 default: 5985 ALOGE("invalid port mode: %d", mode); 5986 break; 5987 } 5988} 5989 5990void ACodec::BaseState::getMoreInputDataIfPossible() { 5991 if (mCodec->mPortEOS[kPortIndexInput]) { 5992 return; 5993 } 5994 5995 BufferInfo *eligible = NULL; 5996 5997 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 5998 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 5999 6000#if 0 6001 if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) { 6002 // There's already a "read" pending. 6003 return; 6004 } 6005#endif 6006 6007 if (info->mStatus == BufferInfo::OWNED_BY_US) { 6008 eligible = info; 6009 } 6010 } 6011 6012 if (eligible == NULL) { 6013 return; 6014 } 6015 6016 postFillThisBuffer(eligible); 6017} 6018 6019bool ACodec::BaseState::onOMXFillBufferDone( 6020 IOMX::buffer_id bufferID, 6021 size_t rangeOffset, size_t rangeLength, 6022 OMX_U32 flags, 6023 int64_t timeUs, 6024 int fenceFd) { 6025 ALOGV("[%s] onOMXFillBufferDone %u time %" PRId64 " us, flags = 0x%08x", 6026 mCodec->mComponentName.c_str(), bufferID, timeUs, flags); 6027 6028 ssize_t index; 6029 status_t err= OK; 6030 6031#if TRACK_BUFFER_TIMING 6032 index = mCodec->mBufferStats.indexOfKey(timeUs); 6033 if (index >= 0) { 6034 ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index); 6035 stats->mFillBufferDoneTimeUs = ALooper::GetNowUs(); 6036 6037 ALOGI("frame PTS %lld: %lld", 6038 timeUs, 6039 stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs); 6040 6041 mCodec->mBufferStats.removeItemsAt(index); 6042 stats = NULL; 6043 } 6044#endif 6045 6046 BufferInfo *info = 6047 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 6048 BufferInfo::Status status = BufferInfo::getSafeStatus(info); 6049 if (status != BufferInfo::OWNED_BY_COMPONENT) { 6050 ALOGE("Wrong ownership in FBD: %s(%d) buffer #%u", _asString(status), status, bufferID); 6051 mCodec->dumpBuffers(kPortIndexOutput); 6052 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6053 if (fenceFd >= 0) { 6054 ::close(fenceFd); 6055 } 6056 return true; 6057 } 6058 6059 info->mDequeuedAt = ++mCodec->mDequeueCounter; 6060 info->mStatus = BufferInfo::OWNED_BY_US; 6061 6062 if (info->mRenderInfo != NULL) { 6063 // The fence for an emptied buffer must have signaled, but there still could be queued 6064 // or out-of-order dequeued buffers in the render queue prior to this buffer. Drop these, 6065 // as we will soon requeue this buffer to the surface. While in theory we could still keep 6066 // track of buffers that are requeued to the surface, it is better to add support to the 6067 // buffer-queue to notify us of released buffers and their fences (in the future). 6068 mCodec->notifyOfRenderedFrames(true /* dropIncomplete */); 6069 } 6070 6071 // byte buffers cannot take fences, so wait for any fence now 6072 if (mCodec->mNativeWindow == NULL) { 6073 (void)mCodec->waitForFence(fenceFd, "onOMXFillBufferDone"); 6074 fenceFd = -1; 6075 } 6076 info->setReadFence(fenceFd, "onOMXFillBufferDone"); 6077 6078 PortMode mode = getPortMode(kPortIndexOutput); 6079 6080 switch (mode) { 6081 case KEEP_BUFFERS: 6082 break; 6083 6084 case RESUBMIT_BUFFERS: 6085 { 6086 if (rangeLength == 0 && (!(flags & OMX_BUFFERFLAG_EOS) 6087 || mCodec->mPortEOS[kPortIndexOutput])) { 6088 ALOGV("[%s] calling fillBuffer %u", 6089 mCodec->mComponentName.c_str(), info->mBufferID); 6090 6091 err = mCodec->fillBuffer(info); 6092 if (err != OK) { 6093 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6094 return true; 6095 } 6096 break; 6097 } 6098 6099 sp<MediaCodecBuffer> buffer = info->mData; 6100 6101 if (mCodec->mOutputFormat != mCodec->mLastOutputFormat && rangeLength > 0) { 6102 // pretend that output format has changed on the first frame (we used to do this) 6103 if (mCodec->mBaseOutputFormat == mCodec->mOutputFormat) { 6104 mCodec->onOutputFormatChanged(mCodec->mOutputFormat); 6105 } 6106 mCodec->sendFormatChange(); 6107 } 6108 buffer->setFormat(mCodec->mOutputFormat); 6109 6110 if (mCodec->usingSecureBufferOnEncoderOutput()) { 6111 native_handle_t *handle = NULL; 6112 sp<SecureBuffer> secureBuffer = static_cast<SecureBuffer *>(buffer.get()); 6113 if (secureBuffer != NULL) { 6114#ifdef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS 6115 // handle is only valid on 32-bit/mediaserver process 6116 handle = NULL; 6117#else 6118 handle = (native_handle_t *)secureBuffer->getDestinationPointer(); 6119#endif 6120 } 6121 buffer->meta()->setPointer("handle", handle); 6122 buffer->meta()->setInt32("rangeOffset", rangeOffset); 6123 buffer->meta()->setInt32("rangeLength", rangeLength); 6124 } else if (buffer->base() == info->mCodecData->base()) { 6125 buffer->setRange(rangeOffset, rangeLength); 6126 } else { 6127 info->mCodecData->setRange(rangeOffset, rangeLength); 6128 // in this case we know that mConverter is not null 6129 status_t err = mCodec->mConverter[kPortIndexOutput]->convert( 6130 info->mCodecData, buffer); 6131 if (err != OK) { 6132 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6133 return true; 6134 } 6135 } 6136#if 0 6137 if (mCodec->mNativeWindow == NULL) { 6138 if (IsIDR(info->mData->data(), info->mData->size())) { 6139 ALOGI("IDR frame"); 6140 } 6141 } 6142#endif 6143 6144 if (mCodec->mSkipCutBuffer != NULL) { 6145 mCodec->mSkipCutBuffer->submit(buffer); 6146 } 6147 buffer->meta()->setInt64("timeUs", timeUs); 6148 6149 info->mData.clear(); 6150 6151 mCodec->mBufferChannel->drainThisBuffer(info->mBufferID, flags); 6152 6153 info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM; 6154 6155 if (flags & OMX_BUFFERFLAG_EOS) { 6156 ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str()); 6157 6158 mCodec->mCallback->onEos(mCodec->mInputEOSResult); 6159 mCodec->mPortEOS[kPortIndexOutput] = true; 6160 } 6161 break; 6162 } 6163 6164 case FREE_BUFFERS: 6165 err = mCodec->freeBuffer(kPortIndexOutput, index); 6166 if (err != OK) { 6167 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6168 return true; 6169 } 6170 break; 6171 6172 default: 6173 ALOGE("Invalid port mode: %d", mode); 6174 return false; 6175 } 6176 6177 return true; 6178} 6179 6180void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { 6181 IOMX::buffer_id bufferID; 6182 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID)); 6183 sp<RefBase> obj; 6184 CHECK(msg->findObject("buffer", &obj)); 6185 sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get()); 6186 int32_t discarded = 0; 6187 msg->findInt32("discarded", &discarded); 6188 6189 ssize_t index; 6190 BufferInfo *info = mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 6191 BufferInfo::Status status = BufferInfo::getSafeStatus(info); 6192 if (status != BufferInfo::OWNED_BY_DOWNSTREAM) { 6193 ALOGE("Wrong ownership in OBD: %s(%d) buffer #%u", _asString(status), status, bufferID); 6194 mCodec->dumpBuffers(kPortIndexOutput); 6195 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6196 return; 6197 } 6198 info->mData = buffer; 6199 int32_t render; 6200 if (mCodec->mNativeWindow != NULL 6201 && msg->findInt32("render", &render) && render != 0 6202 && !discarded && buffer->size() != 0) { 6203 ATRACE_NAME("render"); 6204 // The client wants this buffer to be rendered. 6205 6206 android_native_rect_t crop; 6207 if (buffer->format()->findRect("crop", &crop.left, &crop.top, &crop.right, &crop.bottom)) { 6208 // NOTE: native window uses extended right-bottom coordinate 6209 ++crop.right; 6210 ++crop.bottom; 6211 if (memcmp(&crop, &mCodec->mLastNativeWindowCrop, sizeof(crop)) != 0) { 6212 mCodec->mLastNativeWindowCrop = crop; 6213 status_t err = native_window_set_crop(mCodec->mNativeWindow.get(), &crop); 6214 ALOGW_IF(err != NO_ERROR, "failed to set crop: %d", err); 6215 } 6216 } 6217 6218 int32_t dataSpace; 6219 if (buffer->format()->findInt32("android._dataspace", &dataSpace) 6220 && dataSpace != mCodec->mLastNativeWindowDataSpace) { 6221 status_t err = native_window_set_buffers_data_space( 6222 mCodec->mNativeWindow.get(), (android_dataspace)dataSpace); 6223 mCodec->mLastNativeWindowDataSpace = dataSpace; 6224 ALOGW_IF(err != NO_ERROR, "failed to set dataspace: %d", err); 6225 } 6226 if (buffer->format()->contains("hdr-static-info")) { 6227 HDRStaticInfo info; 6228 if (ColorUtils::getHDRStaticInfoFromFormat(buffer->format(), &info) 6229 && memcmp(&mCodec->mLastHDRStaticInfo, &info, sizeof(info))) { 6230 setNativeWindowHdrMetadata(mCodec->mNativeWindow.get(), &info); 6231 mCodec->mLastHDRStaticInfo = info; 6232 } 6233 } 6234 6235 // save buffers sent to the surface so we can get render time when they return 6236 int64_t mediaTimeUs = -1; 6237 buffer->meta()->findInt64("timeUs", &mediaTimeUs); 6238 if (mediaTimeUs >= 0) { 6239 mCodec->mRenderTracker.onFrameQueued( 6240 mediaTimeUs, info->mGraphicBuffer, new Fence(::dup(info->mFenceFd))); 6241 } 6242 6243 int64_t timestampNs = 0; 6244 if (!msg->findInt64("timestampNs", ×tampNs)) { 6245 // use media timestamp if client did not request a specific render timestamp 6246 if (buffer->meta()->findInt64("timeUs", ×tampNs)) { 6247 ALOGV("using buffer PTS of %lld", (long long)timestampNs); 6248 timestampNs *= 1000; 6249 } 6250 } 6251 6252 status_t err; 6253 err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs); 6254 ALOGW_IF(err != NO_ERROR, "failed to set buffer timestamp: %d", err); 6255 6256 info->checkReadFence("onOutputBufferDrained before queueBuffer"); 6257 err = mCodec->mNativeWindow->queueBuffer( 6258 mCodec->mNativeWindow.get(), info->mGraphicBuffer.get(), info->mFenceFd); 6259 info->mFenceFd = -1; 6260 if (err == OK) { 6261 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 6262 } else { 6263 ALOGE("queueBuffer failed in onOutputBufferDrained: %d", err); 6264 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6265 info->mStatus = BufferInfo::OWNED_BY_US; 6266 // keeping read fence as write fence to avoid clobbering 6267 info->mIsReadFence = false; 6268 } 6269 } else { 6270 if (mCodec->mNativeWindow != NULL && (discarded || buffer->size() != 0)) { 6271 // move read fence into write fence to avoid clobbering 6272 info->mIsReadFence = false; 6273 ATRACE_NAME("frame-drop"); 6274 } 6275 info->mStatus = BufferInfo::OWNED_BY_US; 6276 } 6277 6278 PortMode mode = getPortMode(kPortIndexOutput); 6279 6280 switch (mode) { 6281 case KEEP_BUFFERS: 6282 { 6283 // XXX fishy, revisit!!! What about the FREE_BUFFERS case below? 6284 6285 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 6286 // We cannot resubmit the buffer we just rendered, dequeue 6287 // the spare instead. 6288 6289 info = mCodec->dequeueBufferFromNativeWindow(); 6290 } 6291 break; 6292 } 6293 6294 case RESUBMIT_BUFFERS: 6295 { 6296 if (!mCodec->mPortEOS[kPortIndexOutput]) { 6297 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 6298 // We cannot resubmit the buffer we just rendered, dequeue 6299 // the spare instead. 6300 6301 info = mCodec->dequeueBufferFromNativeWindow(); 6302 } 6303 6304 if (info != NULL) { 6305 ALOGV("[%s] calling fillBuffer %u", 6306 mCodec->mComponentName.c_str(), info->mBufferID); 6307 info->checkWriteFence("onOutputBufferDrained::RESUBMIT_BUFFERS"); 6308 status_t err = mCodec->fillBuffer(info); 6309 if (err != OK) { 6310 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6311 } 6312 } 6313 } 6314 break; 6315 } 6316 6317 case FREE_BUFFERS: 6318 { 6319 status_t err = mCodec->freeBuffer(kPortIndexOutput, index); 6320 if (err != OK) { 6321 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6322 } 6323 break; 6324 } 6325 6326 default: 6327 ALOGE("Invalid port mode: %d", mode); 6328 return; 6329 } 6330} 6331 6332//////////////////////////////////////////////////////////////////////////////// 6333 6334ACodec::UninitializedState::UninitializedState(ACodec *codec) 6335 : BaseState(codec) { 6336} 6337 6338void ACodec::UninitializedState::stateEntered() { 6339 ALOGV("Now uninitialized"); 6340 6341 if (mDeathNotifier != NULL) { 6342 if (mCodec->mOMXNode != NULL) { 6343 auto tOmxNode = mCodec->mOMXNode->getHalInterface(); 6344 tOmxNode->unlinkToDeath(mDeathNotifier); 6345 } 6346 mDeathNotifier.clear(); 6347 } 6348 6349 mCodec->mUsingNativeWindow = false; 6350 mCodec->mNativeWindow.clear(); 6351 mCodec->mNativeWindowUsageBits = 0; 6352 mCodec->mOMX.clear(); 6353 mCodec->mOMXNode.clear(); 6354 mCodec->mFlags = 0; 6355 mCodec->mPortMode[kPortIndexInput] = IOMX::kPortModePresetByteBuffer; 6356 mCodec->mPortMode[kPortIndexOutput] = IOMX::kPortModePresetByteBuffer; 6357 mCodec->mConverter[0].clear(); 6358 mCodec->mConverter[1].clear(); 6359 mCodec->mComponentName.clear(); 6360} 6361 6362bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) { 6363 bool handled = false; 6364 6365 switch (msg->what()) { 6366 case ACodec::kWhatSetup: 6367 { 6368 onSetup(msg); 6369 6370 handled = true; 6371 break; 6372 } 6373 6374 case ACodec::kWhatAllocateComponent: 6375 { 6376 onAllocateComponent(msg); 6377 handled = true; 6378 break; 6379 } 6380 6381 case ACodec::kWhatShutdown: 6382 { 6383 int32_t keepComponentAllocated; 6384 CHECK(msg->findInt32( 6385 "keepComponentAllocated", &keepComponentAllocated)); 6386 ALOGW_IF(keepComponentAllocated, 6387 "cannot keep component allocated on shutdown in Uninitialized state"); 6388 if (keepComponentAllocated) { 6389 mCodec->mCallback->onStopCompleted(); 6390 } else { 6391 mCodec->mCallback->onReleaseCompleted(); 6392 } 6393 handled = true; 6394 break; 6395 } 6396 6397 case ACodec::kWhatFlush: 6398 { 6399 mCodec->mCallback->onFlushCompleted(); 6400 handled = true; 6401 break; 6402 } 6403 6404 case ACodec::kWhatReleaseCodecInstance: 6405 { 6406 // nothing to do, as we have already signaled shutdown 6407 handled = true; 6408 break; 6409 } 6410 6411 default: 6412 return BaseState::onMessageReceived(msg); 6413 } 6414 6415 return handled; 6416} 6417 6418void ACodec::UninitializedState::onSetup( 6419 const sp<AMessage> &msg) { 6420 if (onAllocateComponent(msg) 6421 && mCodec->mLoadedState->onConfigureComponent(msg)) { 6422 mCodec->mLoadedState->onStart(); 6423 } 6424} 6425 6426bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) { 6427 ALOGV("onAllocateComponent"); 6428 6429 CHECK(mCodec->mOMXNode == NULL); 6430 6431 sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec); 6432 6433 sp<RefBase> obj; 6434 CHECK(msg->findObject("codecInfo", &obj)); 6435 sp<MediaCodecInfo> info = (MediaCodecInfo *)obj.get(); 6436 if (info == nullptr) { 6437 ALOGE("Unexpected nullptr for codec information"); 6438 mCodec->signalError(OMX_ErrorUndefined, UNKNOWN_ERROR); 6439 return false; 6440 } 6441 AString owner = (info->getOwnerName() == nullptr) ? "default" : info->getOwnerName(); 6442 6443 AString componentName; 6444 CHECK(msg->findString("componentName", &componentName)); 6445 6446 sp<CodecObserver> observer = new CodecObserver; 6447 sp<IOMX> omx; 6448 sp<IOMXNode> omxNode; 6449 6450 status_t err = NAME_NOT_FOUND; 6451 OMXClient client; 6452 if (client.connect(owner.c_str()) != OK) { 6453 mCodec->signalError(OMX_ErrorUndefined, NO_INIT); 6454 return false; 6455 } 6456 omx = client.interface(); 6457 6458 pid_t tid = gettid(); 6459 int prevPriority = androidGetThreadPriority(tid); 6460 androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND); 6461 err = omx->allocateNode(componentName.c_str(), observer, &omxNode); 6462 androidSetThreadPriority(tid, prevPriority); 6463 6464 if (err != OK) { 6465 ALOGE("Unable to instantiate codec '%s' with err %#x.", componentName.c_str(), err); 6466 6467 mCodec->signalError((OMX_ERRORTYPE)err, makeNoSideEffectStatus(err)); 6468 return false; 6469 } 6470 6471 mDeathNotifier = new DeathNotifier(notify); 6472 auto tOmxNode = omxNode->getHalInterface(); 6473 if (!tOmxNode->linkToDeath(mDeathNotifier, 0)) { 6474 mDeathNotifier.clear(); 6475 } 6476 6477 notify = new AMessage(kWhatOMXMessageList, mCodec); 6478 notify->setInt32("generation", ++mCodec->mNodeGeneration); 6479 observer->setNotificationMessage(notify); 6480 6481 mCodec->mComponentName = componentName; 6482 mCodec->mRenderTracker.setComponentName(componentName); 6483 mCodec->mFlags = 0; 6484 6485 if (componentName.endsWith(".secure")) { 6486 mCodec->mFlags |= kFlagIsSecure; 6487 mCodec->mFlags |= kFlagIsGrallocUsageProtected; 6488 mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown; 6489 } 6490 6491 mCodec->mOMX = omx; 6492 mCodec->mOMXNode = omxNode; 6493 mCodec->mCallback->onComponentAllocated(mCodec->mComponentName.c_str()); 6494 mCodec->changeState(mCodec->mLoadedState); 6495 6496 return true; 6497} 6498 6499//////////////////////////////////////////////////////////////////////////////// 6500 6501ACodec::LoadedState::LoadedState(ACodec *codec) 6502 : BaseState(codec) { 6503} 6504 6505void ACodec::LoadedState::stateEntered() { 6506 ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str()); 6507 6508 mCodec->mPortEOS[kPortIndexInput] = 6509 mCodec->mPortEOS[kPortIndexOutput] = false; 6510 6511 mCodec->mInputEOSResult = OK; 6512 6513 mCodec->mDequeueCounter = 0; 6514 mCodec->mMetadataBuffersToSubmit = 0; 6515 mCodec->mRepeatFrameDelayUs = -1ll; 6516 mCodec->mInputFormat.clear(); 6517 mCodec->mOutputFormat.clear(); 6518 mCodec->mBaseOutputFormat.clear(); 6519 mCodec->mGraphicBufferSource.clear(); 6520 6521 if (mCodec->mShutdownInProgress) { 6522 bool keepComponentAllocated = mCodec->mKeepComponentAllocated; 6523 6524 mCodec->mShutdownInProgress = false; 6525 mCodec->mKeepComponentAllocated = false; 6526 6527 onShutdown(keepComponentAllocated); 6528 } 6529 mCodec->mExplicitShutdown = false; 6530 6531 mCodec->processDeferredMessages(); 6532} 6533 6534void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) { 6535 if (!keepComponentAllocated) { 6536 (void)mCodec->mOMXNode->freeNode(); 6537 6538 mCodec->changeState(mCodec->mUninitializedState); 6539 } 6540 6541 if (mCodec->mExplicitShutdown) { 6542 if (keepComponentAllocated) { 6543 mCodec->mCallback->onStopCompleted(); 6544 } else { 6545 mCodec->mCallback->onReleaseCompleted(); 6546 } 6547 mCodec->mExplicitShutdown = false; 6548 } 6549} 6550 6551bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) { 6552 bool handled = false; 6553 6554 switch (msg->what()) { 6555 case ACodec::kWhatConfigureComponent: 6556 { 6557 onConfigureComponent(msg); 6558 handled = true; 6559 break; 6560 } 6561 6562 case ACodec::kWhatCreateInputSurface: 6563 { 6564 onCreateInputSurface(msg); 6565 handled = true; 6566 break; 6567 } 6568 6569 case ACodec::kWhatSetInputSurface: 6570 { 6571 onSetInputSurface(msg); 6572 handled = true; 6573 break; 6574 } 6575 6576 case ACodec::kWhatStart: 6577 { 6578 onStart(); 6579 handled = true; 6580 break; 6581 } 6582 6583 case ACodec::kWhatShutdown: 6584 { 6585 int32_t keepComponentAllocated; 6586 CHECK(msg->findInt32( 6587 "keepComponentAllocated", &keepComponentAllocated)); 6588 6589 mCodec->mExplicitShutdown = true; 6590 onShutdown(keepComponentAllocated); 6591 6592 handled = true; 6593 break; 6594 } 6595 6596 case ACodec::kWhatFlush: 6597 { 6598 mCodec->mCallback->onFlushCompleted(); 6599 handled = true; 6600 break; 6601 } 6602 6603 default: 6604 return BaseState::onMessageReceived(msg); 6605 } 6606 6607 return handled; 6608} 6609 6610bool ACodec::LoadedState::onConfigureComponent( 6611 const sp<AMessage> &msg) { 6612 ALOGV("onConfigureComponent"); 6613 6614 CHECK(mCodec->mOMXNode != NULL); 6615 6616 status_t err = OK; 6617 AString mime; 6618 if (!msg->findString("mime", &mime)) { 6619 err = BAD_VALUE; 6620 } else { 6621 err = mCodec->configureCodec(mime.c_str(), msg); 6622 } 6623 if (err != OK) { 6624 ALOGE("[%s] configureCodec returning error %d", 6625 mCodec->mComponentName.c_str(), err); 6626 6627 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6628 return false; 6629 } 6630 6631 mCodec->mCallback->onComponentConfigured(mCodec->mInputFormat, mCodec->mOutputFormat); 6632 6633 return true; 6634} 6635 6636status_t ACodec::LoadedState::setupInputSurface() { 6637 if (mCodec->mGraphicBufferSource == NULL) { 6638 return BAD_VALUE; 6639 } 6640 6641 android_dataspace dataSpace; 6642 status_t err = 6643 mCodec->setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace(&dataSpace); 6644 if (err != OK) { 6645 ALOGE("Failed to get default data space"); 6646 return err; 6647 } 6648 6649 err = statusFromBinderStatus( 6650 mCodec->mGraphicBufferSource->configure(mCodec->mOMXNode, dataSpace)); 6651 if (err != OK) { 6652 ALOGE("[%s] Unable to configure for node (err %d)", 6653 mCodec->mComponentName.c_str(), err); 6654 return err; 6655 } 6656 6657 if (mCodec->mRepeatFrameDelayUs > 0ll) { 6658 err = statusFromBinderStatus( 6659 mCodec->mGraphicBufferSource->setRepeatPreviousFrameDelayUs( 6660 mCodec->mRepeatFrameDelayUs)); 6661 6662 if (err != OK) { 6663 ALOGE("[%s] Unable to configure option to repeat previous " 6664 "frames (err %d)", 6665 mCodec->mComponentName.c_str(), err); 6666 return err; 6667 } 6668 } 6669 6670 if (mCodec->mMaxPtsGapUs > 0ll) { 6671 OMX_PARAM_U32TYPE maxPtsGapParams; 6672 InitOMXParams(&maxPtsGapParams); 6673 maxPtsGapParams.nPortIndex = kPortIndexInput; 6674 maxPtsGapParams.nU32 = (uint32_t) mCodec->mMaxPtsGapUs; 6675 6676 err = mCodec->mOMXNode->setParameter( 6677 (OMX_INDEXTYPE)OMX_IndexParamMaxFrameDurationForBitrateControl, 6678 &maxPtsGapParams, sizeof(maxPtsGapParams)); 6679 6680 if (err != OK) { 6681 ALOGE("[%s] Unable to configure max timestamp gap (err %d)", 6682 mCodec->mComponentName.c_str(), err); 6683 return err; 6684 } 6685 } 6686 6687 if (mCodec->mMaxFps > 0) { 6688 err = statusFromBinderStatus( 6689 mCodec->mGraphicBufferSource->setMaxFps(mCodec->mMaxFps)); 6690 6691 if (err != OK) { 6692 ALOGE("[%s] Unable to configure max fps (err %d)", 6693 mCodec->mComponentName.c_str(), err); 6694 return err; 6695 } 6696 } 6697 6698 if (mCodec->mCaptureFps > 0. && mCodec->mFps > 0.) { 6699 err = statusFromBinderStatus( 6700 mCodec->mGraphicBufferSource->setTimeLapseConfig( 6701 mCodec->mFps, mCodec->mCaptureFps)); 6702 6703 if (err != OK) { 6704 ALOGE("[%s] Unable to configure time lapse (err %d)", 6705 mCodec->mComponentName.c_str(), err); 6706 return err; 6707 } 6708 } 6709 6710 if (mCodec->mCreateInputBuffersSuspended) { 6711 err = statusFromBinderStatus( 6712 mCodec->mGraphicBufferSource->setSuspend(true, -1)); 6713 6714 if (err != OK) { 6715 ALOGE("[%s] Unable to configure option to suspend (err %d)", 6716 mCodec->mComponentName.c_str(), err); 6717 return err; 6718 } 6719 } 6720 6721 uint32_t usageBits; 6722 if (mCodec->mOMXNode->getParameter( 6723 (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits, 6724 &usageBits, sizeof(usageBits)) == OK) { 6725 mCodec->mInputFormat->setInt32( 6726 "using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN)); 6727 } 6728 6729 sp<ABuffer> colorAspectsBuffer; 6730 if (mCodec->mInputFormat->findBuffer("android._color-aspects", &colorAspectsBuffer)) { 6731 if (colorAspectsBuffer->size() != sizeof(ColorAspects)) { 6732 return INVALID_OPERATION; 6733 } 6734 6735 err = statusFromBinderStatus( 6736 mCodec->mGraphicBufferSource->setColorAspects(ColorUtils::packToU32( 6737 *(ColorAspects *)colorAspectsBuffer->base()))); 6738 6739 if (err != OK) { 6740 ALOGE("[%s] Unable to configure color aspects (err %d)", 6741 mCodec->mComponentName.c_str(), err); 6742 return err; 6743 } 6744 } 6745 return OK; 6746} 6747 6748void ACodec::LoadedState::onCreateInputSurface( 6749 const sp<AMessage> & /* msg */) { 6750 ALOGV("onCreateInputSurface"); 6751 6752 sp<IGraphicBufferProducer> bufferProducer; 6753 status_t err = mCodec->mOMX->createInputSurface( 6754 &bufferProducer, &mCodec->mGraphicBufferSource); 6755 6756 if (err == OK) { 6757 err = setupInputSurface(); 6758 } 6759 6760 if (err == OK) { 6761 mCodec->mCallback->onInputSurfaceCreated( 6762 mCodec->mInputFormat, 6763 mCodec->mOutputFormat, 6764 new BufferProducerWrapper(bufferProducer)); 6765 } else { 6766 // Can't use mCodec->signalError() here -- MediaCodec won't forward 6767 // the error through because it's in the "configured" state. We 6768 // send a kWhatInputSurfaceCreated with an error value instead. 6769 ALOGE("[%s] onCreateInputSurface returning error %d", 6770 mCodec->mComponentName.c_str(), err); 6771 mCodec->mCallback->onInputSurfaceCreationFailed(err); 6772 } 6773} 6774 6775void ACodec::LoadedState::onSetInputSurface(const sp<AMessage> &msg) { 6776 ALOGV("onSetInputSurface"); 6777 6778 sp<RefBase> obj; 6779 CHECK(msg->findObject("input-surface", &obj)); 6780 sp<PersistentSurface> surface = static_cast<PersistentSurface *>(obj.get()); 6781 mCodec->mGraphicBufferSource = surface->getBufferSource(); 6782 6783 status_t err = setupInputSurface(); 6784 6785 if (err == OK) { 6786 mCodec->mCallback->onInputSurfaceAccepted( 6787 mCodec->mInputFormat, mCodec->mOutputFormat); 6788 } else { 6789 // Can't use mCodec->signalError() here -- MediaCodec won't forward 6790 // the error through because it's in the "configured" state. We 6791 // send a kWhatInputSurfaceAccepted with an error value instead. 6792 ALOGE("[%s] onSetInputSurface returning error %d", 6793 mCodec->mComponentName.c_str(), err); 6794 mCodec->mCallback->onInputSurfaceDeclined(err); 6795 } 6796} 6797 6798void ACodec::LoadedState::onStart() { 6799 ALOGV("onStart"); 6800 6801 status_t err = mCodec->mOMXNode->sendCommand(OMX_CommandStateSet, OMX_StateIdle); 6802 if (err != OK) { 6803 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6804 } else { 6805 mCodec->changeState(mCodec->mLoadedToIdleState); 6806 } 6807} 6808 6809//////////////////////////////////////////////////////////////////////////////// 6810 6811ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec) 6812 : BaseState(codec) { 6813} 6814 6815void ACodec::LoadedToIdleState::stateEntered() { 6816 ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str()); 6817 6818 status_t err; 6819 if ((err = allocateBuffers()) != OK) { 6820 ALOGE("Failed to allocate buffers after transitioning to IDLE state " 6821 "(error 0x%08x)", 6822 err); 6823 6824 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6825 6826 mCodec->mOMXNode->sendCommand( 6827 OMX_CommandStateSet, OMX_StateLoaded); 6828 if (mCodec->allYourBuffersAreBelongToUs(kPortIndexInput)) { 6829 mCodec->freeBuffersOnPort(kPortIndexInput); 6830 } 6831 if (mCodec->allYourBuffersAreBelongToUs(kPortIndexOutput)) { 6832 mCodec->freeBuffersOnPort(kPortIndexOutput); 6833 } 6834 6835 mCodec->changeState(mCodec->mLoadedState); 6836 } 6837} 6838 6839status_t ACodec::LoadedToIdleState::allocateBuffers() { 6840 status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput); 6841 if (err != OK) { 6842 return err; 6843 } 6844 6845 err = mCodec->allocateBuffersOnPort(kPortIndexOutput); 6846 if (err != OK) { 6847 return err; 6848 } 6849 6850 mCodec->mCallback->onStartCompleted(); 6851 6852 return OK; 6853} 6854 6855bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) { 6856 switch (msg->what()) { 6857 case kWhatSetParameters: 6858 case kWhatShutdown: 6859 { 6860 mCodec->deferMessage(msg); 6861 return true; 6862 } 6863 6864 case kWhatSignalEndOfInputStream: 6865 { 6866 mCodec->onSignalEndOfInputStream(); 6867 return true; 6868 } 6869 6870 case kWhatResume: 6871 { 6872 // We'll be active soon enough. 6873 return true; 6874 } 6875 6876 case kWhatFlush: 6877 { 6878 // We haven't even started yet, so we're flushed alright... 6879 mCodec->mCallback->onFlushCompleted(); 6880 return true; 6881 } 6882 6883 default: 6884 return BaseState::onMessageReceived(msg); 6885 } 6886} 6887 6888bool ACodec::LoadedToIdleState::onOMXEvent( 6889 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 6890 switch (event) { 6891 case OMX_EventCmdComplete: 6892 { 6893 status_t err = OK; 6894 if (data1 != (OMX_U32)OMX_CommandStateSet 6895 || data2 != (OMX_U32)OMX_StateIdle) { 6896 ALOGE("Unexpected command completion in LoadedToIdleState: %s(%u) %s(%u)", 6897 asString((OMX_COMMANDTYPE)data1), data1, 6898 asString((OMX_STATETYPE)data2), data2); 6899 err = FAILED_TRANSACTION; 6900 } 6901 6902 if (err == OK) { 6903 err = mCodec->mOMXNode->sendCommand( 6904 OMX_CommandStateSet, OMX_StateExecuting); 6905 } 6906 6907 if (err != OK) { 6908 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6909 } else { 6910 mCodec->changeState(mCodec->mIdleToExecutingState); 6911 } 6912 6913 return true; 6914 } 6915 6916 default: 6917 return BaseState::onOMXEvent(event, data1, data2); 6918 } 6919} 6920 6921//////////////////////////////////////////////////////////////////////////////// 6922 6923ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec) 6924 : BaseState(codec) { 6925} 6926 6927void ACodec::IdleToExecutingState::stateEntered() { 6928 ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str()); 6929} 6930 6931bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) { 6932 switch (msg->what()) { 6933 case kWhatSetParameters: 6934 case kWhatShutdown: 6935 { 6936 mCodec->deferMessage(msg); 6937 return true; 6938 } 6939 6940 case kWhatResume: 6941 { 6942 // We'll be active soon enough. 6943 return true; 6944 } 6945 6946 case kWhatFlush: 6947 { 6948 // We haven't even started yet, so we're flushed alright... 6949 mCodec->mCallback->onFlushCompleted(); 6950 return true; 6951 } 6952 6953 case kWhatSignalEndOfInputStream: 6954 { 6955 mCodec->onSignalEndOfInputStream(); 6956 return true; 6957 } 6958 6959 default: 6960 return BaseState::onMessageReceived(msg); 6961 } 6962} 6963 6964bool ACodec::IdleToExecutingState::onOMXEvent( 6965 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 6966 switch (event) { 6967 case OMX_EventCmdComplete: 6968 { 6969 if (data1 != (OMX_U32)OMX_CommandStateSet 6970 || data2 != (OMX_U32)OMX_StateExecuting) { 6971 ALOGE("Unexpected command completion in IdleToExecutingState: %s(%u) %s(%u)", 6972 asString((OMX_COMMANDTYPE)data1), data1, 6973 asString((OMX_STATETYPE)data2), data2); 6974 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6975 return true; 6976 } 6977 6978 mCodec->mExecutingState->resume(); 6979 mCodec->changeState(mCodec->mExecutingState); 6980 6981 return true; 6982 } 6983 6984 default: 6985 return BaseState::onOMXEvent(event, data1, data2); 6986 } 6987} 6988 6989//////////////////////////////////////////////////////////////////////////////// 6990 6991ACodec::ExecutingState::ExecutingState(ACodec *codec) 6992 : BaseState(codec), 6993 mActive(false) { 6994} 6995 6996ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode( 6997 OMX_U32 /* portIndex */) { 6998 return RESUBMIT_BUFFERS; 6999} 7000 7001void ACodec::ExecutingState::submitOutputMetaBuffers() { 7002 // submit as many buffers as there are input buffers with the codec 7003 // in case we are in port reconfiguring 7004 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 7005 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 7006 7007 if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) { 7008 if (mCodec->submitOutputMetadataBuffer() != OK) 7009 break; 7010 } 7011 } 7012 7013 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** 7014 mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround(); 7015} 7016 7017void ACodec::ExecutingState::submitRegularOutputBuffers() { 7018 bool failed = false; 7019 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) { 7020 BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i); 7021 7022 if (mCodec->mNativeWindow != NULL) { 7023 if (info->mStatus != BufferInfo::OWNED_BY_US 7024 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) { 7025 ALOGE("buffers should be owned by us or the surface"); 7026 failed = true; 7027 break; 7028 } 7029 7030 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 7031 continue; 7032 } 7033 } else { 7034 if (info->mStatus != BufferInfo::OWNED_BY_US) { 7035 ALOGE("buffers should be owned by us"); 7036 failed = true; 7037 break; 7038 } 7039 } 7040 7041 ALOGV("[%s] calling fillBuffer %u", mCodec->mComponentName.c_str(), info->mBufferID); 7042 7043 info->checkWriteFence("submitRegularOutputBuffers"); 7044 status_t err = mCodec->fillBuffer(info); 7045 if (err != OK) { 7046 failed = true; 7047 break; 7048 } 7049 } 7050 7051 if (failed) { 7052 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 7053 } 7054} 7055 7056void ACodec::ExecutingState::submitOutputBuffers() { 7057 submitRegularOutputBuffers(); 7058 if (mCodec->storingMetadataInDecodedBuffers()) { 7059 submitOutputMetaBuffers(); 7060 } 7061} 7062 7063void ACodec::ExecutingState::resume() { 7064 if (mActive) { 7065 ALOGV("[%s] We're already active, no need to resume.", mCodec->mComponentName.c_str()); 7066 return; 7067 } 7068 7069 submitOutputBuffers(); 7070 7071 // Post all available input buffers 7072 if (mCodec->mBuffers[kPortIndexInput].size() == 0u) { 7073 ALOGW("[%s] we don't have any input buffers to resume", mCodec->mComponentName.c_str()); 7074 } 7075 7076 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) { 7077 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 7078 if (info->mStatus == BufferInfo::OWNED_BY_US) { 7079 postFillThisBuffer(info); 7080 } 7081 } 7082 7083 mActive = true; 7084} 7085 7086void ACodec::ExecutingState::stateEntered() { 7087 ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str()); 7088 mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC)); 7089 mCodec->processDeferredMessages(); 7090} 7091 7092bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) { 7093 bool handled = false; 7094 7095 switch (msg->what()) { 7096 case kWhatShutdown: 7097 { 7098 int32_t keepComponentAllocated; 7099 CHECK(msg->findInt32( 7100 "keepComponentAllocated", &keepComponentAllocated)); 7101 7102 mCodec->mShutdownInProgress = true; 7103 mCodec->mExplicitShutdown = true; 7104 mCodec->mKeepComponentAllocated = keepComponentAllocated; 7105 7106 mActive = false; 7107 7108 status_t err = mCodec->mOMXNode->sendCommand( 7109 OMX_CommandStateSet, OMX_StateIdle); 7110 if (err != OK) { 7111 if (keepComponentAllocated) { 7112 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 7113 } 7114 // TODO: do some recovery here. 7115 } else { 7116 mCodec->changeState(mCodec->mExecutingToIdleState); 7117 } 7118 7119 handled = true; 7120 break; 7121 } 7122 7123 case kWhatFlush: 7124 { 7125 ALOGV("[%s] ExecutingState flushing now " 7126 "(codec owns %zu/%zu input, %zu/%zu output).", 7127 mCodec->mComponentName.c_str(), 7128 mCodec->countBuffersOwnedByComponent(kPortIndexInput), 7129 mCodec->mBuffers[kPortIndexInput].size(), 7130 mCodec->countBuffersOwnedByComponent(kPortIndexOutput), 7131 mCodec->mBuffers[kPortIndexOutput].size()); 7132 7133 mActive = false; 7134 7135 status_t err = mCodec->mOMXNode->sendCommand(OMX_CommandFlush, OMX_ALL); 7136 if (err != OK) { 7137 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 7138 } else { 7139 mCodec->changeState(mCodec->mFlushingState); 7140 } 7141 7142 handled = true; 7143 break; 7144 } 7145 7146 case kWhatResume: 7147 { 7148 resume(); 7149 7150 handled = true; 7151 break; 7152 } 7153 7154 case kWhatRequestIDRFrame: 7155 { 7156 status_t err = mCodec->requestIDRFrame(); 7157 if (err != OK) { 7158 ALOGW("Requesting an IDR frame failed."); 7159 } 7160 7161 handled = true; 7162 break; 7163 } 7164 7165 case kWhatSetParameters: 7166 { 7167 sp<AMessage> params; 7168 CHECK(msg->findMessage("params", ¶ms)); 7169 7170 status_t err = mCodec->setParameters(params); 7171 7172 sp<AMessage> reply; 7173 if (msg->findMessage("reply", &reply)) { 7174 reply->setInt32("err", err); 7175 reply->post(); 7176 } 7177 7178 handled = true; 7179 break; 7180 } 7181 7182 case ACodec::kWhatSignalEndOfInputStream: 7183 { 7184 mCodec->onSignalEndOfInputStream(); 7185 handled = true; 7186 break; 7187 } 7188 7189 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** 7190 case kWhatSubmitOutputMetadataBufferIfEOS: 7191 { 7192 if (mCodec->mPortEOS[kPortIndexInput] && 7193 !mCodec->mPortEOS[kPortIndexOutput]) { 7194 status_t err = mCodec->submitOutputMetadataBuffer(); 7195 if (err == OK) { 7196 mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround(); 7197 } 7198 } 7199 return true; 7200 } 7201 7202 default: 7203 handled = BaseState::onMessageReceived(msg); 7204 break; 7205 } 7206 7207 return handled; 7208} 7209 7210status_t ACodec::setParameters(const sp<AMessage> ¶ms) { 7211 int32_t videoBitrate; 7212 if (params->findInt32("video-bitrate", &videoBitrate)) { 7213 OMX_VIDEO_CONFIG_BITRATETYPE configParams; 7214 InitOMXParams(&configParams); 7215 configParams.nPortIndex = kPortIndexOutput; 7216 configParams.nEncodeBitrate = videoBitrate; 7217 7218 status_t err = mOMXNode->setConfig( 7219 OMX_IndexConfigVideoBitrate, 7220 &configParams, 7221 sizeof(configParams)); 7222 7223 if (err != OK) { 7224 ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d", 7225 videoBitrate, err); 7226 7227 return err; 7228 } 7229 } 7230 7231 int64_t timeOffsetUs; 7232 if (params->findInt64("time-offset-us", &timeOffsetUs)) { 7233 if (mGraphicBufferSource == NULL) { 7234 ALOGE("[%s] Invalid to set input buffer time offset without surface", 7235 mComponentName.c_str()); 7236 return INVALID_OPERATION; 7237 } 7238 7239 status_t err = statusFromBinderStatus( 7240 mGraphicBufferSource->setTimeOffsetUs(timeOffsetUs)); 7241 7242 if (err != OK) { 7243 ALOGE("[%s] Unable to set input buffer time offset (err %d)", 7244 mComponentName.c_str(), 7245 err); 7246 return err; 7247 } 7248 } 7249 7250 int64_t skipFramesBeforeUs; 7251 if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) { 7252 if (mGraphicBufferSource == NULL) { 7253 ALOGE("[%s] Invalid to set start time without surface", 7254 mComponentName.c_str()); 7255 return INVALID_OPERATION; 7256 } 7257 7258 status_t err = statusFromBinderStatus( 7259 mGraphicBufferSource->setStartTimeUs(skipFramesBeforeUs)); 7260 7261 if (err != OK) { 7262 ALOGE("Failed to set parameter 'skip-frames-before' (err %d)", err); 7263 return err; 7264 } 7265 } 7266 7267 int32_t dropInputFrames; 7268 if (params->findInt32("drop-input-frames", &dropInputFrames)) { 7269 if (mGraphicBufferSource == NULL) { 7270 ALOGE("[%s] Invalid to set suspend without surface", 7271 mComponentName.c_str()); 7272 return INVALID_OPERATION; 7273 } 7274 7275 int64_t suspendStartTimeUs = -1; 7276 (void) params->findInt64("drop-start-time-us", &suspendStartTimeUs); 7277 status_t err = statusFromBinderStatus( 7278 mGraphicBufferSource->setSuspend(dropInputFrames != 0, suspendStartTimeUs)); 7279 7280 if (err != OK) { 7281 ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err); 7282 return err; 7283 } 7284 } 7285 7286 int64_t stopTimeUs; 7287 if (params->findInt64("stop-time-us", &stopTimeUs)) { 7288 if (mGraphicBufferSource == NULL) { 7289 ALOGE("[%s] Invalid to set stop time without surface", 7290 mComponentName.c_str()); 7291 return INVALID_OPERATION; 7292 } 7293 status_t err = statusFromBinderStatus( 7294 mGraphicBufferSource->setStopTimeUs(stopTimeUs)); 7295 7296 if (err != OK) { 7297 ALOGE("Failed to set parameter 'stop-time-us' (err %d)", err); 7298 return err; 7299 } 7300 7301 int64_t stopTimeOffsetUs; 7302 err = statusFromBinderStatus( 7303 mGraphicBufferSource->getStopTimeOffsetUs(&stopTimeOffsetUs)); 7304 7305 if (err != OK) { 7306 ALOGE("Failed to get stop time offset (err %d)", err); 7307 return err; 7308 } 7309 mInputFormat->setInt64("android._stop-time-offset-us", stopTimeOffsetUs); 7310 } 7311 7312 int32_t dummy; 7313 if (params->findInt32("request-sync", &dummy)) { 7314 status_t err = requestIDRFrame(); 7315 7316 if (err != OK) { 7317 ALOGE("Requesting a sync frame failed w/ err %d", err); 7318 return err; 7319 } 7320 } 7321 7322 int32_t rateInt = -1; 7323 float rateFloat = -1; 7324 if (!params->findFloat("operating-rate", &rateFloat)) { 7325 params->findInt32("operating-rate", &rateInt); 7326 rateFloat = (float) rateInt; // 16MHz (FLINTMAX) is OK for upper bound. 7327 } 7328 if (rateFloat > 0) { 7329 status_t err = setOperatingRate(rateFloat, mIsVideo); 7330 if (err != OK) { 7331 ALOGI("Failed to set parameter 'operating-rate' (err %d)", err); 7332 } 7333 } 7334 7335 int32_t intraRefreshPeriod = 0; 7336 if (params->findInt32("intra-refresh-period", &intraRefreshPeriod) 7337 && intraRefreshPeriod > 0) { 7338 status_t err = setIntraRefreshPeriod(intraRefreshPeriod, false); 7339 if (err != OK) { 7340 ALOGI("[%s] failed setIntraRefreshPeriod. Failure is fine since this key is optional", 7341 mComponentName.c_str()); 7342 err = OK; 7343 } 7344 } 7345 7346 int32_t latency = 0; 7347 if (params->findInt32("latency", &latency) && latency > 0) { 7348 status_t err = setLatency(latency); 7349 if (err != OK) { 7350 ALOGI("[%s] failed setLatency. Failure is fine since this key is optional", 7351 mComponentName.c_str()); 7352 err = OK; 7353 } 7354 } 7355 7356 // Ignore errors as failure is expected for codecs that aren't video encoders. 7357 (void)configureTemporalLayers(params, false /* inConfigure */, mOutputFormat); 7358 7359 return setVendorParameters(params); 7360} 7361 7362// Removes trailing tags matching |tag| from |key| (e.g. a settings name). |minLength| specifies 7363// the minimum number of characters to keep in |key| (even if it has trailing tags). 7364// (Used to remove trailing 'value' tags in settings names, e.g. to normalize 7365// 'vendor.settingsX.value' to 'vendor.settingsX') 7366static void removeTrailingTags(char *key, size_t minLength, const char *tag) { 7367 size_t length = strlen(key); 7368 size_t tagLength = strlen(tag); 7369 while (length > minLength + tagLength 7370 && !strcmp(key + length - tagLength, tag) 7371 && key[length - tagLength - 1] == '.') { 7372 length -= tagLength + 1; 7373 key[length] = '\0'; 7374 } 7375} 7376 7377/** 7378 * Struct encompassing a vendor extension config structure and a potential error status (in case 7379 * the structure is null). Used to iterate through vendor extensions. 7380 */ 7381struct VendorExtension { 7382 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *config; // structure does not own config 7383 status_t status; 7384 7385 // create based on an error status 7386 VendorExtension(status_t s_ = NO_INIT) : config(nullptr), status(s_) { } 7387 7388 // create based on a successfully retrieved config structure 7389 VendorExtension(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *c_) : config(c_), status(OK) { } 7390}; 7391 7392// class VendorExtensions; 7393/** 7394 * Forward iterator to enumerate vendor extensions supported by an OMX component. 7395 */ 7396class VendorExtensionIterator { 7397//private: 7398 static constexpr size_t kLastIndex = ~(size_t)0; // last index marker 7399 7400 sp<IOMXNode> mNode; // component 7401 size_t mIndex; // current android extension index 7402 std::unique_ptr<uint8_t[]> mBacking; // current extension's backing 7403 VendorExtension mCurrent; // current extension 7404 7405 VendorExtensionIterator(const sp<IOMXNode> &node, size_t index) 7406 : mNode(node), 7407 mIndex(index) { 7408 mCurrent = retrieve(); 7409 } 7410 7411 friend class VendorExtensions; 7412 7413public: 7414 // copy constructor 7415 VendorExtensionIterator(const VendorExtensionIterator &it) 7416 : VendorExtensionIterator(it.mNode, it.mIndex) { } 7417 7418 // retrieves the current extension pointed to by this iterator 7419 VendorExtension retrieve() { 7420 if (mIndex == kLastIndex) { 7421 return NO_INIT; 7422 } 7423 7424 // try with one param first, then retry if extension needs more than 1 param 7425 for (size_t paramSizeUsed = 1;; ) { 7426 if (paramSizeUsed > OMX_MAX_ANDROID_VENDOR_PARAMCOUNT) { 7427 return BAD_VALUE; // this prevents overflow in the following formula 7428 } 7429 7430 size_t size = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE) + 7431 (paramSizeUsed - 1) * sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE::param); 7432 mBacking.reset(new uint8_t[size]); 7433 if (!mBacking) { 7434 return NO_MEMORY; 7435 } 7436 7437 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *config = 7438 reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(mBacking.get()); 7439 7440 InitOMXParams(config); 7441 config->nSize = size; 7442 config->nIndex = mIndex; 7443 config->nParamSizeUsed = paramSizeUsed; 7444 status_t err = mNode->getConfig( 7445 (OMX_INDEXTYPE)OMX_IndexConfigAndroidVendorExtension, config, size); 7446 if (err == OK && config->nParamCount > paramSizeUsed && paramSizeUsed == 1) { 7447 // reallocate if we need a bigger config 7448 paramSizeUsed = config->nParamCount; 7449 continue; 7450 } else if (err == NOT_ENOUGH_DATA 7451 || (err != OK && mIndex == 0)) { 7452 // stop iterator on no-more signal, or if index is not at all supported 7453 mIndex = kLastIndex; 7454 return NO_INIT; 7455 } else if (err != OK) { 7456 return err; 7457 } else if (paramSizeUsed != config->nParamSizeUsed) { 7458 return BAD_VALUE; // component shall not modify size of nParam 7459 } 7460 7461 return config; 7462 } 7463 } 7464 7465 // returns extension pointed to by this iterator 7466 VendorExtension operator*() { 7467 return mCurrent; 7468 } 7469 7470 // prefix increment: move to next extension 7471 VendorExtensionIterator &operator++() { // prefix 7472 if (mIndex != kLastIndex) { 7473 ++mIndex; 7474 mCurrent = retrieve(); 7475 } 7476 return *this; 7477 } 7478 7479 // iterator equality operators 7480 bool operator==(const VendorExtensionIterator &o) { 7481 return mNode == o.mNode && mIndex == o.mIndex; 7482 } 7483 7484 bool operator!=(const VendorExtensionIterator &o) { 7485 return !(*this == o); 7486 } 7487}; 7488 7489/** 7490 * Iterable container for vendor extensions provided by a component 7491 */ 7492class VendorExtensions { 7493//private: 7494 sp<IOMXNode> mNode; 7495 7496public: 7497 VendorExtensions(const sp<IOMXNode> &node) 7498 : mNode(node) { 7499 } 7500 7501 VendorExtensionIterator begin() { 7502 return VendorExtensionIterator(mNode, 0); 7503 } 7504 7505 VendorExtensionIterator end() { 7506 return VendorExtensionIterator(mNode, VendorExtensionIterator::kLastIndex); 7507 } 7508}; 7509 7510status_t ACodec::setVendorParameters(const sp<AMessage> ¶ms) { 7511 std::map<std::string, std::string> vendorKeys; // maps reduced name to actual name 7512 constexpr char prefix[] = "vendor."; 7513 constexpr size_t prefixLength = sizeof(prefix) - 1; 7514 // longest possible vendor param name 7515 char reducedKey[OMX_MAX_STRINGNAME_SIZE + OMX_MAX_STRINGVALUE_SIZE]; 7516 7517 // identify all vendor keys to speed up search later and to detect vendor keys 7518 for (size_t i = params->countEntries(); i; --i) { 7519 AMessage::Type keyType; 7520 const char* key = params->getEntryNameAt(i - 1, &keyType); 7521 if (key != nullptr && !strncmp(key, prefix, prefixLength) 7522 // it is safe to limit format keys to the max vendor param size as we only 7523 // shorten parameter names by removing any trailing 'value' tags, and we 7524 // already remove the vendor prefix. 7525 && strlen(key + prefixLength) < sizeof(reducedKey) 7526 && (keyType == AMessage::kTypeInt32 7527 || keyType == AMessage::kTypeInt64 7528 || keyType == AMessage::kTypeString)) { 7529 strcpy(reducedKey, key + prefixLength); 7530 removeTrailingTags(reducedKey, 0, "value"); 7531 auto existingKey = vendorKeys.find(reducedKey); 7532 if (existingKey != vendorKeys.end()) { 7533 ALOGW("[%s] vendor parameter '%s' aliases parameter '%s'", 7534 mComponentName.c_str(), key, existingKey->second.c_str()); 7535 // ignore for now 7536 } 7537 vendorKeys.emplace(reducedKey, key); 7538 } 7539 } 7540 7541 // don't bother component if we don't have vendor extensions as they may not have implemented 7542 // the android vendor extension support, which will lead to unnecessary OMX failure logs. 7543 if (vendorKeys.empty()) { 7544 return OK; 7545 } 7546 7547 char key[sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE::cName) + 7548 sizeof(OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE::cKey)]; 7549 7550 status_t finalError = OK; 7551 7552 // don't try again if component does not have vendor extensions 7553 if (mVendorExtensionsStatus == kExtensionsNone) { 7554 return OK; 7555 } 7556 7557 for (VendorExtension ext : VendorExtensions(mOMXNode)) { 7558 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *config = ext.config; 7559 if (config == nullptr) { 7560 return ext.status; 7561 } 7562 7563 mVendorExtensionsStatus = kExtensionsExist; 7564 7565 config->cName[sizeof(config->cName) - 1] = '\0'; // null-terminate name 7566 strcpy(key, (const char *)config->cName); 7567 size_t nameLength = strlen(key); 7568 key[nameLength] = '.'; 7569 7570 // don't set vendor extension if client has not provided any of its parameters 7571 // or if client simply unsets parameters that are already unset 7572 bool needToSet = false; 7573 for (size_t paramIndex = 0; paramIndex < config->nParamCount; ++paramIndex) { 7574 // null-terminate param key 7575 config->param[paramIndex].cKey[sizeof(config->param[0].cKey) - 1] = '\0'; 7576 strcpy(key + nameLength + 1, (const char *)config->param[paramIndex].cKey); 7577 removeTrailingTags(key, nameLength, "value"); 7578 auto existingKey = vendorKeys.find(key); 7579 7580 // don't touch (e.g. change) parameters that are not specified by client 7581 if (existingKey == vendorKeys.end()) { 7582 continue; 7583 } 7584 7585 bool wasSet = config->param[paramIndex].bSet; 7586 switch (config->param[paramIndex].eValueType) { 7587 case OMX_AndroidVendorValueInt32: 7588 { 7589 int32_t value; 7590 config->param[paramIndex].bSet = 7591 (OMX_BOOL)params->findInt32(existingKey->second.c_str(), &value); 7592 if (config->param[paramIndex].bSet) { 7593 config->param[paramIndex].nInt32 = value; 7594 } 7595 break; 7596 } 7597 case OMX_AndroidVendorValueInt64: 7598 { 7599 int64_t value; 7600 config->param[paramIndex].bSet = 7601 (OMX_BOOL)params->findAsInt64(existingKey->second.c_str(), &value); 7602 if (config->param[paramIndex].bSet) { 7603 config->param[paramIndex].nInt64 = value; 7604 } 7605 break; 7606 } 7607 case OMX_AndroidVendorValueString: 7608 { 7609 AString value; 7610 config->param[paramIndex].bSet = 7611 (OMX_BOOL)params->findString(existingKey->second.c_str(), &value); 7612 if (config->param[paramIndex].bSet) { 7613 strncpy((char *)config->param[paramIndex].cString, value.c_str(), 7614 sizeof(OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE::cString)); 7615 } 7616 break; 7617 } 7618 default: 7619 ALOGW("[%s] vendor parameter '%s' is not a supported value", 7620 mComponentName.c_str(), key); 7621 continue; 7622 } 7623 if (config->param[paramIndex].bSet || wasSet) { 7624 needToSet = true; 7625 } 7626 } 7627 7628 if (needToSet) { 7629 status_t err = mOMXNode->setConfig( 7630 (OMX_INDEXTYPE)OMX_IndexConfigAndroidVendorExtension, 7631 config, config->nSize); 7632 if (err != OK) { 7633 key[nameLength] = '\0'; 7634 ALOGW("[%s] failed to set vendor extension '%s'", mComponentName.c_str(), key); 7635 // try to set each extension, and return first failure 7636 if (finalError == OK) { 7637 finalError = err; 7638 } 7639 } 7640 } 7641 } 7642 7643 if (mVendorExtensionsStatus == kExtensionsUnchecked) { 7644 mVendorExtensionsStatus = kExtensionsNone; 7645 } 7646 7647 return finalError; 7648} 7649 7650status_t ACodec::getVendorParameters(OMX_U32 portIndex, sp<AMessage> &format) { 7651 constexpr char prefix[] = "vendor."; 7652 constexpr size_t prefixLength = sizeof(prefix) - 1; 7653 char key[sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE::cName) + 7654 sizeof(OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE::cKey) + prefixLength]; 7655 strcpy(key, prefix); 7656 7657 // don't try again if component does not have vendor extensions 7658 if (mVendorExtensionsStatus == kExtensionsNone) { 7659 return OK; 7660 } 7661 7662 for (VendorExtension ext : VendorExtensions(mOMXNode)) { 7663 OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *config = ext.config; 7664 if (config == nullptr) { 7665 return ext.status; 7666 } 7667 7668 mVendorExtensionsStatus = kExtensionsExist; 7669 7670 if (config->eDir != (portIndex == kPortIndexInput ? OMX_DirInput : OMX_DirOutput)) { 7671 continue; 7672 } 7673 7674 config->cName[sizeof(config->cName) - 1] = '\0'; // null-terminate name 7675 strcpy(key + prefixLength, (const char *)config->cName); 7676 size_t nameLength = strlen(key); 7677 key[nameLength] = '.'; 7678 7679 for (size_t paramIndex = 0; paramIndex < config->nParamCount; ++paramIndex) { 7680 // null-terminate param key 7681 config->param[paramIndex].cKey[sizeof(config->param[0].cKey) - 1] = '\0'; 7682 strcpy(key + nameLength + 1, (const char *)config->param[paramIndex].cKey); 7683 removeTrailingTags(key, nameLength, "value"); 7684 if (config->param[paramIndex].bSet) { 7685 switch (config->param[paramIndex].eValueType) { 7686 case OMX_AndroidVendorValueInt32: 7687 { 7688 format->setInt32(key, config->param[paramIndex].nInt32); 7689 break; 7690 } 7691 case OMX_AndroidVendorValueInt64: 7692 { 7693 format->setInt64(key, config->param[paramIndex].nInt64); 7694 break; 7695 } 7696 case OMX_AndroidVendorValueString: 7697 { 7698 config->param[paramIndex].cString[OMX_MAX_STRINGVALUE_SIZE - 1] = '\0'; 7699 format->setString(key, (const char *)config->param[paramIndex].cString); 7700 break; 7701 } 7702 default: 7703 ALOGW("vendor parameter %s is not a supported value", key); 7704 continue; 7705 } 7706 } 7707 } 7708 } 7709 7710 if (mVendorExtensionsStatus == kExtensionsUnchecked) { 7711 mVendorExtensionsStatus = kExtensionsNone; 7712 } 7713 7714 return OK; 7715} 7716 7717void ACodec::onSignalEndOfInputStream() { 7718 status_t err = INVALID_OPERATION; 7719 if (mGraphicBufferSource != NULL) { 7720 err = statusFromBinderStatus(mGraphicBufferSource->signalEndOfInputStream()); 7721 } 7722 mCallback->onSignaledInputEOS(err); 7723} 7724 7725void ACodec::forceStateTransition(int generation) { 7726 if (generation != mStateGeneration) { 7727 ALOGV("Ignoring stale force state transition message: #%d (now #%d)", 7728 generation, mStateGeneration); 7729 return; 7730 } 7731 ALOGE("State machine stuck"); 7732 // Error must have already been signalled to the client. 7733 7734 // Deferred messages will be handled at LoadedState at the end of the 7735 // transition. 7736 mShutdownInProgress = true; 7737 // No shutdown complete callback at the end of the transition. 7738 mExplicitShutdown = false; 7739 mKeepComponentAllocated = true; 7740 7741 status_t err = mOMXNode->sendCommand(OMX_CommandStateSet, OMX_StateIdle); 7742 if (err != OK) { 7743 // TODO: do some recovery here. 7744 } else { 7745 changeState(mExecutingToIdleState); 7746 } 7747} 7748 7749bool ACodec::ExecutingState::onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) { 7750 mCodec->onFrameRendered(mediaTimeUs, systemNano); 7751 return true; 7752} 7753 7754bool ACodec::ExecutingState::onOMXEvent( 7755 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 7756 switch (event) { 7757 case OMX_EventPortSettingsChanged: 7758 { 7759 CHECK_EQ(data1, (OMX_U32)kPortIndexOutput); 7760 7761 mCodec->onOutputFormatChanged(); 7762 7763 if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) { 7764 mCodec->mMetadataBuffersToSubmit = 0; 7765 CHECK_EQ(mCodec->mOMXNode->sendCommand( 7766 OMX_CommandPortDisable, kPortIndexOutput), 7767 (status_t)OK); 7768 7769 mCodec->freeOutputBuffersNotOwnedByComponent(); 7770 7771 mCodec->changeState(mCodec->mOutputPortSettingsChangedState); 7772 } else if (data2 != OMX_IndexConfigCommonOutputCrop 7773 && data2 != OMX_IndexConfigAndroidIntraRefresh) { 7774 ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08x", 7775 mCodec->mComponentName.c_str(), data2); 7776 } 7777 7778 return true; 7779 } 7780 7781 case OMX_EventBufferFlag: 7782 { 7783 return true; 7784 } 7785 7786 default: 7787 return BaseState::onOMXEvent(event, data1, data2); 7788 } 7789} 7790 7791//////////////////////////////////////////////////////////////////////////////// 7792 7793ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState( 7794 ACodec *codec) 7795 : BaseState(codec) { 7796} 7797 7798ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode( 7799 OMX_U32 portIndex) { 7800 if (portIndex == kPortIndexOutput) { 7801 return FREE_BUFFERS; 7802 } 7803 7804 CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput); 7805 7806 return RESUBMIT_BUFFERS; 7807} 7808 7809bool ACodec::OutputPortSettingsChangedState::onMessageReceived( 7810 const sp<AMessage> &msg) { 7811 bool handled = false; 7812 7813 switch (msg->what()) { 7814 case kWhatFlush: 7815 case kWhatShutdown: { 7816 if (mCodec->mFatalError) { 7817 sp<AMessage> msg = new AMessage(ACodec::kWhatForceStateTransition, mCodec); 7818 msg->setInt32("generation", mCodec->mStateGeneration); 7819 msg->post(3000000); 7820 } 7821 // fall-through 7822 } 7823 case kWhatResume: 7824 case kWhatSetParameters: 7825 { 7826 if (msg->what() == kWhatResume) { 7827 ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str()); 7828 } 7829 7830 mCodec->deferMessage(msg); 7831 handled = true; 7832 break; 7833 } 7834 7835 case kWhatForceStateTransition: 7836 { 7837 int32_t generation = 0; 7838 CHECK(msg->findInt32("generation", &generation)); 7839 mCodec->forceStateTransition(generation); 7840 7841 handled = true; 7842 break; 7843 } 7844 7845 default: 7846 handled = BaseState::onMessageReceived(msg); 7847 break; 7848 } 7849 7850 return handled; 7851} 7852 7853void ACodec::OutputPortSettingsChangedState::stateEntered() { 7854 ALOGV("[%s] Now handling output port settings change", 7855 mCodec->mComponentName.c_str()); 7856} 7857 7858bool ACodec::OutputPortSettingsChangedState::onOMXFrameRendered( 7859 int64_t mediaTimeUs, nsecs_t systemNano) { 7860 mCodec->onFrameRendered(mediaTimeUs, systemNano); 7861 return true; 7862} 7863 7864bool ACodec::OutputPortSettingsChangedState::onOMXEvent( 7865 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 7866 switch (event) { 7867 case OMX_EventCmdComplete: 7868 { 7869 if (data1 == (OMX_U32)OMX_CommandPortDisable) { 7870 if (data2 != (OMX_U32)kPortIndexOutput) { 7871 ALOGW("ignoring EventCmdComplete CommandPortDisable for port %u", data2); 7872 return false; 7873 } 7874 7875 ALOGV("[%s] Output port now disabled.", mCodec->mComponentName.c_str()); 7876 7877 status_t err = OK; 7878 if (!mCodec->mBuffers[kPortIndexOutput].isEmpty()) { 7879 ALOGE("disabled port should be empty, but has %zu buffers", 7880 mCodec->mBuffers[kPortIndexOutput].size()); 7881 err = FAILED_TRANSACTION; 7882 } else { 7883 mCodec->mAllocator[kPortIndexOutput].clear(); 7884 } 7885 7886 if (err == OK) { 7887 err = mCodec->mOMXNode->sendCommand( 7888 OMX_CommandPortEnable, kPortIndexOutput); 7889 } 7890 7891 if (err == OK) { 7892 err = mCodec->allocateBuffersOnPort(kPortIndexOutput); 7893 ALOGE_IF(err != OK, "Failed to allocate output port buffers after port " 7894 "reconfiguration: (%d)", err); 7895 mCodec->mCallback->onOutputBuffersChanged(); 7896 } 7897 7898 if (err != OK) { 7899 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 7900 ALOGE("Error occurred while disabling the output port"); 7901 } 7902 7903 return true; 7904 } else if (data1 == (OMX_U32)OMX_CommandPortEnable) { 7905 if (data2 != (OMX_U32)kPortIndexOutput) { 7906 ALOGW("ignoring EventCmdComplete OMX_CommandPortEnable for port %u", data2); 7907 return false; 7908 } 7909 7910 ALOGV("[%s] Output port now reenabled.", mCodec->mComponentName.c_str()); 7911 7912 if (mCodec->mExecutingState->active()) { 7913 mCodec->mExecutingState->submitOutputBuffers(); 7914 } 7915 7916 mCodec->changeState(mCodec->mExecutingState); 7917 7918 return true; 7919 } 7920 7921 return false; 7922 } 7923 7924 default: 7925 return BaseState::onOMXEvent(event, data1, data2); 7926 } 7927} 7928 7929//////////////////////////////////////////////////////////////////////////////// 7930 7931ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec) 7932 : BaseState(codec), 7933 mComponentNowIdle(false) { 7934} 7935 7936bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) { 7937 bool handled = false; 7938 7939 switch (msg->what()) { 7940 case kWhatFlush: 7941 { 7942 // Don't send me a flush request if you previously wanted me 7943 // to shutdown. 7944 ALOGW("Ignoring flush request in ExecutingToIdleState"); 7945 break; 7946 } 7947 7948 case kWhatShutdown: 7949 { 7950 mCodec->deferMessage(msg); 7951 handled = true; 7952 break; 7953 } 7954 7955 default: 7956 handled = BaseState::onMessageReceived(msg); 7957 break; 7958 } 7959 7960 return handled; 7961} 7962 7963void ACodec::ExecutingToIdleState::stateEntered() { 7964 ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str()); 7965 7966 mComponentNowIdle = false; 7967 mCodec->mLastOutputFormat.clear(); 7968} 7969 7970bool ACodec::ExecutingToIdleState::onOMXEvent( 7971 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 7972 switch (event) { 7973 case OMX_EventCmdComplete: 7974 { 7975 if (data1 != (OMX_U32)OMX_CommandStateSet 7976 || data2 != (OMX_U32)OMX_StateIdle) { 7977 ALOGE("Unexpected command completion in ExecutingToIdleState: %s(%u) %s(%u)", 7978 asString((OMX_COMMANDTYPE)data1), data1, 7979 asString((OMX_STATETYPE)data2), data2); 7980 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 7981 return true; 7982 } 7983 7984 mComponentNowIdle = true; 7985 7986 changeStateIfWeOwnAllBuffers(); 7987 7988 return true; 7989 } 7990 7991 case OMX_EventPortSettingsChanged: 7992 case OMX_EventBufferFlag: 7993 { 7994 // We're shutting down and don't care about this anymore. 7995 return true; 7996 } 7997 7998 default: 7999 return BaseState::onOMXEvent(event, data1, data2); 8000 } 8001} 8002 8003void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() { 8004 if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) { 8005 status_t err = mCodec->mOMXNode->sendCommand( 8006 OMX_CommandStateSet, OMX_StateLoaded); 8007 if (err == OK) { 8008 err = mCodec->freeBuffersOnPort(kPortIndexInput); 8009 status_t err2 = mCodec->freeBuffersOnPort(kPortIndexOutput); 8010 if (err == OK) { 8011 err = err2; 8012 } 8013 } 8014 8015 if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown) 8016 && mCodec->mNativeWindow != NULL) { 8017 // We push enough 1x1 blank buffers to ensure that one of 8018 // them has made it to the display. This allows the OMX 8019 // component teardown to zero out any protected buffers 8020 // without the risk of scanning out one of those buffers. 8021 pushBlankBuffersToNativeWindow(mCodec->mNativeWindow.get()); 8022 } 8023 8024 if (err != OK) { 8025 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 8026 return; 8027 } 8028 8029 mCodec->changeState(mCodec->mIdleToLoadedState); 8030 } 8031} 8032 8033void ACodec::ExecutingToIdleState::onInputBufferFilled( 8034 const sp<AMessage> &msg) { 8035 BaseState::onInputBufferFilled(msg); 8036 8037 changeStateIfWeOwnAllBuffers(); 8038} 8039 8040void ACodec::ExecutingToIdleState::onOutputBufferDrained( 8041 const sp<AMessage> &msg) { 8042 BaseState::onOutputBufferDrained(msg); 8043 8044 changeStateIfWeOwnAllBuffers(); 8045} 8046 8047//////////////////////////////////////////////////////////////////////////////// 8048 8049ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec) 8050 : BaseState(codec) { 8051} 8052 8053bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) { 8054 bool handled = false; 8055 8056 switch (msg->what()) { 8057 case kWhatShutdown: 8058 { 8059 mCodec->deferMessage(msg); 8060 handled = true; 8061 break; 8062 } 8063 8064 case kWhatFlush: 8065 { 8066 // Don't send me a flush request if you previously wanted me 8067 // to shutdown. 8068 ALOGE("Got flush request in IdleToLoadedState"); 8069 break; 8070 } 8071 8072 default: 8073 handled = BaseState::onMessageReceived(msg); 8074 break; 8075 } 8076 8077 return handled; 8078} 8079 8080void ACodec::IdleToLoadedState::stateEntered() { 8081 ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str()); 8082} 8083 8084bool ACodec::IdleToLoadedState::onOMXEvent( 8085 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 8086 switch (event) { 8087 case OMX_EventCmdComplete: 8088 { 8089 if (data1 != (OMX_U32)OMX_CommandStateSet 8090 || data2 != (OMX_U32)OMX_StateLoaded) { 8091 ALOGE("Unexpected command completion in IdleToLoadedState: %s(%u) %s(%u)", 8092 asString((OMX_COMMANDTYPE)data1), data1, 8093 asString((OMX_STATETYPE)data2), data2); 8094 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 8095 return true; 8096 } 8097 8098 mCodec->changeState(mCodec->mLoadedState); 8099 8100 return true; 8101 } 8102 8103 default: 8104 return BaseState::onOMXEvent(event, data1, data2); 8105 } 8106} 8107 8108//////////////////////////////////////////////////////////////////////////////// 8109 8110ACodec::FlushingState::FlushingState(ACodec *codec) 8111 : BaseState(codec) { 8112} 8113 8114void ACodec::FlushingState::stateEntered() { 8115 ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str()); 8116 8117 mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false; 8118} 8119 8120bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) { 8121 bool handled = false; 8122 8123 switch (msg->what()) { 8124 case kWhatShutdown: 8125 { 8126 mCodec->deferMessage(msg); 8127 if (mCodec->mFatalError) { 8128 sp<AMessage> msg = new AMessage(ACodec::kWhatForceStateTransition, mCodec); 8129 msg->setInt32("generation", mCodec->mStateGeneration); 8130 msg->post(3000000); 8131 } 8132 break; 8133 } 8134 8135 case kWhatFlush: 8136 { 8137 // We're already doing this right now. 8138 handled = true; 8139 break; 8140 } 8141 8142 case kWhatForceStateTransition: 8143 { 8144 int32_t generation = 0; 8145 CHECK(msg->findInt32("generation", &generation)); 8146 mCodec->forceStateTransition(generation); 8147 8148 handled = true; 8149 break; 8150 } 8151 8152 default: 8153 handled = BaseState::onMessageReceived(msg); 8154 break; 8155 } 8156 8157 return handled; 8158} 8159 8160bool ACodec::FlushingState::onOMXEvent( 8161 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 8162 ALOGV("[%s] FlushingState onOMXEvent(%u,%d)", 8163 mCodec->mComponentName.c_str(), event, (OMX_S32)data1); 8164 8165 switch (event) { 8166 case OMX_EventCmdComplete: 8167 { 8168 if (data1 != (OMX_U32)OMX_CommandFlush) { 8169 ALOGE("unexpected EventCmdComplete %s(%d) data2:%d in FlushingState", 8170 asString((OMX_COMMANDTYPE)data1), data1, data2); 8171 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 8172 return true; 8173 } 8174 8175 if (data2 == kPortIndexInput || data2 == kPortIndexOutput) { 8176 if (mFlushComplete[data2]) { 8177 ALOGW("Flush already completed for %s port", 8178 data2 == kPortIndexInput ? "input" : "output"); 8179 return true; 8180 } 8181 mFlushComplete[data2] = true; 8182 8183 if (mFlushComplete[kPortIndexInput] && mFlushComplete[kPortIndexOutput]) { 8184 changeStateIfWeOwnAllBuffers(); 8185 } 8186 } else if (data2 == OMX_ALL) { 8187 if (!mFlushComplete[kPortIndexInput] || !mFlushComplete[kPortIndexOutput]) { 8188 ALOGW("received flush complete event for OMX_ALL before ports have been" 8189 "flushed (%d/%d)", 8190 mFlushComplete[kPortIndexInput], mFlushComplete[kPortIndexOutput]); 8191 return false; 8192 } 8193 8194 changeStateIfWeOwnAllBuffers(); 8195 } else { 8196 ALOGW("data2 not OMX_ALL but %u in EventCmdComplete CommandFlush", data2); 8197 } 8198 8199 return true; 8200 } 8201 8202 case OMX_EventPortSettingsChanged: 8203 { 8204 sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec); 8205 msg->setInt32("type", omx_message::EVENT); 8206 msg->setInt32("generation", mCodec->mNodeGeneration); 8207 msg->setInt32("event", event); 8208 msg->setInt32("data1", data1); 8209 msg->setInt32("data2", data2); 8210 8211 ALOGV("[%s] Deferring OMX_EventPortSettingsChanged", 8212 mCodec->mComponentName.c_str()); 8213 8214 mCodec->deferMessage(msg); 8215 8216 return true; 8217 } 8218 8219 default: 8220 return BaseState::onOMXEvent(event, data1, data2); 8221 } 8222 8223 return true; 8224} 8225 8226void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) { 8227 BaseState::onOutputBufferDrained(msg); 8228 8229 changeStateIfWeOwnAllBuffers(); 8230} 8231 8232void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) { 8233 BaseState::onInputBufferFilled(msg); 8234 8235 changeStateIfWeOwnAllBuffers(); 8236} 8237 8238void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() { 8239 if (mFlushComplete[kPortIndexInput] 8240 && mFlushComplete[kPortIndexOutput] 8241 && mCodec->allYourBuffersAreBelongToUs()) { 8242 // We now own all buffers except possibly those still queued with 8243 // the native window for rendering. Let's get those back as well. 8244 mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs(); 8245 8246 mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC)); 8247 8248 mCodec->mCallback->onFlushCompleted(); 8249 8250 mCodec->mPortEOS[kPortIndexInput] = 8251 mCodec->mPortEOS[kPortIndexOutput] = false; 8252 8253 mCodec->mInputEOSResult = OK; 8254 8255 if (mCodec->mSkipCutBuffer != NULL) { 8256 mCodec->mSkipCutBuffer->clear(); 8257 } 8258 8259 mCodec->changeState(mCodec->mExecutingState); 8260 } 8261} 8262 8263status_t ACodec::queryCapabilities( 8264 const char* owner, const char* name, const char* mime, bool isEncoder, 8265 MediaCodecInfo::CapabilitiesWriter* caps) { 8266 const char *role = GetComponentRole(isEncoder, mime); 8267 if (role == NULL) { 8268 return BAD_VALUE; 8269 } 8270 8271 OMXClient client; 8272 status_t err = client.connect(owner); 8273 if (err != OK) { 8274 return err; 8275 } 8276 8277 sp<IOMX> omx = client.interface(); 8278 sp<CodecObserver> observer = new CodecObserver; 8279 sp<IOMXNode> omxNode; 8280 8281 err = omx->allocateNode(name, observer, &omxNode); 8282 if (err != OK) { 8283 client.disconnect(); 8284 return err; 8285 } 8286 8287 err = SetComponentRole(omxNode, role); 8288 if (err != OK) { 8289 omxNode->freeNode(); 8290 client.disconnect(); 8291 return err; 8292 } 8293 8294 bool isVideo = strncasecmp(mime, "video/", 6) == 0; 8295 bool isImage = strncasecmp(mime, "image/", 6) == 0; 8296 8297 if (isVideo || isImage) { 8298 OMX_VIDEO_PARAM_PROFILELEVELTYPE param; 8299 InitOMXParams(¶m); 8300 param.nPortIndex = isEncoder ? kPortIndexOutput : kPortIndexInput; 8301 8302 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { 8303 param.nProfileIndex = index; 8304 status_t err = omxNode->getParameter( 8305 OMX_IndexParamVideoProfileLevelQuerySupported, 8306 ¶m, sizeof(param)); 8307 if (err != OK) { 8308 break; 8309 } 8310 caps->addProfileLevel(param.eProfile, param.eLevel); 8311 8312 // AVC components may not list the constrained profiles explicitly, but 8313 // decoders that support a profile also support its constrained version. 8314 // Encoders must explicitly support constrained profiles. 8315 if (!isEncoder && strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC) == 0) { 8316 if (param.eProfile == OMX_VIDEO_AVCProfileHigh) { 8317 caps->addProfileLevel(OMX_VIDEO_AVCProfileConstrainedHigh, param.eLevel); 8318 } else if (param.eProfile == OMX_VIDEO_AVCProfileBaseline) { 8319 caps->addProfileLevel(OMX_VIDEO_AVCProfileConstrainedBaseline, param.eLevel); 8320 } 8321 } 8322 8323 if (index == kMaxIndicesToCheck) { 8324 ALOGW("[%s] stopping checking profiles after %u: %x/%x", 8325 name, index, 8326 param.eProfile, param.eLevel); 8327 } 8328 } 8329 8330 // Color format query 8331 // return colors in the order reported by the OMX component 8332 // prefix "flexible" standard ones with the flexible equivalent 8333 OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat; 8334 InitOMXParams(&portFormat); 8335 portFormat.nPortIndex = isEncoder ? kPortIndexInput : kPortIndexOutput; 8336 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { 8337 portFormat.nIndex = index; 8338 status_t err = omxNode->getParameter( 8339 OMX_IndexParamVideoPortFormat, 8340 &portFormat, sizeof(portFormat)); 8341 if (err != OK) { 8342 break; 8343 } 8344 8345 OMX_U32 flexibleEquivalent; 8346 if (IsFlexibleColorFormat( 8347 omxNode, portFormat.eColorFormat, false /* usingNativeWindow */, 8348 &flexibleEquivalent)) { 8349 caps->addColorFormat(flexibleEquivalent); 8350 } 8351 caps->addColorFormat(portFormat.eColorFormat); 8352 8353 if (index == kMaxIndicesToCheck) { 8354 ALOGW("[%s] stopping checking formats after %u: %s(%x)", 8355 name, index, 8356 asString(portFormat.eColorFormat), portFormat.eColorFormat); 8357 } 8358 } 8359 } else if (strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC) == 0) { 8360 // More audio codecs if they have profiles. 8361 OMX_AUDIO_PARAM_ANDROID_PROFILETYPE param; 8362 InitOMXParams(¶m); 8363 param.nPortIndex = isEncoder ? kPortIndexOutput : kPortIndexInput; 8364 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { 8365 param.nProfileIndex = index; 8366 status_t err = omxNode->getParameter( 8367 (OMX_INDEXTYPE)OMX_IndexParamAudioProfileQuerySupported, 8368 ¶m, sizeof(param)); 8369 if (err != OK) { 8370 break; 8371 } 8372 // For audio, level is ignored. 8373 caps->addProfileLevel(param.eProfile, 0 /* level */); 8374 8375 if (index == kMaxIndicesToCheck) { 8376 ALOGW("[%s] stopping checking profiles after %u: %x", 8377 name, index, 8378 param.eProfile); 8379 } 8380 } 8381 8382 // NOTE: Without Android extensions, OMX does not provide a way to query 8383 // AAC profile support 8384 if (param.nProfileIndex == 0) { 8385 ALOGW("component %s doesn't support profile query.", name); 8386 } 8387 } 8388 8389 if (isVideo && !isEncoder) { 8390 native_handle_t *sidebandHandle = NULL; 8391 if (omxNode->configureVideoTunnelMode( 8392 kPortIndexOutput, OMX_TRUE, 0, &sidebandHandle) == OK) { 8393 // tunneled playback includes adaptive playback 8394 caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback 8395 | MediaCodecInfo::Capabilities::kFlagSupportsTunneledPlayback); 8396 } else if (omxNode->setPortMode( 8397 kPortIndexOutput, IOMX::kPortModeDynamicANWBuffer) == OK || 8398 omxNode->prepareForAdaptivePlayback( 8399 kPortIndexOutput, OMX_TRUE, 8400 1280 /* width */, 720 /* height */) == OK) { 8401 caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback); 8402 } 8403 } 8404 8405 if (isVideo && isEncoder) { 8406 OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params; 8407 InitOMXParams(¶ms); 8408 params.nPortIndex = kPortIndexOutput; 8409 // TODO: should we verify if fallback is supported? 8410 if (omxNode->getConfig( 8411 (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, 8412 ¶ms, sizeof(params)) == OK) { 8413 caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsIntraRefresh); 8414 } 8415 } 8416 8417 omxNode->freeNode(); 8418 client.disconnect(); 8419 return OK; 8420} 8421 8422// These are supposed be equivalent to the logic in 8423// "audio_channel_out_mask_from_count". 8424//static 8425status_t ACodec::getOMXChannelMapping(size_t numChannels, OMX_AUDIO_CHANNELTYPE map[]) { 8426 switch (numChannels) { 8427 case 1: 8428 map[0] = OMX_AUDIO_ChannelCF; 8429 break; 8430 case 2: 8431 map[0] = OMX_AUDIO_ChannelLF; 8432 map[1] = OMX_AUDIO_ChannelRF; 8433 break; 8434 case 3: 8435 map[0] = OMX_AUDIO_ChannelLF; 8436 map[1] = OMX_AUDIO_ChannelRF; 8437 map[2] = OMX_AUDIO_ChannelCF; 8438 break; 8439 case 4: 8440 map[0] = OMX_AUDIO_ChannelLF; 8441 map[1] = OMX_AUDIO_ChannelRF; 8442 map[2] = OMX_AUDIO_ChannelLR; 8443 map[3] = OMX_AUDIO_ChannelRR; 8444 break; 8445 case 5: 8446 map[0] = OMX_AUDIO_ChannelLF; 8447 map[1] = OMX_AUDIO_ChannelRF; 8448 map[2] = OMX_AUDIO_ChannelCF; 8449 map[3] = OMX_AUDIO_ChannelLR; 8450 map[4] = OMX_AUDIO_ChannelRR; 8451 break; 8452 case 6: 8453 map[0] = OMX_AUDIO_ChannelLF; 8454 map[1] = OMX_AUDIO_ChannelRF; 8455 map[2] = OMX_AUDIO_ChannelCF; 8456 map[3] = OMX_AUDIO_ChannelLFE; 8457 map[4] = OMX_AUDIO_ChannelLR; 8458 map[5] = OMX_AUDIO_ChannelRR; 8459 break; 8460 case 7: 8461 map[0] = OMX_AUDIO_ChannelLF; 8462 map[1] = OMX_AUDIO_ChannelRF; 8463 map[2] = OMX_AUDIO_ChannelCF; 8464 map[3] = OMX_AUDIO_ChannelLFE; 8465 map[4] = OMX_AUDIO_ChannelLR; 8466 map[5] = OMX_AUDIO_ChannelRR; 8467 map[6] = OMX_AUDIO_ChannelCS; 8468 break; 8469 case 8: 8470 map[0] = OMX_AUDIO_ChannelLF; 8471 map[1] = OMX_AUDIO_ChannelRF; 8472 map[2] = OMX_AUDIO_ChannelCF; 8473 map[3] = OMX_AUDIO_ChannelLFE; 8474 map[4] = OMX_AUDIO_ChannelLR; 8475 map[5] = OMX_AUDIO_ChannelRR; 8476 map[6] = OMX_AUDIO_ChannelLS; 8477 map[7] = OMX_AUDIO_ChannelRS; 8478 break; 8479 default: 8480 return -EINVAL; 8481 } 8482 8483 return OK; 8484} 8485 8486} // namespace android 8487