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