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