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