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