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