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