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