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