ACodec.cpp revision b0a4b9e917bd26bf366fb20c48315f51285c18f9
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 sp<IGraphicBufferProducer> bufferProducer; 6128 status_t err = mCodec->mOMX->createInputSurface( 6129 mCodec->mNode, kPortIndexInput, &bufferProducer, &mCodec->mInputMetadataType); 6130 6131 if (err == OK) { 6132 err = setupInputSurface(); 6133 } 6134 6135 if (err == OK) { 6136 notify->setObject("input-surface", 6137 new BufferProducerWrapper(bufferProducer)); 6138 } else { 6139 // Can't use mCodec->signalError() here -- MediaCodec won't forward 6140 // the error through because it's in the "configured" state. We 6141 // send a kWhatInputSurfaceCreated with an error value instead. 6142 ALOGE("[%s] onCreateInputSurface returning error %d", 6143 mCodec->mComponentName.c_str(), err); 6144 notify->setInt32("err", err); 6145 } 6146 notify->post(); 6147} 6148 6149void ACodec::LoadedState::onSetInputSurface( 6150 const sp<AMessage> &msg) { 6151 ALOGV("onSetInputSurface"); 6152 6153 sp<AMessage> notify = mCodec->mNotify->dup(); 6154 notify->setInt32("what", CodecBase::kWhatInputSurfaceAccepted); 6155 6156 sp<RefBase> obj; 6157 CHECK(msg->findObject("input-surface", &obj)); 6158 sp<PersistentSurface> surface = static_cast<PersistentSurface *>(obj.get()); 6159 6160 status_t err = mCodec->mOMX->setInputSurface( 6161 mCodec->mNode, kPortIndexInput, surface->getBufferConsumer(), 6162 &mCodec->mInputMetadataType); 6163 6164 if (err == OK) { 6165 err = setupInputSurface(); 6166 } 6167 6168 if (err != OK) { 6169 // Can't use mCodec->signalError() here -- MediaCodec won't forward 6170 // the error through because it's in the "configured" state. We 6171 // send a kWhatInputSurfaceAccepted with an error value instead. 6172 ALOGE("[%s] onSetInputSurface returning error %d", 6173 mCodec->mComponentName.c_str(), err); 6174 notify->setInt32("err", err); 6175 } 6176 notify->post(); 6177} 6178 6179void ACodec::LoadedState::onStart() { 6180 ALOGV("onStart"); 6181 6182 status_t err = mCodec->mOMX->sendCommand(mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle); 6183 if (err != OK) { 6184 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6185 } else { 6186 mCodec->changeState(mCodec->mLoadedToIdleState); 6187 } 6188} 6189 6190//////////////////////////////////////////////////////////////////////////////// 6191 6192ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec) 6193 : BaseState(codec) { 6194} 6195 6196void ACodec::LoadedToIdleState::stateEntered() { 6197 ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str()); 6198 6199 status_t err; 6200 if ((err = allocateBuffers()) != OK) { 6201 ALOGE("Failed to allocate buffers after transitioning to IDLE state " 6202 "(error 0x%08x)", 6203 err); 6204 6205 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6206 6207 mCodec->mOMX->sendCommand( 6208 mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded); 6209 if (mCodec->allYourBuffersAreBelongToUs(kPortIndexInput)) { 6210 mCodec->freeBuffersOnPort(kPortIndexInput); 6211 } 6212 if (mCodec->allYourBuffersAreBelongToUs(kPortIndexOutput)) { 6213 mCodec->freeBuffersOnPort(kPortIndexOutput); 6214 } 6215 6216 mCodec->changeState(mCodec->mLoadedState); 6217 } 6218} 6219 6220status_t ACodec::LoadedToIdleState::allocateBuffers() { 6221 status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput); 6222 6223 if (err != OK) { 6224 return err; 6225 } 6226 6227 return mCodec->allocateBuffersOnPort(kPortIndexOutput); 6228} 6229 6230bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) { 6231 switch (msg->what()) { 6232 case kWhatSetParameters: 6233 case kWhatShutdown: 6234 { 6235 mCodec->deferMessage(msg); 6236 return true; 6237 } 6238 6239 case kWhatSignalEndOfInputStream: 6240 { 6241 mCodec->onSignalEndOfInputStream(); 6242 return true; 6243 } 6244 6245 case kWhatResume: 6246 { 6247 // We'll be active soon enough. 6248 return true; 6249 } 6250 6251 case kWhatFlush: 6252 { 6253 // We haven't even started yet, so we're flushed alright... 6254 sp<AMessage> notify = mCodec->mNotify->dup(); 6255 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 6256 notify->post(); 6257 return true; 6258 } 6259 6260 default: 6261 return BaseState::onMessageReceived(msg); 6262 } 6263} 6264 6265bool ACodec::LoadedToIdleState::onOMXEvent( 6266 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 6267 switch (event) { 6268 case OMX_EventCmdComplete: 6269 { 6270 status_t err = OK; 6271 if (data1 != (OMX_U32)OMX_CommandStateSet 6272 || data2 != (OMX_U32)OMX_StateIdle) { 6273 ALOGE("Unexpected command completion in LoadedToIdleState: %s(%u) %s(%u)", 6274 asString((OMX_COMMANDTYPE)data1), data1, 6275 asString((OMX_STATETYPE)data2), data2); 6276 err = FAILED_TRANSACTION; 6277 } 6278 6279 if (err == OK) { 6280 err = mCodec->mOMX->sendCommand( 6281 mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting); 6282 } 6283 6284 if (err != OK) { 6285 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6286 } else { 6287 mCodec->changeState(mCodec->mIdleToExecutingState); 6288 } 6289 6290 return true; 6291 } 6292 6293 default: 6294 return BaseState::onOMXEvent(event, data1, data2); 6295 } 6296} 6297 6298//////////////////////////////////////////////////////////////////////////////// 6299 6300ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec) 6301 : BaseState(codec) { 6302} 6303 6304void ACodec::IdleToExecutingState::stateEntered() { 6305 ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str()); 6306} 6307 6308bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) { 6309 switch (msg->what()) { 6310 case kWhatSetParameters: 6311 case kWhatShutdown: 6312 { 6313 mCodec->deferMessage(msg); 6314 return true; 6315 } 6316 6317 case kWhatResume: 6318 { 6319 // We'll be active soon enough. 6320 return true; 6321 } 6322 6323 case kWhatFlush: 6324 { 6325 // We haven't even started yet, so we're flushed alright... 6326 sp<AMessage> notify = mCodec->mNotify->dup(); 6327 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 6328 notify->post(); 6329 6330 return true; 6331 } 6332 6333 case kWhatSignalEndOfInputStream: 6334 { 6335 mCodec->onSignalEndOfInputStream(); 6336 return true; 6337 } 6338 6339 default: 6340 return BaseState::onMessageReceived(msg); 6341 } 6342} 6343 6344bool ACodec::IdleToExecutingState::onOMXEvent( 6345 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 6346 switch (event) { 6347 case OMX_EventCmdComplete: 6348 { 6349 if (data1 != (OMX_U32)OMX_CommandStateSet 6350 || data2 != (OMX_U32)OMX_StateExecuting) { 6351 ALOGE("Unexpected command completion in IdleToExecutingState: %s(%u) %s(%u)", 6352 asString((OMX_COMMANDTYPE)data1), data1, 6353 asString((OMX_STATETYPE)data2), data2); 6354 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6355 return true; 6356 } 6357 6358 mCodec->mExecutingState->resume(); 6359 mCodec->changeState(mCodec->mExecutingState); 6360 6361 return true; 6362 } 6363 6364 default: 6365 return BaseState::onOMXEvent(event, data1, data2); 6366 } 6367} 6368 6369//////////////////////////////////////////////////////////////////////////////// 6370 6371ACodec::ExecutingState::ExecutingState(ACodec *codec) 6372 : BaseState(codec), 6373 mActive(false) { 6374} 6375 6376ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode( 6377 OMX_U32 /* portIndex */) { 6378 return RESUBMIT_BUFFERS; 6379} 6380 6381void ACodec::ExecutingState::submitOutputMetaBuffers() { 6382 // submit as many buffers as there are input buffers with the codec 6383 // in case we are in port reconfiguring 6384 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 6385 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 6386 6387 if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) { 6388 if (mCodec->submitOutputMetadataBuffer() != OK) 6389 break; 6390 } 6391 } 6392 6393 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** 6394 mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround(); 6395} 6396 6397void ACodec::ExecutingState::submitRegularOutputBuffers() { 6398 bool failed = false; 6399 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) { 6400 BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i); 6401 6402 if (mCodec->mNativeWindow != NULL) { 6403 if (info->mStatus != BufferInfo::OWNED_BY_US 6404 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) { 6405 ALOGE("buffers should be owned by us or the surface"); 6406 failed = true; 6407 break; 6408 } 6409 6410 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 6411 continue; 6412 } 6413 } else { 6414 if (info->mStatus != BufferInfo::OWNED_BY_US) { 6415 ALOGE("buffers should be owned by us"); 6416 failed = true; 6417 break; 6418 } 6419 } 6420 6421 ALOGV("[%s] calling fillBuffer %u", mCodec->mComponentName.c_str(), info->mBufferID); 6422 6423 info->checkWriteFence("submitRegularOutputBuffers"); 6424 status_t err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID, info->mFenceFd); 6425 info->mFenceFd = -1; 6426 if (err != OK) { 6427 failed = true; 6428 break; 6429 } 6430 6431 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 6432 } 6433 6434 if (failed) { 6435 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6436 } 6437} 6438 6439void ACodec::ExecutingState::submitOutputBuffers() { 6440 submitRegularOutputBuffers(); 6441 if (mCodec->storingMetadataInDecodedBuffers()) { 6442 submitOutputMetaBuffers(); 6443 } 6444} 6445 6446void ACodec::ExecutingState::resume() { 6447 if (mActive) { 6448 ALOGV("[%s] We're already active, no need to resume.", mCodec->mComponentName.c_str()); 6449 return; 6450 } 6451 6452 submitOutputBuffers(); 6453 6454 // Post all available input buffers 6455 if (mCodec->mBuffers[kPortIndexInput].size() == 0u) { 6456 ALOGW("[%s] we don't have any input buffers to resume", mCodec->mComponentName.c_str()); 6457 } 6458 6459 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) { 6460 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 6461 if (info->mStatus == BufferInfo::OWNED_BY_US) { 6462 postFillThisBuffer(info); 6463 } 6464 } 6465 6466 mActive = true; 6467} 6468 6469void ACodec::ExecutingState::stateEntered() { 6470 ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str()); 6471 6472 mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC)); 6473 mCodec->processDeferredMessages(); 6474} 6475 6476bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) { 6477 bool handled = false; 6478 6479 switch (msg->what()) { 6480 case kWhatShutdown: 6481 { 6482 int32_t keepComponentAllocated; 6483 CHECK(msg->findInt32( 6484 "keepComponentAllocated", &keepComponentAllocated)); 6485 6486 mCodec->mShutdownInProgress = true; 6487 mCodec->mExplicitShutdown = true; 6488 mCodec->mKeepComponentAllocated = keepComponentAllocated; 6489 6490 mActive = false; 6491 6492 status_t err = mCodec->mOMX->sendCommand( 6493 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle); 6494 if (err != OK) { 6495 if (keepComponentAllocated) { 6496 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6497 } 6498 // TODO: do some recovery here. 6499 } else { 6500 mCodec->changeState(mCodec->mExecutingToIdleState); 6501 } 6502 6503 handled = true; 6504 break; 6505 } 6506 6507 case kWhatFlush: 6508 { 6509 ALOGV("[%s] ExecutingState flushing now " 6510 "(codec owns %zu/%zu input, %zu/%zu output).", 6511 mCodec->mComponentName.c_str(), 6512 mCodec->countBuffersOwnedByComponent(kPortIndexInput), 6513 mCodec->mBuffers[kPortIndexInput].size(), 6514 mCodec->countBuffersOwnedByComponent(kPortIndexOutput), 6515 mCodec->mBuffers[kPortIndexOutput].size()); 6516 6517 mActive = false; 6518 6519 status_t err = mCodec->mOMX->sendCommand(mCodec->mNode, OMX_CommandFlush, OMX_ALL); 6520 if (err != OK) { 6521 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6522 } else { 6523 mCodec->changeState(mCodec->mFlushingState); 6524 } 6525 6526 handled = true; 6527 break; 6528 } 6529 6530 case kWhatResume: 6531 { 6532 resume(); 6533 6534 handled = true; 6535 break; 6536 } 6537 6538 case kWhatRequestIDRFrame: 6539 { 6540 status_t err = mCodec->requestIDRFrame(); 6541 if (err != OK) { 6542 ALOGW("Requesting an IDR frame failed."); 6543 } 6544 6545 handled = true; 6546 break; 6547 } 6548 6549 case kWhatSetParameters: 6550 { 6551 sp<AMessage> params; 6552 CHECK(msg->findMessage("params", ¶ms)); 6553 6554 status_t err = mCodec->setParameters(params); 6555 6556 sp<AMessage> reply; 6557 if (msg->findMessage("reply", &reply)) { 6558 reply->setInt32("err", err); 6559 reply->post(); 6560 } 6561 6562 handled = true; 6563 break; 6564 } 6565 6566 case ACodec::kWhatSignalEndOfInputStream: 6567 { 6568 mCodec->onSignalEndOfInputStream(); 6569 handled = true; 6570 break; 6571 } 6572 6573 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** 6574 case kWhatSubmitOutputMetadataBufferIfEOS: 6575 { 6576 if (mCodec->mPortEOS[kPortIndexInput] && 6577 !mCodec->mPortEOS[kPortIndexOutput]) { 6578 status_t err = mCodec->submitOutputMetadataBuffer(); 6579 if (err == OK) { 6580 mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround(); 6581 } 6582 } 6583 return true; 6584 } 6585 6586 default: 6587 handled = BaseState::onMessageReceived(msg); 6588 break; 6589 } 6590 6591 return handled; 6592} 6593 6594status_t ACodec::setParameters(const sp<AMessage> ¶ms) { 6595 int32_t videoBitrate; 6596 if (params->findInt32("video-bitrate", &videoBitrate)) { 6597 OMX_VIDEO_CONFIG_BITRATETYPE configParams; 6598 InitOMXParams(&configParams); 6599 configParams.nPortIndex = kPortIndexOutput; 6600 configParams.nEncodeBitrate = videoBitrate; 6601 6602 status_t err = mOMX->setConfig( 6603 mNode, 6604 OMX_IndexConfigVideoBitrate, 6605 &configParams, 6606 sizeof(configParams)); 6607 6608 if (err != OK) { 6609 ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d", 6610 videoBitrate, err); 6611 6612 return err; 6613 } 6614 } 6615 6616 int64_t skipFramesBeforeUs; 6617 if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) { 6618 status_t err = 6619 mOMX->setInternalOption( 6620 mNode, 6621 kPortIndexInput, 6622 IOMX::INTERNAL_OPTION_START_TIME, 6623 &skipFramesBeforeUs, 6624 sizeof(skipFramesBeforeUs)); 6625 6626 if (err != OK) { 6627 ALOGE("Failed to set parameter 'skip-frames-before' (err %d)", err); 6628 return err; 6629 } 6630 } 6631 6632 int32_t dropInputFrames; 6633 if (params->findInt32("drop-input-frames", &dropInputFrames)) { 6634 bool suspend = dropInputFrames != 0; 6635 6636 status_t err = 6637 mOMX->setInternalOption( 6638 mNode, 6639 kPortIndexInput, 6640 IOMX::INTERNAL_OPTION_SUSPEND, 6641 &suspend, 6642 sizeof(suspend)); 6643 6644 if (err != OK) { 6645 ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err); 6646 return err; 6647 } 6648 } 6649 6650 int32_t dummy; 6651 if (params->findInt32("request-sync", &dummy)) { 6652 status_t err = requestIDRFrame(); 6653 6654 if (err != OK) { 6655 ALOGE("Requesting a sync frame failed w/ err %d", err); 6656 return err; 6657 } 6658 } 6659 6660 float rate; 6661 if (params->findFloat("operating-rate", &rate) && rate > 0) { 6662 status_t err = setOperatingRate(rate, mIsVideo); 6663 if (err != OK) { 6664 ALOGE("Failed to set parameter 'operating-rate' (err %d)", err); 6665 return err; 6666 } 6667 } 6668 6669 int32_t intraRefreshPeriod = 0; 6670 if (params->findInt32("intra-refresh-period", &intraRefreshPeriod) 6671 && intraRefreshPeriod > 0) { 6672 status_t err = setIntraRefreshPeriod(intraRefreshPeriod, false); 6673 if (err != OK) { 6674 ALOGI("[%s] failed setIntraRefreshPeriod. Failure is fine since this key is optional", 6675 mComponentName.c_str()); 6676 err = OK; 6677 } 6678 } 6679 6680 return OK; 6681} 6682 6683void ACodec::onSignalEndOfInputStream() { 6684 sp<AMessage> notify = mNotify->dup(); 6685 notify->setInt32("what", CodecBase::kWhatSignaledInputEOS); 6686 6687 status_t err = mOMX->signalEndOfInputStream(mNode); 6688 if (err != OK) { 6689 notify->setInt32("err", err); 6690 } 6691 notify->post(); 6692} 6693 6694bool ACodec::ExecutingState::onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) { 6695 mCodec->onFrameRendered(mediaTimeUs, systemNano); 6696 return true; 6697} 6698 6699bool ACodec::ExecutingState::onOMXEvent( 6700 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 6701 switch (event) { 6702 case OMX_EventPortSettingsChanged: 6703 { 6704 CHECK_EQ(data1, (OMX_U32)kPortIndexOutput); 6705 6706 mCodec->onOutputFormatChanged(); 6707 6708 if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) { 6709 mCodec->mMetadataBuffersToSubmit = 0; 6710 CHECK_EQ(mCodec->mOMX->sendCommand( 6711 mCodec->mNode, 6712 OMX_CommandPortDisable, kPortIndexOutput), 6713 (status_t)OK); 6714 6715 mCodec->freeOutputBuffersNotOwnedByComponent(); 6716 6717 mCodec->changeState(mCodec->mOutputPortSettingsChangedState); 6718 } else if (data2 != OMX_IndexConfigCommonOutputCrop 6719 && data2 != OMX_IndexConfigAndroidIntraRefresh) { 6720 ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08x", 6721 mCodec->mComponentName.c_str(), data2); 6722 } 6723 6724 return true; 6725 } 6726 6727 case OMX_EventBufferFlag: 6728 { 6729 return true; 6730 } 6731 6732 default: 6733 return BaseState::onOMXEvent(event, data1, data2); 6734 } 6735} 6736 6737//////////////////////////////////////////////////////////////////////////////// 6738 6739ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState( 6740 ACodec *codec) 6741 : BaseState(codec) { 6742} 6743 6744ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode( 6745 OMX_U32 portIndex) { 6746 if (portIndex == kPortIndexOutput) { 6747 return FREE_BUFFERS; 6748 } 6749 6750 CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput); 6751 6752 return RESUBMIT_BUFFERS; 6753} 6754 6755bool ACodec::OutputPortSettingsChangedState::onMessageReceived( 6756 const sp<AMessage> &msg) { 6757 bool handled = false; 6758 6759 switch (msg->what()) { 6760 case kWhatFlush: 6761 case kWhatShutdown: 6762 case kWhatResume: 6763 case kWhatSetParameters: 6764 { 6765 if (msg->what() == kWhatResume) { 6766 ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str()); 6767 } 6768 6769 mCodec->deferMessage(msg); 6770 handled = true; 6771 break; 6772 } 6773 6774 default: 6775 handled = BaseState::onMessageReceived(msg); 6776 break; 6777 } 6778 6779 return handled; 6780} 6781 6782void ACodec::OutputPortSettingsChangedState::stateEntered() { 6783 ALOGV("[%s] Now handling output port settings change", 6784 mCodec->mComponentName.c_str()); 6785} 6786 6787bool ACodec::OutputPortSettingsChangedState::onOMXFrameRendered( 6788 int64_t mediaTimeUs, nsecs_t systemNano) { 6789 mCodec->onFrameRendered(mediaTimeUs, systemNano); 6790 return true; 6791} 6792 6793bool ACodec::OutputPortSettingsChangedState::onOMXEvent( 6794 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 6795 switch (event) { 6796 case OMX_EventCmdComplete: 6797 { 6798 if (data1 == (OMX_U32)OMX_CommandPortDisable) { 6799 if (data2 != (OMX_U32)kPortIndexOutput) { 6800 ALOGW("ignoring EventCmdComplete CommandPortDisable for port %u", data2); 6801 return false; 6802 } 6803 6804 ALOGV("[%s] Output port now disabled.", mCodec->mComponentName.c_str()); 6805 6806 status_t err = OK; 6807 if (!mCodec->mBuffers[kPortIndexOutput].isEmpty()) { 6808 ALOGE("disabled port should be empty, but has %zu buffers", 6809 mCodec->mBuffers[kPortIndexOutput].size()); 6810 err = FAILED_TRANSACTION; 6811 } else { 6812 mCodec->mDealer[kPortIndexOutput].clear(); 6813 } 6814 6815 if (err == OK) { 6816 err = mCodec->mOMX->sendCommand( 6817 mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput); 6818 } 6819 6820 if (err == OK) { 6821 err = mCodec->allocateBuffersOnPort(kPortIndexOutput); 6822 ALOGE_IF(err != OK, "Failed to allocate output port buffers after port " 6823 "reconfiguration: (%d)", err); 6824 } 6825 6826 if (err != OK) { 6827 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6828 6829 // This is technically not correct, but appears to be 6830 // the only way to free the component instance. 6831 // Controlled transitioning from excecuting->idle 6832 // and idle->loaded seem impossible probably because 6833 // the output port never finishes re-enabling. 6834 mCodec->mShutdownInProgress = true; 6835 mCodec->mKeepComponentAllocated = false; 6836 mCodec->changeState(mCodec->mLoadedState); 6837 } 6838 6839 return true; 6840 } else if (data1 == (OMX_U32)OMX_CommandPortEnable) { 6841 if (data2 != (OMX_U32)kPortIndexOutput) { 6842 ALOGW("ignoring EventCmdComplete OMX_CommandPortEnable for port %u", data2); 6843 return false; 6844 } 6845 6846 ALOGV("[%s] Output port now reenabled.", mCodec->mComponentName.c_str()); 6847 6848 if (mCodec->mExecutingState->active()) { 6849 mCodec->mExecutingState->submitOutputBuffers(); 6850 } 6851 6852 mCodec->changeState(mCodec->mExecutingState); 6853 6854 return true; 6855 } 6856 6857 return false; 6858 } 6859 6860 default: 6861 return false; 6862 } 6863} 6864 6865//////////////////////////////////////////////////////////////////////////////// 6866 6867ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec) 6868 : BaseState(codec), 6869 mComponentNowIdle(false) { 6870} 6871 6872bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) { 6873 bool handled = false; 6874 6875 switch (msg->what()) { 6876 case kWhatFlush: 6877 { 6878 // Don't send me a flush request if you previously wanted me 6879 // to shutdown. 6880 ALOGW("Ignoring flush request in ExecutingToIdleState"); 6881 break; 6882 } 6883 6884 case kWhatShutdown: 6885 { 6886 // We're already doing that... 6887 6888 handled = true; 6889 break; 6890 } 6891 6892 default: 6893 handled = BaseState::onMessageReceived(msg); 6894 break; 6895 } 6896 6897 return handled; 6898} 6899 6900void ACodec::ExecutingToIdleState::stateEntered() { 6901 ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str()); 6902 6903 mComponentNowIdle = false; 6904 mCodec->mLastOutputFormat.clear(); 6905} 6906 6907bool ACodec::ExecutingToIdleState::onOMXEvent( 6908 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 6909 switch (event) { 6910 case OMX_EventCmdComplete: 6911 { 6912 if (data1 != (OMX_U32)OMX_CommandStateSet 6913 || data2 != (OMX_U32)OMX_StateIdle) { 6914 ALOGE("Unexpected command completion in ExecutingToIdleState: %s(%u) %s(%u)", 6915 asString((OMX_COMMANDTYPE)data1), data1, 6916 asString((OMX_STATETYPE)data2), data2); 6917 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6918 return true; 6919 } 6920 6921 mComponentNowIdle = true; 6922 6923 changeStateIfWeOwnAllBuffers(); 6924 6925 return true; 6926 } 6927 6928 case OMX_EventPortSettingsChanged: 6929 case OMX_EventBufferFlag: 6930 { 6931 // We're shutting down and don't care about this anymore. 6932 return true; 6933 } 6934 6935 default: 6936 return BaseState::onOMXEvent(event, data1, data2); 6937 } 6938} 6939 6940void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() { 6941 if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) { 6942 status_t err = mCodec->mOMX->sendCommand( 6943 mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded); 6944 if (err == OK) { 6945 err = mCodec->freeBuffersOnPort(kPortIndexInput); 6946 status_t err2 = mCodec->freeBuffersOnPort(kPortIndexOutput); 6947 if (err == OK) { 6948 err = err2; 6949 } 6950 } 6951 6952 if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown) 6953 && mCodec->mNativeWindow != NULL) { 6954 // We push enough 1x1 blank buffers to ensure that one of 6955 // them has made it to the display. This allows the OMX 6956 // component teardown to zero out any protected buffers 6957 // without the risk of scanning out one of those buffers. 6958 pushBlankBuffersToNativeWindow(mCodec->mNativeWindow.get()); 6959 } 6960 6961 if (err != OK) { 6962 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6963 return; 6964 } 6965 6966 mCodec->changeState(mCodec->mIdleToLoadedState); 6967 } 6968} 6969 6970void ACodec::ExecutingToIdleState::onInputBufferFilled( 6971 const sp<AMessage> &msg) { 6972 BaseState::onInputBufferFilled(msg); 6973 6974 changeStateIfWeOwnAllBuffers(); 6975} 6976 6977void ACodec::ExecutingToIdleState::onOutputBufferDrained( 6978 const sp<AMessage> &msg) { 6979 BaseState::onOutputBufferDrained(msg); 6980 6981 changeStateIfWeOwnAllBuffers(); 6982} 6983 6984//////////////////////////////////////////////////////////////////////////////// 6985 6986ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec) 6987 : BaseState(codec) { 6988} 6989 6990bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) { 6991 bool handled = false; 6992 6993 switch (msg->what()) { 6994 case kWhatShutdown: 6995 { 6996 // We're already doing that... 6997 6998 handled = true; 6999 break; 7000 } 7001 7002 case kWhatFlush: 7003 { 7004 // Don't send me a flush request if you previously wanted me 7005 // to shutdown. 7006 ALOGE("Got flush request in IdleToLoadedState"); 7007 break; 7008 } 7009 7010 default: 7011 handled = BaseState::onMessageReceived(msg); 7012 break; 7013 } 7014 7015 return handled; 7016} 7017 7018void ACodec::IdleToLoadedState::stateEntered() { 7019 ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str()); 7020} 7021 7022bool ACodec::IdleToLoadedState::onOMXEvent( 7023 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 7024 switch (event) { 7025 case OMX_EventCmdComplete: 7026 { 7027 if (data1 != (OMX_U32)OMX_CommandStateSet 7028 || data2 != (OMX_U32)OMX_StateLoaded) { 7029 ALOGE("Unexpected command completion in IdleToLoadedState: %s(%u) %s(%u)", 7030 asString((OMX_COMMANDTYPE)data1), data1, 7031 asString((OMX_STATETYPE)data2), data2); 7032 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 7033 return true; 7034 } 7035 7036 mCodec->changeState(mCodec->mLoadedState); 7037 7038 return true; 7039 } 7040 7041 default: 7042 return BaseState::onOMXEvent(event, data1, data2); 7043 } 7044} 7045 7046//////////////////////////////////////////////////////////////////////////////// 7047 7048ACodec::FlushingState::FlushingState(ACodec *codec) 7049 : BaseState(codec) { 7050} 7051 7052void ACodec::FlushingState::stateEntered() { 7053 ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str()); 7054 7055 mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false; 7056} 7057 7058bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) { 7059 bool handled = false; 7060 7061 switch (msg->what()) { 7062 case kWhatShutdown: 7063 { 7064 mCodec->deferMessage(msg); 7065 break; 7066 } 7067 7068 case kWhatFlush: 7069 { 7070 // We're already doing this right now. 7071 handled = true; 7072 break; 7073 } 7074 7075 default: 7076 handled = BaseState::onMessageReceived(msg); 7077 break; 7078 } 7079 7080 return handled; 7081} 7082 7083bool ACodec::FlushingState::onOMXEvent( 7084 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 7085 ALOGV("[%s] FlushingState onOMXEvent(%u,%d)", 7086 mCodec->mComponentName.c_str(), event, (OMX_S32)data1); 7087 7088 switch (event) { 7089 case OMX_EventCmdComplete: 7090 { 7091 if (data1 != (OMX_U32)OMX_CommandFlush) { 7092 ALOGE("unexpected EventCmdComplete %s(%d) data2:%d in FlushingState", 7093 asString((OMX_COMMANDTYPE)data1), data1, data2); 7094 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 7095 return true; 7096 } 7097 7098 if (data2 == kPortIndexInput || data2 == kPortIndexOutput) { 7099 if (mFlushComplete[data2]) { 7100 ALOGW("Flush already completed for %s port", 7101 data2 == kPortIndexInput ? "input" : "output"); 7102 return true; 7103 } 7104 mFlushComplete[data2] = true; 7105 7106 if (mFlushComplete[kPortIndexInput] && mFlushComplete[kPortIndexOutput]) { 7107 changeStateIfWeOwnAllBuffers(); 7108 } 7109 } else if (data2 == OMX_ALL) { 7110 if (!mFlushComplete[kPortIndexInput] || !mFlushComplete[kPortIndexOutput]) { 7111 ALOGW("received flush complete event for OMX_ALL before ports have been" 7112 "flushed (%d/%d)", 7113 mFlushComplete[kPortIndexInput], mFlushComplete[kPortIndexOutput]); 7114 return false; 7115 } 7116 7117 changeStateIfWeOwnAllBuffers(); 7118 } else { 7119 ALOGW("data2 not OMX_ALL but %u in EventCmdComplete CommandFlush", data2); 7120 } 7121 7122 return true; 7123 } 7124 7125 case OMX_EventPortSettingsChanged: 7126 { 7127 sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec); 7128 msg->setInt32("type", omx_message::EVENT); 7129 msg->setInt32("node", mCodec->mNode); 7130 msg->setInt32("event", event); 7131 msg->setInt32("data1", data1); 7132 msg->setInt32("data2", data2); 7133 7134 ALOGV("[%s] Deferring OMX_EventPortSettingsChanged", 7135 mCodec->mComponentName.c_str()); 7136 7137 mCodec->deferMessage(msg); 7138 7139 return true; 7140 } 7141 7142 default: 7143 return BaseState::onOMXEvent(event, data1, data2); 7144 } 7145 7146 return true; 7147} 7148 7149void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) { 7150 BaseState::onOutputBufferDrained(msg); 7151 7152 changeStateIfWeOwnAllBuffers(); 7153} 7154 7155void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) { 7156 BaseState::onInputBufferFilled(msg); 7157 7158 changeStateIfWeOwnAllBuffers(); 7159} 7160 7161void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() { 7162 if (mFlushComplete[kPortIndexInput] 7163 && mFlushComplete[kPortIndexOutput] 7164 && mCodec->allYourBuffersAreBelongToUs()) { 7165 // We now own all buffers except possibly those still queued with 7166 // the native window for rendering. Let's get those back as well. 7167 mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs(); 7168 7169 mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC)); 7170 7171 sp<AMessage> notify = mCodec->mNotify->dup(); 7172 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 7173 notify->post(); 7174 7175 mCodec->mPortEOS[kPortIndexInput] = 7176 mCodec->mPortEOS[kPortIndexOutput] = false; 7177 7178 mCodec->mInputEOSResult = OK; 7179 7180 if (mCodec->mSkipCutBuffer != NULL) { 7181 mCodec->mSkipCutBuffer->clear(); 7182 } 7183 7184 mCodec->changeState(mCodec->mExecutingState); 7185 } 7186} 7187 7188status_t ACodec::queryCapabilities( 7189 const AString &name, const AString &mime, bool isEncoder, 7190 sp<MediaCodecInfo::Capabilities> *caps) { 7191 (*caps).clear(); 7192 const char *role = getComponentRole(isEncoder, mime.c_str()); 7193 if (role == NULL) { 7194 return BAD_VALUE; 7195 } 7196 7197 OMXClient client; 7198 status_t err = client.connect(); 7199 if (err != OK) { 7200 return err; 7201 } 7202 7203 sp<IOMX> omx = client.interface(); 7204 sp<CodecObserver> observer = new CodecObserver; 7205 IOMX::node_id node = 0; 7206 7207 err = omx->allocateNode(name.c_str(), observer, NULL, &node); 7208 if (err != OK) { 7209 client.disconnect(); 7210 return err; 7211 } 7212 7213 err = setComponentRole(omx, node, role); 7214 if (err != OK) { 7215 omx->freeNode(node); 7216 client.disconnect(); 7217 return err; 7218 } 7219 7220 sp<MediaCodecInfo::CapabilitiesBuilder> builder = new MediaCodecInfo::CapabilitiesBuilder(); 7221 bool isVideo = mime.startsWithIgnoreCase("video/"); 7222 7223 if (isVideo) { 7224 OMX_VIDEO_PARAM_PROFILELEVELTYPE param; 7225 InitOMXParams(¶m); 7226 param.nPortIndex = isEncoder ? kPortIndexOutput : kPortIndexInput; 7227 7228 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { 7229 param.nProfileIndex = index; 7230 status_t err = omx->getParameter( 7231 node, OMX_IndexParamVideoProfileLevelQuerySupported, 7232 ¶m, sizeof(param)); 7233 if (err != OK) { 7234 break; 7235 } 7236 builder->addProfileLevel(param.eProfile, param.eLevel); 7237 7238 if (index == kMaxIndicesToCheck) { 7239 ALOGW("[%s] stopping checking profiles after %u: %x/%x", 7240 name.c_str(), index, 7241 param.eProfile, param.eLevel); 7242 } 7243 } 7244 7245 // Color format query 7246 // return colors in the order reported by the OMX component 7247 // prefix "flexible" standard ones with the flexible equivalent 7248 OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat; 7249 InitOMXParams(&portFormat); 7250 portFormat.nPortIndex = isEncoder ? kPortIndexInput : kPortIndexOutput; 7251 Vector<uint32_t> supportedColors; // shadow copy to check for duplicates 7252 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { 7253 portFormat.nIndex = index; 7254 status_t err = omx->getParameter( 7255 node, OMX_IndexParamVideoPortFormat, 7256 &portFormat, sizeof(portFormat)); 7257 if (err != OK) { 7258 break; 7259 } 7260 7261 OMX_U32 flexibleEquivalent; 7262 if (isFlexibleColorFormat( 7263 omx, node, portFormat.eColorFormat, false /* usingNativeWindow */, 7264 &flexibleEquivalent)) { 7265 bool marked = false; 7266 for (size_t i = 0; i < supportedColors.size(); ++i) { 7267 if (supportedColors[i] == flexibleEquivalent) { 7268 marked = true; 7269 break; 7270 } 7271 } 7272 if (!marked) { 7273 supportedColors.push(flexibleEquivalent); 7274 builder->addColorFormat(flexibleEquivalent); 7275 } 7276 } 7277 supportedColors.push(portFormat.eColorFormat); 7278 builder->addColorFormat(portFormat.eColorFormat); 7279 7280 if (index == kMaxIndicesToCheck) { 7281 ALOGW("[%s] stopping checking formats after %u: %s(%x)", 7282 name.c_str(), index, 7283 asString(portFormat.eColorFormat), portFormat.eColorFormat); 7284 } 7285 } 7286 } else if (mime.equalsIgnoreCase(MEDIA_MIMETYPE_AUDIO_AAC)) { 7287 // More audio codecs if they have profiles. 7288 OMX_AUDIO_PARAM_ANDROID_PROFILETYPE param; 7289 InitOMXParams(¶m); 7290 param.nPortIndex = isEncoder ? kPortIndexOutput : kPortIndexInput; 7291 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { 7292 param.nProfileIndex = index; 7293 status_t err = omx->getParameter( 7294 node, (OMX_INDEXTYPE)OMX_IndexParamAudioProfileQuerySupported, 7295 ¶m, sizeof(param)); 7296 if (err != OK) { 7297 break; 7298 } 7299 // For audio, level is ignored. 7300 builder->addProfileLevel(param.eProfile, 0 /* level */); 7301 7302 if (index == kMaxIndicesToCheck) { 7303 ALOGW("[%s] stopping checking profiles after %u: %x", 7304 name.c_str(), index, 7305 param.eProfile); 7306 } 7307 } 7308 7309 // NOTE: Without Android extensions, OMX does not provide a way to query 7310 // AAC profile support 7311 if (param.nProfileIndex == 0) { 7312 ALOGW("component %s doesn't support profile query.", name.c_str()); 7313 } 7314 } 7315 7316 if (isVideo && !isEncoder) { 7317 native_handle_t *sidebandHandle = NULL; 7318 if (omx->configureVideoTunnelMode( 7319 node, kPortIndexOutput, OMX_TRUE, 0, &sidebandHandle) == OK) { 7320 // tunneled playback includes adaptive playback 7321 builder->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback 7322 | MediaCodecInfo::Capabilities::kFlagSupportsTunneledPlayback); 7323 } else if (omx->storeMetaDataInBuffers( 7324 node, kPortIndexOutput, OMX_TRUE) == OK || 7325 omx->prepareForAdaptivePlayback( 7326 node, kPortIndexOutput, OMX_TRUE, 7327 1280 /* width */, 720 /* height */) == OK) { 7328 builder->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback); 7329 } 7330 } 7331 7332 if (isVideo && isEncoder) { 7333 OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params; 7334 InitOMXParams(¶ms); 7335 params.nPortIndex = kPortIndexOutput; 7336 // TODO: should we verify if fallback is supported? 7337 if (omx->getConfig( 7338 node, (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, 7339 ¶ms, sizeof(params)) == OK) { 7340 builder->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsIntraRefresh); 7341 } 7342 } 7343 7344 *caps = builder; 7345 omx->freeNode(node); 7346 client.disconnect(); 7347 return OK; 7348} 7349 7350// These are supposed be equivalent to the logic in 7351// "audio_channel_out_mask_from_count". 7352//static 7353status_t ACodec::getOMXChannelMapping(size_t numChannels, OMX_AUDIO_CHANNELTYPE map[]) { 7354 switch (numChannels) { 7355 case 1: 7356 map[0] = OMX_AUDIO_ChannelCF; 7357 break; 7358 case 2: 7359 map[0] = OMX_AUDIO_ChannelLF; 7360 map[1] = OMX_AUDIO_ChannelRF; 7361 break; 7362 case 3: 7363 map[0] = OMX_AUDIO_ChannelLF; 7364 map[1] = OMX_AUDIO_ChannelRF; 7365 map[2] = OMX_AUDIO_ChannelCF; 7366 break; 7367 case 4: 7368 map[0] = OMX_AUDIO_ChannelLF; 7369 map[1] = OMX_AUDIO_ChannelRF; 7370 map[2] = OMX_AUDIO_ChannelLR; 7371 map[3] = OMX_AUDIO_ChannelRR; 7372 break; 7373 case 5: 7374 map[0] = OMX_AUDIO_ChannelLF; 7375 map[1] = OMX_AUDIO_ChannelRF; 7376 map[2] = OMX_AUDIO_ChannelCF; 7377 map[3] = OMX_AUDIO_ChannelLR; 7378 map[4] = OMX_AUDIO_ChannelRR; 7379 break; 7380 case 6: 7381 map[0] = OMX_AUDIO_ChannelLF; 7382 map[1] = OMX_AUDIO_ChannelRF; 7383 map[2] = OMX_AUDIO_ChannelCF; 7384 map[3] = OMX_AUDIO_ChannelLFE; 7385 map[4] = OMX_AUDIO_ChannelLR; 7386 map[5] = OMX_AUDIO_ChannelRR; 7387 break; 7388 case 7: 7389 map[0] = OMX_AUDIO_ChannelLF; 7390 map[1] = OMX_AUDIO_ChannelRF; 7391 map[2] = OMX_AUDIO_ChannelCF; 7392 map[3] = OMX_AUDIO_ChannelLFE; 7393 map[4] = OMX_AUDIO_ChannelLR; 7394 map[5] = OMX_AUDIO_ChannelRR; 7395 map[6] = OMX_AUDIO_ChannelCS; 7396 break; 7397 case 8: 7398 map[0] = OMX_AUDIO_ChannelLF; 7399 map[1] = OMX_AUDIO_ChannelRF; 7400 map[2] = OMX_AUDIO_ChannelCF; 7401 map[3] = OMX_AUDIO_ChannelLFE; 7402 map[4] = OMX_AUDIO_ChannelLR; 7403 map[5] = OMX_AUDIO_ChannelRR; 7404 map[6] = OMX_AUDIO_ChannelLS; 7405 map[7] = OMX_AUDIO_ChannelRS; 7406 break; 7407 default: 7408 return -EINVAL; 7409 } 7410 7411 return OK; 7412} 7413 7414} // namespace android 7415