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