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