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