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