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