ACodec.cpp revision e9e63bcf6c36351f1129b0bdc5e93f17f0f9f0b4
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 int32_t width, height; 1271 if (!msg->findInt32("width", &width) 1272 || !msg->findInt32("height", &height)) { 1273 err = INVALID_OPERATION; 1274 } else { 1275 err = setupVideoDecoder(mime, width, height); 1276 } 1277 } 1278 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) { 1279 int32_t numChannels, sampleRate; 1280 if (!msg->findInt32("channel-count", &numChannels) 1281 || !msg->findInt32("sample-rate", &sampleRate)) { 1282 // Since we did not always check for these, leave them optional 1283 // and have the decoder figure it all out. 1284 err = OK; 1285 } else { 1286 err = setupRawAudioFormat( 1287 encoder ? kPortIndexInput : kPortIndexOutput, 1288 sampleRate, 1289 numChannels); 1290 } 1291 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 1292 int32_t numChannels, sampleRate; 1293 if (!msg->findInt32("channel-count", &numChannels) 1294 || !msg->findInt32("sample-rate", &sampleRate)) { 1295 err = INVALID_OPERATION; 1296 } else { 1297 int32_t isADTS, aacProfile; 1298 if (!msg->findInt32("is-adts", &isADTS)) { 1299 isADTS = 0; 1300 } 1301 if (!msg->findInt32("aac-profile", &aacProfile)) { 1302 aacProfile = OMX_AUDIO_AACObjectNull; 1303 } 1304 1305 err = setupAACCodec( 1306 encoder, numChannels, sampleRate, bitRate, aacProfile, 1307 isADTS != 0); 1308 } 1309 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) { 1310 err = setupAMRCodec(encoder, false /* isWAMR */, bitRate); 1311 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) { 1312 err = setupAMRCodec(encoder, true /* isWAMR */, bitRate); 1313 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW) 1314 || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) { 1315 // These are PCM-like formats with a fixed sample rate but 1316 // a variable number of channels. 1317 1318 int32_t numChannels; 1319 if (!msg->findInt32("channel-count", &numChannels)) { 1320 err = INVALID_OPERATION; 1321 } else { 1322 err = setupG711Codec(encoder, numChannels); 1323 } 1324 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) { 1325 int32_t numChannels, sampleRate, compressionLevel = -1; 1326 if (encoder && 1327 (!msg->findInt32("channel-count", &numChannels) 1328 || !msg->findInt32("sample-rate", &sampleRate))) { 1329 ALOGE("missing channel count or sample rate for FLAC encoder"); 1330 err = INVALID_OPERATION; 1331 } else { 1332 if (encoder) { 1333 if (!msg->findInt32( 1334 "flac-compression-level", &compressionLevel)) { 1335 compressionLevel = 5;// default FLAC compression level 1336 } else if (compressionLevel < 0) { 1337 ALOGW("compression level %d outside [0..8] range, " 1338 "using 0", 1339 compressionLevel); 1340 compressionLevel = 0; 1341 } else if (compressionLevel > 8) { 1342 ALOGW("compression level %d outside [0..8] range, " 1343 "using 8", 1344 compressionLevel); 1345 compressionLevel = 8; 1346 } 1347 } 1348 err = setupFlacCodec( 1349 encoder, numChannels, sampleRate, compressionLevel); 1350 } 1351 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) { 1352 int32_t numChannels, sampleRate; 1353 if (encoder 1354 || !msg->findInt32("channel-count", &numChannels) 1355 || !msg->findInt32("sample-rate", &sampleRate)) { 1356 err = INVALID_OPERATION; 1357 } else { 1358 err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels); 1359 } 1360 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AC3)) { 1361 int32_t numChannels; 1362 int32_t sampleRate; 1363 if (!msg->findInt32("channel-count", &numChannels) 1364 || !msg->findInt32("sample-rate", &sampleRate)) { 1365 err = INVALID_OPERATION; 1366 } else { 1367 err = setupAC3Codec(encoder, numChannels, sampleRate); 1368 } 1369 } 1370 1371 if (err != OK) { 1372 return err; 1373 } 1374 1375 if (!msg->findInt32("encoder-delay", &mEncoderDelay)) { 1376 mEncoderDelay = 0; 1377 } 1378 1379 if (!msg->findInt32("encoder-padding", &mEncoderPadding)) { 1380 mEncoderPadding = 0; 1381 } 1382 1383 if (msg->findInt32("channel-mask", &mChannelMask)) { 1384 mChannelMaskPresent = true; 1385 } else { 1386 mChannelMaskPresent = false; 1387 } 1388 1389 int32_t maxInputSize; 1390 if (msg->findInt32("max-input-size", &maxInputSize)) { 1391 err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize); 1392 } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) { 1393 err = setMinBufferSize(kPortIndexInput, 8192); // XXX 1394 } 1395 1396 CHECK_EQ(getPortFormat(kPortIndexInput, inputFormat), (status_t)OK); 1397 CHECK_EQ(getPortFormat(kPortIndexOutput, outputFormat), (status_t)OK); 1398 mInputFormat = inputFormat; 1399 mOutputFormat = outputFormat; 1400 1401 return err; 1402} 1403 1404status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) { 1405 OMX_PARAM_PORTDEFINITIONTYPE def; 1406 InitOMXParams(&def); 1407 def.nPortIndex = portIndex; 1408 1409 status_t err = mOMX->getParameter( 1410 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1411 1412 if (err != OK) { 1413 return err; 1414 } 1415 1416 if (def.nBufferSize >= size) { 1417 return OK; 1418 } 1419 1420 def.nBufferSize = size; 1421 1422 err = mOMX->setParameter( 1423 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1424 1425 if (err != OK) { 1426 return err; 1427 } 1428 1429 err = mOMX->getParameter( 1430 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1431 1432 if (err != OK) { 1433 return err; 1434 } 1435 1436 CHECK(def.nBufferSize >= size); 1437 1438 return OK; 1439} 1440 1441status_t ACodec::selectAudioPortFormat( 1442 OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) { 1443 OMX_AUDIO_PARAM_PORTFORMATTYPE format; 1444 InitOMXParams(&format); 1445 1446 format.nPortIndex = portIndex; 1447 for (OMX_U32 index = 0;; ++index) { 1448 format.nIndex = index; 1449 1450 status_t err = mOMX->getParameter( 1451 mNode, OMX_IndexParamAudioPortFormat, 1452 &format, sizeof(format)); 1453 1454 if (err != OK) { 1455 return err; 1456 } 1457 1458 if (format.eEncoding == desiredFormat) { 1459 break; 1460 } 1461 } 1462 1463 return mOMX->setParameter( 1464 mNode, OMX_IndexParamAudioPortFormat, &format, sizeof(format)); 1465} 1466 1467status_t ACodec::setupAACCodec( 1468 bool encoder, int32_t numChannels, int32_t sampleRate, 1469 int32_t bitRate, int32_t aacProfile, bool isADTS) { 1470 if (encoder && isADTS) { 1471 return -EINVAL; 1472 } 1473 1474 status_t err = setupRawAudioFormat( 1475 encoder ? kPortIndexInput : kPortIndexOutput, 1476 sampleRate, 1477 numChannels); 1478 1479 if (err != OK) { 1480 return err; 1481 } 1482 1483 if (encoder) { 1484 err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC); 1485 1486 if (err != OK) { 1487 return err; 1488 } 1489 1490 OMX_PARAM_PORTDEFINITIONTYPE def; 1491 InitOMXParams(&def); 1492 def.nPortIndex = kPortIndexOutput; 1493 1494 err = mOMX->getParameter( 1495 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1496 1497 if (err != OK) { 1498 return err; 1499 } 1500 1501 def.format.audio.bFlagErrorConcealment = OMX_TRUE; 1502 def.format.audio.eEncoding = OMX_AUDIO_CodingAAC; 1503 1504 err = mOMX->setParameter( 1505 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1506 1507 if (err != OK) { 1508 return err; 1509 } 1510 1511 OMX_AUDIO_PARAM_AACPROFILETYPE profile; 1512 InitOMXParams(&profile); 1513 profile.nPortIndex = kPortIndexOutput; 1514 1515 err = mOMX->getParameter( 1516 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 1517 1518 if (err != OK) { 1519 return err; 1520 } 1521 1522 profile.nChannels = numChannels; 1523 1524 profile.eChannelMode = 1525 (numChannels == 1) 1526 ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo; 1527 1528 profile.nSampleRate = sampleRate; 1529 profile.nBitRate = bitRate; 1530 profile.nAudioBandWidth = 0; 1531 profile.nFrameLength = 0; 1532 profile.nAACtools = OMX_AUDIO_AACToolAll; 1533 profile.nAACERtools = OMX_AUDIO_AACERNone; 1534 profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile; 1535 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF; 1536 1537 err = mOMX->setParameter( 1538 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 1539 1540 if (err != OK) { 1541 return err; 1542 } 1543 1544 return err; 1545 } 1546 1547 OMX_AUDIO_PARAM_AACPROFILETYPE profile; 1548 InitOMXParams(&profile); 1549 profile.nPortIndex = kPortIndexInput; 1550 1551 err = mOMX->getParameter( 1552 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 1553 1554 if (err != OK) { 1555 return err; 1556 } 1557 1558 profile.nChannels = numChannels; 1559 profile.nSampleRate = sampleRate; 1560 1561 profile.eAACStreamFormat = 1562 isADTS 1563 ? OMX_AUDIO_AACStreamFormatMP4ADTS 1564 : OMX_AUDIO_AACStreamFormatMP4FF; 1565 1566 return mOMX->setParameter( 1567 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 1568} 1569 1570status_t ACodec::setupAC3Codec( 1571 bool encoder, int32_t numChannels, int32_t sampleRate) { 1572 status_t err = setupRawAudioFormat( 1573 encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels); 1574 1575 if (err != OK) { 1576 return err; 1577 } 1578 1579 if (encoder) { 1580 ALOGW("AC3 encoding is not supported."); 1581 return INVALID_OPERATION; 1582 } 1583 1584 OMX_AUDIO_PARAM_ANDROID_AC3TYPE def; 1585 InitOMXParams(&def); 1586 def.nPortIndex = kPortIndexInput; 1587 1588 err = mOMX->getParameter( 1589 mNode, 1590 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, 1591 &def, 1592 sizeof(def)); 1593 1594 if (err != OK) { 1595 return err; 1596 } 1597 1598 def.nChannels = numChannels; 1599 def.nSampleRate = sampleRate; 1600 1601 return mOMX->setParameter( 1602 mNode, 1603 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, 1604 &def, 1605 sizeof(def)); 1606} 1607 1608static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate( 1609 bool isAMRWB, int32_t bps) { 1610 if (isAMRWB) { 1611 if (bps <= 6600) { 1612 return OMX_AUDIO_AMRBandModeWB0; 1613 } else if (bps <= 8850) { 1614 return OMX_AUDIO_AMRBandModeWB1; 1615 } else if (bps <= 12650) { 1616 return OMX_AUDIO_AMRBandModeWB2; 1617 } else if (bps <= 14250) { 1618 return OMX_AUDIO_AMRBandModeWB3; 1619 } else if (bps <= 15850) { 1620 return OMX_AUDIO_AMRBandModeWB4; 1621 } else if (bps <= 18250) { 1622 return OMX_AUDIO_AMRBandModeWB5; 1623 } else if (bps <= 19850) { 1624 return OMX_AUDIO_AMRBandModeWB6; 1625 } else if (bps <= 23050) { 1626 return OMX_AUDIO_AMRBandModeWB7; 1627 } 1628 1629 // 23850 bps 1630 return OMX_AUDIO_AMRBandModeWB8; 1631 } else { // AMRNB 1632 if (bps <= 4750) { 1633 return OMX_AUDIO_AMRBandModeNB0; 1634 } else if (bps <= 5150) { 1635 return OMX_AUDIO_AMRBandModeNB1; 1636 } else if (bps <= 5900) { 1637 return OMX_AUDIO_AMRBandModeNB2; 1638 } else if (bps <= 6700) { 1639 return OMX_AUDIO_AMRBandModeNB3; 1640 } else if (bps <= 7400) { 1641 return OMX_AUDIO_AMRBandModeNB4; 1642 } else if (bps <= 7950) { 1643 return OMX_AUDIO_AMRBandModeNB5; 1644 } else if (bps <= 10200) { 1645 return OMX_AUDIO_AMRBandModeNB6; 1646 } 1647 1648 // 12200 bps 1649 return OMX_AUDIO_AMRBandModeNB7; 1650 } 1651} 1652 1653status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) { 1654 OMX_AUDIO_PARAM_AMRTYPE def; 1655 InitOMXParams(&def); 1656 def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput; 1657 1658 status_t err = 1659 mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); 1660 1661 if (err != OK) { 1662 return err; 1663 } 1664 1665 def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF; 1666 def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate); 1667 1668 err = mOMX->setParameter( 1669 mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); 1670 1671 if (err != OK) { 1672 return err; 1673 } 1674 1675 return setupRawAudioFormat( 1676 encoder ? kPortIndexInput : kPortIndexOutput, 1677 isWAMR ? 16000 : 8000 /* sampleRate */, 1678 1 /* numChannels */); 1679} 1680 1681status_t ACodec::setupG711Codec(bool encoder, int32_t numChannels) { 1682 CHECK(!encoder); // XXX TODO 1683 1684 return setupRawAudioFormat( 1685 kPortIndexInput, 8000 /* sampleRate */, numChannels); 1686} 1687 1688status_t ACodec::setupFlacCodec( 1689 bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel) { 1690 1691 if (encoder) { 1692 OMX_AUDIO_PARAM_FLACTYPE def; 1693 InitOMXParams(&def); 1694 def.nPortIndex = kPortIndexOutput; 1695 1696 // configure compression level 1697 status_t err = mOMX->getParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def)); 1698 if (err != OK) { 1699 ALOGE("setupFlacCodec(): Error %d getting OMX_IndexParamAudioFlac parameter", err); 1700 return err; 1701 } 1702 def.nCompressionLevel = compressionLevel; 1703 err = mOMX->setParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def)); 1704 if (err != OK) { 1705 ALOGE("setupFlacCodec(): Error %d setting OMX_IndexParamAudioFlac parameter", err); 1706 return err; 1707 } 1708 } 1709 1710 return setupRawAudioFormat( 1711 encoder ? kPortIndexInput : kPortIndexOutput, 1712 sampleRate, 1713 numChannels); 1714} 1715 1716status_t ACodec::setupRawAudioFormat( 1717 OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) { 1718 OMX_PARAM_PORTDEFINITIONTYPE def; 1719 InitOMXParams(&def); 1720 def.nPortIndex = portIndex; 1721 1722 status_t err = mOMX->getParameter( 1723 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1724 1725 if (err != OK) { 1726 return err; 1727 } 1728 1729 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; 1730 1731 err = mOMX->setParameter( 1732 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1733 1734 if (err != OK) { 1735 return err; 1736 } 1737 1738 OMX_AUDIO_PARAM_PCMMODETYPE pcmParams; 1739 InitOMXParams(&pcmParams); 1740 pcmParams.nPortIndex = portIndex; 1741 1742 err = mOMX->getParameter( 1743 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); 1744 1745 if (err != OK) { 1746 return err; 1747 } 1748 1749 pcmParams.nChannels = numChannels; 1750 pcmParams.eNumData = OMX_NumericalDataSigned; 1751 pcmParams.bInterleaved = OMX_TRUE; 1752 pcmParams.nBitPerSample = 16; 1753 pcmParams.nSamplingRate = sampleRate; 1754 pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear; 1755 1756 if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) { 1757 return OMX_ErrorNone; 1758 } 1759 1760 return mOMX->setParameter( 1761 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); 1762} 1763 1764status_t ACodec::setVideoPortFormatType( 1765 OMX_U32 portIndex, 1766 OMX_VIDEO_CODINGTYPE compressionFormat, 1767 OMX_COLOR_FORMATTYPE colorFormat) { 1768 OMX_VIDEO_PARAM_PORTFORMATTYPE format; 1769 InitOMXParams(&format); 1770 format.nPortIndex = portIndex; 1771 format.nIndex = 0; 1772 bool found = false; 1773 1774 OMX_U32 index = 0; 1775 for (;;) { 1776 format.nIndex = index; 1777 status_t err = mOMX->getParameter( 1778 mNode, OMX_IndexParamVideoPortFormat, 1779 &format, sizeof(format)); 1780 1781 if (err != OK) { 1782 return err; 1783 } 1784 1785 // The following assertion is violated by TI's video decoder. 1786 // CHECK_EQ(format.nIndex, index); 1787 1788 if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) { 1789 if (portIndex == kPortIndexInput 1790 && colorFormat == format.eColorFormat) { 1791 // eCompressionFormat does not seem right. 1792 found = true; 1793 break; 1794 } 1795 if (portIndex == kPortIndexOutput 1796 && compressionFormat == format.eCompressionFormat) { 1797 // eColorFormat does not seem right. 1798 found = true; 1799 break; 1800 } 1801 } 1802 1803 if (format.eCompressionFormat == compressionFormat 1804 && format.eColorFormat == colorFormat) { 1805 found = true; 1806 break; 1807 } 1808 1809 ++index; 1810 } 1811 1812 if (!found) { 1813 return UNKNOWN_ERROR; 1814 } 1815 1816 status_t err = mOMX->setParameter( 1817 mNode, OMX_IndexParamVideoPortFormat, 1818 &format, sizeof(format)); 1819 1820 return err; 1821} 1822 1823status_t ACodec::setSupportedOutputFormat() { 1824 OMX_VIDEO_PARAM_PORTFORMATTYPE format; 1825 InitOMXParams(&format); 1826 format.nPortIndex = kPortIndexOutput; 1827 format.nIndex = 0; 1828 1829 status_t err = mOMX->getParameter( 1830 mNode, OMX_IndexParamVideoPortFormat, 1831 &format, sizeof(format)); 1832 CHECK_EQ(err, (status_t)OK); 1833 CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused); 1834 1835 return mOMX->setParameter( 1836 mNode, OMX_IndexParamVideoPortFormat, 1837 &format, sizeof(format)); 1838} 1839 1840static const struct VideoCodingMapEntry { 1841 const char *mMime; 1842 OMX_VIDEO_CODINGTYPE mVideoCodingType; 1843} kVideoCodingMapEntry[] = { 1844 { MEDIA_MIMETYPE_VIDEO_AVC, OMX_VIDEO_CodingAVC }, 1845 { MEDIA_MIMETYPE_VIDEO_HEVC, OMX_VIDEO_CodingHEVC }, 1846 { MEDIA_MIMETYPE_VIDEO_MPEG4, OMX_VIDEO_CodingMPEG4 }, 1847 { MEDIA_MIMETYPE_VIDEO_H263, OMX_VIDEO_CodingH263 }, 1848 { MEDIA_MIMETYPE_VIDEO_MPEG2, OMX_VIDEO_CodingMPEG2 }, 1849 { MEDIA_MIMETYPE_VIDEO_VP8, OMX_VIDEO_CodingVP8 }, 1850 { MEDIA_MIMETYPE_VIDEO_VP9, OMX_VIDEO_CodingVP9 }, 1851}; 1852 1853static status_t GetVideoCodingTypeFromMime( 1854 const char *mime, OMX_VIDEO_CODINGTYPE *codingType) { 1855 for (size_t i = 0; 1856 i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]); 1857 ++i) { 1858 if (!strcasecmp(mime, kVideoCodingMapEntry[i].mMime)) { 1859 *codingType = kVideoCodingMapEntry[i].mVideoCodingType; 1860 return OK; 1861 } 1862 } 1863 1864 *codingType = OMX_VIDEO_CodingUnused; 1865 1866 return ERROR_UNSUPPORTED; 1867} 1868 1869static status_t GetMimeTypeForVideoCoding( 1870 OMX_VIDEO_CODINGTYPE codingType, AString *mime) { 1871 for (size_t i = 0; 1872 i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]); 1873 ++i) { 1874 if (codingType == kVideoCodingMapEntry[i].mVideoCodingType) { 1875 *mime = kVideoCodingMapEntry[i].mMime; 1876 return OK; 1877 } 1878 } 1879 1880 mime->clear(); 1881 1882 return ERROR_UNSUPPORTED; 1883} 1884 1885status_t ACodec::setupVideoDecoder( 1886 const char *mime, int32_t width, int32_t height) { 1887 OMX_VIDEO_CODINGTYPE compressionFormat; 1888 status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat); 1889 1890 if (err != OK) { 1891 return err; 1892 } 1893 1894 err = setVideoPortFormatType( 1895 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused); 1896 1897 if (err != OK) { 1898 return err; 1899 } 1900 1901 err = setSupportedOutputFormat(); 1902 1903 if (err != OK) { 1904 return err; 1905 } 1906 1907 err = setVideoFormatOnPort( 1908 kPortIndexInput, width, height, compressionFormat); 1909 1910 if (err != OK) { 1911 return err; 1912 } 1913 1914 err = setVideoFormatOnPort( 1915 kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused); 1916 1917 if (err != OK) { 1918 return err; 1919 } 1920 1921 return OK; 1922} 1923 1924status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) { 1925 int32_t tmp; 1926 if (!msg->findInt32("color-format", &tmp)) { 1927 return INVALID_OPERATION; 1928 } 1929 1930 OMX_COLOR_FORMATTYPE colorFormat = 1931 static_cast<OMX_COLOR_FORMATTYPE>(tmp); 1932 1933 status_t err = setVideoPortFormatType( 1934 kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat); 1935 1936 if (err != OK) { 1937 ALOGE("[%s] does not support color format %d", 1938 mComponentName.c_str(), colorFormat); 1939 1940 return err; 1941 } 1942 1943 /* Input port configuration */ 1944 1945 OMX_PARAM_PORTDEFINITIONTYPE def; 1946 InitOMXParams(&def); 1947 1948 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 1949 1950 def.nPortIndex = kPortIndexInput; 1951 1952 err = mOMX->getParameter( 1953 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1954 1955 if (err != OK) { 1956 return err; 1957 } 1958 1959 int32_t width, height, bitrate; 1960 if (!msg->findInt32("width", &width) 1961 || !msg->findInt32("height", &height) 1962 || !msg->findInt32("bitrate", &bitrate)) { 1963 return INVALID_OPERATION; 1964 } 1965 1966 video_def->nFrameWidth = width; 1967 video_def->nFrameHeight = height; 1968 1969 int32_t stride; 1970 if (!msg->findInt32("stride", &stride)) { 1971 stride = width; 1972 } 1973 1974 video_def->nStride = stride; 1975 1976 int32_t sliceHeight; 1977 if (!msg->findInt32("slice-height", &sliceHeight)) { 1978 sliceHeight = height; 1979 } 1980 1981 video_def->nSliceHeight = sliceHeight; 1982 1983 def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2; 1984 1985 float frameRate; 1986 if (!msg->findFloat("frame-rate", &frameRate)) { 1987 int32_t tmp; 1988 if (!msg->findInt32("frame-rate", &tmp)) { 1989 return INVALID_OPERATION; 1990 } 1991 frameRate = (float)tmp; 1992 mTimePerFrameUs = (int64_t) (1000000.0f / frameRate); 1993 } 1994 1995 video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f); 1996 video_def->eCompressionFormat = OMX_VIDEO_CodingUnused; 1997 video_def->eColorFormat = colorFormat; 1998 1999 err = mOMX->setParameter( 2000 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2001 2002 if (err != OK) { 2003 ALOGE("[%s] failed to set input port definition parameters.", 2004 mComponentName.c_str()); 2005 2006 return err; 2007 } 2008 2009 /* Output port configuration */ 2010 2011 OMX_VIDEO_CODINGTYPE compressionFormat; 2012 err = GetVideoCodingTypeFromMime(mime, &compressionFormat); 2013 2014 if (err != OK) { 2015 return err; 2016 } 2017 2018 err = setVideoPortFormatType( 2019 kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused); 2020 2021 if (err != OK) { 2022 ALOGE("[%s] does not support compression format %d", 2023 mComponentName.c_str(), compressionFormat); 2024 2025 return err; 2026 } 2027 2028 def.nPortIndex = kPortIndexOutput; 2029 2030 err = mOMX->getParameter( 2031 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2032 2033 if (err != OK) { 2034 return err; 2035 } 2036 2037 video_def->nFrameWidth = width; 2038 video_def->nFrameHeight = height; 2039 video_def->xFramerate = 0; 2040 video_def->nBitrate = bitrate; 2041 video_def->eCompressionFormat = compressionFormat; 2042 video_def->eColorFormat = OMX_COLOR_FormatUnused; 2043 2044 err = mOMX->setParameter( 2045 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2046 2047 if (err != OK) { 2048 ALOGE("[%s] failed to set output port definition parameters.", 2049 mComponentName.c_str()); 2050 2051 return err; 2052 } 2053 2054 switch (compressionFormat) { 2055 case OMX_VIDEO_CodingMPEG4: 2056 err = setupMPEG4EncoderParameters(msg); 2057 break; 2058 2059 case OMX_VIDEO_CodingH263: 2060 err = setupH263EncoderParameters(msg); 2061 break; 2062 2063 case OMX_VIDEO_CodingAVC: 2064 err = setupAVCEncoderParameters(msg); 2065 break; 2066 2067 case OMX_VIDEO_CodingHEVC: 2068 err = setupHEVCEncoderParameters(msg); 2069 break; 2070 2071 case OMX_VIDEO_CodingVP8: 2072 case OMX_VIDEO_CodingVP9: 2073 err = setupVPXEncoderParameters(msg); 2074 break; 2075 2076 default: 2077 break; 2078 } 2079 2080 ALOGI("setupVideoEncoder succeeded"); 2081 2082 return err; 2083} 2084 2085status_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) { 2086 OMX_VIDEO_PARAM_INTRAREFRESHTYPE params; 2087 InitOMXParams(¶ms); 2088 params.nPortIndex = kPortIndexOutput; 2089 2090 params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode); 2091 2092 if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic || 2093 params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) { 2094 int32_t mbs; 2095 if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) { 2096 return INVALID_OPERATION; 2097 } 2098 params.nCirMBs = mbs; 2099 } 2100 2101 if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive || 2102 params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) { 2103 int32_t mbs; 2104 if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) { 2105 return INVALID_OPERATION; 2106 } 2107 params.nAirMBs = mbs; 2108 2109 int32_t ref; 2110 if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) { 2111 return INVALID_OPERATION; 2112 } 2113 params.nAirRef = ref; 2114 } 2115 2116 status_t err = mOMX->setParameter( 2117 mNode, OMX_IndexParamVideoIntraRefresh, 2118 ¶ms, sizeof(params)); 2119 return err; 2120} 2121 2122static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) { 2123 if (iFramesInterval < 0) { 2124 return 0xFFFFFFFF; 2125 } else if (iFramesInterval == 0) { 2126 return 0; 2127 } 2128 OMX_U32 ret = frameRate * iFramesInterval; 2129 CHECK(ret > 1); 2130 return ret; 2131} 2132 2133static OMX_VIDEO_CONTROLRATETYPE getBitrateMode(const sp<AMessage> &msg) { 2134 int32_t tmp; 2135 if (!msg->findInt32("bitrate-mode", &tmp)) { 2136 return OMX_Video_ControlRateVariable; 2137 } 2138 2139 return static_cast<OMX_VIDEO_CONTROLRATETYPE>(tmp); 2140} 2141 2142status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) { 2143 int32_t bitrate, iFrameInterval; 2144 if (!msg->findInt32("bitrate", &bitrate) 2145 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 2146 return INVALID_OPERATION; 2147 } 2148 2149 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 2150 2151 float frameRate; 2152 if (!msg->findFloat("frame-rate", &frameRate)) { 2153 int32_t tmp; 2154 if (!msg->findInt32("frame-rate", &tmp)) { 2155 return INVALID_OPERATION; 2156 } 2157 frameRate = (float)tmp; 2158 } 2159 2160 OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type; 2161 InitOMXParams(&mpeg4type); 2162 mpeg4type.nPortIndex = kPortIndexOutput; 2163 2164 status_t err = mOMX->getParameter( 2165 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); 2166 2167 if (err != OK) { 2168 return err; 2169 } 2170 2171 mpeg4type.nSliceHeaderSpacing = 0; 2172 mpeg4type.bSVH = OMX_FALSE; 2173 mpeg4type.bGov = OMX_FALSE; 2174 2175 mpeg4type.nAllowedPictureTypes = 2176 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 2177 2178 mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 2179 if (mpeg4type.nPFrames == 0) { 2180 mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 2181 } 2182 mpeg4type.nBFrames = 0; 2183 mpeg4type.nIDCVLCThreshold = 0; 2184 mpeg4type.bACPred = OMX_TRUE; 2185 mpeg4type.nMaxPacketSize = 256; 2186 mpeg4type.nTimeIncRes = 1000; 2187 mpeg4type.nHeaderExtension = 0; 2188 mpeg4type.bReversibleVLC = OMX_FALSE; 2189 2190 int32_t profile; 2191 if (msg->findInt32("profile", &profile)) { 2192 int32_t level; 2193 if (!msg->findInt32("level", &level)) { 2194 return INVALID_OPERATION; 2195 } 2196 2197 err = verifySupportForProfileAndLevel(profile, level); 2198 2199 if (err != OK) { 2200 return err; 2201 } 2202 2203 mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile); 2204 mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level); 2205 } 2206 2207 err = mOMX->setParameter( 2208 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); 2209 2210 if (err != OK) { 2211 return err; 2212 } 2213 2214 err = configureBitrate(bitrate, bitrateMode); 2215 2216 if (err != OK) { 2217 return err; 2218 } 2219 2220 return setupErrorCorrectionParameters(); 2221} 2222 2223status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) { 2224 int32_t bitrate, iFrameInterval; 2225 if (!msg->findInt32("bitrate", &bitrate) 2226 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 2227 return INVALID_OPERATION; 2228 } 2229 2230 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 2231 2232 float frameRate; 2233 if (!msg->findFloat("frame-rate", &frameRate)) { 2234 int32_t tmp; 2235 if (!msg->findInt32("frame-rate", &tmp)) { 2236 return INVALID_OPERATION; 2237 } 2238 frameRate = (float)tmp; 2239 } 2240 2241 OMX_VIDEO_PARAM_H263TYPE h263type; 2242 InitOMXParams(&h263type); 2243 h263type.nPortIndex = kPortIndexOutput; 2244 2245 status_t err = mOMX->getParameter( 2246 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); 2247 2248 if (err != OK) { 2249 return err; 2250 } 2251 2252 h263type.nAllowedPictureTypes = 2253 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 2254 2255 h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 2256 if (h263type.nPFrames == 0) { 2257 h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 2258 } 2259 h263type.nBFrames = 0; 2260 2261 int32_t profile; 2262 if (msg->findInt32("profile", &profile)) { 2263 int32_t level; 2264 if (!msg->findInt32("level", &level)) { 2265 return INVALID_OPERATION; 2266 } 2267 2268 err = verifySupportForProfileAndLevel(profile, level); 2269 2270 if (err != OK) { 2271 return err; 2272 } 2273 2274 h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile); 2275 h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level); 2276 } 2277 2278 h263type.bPLUSPTYPEAllowed = OMX_FALSE; 2279 h263type.bForceRoundingTypeToZero = OMX_FALSE; 2280 h263type.nPictureHeaderRepetition = 0; 2281 h263type.nGOBHeaderInterval = 0; 2282 2283 err = mOMX->setParameter( 2284 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); 2285 2286 if (err != OK) { 2287 return err; 2288 } 2289 2290 err = configureBitrate(bitrate, bitrateMode); 2291 2292 if (err != OK) { 2293 return err; 2294 } 2295 2296 return setupErrorCorrectionParameters(); 2297} 2298 2299status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) { 2300 int32_t bitrate, iFrameInterval; 2301 if (!msg->findInt32("bitrate", &bitrate) 2302 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 2303 return INVALID_OPERATION; 2304 } 2305 2306 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 2307 2308 float frameRate; 2309 if (!msg->findFloat("frame-rate", &frameRate)) { 2310 int32_t tmp; 2311 if (!msg->findInt32("frame-rate", &tmp)) { 2312 return INVALID_OPERATION; 2313 } 2314 frameRate = (float)tmp; 2315 } 2316 2317 status_t err = OK; 2318 int32_t intraRefreshMode = 0; 2319 if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) { 2320 err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode); 2321 if (err != OK) { 2322 ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x", 2323 err, intraRefreshMode); 2324 return err; 2325 } 2326 } 2327 2328 OMX_VIDEO_PARAM_AVCTYPE h264type; 2329 InitOMXParams(&h264type); 2330 h264type.nPortIndex = kPortIndexOutput; 2331 2332 err = mOMX->getParameter( 2333 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 2334 2335 if (err != OK) { 2336 return err; 2337 } 2338 2339 h264type.nAllowedPictureTypes = 2340 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 2341 2342 int32_t profile; 2343 if (msg->findInt32("profile", &profile)) { 2344 int32_t level; 2345 if (!msg->findInt32("level", &level)) { 2346 return INVALID_OPERATION; 2347 } 2348 2349 err = verifySupportForProfileAndLevel(profile, level); 2350 2351 if (err != OK) { 2352 return err; 2353 } 2354 2355 h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile); 2356 h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level); 2357 } 2358 2359 // XXX 2360 if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) { 2361 ALOGW("Use baseline profile instead of %d for AVC recording", 2362 h264type.eProfile); 2363 h264type.eProfile = OMX_VIDEO_AVCProfileBaseline; 2364 } 2365 2366 if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) { 2367 h264type.nSliceHeaderSpacing = 0; 2368 h264type.bUseHadamard = OMX_TRUE; 2369 h264type.nRefFrames = 1; 2370 h264type.nBFrames = 0; 2371 h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 2372 if (h264type.nPFrames == 0) { 2373 h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 2374 } 2375 h264type.nRefIdx10ActiveMinus1 = 0; 2376 h264type.nRefIdx11ActiveMinus1 = 0; 2377 h264type.bEntropyCodingCABAC = OMX_FALSE; 2378 h264type.bWeightedPPrediction = OMX_FALSE; 2379 h264type.bconstIpred = OMX_FALSE; 2380 h264type.bDirect8x8Inference = OMX_FALSE; 2381 h264type.bDirectSpatialTemporal = OMX_FALSE; 2382 h264type.nCabacInitIdc = 0; 2383 } 2384 2385 if (h264type.nBFrames != 0) { 2386 h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB; 2387 } 2388 2389 h264type.bEnableUEP = OMX_FALSE; 2390 h264type.bEnableFMO = OMX_FALSE; 2391 h264type.bEnableASO = OMX_FALSE; 2392 h264type.bEnableRS = OMX_FALSE; 2393 h264type.bFrameMBsOnly = OMX_TRUE; 2394 h264type.bMBAFF = OMX_FALSE; 2395 h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; 2396 2397 err = mOMX->setParameter( 2398 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 2399 2400 if (err != OK) { 2401 return err; 2402 } 2403 2404 return configureBitrate(bitrate, bitrateMode); 2405} 2406 2407status_t ACodec::setupHEVCEncoderParameters(const sp<AMessage> &msg) { 2408 int32_t bitrate, iFrameInterval; 2409 if (!msg->findInt32("bitrate", &bitrate) 2410 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 2411 return INVALID_OPERATION; 2412 } 2413 2414 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 2415 2416 float frameRate; 2417 if (!msg->findFloat("frame-rate", &frameRate)) { 2418 int32_t tmp; 2419 if (!msg->findInt32("frame-rate", &tmp)) { 2420 return INVALID_OPERATION; 2421 } 2422 frameRate = (float)tmp; 2423 } 2424 2425 OMX_VIDEO_PARAM_HEVCTYPE hevcType; 2426 InitOMXParams(&hevcType); 2427 hevcType.nPortIndex = kPortIndexOutput; 2428 2429 status_t err = OK; 2430 err = mOMX->getParameter( 2431 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType)); 2432 if (err != OK) { 2433 return err; 2434 } 2435 2436 int32_t profile; 2437 if (msg->findInt32("profile", &profile)) { 2438 int32_t level; 2439 if (!msg->findInt32("level", &level)) { 2440 return INVALID_OPERATION; 2441 } 2442 2443 err = verifySupportForProfileAndLevel(profile, level); 2444 if (err != OK) { 2445 return err; 2446 } 2447 2448 hevcType.eProfile = static_cast<OMX_VIDEO_HEVCPROFILETYPE>(profile); 2449 hevcType.eLevel = static_cast<OMX_VIDEO_HEVCLEVELTYPE>(level); 2450 } 2451 2452 // TODO: Need OMX structure definition for setting iFrameInterval 2453 2454 err = mOMX->setParameter( 2455 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType)); 2456 if (err != OK) { 2457 return err; 2458 } 2459 2460 return configureBitrate(bitrate, bitrateMode); 2461} 2462 2463status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg) { 2464 int32_t bitrate; 2465 int32_t iFrameInterval = 0; 2466 size_t tsLayers = 0; 2467 OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE pattern = 2468 OMX_VIDEO_VPXTemporalLayerPatternNone; 2469 static const uint32_t kVp8LayerRateAlloction 2470 [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] 2471 [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] = { 2472 {100, 100, 100}, // 1 layer 2473 { 60, 100, 100}, // 2 layers {60%, 40%} 2474 { 40, 60, 100}, // 3 layers {40%, 20%, 40%} 2475 }; 2476 if (!msg->findInt32("bitrate", &bitrate)) { 2477 return INVALID_OPERATION; 2478 } 2479 msg->findInt32("i-frame-interval", &iFrameInterval); 2480 2481 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 2482 2483 float frameRate; 2484 if (!msg->findFloat("frame-rate", &frameRate)) { 2485 int32_t tmp; 2486 if (!msg->findInt32("frame-rate", &tmp)) { 2487 return INVALID_OPERATION; 2488 } 2489 frameRate = (float)tmp; 2490 } 2491 2492 AString tsSchema; 2493 if (msg->findString("ts-schema", &tsSchema)) { 2494 if (tsSchema == "webrtc.vp8.1-layer") { 2495 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC; 2496 tsLayers = 1; 2497 } else if (tsSchema == "webrtc.vp8.2-layer") { 2498 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC; 2499 tsLayers = 2; 2500 } else if (tsSchema == "webrtc.vp8.3-layer") { 2501 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC; 2502 tsLayers = 3; 2503 } else { 2504 ALOGW("Unsupported ts-schema [%s]", tsSchema.c_str()); 2505 } 2506 } 2507 2508 OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type; 2509 InitOMXParams(&vp8type); 2510 vp8type.nPortIndex = kPortIndexOutput; 2511 status_t err = mOMX->getParameter( 2512 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder, 2513 &vp8type, sizeof(vp8type)); 2514 2515 if (err == OK) { 2516 if (iFrameInterval > 0) { 2517 vp8type.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate); 2518 } 2519 vp8type.eTemporalPattern = pattern; 2520 vp8type.nTemporalLayerCount = tsLayers; 2521 if (tsLayers > 0) { 2522 for (size_t i = 0; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) { 2523 vp8type.nTemporalLayerBitrateRatio[i] = 2524 kVp8LayerRateAlloction[tsLayers - 1][i]; 2525 } 2526 } 2527 if (bitrateMode == OMX_Video_ControlRateConstant) { 2528 vp8type.nMinQuantizer = 2; 2529 vp8type.nMaxQuantizer = 63; 2530 } 2531 2532 err = mOMX->setParameter( 2533 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder, 2534 &vp8type, sizeof(vp8type)); 2535 if (err != OK) { 2536 ALOGW("Extended VP8 parameters set failed: %d", err); 2537 } 2538 } 2539 2540 return configureBitrate(bitrate, bitrateMode); 2541} 2542 2543status_t ACodec::verifySupportForProfileAndLevel( 2544 int32_t profile, int32_t level) { 2545 OMX_VIDEO_PARAM_PROFILELEVELTYPE params; 2546 InitOMXParams(¶ms); 2547 params.nPortIndex = kPortIndexOutput; 2548 2549 for (params.nProfileIndex = 0;; ++params.nProfileIndex) { 2550 status_t err = mOMX->getParameter( 2551 mNode, 2552 OMX_IndexParamVideoProfileLevelQuerySupported, 2553 ¶ms, 2554 sizeof(params)); 2555 2556 if (err != OK) { 2557 return err; 2558 } 2559 2560 int32_t supportedProfile = static_cast<int32_t>(params.eProfile); 2561 int32_t supportedLevel = static_cast<int32_t>(params.eLevel); 2562 2563 if (profile == supportedProfile && level <= supportedLevel) { 2564 return OK; 2565 } 2566 } 2567} 2568 2569status_t ACodec::configureBitrate( 2570 int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode) { 2571 OMX_VIDEO_PARAM_BITRATETYPE bitrateType; 2572 InitOMXParams(&bitrateType); 2573 bitrateType.nPortIndex = kPortIndexOutput; 2574 2575 status_t err = mOMX->getParameter( 2576 mNode, OMX_IndexParamVideoBitrate, 2577 &bitrateType, sizeof(bitrateType)); 2578 2579 if (err != OK) { 2580 return err; 2581 } 2582 2583 bitrateType.eControlRate = bitrateMode; 2584 bitrateType.nTargetBitrate = bitrate; 2585 2586 return mOMX->setParameter( 2587 mNode, OMX_IndexParamVideoBitrate, 2588 &bitrateType, sizeof(bitrateType)); 2589} 2590 2591status_t ACodec::setupErrorCorrectionParameters() { 2592 OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType; 2593 InitOMXParams(&errorCorrectionType); 2594 errorCorrectionType.nPortIndex = kPortIndexOutput; 2595 2596 status_t err = mOMX->getParameter( 2597 mNode, OMX_IndexParamVideoErrorCorrection, 2598 &errorCorrectionType, sizeof(errorCorrectionType)); 2599 2600 if (err != OK) { 2601 return OK; // Optional feature. Ignore this failure 2602 } 2603 2604 errorCorrectionType.bEnableHEC = OMX_FALSE; 2605 errorCorrectionType.bEnableResync = OMX_TRUE; 2606 errorCorrectionType.nResynchMarkerSpacing = 256; 2607 errorCorrectionType.bEnableDataPartitioning = OMX_FALSE; 2608 errorCorrectionType.bEnableRVLC = OMX_FALSE; 2609 2610 return mOMX->setParameter( 2611 mNode, OMX_IndexParamVideoErrorCorrection, 2612 &errorCorrectionType, sizeof(errorCorrectionType)); 2613} 2614 2615status_t ACodec::setVideoFormatOnPort( 2616 OMX_U32 portIndex, 2617 int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) { 2618 OMX_PARAM_PORTDEFINITIONTYPE def; 2619 InitOMXParams(&def); 2620 def.nPortIndex = portIndex; 2621 2622 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 2623 2624 status_t err = mOMX->getParameter( 2625 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2626 2627 CHECK_EQ(err, (status_t)OK); 2628 2629 if (portIndex == kPortIndexInput) { 2630 // XXX Need a (much) better heuristic to compute input buffer sizes. 2631 const size_t X = 64 * 1024; 2632 if (def.nBufferSize < X) { 2633 def.nBufferSize = X; 2634 } 2635 } 2636 2637 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo); 2638 2639 video_def->nFrameWidth = width; 2640 video_def->nFrameHeight = height; 2641 2642 if (portIndex == kPortIndexInput) { 2643 video_def->eCompressionFormat = compressionFormat; 2644 video_def->eColorFormat = OMX_COLOR_FormatUnused; 2645 } 2646 2647 err = mOMX->setParameter( 2648 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2649 2650 return err; 2651} 2652 2653status_t ACodec::initNativeWindow() { 2654 if (mNativeWindow != NULL) { 2655 return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE); 2656 } 2657 2658 mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE); 2659 return OK; 2660} 2661 2662size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const { 2663 size_t n = 0; 2664 2665 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 2666 const BufferInfo &info = mBuffers[portIndex].itemAt(i); 2667 2668 if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) { 2669 ++n; 2670 } 2671 } 2672 2673 return n; 2674} 2675 2676size_t ACodec::countBuffersOwnedByNativeWindow() const { 2677 size_t n = 0; 2678 2679 for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) { 2680 const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i); 2681 2682 if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 2683 ++n; 2684 } 2685 } 2686 2687 return n; 2688} 2689 2690void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() { 2691 if (mNativeWindow == NULL) { 2692 return; 2693 } 2694 2695 while (countBuffersOwnedByNativeWindow() > mNumUndequeuedBuffers 2696 && dequeueBufferFromNativeWindow() != NULL) { 2697 // these buffers will be submitted as regular buffers; account for this 2698 if (mStoreMetaDataInOutputBuffers && mMetaDataBuffersToSubmit > 0) { 2699 --mMetaDataBuffersToSubmit; 2700 } 2701 } 2702} 2703 2704bool ACodec::allYourBuffersAreBelongToUs( 2705 OMX_U32 portIndex) { 2706 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 2707 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 2708 2709 if (info->mStatus != BufferInfo::OWNED_BY_US 2710 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) { 2711 ALOGV("[%s] Buffer %u on port %u still has status %d", 2712 mComponentName.c_str(), 2713 info->mBufferID, portIndex, info->mStatus); 2714 return false; 2715 } 2716 } 2717 2718 return true; 2719} 2720 2721bool ACodec::allYourBuffersAreBelongToUs() { 2722 return allYourBuffersAreBelongToUs(kPortIndexInput) 2723 && allYourBuffersAreBelongToUs(kPortIndexOutput); 2724} 2725 2726void ACodec::deferMessage(const sp<AMessage> &msg) { 2727 bool wasEmptyBefore = mDeferredQueue.empty(); 2728 mDeferredQueue.push_back(msg); 2729} 2730 2731void ACodec::processDeferredMessages() { 2732 List<sp<AMessage> > queue = mDeferredQueue; 2733 mDeferredQueue.clear(); 2734 2735 List<sp<AMessage> >::iterator it = queue.begin(); 2736 while (it != queue.end()) { 2737 onMessageReceived(*it++); 2738 } 2739} 2740 2741// static 2742void ACodec::describeDefaultColorFormat(DescribeColorFormatParams ¶ms) { 2743 MediaImage &image = params.sMediaImage; 2744 memset(&image, 0, sizeof(image)); 2745 2746 image.mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN; 2747 image.mNumPlanes = 0; 2748 2749 const OMX_COLOR_FORMATTYPE fmt = params.eColorFormat; 2750 // we need stride and slice-height to be non-zero 2751 if (params.nStride == 0 || params.nSliceHeight == 0) { 2752 ALOGW("cannot describe color format 0x%x = %d with stride=%u and sliceHeight=%u", 2753 fmt, fmt, params.nStride, params.nSliceHeight); 2754 return; 2755 } 2756 2757 image.mWidth = params.nFrameWidth; 2758 image.mHeight = params.nFrameHeight; 2759 2760 // only supporting YUV420 2761 if (fmt != OMX_COLOR_FormatYUV420Planar && 2762 fmt != OMX_COLOR_FormatYUV420PackedPlanar && 2763 fmt != OMX_COLOR_FormatYUV420SemiPlanar && 2764 fmt != OMX_COLOR_FormatYUV420PackedSemiPlanar) { 2765 ALOGW("do not know color format 0x%x = %d", fmt, fmt); 2766 return; 2767 } 2768 2769 // set-up YUV format 2770 image.mType = MediaImage::MEDIA_IMAGE_TYPE_YUV; 2771 image.mNumPlanes = 3; 2772 image.mBitDepth = 8; 2773 image.mPlane[image.Y].mOffset = 0; 2774 image.mPlane[image.Y].mColInc = 1; 2775 image.mPlane[image.Y].mRowInc = params.nStride; 2776 image.mPlane[image.Y].mHorizSubsampling = 1; 2777 image.mPlane[image.Y].mVertSubsampling = 1; 2778 2779 switch (fmt) { 2780 case OMX_COLOR_FormatYUV420Planar: // used for YV12 2781 case OMX_COLOR_FormatYUV420PackedPlanar: 2782 image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight; 2783 image.mPlane[image.U].mColInc = 1; 2784 image.mPlane[image.U].mRowInc = params.nStride / 2; 2785 image.mPlane[image.U].mHorizSubsampling = 2; 2786 image.mPlane[image.U].mVertSubsampling = 2; 2787 2788 image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset 2789 + (params.nStride * params.nSliceHeight / 4); 2790 image.mPlane[image.V].mColInc = 1; 2791 image.mPlane[image.V].mRowInc = params.nStride / 2; 2792 image.mPlane[image.V].mHorizSubsampling = 2; 2793 image.mPlane[image.V].mVertSubsampling = 2; 2794 break; 2795 2796 case OMX_COLOR_FormatYUV420SemiPlanar: 2797 // FIXME: NV21 for sw-encoder, NV12 for decoder and hw-encoder 2798 case OMX_COLOR_FormatYUV420PackedSemiPlanar: 2799 // NV12 2800 image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight; 2801 image.mPlane[image.U].mColInc = 2; 2802 image.mPlane[image.U].mRowInc = params.nStride; 2803 image.mPlane[image.U].mHorizSubsampling = 2; 2804 image.mPlane[image.U].mVertSubsampling = 2; 2805 2806 image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset + 1; 2807 image.mPlane[image.V].mColInc = 2; 2808 image.mPlane[image.V].mRowInc = params.nStride; 2809 image.mPlane[image.V].mHorizSubsampling = 2; 2810 image.mPlane[image.V].mVertSubsampling = 2; 2811 break; 2812 2813 default: 2814 TRESPASS(); 2815 } 2816} 2817 2818status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> ¬ify) { 2819 // TODO: catch errors an return them instead of using CHECK 2820 OMX_PARAM_PORTDEFINITIONTYPE def; 2821 InitOMXParams(&def); 2822 def.nPortIndex = portIndex; 2823 2824 CHECK_EQ(mOMX->getParameter( 2825 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)), 2826 (status_t)OK); 2827 2828 CHECK_EQ((int)def.eDir, 2829 (int)(portIndex == kPortIndexOutput ? OMX_DirOutput : OMX_DirInput)); 2830 2831 switch (def.eDomain) { 2832 case OMX_PortDomainVideo: 2833 { 2834 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video; 2835 switch ((int)videoDef->eCompressionFormat) { 2836 case OMX_VIDEO_CodingUnused: 2837 { 2838 CHECK(mIsEncoder ^ (portIndex == kPortIndexOutput)); 2839 notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW); 2840 2841 notify->setInt32("stride", videoDef->nStride); 2842 notify->setInt32("slice-height", videoDef->nSliceHeight); 2843 notify->setInt32("color-format", videoDef->eColorFormat); 2844 2845 2846 DescribeColorFormatParams describeParams; 2847 InitOMXParams(&describeParams); 2848 describeParams.eColorFormat = videoDef->eColorFormat; 2849 describeParams.nFrameWidth = videoDef->nFrameWidth; 2850 describeParams.nFrameHeight = videoDef->nFrameHeight; 2851 describeParams.nStride = videoDef->nStride; 2852 describeParams.nSliceHeight = videoDef->nSliceHeight; 2853 2854 OMX_INDEXTYPE describeColorFormatIndex; 2855 if (mOMX->getExtensionIndex( 2856 mNode, "OMX.google.android.index.describeColorFormat", 2857 &describeColorFormatIndex) || 2858 mOMX->getParameter( 2859 mNode, describeColorFormatIndex, 2860 &describeParams, sizeof(describeParams))) { 2861 describeDefaultColorFormat(describeParams); 2862 } 2863 2864 if (describeParams.sMediaImage.mType != MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN) { 2865 notify->setBuffer( 2866 "image-data", 2867 ABuffer::CreateAsCopy( 2868 &describeParams.sMediaImage, 2869 sizeof(describeParams.sMediaImage))); 2870 } 2871 2872 OMX_CONFIG_RECTTYPE rect; 2873 InitOMXParams(&rect); 2874 rect.nPortIndex = kPortIndexOutput; 2875 2876 if (mOMX->getConfig( 2877 mNode, OMX_IndexConfigCommonOutputCrop, 2878 &rect, sizeof(rect)) != OK) { 2879 rect.nLeft = 0; 2880 rect.nTop = 0; 2881 rect.nWidth = videoDef->nFrameWidth; 2882 rect.nHeight = videoDef->nFrameHeight; 2883 } 2884 2885 CHECK_GE(rect.nLeft, 0); 2886 CHECK_GE(rect.nTop, 0); 2887 CHECK_GE(rect.nWidth, 0u); 2888 CHECK_GE(rect.nHeight, 0u); 2889 CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth); 2890 CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight); 2891 2892 notify->setRect( 2893 "crop", 2894 rect.nLeft, 2895 rect.nTop, 2896 rect.nLeft + rect.nWidth - 1, 2897 rect.nTop + rect.nHeight - 1); 2898 2899 break; 2900 } 2901 2902 case OMX_VIDEO_CodingVP8: 2903 case OMX_VIDEO_CodingVP9: 2904 { 2905 OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type; 2906 InitOMXParams(&vp8type); 2907 vp8type.nPortIndex = kPortIndexOutput; 2908 status_t err = mOMX->getParameter( 2909 mNode, 2910 (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder, 2911 &vp8type, 2912 sizeof(vp8type)); 2913 2914 if (err == OK) { 2915 AString tsSchema = "none"; 2916 if (vp8type.eTemporalPattern 2917 == OMX_VIDEO_VPXTemporalLayerPatternWebRTC) { 2918 switch (vp8type.nTemporalLayerCount) { 2919 case 1: 2920 { 2921 tsSchema = "webrtc.vp8.1-layer"; 2922 break; 2923 } 2924 case 2: 2925 { 2926 tsSchema = "webrtc.vp8.2-layer"; 2927 break; 2928 } 2929 case 3: 2930 { 2931 tsSchema = "webrtc.vp8.3-layer"; 2932 break; 2933 } 2934 default: 2935 { 2936 break; 2937 } 2938 } 2939 } 2940 notify->setString("ts-schema", tsSchema); 2941 } 2942 // Fall through to set up mime. 2943 } 2944 2945 default: 2946 { 2947 CHECK(mIsEncoder ^ (portIndex == kPortIndexInput)); 2948 AString mime; 2949 if (GetMimeTypeForVideoCoding( 2950 videoDef->eCompressionFormat, &mime) != OK) { 2951 notify->setString("mime", "application/octet-stream"); 2952 } else { 2953 notify->setString("mime", mime.c_str()); 2954 } 2955 break; 2956 } 2957 } 2958 2959 notify->setInt32("width", videoDef->nFrameWidth); 2960 notify->setInt32("height", videoDef->nFrameHeight); 2961 break; 2962 } 2963 2964 case OMX_PortDomainAudio: 2965 { 2966 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio; 2967 2968 switch ((int)audioDef->eEncoding) { 2969 case OMX_AUDIO_CodingPCM: 2970 { 2971 OMX_AUDIO_PARAM_PCMMODETYPE params; 2972 InitOMXParams(¶ms); 2973 params.nPortIndex = portIndex; 2974 2975 CHECK_EQ(mOMX->getParameter( 2976 mNode, OMX_IndexParamAudioPcm, 2977 ¶ms, sizeof(params)), 2978 (status_t)OK); 2979 2980 CHECK_GT(params.nChannels, 0); 2981 CHECK(params.nChannels == 1 || params.bInterleaved); 2982 CHECK_EQ(params.nBitPerSample, 16u); 2983 2984 CHECK_EQ((int)params.eNumData, 2985 (int)OMX_NumericalDataSigned); 2986 2987 CHECK_EQ((int)params.ePCMMode, 2988 (int)OMX_AUDIO_PCMModeLinear); 2989 2990 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW); 2991 notify->setInt32("channel-count", params.nChannels); 2992 notify->setInt32("sample-rate", params.nSamplingRate); 2993 2994 if (mChannelMaskPresent) { 2995 notify->setInt32("channel-mask", mChannelMask); 2996 } 2997 break; 2998 } 2999 3000 case OMX_AUDIO_CodingAAC: 3001 { 3002 OMX_AUDIO_PARAM_AACPROFILETYPE params; 3003 InitOMXParams(¶ms); 3004 params.nPortIndex = portIndex; 3005 3006 CHECK_EQ(mOMX->getParameter( 3007 mNode, OMX_IndexParamAudioAac, 3008 ¶ms, sizeof(params)), 3009 (status_t)OK); 3010 3011 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC); 3012 notify->setInt32("channel-count", params.nChannels); 3013 notify->setInt32("sample-rate", params.nSampleRate); 3014 break; 3015 } 3016 3017 case OMX_AUDIO_CodingAMR: 3018 { 3019 OMX_AUDIO_PARAM_AMRTYPE params; 3020 InitOMXParams(¶ms); 3021 params.nPortIndex = portIndex; 3022 3023 CHECK_EQ(mOMX->getParameter( 3024 mNode, OMX_IndexParamAudioAmr, 3025 ¶ms, sizeof(params)), 3026 (status_t)OK); 3027 3028 notify->setInt32("channel-count", 1); 3029 if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) { 3030 notify->setString( 3031 "mime", MEDIA_MIMETYPE_AUDIO_AMR_WB); 3032 3033 notify->setInt32("sample-rate", 16000); 3034 } else { 3035 notify->setString( 3036 "mime", MEDIA_MIMETYPE_AUDIO_AMR_NB); 3037 3038 notify->setInt32("sample-rate", 8000); 3039 } 3040 break; 3041 } 3042 3043 case OMX_AUDIO_CodingFLAC: 3044 { 3045 OMX_AUDIO_PARAM_FLACTYPE params; 3046 InitOMXParams(¶ms); 3047 params.nPortIndex = portIndex; 3048 3049 CHECK_EQ(mOMX->getParameter( 3050 mNode, OMX_IndexParamAudioFlac, 3051 ¶ms, sizeof(params)), 3052 (status_t)OK); 3053 3054 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC); 3055 notify->setInt32("channel-count", params.nChannels); 3056 notify->setInt32("sample-rate", params.nSampleRate); 3057 break; 3058 } 3059 3060 case OMX_AUDIO_CodingMP3: 3061 { 3062 OMX_AUDIO_PARAM_MP3TYPE params; 3063 InitOMXParams(¶ms); 3064 params.nPortIndex = portIndex; 3065 3066 CHECK_EQ(mOMX->getParameter( 3067 mNode, OMX_IndexParamAudioMp3, 3068 ¶ms, sizeof(params)), 3069 (status_t)OK); 3070 3071 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MPEG); 3072 notify->setInt32("channel-count", params.nChannels); 3073 notify->setInt32("sample-rate", params.nSampleRate); 3074 break; 3075 } 3076 3077 case OMX_AUDIO_CodingVORBIS: 3078 { 3079 OMX_AUDIO_PARAM_VORBISTYPE params; 3080 InitOMXParams(¶ms); 3081 params.nPortIndex = portIndex; 3082 3083 CHECK_EQ(mOMX->getParameter( 3084 mNode, OMX_IndexParamAudioVorbis, 3085 ¶ms, sizeof(params)), 3086 (status_t)OK); 3087 3088 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_VORBIS); 3089 notify->setInt32("channel-count", params.nChannels); 3090 notify->setInt32("sample-rate", params.nSampleRate); 3091 break; 3092 } 3093 3094 case OMX_AUDIO_CodingAndroidAC3: 3095 { 3096 OMX_AUDIO_PARAM_ANDROID_AC3TYPE params; 3097 InitOMXParams(¶ms); 3098 params.nPortIndex = portIndex; 3099 3100 CHECK_EQ((status_t)OK, mOMX->getParameter( 3101 mNode, 3102 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, 3103 ¶ms, 3104 sizeof(params))); 3105 3106 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3); 3107 notify->setInt32("channel-count", params.nChannels); 3108 notify->setInt32("sample-rate", params.nSampleRate); 3109 break; 3110 } 3111 3112 case OMX_AUDIO_CodingAndroidOPUS: 3113 { 3114 OMX_AUDIO_PARAM_ANDROID_OPUSTYPE params; 3115 InitOMXParams(¶ms); 3116 params.nPortIndex = portIndex; 3117 3118 CHECK_EQ((status_t)OK, mOMX->getParameter( 3119 mNode, 3120 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus, 3121 ¶ms, 3122 sizeof(params))); 3123 3124 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_OPUS); 3125 notify->setInt32("channel-count", params.nChannels); 3126 notify->setInt32("sample-rate", params.nSampleRate); 3127 break; 3128 } 3129 3130 default: 3131 ALOGE("UNKNOWN AUDIO CODING: %d\n", audioDef->eEncoding); 3132 TRESPASS(); 3133 } 3134 break; 3135 } 3136 3137 default: 3138 TRESPASS(); 3139 } 3140 3141 return OK; 3142} 3143 3144void ACodec::sendFormatChange(const sp<AMessage> &reply) { 3145 sp<AMessage> notify = mNotify->dup(); 3146 notify->setInt32("what", kWhatOutputFormatChanged); 3147 3148 CHECK_EQ(getPortFormat(kPortIndexOutput, notify), (status_t)OK); 3149 3150 AString mime; 3151 CHECK(notify->findString("mime", &mime)); 3152 3153 int32_t left, top, right, bottom; 3154 if (mime == MEDIA_MIMETYPE_VIDEO_RAW && 3155 mNativeWindow != NULL && 3156 notify->findRect("crop", &left, &top, &right, &bottom)) { 3157 // notify renderer of the crop change 3158 // NOTE: native window uses extended right-bottom coordinate 3159 reply->setRect("crop", left, top, right + 1, bottom + 1); 3160 } else if (mime == MEDIA_MIMETYPE_AUDIO_RAW && 3161 (mEncoderDelay || mEncoderPadding)) { 3162 int32_t channelCount; 3163 CHECK(notify->findInt32("channel-count", &channelCount)); 3164 size_t frameSize = channelCount * sizeof(int16_t); 3165 if (mSkipCutBuffer != NULL) { 3166 size_t prevbufsize = mSkipCutBuffer->size(); 3167 if (prevbufsize != 0) { 3168 ALOGW("Replacing SkipCutBuffer holding %d " 3169 "bytes", 3170 prevbufsize); 3171 } 3172 } 3173 mSkipCutBuffer = new SkipCutBuffer( 3174 mEncoderDelay * frameSize, 3175 mEncoderPadding * frameSize); 3176 } 3177 3178 notify->post(); 3179 3180 mSentFormat = true; 3181} 3182 3183void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) { 3184 sp<AMessage> notify = mNotify->dup(); 3185 notify->setInt32("what", CodecBase::kWhatError); 3186 notify->setInt32("omx-error", error); 3187 notify->setInt32("err", internalError); 3188 notify->post(); 3189} 3190 3191status_t ACodec::pushBlankBuffersToNativeWindow() { 3192 status_t err = NO_ERROR; 3193 ANativeWindowBuffer* anb = NULL; 3194 int numBufs = 0; 3195 int minUndequeuedBufs = 0; 3196 3197 // We need to reconnect to the ANativeWindow as a CPU client to ensure that 3198 // no frames get dropped by SurfaceFlinger assuming that these are video 3199 // frames. 3200 err = native_window_api_disconnect(mNativeWindow.get(), 3201 NATIVE_WINDOW_API_MEDIA); 3202 if (err != NO_ERROR) { 3203 ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)", 3204 strerror(-err), -err); 3205 return err; 3206 } 3207 3208 err = native_window_api_connect(mNativeWindow.get(), 3209 NATIVE_WINDOW_API_CPU); 3210 if (err != NO_ERROR) { 3211 ALOGE("error pushing blank frames: api_connect failed: %s (%d)", 3212 strerror(-err), -err); 3213 return err; 3214 } 3215 3216 err = native_window_set_buffers_geometry(mNativeWindow.get(), 1, 1, 3217 HAL_PIXEL_FORMAT_RGBX_8888); 3218 if (err != NO_ERROR) { 3219 ALOGE("error pushing blank frames: set_buffers_geometry failed: %s (%d)", 3220 strerror(-err), -err); 3221 goto error; 3222 } 3223 3224 err = native_window_set_scaling_mode(mNativeWindow.get(), 3225 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); 3226 if (err != NO_ERROR) { 3227 ALOGE("error pushing blank_frames: set_scaling_mode failed: %s (%d)", 3228 strerror(-err), -err); 3229 goto error; 3230 } 3231 3232 err = native_window_set_usage(mNativeWindow.get(), 3233 GRALLOC_USAGE_SW_WRITE_OFTEN); 3234 if (err != NO_ERROR) { 3235 ALOGE("error pushing blank frames: set_usage failed: %s (%d)", 3236 strerror(-err), -err); 3237 goto error; 3238 } 3239 3240 err = mNativeWindow->query(mNativeWindow.get(), 3241 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs); 3242 if (err != NO_ERROR) { 3243 ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query " 3244 "failed: %s (%d)", strerror(-err), -err); 3245 goto error; 3246 } 3247 3248 numBufs = minUndequeuedBufs + 1; 3249 err = native_window_set_buffer_count(mNativeWindow.get(), numBufs); 3250 if (err != NO_ERROR) { 3251 ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)", 3252 strerror(-err), -err); 3253 goto error; 3254 } 3255 3256 // We push numBufs + 1 buffers to ensure that we've drawn into the same 3257 // buffer twice. This should guarantee that the buffer has been displayed 3258 // on the screen and then been replaced, so an previous video frames are 3259 // guaranteed NOT to be currently displayed. 3260 for (int i = 0; i < numBufs + 1; i++) { 3261 int fenceFd = -1; 3262 err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &anb); 3263 if (err != NO_ERROR) { 3264 ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)", 3265 strerror(-err), -err); 3266 goto error; 3267 } 3268 3269 sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); 3270 3271 // Fill the buffer with the a 1x1 checkerboard pattern ;) 3272 uint32_t* img = NULL; 3273 err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); 3274 if (err != NO_ERROR) { 3275 ALOGE("error pushing blank frames: lock failed: %s (%d)", 3276 strerror(-err), -err); 3277 goto error; 3278 } 3279 3280 *img = 0; 3281 3282 err = buf->unlock(); 3283 if (err != NO_ERROR) { 3284 ALOGE("error pushing blank frames: unlock failed: %s (%d)", 3285 strerror(-err), -err); 3286 goto error; 3287 } 3288 3289 err = mNativeWindow->queueBuffer(mNativeWindow.get(), 3290 buf->getNativeBuffer(), -1); 3291 if (err != NO_ERROR) { 3292 ALOGE("error pushing blank frames: queueBuffer failed: %s (%d)", 3293 strerror(-err), -err); 3294 goto error; 3295 } 3296 3297 anb = NULL; 3298 } 3299 3300error: 3301 3302 if (err != NO_ERROR) { 3303 // Clean up after an error. 3304 if (anb != NULL) { 3305 mNativeWindow->cancelBuffer(mNativeWindow.get(), anb, -1); 3306 } 3307 3308 native_window_api_disconnect(mNativeWindow.get(), 3309 NATIVE_WINDOW_API_CPU); 3310 native_window_api_connect(mNativeWindow.get(), 3311 NATIVE_WINDOW_API_MEDIA); 3312 3313 return err; 3314 } else { 3315 // Clean up after success. 3316 err = native_window_api_disconnect(mNativeWindow.get(), 3317 NATIVE_WINDOW_API_CPU); 3318 if (err != NO_ERROR) { 3319 ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)", 3320 strerror(-err), -err); 3321 return err; 3322 } 3323 3324 err = native_window_api_connect(mNativeWindow.get(), 3325 NATIVE_WINDOW_API_MEDIA); 3326 if (err != NO_ERROR) { 3327 ALOGE("error pushing blank frames: api_connect failed: %s (%d)", 3328 strerror(-err), -err); 3329 return err; 3330 } 3331 3332 return NO_ERROR; 3333 } 3334} 3335 3336//////////////////////////////////////////////////////////////////////////////// 3337 3338ACodec::PortDescription::PortDescription() { 3339} 3340 3341status_t ACodec::requestIDRFrame() { 3342 if (!mIsEncoder) { 3343 return ERROR_UNSUPPORTED; 3344 } 3345 3346 OMX_CONFIG_INTRAREFRESHVOPTYPE params; 3347 InitOMXParams(¶ms); 3348 3349 params.nPortIndex = kPortIndexOutput; 3350 params.IntraRefreshVOP = OMX_TRUE; 3351 3352 return mOMX->setConfig( 3353 mNode, 3354 OMX_IndexConfigVideoIntraVOPRefresh, 3355 ¶ms, 3356 sizeof(params)); 3357} 3358 3359void ACodec::PortDescription::addBuffer( 3360 IOMX::buffer_id id, const sp<ABuffer> &buffer) { 3361 mBufferIDs.push_back(id); 3362 mBuffers.push_back(buffer); 3363} 3364 3365size_t ACodec::PortDescription::countBuffers() { 3366 return mBufferIDs.size(); 3367} 3368 3369IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const { 3370 return mBufferIDs.itemAt(index); 3371} 3372 3373sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const { 3374 return mBuffers.itemAt(index); 3375} 3376 3377//////////////////////////////////////////////////////////////////////////////// 3378 3379ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState) 3380 : AState(parentState), 3381 mCodec(codec) { 3382} 3383 3384ACodec::BaseState::PortMode ACodec::BaseState::getPortMode( 3385 OMX_U32 /* portIndex */) { 3386 return KEEP_BUFFERS; 3387} 3388 3389bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) { 3390 switch (msg->what()) { 3391 case kWhatInputBufferFilled: 3392 { 3393 onInputBufferFilled(msg); 3394 break; 3395 } 3396 3397 case kWhatOutputBufferDrained: 3398 { 3399 onOutputBufferDrained(msg); 3400 break; 3401 } 3402 3403 case ACodec::kWhatOMXMessage: 3404 { 3405 return onOMXMessage(msg); 3406 } 3407 3408 case ACodec::kWhatCreateInputSurface: 3409 case ACodec::kWhatSignalEndOfInputStream: 3410 { 3411 ALOGE("Message 0x%x was not handled", msg->what()); 3412 mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION); 3413 return true; 3414 } 3415 3416 case ACodec::kWhatOMXDied: 3417 { 3418 ALOGE("OMX/mediaserver died, signalling error!"); 3419 mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT); 3420 break; 3421 } 3422 3423 default: 3424 return false; 3425 } 3426 3427 return true; 3428} 3429 3430bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) { 3431 int32_t type; 3432 CHECK(msg->findInt32("type", &type)); 3433 3434 // there is a possibility that this is an outstanding message for a 3435 // codec that we have already destroyed 3436 if (mCodec->mNode == NULL) { 3437 ALOGI("ignoring message as already freed component: %s", 3438 msg->debugString().c_str()); 3439 return true; 3440 } 3441 3442 IOMX::node_id nodeID; 3443 CHECK(msg->findInt32("node", (int32_t*)&nodeID)); 3444 CHECK_EQ(nodeID, mCodec->mNode); 3445 3446 switch (type) { 3447 case omx_message::EVENT: 3448 { 3449 int32_t event, data1, data2; 3450 CHECK(msg->findInt32("event", &event)); 3451 CHECK(msg->findInt32("data1", &data1)); 3452 CHECK(msg->findInt32("data2", &data2)); 3453 3454 if (event == OMX_EventCmdComplete 3455 && data1 == OMX_CommandFlush 3456 && data2 == (int32_t)OMX_ALL) { 3457 // Use of this notification is not consistent across 3458 // implementations. We'll drop this notification and rely 3459 // on flush-complete notifications on the individual port 3460 // indices instead. 3461 3462 return true; 3463 } 3464 3465 return onOMXEvent( 3466 static_cast<OMX_EVENTTYPE>(event), 3467 static_cast<OMX_U32>(data1), 3468 static_cast<OMX_U32>(data2)); 3469 } 3470 3471 case omx_message::EMPTY_BUFFER_DONE: 3472 { 3473 IOMX::buffer_id bufferID; 3474 CHECK(msg->findInt32("buffer", (int32_t*)&bufferID)); 3475 3476 return onOMXEmptyBufferDone(bufferID); 3477 } 3478 3479 case omx_message::FILL_BUFFER_DONE: 3480 { 3481 IOMX::buffer_id bufferID; 3482 CHECK(msg->findInt32("buffer", (int32_t*)&bufferID)); 3483 3484 int32_t rangeOffset, rangeLength, flags; 3485 int64_t timeUs; 3486 3487 CHECK(msg->findInt32("range_offset", &rangeOffset)); 3488 CHECK(msg->findInt32("range_length", &rangeLength)); 3489 CHECK(msg->findInt32("flags", &flags)); 3490 CHECK(msg->findInt64("timestamp", &timeUs)); 3491 3492 return onOMXFillBufferDone( 3493 bufferID, 3494 (size_t)rangeOffset, (size_t)rangeLength, 3495 (OMX_U32)flags, 3496 timeUs); 3497 } 3498 3499 default: 3500 TRESPASS(); 3501 break; 3502 } 3503} 3504 3505bool ACodec::BaseState::onOMXEvent( 3506 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3507 if (event != OMX_EventError) { 3508 ALOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)", 3509 mCodec->mComponentName.c_str(), event, data1, data2); 3510 3511 return false; 3512 } 3513 3514 ALOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1); 3515 3516 mCodec->signalError((OMX_ERRORTYPE)data1); 3517 3518 return true; 3519} 3520 3521bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) { 3522 ALOGV("[%s] onOMXEmptyBufferDone %p", 3523 mCodec->mComponentName.c_str(), bufferID); 3524 3525 BufferInfo *info = 3526 mCodec->findBufferByID(kPortIndexInput, bufferID); 3527 3528 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); 3529 info->mStatus = BufferInfo::OWNED_BY_US; 3530 3531 const sp<AMessage> &bufferMeta = info->mData->meta(); 3532 void *mediaBuffer; 3533 if (bufferMeta->findPointer("mediaBuffer", &mediaBuffer) 3534 && mediaBuffer != NULL) { 3535 // We're in "store-metadata-in-buffers" mode, the underlying 3536 // OMX component had access to data that's implicitly refcounted 3537 // by this "mediaBuffer" object. Now that the OMX component has 3538 // told us that it's done with the input buffer, we can decrement 3539 // the mediaBuffer's reference count. 3540 3541 ALOGV("releasing mbuf %p", mediaBuffer); 3542 3543 ((MediaBuffer *)mediaBuffer)->release(); 3544 mediaBuffer = NULL; 3545 3546 bufferMeta->setPointer("mediaBuffer", NULL); 3547 } 3548 3549 PortMode mode = getPortMode(kPortIndexInput); 3550 3551 switch (mode) { 3552 case KEEP_BUFFERS: 3553 break; 3554 3555 case RESUBMIT_BUFFERS: 3556 postFillThisBuffer(info); 3557 break; 3558 3559 default: 3560 { 3561 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 3562 TRESPASS(); // Not currently used 3563 break; 3564 } 3565 } 3566 3567 return true; 3568} 3569 3570void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) { 3571 if (mCodec->mPortEOS[kPortIndexInput]) { 3572 return; 3573 } 3574 3575 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 3576 3577 sp<AMessage> notify = mCodec->mNotify->dup(); 3578 notify->setInt32("what", CodecBase::kWhatFillThisBuffer); 3579 notify->setInt32("buffer-id", info->mBufferID); 3580 3581 info->mData->meta()->clear(); 3582 notify->setBuffer("buffer", info->mData); 3583 3584 sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id()); 3585 reply->setInt32("buffer-id", info->mBufferID); 3586 3587 notify->setMessage("reply", reply); 3588 3589 notify->post(); 3590 3591 info->mStatus = BufferInfo::OWNED_BY_UPSTREAM; 3592} 3593 3594void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { 3595 IOMX::buffer_id bufferID; 3596 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID)); 3597 sp<ABuffer> buffer; 3598 int32_t err = OK; 3599 bool eos = false; 3600 PortMode mode = getPortMode(kPortIndexInput); 3601 3602 if (!msg->findBuffer("buffer", &buffer)) { 3603 /* these are unfilled buffers returned by client */ 3604 CHECK(msg->findInt32("err", &err)); 3605 3606 if (err == OK) { 3607 /* buffers with no errors are returned on MediaCodec.flush */ 3608 mode = KEEP_BUFFERS; 3609 } else { 3610 ALOGV("[%s] saw error %d instead of an input buffer", 3611 mCodec->mComponentName.c_str(), err); 3612 eos = true; 3613 } 3614 3615 buffer.clear(); 3616 } 3617 3618 int32_t tmp; 3619 if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) { 3620 eos = true; 3621 err = ERROR_END_OF_STREAM; 3622 } 3623 3624 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID); 3625 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM); 3626 3627 info->mStatus = BufferInfo::OWNED_BY_US; 3628 3629 switch (mode) { 3630 case KEEP_BUFFERS: 3631 { 3632 if (eos) { 3633 if (!mCodec->mPortEOS[kPortIndexInput]) { 3634 mCodec->mPortEOS[kPortIndexInput] = true; 3635 mCodec->mInputEOSResult = err; 3636 } 3637 } 3638 break; 3639 } 3640 3641 case RESUBMIT_BUFFERS: 3642 { 3643 if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) { 3644 int64_t timeUs; 3645 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 3646 3647 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME; 3648 3649 int32_t isCSD; 3650 if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) { 3651 flags |= OMX_BUFFERFLAG_CODECCONFIG; 3652 } 3653 3654 if (eos) { 3655 flags |= OMX_BUFFERFLAG_EOS; 3656 } 3657 3658 if (buffer != info->mData) { 3659 ALOGV("[%s] Needs to copy input data for buffer %p. (%p != %p)", 3660 mCodec->mComponentName.c_str(), 3661 bufferID, 3662 buffer.get(), info->mData.get()); 3663 3664 CHECK_LE(buffer->size(), info->mData->capacity()); 3665 memcpy(info->mData->data(), buffer->data(), buffer->size()); 3666 } 3667 3668 if (flags & OMX_BUFFERFLAG_CODECCONFIG) { 3669 ALOGV("[%s] calling emptyBuffer %p w/ codec specific data", 3670 mCodec->mComponentName.c_str(), bufferID); 3671 } else if (flags & OMX_BUFFERFLAG_EOS) { 3672 ALOGV("[%s] calling emptyBuffer %p w/ EOS", 3673 mCodec->mComponentName.c_str(), bufferID); 3674 } else { 3675#if TRACK_BUFFER_TIMING 3676 ALOGI("[%s] calling emptyBuffer %p w/ time %lld us", 3677 mCodec->mComponentName.c_str(), bufferID, timeUs); 3678#else 3679 ALOGV("[%s] calling emptyBuffer %p w/ time %lld us", 3680 mCodec->mComponentName.c_str(), bufferID, timeUs); 3681#endif 3682 } 3683 3684#if TRACK_BUFFER_TIMING 3685 ACodec::BufferStats stats; 3686 stats.mEmptyBufferTimeUs = ALooper::GetNowUs(); 3687 stats.mFillBufferDoneTimeUs = -1ll; 3688 mCodec->mBufferStats.add(timeUs, stats); 3689#endif 3690 3691 if (mCodec->mStoreMetaDataInOutputBuffers) { 3692 // try to submit an output buffer for each input buffer 3693 PortMode outputMode = getPortMode(kPortIndexOutput); 3694 3695 ALOGV("MetaDataBuffersToSubmit=%u portMode=%s", 3696 mCodec->mMetaDataBuffersToSubmit, 3697 (outputMode == FREE_BUFFERS ? "FREE" : 3698 outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT")); 3699 if (outputMode == RESUBMIT_BUFFERS) { 3700 CHECK_EQ(mCodec->submitOutputMetaDataBuffer(), 3701 (status_t)OK); 3702 } 3703 } 3704 3705 CHECK_EQ(mCodec->mOMX->emptyBuffer( 3706 mCodec->mNode, 3707 bufferID, 3708 0, 3709 buffer->size(), 3710 flags, 3711 timeUs), 3712 (status_t)OK); 3713 3714 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 3715 3716 if (!eos) { 3717 getMoreInputDataIfPossible(); 3718 } else { 3719 ALOGV("[%s] Signalled EOS on the input port", 3720 mCodec->mComponentName.c_str()); 3721 3722 mCodec->mPortEOS[kPortIndexInput] = true; 3723 mCodec->mInputEOSResult = err; 3724 } 3725 } else if (!mCodec->mPortEOS[kPortIndexInput]) { 3726 if (err != ERROR_END_OF_STREAM) { 3727 ALOGV("[%s] Signalling EOS on the input port " 3728 "due to error %d", 3729 mCodec->mComponentName.c_str(), err); 3730 } else { 3731 ALOGV("[%s] Signalling EOS on the input port", 3732 mCodec->mComponentName.c_str()); 3733 } 3734 3735 ALOGV("[%s] calling emptyBuffer %p signalling EOS", 3736 mCodec->mComponentName.c_str(), bufferID); 3737 3738 CHECK_EQ(mCodec->mOMX->emptyBuffer( 3739 mCodec->mNode, 3740 bufferID, 3741 0, 3742 0, 3743 OMX_BUFFERFLAG_EOS, 3744 0), 3745 (status_t)OK); 3746 3747 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 3748 3749 mCodec->mPortEOS[kPortIndexInput] = true; 3750 mCodec->mInputEOSResult = err; 3751 } 3752 break; 3753 } 3754 3755 default: 3756 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 3757 break; 3758 } 3759} 3760 3761void ACodec::BaseState::getMoreInputDataIfPossible() { 3762 if (mCodec->mPortEOS[kPortIndexInput]) { 3763 return; 3764 } 3765 3766 BufferInfo *eligible = NULL; 3767 3768 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 3769 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 3770 3771#if 0 3772 if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) { 3773 // There's already a "read" pending. 3774 return; 3775 } 3776#endif 3777 3778 if (info->mStatus == BufferInfo::OWNED_BY_US) { 3779 eligible = info; 3780 } 3781 } 3782 3783 if (eligible == NULL) { 3784 return; 3785 } 3786 3787 postFillThisBuffer(eligible); 3788} 3789 3790bool ACodec::BaseState::onOMXFillBufferDone( 3791 IOMX::buffer_id bufferID, 3792 size_t rangeOffset, size_t rangeLength, 3793 OMX_U32 flags, 3794 int64_t timeUs) { 3795 ALOGV("[%s] onOMXFillBufferDone %u time %" PRId64 " us, flags = 0x%08x", 3796 mCodec->mComponentName.c_str(), bufferID, timeUs, flags); 3797 3798 ssize_t index; 3799 3800#if TRACK_BUFFER_TIMING 3801 index = mCodec->mBufferStats.indexOfKey(timeUs); 3802 if (index >= 0) { 3803 ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index); 3804 stats->mFillBufferDoneTimeUs = ALooper::GetNowUs(); 3805 3806 ALOGI("frame PTS %lld: %lld", 3807 timeUs, 3808 stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs); 3809 3810 mCodec->mBufferStats.removeItemsAt(index); 3811 stats = NULL; 3812 } 3813#endif 3814 3815 BufferInfo *info = 3816 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 3817 3818 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); 3819 3820 info->mDequeuedAt = ++mCodec->mDequeueCounter; 3821 info->mStatus = BufferInfo::OWNED_BY_US; 3822 3823 PortMode mode = getPortMode(kPortIndexOutput); 3824 3825 switch (mode) { 3826 case KEEP_BUFFERS: 3827 break; 3828 3829 case RESUBMIT_BUFFERS: 3830 { 3831 if (rangeLength == 0 && !(flags & OMX_BUFFERFLAG_EOS)) { 3832 ALOGV("[%s] calling fillBuffer %u", 3833 mCodec->mComponentName.c_str(), info->mBufferID); 3834 3835 CHECK_EQ(mCodec->mOMX->fillBuffer( 3836 mCodec->mNode, info->mBufferID), 3837 (status_t)OK); 3838 3839 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 3840 break; 3841 } 3842 3843 sp<AMessage> reply = 3844 new AMessage(kWhatOutputBufferDrained, mCodec->id()); 3845 3846 if (!mCodec->mSentFormat && rangeLength > 0) { 3847 mCodec->sendFormatChange(reply); 3848 } 3849 3850 if (mCodec->mUseMetadataOnEncoderOutput) { 3851 native_handle_t* handle = 3852 *(native_handle_t**)(info->mData->data() + 4); 3853 info->mData->meta()->setPointer("handle", handle); 3854 info->mData->meta()->setInt32("rangeOffset", rangeOffset); 3855 info->mData->meta()->setInt32("rangeLength", rangeLength); 3856 } else { 3857 info->mData->setRange(rangeOffset, rangeLength); 3858 } 3859#if 0 3860 if (mCodec->mNativeWindow == NULL) { 3861 if (IsIDR(info->mData)) { 3862 ALOGI("IDR frame"); 3863 } 3864 } 3865#endif 3866 3867 if (mCodec->mSkipCutBuffer != NULL) { 3868 mCodec->mSkipCutBuffer->submit(info->mData); 3869 } 3870 info->mData->meta()->setInt64("timeUs", timeUs); 3871 3872 sp<AMessage> notify = mCodec->mNotify->dup(); 3873 notify->setInt32("what", CodecBase::kWhatDrainThisBuffer); 3874 notify->setInt32("buffer-id", info->mBufferID); 3875 notify->setBuffer("buffer", info->mData); 3876 notify->setInt32("flags", flags); 3877 3878 reply->setInt32("buffer-id", info->mBufferID); 3879 3880 notify->setMessage("reply", reply); 3881 3882 notify->post(); 3883 3884 info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM; 3885 3886 if (flags & OMX_BUFFERFLAG_EOS) { 3887 ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str()); 3888 3889 sp<AMessage> notify = mCodec->mNotify->dup(); 3890 notify->setInt32("what", CodecBase::kWhatEOS); 3891 notify->setInt32("err", mCodec->mInputEOSResult); 3892 notify->post(); 3893 3894 mCodec->mPortEOS[kPortIndexOutput] = true; 3895 } 3896 break; 3897 } 3898 3899 default: 3900 { 3901 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 3902 3903 CHECK_EQ((status_t)OK, 3904 mCodec->freeBuffer(kPortIndexOutput, index)); 3905 break; 3906 } 3907 } 3908 3909 return true; 3910} 3911 3912void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { 3913 IOMX::buffer_id bufferID; 3914 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID)); 3915 ssize_t index; 3916 BufferInfo *info = 3917 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 3918 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM); 3919 3920 android_native_rect_t crop; 3921 if (msg->findRect("crop", 3922 &crop.left, &crop.top, &crop.right, &crop.bottom)) { 3923 CHECK_EQ(0, native_window_set_crop( 3924 mCodec->mNativeWindow.get(), &crop)); 3925 } 3926 3927 int32_t render; 3928 if (mCodec->mNativeWindow != NULL 3929 && msg->findInt32("render", &render) && render != 0 3930 && info->mData != NULL && info->mData->size() != 0) { 3931 ATRACE_NAME("render"); 3932 // The client wants this buffer to be rendered. 3933 3934 int64_t timestampNs = 0; 3935 if (!msg->findInt64("timestampNs", ×tampNs)) { 3936 // TODO: it seems like we should use the timestamp 3937 // in the (media)buffer as it potentially came from 3938 // an input surface, but we did not propagate it prior to 3939 // API 20. Perhaps check for target SDK version. 3940#if 0 3941 if (info->mData->meta()->findInt64("timeUs", ×tampNs)) { 3942 ALOGV("using buffer PTS of %" PRId64, timestampNs); 3943 timestampNs *= 1000; 3944 } 3945#endif 3946 } 3947 3948 status_t err; 3949 err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs); 3950 if (err != OK) { 3951 ALOGW("failed to set buffer timestamp: %d", err); 3952 } 3953 3954 if ((err = mCodec->mNativeWindow->queueBuffer( 3955 mCodec->mNativeWindow.get(), 3956 info->mGraphicBuffer.get(), -1)) == OK) { 3957 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 3958 } else { 3959 mCodec->signalError(OMX_ErrorUndefined, err); 3960 info->mStatus = BufferInfo::OWNED_BY_US; 3961 } 3962 } else { 3963 if (mCodec->mNativeWindow != NULL && 3964 (info->mData == NULL || info->mData->size() != 0)) { 3965 ATRACE_NAME("frame-drop"); 3966 } 3967 info->mStatus = BufferInfo::OWNED_BY_US; 3968 } 3969 3970 PortMode mode = getPortMode(kPortIndexOutput); 3971 3972 switch (mode) { 3973 case KEEP_BUFFERS: 3974 { 3975 // XXX fishy, revisit!!! What about the FREE_BUFFERS case below? 3976 3977 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 3978 // We cannot resubmit the buffer we just rendered, dequeue 3979 // the spare instead. 3980 3981 info = mCodec->dequeueBufferFromNativeWindow(); 3982 } 3983 break; 3984 } 3985 3986 case RESUBMIT_BUFFERS: 3987 { 3988 if (!mCodec->mPortEOS[kPortIndexOutput]) { 3989 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 3990 // We cannot resubmit the buffer we just rendered, dequeue 3991 // the spare instead. 3992 3993 info = mCodec->dequeueBufferFromNativeWindow(); 3994 } 3995 3996 if (info != NULL) { 3997 ALOGV("[%s] calling fillBuffer %u", 3998 mCodec->mComponentName.c_str(), info->mBufferID); 3999 4000 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), 4001 (status_t)OK); 4002 4003 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 4004 } 4005 } 4006 break; 4007 } 4008 4009 default: 4010 { 4011 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 4012 4013 CHECK_EQ((status_t)OK, 4014 mCodec->freeBuffer(kPortIndexOutput, index)); 4015 break; 4016 } 4017 } 4018} 4019 4020//////////////////////////////////////////////////////////////////////////////// 4021 4022ACodec::UninitializedState::UninitializedState(ACodec *codec) 4023 : BaseState(codec) { 4024} 4025 4026void ACodec::UninitializedState::stateEntered() { 4027 ALOGV("Now uninitialized"); 4028 4029 if (mDeathNotifier != NULL) { 4030 mCodec->mOMX->asBinder()->unlinkToDeath(mDeathNotifier); 4031 mDeathNotifier.clear(); 4032 } 4033 4034 mCodec->mNativeWindow.clear(); 4035 mCodec->mNode = NULL; 4036 mCodec->mOMX.clear(); 4037 mCodec->mQuirks = 0; 4038 mCodec->mFlags = 0; 4039 mCodec->mUseMetadataOnEncoderOutput = 0; 4040 mCodec->mComponentName.clear(); 4041} 4042 4043bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) { 4044 bool handled = false; 4045 4046 switch (msg->what()) { 4047 case ACodec::kWhatSetup: 4048 { 4049 onSetup(msg); 4050 4051 handled = true; 4052 break; 4053 } 4054 4055 case ACodec::kWhatAllocateComponent: 4056 { 4057 onAllocateComponent(msg); 4058 handled = true; 4059 break; 4060 } 4061 4062 case ACodec::kWhatShutdown: 4063 { 4064 int32_t keepComponentAllocated; 4065 CHECK(msg->findInt32( 4066 "keepComponentAllocated", &keepComponentAllocated)); 4067 ALOGW_IF(keepComponentAllocated, 4068 "cannot keep component allocated on shutdown in Uninitialized state"); 4069 4070 sp<AMessage> notify = mCodec->mNotify->dup(); 4071 notify->setInt32("what", CodecBase::kWhatShutdownCompleted); 4072 notify->post(); 4073 4074 handled = true; 4075 break; 4076 } 4077 4078 case ACodec::kWhatFlush: 4079 { 4080 sp<AMessage> notify = mCodec->mNotify->dup(); 4081 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 4082 notify->post(); 4083 4084 handled = true; 4085 break; 4086 } 4087 4088 default: 4089 return BaseState::onMessageReceived(msg); 4090 } 4091 4092 return handled; 4093} 4094 4095void ACodec::UninitializedState::onSetup( 4096 const sp<AMessage> &msg) { 4097 if (onAllocateComponent(msg) 4098 && mCodec->mLoadedState->onConfigureComponent(msg)) { 4099 mCodec->mLoadedState->onStart(); 4100 } 4101} 4102 4103bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) { 4104 ALOGV("onAllocateComponent"); 4105 4106 CHECK(mCodec->mNode == NULL); 4107 4108 OMXClient client; 4109 CHECK_EQ(client.connect(), (status_t)OK); 4110 4111 sp<IOMX> omx = client.interface(); 4112 4113 sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec->id()); 4114 4115 mDeathNotifier = new DeathNotifier(notify); 4116 if (omx->asBinder()->linkToDeath(mDeathNotifier) != OK) { 4117 // This was a local binder, if it dies so do we, we won't care 4118 // about any notifications in the afterlife. 4119 mDeathNotifier.clear(); 4120 } 4121 4122 Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs; 4123 4124 AString mime; 4125 4126 AString componentName; 4127 uint32_t quirks = 0; 4128 int32_t encoder = false; 4129 if (msg->findString("componentName", &componentName)) { 4130 ssize_t index = matchingCodecs.add(); 4131 OMXCodec::CodecNameAndQuirks *entry = &matchingCodecs.editItemAt(index); 4132 entry->mName = String8(componentName.c_str()); 4133 4134 if (!OMXCodec::findCodecQuirks( 4135 componentName.c_str(), &entry->mQuirks)) { 4136 entry->mQuirks = 0; 4137 } 4138 } else { 4139 CHECK(msg->findString("mime", &mime)); 4140 4141 if (!msg->findInt32("encoder", &encoder)) { 4142 encoder = false; 4143 } 4144 4145 OMXCodec::findMatchingCodecs( 4146 mime.c_str(), 4147 encoder, // createEncoder 4148 NULL, // matchComponentName 4149 0, // flags 4150 &matchingCodecs); 4151 } 4152 4153 sp<CodecObserver> observer = new CodecObserver; 4154 IOMX::node_id node = NULL; 4155 4156 for (size_t matchIndex = 0; matchIndex < matchingCodecs.size(); 4157 ++matchIndex) { 4158 componentName = matchingCodecs.itemAt(matchIndex).mName.string(); 4159 quirks = matchingCodecs.itemAt(matchIndex).mQuirks; 4160 4161 pid_t tid = androidGetTid(); 4162 int prevPriority = androidGetThreadPriority(tid); 4163 androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND); 4164 status_t err = omx->allocateNode(componentName.c_str(), observer, &node); 4165 androidSetThreadPriority(tid, prevPriority); 4166 4167 if (err == OK) { 4168 break; 4169 } else { 4170 ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str()); 4171 } 4172 4173 node = NULL; 4174 } 4175 4176 if (node == NULL) { 4177 if (!mime.empty()) { 4178 ALOGE("Unable to instantiate a %scoder for type '%s'.", 4179 encoder ? "en" : "de", mime.c_str()); 4180 } else { 4181 ALOGE("Unable to instantiate codec '%s'.", componentName.c_str()); 4182 } 4183 4184 mCodec->signalError(OMX_ErrorComponentNotFound); 4185 return false; 4186 } 4187 4188 notify = new AMessage(kWhatOMXMessage, mCodec->id()); 4189 observer->setNotificationMessage(notify); 4190 4191 mCodec->mComponentName = componentName; 4192 mCodec->mFlags = 0; 4193 4194 if (componentName.endsWith(".secure")) { 4195 mCodec->mFlags |= kFlagIsSecure; 4196 mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown; 4197 } 4198 4199 mCodec->mQuirks = quirks; 4200 mCodec->mOMX = omx; 4201 mCodec->mNode = node; 4202 4203 { 4204 sp<AMessage> notify = mCodec->mNotify->dup(); 4205 notify->setInt32("what", CodecBase::kWhatComponentAllocated); 4206 notify->setString("componentName", mCodec->mComponentName.c_str()); 4207 notify->post(); 4208 } 4209 4210 mCodec->changeState(mCodec->mLoadedState); 4211 4212 return true; 4213} 4214 4215//////////////////////////////////////////////////////////////////////////////// 4216 4217ACodec::LoadedState::LoadedState(ACodec *codec) 4218 : BaseState(codec) { 4219} 4220 4221void ACodec::LoadedState::stateEntered() { 4222 ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str()); 4223 4224 mCodec->mPortEOS[kPortIndexInput] = 4225 mCodec->mPortEOS[kPortIndexOutput] = false; 4226 4227 mCodec->mInputEOSResult = OK; 4228 4229 mCodec->mDequeueCounter = 0; 4230 mCodec->mMetaDataBuffersToSubmit = 0; 4231 mCodec->mRepeatFrameDelayUs = -1ll; 4232 mCodec->mInputFormat.clear(); 4233 mCodec->mOutputFormat.clear(); 4234 4235 if (mCodec->mShutdownInProgress) { 4236 bool keepComponentAllocated = mCodec->mKeepComponentAllocated; 4237 4238 mCodec->mShutdownInProgress = false; 4239 mCodec->mKeepComponentAllocated = false; 4240 4241 onShutdown(keepComponentAllocated); 4242 } 4243 mCodec->mExplicitShutdown = false; 4244} 4245 4246void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) { 4247 if (!keepComponentAllocated) { 4248 CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK); 4249 4250 mCodec->changeState(mCodec->mUninitializedState); 4251 } 4252 4253 if (mCodec->mExplicitShutdown) { 4254 sp<AMessage> notify = mCodec->mNotify->dup(); 4255 notify->setInt32("what", CodecBase::kWhatShutdownCompleted); 4256 notify->post(); 4257 mCodec->mExplicitShutdown = false; 4258 } 4259} 4260 4261bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) { 4262 bool handled = false; 4263 4264 switch (msg->what()) { 4265 case ACodec::kWhatConfigureComponent: 4266 { 4267 onConfigureComponent(msg); 4268 handled = true; 4269 break; 4270 } 4271 4272 case ACodec::kWhatCreateInputSurface: 4273 { 4274 onCreateInputSurface(msg); 4275 handled = true; 4276 break; 4277 } 4278 4279 case ACodec::kWhatStart: 4280 { 4281 onStart(); 4282 handled = true; 4283 break; 4284 } 4285 4286 case ACodec::kWhatShutdown: 4287 { 4288 int32_t keepComponentAllocated; 4289 CHECK(msg->findInt32( 4290 "keepComponentAllocated", &keepComponentAllocated)); 4291 4292 mCodec->mExplicitShutdown = true; 4293 onShutdown(keepComponentAllocated); 4294 4295 handled = true; 4296 break; 4297 } 4298 4299 case ACodec::kWhatFlush: 4300 { 4301 sp<AMessage> notify = mCodec->mNotify->dup(); 4302 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 4303 notify->post(); 4304 4305 handled = true; 4306 break; 4307 } 4308 4309 default: 4310 return BaseState::onMessageReceived(msg); 4311 } 4312 4313 return handled; 4314} 4315 4316bool ACodec::LoadedState::onConfigureComponent( 4317 const sp<AMessage> &msg) { 4318 ALOGV("onConfigureComponent"); 4319 4320 CHECK(mCodec->mNode != NULL); 4321 4322 AString mime; 4323 CHECK(msg->findString("mime", &mime)); 4324 4325 status_t err = mCodec->configureCodec(mime.c_str(), msg); 4326 4327 if (err != OK) { 4328 ALOGE("[%s] configureCodec returning error %d", 4329 mCodec->mComponentName.c_str(), err); 4330 4331 mCodec->signalError(OMX_ErrorUndefined, err); 4332 return false; 4333 } 4334 4335 sp<RefBase> obj; 4336 if (msg->findObject("native-window", &obj) 4337 && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) { 4338 sp<NativeWindowWrapper> nativeWindow( 4339 static_cast<NativeWindowWrapper *>(obj.get())); 4340 CHECK(nativeWindow != NULL); 4341 mCodec->mNativeWindow = nativeWindow->getNativeWindow(); 4342 4343 native_window_set_scaling_mode( 4344 mCodec->mNativeWindow.get(), 4345 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); 4346 } 4347 CHECK_EQ((status_t)OK, mCodec->initNativeWindow()); 4348 4349 { 4350 sp<AMessage> notify = mCodec->mNotify->dup(); 4351 notify->setInt32("what", CodecBase::kWhatComponentConfigured); 4352 notify->setMessage("input-format", mCodec->mInputFormat); 4353 notify->setMessage("output-format", mCodec->mOutputFormat); 4354 notify->post(); 4355 } 4356 4357 return true; 4358} 4359 4360void ACodec::LoadedState::onCreateInputSurface( 4361 const sp<AMessage> & /* msg */) { 4362 ALOGV("onCreateInputSurface"); 4363 4364 sp<AMessage> notify = mCodec->mNotify->dup(); 4365 notify->setInt32("what", CodecBase::kWhatInputSurfaceCreated); 4366 4367 sp<IGraphicBufferProducer> bufferProducer; 4368 status_t err; 4369 4370 err = mCodec->mOMX->createInputSurface(mCodec->mNode, kPortIndexInput, 4371 &bufferProducer); 4372 4373 if (err == OK && mCodec->mRepeatFrameDelayUs > 0ll) { 4374 err = mCodec->mOMX->setInternalOption( 4375 mCodec->mNode, 4376 kPortIndexInput, 4377 IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY, 4378 &mCodec->mRepeatFrameDelayUs, 4379 sizeof(mCodec->mRepeatFrameDelayUs)); 4380 4381 if (err != OK) { 4382 ALOGE("[%s] Unable to configure option to repeat previous " 4383 "frames (err %d)", 4384 mCodec->mComponentName.c_str(), 4385 err); 4386 } 4387 } 4388 4389 if (err == OK && mCodec->mMaxPtsGapUs > 0ll) { 4390 err = mCodec->mOMX->setInternalOption( 4391 mCodec->mNode, 4392 kPortIndexInput, 4393 IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP, 4394 &mCodec->mMaxPtsGapUs, 4395 sizeof(mCodec->mMaxPtsGapUs)); 4396 4397 if (err != OK) { 4398 ALOGE("[%s] Unable to configure max timestamp gap (err %d)", 4399 mCodec->mComponentName.c_str(), 4400 err); 4401 } 4402 } 4403 4404 if (err == OK && mCodec->mTimePerCaptureUs > 0ll 4405 && mCodec->mTimePerFrameUs > 0ll) { 4406 int64_t timeLapse[2]; 4407 timeLapse[0] = mCodec->mTimePerFrameUs; 4408 timeLapse[1] = mCodec->mTimePerCaptureUs; 4409 err = mCodec->mOMX->setInternalOption( 4410 mCodec->mNode, 4411 kPortIndexInput, 4412 IOMX::INTERNAL_OPTION_TIME_LAPSE, 4413 &timeLapse[0], 4414 sizeof(timeLapse)); 4415 4416 if (err != OK) { 4417 ALOGE("[%s] Unable to configure time lapse (err %d)", 4418 mCodec->mComponentName.c_str(), 4419 err); 4420 } 4421 } 4422 4423 if (err == OK && mCodec->mCreateInputBuffersSuspended) { 4424 bool suspend = true; 4425 err = mCodec->mOMX->setInternalOption( 4426 mCodec->mNode, 4427 kPortIndexInput, 4428 IOMX::INTERNAL_OPTION_SUSPEND, 4429 &suspend, 4430 sizeof(suspend)); 4431 4432 if (err != OK) { 4433 ALOGE("[%s] Unable to configure option to suspend (err %d)", 4434 mCodec->mComponentName.c_str(), 4435 err); 4436 } 4437 } 4438 4439 if (err == OK) { 4440 notify->setObject("input-surface", 4441 new BufferProducerWrapper(bufferProducer)); 4442 } else { 4443 // Can't use mCodec->signalError() here -- MediaCodec won't forward 4444 // the error through because it's in the "configured" state. We 4445 // send a kWhatInputSurfaceCreated with an error value instead. 4446 ALOGE("[%s] onCreateInputSurface returning error %d", 4447 mCodec->mComponentName.c_str(), err); 4448 notify->setInt32("err", err); 4449 } 4450 notify->post(); 4451} 4452 4453void ACodec::LoadedState::onStart() { 4454 ALOGV("onStart"); 4455 4456 CHECK_EQ(mCodec->mOMX->sendCommand( 4457 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle), 4458 (status_t)OK); 4459 4460 mCodec->changeState(mCodec->mLoadedToIdleState); 4461} 4462 4463//////////////////////////////////////////////////////////////////////////////// 4464 4465ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec) 4466 : BaseState(codec) { 4467} 4468 4469void ACodec::LoadedToIdleState::stateEntered() { 4470 ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str()); 4471 4472 status_t err; 4473 if ((err = allocateBuffers()) != OK) { 4474 ALOGE("Failed to allocate buffers after transitioning to IDLE state " 4475 "(error 0x%08x)", 4476 err); 4477 4478 mCodec->signalError(OMX_ErrorUndefined, err); 4479 4480 mCodec->changeState(mCodec->mLoadedState); 4481 } 4482} 4483 4484status_t ACodec::LoadedToIdleState::allocateBuffers() { 4485 status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput); 4486 4487 if (err != OK) { 4488 return err; 4489 } 4490 4491 return mCodec->allocateBuffersOnPort(kPortIndexOutput); 4492} 4493 4494bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) { 4495 switch (msg->what()) { 4496 case kWhatSetParameters: 4497 case kWhatShutdown: 4498 { 4499 mCodec->deferMessage(msg); 4500 return true; 4501 } 4502 4503 case kWhatSignalEndOfInputStream: 4504 { 4505 mCodec->onSignalEndOfInputStream(); 4506 return true; 4507 } 4508 4509 case kWhatResume: 4510 { 4511 // We'll be active soon enough. 4512 return true; 4513 } 4514 4515 case kWhatFlush: 4516 { 4517 // We haven't even started yet, so we're flushed alright... 4518 sp<AMessage> notify = mCodec->mNotify->dup(); 4519 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 4520 notify->post(); 4521 return true; 4522 } 4523 4524 default: 4525 return BaseState::onMessageReceived(msg); 4526 } 4527} 4528 4529bool ACodec::LoadedToIdleState::onOMXEvent( 4530 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 4531 switch (event) { 4532 case OMX_EventCmdComplete: 4533 { 4534 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 4535 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); 4536 4537 CHECK_EQ(mCodec->mOMX->sendCommand( 4538 mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting), 4539 (status_t)OK); 4540 4541 mCodec->changeState(mCodec->mIdleToExecutingState); 4542 4543 return true; 4544 } 4545 4546 default: 4547 return BaseState::onOMXEvent(event, data1, data2); 4548 } 4549} 4550 4551//////////////////////////////////////////////////////////////////////////////// 4552 4553ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec) 4554 : BaseState(codec) { 4555} 4556 4557void ACodec::IdleToExecutingState::stateEntered() { 4558 ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str()); 4559} 4560 4561bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) { 4562 switch (msg->what()) { 4563 case kWhatSetParameters: 4564 case kWhatShutdown: 4565 { 4566 mCodec->deferMessage(msg); 4567 return true; 4568 } 4569 4570 case kWhatResume: 4571 { 4572 // We'll be active soon enough. 4573 return true; 4574 } 4575 4576 case kWhatFlush: 4577 { 4578 // We haven't even started yet, so we're flushed alright... 4579 sp<AMessage> notify = mCodec->mNotify->dup(); 4580 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 4581 notify->post(); 4582 4583 return true; 4584 } 4585 4586 case kWhatSignalEndOfInputStream: 4587 { 4588 mCodec->onSignalEndOfInputStream(); 4589 return true; 4590 } 4591 4592 default: 4593 return BaseState::onMessageReceived(msg); 4594 } 4595} 4596 4597bool ACodec::IdleToExecutingState::onOMXEvent( 4598 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 4599 switch (event) { 4600 case OMX_EventCmdComplete: 4601 { 4602 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 4603 CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting); 4604 4605 mCodec->mExecutingState->resume(); 4606 mCodec->changeState(mCodec->mExecutingState); 4607 4608 return true; 4609 } 4610 4611 default: 4612 return BaseState::onOMXEvent(event, data1, data2); 4613 } 4614} 4615 4616//////////////////////////////////////////////////////////////////////////////// 4617 4618ACodec::ExecutingState::ExecutingState(ACodec *codec) 4619 : BaseState(codec), 4620 mActive(false) { 4621} 4622 4623ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode( 4624 OMX_U32 /* portIndex */) { 4625 return RESUBMIT_BUFFERS; 4626} 4627 4628void ACodec::ExecutingState::submitOutputMetaBuffers() { 4629 // submit as many buffers as there are input buffers with the codec 4630 // in case we are in port reconfiguring 4631 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 4632 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 4633 4634 if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) { 4635 if (mCodec->submitOutputMetaDataBuffer() != OK) 4636 break; 4637 } 4638 } 4639 4640 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** 4641 mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround(); 4642} 4643 4644void ACodec::ExecutingState::submitRegularOutputBuffers() { 4645 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) { 4646 BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i); 4647 4648 if (mCodec->mNativeWindow != NULL) { 4649 CHECK(info->mStatus == BufferInfo::OWNED_BY_US 4650 || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW); 4651 4652 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 4653 continue; 4654 } 4655 } else { 4656 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 4657 } 4658 4659 ALOGV("[%s] calling fillBuffer %p", 4660 mCodec->mComponentName.c_str(), info->mBufferID); 4661 4662 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), 4663 (status_t)OK); 4664 4665 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 4666 } 4667} 4668 4669void ACodec::ExecutingState::submitOutputBuffers() { 4670 submitRegularOutputBuffers(); 4671 if (mCodec->mStoreMetaDataInOutputBuffers) { 4672 submitOutputMetaBuffers(); 4673 } 4674} 4675 4676void ACodec::ExecutingState::resume() { 4677 if (mActive) { 4678 ALOGV("[%s] We're already active, no need to resume.", 4679 mCodec->mComponentName.c_str()); 4680 4681 return; 4682 } 4683 4684 submitOutputBuffers(); 4685 4686 // Post all available input buffers 4687 CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u); 4688 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) { 4689 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 4690 if (info->mStatus == BufferInfo::OWNED_BY_US) { 4691 postFillThisBuffer(info); 4692 } 4693 } 4694 4695 mActive = true; 4696} 4697 4698void ACodec::ExecutingState::stateEntered() { 4699 ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str()); 4700 4701 mCodec->processDeferredMessages(); 4702} 4703 4704bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) { 4705 bool handled = false; 4706 4707 switch (msg->what()) { 4708 case kWhatShutdown: 4709 { 4710 int32_t keepComponentAllocated; 4711 CHECK(msg->findInt32( 4712 "keepComponentAllocated", &keepComponentAllocated)); 4713 4714 mCodec->mShutdownInProgress = true; 4715 mCodec->mExplicitShutdown = true; 4716 mCodec->mKeepComponentAllocated = keepComponentAllocated; 4717 4718 mActive = false; 4719 4720 CHECK_EQ(mCodec->mOMX->sendCommand( 4721 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle), 4722 (status_t)OK); 4723 4724 mCodec->changeState(mCodec->mExecutingToIdleState); 4725 4726 handled = true; 4727 break; 4728 } 4729 4730 case kWhatFlush: 4731 { 4732 ALOGV("[%s] ExecutingState flushing now " 4733 "(codec owns %d/%d input, %d/%d output).", 4734 mCodec->mComponentName.c_str(), 4735 mCodec->countBuffersOwnedByComponent(kPortIndexInput), 4736 mCodec->mBuffers[kPortIndexInput].size(), 4737 mCodec->countBuffersOwnedByComponent(kPortIndexOutput), 4738 mCodec->mBuffers[kPortIndexOutput].size()); 4739 4740 mActive = false; 4741 4742 CHECK_EQ(mCodec->mOMX->sendCommand( 4743 mCodec->mNode, OMX_CommandFlush, OMX_ALL), 4744 (status_t)OK); 4745 4746 mCodec->changeState(mCodec->mFlushingState); 4747 handled = true; 4748 break; 4749 } 4750 4751 case kWhatResume: 4752 { 4753 resume(); 4754 4755 handled = true; 4756 break; 4757 } 4758 4759 case kWhatRequestIDRFrame: 4760 { 4761 status_t err = mCodec->requestIDRFrame(); 4762 if (err != OK) { 4763 ALOGW("Requesting an IDR frame failed."); 4764 } 4765 4766 handled = true; 4767 break; 4768 } 4769 4770 case kWhatSetParameters: 4771 { 4772 sp<AMessage> params; 4773 CHECK(msg->findMessage("params", ¶ms)); 4774 4775 status_t err = mCodec->setParameters(params); 4776 4777 sp<AMessage> reply; 4778 if (msg->findMessage("reply", &reply)) { 4779 reply->setInt32("err", err); 4780 reply->post(); 4781 } 4782 4783 handled = true; 4784 break; 4785 } 4786 4787 case ACodec::kWhatSignalEndOfInputStream: 4788 { 4789 mCodec->onSignalEndOfInputStream(); 4790 handled = true; 4791 break; 4792 } 4793 4794 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** 4795 case kWhatSubmitOutputMetaDataBufferIfEOS: 4796 { 4797 if (mCodec->mPortEOS[kPortIndexInput] && 4798 !mCodec->mPortEOS[kPortIndexOutput]) { 4799 status_t err = mCodec->submitOutputMetaDataBuffer(); 4800 if (err == OK) { 4801 mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround(); 4802 } 4803 } 4804 return true; 4805 } 4806 4807 default: 4808 handled = BaseState::onMessageReceived(msg); 4809 break; 4810 } 4811 4812 return handled; 4813} 4814 4815status_t ACodec::setParameters(const sp<AMessage> ¶ms) { 4816 int32_t videoBitrate; 4817 if (params->findInt32("video-bitrate", &videoBitrate)) { 4818 OMX_VIDEO_CONFIG_BITRATETYPE configParams; 4819 InitOMXParams(&configParams); 4820 configParams.nPortIndex = kPortIndexOutput; 4821 configParams.nEncodeBitrate = videoBitrate; 4822 4823 status_t err = mOMX->setConfig( 4824 mNode, 4825 OMX_IndexConfigVideoBitrate, 4826 &configParams, 4827 sizeof(configParams)); 4828 4829 if (err != OK) { 4830 ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d", 4831 videoBitrate, err); 4832 4833 return err; 4834 } 4835 } 4836 4837 int64_t skipFramesBeforeUs; 4838 if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) { 4839 status_t err = 4840 mOMX->setInternalOption( 4841 mNode, 4842 kPortIndexInput, 4843 IOMX::INTERNAL_OPTION_START_TIME, 4844 &skipFramesBeforeUs, 4845 sizeof(skipFramesBeforeUs)); 4846 4847 if (err != OK) { 4848 ALOGE("Failed to set parameter 'skip-frames-before' (err %d)", err); 4849 return err; 4850 } 4851 } 4852 4853 int32_t dropInputFrames; 4854 if (params->findInt32("drop-input-frames", &dropInputFrames)) { 4855 bool suspend = dropInputFrames != 0; 4856 4857 status_t err = 4858 mOMX->setInternalOption( 4859 mNode, 4860 kPortIndexInput, 4861 IOMX::INTERNAL_OPTION_SUSPEND, 4862 &suspend, 4863 sizeof(suspend)); 4864 4865 if (err != OK) { 4866 ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err); 4867 return err; 4868 } 4869 } 4870 4871 int32_t dummy; 4872 if (params->findInt32("request-sync", &dummy)) { 4873 status_t err = requestIDRFrame(); 4874 4875 if (err != OK) { 4876 ALOGE("Requesting a sync frame failed w/ err %d", err); 4877 return err; 4878 } 4879 } 4880 4881 return OK; 4882} 4883 4884void ACodec::onSignalEndOfInputStream() { 4885 sp<AMessage> notify = mNotify->dup(); 4886 notify->setInt32("what", CodecBase::kWhatSignaledInputEOS); 4887 4888 status_t err = mOMX->signalEndOfInputStream(mNode); 4889 if (err != OK) { 4890 notify->setInt32("err", err); 4891 } 4892 notify->post(); 4893} 4894 4895bool ACodec::ExecutingState::onOMXEvent( 4896 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 4897 switch (event) { 4898 case OMX_EventPortSettingsChanged: 4899 { 4900 CHECK_EQ(data1, (OMX_U32)kPortIndexOutput); 4901 4902 if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) { 4903 mCodec->mMetaDataBuffersToSubmit = 0; 4904 CHECK_EQ(mCodec->mOMX->sendCommand( 4905 mCodec->mNode, 4906 OMX_CommandPortDisable, kPortIndexOutput), 4907 (status_t)OK); 4908 4909 mCodec->freeOutputBuffersNotOwnedByComponent(); 4910 4911 mCodec->changeState(mCodec->mOutputPortSettingsChangedState); 4912 } else if (data2 == OMX_IndexConfigCommonOutputCrop) { 4913 mCodec->mSentFormat = false; 4914 } else { 4915 ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx", 4916 mCodec->mComponentName.c_str(), data2); 4917 } 4918 4919 return true; 4920 } 4921 4922 case OMX_EventBufferFlag: 4923 { 4924 return true; 4925 } 4926 4927 default: 4928 return BaseState::onOMXEvent(event, data1, data2); 4929 } 4930} 4931 4932//////////////////////////////////////////////////////////////////////////////// 4933 4934ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState( 4935 ACodec *codec) 4936 : BaseState(codec) { 4937} 4938 4939ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode( 4940 OMX_U32 portIndex) { 4941 if (portIndex == kPortIndexOutput) { 4942 return FREE_BUFFERS; 4943 } 4944 4945 CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput); 4946 4947 return RESUBMIT_BUFFERS; 4948} 4949 4950bool ACodec::OutputPortSettingsChangedState::onMessageReceived( 4951 const sp<AMessage> &msg) { 4952 bool handled = false; 4953 4954 switch (msg->what()) { 4955 case kWhatFlush: 4956 case kWhatShutdown: 4957 case kWhatResume: 4958 { 4959 if (msg->what() == kWhatResume) { 4960 ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str()); 4961 } 4962 4963 mCodec->deferMessage(msg); 4964 handled = true; 4965 break; 4966 } 4967 4968 default: 4969 handled = BaseState::onMessageReceived(msg); 4970 break; 4971 } 4972 4973 return handled; 4974} 4975 4976void ACodec::OutputPortSettingsChangedState::stateEntered() { 4977 ALOGV("[%s] Now handling output port settings change", 4978 mCodec->mComponentName.c_str()); 4979} 4980 4981bool ACodec::OutputPortSettingsChangedState::onOMXEvent( 4982 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 4983 switch (event) { 4984 case OMX_EventCmdComplete: 4985 { 4986 if (data1 == (OMX_U32)OMX_CommandPortDisable) { 4987 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput); 4988 4989 ALOGV("[%s] Output port now disabled.", 4990 mCodec->mComponentName.c_str()); 4991 4992 CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty()); 4993 mCodec->mDealer[kPortIndexOutput].clear(); 4994 4995 CHECK_EQ(mCodec->mOMX->sendCommand( 4996 mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput), 4997 (status_t)OK); 4998 4999 status_t err; 5000 if ((err = mCodec->allocateBuffersOnPort( 5001 kPortIndexOutput)) != OK) { 5002 ALOGE("Failed to allocate output port buffers after " 5003 "port reconfiguration (error 0x%08x)", 5004 err); 5005 5006 mCodec->signalError(OMX_ErrorUndefined, err); 5007 5008 // This is technically not correct, but appears to be 5009 // the only way to free the component instance. 5010 // Controlled transitioning from excecuting->idle 5011 // and idle->loaded seem impossible probably because 5012 // the output port never finishes re-enabling. 5013 mCodec->mShutdownInProgress = true; 5014 mCodec->mKeepComponentAllocated = false; 5015 mCodec->changeState(mCodec->mLoadedState); 5016 } 5017 5018 return true; 5019 } else if (data1 == (OMX_U32)OMX_CommandPortEnable) { 5020 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput); 5021 5022 mCodec->mSentFormat = false; 5023 5024 ALOGV("[%s] Output port now reenabled.", 5025 mCodec->mComponentName.c_str()); 5026 5027 if (mCodec->mExecutingState->active()) { 5028 mCodec->mExecutingState->submitOutputBuffers(); 5029 } 5030 5031 mCodec->changeState(mCodec->mExecutingState); 5032 5033 return true; 5034 } 5035 5036 return false; 5037 } 5038 5039 default: 5040 return false; 5041 } 5042} 5043 5044//////////////////////////////////////////////////////////////////////////////// 5045 5046ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec) 5047 : BaseState(codec), 5048 mComponentNowIdle(false) { 5049} 5050 5051bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) { 5052 bool handled = false; 5053 5054 switch (msg->what()) { 5055 case kWhatFlush: 5056 { 5057 // Don't send me a flush request if you previously wanted me 5058 // to shutdown. 5059 TRESPASS(); 5060 break; 5061 } 5062 5063 case kWhatShutdown: 5064 { 5065 // We're already doing that... 5066 5067 handled = true; 5068 break; 5069 } 5070 5071 default: 5072 handled = BaseState::onMessageReceived(msg); 5073 break; 5074 } 5075 5076 return handled; 5077} 5078 5079void ACodec::ExecutingToIdleState::stateEntered() { 5080 ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str()); 5081 5082 mComponentNowIdle = false; 5083 mCodec->mSentFormat = false; 5084} 5085 5086bool ACodec::ExecutingToIdleState::onOMXEvent( 5087 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 5088 switch (event) { 5089 case OMX_EventCmdComplete: 5090 { 5091 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 5092 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); 5093 5094 mComponentNowIdle = true; 5095 5096 changeStateIfWeOwnAllBuffers(); 5097 5098 return true; 5099 } 5100 5101 case OMX_EventPortSettingsChanged: 5102 case OMX_EventBufferFlag: 5103 { 5104 // We're shutting down and don't care about this anymore. 5105 return true; 5106 } 5107 5108 default: 5109 return BaseState::onOMXEvent(event, data1, data2); 5110 } 5111} 5112 5113void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() { 5114 if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) { 5115 CHECK_EQ(mCodec->mOMX->sendCommand( 5116 mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded), 5117 (status_t)OK); 5118 5119 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK); 5120 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK); 5121 5122 if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown) 5123 && mCodec->mNativeWindow != NULL) { 5124 // We push enough 1x1 blank buffers to ensure that one of 5125 // them has made it to the display. This allows the OMX 5126 // component teardown to zero out any protected buffers 5127 // without the risk of scanning out one of those buffers. 5128 mCodec->pushBlankBuffersToNativeWindow(); 5129 } 5130 5131 mCodec->changeState(mCodec->mIdleToLoadedState); 5132 } 5133} 5134 5135void ACodec::ExecutingToIdleState::onInputBufferFilled( 5136 const sp<AMessage> &msg) { 5137 BaseState::onInputBufferFilled(msg); 5138 5139 changeStateIfWeOwnAllBuffers(); 5140} 5141 5142void ACodec::ExecutingToIdleState::onOutputBufferDrained( 5143 const sp<AMessage> &msg) { 5144 BaseState::onOutputBufferDrained(msg); 5145 5146 changeStateIfWeOwnAllBuffers(); 5147} 5148 5149//////////////////////////////////////////////////////////////////////////////// 5150 5151ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec) 5152 : BaseState(codec) { 5153} 5154 5155bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) { 5156 bool handled = false; 5157 5158 switch (msg->what()) { 5159 case kWhatShutdown: 5160 { 5161 // We're already doing that... 5162 5163 handled = true; 5164 break; 5165 } 5166 5167 case kWhatFlush: 5168 { 5169 // Don't send me a flush request if you previously wanted me 5170 // to shutdown. 5171 TRESPASS(); 5172 break; 5173 } 5174 5175 default: 5176 handled = BaseState::onMessageReceived(msg); 5177 break; 5178 } 5179 5180 return handled; 5181} 5182 5183void ACodec::IdleToLoadedState::stateEntered() { 5184 ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str()); 5185} 5186 5187bool ACodec::IdleToLoadedState::onOMXEvent( 5188 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 5189 switch (event) { 5190 case OMX_EventCmdComplete: 5191 { 5192 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 5193 CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded); 5194 5195 mCodec->changeState(mCodec->mLoadedState); 5196 5197 return true; 5198 } 5199 5200 default: 5201 return BaseState::onOMXEvent(event, data1, data2); 5202 } 5203} 5204 5205//////////////////////////////////////////////////////////////////////////////// 5206 5207ACodec::FlushingState::FlushingState(ACodec *codec) 5208 : BaseState(codec) { 5209} 5210 5211void ACodec::FlushingState::stateEntered() { 5212 ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str()); 5213 5214 mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false; 5215} 5216 5217bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) { 5218 bool handled = false; 5219 5220 switch (msg->what()) { 5221 case kWhatShutdown: 5222 { 5223 mCodec->deferMessage(msg); 5224 break; 5225 } 5226 5227 case kWhatFlush: 5228 { 5229 // We're already doing this right now. 5230 handled = true; 5231 break; 5232 } 5233 5234 default: 5235 handled = BaseState::onMessageReceived(msg); 5236 break; 5237 } 5238 5239 return handled; 5240} 5241 5242bool ACodec::FlushingState::onOMXEvent( 5243 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 5244 ALOGV("[%s] FlushingState onOMXEvent(%d,%ld)", 5245 mCodec->mComponentName.c_str(), event, data1); 5246 5247 switch (event) { 5248 case OMX_EventCmdComplete: 5249 { 5250 CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush); 5251 5252 if (data2 == kPortIndexInput || data2 == kPortIndexOutput) { 5253 CHECK(!mFlushComplete[data2]); 5254 mFlushComplete[data2] = true; 5255 5256 if (mFlushComplete[kPortIndexInput] 5257 && mFlushComplete[kPortIndexOutput]) { 5258 changeStateIfWeOwnAllBuffers(); 5259 } 5260 } else { 5261 CHECK_EQ(data2, OMX_ALL); 5262 CHECK(mFlushComplete[kPortIndexInput]); 5263 CHECK(mFlushComplete[kPortIndexOutput]); 5264 5265 changeStateIfWeOwnAllBuffers(); 5266 } 5267 5268 return true; 5269 } 5270 5271 case OMX_EventPortSettingsChanged: 5272 { 5273 sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id()); 5274 msg->setInt32("type", omx_message::EVENT); 5275 msg->setInt32("node", mCodec->mNode); 5276 msg->setInt32("event", event); 5277 msg->setInt32("data1", data1); 5278 msg->setInt32("data2", data2); 5279 5280 ALOGV("[%s] Deferring OMX_EventPortSettingsChanged", 5281 mCodec->mComponentName.c_str()); 5282 5283 mCodec->deferMessage(msg); 5284 5285 return true; 5286 } 5287 5288 default: 5289 return BaseState::onOMXEvent(event, data1, data2); 5290 } 5291 5292 return true; 5293} 5294 5295void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) { 5296 BaseState::onOutputBufferDrained(msg); 5297 5298 changeStateIfWeOwnAllBuffers(); 5299} 5300 5301void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) { 5302 BaseState::onInputBufferFilled(msg); 5303 5304 changeStateIfWeOwnAllBuffers(); 5305} 5306 5307void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() { 5308 if (mFlushComplete[kPortIndexInput] 5309 && mFlushComplete[kPortIndexOutput] 5310 && mCodec->allYourBuffersAreBelongToUs()) { 5311 // We now own all buffers except possibly those still queued with 5312 // the native window for rendering. Let's get those back as well. 5313 mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs(); 5314 5315 sp<AMessage> notify = mCodec->mNotify->dup(); 5316 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 5317 notify->post(); 5318 5319 mCodec->mPortEOS[kPortIndexInput] = 5320 mCodec->mPortEOS[kPortIndexOutput] = false; 5321 5322 mCodec->mInputEOSResult = OK; 5323 5324 if (mCodec->mSkipCutBuffer != NULL) { 5325 mCodec->mSkipCutBuffer->clear(); 5326 } 5327 5328 mCodec->changeState(mCodec->mExecutingState); 5329 } 5330} 5331 5332} // namespace android 5333