ACodec.cpp revision 57fad3c31f46ec98d15bc253c16f9d269aeb8ea7
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 // XXX 3697 if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) { 3698 ALOGW("Use baseline profile instead of %d for AVC recording", 3699 h264type.eProfile); 3700 h264type.eProfile = OMX_VIDEO_AVCProfileBaseline; 3701 } 3702 3703 if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) { 3704 h264type.nSliceHeaderSpacing = 0; 3705 h264type.bUseHadamard = OMX_TRUE; 3706 h264type.nRefFrames = 1; 3707 h264type.nBFrames = 0; 3708 h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 3709 if (h264type.nPFrames == 0) { 3710 h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 3711 } 3712 h264type.nRefIdx10ActiveMinus1 = 0; 3713 h264type.nRefIdx11ActiveMinus1 = 0; 3714 h264type.bEntropyCodingCABAC = OMX_FALSE; 3715 h264type.bWeightedPPrediction = OMX_FALSE; 3716 h264type.bconstIpred = OMX_FALSE; 3717 h264type.bDirect8x8Inference = OMX_FALSE; 3718 h264type.bDirectSpatialTemporal = OMX_FALSE; 3719 h264type.nCabacInitIdc = 0; 3720 } 3721 3722 if (h264type.nBFrames != 0) { 3723 h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB; 3724 } 3725 3726 h264type.bEnableUEP = OMX_FALSE; 3727 h264type.bEnableFMO = OMX_FALSE; 3728 h264type.bEnableASO = OMX_FALSE; 3729 h264type.bEnableRS = OMX_FALSE; 3730 h264type.bFrameMBsOnly = OMX_TRUE; 3731 h264type.bMBAFF = OMX_FALSE; 3732 h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; 3733 3734 err = mOMX->setParameter( 3735 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 3736 3737 if (err != OK) { 3738 return err; 3739 } 3740 3741 return configureBitrate(bitrate, bitrateMode); 3742} 3743 3744status_t ACodec::setupHEVCEncoderParameters(const sp<AMessage> &msg) { 3745 int32_t bitrate, iFrameInterval; 3746 if (!msg->findInt32("bitrate", &bitrate) 3747 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 3748 return INVALID_OPERATION; 3749 } 3750 3751 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 3752 3753 float frameRate; 3754 if (!msg->findFloat("frame-rate", &frameRate)) { 3755 int32_t tmp; 3756 if (!msg->findInt32("frame-rate", &tmp)) { 3757 return INVALID_OPERATION; 3758 } 3759 frameRate = (float)tmp; 3760 } 3761 3762 OMX_VIDEO_PARAM_HEVCTYPE hevcType; 3763 InitOMXParams(&hevcType); 3764 hevcType.nPortIndex = kPortIndexOutput; 3765 3766 status_t err = OK; 3767 err = mOMX->getParameter( 3768 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType)); 3769 if (err != OK) { 3770 return err; 3771 } 3772 3773 int32_t profile; 3774 if (msg->findInt32("profile", &profile)) { 3775 int32_t level; 3776 if (!msg->findInt32("level", &level)) { 3777 return INVALID_OPERATION; 3778 } 3779 3780 err = verifySupportForProfileAndLevel(profile, level); 3781 if (err != OK) { 3782 return err; 3783 } 3784 3785 hevcType.eProfile = static_cast<OMX_VIDEO_HEVCPROFILETYPE>(profile); 3786 hevcType.eLevel = static_cast<OMX_VIDEO_HEVCLEVELTYPE>(level); 3787 } 3788 // TODO: finer control? 3789 hevcType.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate); 3790 3791 err = mOMX->setParameter( 3792 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType)); 3793 if (err != OK) { 3794 return err; 3795 } 3796 3797 return configureBitrate(bitrate, bitrateMode); 3798} 3799 3800status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg) { 3801 int32_t bitrate; 3802 int32_t iFrameInterval = 0; 3803 size_t tsLayers = 0; 3804 OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE pattern = 3805 OMX_VIDEO_VPXTemporalLayerPatternNone; 3806 static const uint32_t kVp8LayerRateAlloction 3807 [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] 3808 [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] = { 3809 {100, 100, 100}, // 1 layer 3810 { 60, 100, 100}, // 2 layers {60%, 40%} 3811 { 40, 60, 100}, // 3 layers {40%, 20%, 40%} 3812 }; 3813 if (!msg->findInt32("bitrate", &bitrate)) { 3814 return INVALID_OPERATION; 3815 } 3816 msg->findInt32("i-frame-interval", &iFrameInterval); 3817 3818 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 3819 3820 float frameRate; 3821 if (!msg->findFloat("frame-rate", &frameRate)) { 3822 int32_t tmp; 3823 if (!msg->findInt32("frame-rate", &tmp)) { 3824 return INVALID_OPERATION; 3825 } 3826 frameRate = (float)tmp; 3827 } 3828 3829 AString tsSchema; 3830 if (msg->findString("ts-schema", &tsSchema)) { 3831 if (tsSchema == "webrtc.vp8.1-layer") { 3832 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC; 3833 tsLayers = 1; 3834 } else if (tsSchema == "webrtc.vp8.2-layer") { 3835 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC; 3836 tsLayers = 2; 3837 } else if (tsSchema == "webrtc.vp8.3-layer") { 3838 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC; 3839 tsLayers = 3; 3840 } else { 3841 ALOGW("Unsupported ts-schema [%s]", tsSchema.c_str()); 3842 } 3843 } 3844 3845 OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type; 3846 InitOMXParams(&vp8type); 3847 vp8type.nPortIndex = kPortIndexOutput; 3848 status_t err = mOMX->getParameter( 3849 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder, 3850 &vp8type, sizeof(vp8type)); 3851 3852 if (err == OK) { 3853 if (iFrameInterval > 0) { 3854 vp8type.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate); 3855 } 3856 vp8type.eTemporalPattern = pattern; 3857 vp8type.nTemporalLayerCount = tsLayers; 3858 if (tsLayers > 0) { 3859 for (size_t i = 0; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) { 3860 vp8type.nTemporalLayerBitrateRatio[i] = 3861 kVp8LayerRateAlloction[tsLayers - 1][i]; 3862 } 3863 } 3864 if (bitrateMode == OMX_Video_ControlRateConstant) { 3865 vp8type.nMinQuantizer = 2; 3866 vp8type.nMaxQuantizer = 63; 3867 } 3868 3869 err = mOMX->setParameter( 3870 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder, 3871 &vp8type, sizeof(vp8type)); 3872 if (err != OK) { 3873 ALOGW("Extended VP8 parameters set failed: %d", err); 3874 } 3875 } 3876 3877 return configureBitrate(bitrate, bitrateMode); 3878} 3879 3880status_t ACodec::verifySupportForProfileAndLevel( 3881 int32_t profile, int32_t level) { 3882 OMX_VIDEO_PARAM_PROFILELEVELTYPE params; 3883 InitOMXParams(¶ms); 3884 params.nPortIndex = kPortIndexOutput; 3885 3886 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { 3887 params.nProfileIndex = index; 3888 status_t err = mOMX->getParameter( 3889 mNode, 3890 OMX_IndexParamVideoProfileLevelQuerySupported, 3891 ¶ms, 3892 sizeof(params)); 3893 3894 if (err != OK) { 3895 return err; 3896 } 3897 3898 int32_t supportedProfile = static_cast<int32_t>(params.eProfile); 3899 int32_t supportedLevel = static_cast<int32_t>(params.eLevel); 3900 3901 if (profile == supportedProfile && level <= supportedLevel) { 3902 return OK; 3903 } 3904 3905 if (index == kMaxIndicesToCheck) { 3906 ALOGW("[%s] stopping checking profiles after %u: %x/%x", 3907 mComponentName.c_str(), index, 3908 params.eProfile, params.eLevel); 3909 } 3910 } 3911 return ERROR_UNSUPPORTED; 3912} 3913 3914status_t ACodec::configureBitrate( 3915 int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode) { 3916 OMX_VIDEO_PARAM_BITRATETYPE bitrateType; 3917 InitOMXParams(&bitrateType); 3918 bitrateType.nPortIndex = kPortIndexOutput; 3919 3920 status_t err = mOMX->getParameter( 3921 mNode, OMX_IndexParamVideoBitrate, 3922 &bitrateType, sizeof(bitrateType)); 3923 3924 if (err != OK) { 3925 return err; 3926 } 3927 3928 bitrateType.eControlRate = bitrateMode; 3929 bitrateType.nTargetBitrate = bitrate; 3930 3931 return mOMX->setParameter( 3932 mNode, OMX_IndexParamVideoBitrate, 3933 &bitrateType, sizeof(bitrateType)); 3934} 3935 3936status_t ACodec::setupErrorCorrectionParameters() { 3937 OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType; 3938 InitOMXParams(&errorCorrectionType); 3939 errorCorrectionType.nPortIndex = kPortIndexOutput; 3940 3941 status_t err = mOMX->getParameter( 3942 mNode, OMX_IndexParamVideoErrorCorrection, 3943 &errorCorrectionType, sizeof(errorCorrectionType)); 3944 3945 if (err != OK) { 3946 return OK; // Optional feature. Ignore this failure 3947 } 3948 3949 errorCorrectionType.bEnableHEC = OMX_FALSE; 3950 errorCorrectionType.bEnableResync = OMX_TRUE; 3951 errorCorrectionType.nResynchMarkerSpacing = 256; 3952 errorCorrectionType.bEnableDataPartitioning = OMX_FALSE; 3953 errorCorrectionType.bEnableRVLC = OMX_FALSE; 3954 3955 return mOMX->setParameter( 3956 mNode, OMX_IndexParamVideoErrorCorrection, 3957 &errorCorrectionType, sizeof(errorCorrectionType)); 3958} 3959 3960status_t ACodec::setVideoFormatOnPort( 3961 OMX_U32 portIndex, 3962 int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat, 3963 float frameRate) { 3964 OMX_PARAM_PORTDEFINITIONTYPE def; 3965 InitOMXParams(&def); 3966 def.nPortIndex = portIndex; 3967 3968 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 3969 3970 status_t err = mOMX->getParameter( 3971 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 3972 if (err != OK) { 3973 return err; 3974 } 3975 3976 if (portIndex == kPortIndexInput) { 3977 // XXX Need a (much) better heuristic to compute input buffer sizes. 3978 const size_t X = 64 * 1024; 3979 if (def.nBufferSize < X) { 3980 def.nBufferSize = X; 3981 } 3982 } 3983 3984 if (def.eDomain != OMX_PortDomainVideo) { 3985 ALOGE("expected video port, got %s(%d)", asString(def.eDomain), def.eDomain); 3986 return FAILED_TRANSACTION; 3987 } 3988 3989 video_def->nFrameWidth = width; 3990 video_def->nFrameHeight = height; 3991 3992 if (portIndex == kPortIndexInput) { 3993 video_def->eCompressionFormat = compressionFormat; 3994 video_def->eColorFormat = OMX_COLOR_FormatUnused; 3995 if (frameRate >= 0) { 3996 video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f); 3997 } 3998 } 3999 4000 err = mOMX->setParameter( 4001 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 4002 4003 return err; 4004} 4005 4006status_t ACodec::initNativeWindow() { 4007 if (mNativeWindow != NULL) { 4008 return mOMX->enableNativeBuffers(mNode, kPortIndexOutput, OMX_TRUE /* graphic */, OMX_TRUE); 4009 } 4010 4011 mOMX->enableNativeBuffers(mNode, kPortIndexOutput, OMX_TRUE /* graphic */, OMX_FALSE); 4012 return OK; 4013} 4014 4015size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const { 4016 size_t n = 0; 4017 4018 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 4019 const BufferInfo &info = mBuffers[portIndex].itemAt(i); 4020 4021 if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) { 4022 ++n; 4023 } 4024 } 4025 4026 return n; 4027} 4028 4029size_t ACodec::countBuffersOwnedByNativeWindow() const { 4030 size_t n = 0; 4031 4032 for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) { 4033 const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i); 4034 4035 if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 4036 ++n; 4037 } 4038 } 4039 4040 return n; 4041} 4042 4043void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() { 4044 if (mNativeWindow == NULL) { 4045 return; 4046 } 4047 4048 while (countBuffersOwnedByNativeWindow() > mNumUndequeuedBuffers 4049 && dequeueBufferFromNativeWindow() != NULL) { 4050 // these buffers will be submitted as regular buffers; account for this 4051 if (storingMetadataInDecodedBuffers() && mMetadataBuffersToSubmit > 0) { 4052 --mMetadataBuffersToSubmit; 4053 } 4054 } 4055} 4056 4057bool ACodec::allYourBuffersAreBelongToUs( 4058 OMX_U32 portIndex) { 4059 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 4060 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 4061 4062 if (info->mStatus != BufferInfo::OWNED_BY_US 4063 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) { 4064 ALOGV("[%s] Buffer %u on port %u still has status %d", 4065 mComponentName.c_str(), 4066 info->mBufferID, portIndex, info->mStatus); 4067 return false; 4068 } 4069 } 4070 4071 return true; 4072} 4073 4074bool ACodec::allYourBuffersAreBelongToUs() { 4075 return allYourBuffersAreBelongToUs(kPortIndexInput) 4076 && allYourBuffersAreBelongToUs(kPortIndexOutput); 4077} 4078 4079void ACodec::deferMessage(const sp<AMessage> &msg) { 4080 mDeferredQueue.push_back(msg); 4081} 4082 4083void ACodec::processDeferredMessages() { 4084 List<sp<AMessage> > queue = mDeferredQueue; 4085 mDeferredQueue.clear(); 4086 4087 List<sp<AMessage> >::iterator it = queue.begin(); 4088 while (it != queue.end()) { 4089 onMessageReceived(*it++); 4090 } 4091} 4092 4093// static 4094bool ACodec::describeDefaultColorFormat(DescribeColorFormat2Params ¶ms) { 4095 MediaImage2 &image = params.sMediaImage; 4096 memset(&image, 0, sizeof(image)); 4097 4098 image.mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN; 4099 image.mNumPlanes = 0; 4100 4101 const OMX_COLOR_FORMATTYPE fmt = params.eColorFormat; 4102 image.mWidth = params.nFrameWidth; 4103 image.mHeight = params.nFrameHeight; 4104 4105 // only supporting YUV420 4106 if (fmt != OMX_COLOR_FormatYUV420Planar && 4107 fmt != OMX_COLOR_FormatYUV420PackedPlanar && 4108 fmt != OMX_COLOR_FormatYUV420SemiPlanar && 4109 fmt != OMX_COLOR_FormatYUV420PackedSemiPlanar && 4110 fmt != (OMX_COLOR_FORMATTYPE)HAL_PIXEL_FORMAT_YV12) { 4111 ALOGW("do not know color format 0x%x = %d", fmt, fmt); 4112 return false; 4113 } 4114 4115 // TEMPORARY FIX for some vendors that advertise sliceHeight as 0 4116 if (params.nStride != 0 && params.nSliceHeight == 0) { 4117 ALOGW("using sliceHeight=%u instead of what codec advertised (=0)", 4118 params.nFrameHeight); 4119 params.nSliceHeight = params.nFrameHeight; 4120 } 4121 4122 // we need stride and slice-height to be non-zero and sensible. These values were chosen to 4123 // prevent integer overflows further down the line, and do not indicate support for 4124 // 32kx32k video. 4125 if (params.nStride == 0 || params.nSliceHeight == 0 4126 || params.nStride > 32768 || params.nSliceHeight > 32768) { 4127 ALOGW("cannot describe color format 0x%x = %d with stride=%u and sliceHeight=%u", 4128 fmt, fmt, params.nStride, params.nSliceHeight); 4129 return false; 4130 } 4131 4132 // set-up YUV format 4133 image.mType = MediaImage2::MEDIA_IMAGE_TYPE_YUV; 4134 image.mNumPlanes = 3; 4135 image.mBitDepth = 8; 4136 image.mBitDepthAllocated = 8; 4137 image.mPlane[image.Y].mOffset = 0; 4138 image.mPlane[image.Y].mColInc = 1; 4139 image.mPlane[image.Y].mRowInc = params.nStride; 4140 image.mPlane[image.Y].mHorizSubsampling = 1; 4141 image.mPlane[image.Y].mVertSubsampling = 1; 4142 4143 switch ((int)fmt) { 4144 case HAL_PIXEL_FORMAT_YV12: 4145 if (params.bUsingNativeBuffers) { 4146 size_t ystride = align(params.nStride, 16); 4147 size_t cstride = align(params.nStride / 2, 16); 4148 image.mPlane[image.Y].mRowInc = ystride; 4149 4150 image.mPlane[image.V].mOffset = ystride * params.nSliceHeight; 4151 image.mPlane[image.V].mColInc = 1; 4152 image.mPlane[image.V].mRowInc = cstride; 4153 image.mPlane[image.V].mHorizSubsampling = 2; 4154 image.mPlane[image.V].mVertSubsampling = 2; 4155 4156 image.mPlane[image.U].mOffset = image.mPlane[image.V].mOffset 4157 + (cstride * params.nSliceHeight / 2); 4158 image.mPlane[image.U].mColInc = 1; 4159 image.mPlane[image.U].mRowInc = cstride; 4160 image.mPlane[image.U].mHorizSubsampling = 2; 4161 image.mPlane[image.U].mVertSubsampling = 2; 4162 break; 4163 } else { 4164 // fall through as YV12 is used for YUV420Planar by some codecs 4165 } 4166 4167 case OMX_COLOR_FormatYUV420Planar: 4168 case OMX_COLOR_FormatYUV420PackedPlanar: 4169 image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight; 4170 image.mPlane[image.U].mColInc = 1; 4171 image.mPlane[image.U].mRowInc = params.nStride / 2; 4172 image.mPlane[image.U].mHorizSubsampling = 2; 4173 image.mPlane[image.U].mVertSubsampling = 2; 4174 4175 image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset 4176 + (params.nStride * params.nSliceHeight / 4); 4177 image.mPlane[image.V].mColInc = 1; 4178 image.mPlane[image.V].mRowInc = params.nStride / 2; 4179 image.mPlane[image.V].mHorizSubsampling = 2; 4180 image.mPlane[image.V].mVertSubsampling = 2; 4181 break; 4182 4183 case OMX_COLOR_FormatYUV420SemiPlanar: 4184 // FIXME: NV21 for sw-encoder, NV12 for decoder and hw-encoder 4185 case OMX_COLOR_FormatYUV420PackedSemiPlanar: 4186 // NV12 4187 image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight; 4188 image.mPlane[image.U].mColInc = 2; 4189 image.mPlane[image.U].mRowInc = params.nStride; 4190 image.mPlane[image.U].mHorizSubsampling = 2; 4191 image.mPlane[image.U].mVertSubsampling = 2; 4192 4193 image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset + 1; 4194 image.mPlane[image.V].mColInc = 2; 4195 image.mPlane[image.V].mRowInc = params.nStride; 4196 image.mPlane[image.V].mHorizSubsampling = 2; 4197 image.mPlane[image.V].mVertSubsampling = 2; 4198 break; 4199 4200 default: 4201 TRESPASS(); 4202 } 4203 return true; 4204} 4205 4206// static 4207bool ACodec::describeColorFormat( 4208 const sp<IOMX> &omx, IOMX::node_id node, 4209 DescribeColorFormat2Params &describeParams) 4210{ 4211 OMX_INDEXTYPE describeColorFormatIndex; 4212 if (omx->getExtensionIndex( 4213 node, "OMX.google.android.index.describeColorFormat", 4214 &describeColorFormatIndex) == OK) { 4215 DescribeColorFormatParams describeParamsV1(describeParams); 4216 if (omx->getParameter( 4217 node, describeColorFormatIndex, 4218 &describeParamsV1, sizeof(describeParamsV1)) == OK) { 4219 describeParams.initFromV1(describeParamsV1); 4220 return describeParams.sMediaImage.mType != MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN; 4221 } 4222 } else if (omx->getExtensionIndex( 4223 node, "OMX.google.android.index.describeColorFormat2", &describeColorFormatIndex) == OK 4224 && omx->getParameter( 4225 node, describeColorFormatIndex, &describeParams, sizeof(describeParams)) == OK) { 4226 return describeParams.sMediaImage.mType != MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN; 4227 } 4228 4229 return describeDefaultColorFormat(describeParams); 4230} 4231 4232// static 4233bool ACodec::isFlexibleColorFormat( 4234 const sp<IOMX> &omx, IOMX::node_id node, 4235 uint32_t colorFormat, bool usingNativeBuffers, OMX_U32 *flexibleEquivalent) { 4236 DescribeColorFormat2Params describeParams; 4237 InitOMXParams(&describeParams); 4238 describeParams.eColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat; 4239 // reasonable dummy values 4240 describeParams.nFrameWidth = 128; 4241 describeParams.nFrameHeight = 128; 4242 describeParams.nStride = 128; 4243 describeParams.nSliceHeight = 128; 4244 describeParams.bUsingNativeBuffers = (OMX_BOOL)usingNativeBuffers; 4245 4246 CHECK(flexibleEquivalent != NULL); 4247 4248 if (!describeColorFormat(omx, node, describeParams)) { 4249 return false; 4250 } 4251 4252 const MediaImage2 &img = describeParams.sMediaImage; 4253 if (img.mType == MediaImage2::MEDIA_IMAGE_TYPE_YUV) { 4254 if (img.mNumPlanes != 3 4255 || img.mPlane[img.Y].mHorizSubsampling != 1 4256 || img.mPlane[img.Y].mVertSubsampling != 1) { 4257 return false; 4258 } 4259 4260 // YUV 420 4261 if (img.mPlane[img.U].mHorizSubsampling == 2 4262 && img.mPlane[img.U].mVertSubsampling == 2 4263 && img.mPlane[img.V].mHorizSubsampling == 2 4264 && img.mPlane[img.V].mVertSubsampling == 2) { 4265 // possible flexible YUV420 format 4266 if (img.mBitDepth <= 8) { 4267 *flexibleEquivalent = OMX_COLOR_FormatYUV420Flexible; 4268 return true; 4269 } 4270 } 4271 } 4272 return false; 4273} 4274 4275status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> ¬ify) { 4276 const char *niceIndex = portIndex == kPortIndexInput ? "input" : "output"; 4277 OMX_PARAM_PORTDEFINITIONTYPE def; 4278 InitOMXParams(&def); 4279 def.nPortIndex = portIndex; 4280 4281 status_t err = mOMX->getParameter(mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 4282 if (err != OK) { 4283 return err; 4284 } 4285 4286 if (def.eDir != (portIndex == kPortIndexOutput ? OMX_DirOutput : OMX_DirInput)) { 4287 ALOGE("unexpected dir: %s(%d) on %s port", asString(def.eDir), def.eDir, niceIndex); 4288 return BAD_VALUE; 4289 } 4290 4291 switch (def.eDomain) { 4292 case OMX_PortDomainVideo: 4293 { 4294 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video; 4295 switch ((int)videoDef->eCompressionFormat) { 4296 case OMX_VIDEO_CodingUnused: 4297 { 4298 CHECK(mIsEncoder ^ (portIndex == kPortIndexOutput)); 4299 notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW); 4300 4301 notify->setInt32("stride", videoDef->nStride); 4302 notify->setInt32("slice-height", videoDef->nSliceHeight); 4303 notify->setInt32("color-format", videoDef->eColorFormat); 4304 4305 if (mNativeWindow == NULL) { 4306 DescribeColorFormat2Params describeParams; 4307 InitOMXParams(&describeParams); 4308 describeParams.eColorFormat = videoDef->eColorFormat; 4309 describeParams.nFrameWidth = videoDef->nFrameWidth; 4310 describeParams.nFrameHeight = videoDef->nFrameHeight; 4311 describeParams.nStride = videoDef->nStride; 4312 describeParams.nSliceHeight = videoDef->nSliceHeight; 4313 describeParams.bUsingNativeBuffers = OMX_FALSE; 4314 4315 if (describeColorFormat(mOMX, mNode, describeParams)) { 4316 notify->setBuffer( 4317 "image-data", 4318 ABuffer::CreateAsCopy( 4319 &describeParams.sMediaImage, 4320 sizeof(describeParams.sMediaImage))); 4321 4322 MediaImage2 &img = describeParams.sMediaImage; 4323 MediaImage2::PlaneInfo *plane = img.mPlane; 4324 ALOGV("[%s] MediaImage { F(%ux%u) @%u+%d+%d @%u+%d+%d @%u+%d+%d }", 4325 mComponentName.c_str(), img.mWidth, img.mHeight, 4326 plane[0].mOffset, plane[0].mColInc, plane[0].mRowInc, 4327 plane[1].mOffset, plane[1].mColInc, plane[1].mRowInc, 4328 plane[2].mOffset, plane[2].mColInc, plane[2].mRowInc); 4329 } 4330 } 4331 4332 if (portIndex != kPortIndexOutput) { 4333 // TODO: also get input crop 4334 break; 4335 } 4336 4337 (void)getColorAspects(portIndex, notify); 4338 4339 OMX_CONFIG_RECTTYPE rect; 4340 InitOMXParams(&rect); 4341 rect.nPortIndex = portIndex; 4342 4343 if (mOMX->getConfig( 4344 mNode, 4345 (portIndex == kPortIndexOutput ? 4346 OMX_IndexConfigCommonOutputCrop : 4347 OMX_IndexConfigCommonInputCrop), 4348 &rect, sizeof(rect)) != OK) { 4349 rect.nLeft = 0; 4350 rect.nTop = 0; 4351 rect.nWidth = videoDef->nFrameWidth; 4352 rect.nHeight = videoDef->nFrameHeight; 4353 } 4354 4355 if (rect.nLeft < 0 || 4356 rect.nTop < 0 || 4357 rect.nLeft + rect.nWidth > videoDef->nFrameWidth || 4358 rect.nTop + rect.nHeight > videoDef->nFrameHeight) { 4359 ALOGE("Wrong cropped rect (%d, %d) - (%u, %u) vs. frame (%u, %u)", 4360 rect.nLeft, rect.nTop, 4361 rect.nLeft + rect.nWidth, rect.nTop + rect.nHeight, 4362 videoDef->nFrameWidth, videoDef->nFrameHeight); 4363 return BAD_VALUE; 4364 } 4365 4366 notify->setRect( 4367 "crop", 4368 rect.nLeft, 4369 rect.nTop, 4370 rect.nLeft + rect.nWidth - 1, 4371 rect.nTop + rect.nHeight - 1); 4372 4373 break; 4374 } 4375 4376 case OMX_VIDEO_CodingVP8: 4377 case OMX_VIDEO_CodingVP9: 4378 { 4379 OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type; 4380 InitOMXParams(&vp8type); 4381 vp8type.nPortIndex = kPortIndexOutput; 4382 status_t err = mOMX->getParameter( 4383 mNode, 4384 (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder, 4385 &vp8type, 4386 sizeof(vp8type)); 4387 4388 if (err == OK) { 4389 AString tsSchema = "none"; 4390 if (vp8type.eTemporalPattern 4391 == OMX_VIDEO_VPXTemporalLayerPatternWebRTC) { 4392 switch (vp8type.nTemporalLayerCount) { 4393 case 1: 4394 { 4395 tsSchema = "webrtc.vp8.1-layer"; 4396 break; 4397 } 4398 case 2: 4399 { 4400 tsSchema = "webrtc.vp8.2-layer"; 4401 break; 4402 } 4403 case 3: 4404 { 4405 tsSchema = "webrtc.vp8.3-layer"; 4406 break; 4407 } 4408 default: 4409 { 4410 break; 4411 } 4412 } 4413 } 4414 notify->setString("ts-schema", tsSchema); 4415 } 4416 // Fall through to set up mime. 4417 } 4418 4419 default: 4420 { 4421 if (mIsEncoder ^ (portIndex == kPortIndexOutput)) { 4422 // should be CodingUnused 4423 ALOGE("Raw port video compression format is %s(%d)", 4424 asString(videoDef->eCompressionFormat), 4425 videoDef->eCompressionFormat); 4426 return BAD_VALUE; 4427 } 4428 AString mime; 4429 if (GetMimeTypeForVideoCoding( 4430 videoDef->eCompressionFormat, &mime) != OK) { 4431 notify->setString("mime", "application/octet-stream"); 4432 } else { 4433 notify->setString("mime", mime.c_str()); 4434 } 4435 uint32_t intraRefreshPeriod = 0; 4436 if (mIsEncoder && getIntraRefreshPeriod(&intraRefreshPeriod) == OK 4437 && intraRefreshPeriod > 0) { 4438 notify->setInt32("intra-refresh-period", intraRefreshPeriod); 4439 } 4440 break; 4441 } 4442 } 4443 notify->setInt32("width", videoDef->nFrameWidth); 4444 notify->setInt32("height", videoDef->nFrameHeight); 4445 ALOGV("[%s] %s format is %s", mComponentName.c_str(), 4446 portIndex == kPortIndexInput ? "input" : "output", 4447 notify->debugString().c_str()); 4448 4449 break; 4450 } 4451 4452 case OMX_PortDomainAudio: 4453 { 4454 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio; 4455 4456 switch ((int)audioDef->eEncoding) { 4457 case OMX_AUDIO_CodingPCM: 4458 { 4459 OMX_AUDIO_PARAM_PCMMODETYPE params; 4460 InitOMXParams(¶ms); 4461 params.nPortIndex = portIndex; 4462 4463 err = mOMX->getParameter( 4464 mNode, OMX_IndexParamAudioPcm, ¶ms, sizeof(params)); 4465 if (err != OK) { 4466 return err; 4467 } 4468 4469 if (params.nChannels <= 0 4470 || (params.nChannels != 1 && !params.bInterleaved) 4471 || params.nBitPerSample != 16u 4472 || params.eNumData != OMX_NumericalDataSigned 4473 || params.ePCMMode != OMX_AUDIO_PCMModeLinear) { 4474 ALOGE("unsupported PCM port: %u channels%s, %u-bit, %s(%d), %s(%d) mode ", 4475 params.nChannels, 4476 params.bInterleaved ? " interleaved" : "", 4477 params.nBitPerSample, 4478 asString(params.eNumData), params.eNumData, 4479 asString(params.ePCMMode), params.ePCMMode); 4480 return FAILED_TRANSACTION; 4481 } 4482 4483 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW); 4484 notify->setInt32("channel-count", params.nChannels); 4485 notify->setInt32("sample-rate", params.nSamplingRate); 4486 4487 if (mChannelMaskPresent) { 4488 notify->setInt32("channel-mask", mChannelMask); 4489 } 4490 break; 4491 } 4492 4493 case OMX_AUDIO_CodingAAC: 4494 { 4495 OMX_AUDIO_PARAM_AACPROFILETYPE params; 4496 InitOMXParams(¶ms); 4497 params.nPortIndex = portIndex; 4498 4499 err = mOMX->getParameter( 4500 mNode, OMX_IndexParamAudioAac, ¶ms, sizeof(params)); 4501 if (err != OK) { 4502 return err; 4503 } 4504 4505 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC); 4506 notify->setInt32("channel-count", params.nChannels); 4507 notify->setInt32("sample-rate", params.nSampleRate); 4508 break; 4509 } 4510 4511 case OMX_AUDIO_CodingAMR: 4512 { 4513 OMX_AUDIO_PARAM_AMRTYPE params; 4514 InitOMXParams(¶ms); 4515 params.nPortIndex = portIndex; 4516 4517 err = mOMX->getParameter( 4518 mNode, OMX_IndexParamAudioAmr, ¶ms, sizeof(params)); 4519 if (err != OK) { 4520 return err; 4521 } 4522 4523 notify->setInt32("channel-count", 1); 4524 if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) { 4525 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_WB); 4526 notify->setInt32("sample-rate", 16000); 4527 } else { 4528 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB); 4529 notify->setInt32("sample-rate", 8000); 4530 } 4531 break; 4532 } 4533 4534 case OMX_AUDIO_CodingFLAC: 4535 { 4536 OMX_AUDIO_PARAM_FLACTYPE params; 4537 InitOMXParams(¶ms); 4538 params.nPortIndex = portIndex; 4539 4540 err = mOMX->getParameter( 4541 mNode, OMX_IndexParamAudioFlac, ¶ms, sizeof(params)); 4542 if (err != OK) { 4543 return err; 4544 } 4545 4546 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC); 4547 notify->setInt32("channel-count", params.nChannels); 4548 notify->setInt32("sample-rate", params.nSampleRate); 4549 break; 4550 } 4551 4552 case OMX_AUDIO_CodingMP3: 4553 { 4554 OMX_AUDIO_PARAM_MP3TYPE params; 4555 InitOMXParams(¶ms); 4556 params.nPortIndex = portIndex; 4557 4558 err = mOMX->getParameter( 4559 mNode, OMX_IndexParamAudioMp3, ¶ms, sizeof(params)); 4560 if (err != OK) { 4561 return err; 4562 } 4563 4564 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MPEG); 4565 notify->setInt32("channel-count", params.nChannels); 4566 notify->setInt32("sample-rate", params.nSampleRate); 4567 break; 4568 } 4569 4570 case OMX_AUDIO_CodingVORBIS: 4571 { 4572 OMX_AUDIO_PARAM_VORBISTYPE params; 4573 InitOMXParams(¶ms); 4574 params.nPortIndex = portIndex; 4575 4576 err = mOMX->getParameter( 4577 mNode, OMX_IndexParamAudioVorbis, ¶ms, sizeof(params)); 4578 if (err != OK) { 4579 return err; 4580 } 4581 4582 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_VORBIS); 4583 notify->setInt32("channel-count", params.nChannels); 4584 notify->setInt32("sample-rate", params.nSampleRate); 4585 break; 4586 } 4587 4588 case OMX_AUDIO_CodingAndroidAC3: 4589 { 4590 OMX_AUDIO_PARAM_ANDROID_AC3TYPE params; 4591 InitOMXParams(¶ms); 4592 params.nPortIndex = portIndex; 4593 4594 err = mOMX->getParameter( 4595 mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, 4596 ¶ms, sizeof(params)); 4597 if (err != OK) { 4598 return err; 4599 } 4600 4601 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3); 4602 notify->setInt32("channel-count", params.nChannels); 4603 notify->setInt32("sample-rate", params.nSampleRate); 4604 break; 4605 } 4606 4607 case OMX_AUDIO_CodingAndroidEAC3: 4608 { 4609 OMX_AUDIO_PARAM_ANDROID_EAC3TYPE params; 4610 InitOMXParams(¶ms); 4611 params.nPortIndex = portIndex; 4612 4613 err = mOMX->getParameter( 4614 mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, 4615 ¶ms, sizeof(params)); 4616 if (err != OK) { 4617 return err; 4618 } 4619 4620 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_EAC3); 4621 notify->setInt32("channel-count", params.nChannels); 4622 notify->setInt32("sample-rate", params.nSampleRate); 4623 break; 4624 } 4625 4626 case OMX_AUDIO_CodingAndroidOPUS: 4627 { 4628 OMX_AUDIO_PARAM_ANDROID_OPUSTYPE params; 4629 InitOMXParams(¶ms); 4630 params.nPortIndex = portIndex; 4631 4632 err = mOMX->getParameter( 4633 mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus, 4634 ¶ms, sizeof(params)); 4635 if (err != OK) { 4636 return err; 4637 } 4638 4639 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_OPUS); 4640 notify->setInt32("channel-count", params.nChannels); 4641 notify->setInt32("sample-rate", params.nSampleRate); 4642 break; 4643 } 4644 4645 case OMX_AUDIO_CodingG711: 4646 { 4647 OMX_AUDIO_PARAM_PCMMODETYPE params; 4648 InitOMXParams(¶ms); 4649 params.nPortIndex = portIndex; 4650 4651 err = mOMX->getParameter( 4652 mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioPcm, ¶ms, sizeof(params)); 4653 if (err != OK) { 4654 return err; 4655 } 4656 4657 const char *mime = NULL; 4658 if (params.ePCMMode == OMX_AUDIO_PCMModeMULaw) { 4659 mime = MEDIA_MIMETYPE_AUDIO_G711_MLAW; 4660 } else if (params.ePCMMode == OMX_AUDIO_PCMModeALaw) { 4661 mime = MEDIA_MIMETYPE_AUDIO_G711_ALAW; 4662 } else { // params.ePCMMode == OMX_AUDIO_PCMModeLinear 4663 mime = MEDIA_MIMETYPE_AUDIO_RAW; 4664 } 4665 notify->setString("mime", mime); 4666 notify->setInt32("channel-count", params.nChannels); 4667 notify->setInt32("sample-rate", params.nSamplingRate); 4668 break; 4669 } 4670 4671 case OMX_AUDIO_CodingGSMFR: 4672 { 4673 OMX_AUDIO_PARAM_PCMMODETYPE params; 4674 InitOMXParams(¶ms); 4675 params.nPortIndex = portIndex; 4676 4677 err = mOMX->getParameter( 4678 mNode, OMX_IndexParamAudioPcm, ¶ms, sizeof(params)); 4679 if (err != OK) { 4680 return err; 4681 } 4682 4683 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MSGSM); 4684 notify->setInt32("channel-count", params.nChannels); 4685 notify->setInt32("sample-rate", params.nSamplingRate); 4686 break; 4687 } 4688 4689 default: 4690 ALOGE("Unsupported audio coding: %s(%d)\n", 4691 asString(audioDef->eEncoding), audioDef->eEncoding); 4692 return BAD_TYPE; 4693 } 4694 break; 4695 } 4696 4697 default: 4698 ALOGE("Unsupported domain: %s(%d)", asString(def.eDomain), def.eDomain); 4699 return BAD_TYPE; 4700 } 4701 4702 return OK; 4703} 4704 4705void ACodec::sendFormatChange(const sp<AMessage> &reply) { 4706 sp<AMessage> notify = mBaseOutputFormat->dup(); 4707 notify->setInt32("what", kWhatOutputFormatChanged); 4708 4709 if (getPortFormat(kPortIndexOutput, notify) != OK) { 4710 ALOGE("[%s] Failed to get port format to send format change", mComponentName.c_str()); 4711 return; 4712 } 4713 4714 AString mime; 4715 CHECK(notify->findString("mime", &mime)); 4716 4717 int32_t left, top, right, bottom; 4718 if (mime == MEDIA_MIMETYPE_VIDEO_RAW && 4719 mNativeWindow != NULL && 4720 notify->findRect("crop", &left, &top, &right, &bottom)) { 4721 // notify renderer of the crop change 4722 // NOTE: native window uses extended right-bottom coordinate 4723 reply->setRect("crop", left, top, right + 1, bottom + 1); 4724 } else if (mime == MEDIA_MIMETYPE_AUDIO_RAW && 4725 (mEncoderDelay || mEncoderPadding)) { 4726 int32_t channelCount; 4727 CHECK(notify->findInt32("channel-count", &channelCount)); 4728 if (mSkipCutBuffer != NULL) { 4729 size_t prevbufsize = mSkipCutBuffer->size(); 4730 if (prevbufsize != 0) { 4731 ALOGW("Replacing SkipCutBuffer holding %zu bytes", prevbufsize); 4732 } 4733 } 4734 mSkipCutBuffer = new SkipCutBuffer(mEncoderDelay, mEncoderPadding, channelCount); 4735 } 4736 4737 notify->post(); 4738 4739 mSentFormat = true; 4740} 4741 4742void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) { 4743 sp<AMessage> notify = mNotify->dup(); 4744 notify->setInt32("what", CodecBase::kWhatError); 4745 ALOGE("signalError(omxError %#x, internalError %d)", error, internalError); 4746 4747 if (internalError == UNKNOWN_ERROR) { // find better error code 4748 const status_t omxStatus = statusFromOMXError(error); 4749 if (omxStatus != 0) { 4750 internalError = omxStatus; 4751 } else { 4752 ALOGW("Invalid OMX error %#x", error); 4753 } 4754 } 4755 4756 mFatalError = true; 4757 4758 notify->setInt32("err", internalError); 4759 notify->setInt32("actionCode", ACTION_CODE_FATAL); // could translate from OMX error. 4760 notify->post(); 4761} 4762 4763//////////////////////////////////////////////////////////////////////////////// 4764 4765ACodec::PortDescription::PortDescription() { 4766} 4767 4768status_t ACodec::requestIDRFrame() { 4769 if (!mIsEncoder) { 4770 return ERROR_UNSUPPORTED; 4771 } 4772 4773 OMX_CONFIG_INTRAREFRESHVOPTYPE params; 4774 InitOMXParams(¶ms); 4775 4776 params.nPortIndex = kPortIndexOutput; 4777 params.IntraRefreshVOP = OMX_TRUE; 4778 4779 return mOMX->setConfig( 4780 mNode, 4781 OMX_IndexConfigVideoIntraVOPRefresh, 4782 ¶ms, 4783 sizeof(params)); 4784} 4785 4786void ACodec::PortDescription::addBuffer( 4787 IOMX::buffer_id id, const sp<ABuffer> &buffer, 4788 const sp<NativeHandle> &handle, const sp<RefBase> &memRef) { 4789 mBufferIDs.push_back(id); 4790 mBuffers.push_back(buffer); 4791 mHandles.push_back(handle); 4792 mMemRefs.push_back(memRef); 4793} 4794 4795size_t ACodec::PortDescription::countBuffers() { 4796 return mBufferIDs.size(); 4797} 4798 4799IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const { 4800 return mBufferIDs.itemAt(index); 4801} 4802 4803sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const { 4804 return mBuffers.itemAt(index); 4805} 4806 4807sp<NativeHandle> ACodec::PortDescription::handleAt(size_t index) const { 4808 return mHandles.itemAt(index); 4809} 4810 4811sp<RefBase> ACodec::PortDescription::memRefAt(size_t index) const { 4812 return mMemRefs.itemAt(index); 4813} 4814 4815//////////////////////////////////////////////////////////////////////////////// 4816 4817ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState) 4818 : AState(parentState), 4819 mCodec(codec) { 4820} 4821 4822ACodec::BaseState::PortMode ACodec::BaseState::getPortMode( 4823 OMX_U32 /* portIndex */) { 4824 return KEEP_BUFFERS; 4825} 4826 4827bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) { 4828 switch (msg->what()) { 4829 case kWhatInputBufferFilled: 4830 { 4831 onInputBufferFilled(msg); 4832 break; 4833 } 4834 4835 case kWhatOutputBufferDrained: 4836 { 4837 onOutputBufferDrained(msg); 4838 break; 4839 } 4840 4841 case ACodec::kWhatOMXMessageList: 4842 { 4843 return checkOMXMessage(msg) ? onOMXMessageList(msg) : true; 4844 } 4845 4846 case ACodec::kWhatOMXMessageItem: 4847 { 4848 // no need to check as we already did it for kWhatOMXMessageList 4849 return onOMXMessage(msg); 4850 } 4851 4852 case ACodec::kWhatOMXMessage: 4853 { 4854 return checkOMXMessage(msg) ? onOMXMessage(msg) : true; 4855 } 4856 4857 case ACodec::kWhatSetSurface: 4858 { 4859 sp<AReplyToken> replyID; 4860 CHECK(msg->senderAwaitsResponse(&replyID)); 4861 4862 sp<RefBase> obj; 4863 CHECK(msg->findObject("surface", &obj)); 4864 4865 status_t err = mCodec->handleSetSurface(static_cast<Surface *>(obj.get())); 4866 4867 sp<AMessage> response = new AMessage; 4868 response->setInt32("err", err); 4869 response->postReply(replyID); 4870 break; 4871 } 4872 4873 case ACodec::kWhatCreateInputSurface: 4874 case ACodec::kWhatSetInputSurface: 4875 case ACodec::kWhatSignalEndOfInputStream: 4876 { 4877 // This may result in an app illegal state exception. 4878 ALOGE("Message 0x%x was not handled", msg->what()); 4879 mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION); 4880 return true; 4881 } 4882 4883 case ACodec::kWhatOMXDied: 4884 { 4885 // This will result in kFlagSawMediaServerDie handling in MediaCodec. 4886 ALOGE("OMX/mediaserver died, signalling error!"); 4887 mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT); 4888 break; 4889 } 4890 4891 case ACodec::kWhatReleaseCodecInstance: 4892 { 4893 ALOGI("[%s] forcing the release of codec", 4894 mCodec->mComponentName.c_str()); 4895 status_t err = mCodec->mOMX->freeNode(mCodec->mNode); 4896 ALOGE_IF("[%s] failed to release codec instance: err=%d", 4897 mCodec->mComponentName.c_str(), err); 4898 sp<AMessage> notify = mCodec->mNotify->dup(); 4899 notify->setInt32("what", CodecBase::kWhatShutdownCompleted); 4900 notify->post(); 4901 break; 4902 } 4903 4904 default: 4905 return false; 4906 } 4907 4908 return true; 4909} 4910 4911bool ACodec::BaseState::checkOMXMessage(const sp<AMessage> &msg) { 4912 // there is a possibility that this is an outstanding message for a 4913 // codec that we have already destroyed 4914 if (mCodec->mNode == 0) { 4915 ALOGI("ignoring message as already freed component: %s", 4916 msg->debugString().c_str()); 4917 return false; 4918 } 4919 4920 IOMX::node_id nodeID; 4921 CHECK(msg->findInt32("node", (int32_t*)&nodeID)); 4922 if (nodeID != mCodec->mNode) { 4923 ALOGE("Unexpected message for nodeID: %u, should have been %u", nodeID, mCodec->mNode); 4924 return false; 4925 } 4926 return true; 4927} 4928 4929bool ACodec::BaseState::onOMXMessageList(const sp<AMessage> &msg) { 4930 sp<RefBase> obj; 4931 CHECK(msg->findObject("messages", &obj)); 4932 sp<MessageList> msgList = static_cast<MessageList *>(obj.get()); 4933 4934 bool receivedRenderedEvents = false; 4935 for (std::list<sp<AMessage>>::const_iterator it = msgList->getList().cbegin(); 4936 it != msgList->getList().cend(); ++it) { 4937 (*it)->setWhat(ACodec::kWhatOMXMessageItem); 4938 mCodec->handleMessage(*it); 4939 int32_t type; 4940 CHECK((*it)->findInt32("type", &type)); 4941 if (type == omx_message::FRAME_RENDERED) { 4942 receivedRenderedEvents = true; 4943 } 4944 } 4945 4946 if (receivedRenderedEvents) { 4947 // NOTE: all buffers are rendered in this case 4948 mCodec->notifyOfRenderedFrames(); 4949 } 4950 return true; 4951} 4952 4953bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) { 4954 int32_t type; 4955 CHECK(msg->findInt32("type", &type)); 4956 4957 switch (type) { 4958 case omx_message::EVENT: 4959 { 4960 int32_t event, data1, data2; 4961 CHECK(msg->findInt32("event", &event)); 4962 CHECK(msg->findInt32("data1", &data1)); 4963 CHECK(msg->findInt32("data2", &data2)); 4964 4965 if (event == OMX_EventCmdComplete 4966 && data1 == OMX_CommandFlush 4967 && data2 == (int32_t)OMX_ALL) { 4968 // Use of this notification is not consistent across 4969 // implementations. We'll drop this notification and rely 4970 // on flush-complete notifications on the individual port 4971 // indices instead. 4972 4973 return true; 4974 } 4975 4976 return onOMXEvent( 4977 static_cast<OMX_EVENTTYPE>(event), 4978 static_cast<OMX_U32>(data1), 4979 static_cast<OMX_U32>(data2)); 4980 } 4981 4982 case omx_message::EMPTY_BUFFER_DONE: 4983 { 4984 IOMX::buffer_id bufferID; 4985 int32_t fenceFd; 4986 4987 CHECK(msg->findInt32("buffer", (int32_t*)&bufferID)); 4988 CHECK(msg->findInt32("fence_fd", &fenceFd)); 4989 4990 return onOMXEmptyBufferDone(bufferID, fenceFd); 4991 } 4992 4993 case omx_message::FILL_BUFFER_DONE: 4994 { 4995 IOMX::buffer_id bufferID; 4996 CHECK(msg->findInt32("buffer", (int32_t*)&bufferID)); 4997 4998 int32_t rangeOffset, rangeLength, flags, fenceFd; 4999 int64_t timeUs; 5000 5001 CHECK(msg->findInt32("range_offset", &rangeOffset)); 5002 CHECK(msg->findInt32("range_length", &rangeLength)); 5003 CHECK(msg->findInt32("flags", &flags)); 5004 CHECK(msg->findInt64("timestamp", &timeUs)); 5005 CHECK(msg->findInt32("fence_fd", &fenceFd)); 5006 5007 return onOMXFillBufferDone( 5008 bufferID, 5009 (size_t)rangeOffset, (size_t)rangeLength, 5010 (OMX_U32)flags, 5011 timeUs, 5012 fenceFd); 5013 } 5014 5015 case omx_message::FRAME_RENDERED: 5016 { 5017 int64_t mediaTimeUs, systemNano; 5018 5019 CHECK(msg->findInt64("media_time_us", &mediaTimeUs)); 5020 CHECK(msg->findInt64("system_nano", &systemNano)); 5021 5022 return onOMXFrameRendered( 5023 mediaTimeUs, systemNano); 5024 } 5025 5026 default: 5027 ALOGE("Unexpected message type: %d", type); 5028 return false; 5029 } 5030} 5031 5032bool ACodec::BaseState::onOMXFrameRendered( 5033 int64_t mediaTimeUs __unused, nsecs_t systemNano __unused) { 5034 // ignore outside of Executing and PortSettingsChanged states 5035 return true; 5036} 5037 5038bool ACodec::BaseState::onOMXEvent( 5039 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 5040 if (event != OMX_EventError) { 5041 ALOGV("[%s] EVENT(%d, 0x%08x, 0x%08x)", 5042 mCodec->mComponentName.c_str(), event, data1, data2); 5043 5044 return false; 5045 } 5046 5047 ALOGE("[%s] ERROR(0x%08x)", mCodec->mComponentName.c_str(), data1); 5048 5049 // verify OMX component sends back an error we expect. 5050 OMX_ERRORTYPE omxError = (OMX_ERRORTYPE)data1; 5051 if (!isOMXError(omxError)) { 5052 ALOGW("Invalid OMX error %#x", omxError); 5053 omxError = OMX_ErrorUndefined; 5054 } 5055 mCodec->signalError(omxError); 5056 5057 return true; 5058} 5059 5060bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID, int fenceFd) { 5061 ALOGV("[%s] onOMXEmptyBufferDone %u", 5062 mCodec->mComponentName.c_str(), bufferID); 5063 5064 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID); 5065 BufferInfo::Status status = BufferInfo::getSafeStatus(info); 5066 if (status != BufferInfo::OWNED_BY_COMPONENT) { 5067 ALOGE("Wrong ownership in EBD: %s(%d) buffer #%u", _asString(status), status, bufferID); 5068 mCodec->dumpBuffers(kPortIndexInput); 5069 if (fenceFd >= 0) { 5070 ::close(fenceFd); 5071 } 5072 return false; 5073 } 5074 info->mStatus = BufferInfo::OWNED_BY_US; 5075 5076 // input buffers cannot take fences, so wait for any fence now 5077 (void)mCodec->waitForFence(fenceFd, "onOMXEmptyBufferDone"); 5078 fenceFd = -1; 5079 5080 // still save fence for completeness 5081 info->setWriteFence(fenceFd, "onOMXEmptyBufferDone"); 5082 5083 // We're in "store-metadata-in-buffers" mode, the underlying 5084 // OMX component had access to data that's implicitly refcounted 5085 // by this "MediaBuffer" object. Now that the OMX component has 5086 // told us that it's done with the input buffer, we can decrement 5087 // the mediaBuffer's reference count. 5088 info->mData->setMediaBufferBase(NULL); 5089 5090 PortMode mode = getPortMode(kPortIndexInput); 5091 5092 switch (mode) { 5093 case KEEP_BUFFERS: 5094 break; 5095 5096 case RESUBMIT_BUFFERS: 5097 postFillThisBuffer(info); 5098 break; 5099 5100 case FREE_BUFFERS: 5101 default: 5102 ALOGE("SHOULD NOT REACH HERE: cannot free empty output buffers"); 5103 return false; 5104 } 5105 5106 return true; 5107} 5108 5109void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) { 5110 if (mCodec->mPortEOS[kPortIndexInput]) { 5111 return; 5112 } 5113 5114 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 5115 5116 sp<AMessage> notify = mCodec->mNotify->dup(); 5117 notify->setInt32("what", CodecBase::kWhatFillThisBuffer); 5118 notify->setInt32("buffer-id", info->mBufferID); 5119 5120 info->mData->meta()->clear(); 5121 notify->setBuffer("buffer", info->mData); 5122 5123 sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec); 5124 reply->setInt32("buffer-id", info->mBufferID); 5125 5126 notify->setMessage("reply", reply); 5127 5128 notify->post(); 5129 5130 info->mStatus = BufferInfo::OWNED_BY_UPSTREAM; 5131} 5132 5133void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { 5134 IOMX::buffer_id bufferID; 5135 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID)); 5136 sp<ABuffer> buffer; 5137 int32_t err = OK; 5138 bool eos = false; 5139 PortMode mode = getPortMode(kPortIndexInput); 5140 5141 if (!msg->findBuffer("buffer", &buffer)) { 5142 /* these are unfilled buffers returned by client */ 5143 CHECK(msg->findInt32("err", &err)); 5144 5145 if (err == OK) { 5146 /* buffers with no errors are returned on MediaCodec.flush */ 5147 mode = KEEP_BUFFERS; 5148 } else { 5149 ALOGV("[%s] saw error %d instead of an input buffer", 5150 mCodec->mComponentName.c_str(), err); 5151 eos = true; 5152 } 5153 5154 buffer.clear(); 5155 } 5156 5157 int32_t tmp; 5158 if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) { 5159 eos = true; 5160 err = ERROR_END_OF_STREAM; 5161 } 5162 5163 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID); 5164 BufferInfo::Status status = BufferInfo::getSafeStatus(info); 5165 if (status != BufferInfo::OWNED_BY_UPSTREAM) { 5166 ALOGE("Wrong ownership in IBF: %s(%d) buffer #%u", _asString(status), status, bufferID); 5167 mCodec->dumpBuffers(kPortIndexInput); 5168 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 5169 return; 5170 } 5171 5172 info->mStatus = BufferInfo::OWNED_BY_US; 5173 5174 switch (mode) { 5175 case KEEP_BUFFERS: 5176 { 5177 if (eos) { 5178 if (!mCodec->mPortEOS[kPortIndexInput]) { 5179 mCodec->mPortEOS[kPortIndexInput] = true; 5180 mCodec->mInputEOSResult = err; 5181 } 5182 } 5183 break; 5184 } 5185 5186 case RESUBMIT_BUFFERS: 5187 { 5188 if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) { 5189 // Do not send empty input buffer w/o EOS to the component. 5190 if (buffer->size() == 0 && !eos) { 5191 postFillThisBuffer(info); 5192 break; 5193 } 5194 5195 int64_t timeUs; 5196 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 5197 5198 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME; 5199 5200 int32_t isCSD; 5201 if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) { 5202 flags |= OMX_BUFFERFLAG_CODECCONFIG; 5203 } 5204 5205 if (eos) { 5206 flags |= OMX_BUFFERFLAG_EOS; 5207 } 5208 5209 if (buffer != info->mData) { 5210 ALOGV("[%s] Needs to copy input data for buffer %u. (%p != %p)", 5211 mCodec->mComponentName.c_str(), 5212 bufferID, 5213 buffer.get(), info->mData.get()); 5214 5215 if (buffer->size() > info->mData->capacity()) { 5216 ALOGE("data size (%zu) is greated than buffer capacity (%zu)", 5217 buffer->size(), // this is the data received 5218 info->mData->capacity()); // this is out buffer size 5219 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 5220 return; 5221 } 5222 memcpy(info->mData->data(), buffer->data(), buffer->size()); 5223 } 5224 5225 if (flags & OMX_BUFFERFLAG_CODECCONFIG) { 5226 ALOGV("[%s] calling emptyBuffer %u w/ codec specific data", 5227 mCodec->mComponentName.c_str(), bufferID); 5228 } else if (flags & OMX_BUFFERFLAG_EOS) { 5229 ALOGV("[%s] calling emptyBuffer %u w/ EOS", 5230 mCodec->mComponentName.c_str(), bufferID); 5231 } else { 5232#if TRACK_BUFFER_TIMING 5233 ALOGI("[%s] calling emptyBuffer %u w/ time %lld us", 5234 mCodec->mComponentName.c_str(), bufferID, (long long)timeUs); 5235#else 5236 ALOGV("[%s] calling emptyBuffer %u w/ time %lld us", 5237 mCodec->mComponentName.c_str(), bufferID, (long long)timeUs); 5238#endif 5239 } 5240 5241#if TRACK_BUFFER_TIMING 5242 ACodec::BufferStats stats; 5243 stats.mEmptyBufferTimeUs = ALooper::GetNowUs(); 5244 stats.mFillBufferDoneTimeUs = -1ll; 5245 mCodec->mBufferStats.add(timeUs, stats); 5246#endif 5247 5248 if (mCodec->storingMetadataInDecodedBuffers()) { 5249 // try to submit an output buffer for each input buffer 5250 PortMode outputMode = getPortMode(kPortIndexOutput); 5251 5252 ALOGV("MetadataBuffersToSubmit=%u portMode=%s", 5253 mCodec->mMetadataBuffersToSubmit, 5254 (outputMode == FREE_BUFFERS ? "FREE" : 5255 outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT")); 5256 if (outputMode == RESUBMIT_BUFFERS) { 5257 mCodec->submitOutputMetadataBuffer(); 5258 } 5259 } 5260 info->checkReadFence("onInputBufferFilled"); 5261 status_t err2 = mCodec->mOMX->emptyBuffer( 5262 mCodec->mNode, 5263 bufferID, 5264 0, 5265 buffer->size(), 5266 flags, 5267 timeUs, 5268 info->mFenceFd); 5269 info->mFenceFd = -1; 5270 if (err2 != OK) { 5271 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2)); 5272 return; 5273 } 5274 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 5275 5276 if (!eos && err == OK) { 5277 getMoreInputDataIfPossible(); 5278 } else { 5279 ALOGV("[%s] Signalled EOS (%d) on the input port", 5280 mCodec->mComponentName.c_str(), err); 5281 5282 mCodec->mPortEOS[kPortIndexInput] = true; 5283 mCodec->mInputEOSResult = err; 5284 } 5285 } else if (!mCodec->mPortEOS[kPortIndexInput]) { 5286 if (err != OK && err != ERROR_END_OF_STREAM) { 5287 ALOGV("[%s] Signalling EOS on the input port due to error %d", 5288 mCodec->mComponentName.c_str(), err); 5289 } else { 5290 ALOGV("[%s] Signalling EOS on the input port", 5291 mCodec->mComponentName.c_str()); 5292 } 5293 5294 ALOGV("[%s] calling emptyBuffer %u signalling EOS", 5295 mCodec->mComponentName.c_str(), bufferID); 5296 5297 info->checkReadFence("onInputBufferFilled"); 5298 status_t err2 = mCodec->mOMX->emptyBuffer( 5299 mCodec->mNode, 5300 bufferID, 5301 0, 5302 0, 5303 OMX_BUFFERFLAG_EOS, 5304 0, 5305 info->mFenceFd); 5306 info->mFenceFd = -1; 5307 if (err2 != OK) { 5308 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2)); 5309 return; 5310 } 5311 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 5312 5313 mCodec->mPortEOS[kPortIndexInput] = true; 5314 mCodec->mInputEOSResult = err; 5315 } 5316 break; 5317 } 5318 5319 case FREE_BUFFERS: 5320 break; 5321 5322 default: 5323 ALOGE("invalid port mode: %d", mode); 5324 break; 5325 } 5326} 5327 5328void ACodec::BaseState::getMoreInputDataIfPossible() { 5329 if (mCodec->mPortEOS[kPortIndexInput]) { 5330 return; 5331 } 5332 5333 BufferInfo *eligible = NULL; 5334 5335 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 5336 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 5337 5338#if 0 5339 if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) { 5340 // There's already a "read" pending. 5341 return; 5342 } 5343#endif 5344 5345 if (info->mStatus == BufferInfo::OWNED_BY_US) { 5346 eligible = info; 5347 } 5348 } 5349 5350 if (eligible == NULL) { 5351 return; 5352 } 5353 5354 postFillThisBuffer(eligible); 5355} 5356 5357bool ACodec::BaseState::onOMXFillBufferDone( 5358 IOMX::buffer_id bufferID, 5359 size_t rangeOffset, size_t rangeLength, 5360 OMX_U32 flags, 5361 int64_t timeUs, 5362 int fenceFd) { 5363 ALOGV("[%s] onOMXFillBufferDone %u time %" PRId64 " us, flags = 0x%08x", 5364 mCodec->mComponentName.c_str(), bufferID, timeUs, flags); 5365 5366 ssize_t index; 5367 status_t err= OK; 5368 5369#if TRACK_BUFFER_TIMING 5370 index = mCodec->mBufferStats.indexOfKey(timeUs); 5371 if (index >= 0) { 5372 ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index); 5373 stats->mFillBufferDoneTimeUs = ALooper::GetNowUs(); 5374 5375 ALOGI("frame PTS %lld: %lld", 5376 timeUs, 5377 stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs); 5378 5379 mCodec->mBufferStats.removeItemsAt(index); 5380 stats = NULL; 5381 } 5382#endif 5383 5384 BufferInfo *info = 5385 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 5386 BufferInfo::Status status = BufferInfo::getSafeStatus(info); 5387 if (status != BufferInfo::OWNED_BY_COMPONENT) { 5388 ALOGE("Wrong ownership in FBD: %s(%d) buffer #%u", _asString(status), status, bufferID); 5389 mCodec->dumpBuffers(kPortIndexOutput); 5390 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 5391 if (fenceFd >= 0) { 5392 ::close(fenceFd); 5393 } 5394 return true; 5395 } 5396 5397 info->mDequeuedAt = ++mCodec->mDequeueCounter; 5398 info->mStatus = BufferInfo::OWNED_BY_US; 5399 5400 if (info->mRenderInfo != NULL) { 5401 // The fence for an emptied buffer must have signaled, but there still could be queued 5402 // or out-of-order dequeued buffers in the render queue prior to this buffer. Drop these, 5403 // as we will soon requeue this buffer to the surface. While in theory we could still keep 5404 // track of buffers that are requeued to the surface, it is better to add support to the 5405 // buffer-queue to notify us of released buffers and their fences (in the future). 5406 mCodec->notifyOfRenderedFrames(true /* dropIncomplete */); 5407 } 5408 5409 // byte buffers cannot take fences, so wait for any fence now 5410 if (mCodec->mNativeWindow == NULL) { 5411 (void)mCodec->waitForFence(fenceFd, "onOMXFillBufferDone"); 5412 fenceFd = -1; 5413 } 5414 info->setReadFence(fenceFd, "onOMXFillBufferDone"); 5415 5416 PortMode mode = getPortMode(kPortIndexOutput); 5417 5418 switch (mode) { 5419 case KEEP_BUFFERS: 5420 break; 5421 5422 case RESUBMIT_BUFFERS: 5423 { 5424 if (rangeLength == 0 && (!(flags & OMX_BUFFERFLAG_EOS) 5425 || mCodec->mPortEOS[kPortIndexOutput])) { 5426 ALOGV("[%s] calling fillBuffer %u", 5427 mCodec->mComponentName.c_str(), info->mBufferID); 5428 5429 err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID, info->mFenceFd); 5430 info->mFenceFd = -1; 5431 if (err != OK) { 5432 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 5433 return true; 5434 } 5435 5436 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 5437 break; 5438 } 5439 5440 sp<AMessage> reply = 5441 new AMessage(kWhatOutputBufferDrained, mCodec); 5442 5443 if (!mCodec->mSentFormat && rangeLength > 0) { 5444 mCodec->sendFormatChange(reply); 5445 } 5446 if (mCodec->usingMetadataOnEncoderOutput()) { 5447 native_handle_t *handle = NULL; 5448 VideoGrallocMetadata &grallocMeta = *(VideoGrallocMetadata *)info->mData->data(); 5449 VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)info->mData->data(); 5450 if (info->mData->size() >= sizeof(grallocMeta) 5451 && grallocMeta.eType == kMetadataBufferTypeGrallocSource) { 5452 handle = (native_handle_t *)(uintptr_t)grallocMeta.pHandle; 5453 } else if (info->mData->size() >= sizeof(nativeMeta) 5454 && nativeMeta.eType == kMetadataBufferTypeANWBuffer) { 5455#ifdef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS 5456 // ANativeWindowBuffer is only valid on 32-bit/mediaserver process 5457 handle = NULL; 5458#else 5459 handle = (native_handle_t *)nativeMeta.pBuffer->handle; 5460#endif 5461 } 5462 info->mData->meta()->setPointer("handle", handle); 5463 info->mData->meta()->setInt32("rangeOffset", rangeOffset); 5464 info->mData->meta()->setInt32("rangeLength", rangeLength); 5465 } else { 5466 info->mData->setRange(rangeOffset, rangeLength); 5467 } 5468#if 0 5469 if (mCodec->mNativeWindow == NULL) { 5470 if (IsIDR(info->mData)) { 5471 ALOGI("IDR frame"); 5472 } 5473 } 5474#endif 5475 5476 if (mCodec->mSkipCutBuffer != NULL) { 5477 mCodec->mSkipCutBuffer->submit(info->mData); 5478 } 5479 info->mData->meta()->setInt64("timeUs", timeUs); 5480 5481 sp<AMessage> notify = mCodec->mNotify->dup(); 5482 notify->setInt32("what", CodecBase::kWhatDrainThisBuffer); 5483 notify->setInt32("buffer-id", info->mBufferID); 5484 notify->setBuffer("buffer", info->mData); 5485 notify->setInt32("flags", flags); 5486 5487 reply->setInt32("buffer-id", info->mBufferID); 5488 5489 notify->setMessage("reply", reply); 5490 5491 notify->post(); 5492 5493 info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM; 5494 5495 if (flags & OMX_BUFFERFLAG_EOS) { 5496 ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str()); 5497 5498 sp<AMessage> notify = mCodec->mNotify->dup(); 5499 notify->setInt32("what", CodecBase::kWhatEOS); 5500 notify->setInt32("err", mCodec->mInputEOSResult); 5501 notify->post(); 5502 5503 mCodec->mPortEOS[kPortIndexOutput] = true; 5504 } 5505 break; 5506 } 5507 5508 case FREE_BUFFERS: 5509 err = mCodec->freeBuffer(kPortIndexOutput, index); 5510 if (err != OK) { 5511 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 5512 return true; 5513 } 5514 break; 5515 5516 default: 5517 ALOGE("Invalid port mode: %d", mode); 5518 return false; 5519 } 5520 5521 return true; 5522} 5523 5524void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { 5525 IOMX::buffer_id bufferID; 5526 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID)); 5527 ssize_t index; 5528 BufferInfo *info = mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 5529 BufferInfo::Status status = BufferInfo::getSafeStatus(info); 5530 if (status != BufferInfo::OWNED_BY_DOWNSTREAM) { 5531 ALOGE("Wrong ownership in OBD: %s(%d) buffer #%u", _asString(status), status, bufferID); 5532 mCodec->dumpBuffers(kPortIndexOutput); 5533 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 5534 return; 5535 } 5536 5537 android_native_rect_t crop; 5538 if (msg->findRect("crop", &crop.left, &crop.top, &crop.right, &crop.bottom)) { 5539 status_t err = native_window_set_crop(mCodec->mNativeWindow.get(), &crop); 5540 ALOGW_IF(err != NO_ERROR, "failed to set crop: %d", err); 5541 } 5542 5543 int32_t render; 5544 if (mCodec->mNativeWindow != NULL 5545 && msg->findInt32("render", &render) && render != 0 5546 && info->mData != NULL && info->mData->size() != 0) { 5547 ATRACE_NAME("render"); 5548 // The client wants this buffer to be rendered. 5549 5550 // save buffers sent to the surface so we can get render time when they return 5551 int64_t mediaTimeUs = -1; 5552 info->mData->meta()->findInt64("timeUs", &mediaTimeUs); 5553 if (mediaTimeUs >= 0) { 5554 mCodec->mRenderTracker.onFrameQueued( 5555 mediaTimeUs, info->mGraphicBuffer, new Fence(::dup(info->mFenceFd))); 5556 } 5557 5558 int64_t timestampNs = 0; 5559 if (!msg->findInt64("timestampNs", ×tampNs)) { 5560 // use media timestamp if client did not request a specific render timestamp 5561 if (info->mData->meta()->findInt64("timeUs", ×tampNs)) { 5562 ALOGV("using buffer PTS of %lld", (long long)timestampNs); 5563 timestampNs *= 1000; 5564 } 5565 } 5566 5567 status_t err; 5568 err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs); 5569 ALOGW_IF(err != NO_ERROR, "failed to set buffer timestamp: %d", err); 5570 5571 info->checkReadFence("onOutputBufferDrained before queueBuffer"); 5572 err = mCodec->mNativeWindow->queueBuffer( 5573 mCodec->mNativeWindow.get(), info->mGraphicBuffer.get(), info->mFenceFd); 5574 info->mFenceFd = -1; 5575 if (err == OK) { 5576 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 5577 } else { 5578 ALOGE("queueBuffer failed in onOutputBufferDrained: %d", err); 5579 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 5580 info->mStatus = BufferInfo::OWNED_BY_US; 5581 // keeping read fence as write fence to avoid clobbering 5582 info->mIsReadFence = false; 5583 } 5584 } else { 5585 if (mCodec->mNativeWindow != NULL && 5586 (info->mData == NULL || info->mData->size() != 0)) { 5587 // move read fence into write fence to avoid clobbering 5588 info->mIsReadFence = false; 5589 ATRACE_NAME("frame-drop"); 5590 } 5591 info->mStatus = BufferInfo::OWNED_BY_US; 5592 } 5593 5594 PortMode mode = getPortMode(kPortIndexOutput); 5595 5596 switch (mode) { 5597 case KEEP_BUFFERS: 5598 { 5599 // XXX fishy, revisit!!! What about the FREE_BUFFERS case below? 5600 5601 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 5602 // We cannot resubmit the buffer we just rendered, dequeue 5603 // the spare instead. 5604 5605 info = mCodec->dequeueBufferFromNativeWindow(); 5606 } 5607 break; 5608 } 5609 5610 case RESUBMIT_BUFFERS: 5611 { 5612 if (!mCodec->mPortEOS[kPortIndexOutput]) { 5613 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 5614 // We cannot resubmit the buffer we just rendered, dequeue 5615 // the spare instead. 5616 5617 info = mCodec->dequeueBufferFromNativeWindow(); 5618 } 5619 5620 if (info != NULL) { 5621 ALOGV("[%s] calling fillBuffer %u", 5622 mCodec->mComponentName.c_str(), info->mBufferID); 5623 info->checkWriteFence("onOutputBufferDrained::RESUBMIT_BUFFERS"); 5624 status_t err = mCodec->mOMX->fillBuffer( 5625 mCodec->mNode, info->mBufferID, info->mFenceFd); 5626 info->mFenceFd = -1; 5627 if (err == OK) { 5628 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 5629 } else { 5630 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 5631 } 5632 } 5633 } 5634 break; 5635 } 5636 5637 case FREE_BUFFERS: 5638 { 5639 status_t err = mCodec->freeBuffer(kPortIndexOutput, index); 5640 if (err != OK) { 5641 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 5642 } 5643 break; 5644 } 5645 5646 default: 5647 ALOGE("Invalid port mode: %d", mode); 5648 return; 5649 } 5650} 5651 5652//////////////////////////////////////////////////////////////////////////////// 5653 5654ACodec::UninitializedState::UninitializedState(ACodec *codec) 5655 : BaseState(codec) { 5656} 5657 5658void ACodec::UninitializedState::stateEntered() { 5659 ALOGV("Now uninitialized"); 5660 5661 if (mDeathNotifier != NULL) { 5662 mCodec->mNodeBinder->unlinkToDeath(mDeathNotifier); 5663 mDeathNotifier.clear(); 5664 } 5665 5666 mCodec->mNativeWindow.clear(); 5667 mCodec->mNativeWindowUsageBits = 0; 5668 mCodec->mNode = 0; 5669 mCodec->mOMX.clear(); 5670 mCodec->mQuirks = 0; 5671 mCodec->mFlags = 0; 5672 mCodec->mInputMetadataType = kMetadataBufferTypeInvalid; 5673 mCodec->mOutputMetadataType = kMetadataBufferTypeInvalid; 5674 mCodec->mComponentName.clear(); 5675} 5676 5677bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) { 5678 bool handled = false; 5679 5680 switch (msg->what()) { 5681 case ACodec::kWhatSetup: 5682 { 5683 onSetup(msg); 5684 5685 handled = true; 5686 break; 5687 } 5688 5689 case ACodec::kWhatAllocateComponent: 5690 { 5691 onAllocateComponent(msg); 5692 handled = true; 5693 break; 5694 } 5695 5696 case ACodec::kWhatShutdown: 5697 { 5698 int32_t keepComponentAllocated; 5699 CHECK(msg->findInt32( 5700 "keepComponentAllocated", &keepComponentAllocated)); 5701 ALOGW_IF(keepComponentAllocated, 5702 "cannot keep component allocated on shutdown in Uninitialized state"); 5703 5704 sp<AMessage> notify = mCodec->mNotify->dup(); 5705 notify->setInt32("what", CodecBase::kWhatShutdownCompleted); 5706 notify->post(); 5707 5708 handled = true; 5709 break; 5710 } 5711 5712 case ACodec::kWhatFlush: 5713 { 5714 sp<AMessage> notify = mCodec->mNotify->dup(); 5715 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 5716 notify->post(); 5717 5718 handled = true; 5719 break; 5720 } 5721 5722 case ACodec::kWhatReleaseCodecInstance: 5723 { 5724 // nothing to do, as we have already signaled shutdown 5725 handled = true; 5726 break; 5727 } 5728 5729 default: 5730 return BaseState::onMessageReceived(msg); 5731 } 5732 5733 return handled; 5734} 5735 5736void ACodec::UninitializedState::onSetup( 5737 const sp<AMessage> &msg) { 5738 if (onAllocateComponent(msg) 5739 && mCodec->mLoadedState->onConfigureComponent(msg)) { 5740 mCodec->mLoadedState->onStart(); 5741 } 5742} 5743 5744bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) { 5745 ALOGV("onAllocateComponent"); 5746 5747 CHECK(mCodec->mNode == 0); 5748 5749 OMXClient client; 5750 if (client.connect() != OK) { 5751 mCodec->signalError(OMX_ErrorUndefined, NO_INIT); 5752 return false; 5753 } 5754 5755 sp<IOMX> omx = client.interface(); 5756 5757 sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec); 5758 5759 Vector<AString> matchingCodecs; 5760 5761 AString mime; 5762 5763 AString componentName; 5764 uint32_t quirks = 0; 5765 int32_t encoder = false; 5766 if (msg->findString("componentName", &componentName)) { 5767 sp<IMediaCodecList> list = MediaCodecList::getInstance(); 5768 if (list != NULL && list->findCodecByName(componentName.c_str()) >= 0) { 5769 matchingCodecs.add(componentName); 5770 } 5771 } else { 5772 CHECK(msg->findString("mime", &mime)); 5773 5774 if (!msg->findInt32("encoder", &encoder)) { 5775 encoder = false; 5776 } 5777 5778 MediaCodecList::findMatchingCodecs( 5779 mime.c_str(), 5780 encoder, // createEncoder 5781 0, // flags 5782 &matchingCodecs); 5783 } 5784 5785 sp<CodecObserver> observer = new CodecObserver; 5786 IOMX::node_id node = 0; 5787 5788 status_t err = NAME_NOT_FOUND; 5789 for (size_t matchIndex = 0; matchIndex < matchingCodecs.size(); 5790 ++matchIndex) { 5791 componentName = matchingCodecs[matchIndex]; 5792 quirks = MediaCodecList::getQuirksFor(componentName.c_str()); 5793 5794 pid_t tid = gettid(); 5795 int prevPriority = androidGetThreadPriority(tid); 5796 androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND); 5797 err = omx->allocateNode(componentName.c_str(), observer, &mCodec->mNodeBinder, &node); 5798 androidSetThreadPriority(tid, prevPriority); 5799 5800 if (err == OK) { 5801 break; 5802 } else { 5803 ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str()); 5804 } 5805 5806 node = 0; 5807 } 5808 5809 if (node == 0) { 5810 if (!mime.empty()) { 5811 ALOGE("Unable to instantiate a %scoder for type '%s' with err %#x.", 5812 encoder ? "en" : "de", mime.c_str(), err); 5813 } else { 5814 ALOGE("Unable to instantiate codec '%s' with err %#x.", componentName.c_str(), err); 5815 } 5816 5817 mCodec->signalError((OMX_ERRORTYPE)err, makeNoSideEffectStatus(err)); 5818 return false; 5819 } 5820 5821 mDeathNotifier = new DeathNotifier(notify); 5822 if (mCodec->mNodeBinder == NULL || 5823 mCodec->mNodeBinder->linkToDeath(mDeathNotifier) != OK) { 5824 // This was a local binder, if it dies so do we, we won't care 5825 // about any notifications in the afterlife. 5826 mDeathNotifier.clear(); 5827 } 5828 5829 notify = new AMessage(kWhatOMXMessageList, mCodec); 5830 observer->setNotificationMessage(notify); 5831 5832 mCodec->mComponentName = componentName; 5833 mCodec->mRenderTracker.setComponentName(componentName); 5834 mCodec->mFlags = 0; 5835 5836 if (componentName.endsWith(".secure")) { 5837 mCodec->mFlags |= kFlagIsSecure; 5838 mCodec->mFlags |= kFlagIsGrallocUsageProtected; 5839 mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown; 5840 } 5841 5842 mCodec->mQuirks = quirks; 5843 mCodec->mOMX = omx; 5844 mCodec->mNode = node; 5845 5846 { 5847 sp<AMessage> notify = mCodec->mNotify->dup(); 5848 notify->setInt32("what", CodecBase::kWhatComponentAllocated); 5849 notify->setString("componentName", mCodec->mComponentName.c_str()); 5850 notify->post(); 5851 } 5852 5853 mCodec->changeState(mCodec->mLoadedState); 5854 5855 return true; 5856} 5857 5858//////////////////////////////////////////////////////////////////////////////// 5859 5860ACodec::LoadedState::LoadedState(ACodec *codec) 5861 : BaseState(codec) { 5862} 5863 5864void ACodec::LoadedState::stateEntered() { 5865 ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str()); 5866 5867 mCodec->mPortEOS[kPortIndexInput] = 5868 mCodec->mPortEOS[kPortIndexOutput] = false; 5869 5870 mCodec->mInputEOSResult = OK; 5871 5872 mCodec->mDequeueCounter = 0; 5873 mCodec->mMetadataBuffersToSubmit = 0; 5874 mCodec->mRepeatFrameDelayUs = -1ll; 5875 mCodec->mInputFormat.clear(); 5876 mCodec->mOutputFormat.clear(); 5877 mCodec->mBaseOutputFormat.clear(); 5878 5879 if (mCodec->mShutdownInProgress) { 5880 bool keepComponentAllocated = mCodec->mKeepComponentAllocated; 5881 5882 mCodec->mShutdownInProgress = false; 5883 mCodec->mKeepComponentAllocated = false; 5884 5885 onShutdown(keepComponentAllocated); 5886 } 5887 mCodec->mExplicitShutdown = false; 5888 5889 mCodec->processDeferredMessages(); 5890} 5891 5892void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) { 5893 if (!keepComponentAllocated) { 5894 (void)mCodec->mOMX->freeNode(mCodec->mNode); 5895 5896 mCodec->changeState(mCodec->mUninitializedState); 5897 } 5898 5899 if (mCodec->mExplicitShutdown) { 5900 sp<AMessage> notify = mCodec->mNotify->dup(); 5901 notify->setInt32("what", CodecBase::kWhatShutdownCompleted); 5902 notify->post(); 5903 mCodec->mExplicitShutdown = false; 5904 } 5905} 5906 5907bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) { 5908 bool handled = false; 5909 5910 switch (msg->what()) { 5911 case ACodec::kWhatConfigureComponent: 5912 { 5913 onConfigureComponent(msg); 5914 handled = true; 5915 break; 5916 } 5917 5918 case ACodec::kWhatCreateInputSurface: 5919 { 5920 onCreateInputSurface(msg); 5921 handled = true; 5922 break; 5923 } 5924 5925 case ACodec::kWhatSetInputSurface: 5926 { 5927 onSetInputSurface(msg); 5928 handled = true; 5929 break; 5930 } 5931 5932 case ACodec::kWhatStart: 5933 { 5934 onStart(); 5935 handled = true; 5936 break; 5937 } 5938 5939 case ACodec::kWhatShutdown: 5940 { 5941 int32_t keepComponentAllocated; 5942 CHECK(msg->findInt32( 5943 "keepComponentAllocated", &keepComponentAllocated)); 5944 5945 mCodec->mExplicitShutdown = true; 5946 onShutdown(keepComponentAllocated); 5947 5948 handled = true; 5949 break; 5950 } 5951 5952 case ACodec::kWhatFlush: 5953 { 5954 sp<AMessage> notify = mCodec->mNotify->dup(); 5955 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 5956 notify->post(); 5957 5958 handled = true; 5959 break; 5960 } 5961 5962 default: 5963 return BaseState::onMessageReceived(msg); 5964 } 5965 5966 return handled; 5967} 5968 5969bool ACodec::LoadedState::onConfigureComponent( 5970 const sp<AMessage> &msg) { 5971 ALOGV("onConfigureComponent"); 5972 5973 CHECK(mCodec->mNode != 0); 5974 5975 status_t err = OK; 5976 AString mime; 5977 if (!msg->findString("mime", &mime)) { 5978 err = BAD_VALUE; 5979 } else { 5980 err = mCodec->configureCodec(mime.c_str(), msg); 5981 } 5982 if (err != OK) { 5983 ALOGE("[%s] configureCodec returning error %d", 5984 mCodec->mComponentName.c_str(), err); 5985 5986 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 5987 return false; 5988 } 5989 5990 { 5991 sp<AMessage> notify = mCodec->mNotify->dup(); 5992 notify->setInt32("what", CodecBase::kWhatComponentConfigured); 5993 notify->setMessage("input-format", mCodec->mInputFormat); 5994 notify->setMessage("output-format", mCodec->mOutputFormat); 5995 notify->post(); 5996 } 5997 5998 return true; 5999} 6000 6001status_t ACodec::LoadedState::setupInputSurface() { 6002 status_t err = OK; 6003 6004 if (mCodec->mRepeatFrameDelayUs > 0ll) { 6005 err = mCodec->mOMX->setInternalOption( 6006 mCodec->mNode, 6007 kPortIndexInput, 6008 IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY, 6009 &mCodec->mRepeatFrameDelayUs, 6010 sizeof(mCodec->mRepeatFrameDelayUs)); 6011 6012 if (err != OK) { 6013 ALOGE("[%s] Unable to configure option to repeat previous " 6014 "frames (err %d)", 6015 mCodec->mComponentName.c_str(), 6016 err); 6017 return err; 6018 } 6019 } 6020 6021 if (mCodec->mMaxPtsGapUs > 0ll) { 6022 err = mCodec->mOMX->setInternalOption( 6023 mCodec->mNode, 6024 kPortIndexInput, 6025 IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP, 6026 &mCodec->mMaxPtsGapUs, 6027 sizeof(mCodec->mMaxPtsGapUs)); 6028 6029 if (err != OK) { 6030 ALOGE("[%s] Unable to configure max timestamp gap (err %d)", 6031 mCodec->mComponentName.c_str(), 6032 err); 6033 return err; 6034 } 6035 } 6036 6037 if (mCodec->mMaxFps > 0) { 6038 err = mCodec->mOMX->setInternalOption( 6039 mCodec->mNode, 6040 kPortIndexInput, 6041 IOMX::INTERNAL_OPTION_MAX_FPS, 6042 &mCodec->mMaxFps, 6043 sizeof(mCodec->mMaxFps)); 6044 6045 if (err != OK) { 6046 ALOGE("[%s] Unable to configure max fps (err %d)", 6047 mCodec->mComponentName.c_str(), 6048 err); 6049 return err; 6050 } 6051 } 6052 6053 if (mCodec->mTimePerCaptureUs > 0ll 6054 && mCodec->mTimePerFrameUs > 0ll) { 6055 int64_t timeLapse[2]; 6056 timeLapse[0] = mCodec->mTimePerFrameUs; 6057 timeLapse[1] = mCodec->mTimePerCaptureUs; 6058 err = mCodec->mOMX->setInternalOption( 6059 mCodec->mNode, 6060 kPortIndexInput, 6061 IOMX::INTERNAL_OPTION_TIME_LAPSE, 6062 &timeLapse[0], 6063 sizeof(timeLapse)); 6064 6065 if (err != OK) { 6066 ALOGE("[%s] Unable to configure time lapse (err %d)", 6067 mCodec->mComponentName.c_str(), 6068 err); 6069 return err; 6070 } 6071 } 6072 6073 if (mCodec->mCreateInputBuffersSuspended) { 6074 bool suspend = true; 6075 err = mCodec->mOMX->setInternalOption( 6076 mCodec->mNode, 6077 kPortIndexInput, 6078 IOMX::INTERNAL_OPTION_SUSPEND, 6079 &suspend, 6080 sizeof(suspend)); 6081 6082 if (err != OK) { 6083 ALOGE("[%s] Unable to configure option to suspend (err %d)", 6084 mCodec->mComponentName.c_str(), 6085 err); 6086 return err; 6087 } 6088 } 6089 6090 uint32_t usageBits; 6091 if (mCodec->mOMX->getParameter( 6092 mCodec->mNode, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits, 6093 &usageBits, sizeof(usageBits)) == OK) { 6094 mCodec->mInputFormat->setInt32( 6095 "using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN)); 6096 } 6097 6098 return OK; 6099} 6100 6101void ACodec::LoadedState::onCreateInputSurface( 6102 const sp<AMessage> & /* msg */) { 6103 ALOGV("onCreateInputSurface"); 6104 6105 sp<AMessage> notify = mCodec->mNotify->dup(); 6106 notify->setInt32("what", CodecBase::kWhatInputSurfaceCreated); 6107 6108 android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN; 6109 6110 sp<IGraphicBufferProducer> bufferProducer; 6111 status_t err = mCodec->mOMX->createInputSurface( 6112 mCodec->mNode, kPortIndexInput, dataSpace, &bufferProducer, &mCodec->mInputMetadataType); 6113 6114 if (err == OK) { 6115 err = setupInputSurface(); 6116 } 6117 6118 if (err == OK) { 6119 notify->setObject("input-surface", 6120 new BufferProducerWrapper(bufferProducer)); 6121 } else { 6122 // Can't use mCodec->signalError() here -- MediaCodec won't forward 6123 // the error through because it's in the "configured" state. We 6124 // send a kWhatInputSurfaceCreated with an error value instead. 6125 ALOGE("[%s] onCreateInputSurface returning error %d", 6126 mCodec->mComponentName.c_str(), err); 6127 notify->setInt32("err", err); 6128 } 6129 notify->post(); 6130} 6131 6132void ACodec::LoadedState::onSetInputSurface( 6133 const sp<AMessage> &msg) { 6134 ALOGV("onSetInputSurface"); 6135 6136 sp<AMessage> notify = mCodec->mNotify->dup(); 6137 notify->setInt32("what", CodecBase::kWhatInputSurfaceAccepted); 6138 6139 sp<RefBase> obj; 6140 CHECK(msg->findObject("input-surface", &obj)); 6141 sp<PersistentSurface> surface = static_cast<PersistentSurface *>(obj.get()); 6142 6143 status_t err = mCodec->mOMX->setInputSurface( 6144 mCodec->mNode, kPortIndexInput, surface->getBufferConsumer(), 6145 &mCodec->mInputMetadataType); 6146 6147 if (err == OK) { 6148 err = setupInputSurface(); 6149 } 6150 6151 if (err != OK) { 6152 // Can't use mCodec->signalError() here -- MediaCodec won't forward 6153 // the error through because it's in the "configured" state. We 6154 // send a kWhatInputSurfaceAccepted with an error value instead. 6155 ALOGE("[%s] onSetInputSurface returning error %d", 6156 mCodec->mComponentName.c_str(), err); 6157 notify->setInt32("err", err); 6158 } 6159 notify->post(); 6160} 6161 6162void ACodec::LoadedState::onStart() { 6163 ALOGV("onStart"); 6164 6165 status_t err = mCodec->mOMX->sendCommand(mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle); 6166 if (err != OK) { 6167 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6168 } else { 6169 mCodec->changeState(mCodec->mLoadedToIdleState); 6170 } 6171} 6172 6173//////////////////////////////////////////////////////////////////////////////// 6174 6175ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec) 6176 : BaseState(codec) { 6177} 6178 6179void ACodec::LoadedToIdleState::stateEntered() { 6180 ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str()); 6181 6182 status_t err; 6183 if ((err = allocateBuffers()) != OK) { 6184 ALOGE("Failed to allocate buffers after transitioning to IDLE state " 6185 "(error 0x%08x)", 6186 err); 6187 6188 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6189 6190 mCodec->mOMX->sendCommand( 6191 mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded); 6192 if (mCodec->allYourBuffersAreBelongToUs(kPortIndexInput)) { 6193 mCodec->freeBuffersOnPort(kPortIndexInput); 6194 } 6195 if (mCodec->allYourBuffersAreBelongToUs(kPortIndexOutput)) { 6196 mCodec->freeBuffersOnPort(kPortIndexOutput); 6197 } 6198 6199 mCodec->changeState(mCodec->mLoadedState); 6200 } 6201} 6202 6203status_t ACodec::LoadedToIdleState::allocateBuffers() { 6204 status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput); 6205 6206 if (err != OK) { 6207 return err; 6208 } 6209 6210 return mCodec->allocateBuffersOnPort(kPortIndexOutput); 6211} 6212 6213bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) { 6214 switch (msg->what()) { 6215 case kWhatSetParameters: 6216 case kWhatShutdown: 6217 { 6218 mCodec->deferMessage(msg); 6219 return true; 6220 } 6221 6222 case kWhatSignalEndOfInputStream: 6223 { 6224 mCodec->onSignalEndOfInputStream(); 6225 return true; 6226 } 6227 6228 case kWhatResume: 6229 { 6230 // We'll be active soon enough. 6231 return true; 6232 } 6233 6234 case kWhatFlush: 6235 { 6236 // We haven't even started yet, so we're flushed alright... 6237 sp<AMessage> notify = mCodec->mNotify->dup(); 6238 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 6239 notify->post(); 6240 return true; 6241 } 6242 6243 default: 6244 return BaseState::onMessageReceived(msg); 6245 } 6246} 6247 6248bool ACodec::LoadedToIdleState::onOMXEvent( 6249 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 6250 switch (event) { 6251 case OMX_EventCmdComplete: 6252 { 6253 status_t err = OK; 6254 if (data1 != (OMX_U32)OMX_CommandStateSet 6255 || data2 != (OMX_U32)OMX_StateIdle) { 6256 ALOGE("Unexpected command completion in LoadedToIdleState: %s(%u) %s(%u)", 6257 asString((OMX_COMMANDTYPE)data1), data1, 6258 asString((OMX_STATETYPE)data2), data2); 6259 err = FAILED_TRANSACTION; 6260 } 6261 6262 if (err == OK) { 6263 err = mCodec->mOMX->sendCommand( 6264 mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting); 6265 } 6266 6267 if (err != OK) { 6268 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6269 } else { 6270 mCodec->changeState(mCodec->mIdleToExecutingState); 6271 } 6272 6273 return true; 6274 } 6275 6276 default: 6277 return BaseState::onOMXEvent(event, data1, data2); 6278 } 6279} 6280 6281//////////////////////////////////////////////////////////////////////////////// 6282 6283ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec) 6284 : BaseState(codec) { 6285} 6286 6287void ACodec::IdleToExecutingState::stateEntered() { 6288 ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str()); 6289} 6290 6291bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) { 6292 switch (msg->what()) { 6293 case kWhatSetParameters: 6294 case kWhatShutdown: 6295 { 6296 mCodec->deferMessage(msg); 6297 return true; 6298 } 6299 6300 case kWhatResume: 6301 { 6302 // We'll be active soon enough. 6303 return true; 6304 } 6305 6306 case kWhatFlush: 6307 { 6308 // We haven't even started yet, so we're flushed alright... 6309 sp<AMessage> notify = mCodec->mNotify->dup(); 6310 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 6311 notify->post(); 6312 6313 return true; 6314 } 6315 6316 case kWhatSignalEndOfInputStream: 6317 { 6318 mCodec->onSignalEndOfInputStream(); 6319 return true; 6320 } 6321 6322 default: 6323 return BaseState::onMessageReceived(msg); 6324 } 6325} 6326 6327bool ACodec::IdleToExecutingState::onOMXEvent( 6328 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 6329 switch (event) { 6330 case OMX_EventCmdComplete: 6331 { 6332 if (data1 != (OMX_U32)OMX_CommandStateSet 6333 || data2 != (OMX_U32)OMX_StateExecuting) { 6334 ALOGE("Unexpected command completion in IdleToExecutingState: %s(%u) %s(%u)", 6335 asString((OMX_COMMANDTYPE)data1), data1, 6336 asString((OMX_STATETYPE)data2), data2); 6337 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6338 return true; 6339 } 6340 6341 mCodec->mExecutingState->resume(); 6342 mCodec->changeState(mCodec->mExecutingState); 6343 6344 return true; 6345 } 6346 6347 default: 6348 return BaseState::onOMXEvent(event, data1, data2); 6349 } 6350} 6351 6352//////////////////////////////////////////////////////////////////////////////// 6353 6354ACodec::ExecutingState::ExecutingState(ACodec *codec) 6355 : BaseState(codec), 6356 mActive(false) { 6357} 6358 6359ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode( 6360 OMX_U32 /* portIndex */) { 6361 return RESUBMIT_BUFFERS; 6362} 6363 6364void ACodec::ExecutingState::submitOutputMetaBuffers() { 6365 // submit as many buffers as there are input buffers with the codec 6366 // in case we are in port reconfiguring 6367 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 6368 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 6369 6370 if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) { 6371 if (mCodec->submitOutputMetadataBuffer() != OK) 6372 break; 6373 } 6374 } 6375 6376 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** 6377 mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround(); 6378} 6379 6380void ACodec::ExecutingState::submitRegularOutputBuffers() { 6381 bool failed = false; 6382 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) { 6383 BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i); 6384 6385 if (mCodec->mNativeWindow != NULL) { 6386 if (info->mStatus != BufferInfo::OWNED_BY_US 6387 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) { 6388 ALOGE("buffers should be owned by us or the surface"); 6389 failed = true; 6390 break; 6391 } 6392 6393 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 6394 continue; 6395 } 6396 } else { 6397 if (info->mStatus != BufferInfo::OWNED_BY_US) { 6398 ALOGE("buffers should be owned by us"); 6399 failed = true; 6400 break; 6401 } 6402 } 6403 6404 ALOGV("[%s] calling fillBuffer %u", mCodec->mComponentName.c_str(), info->mBufferID); 6405 6406 info->checkWriteFence("submitRegularOutputBuffers"); 6407 status_t err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID, info->mFenceFd); 6408 info->mFenceFd = -1; 6409 if (err != OK) { 6410 failed = true; 6411 break; 6412 } 6413 6414 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 6415 } 6416 6417 if (failed) { 6418 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6419 } 6420} 6421 6422void ACodec::ExecutingState::submitOutputBuffers() { 6423 submitRegularOutputBuffers(); 6424 if (mCodec->storingMetadataInDecodedBuffers()) { 6425 submitOutputMetaBuffers(); 6426 } 6427} 6428 6429void ACodec::ExecutingState::resume() { 6430 if (mActive) { 6431 ALOGV("[%s] We're already active, no need to resume.", mCodec->mComponentName.c_str()); 6432 return; 6433 } 6434 6435 submitOutputBuffers(); 6436 6437 // Post all available input buffers 6438 if (mCodec->mBuffers[kPortIndexInput].size() == 0u) { 6439 ALOGW("[%s] we don't have any input buffers to resume", mCodec->mComponentName.c_str()); 6440 } 6441 6442 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) { 6443 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 6444 if (info->mStatus == BufferInfo::OWNED_BY_US) { 6445 postFillThisBuffer(info); 6446 } 6447 } 6448 6449 mActive = true; 6450} 6451 6452void ACodec::ExecutingState::stateEntered() { 6453 ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str()); 6454 6455 mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC)); 6456 mCodec->processDeferredMessages(); 6457} 6458 6459bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) { 6460 bool handled = false; 6461 6462 switch (msg->what()) { 6463 case kWhatShutdown: 6464 { 6465 int32_t keepComponentAllocated; 6466 CHECK(msg->findInt32( 6467 "keepComponentAllocated", &keepComponentAllocated)); 6468 6469 mCodec->mShutdownInProgress = true; 6470 mCodec->mExplicitShutdown = true; 6471 mCodec->mKeepComponentAllocated = keepComponentAllocated; 6472 6473 mActive = false; 6474 6475 status_t err = mCodec->mOMX->sendCommand( 6476 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle); 6477 if (err != OK) { 6478 if (keepComponentAllocated) { 6479 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6480 } 6481 // TODO: do some recovery here. 6482 } else { 6483 mCodec->changeState(mCodec->mExecutingToIdleState); 6484 } 6485 6486 handled = true; 6487 break; 6488 } 6489 6490 case kWhatFlush: 6491 { 6492 ALOGV("[%s] ExecutingState flushing now " 6493 "(codec owns %zu/%zu input, %zu/%zu output).", 6494 mCodec->mComponentName.c_str(), 6495 mCodec->countBuffersOwnedByComponent(kPortIndexInput), 6496 mCodec->mBuffers[kPortIndexInput].size(), 6497 mCodec->countBuffersOwnedByComponent(kPortIndexOutput), 6498 mCodec->mBuffers[kPortIndexOutput].size()); 6499 6500 mActive = false; 6501 6502 status_t err = mCodec->mOMX->sendCommand(mCodec->mNode, OMX_CommandFlush, OMX_ALL); 6503 if (err != OK) { 6504 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6505 } else { 6506 mCodec->changeState(mCodec->mFlushingState); 6507 } 6508 6509 handled = true; 6510 break; 6511 } 6512 6513 case kWhatResume: 6514 { 6515 resume(); 6516 6517 handled = true; 6518 break; 6519 } 6520 6521 case kWhatRequestIDRFrame: 6522 { 6523 status_t err = mCodec->requestIDRFrame(); 6524 if (err != OK) { 6525 ALOGW("Requesting an IDR frame failed."); 6526 } 6527 6528 handled = true; 6529 break; 6530 } 6531 6532 case kWhatSetParameters: 6533 { 6534 sp<AMessage> params; 6535 CHECK(msg->findMessage("params", ¶ms)); 6536 6537 status_t err = mCodec->setParameters(params); 6538 6539 sp<AMessage> reply; 6540 if (msg->findMessage("reply", &reply)) { 6541 reply->setInt32("err", err); 6542 reply->post(); 6543 } 6544 6545 handled = true; 6546 break; 6547 } 6548 6549 case ACodec::kWhatSignalEndOfInputStream: 6550 { 6551 mCodec->onSignalEndOfInputStream(); 6552 handled = true; 6553 break; 6554 } 6555 6556 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** 6557 case kWhatSubmitOutputMetadataBufferIfEOS: 6558 { 6559 if (mCodec->mPortEOS[kPortIndexInput] && 6560 !mCodec->mPortEOS[kPortIndexOutput]) { 6561 status_t err = mCodec->submitOutputMetadataBuffer(); 6562 if (err == OK) { 6563 mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround(); 6564 } 6565 } 6566 return true; 6567 } 6568 6569 default: 6570 handled = BaseState::onMessageReceived(msg); 6571 break; 6572 } 6573 6574 return handled; 6575} 6576 6577status_t ACodec::setParameters(const sp<AMessage> ¶ms) { 6578 int32_t videoBitrate; 6579 if (params->findInt32("video-bitrate", &videoBitrate)) { 6580 OMX_VIDEO_CONFIG_BITRATETYPE configParams; 6581 InitOMXParams(&configParams); 6582 configParams.nPortIndex = kPortIndexOutput; 6583 configParams.nEncodeBitrate = videoBitrate; 6584 6585 status_t err = mOMX->setConfig( 6586 mNode, 6587 OMX_IndexConfigVideoBitrate, 6588 &configParams, 6589 sizeof(configParams)); 6590 6591 if (err != OK) { 6592 ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d", 6593 videoBitrate, err); 6594 6595 return err; 6596 } 6597 } 6598 6599 int64_t skipFramesBeforeUs; 6600 if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) { 6601 status_t err = 6602 mOMX->setInternalOption( 6603 mNode, 6604 kPortIndexInput, 6605 IOMX::INTERNAL_OPTION_START_TIME, 6606 &skipFramesBeforeUs, 6607 sizeof(skipFramesBeforeUs)); 6608 6609 if (err != OK) { 6610 ALOGE("Failed to set parameter 'skip-frames-before' (err %d)", err); 6611 return err; 6612 } 6613 } 6614 6615 int32_t dropInputFrames; 6616 if (params->findInt32("drop-input-frames", &dropInputFrames)) { 6617 bool suspend = dropInputFrames != 0; 6618 6619 status_t err = 6620 mOMX->setInternalOption( 6621 mNode, 6622 kPortIndexInput, 6623 IOMX::INTERNAL_OPTION_SUSPEND, 6624 &suspend, 6625 sizeof(suspend)); 6626 6627 if (err != OK) { 6628 ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err); 6629 return err; 6630 } 6631 } 6632 6633 int32_t dummy; 6634 if (params->findInt32("request-sync", &dummy)) { 6635 status_t err = requestIDRFrame(); 6636 6637 if (err != OK) { 6638 ALOGE("Requesting a sync frame failed w/ err %d", err); 6639 return err; 6640 } 6641 } 6642 6643 float rate; 6644 if (params->findFloat("operating-rate", &rate) && rate > 0) { 6645 status_t err = setOperatingRate(rate, mIsVideo); 6646 if (err != OK) { 6647 ALOGE("Failed to set parameter 'operating-rate' (err %d)", err); 6648 return err; 6649 } 6650 } 6651 6652 int32_t intraRefreshPeriod = 0; 6653 if (params->findInt32("intra-refresh-period", &intraRefreshPeriod) 6654 && intraRefreshPeriod > 0) { 6655 status_t err = setIntraRefreshPeriod(intraRefreshPeriod, false); 6656 if (err != OK) { 6657 ALOGI("[%s] failed setIntraRefreshPeriod. Failure is fine since this key is optional", 6658 mComponentName.c_str()); 6659 err = OK; 6660 } 6661 } 6662 6663 return OK; 6664} 6665 6666void ACodec::onSignalEndOfInputStream() { 6667 sp<AMessage> notify = mNotify->dup(); 6668 notify->setInt32("what", CodecBase::kWhatSignaledInputEOS); 6669 6670 status_t err = mOMX->signalEndOfInputStream(mNode); 6671 if (err != OK) { 6672 notify->setInt32("err", err); 6673 } 6674 notify->post(); 6675} 6676 6677bool ACodec::ExecutingState::onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) { 6678 mCodec->onFrameRendered(mediaTimeUs, systemNano); 6679 return true; 6680} 6681 6682bool ACodec::ExecutingState::onOMXEvent( 6683 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 6684 switch (event) { 6685 case OMX_EventPortSettingsChanged: 6686 { 6687 CHECK_EQ(data1, (OMX_U32)kPortIndexOutput); 6688 6689 if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) { 6690 mCodec->mMetadataBuffersToSubmit = 0; 6691 CHECK_EQ(mCodec->mOMX->sendCommand( 6692 mCodec->mNode, 6693 OMX_CommandPortDisable, kPortIndexOutput), 6694 (status_t)OK); 6695 6696 mCodec->freeOutputBuffersNotOwnedByComponent(); 6697 6698 mCodec->changeState(mCodec->mOutputPortSettingsChangedState); 6699 } else if (data2 == OMX_IndexConfigCommonOutputCrop 6700 || data2 == OMX_IndexConfigAndroidIntraRefresh) { 6701 mCodec->mSentFormat = false; 6702 6703 if (mCodec->mTunneled) { 6704 sp<AMessage> dummy = new AMessage(kWhatOutputBufferDrained, mCodec); 6705 mCodec->sendFormatChange(dummy); 6706 } 6707 } else { 6708 ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08x", 6709 mCodec->mComponentName.c_str(), data2); 6710 } 6711 6712 return true; 6713 } 6714 6715 case OMX_EventBufferFlag: 6716 { 6717 return true; 6718 } 6719 6720 default: 6721 return BaseState::onOMXEvent(event, data1, data2); 6722 } 6723} 6724 6725//////////////////////////////////////////////////////////////////////////////// 6726 6727ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState( 6728 ACodec *codec) 6729 : BaseState(codec) { 6730} 6731 6732ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode( 6733 OMX_U32 portIndex) { 6734 if (portIndex == kPortIndexOutput) { 6735 return FREE_BUFFERS; 6736 } 6737 6738 CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput); 6739 6740 return RESUBMIT_BUFFERS; 6741} 6742 6743bool ACodec::OutputPortSettingsChangedState::onMessageReceived( 6744 const sp<AMessage> &msg) { 6745 bool handled = false; 6746 6747 switch (msg->what()) { 6748 case kWhatFlush: 6749 case kWhatShutdown: 6750 case kWhatResume: 6751 case kWhatSetParameters: 6752 { 6753 if (msg->what() == kWhatResume) { 6754 ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str()); 6755 } 6756 6757 mCodec->deferMessage(msg); 6758 handled = true; 6759 break; 6760 } 6761 6762 default: 6763 handled = BaseState::onMessageReceived(msg); 6764 break; 6765 } 6766 6767 return handled; 6768} 6769 6770void ACodec::OutputPortSettingsChangedState::stateEntered() { 6771 ALOGV("[%s] Now handling output port settings change", 6772 mCodec->mComponentName.c_str()); 6773} 6774 6775bool ACodec::OutputPortSettingsChangedState::onOMXFrameRendered( 6776 int64_t mediaTimeUs, nsecs_t systemNano) { 6777 mCodec->onFrameRendered(mediaTimeUs, systemNano); 6778 return true; 6779} 6780 6781bool ACodec::OutputPortSettingsChangedState::onOMXEvent( 6782 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 6783 switch (event) { 6784 case OMX_EventCmdComplete: 6785 { 6786 if (data1 == (OMX_U32)OMX_CommandPortDisable) { 6787 if (data2 != (OMX_U32)kPortIndexOutput) { 6788 ALOGW("ignoring EventCmdComplete CommandPortDisable for port %u", data2); 6789 return false; 6790 } 6791 6792 ALOGV("[%s] Output port now disabled.", mCodec->mComponentName.c_str()); 6793 6794 status_t err = OK; 6795 if (!mCodec->mBuffers[kPortIndexOutput].isEmpty()) { 6796 ALOGE("disabled port should be empty, but has %zu buffers", 6797 mCodec->mBuffers[kPortIndexOutput].size()); 6798 err = FAILED_TRANSACTION; 6799 } else { 6800 mCodec->mDealer[kPortIndexOutput].clear(); 6801 } 6802 6803 if (err == OK) { 6804 err = mCodec->mOMX->sendCommand( 6805 mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput); 6806 } 6807 6808 if (err == OK) { 6809 err = mCodec->allocateBuffersOnPort(kPortIndexOutput); 6810 ALOGE_IF(err != OK, "Failed to allocate output port buffers after port " 6811 "reconfiguration: (%d)", err); 6812 } 6813 6814 if (err != OK) { 6815 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6816 6817 // This is technically not correct, but appears to be 6818 // the only way to free the component instance. 6819 // Controlled transitioning from excecuting->idle 6820 // and idle->loaded seem impossible probably because 6821 // the output port never finishes re-enabling. 6822 mCodec->mShutdownInProgress = true; 6823 mCodec->mKeepComponentAllocated = false; 6824 mCodec->changeState(mCodec->mLoadedState); 6825 } 6826 6827 return true; 6828 } else if (data1 == (OMX_U32)OMX_CommandPortEnable) { 6829 if (data2 != (OMX_U32)kPortIndexOutput) { 6830 ALOGW("ignoring EventCmdComplete OMX_CommandPortEnable for port %u", data2); 6831 return false; 6832 } 6833 6834 mCodec->mSentFormat = false; 6835 6836 if (mCodec->mTunneled) { 6837 sp<AMessage> dummy = new AMessage(kWhatOutputBufferDrained, mCodec); 6838 mCodec->sendFormatChange(dummy); 6839 } 6840 6841 ALOGV("[%s] Output port now reenabled.", mCodec->mComponentName.c_str()); 6842 6843 if (mCodec->mExecutingState->active()) { 6844 mCodec->mExecutingState->submitOutputBuffers(); 6845 } 6846 6847 mCodec->changeState(mCodec->mExecutingState); 6848 6849 return true; 6850 } 6851 6852 return false; 6853 } 6854 6855 default: 6856 return false; 6857 } 6858} 6859 6860//////////////////////////////////////////////////////////////////////////////// 6861 6862ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec) 6863 : BaseState(codec), 6864 mComponentNowIdle(false) { 6865} 6866 6867bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) { 6868 bool handled = false; 6869 6870 switch (msg->what()) { 6871 case kWhatFlush: 6872 { 6873 // Don't send me a flush request if you previously wanted me 6874 // to shutdown. 6875 ALOGW("Ignoring flush request in ExecutingToIdleState"); 6876 break; 6877 } 6878 6879 case kWhatShutdown: 6880 { 6881 // We're already doing that... 6882 6883 handled = true; 6884 break; 6885 } 6886 6887 default: 6888 handled = BaseState::onMessageReceived(msg); 6889 break; 6890 } 6891 6892 return handled; 6893} 6894 6895void ACodec::ExecutingToIdleState::stateEntered() { 6896 ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str()); 6897 6898 mComponentNowIdle = false; 6899 mCodec->mSentFormat = false; 6900} 6901 6902bool ACodec::ExecutingToIdleState::onOMXEvent( 6903 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 6904 switch (event) { 6905 case OMX_EventCmdComplete: 6906 { 6907 if (data1 != (OMX_U32)OMX_CommandStateSet 6908 || data2 != (OMX_U32)OMX_StateIdle) { 6909 ALOGE("Unexpected command completion in ExecutingToIdleState: %s(%u) %s(%u)", 6910 asString((OMX_COMMANDTYPE)data1), data1, 6911 asString((OMX_STATETYPE)data2), data2); 6912 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6913 return true; 6914 } 6915 6916 mComponentNowIdle = true; 6917 6918 changeStateIfWeOwnAllBuffers(); 6919 6920 return true; 6921 } 6922 6923 case OMX_EventPortSettingsChanged: 6924 case OMX_EventBufferFlag: 6925 { 6926 // We're shutting down and don't care about this anymore. 6927 return true; 6928 } 6929 6930 default: 6931 return BaseState::onOMXEvent(event, data1, data2); 6932 } 6933} 6934 6935void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() { 6936 if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) { 6937 status_t err = mCodec->mOMX->sendCommand( 6938 mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded); 6939 if (err == OK) { 6940 err = mCodec->freeBuffersOnPort(kPortIndexInput); 6941 status_t err2 = mCodec->freeBuffersOnPort(kPortIndexOutput); 6942 if (err == OK) { 6943 err = err2; 6944 } 6945 } 6946 6947 if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown) 6948 && mCodec->mNativeWindow != NULL) { 6949 // We push enough 1x1 blank buffers to ensure that one of 6950 // them has made it to the display. This allows the OMX 6951 // component teardown to zero out any protected buffers 6952 // without the risk of scanning out one of those buffers. 6953 pushBlankBuffersToNativeWindow(mCodec->mNativeWindow.get()); 6954 } 6955 6956 if (err != OK) { 6957 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6958 return; 6959 } 6960 6961 mCodec->changeState(mCodec->mIdleToLoadedState); 6962 } 6963} 6964 6965void ACodec::ExecutingToIdleState::onInputBufferFilled( 6966 const sp<AMessage> &msg) { 6967 BaseState::onInputBufferFilled(msg); 6968 6969 changeStateIfWeOwnAllBuffers(); 6970} 6971 6972void ACodec::ExecutingToIdleState::onOutputBufferDrained( 6973 const sp<AMessage> &msg) { 6974 BaseState::onOutputBufferDrained(msg); 6975 6976 changeStateIfWeOwnAllBuffers(); 6977} 6978 6979//////////////////////////////////////////////////////////////////////////////// 6980 6981ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec) 6982 : BaseState(codec) { 6983} 6984 6985bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) { 6986 bool handled = false; 6987 6988 switch (msg->what()) { 6989 case kWhatShutdown: 6990 { 6991 // We're already doing that... 6992 6993 handled = true; 6994 break; 6995 } 6996 6997 case kWhatFlush: 6998 { 6999 // Don't send me a flush request if you previously wanted me 7000 // to shutdown. 7001 ALOGE("Got flush request in IdleToLoadedState"); 7002 break; 7003 } 7004 7005 default: 7006 handled = BaseState::onMessageReceived(msg); 7007 break; 7008 } 7009 7010 return handled; 7011} 7012 7013void ACodec::IdleToLoadedState::stateEntered() { 7014 ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str()); 7015} 7016 7017bool ACodec::IdleToLoadedState::onOMXEvent( 7018 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 7019 switch (event) { 7020 case OMX_EventCmdComplete: 7021 { 7022 if (data1 != (OMX_U32)OMX_CommandStateSet 7023 || data2 != (OMX_U32)OMX_StateLoaded) { 7024 ALOGE("Unexpected command completion in IdleToLoadedState: %s(%u) %s(%u)", 7025 asString((OMX_COMMANDTYPE)data1), data1, 7026 asString((OMX_STATETYPE)data2), data2); 7027 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 7028 return true; 7029 } 7030 7031 mCodec->changeState(mCodec->mLoadedState); 7032 7033 return true; 7034 } 7035 7036 default: 7037 return BaseState::onOMXEvent(event, data1, data2); 7038 } 7039} 7040 7041//////////////////////////////////////////////////////////////////////////////// 7042 7043ACodec::FlushingState::FlushingState(ACodec *codec) 7044 : BaseState(codec) { 7045} 7046 7047void ACodec::FlushingState::stateEntered() { 7048 ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str()); 7049 7050 mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false; 7051} 7052 7053bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) { 7054 bool handled = false; 7055 7056 switch (msg->what()) { 7057 case kWhatShutdown: 7058 { 7059 mCodec->deferMessage(msg); 7060 break; 7061 } 7062 7063 case kWhatFlush: 7064 { 7065 // We're already doing this right now. 7066 handled = true; 7067 break; 7068 } 7069 7070 default: 7071 handled = BaseState::onMessageReceived(msg); 7072 break; 7073 } 7074 7075 return handled; 7076} 7077 7078bool ACodec::FlushingState::onOMXEvent( 7079 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 7080 ALOGV("[%s] FlushingState onOMXEvent(%u,%d)", 7081 mCodec->mComponentName.c_str(), event, (OMX_S32)data1); 7082 7083 switch (event) { 7084 case OMX_EventCmdComplete: 7085 { 7086 if (data1 != (OMX_U32)OMX_CommandFlush) { 7087 ALOGE("unexpected EventCmdComplete %s(%d) data2:%d in FlushingState", 7088 asString((OMX_COMMANDTYPE)data1), data1, data2); 7089 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 7090 return true; 7091 } 7092 7093 if (data2 == kPortIndexInput || data2 == kPortIndexOutput) { 7094 if (mFlushComplete[data2]) { 7095 ALOGW("Flush already completed for %s port", 7096 data2 == kPortIndexInput ? "input" : "output"); 7097 return true; 7098 } 7099 mFlushComplete[data2] = true; 7100 7101 if (mFlushComplete[kPortIndexInput] && mFlushComplete[kPortIndexOutput]) { 7102 changeStateIfWeOwnAllBuffers(); 7103 } 7104 } else if (data2 == OMX_ALL) { 7105 if (!mFlushComplete[kPortIndexInput] || !mFlushComplete[kPortIndexOutput]) { 7106 ALOGW("received flush complete event for OMX_ALL before ports have been" 7107 "flushed (%d/%d)", 7108 mFlushComplete[kPortIndexInput], mFlushComplete[kPortIndexOutput]); 7109 return false; 7110 } 7111 7112 changeStateIfWeOwnAllBuffers(); 7113 } else { 7114 ALOGW("data2 not OMX_ALL but %u in EventCmdComplete CommandFlush", data2); 7115 } 7116 7117 return true; 7118 } 7119 7120 case OMX_EventPortSettingsChanged: 7121 { 7122 sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec); 7123 msg->setInt32("type", omx_message::EVENT); 7124 msg->setInt32("node", mCodec->mNode); 7125 msg->setInt32("event", event); 7126 msg->setInt32("data1", data1); 7127 msg->setInt32("data2", data2); 7128 7129 ALOGV("[%s] Deferring OMX_EventPortSettingsChanged", 7130 mCodec->mComponentName.c_str()); 7131 7132 mCodec->deferMessage(msg); 7133 7134 return true; 7135 } 7136 7137 default: 7138 return BaseState::onOMXEvent(event, data1, data2); 7139 } 7140 7141 return true; 7142} 7143 7144void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) { 7145 BaseState::onOutputBufferDrained(msg); 7146 7147 changeStateIfWeOwnAllBuffers(); 7148} 7149 7150void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) { 7151 BaseState::onInputBufferFilled(msg); 7152 7153 changeStateIfWeOwnAllBuffers(); 7154} 7155 7156void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() { 7157 if (mFlushComplete[kPortIndexInput] 7158 && mFlushComplete[kPortIndexOutput] 7159 && mCodec->allYourBuffersAreBelongToUs()) { 7160 // We now own all buffers except possibly those still queued with 7161 // the native window for rendering. Let's get those back as well. 7162 mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs(); 7163 7164 mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC)); 7165 7166 sp<AMessage> notify = mCodec->mNotify->dup(); 7167 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 7168 notify->post(); 7169 7170 mCodec->mPortEOS[kPortIndexInput] = 7171 mCodec->mPortEOS[kPortIndexOutput] = false; 7172 7173 mCodec->mInputEOSResult = OK; 7174 7175 if (mCodec->mSkipCutBuffer != NULL) { 7176 mCodec->mSkipCutBuffer->clear(); 7177 } 7178 7179 mCodec->changeState(mCodec->mExecutingState); 7180 } 7181} 7182 7183status_t ACodec::queryCapabilities( 7184 const AString &name, const AString &mime, bool isEncoder, 7185 sp<MediaCodecInfo::Capabilities> *caps) { 7186 (*caps).clear(); 7187 const char *role = getComponentRole(isEncoder, mime.c_str()); 7188 if (role == NULL) { 7189 return BAD_VALUE; 7190 } 7191 7192 OMXClient client; 7193 status_t err = client.connect(); 7194 if (err != OK) { 7195 return err; 7196 } 7197 7198 sp<IOMX> omx = client.interface(); 7199 sp<CodecObserver> observer = new CodecObserver; 7200 IOMX::node_id node = 0; 7201 7202 err = omx->allocateNode(name.c_str(), observer, NULL, &node); 7203 if (err != OK) { 7204 client.disconnect(); 7205 return err; 7206 } 7207 7208 err = setComponentRole(omx, node, role); 7209 if (err != OK) { 7210 omx->freeNode(node); 7211 client.disconnect(); 7212 return err; 7213 } 7214 7215 sp<MediaCodecInfo::CapabilitiesBuilder> builder = new MediaCodecInfo::CapabilitiesBuilder(); 7216 bool isVideo = mime.startsWithIgnoreCase("video/"); 7217 7218 if (isVideo) { 7219 OMX_VIDEO_PARAM_PROFILELEVELTYPE param; 7220 InitOMXParams(¶m); 7221 param.nPortIndex = isEncoder ? kPortIndexOutput : kPortIndexInput; 7222 7223 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { 7224 param.nProfileIndex = index; 7225 status_t err = omx->getParameter( 7226 node, OMX_IndexParamVideoProfileLevelQuerySupported, 7227 ¶m, sizeof(param)); 7228 if (err != OK) { 7229 break; 7230 } 7231 builder->addProfileLevel(param.eProfile, param.eLevel); 7232 7233 if (index == kMaxIndicesToCheck) { 7234 ALOGW("[%s] stopping checking profiles after %u: %x/%x", 7235 name.c_str(), index, 7236 param.eProfile, param.eLevel); 7237 } 7238 } 7239 7240 // Color format query 7241 // return colors in the order reported by the OMX component 7242 // prefix "flexible" standard ones with the flexible equivalent 7243 OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat; 7244 InitOMXParams(&portFormat); 7245 portFormat.nPortIndex = isEncoder ? kPortIndexInput : kPortIndexOutput; 7246 Vector<uint32_t> supportedColors; // shadow copy to check for duplicates 7247 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { 7248 portFormat.nIndex = index; 7249 status_t err = omx->getParameter( 7250 node, OMX_IndexParamVideoPortFormat, 7251 &portFormat, sizeof(portFormat)); 7252 if (err != OK) { 7253 break; 7254 } 7255 7256 OMX_U32 flexibleEquivalent; 7257 if (isFlexibleColorFormat( 7258 omx, node, portFormat.eColorFormat, false /* usingNativeWindow */, 7259 &flexibleEquivalent)) { 7260 bool marked = false; 7261 for (size_t i = 0; i < supportedColors.size(); ++i) { 7262 if (supportedColors[i] == flexibleEquivalent) { 7263 marked = true; 7264 break; 7265 } 7266 } 7267 if (!marked) { 7268 supportedColors.push(flexibleEquivalent); 7269 builder->addColorFormat(flexibleEquivalent); 7270 } 7271 } 7272 supportedColors.push(portFormat.eColorFormat); 7273 builder->addColorFormat(portFormat.eColorFormat); 7274 7275 if (index == kMaxIndicesToCheck) { 7276 ALOGW("[%s] stopping checking formats after %u: %s(%x)", 7277 name.c_str(), index, 7278 asString(portFormat.eColorFormat), portFormat.eColorFormat); 7279 } 7280 } 7281 } else if (mime.equalsIgnoreCase(MEDIA_MIMETYPE_AUDIO_AAC)) { 7282 // More audio codecs if they have profiles. 7283 OMX_AUDIO_PARAM_ANDROID_PROFILETYPE param; 7284 InitOMXParams(¶m); 7285 param.nPortIndex = isEncoder ? kPortIndexOutput : kPortIndexInput; 7286 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { 7287 param.nProfileIndex = index; 7288 status_t err = omx->getParameter( 7289 node, (OMX_INDEXTYPE)OMX_IndexParamAudioProfileQuerySupported, 7290 ¶m, sizeof(param)); 7291 if (err != OK) { 7292 break; 7293 } 7294 // For audio, level is ignored. 7295 builder->addProfileLevel(param.eProfile, 0 /* level */); 7296 7297 if (index == kMaxIndicesToCheck) { 7298 ALOGW("[%s] stopping checking profiles after %u: %x", 7299 name.c_str(), index, 7300 param.eProfile); 7301 } 7302 } 7303 7304 // NOTE: Without Android extensions, OMX does not provide a way to query 7305 // AAC profile support 7306 if (param.nProfileIndex == 0) { 7307 ALOGW("component %s doesn't support profile query.", name.c_str()); 7308 } 7309 } 7310 7311 if (isVideo && !isEncoder) { 7312 native_handle_t *sidebandHandle = NULL; 7313 if (omx->configureVideoTunnelMode( 7314 node, kPortIndexOutput, OMX_TRUE, 0, &sidebandHandle) == OK) { 7315 // tunneled playback includes adaptive playback 7316 builder->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback 7317 | MediaCodecInfo::Capabilities::kFlagSupportsTunneledPlayback); 7318 } else if (omx->storeMetaDataInBuffers( 7319 node, kPortIndexOutput, OMX_TRUE) == OK || 7320 omx->prepareForAdaptivePlayback( 7321 node, kPortIndexOutput, OMX_TRUE, 7322 1280 /* width */, 720 /* height */) == OK) { 7323 builder->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback); 7324 } 7325 } 7326 7327 if (isVideo && isEncoder) { 7328 OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params; 7329 InitOMXParams(¶ms); 7330 params.nPortIndex = kPortIndexOutput; 7331 // TODO: should we verify if fallback is supported? 7332 if (omx->getConfig( 7333 node, (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, 7334 ¶ms, sizeof(params)) == OK) { 7335 builder->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsIntraRefresh); 7336 } 7337 } 7338 7339 *caps = builder; 7340 omx->freeNode(node); 7341 client.disconnect(); 7342 return OK; 7343} 7344 7345// These are supposed be equivalent to the logic in 7346// "audio_channel_out_mask_from_count". 7347//static 7348status_t ACodec::getOMXChannelMapping(size_t numChannels, OMX_AUDIO_CHANNELTYPE map[]) { 7349 switch (numChannels) { 7350 case 1: 7351 map[0] = OMX_AUDIO_ChannelCF; 7352 break; 7353 case 2: 7354 map[0] = OMX_AUDIO_ChannelLF; 7355 map[1] = OMX_AUDIO_ChannelRF; 7356 break; 7357 case 3: 7358 map[0] = OMX_AUDIO_ChannelLF; 7359 map[1] = OMX_AUDIO_ChannelRF; 7360 map[2] = OMX_AUDIO_ChannelCF; 7361 break; 7362 case 4: 7363 map[0] = OMX_AUDIO_ChannelLF; 7364 map[1] = OMX_AUDIO_ChannelRF; 7365 map[2] = OMX_AUDIO_ChannelLR; 7366 map[3] = OMX_AUDIO_ChannelRR; 7367 break; 7368 case 5: 7369 map[0] = OMX_AUDIO_ChannelLF; 7370 map[1] = OMX_AUDIO_ChannelRF; 7371 map[2] = OMX_AUDIO_ChannelCF; 7372 map[3] = OMX_AUDIO_ChannelLR; 7373 map[4] = OMX_AUDIO_ChannelRR; 7374 break; 7375 case 6: 7376 map[0] = OMX_AUDIO_ChannelLF; 7377 map[1] = OMX_AUDIO_ChannelRF; 7378 map[2] = OMX_AUDIO_ChannelCF; 7379 map[3] = OMX_AUDIO_ChannelLFE; 7380 map[4] = OMX_AUDIO_ChannelLR; 7381 map[5] = OMX_AUDIO_ChannelRR; 7382 break; 7383 case 7: 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 map[6] = OMX_AUDIO_ChannelCS; 7391 break; 7392 case 8: 7393 map[0] = OMX_AUDIO_ChannelLF; 7394 map[1] = OMX_AUDIO_ChannelRF; 7395 map[2] = OMX_AUDIO_ChannelCF; 7396 map[3] = OMX_AUDIO_ChannelLFE; 7397 map[4] = OMX_AUDIO_ChannelLR; 7398 map[5] = OMX_AUDIO_ChannelRR; 7399 map[6] = OMX_AUDIO_ChannelLS; 7400 map[7] = OMX_AUDIO_ChannelRS; 7401 break; 7402 default: 7403 return -EINVAL; 7404 } 7405 7406 return OK; 7407} 7408 7409} // namespace android 7410