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