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