ACodec.cpp revision 6610a7d621c634fe059b855ca7eb3f58fb8d0757
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 CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar 1456 || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar 1457 || format.eColorFormat == OMX_COLOR_FormatCbYCrY 1458 || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar 1459 || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar 1460 || format.eColorFormat == OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka 1461 || format.eColorFormat == OMX_SEC_COLOR_FormatNV12Tiled); 1462 1463 return mOMX->setParameter( 1464 mNode, OMX_IndexParamVideoPortFormat, 1465 &format, sizeof(format)); 1466} 1467 1468static status_t GetVideoCodingTypeFromMime( 1469 const char *mime, OMX_VIDEO_CODINGTYPE *codingType) { 1470 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 1471 *codingType = OMX_VIDEO_CodingAVC; 1472 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 1473 *codingType = OMX_VIDEO_CodingMPEG4; 1474 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 1475 *codingType = OMX_VIDEO_CodingH263; 1476 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG2, mime)) { 1477 *codingType = OMX_VIDEO_CodingMPEG2; 1478 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_VPX, mime)) { 1479 *codingType = OMX_VIDEO_CodingVPX; 1480 } else { 1481 *codingType = OMX_VIDEO_CodingUnused; 1482 return ERROR_UNSUPPORTED; 1483 } 1484 1485 return OK; 1486} 1487 1488status_t ACodec::setupVideoDecoder( 1489 const char *mime, int32_t width, int32_t height) { 1490 OMX_VIDEO_CODINGTYPE compressionFormat; 1491 status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat); 1492 1493 if (err != OK) { 1494 return err; 1495 } 1496 1497 err = setVideoPortFormatType( 1498 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused); 1499 1500 if (err != OK) { 1501 return err; 1502 } 1503 1504 err = setSupportedOutputFormat(); 1505 1506 if (err != OK) { 1507 return err; 1508 } 1509 1510 err = setVideoFormatOnPort( 1511 kPortIndexInput, width, height, compressionFormat); 1512 1513 if (err != OK) { 1514 return err; 1515 } 1516 1517 err = setVideoFormatOnPort( 1518 kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused); 1519 1520 if (err != OK) { 1521 return err; 1522 } 1523 1524 return OK; 1525} 1526 1527status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) { 1528 int32_t tmp; 1529 if (!msg->findInt32("color-format", &tmp)) { 1530 return INVALID_OPERATION; 1531 } 1532 1533 OMX_COLOR_FORMATTYPE colorFormat = 1534 static_cast<OMX_COLOR_FORMATTYPE>(tmp); 1535 1536 status_t err = setVideoPortFormatType( 1537 kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat); 1538 1539 if (err != OK) { 1540 ALOGE("[%s] does not support color format %d", 1541 mComponentName.c_str(), colorFormat); 1542 1543 return err; 1544 } 1545 1546 /* Input port configuration */ 1547 1548 OMX_PARAM_PORTDEFINITIONTYPE def; 1549 InitOMXParams(&def); 1550 1551 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 1552 1553 def.nPortIndex = kPortIndexInput; 1554 1555 err = mOMX->getParameter( 1556 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1557 1558 if (err != OK) { 1559 return err; 1560 } 1561 1562 int32_t width, height, bitrate; 1563 if (!msg->findInt32("width", &width) 1564 || !msg->findInt32("height", &height) 1565 || !msg->findInt32("bitrate", &bitrate)) { 1566 return INVALID_OPERATION; 1567 } 1568 1569 video_def->nFrameWidth = width; 1570 video_def->nFrameHeight = height; 1571 1572 int32_t stride; 1573 if (!msg->findInt32("stride", &stride)) { 1574 stride = width; 1575 } 1576 1577 video_def->nStride = stride; 1578 1579 int32_t sliceHeight; 1580 if (!msg->findInt32("slice-height", &sliceHeight)) { 1581 sliceHeight = height; 1582 } 1583 1584 video_def->nSliceHeight = sliceHeight; 1585 1586 def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2; 1587 1588 float frameRate; 1589 if (!msg->findFloat("frame-rate", &frameRate)) { 1590 int32_t tmp; 1591 if (!msg->findInt32("frame-rate", &tmp)) { 1592 return INVALID_OPERATION; 1593 } 1594 frameRate = (float)tmp; 1595 } 1596 1597 video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f); 1598 video_def->eCompressionFormat = OMX_VIDEO_CodingUnused; 1599 video_def->eColorFormat = colorFormat; 1600 1601 err = mOMX->setParameter( 1602 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1603 1604 if (err != OK) { 1605 ALOGE("[%s] failed to set input port definition parameters.", 1606 mComponentName.c_str()); 1607 1608 return err; 1609 } 1610 1611 /* Output port configuration */ 1612 1613 OMX_VIDEO_CODINGTYPE compressionFormat; 1614 err = GetVideoCodingTypeFromMime(mime, &compressionFormat); 1615 1616 if (err != OK) { 1617 return err; 1618 } 1619 1620 err = setVideoPortFormatType( 1621 kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused); 1622 1623 if (err != OK) { 1624 ALOGE("[%s] does not support compression format %d", 1625 mComponentName.c_str(), compressionFormat); 1626 1627 return err; 1628 } 1629 1630 def.nPortIndex = kPortIndexOutput; 1631 1632 err = mOMX->getParameter( 1633 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1634 1635 if (err != OK) { 1636 return err; 1637 } 1638 1639 video_def->nFrameWidth = width; 1640 video_def->nFrameHeight = height; 1641 video_def->xFramerate = 0; 1642 video_def->nBitrate = bitrate; 1643 video_def->eCompressionFormat = compressionFormat; 1644 video_def->eColorFormat = OMX_COLOR_FormatUnused; 1645 1646 err = mOMX->setParameter( 1647 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1648 1649 if (err != OK) { 1650 ALOGE("[%s] failed to set output port definition parameters.", 1651 mComponentName.c_str()); 1652 1653 return err; 1654 } 1655 1656 switch (compressionFormat) { 1657 case OMX_VIDEO_CodingMPEG4: 1658 err = setupMPEG4EncoderParameters(msg); 1659 break; 1660 1661 case OMX_VIDEO_CodingH263: 1662 err = setupH263EncoderParameters(msg); 1663 break; 1664 1665 case OMX_VIDEO_CodingAVC: 1666 err = setupAVCEncoderParameters(msg); 1667 break; 1668 1669 default: 1670 break; 1671 } 1672 1673 ALOGI("setupVideoEncoder succeeded"); 1674 1675 return err; 1676} 1677 1678status_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) { 1679 OMX_VIDEO_PARAM_INTRAREFRESHTYPE params; 1680 InitOMXParams(¶ms); 1681 params.nPortIndex = kPortIndexOutput; 1682 1683 params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode); 1684 1685 if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic || 1686 params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) { 1687 int32_t mbs; 1688 if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) { 1689 return INVALID_OPERATION; 1690 } 1691 params.nCirMBs = mbs; 1692 } 1693 1694 if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive || 1695 params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) { 1696 int32_t mbs; 1697 if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) { 1698 return INVALID_OPERATION; 1699 } 1700 params.nAirMBs = mbs; 1701 1702 int32_t ref; 1703 if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) { 1704 return INVALID_OPERATION; 1705 } 1706 params.nAirRef = ref; 1707 } 1708 1709 status_t err = mOMX->setParameter( 1710 mNode, OMX_IndexParamVideoIntraRefresh, 1711 ¶ms, sizeof(params)); 1712 return err; 1713} 1714 1715static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) { 1716 if (iFramesInterval < 0) { 1717 return 0xFFFFFFFF; 1718 } else if (iFramesInterval == 0) { 1719 return 0; 1720 } 1721 OMX_U32 ret = frameRate * iFramesInterval; 1722 CHECK(ret > 1); 1723 return ret; 1724} 1725 1726static OMX_VIDEO_CONTROLRATETYPE getBitrateMode(const sp<AMessage> &msg) { 1727 int32_t tmp; 1728 if (!msg->findInt32("bitrate-mode", &tmp)) { 1729 return OMX_Video_ControlRateVariable; 1730 } 1731 1732 return static_cast<OMX_VIDEO_CONTROLRATETYPE>(tmp); 1733} 1734 1735status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) { 1736 int32_t bitrate, iFrameInterval; 1737 if (!msg->findInt32("bitrate", &bitrate) 1738 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 1739 return INVALID_OPERATION; 1740 } 1741 1742 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 1743 1744 float frameRate; 1745 if (!msg->findFloat("frame-rate", &frameRate)) { 1746 int32_t tmp; 1747 if (!msg->findInt32("frame-rate", &tmp)) { 1748 return INVALID_OPERATION; 1749 } 1750 frameRate = (float)tmp; 1751 } 1752 1753 OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type; 1754 InitOMXParams(&mpeg4type); 1755 mpeg4type.nPortIndex = kPortIndexOutput; 1756 1757 status_t err = mOMX->getParameter( 1758 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); 1759 1760 if (err != OK) { 1761 return err; 1762 } 1763 1764 mpeg4type.nSliceHeaderSpacing = 0; 1765 mpeg4type.bSVH = OMX_FALSE; 1766 mpeg4type.bGov = OMX_FALSE; 1767 1768 mpeg4type.nAllowedPictureTypes = 1769 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 1770 1771 mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 1772 if (mpeg4type.nPFrames == 0) { 1773 mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 1774 } 1775 mpeg4type.nBFrames = 0; 1776 mpeg4type.nIDCVLCThreshold = 0; 1777 mpeg4type.bACPred = OMX_TRUE; 1778 mpeg4type.nMaxPacketSize = 256; 1779 mpeg4type.nTimeIncRes = 1000; 1780 mpeg4type.nHeaderExtension = 0; 1781 mpeg4type.bReversibleVLC = OMX_FALSE; 1782 1783 int32_t profile; 1784 if (msg->findInt32("profile", &profile)) { 1785 int32_t level; 1786 if (!msg->findInt32("level", &level)) { 1787 return INVALID_OPERATION; 1788 } 1789 1790 err = verifySupportForProfileAndLevel(profile, level); 1791 1792 if (err != OK) { 1793 return err; 1794 } 1795 1796 mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile); 1797 mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level); 1798 } 1799 1800 err = mOMX->setParameter( 1801 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); 1802 1803 if (err != OK) { 1804 return err; 1805 } 1806 1807 err = configureBitrate(bitrate, bitrateMode); 1808 1809 if (err != OK) { 1810 return err; 1811 } 1812 1813 return setupErrorCorrectionParameters(); 1814} 1815 1816status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) { 1817 int32_t bitrate, iFrameInterval; 1818 if (!msg->findInt32("bitrate", &bitrate) 1819 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 1820 return INVALID_OPERATION; 1821 } 1822 1823 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 1824 1825 float frameRate; 1826 if (!msg->findFloat("frame-rate", &frameRate)) { 1827 int32_t tmp; 1828 if (!msg->findInt32("frame-rate", &tmp)) { 1829 return INVALID_OPERATION; 1830 } 1831 frameRate = (float)tmp; 1832 } 1833 1834 OMX_VIDEO_PARAM_H263TYPE h263type; 1835 InitOMXParams(&h263type); 1836 h263type.nPortIndex = kPortIndexOutput; 1837 1838 status_t err = mOMX->getParameter( 1839 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); 1840 1841 if (err != OK) { 1842 return err; 1843 } 1844 1845 h263type.nAllowedPictureTypes = 1846 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 1847 1848 h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 1849 if (h263type.nPFrames == 0) { 1850 h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 1851 } 1852 h263type.nBFrames = 0; 1853 1854 int32_t profile; 1855 if (msg->findInt32("profile", &profile)) { 1856 int32_t level; 1857 if (!msg->findInt32("level", &level)) { 1858 return INVALID_OPERATION; 1859 } 1860 1861 err = verifySupportForProfileAndLevel(profile, level); 1862 1863 if (err != OK) { 1864 return err; 1865 } 1866 1867 h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile); 1868 h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level); 1869 } 1870 1871 h263type.bPLUSPTYPEAllowed = OMX_FALSE; 1872 h263type.bForceRoundingTypeToZero = OMX_FALSE; 1873 h263type.nPictureHeaderRepetition = 0; 1874 h263type.nGOBHeaderInterval = 0; 1875 1876 err = mOMX->setParameter( 1877 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); 1878 1879 if (err != OK) { 1880 return err; 1881 } 1882 1883 err = configureBitrate(bitrate, bitrateMode); 1884 1885 if (err != OK) { 1886 return err; 1887 } 1888 1889 return setupErrorCorrectionParameters(); 1890} 1891 1892status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) { 1893 int32_t bitrate, iFrameInterval; 1894 if (!msg->findInt32("bitrate", &bitrate) 1895 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 1896 return INVALID_OPERATION; 1897 } 1898 1899 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 1900 1901 float frameRate; 1902 if (!msg->findFloat("frame-rate", &frameRate)) { 1903 int32_t tmp; 1904 if (!msg->findInt32("frame-rate", &tmp)) { 1905 return INVALID_OPERATION; 1906 } 1907 frameRate = (float)tmp; 1908 } 1909 1910 status_t err = OK; 1911 int32_t intraRefreshMode = 0; 1912 if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) { 1913 err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode); 1914 if (err != OK) { 1915 ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x", 1916 err, intraRefreshMode); 1917 return err; 1918 } 1919 } 1920 1921 OMX_VIDEO_PARAM_AVCTYPE h264type; 1922 InitOMXParams(&h264type); 1923 h264type.nPortIndex = kPortIndexOutput; 1924 1925 err = mOMX->getParameter( 1926 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 1927 1928 if (err != OK) { 1929 return err; 1930 } 1931 1932 h264type.nAllowedPictureTypes = 1933 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 1934 1935 int32_t profile; 1936 if (msg->findInt32("profile", &profile)) { 1937 int32_t level; 1938 if (!msg->findInt32("level", &level)) { 1939 return INVALID_OPERATION; 1940 } 1941 1942 err = verifySupportForProfileAndLevel(profile, level); 1943 1944 if (err != OK) { 1945 return err; 1946 } 1947 1948 h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile); 1949 h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level); 1950 } 1951 1952 // XXX 1953 if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) { 1954 ALOGW("Use baseline profile instead of %d for AVC recording", 1955 h264type.eProfile); 1956 h264type.eProfile = OMX_VIDEO_AVCProfileBaseline; 1957 } 1958 1959 if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) { 1960 h264type.nSliceHeaderSpacing = 0; 1961 h264type.bUseHadamard = OMX_TRUE; 1962 h264type.nRefFrames = 1; 1963 h264type.nBFrames = 0; 1964 h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 1965 if (h264type.nPFrames == 0) { 1966 h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 1967 } 1968 h264type.nRefIdx10ActiveMinus1 = 0; 1969 h264type.nRefIdx11ActiveMinus1 = 0; 1970 h264type.bEntropyCodingCABAC = OMX_FALSE; 1971 h264type.bWeightedPPrediction = OMX_FALSE; 1972 h264type.bconstIpred = OMX_FALSE; 1973 h264type.bDirect8x8Inference = OMX_FALSE; 1974 h264type.bDirectSpatialTemporal = OMX_FALSE; 1975 h264type.nCabacInitIdc = 0; 1976 } 1977 1978 if (h264type.nBFrames != 0) { 1979 h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB; 1980 } 1981 1982 h264type.bEnableUEP = OMX_FALSE; 1983 h264type.bEnableFMO = OMX_FALSE; 1984 h264type.bEnableASO = OMX_FALSE; 1985 h264type.bEnableRS = OMX_FALSE; 1986 h264type.bFrameMBsOnly = OMX_TRUE; 1987 h264type.bMBAFF = OMX_FALSE; 1988 h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; 1989 1990 err = mOMX->setParameter( 1991 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 1992 1993 if (err != OK) { 1994 return err; 1995 } 1996 1997 return configureBitrate(bitrate, bitrateMode); 1998} 1999 2000status_t ACodec::verifySupportForProfileAndLevel( 2001 int32_t profile, int32_t level) { 2002 OMX_VIDEO_PARAM_PROFILELEVELTYPE params; 2003 InitOMXParams(¶ms); 2004 params.nPortIndex = kPortIndexOutput; 2005 2006 for (params.nProfileIndex = 0;; ++params.nProfileIndex) { 2007 status_t err = mOMX->getParameter( 2008 mNode, 2009 OMX_IndexParamVideoProfileLevelQuerySupported, 2010 ¶ms, 2011 sizeof(params)); 2012 2013 if (err != OK) { 2014 return err; 2015 } 2016 2017 int32_t supportedProfile = static_cast<int32_t>(params.eProfile); 2018 int32_t supportedLevel = static_cast<int32_t>(params.eLevel); 2019 2020 if (profile == supportedProfile && level <= supportedLevel) { 2021 return OK; 2022 } 2023 } 2024} 2025 2026status_t ACodec::configureBitrate( 2027 int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode) { 2028 OMX_VIDEO_PARAM_BITRATETYPE bitrateType; 2029 InitOMXParams(&bitrateType); 2030 bitrateType.nPortIndex = kPortIndexOutput; 2031 2032 status_t err = mOMX->getParameter( 2033 mNode, OMX_IndexParamVideoBitrate, 2034 &bitrateType, sizeof(bitrateType)); 2035 2036 if (err != OK) { 2037 return err; 2038 } 2039 2040 bitrateType.eControlRate = bitrateMode; 2041 bitrateType.nTargetBitrate = bitrate; 2042 2043 return mOMX->setParameter( 2044 mNode, OMX_IndexParamVideoBitrate, 2045 &bitrateType, sizeof(bitrateType)); 2046} 2047 2048status_t ACodec::setupErrorCorrectionParameters() { 2049 OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType; 2050 InitOMXParams(&errorCorrectionType); 2051 errorCorrectionType.nPortIndex = kPortIndexOutput; 2052 2053 status_t err = mOMX->getParameter( 2054 mNode, OMX_IndexParamVideoErrorCorrection, 2055 &errorCorrectionType, sizeof(errorCorrectionType)); 2056 2057 if (err != OK) { 2058 return OK; // Optional feature. Ignore this failure 2059 } 2060 2061 errorCorrectionType.bEnableHEC = OMX_FALSE; 2062 errorCorrectionType.bEnableResync = OMX_TRUE; 2063 errorCorrectionType.nResynchMarkerSpacing = 256; 2064 errorCorrectionType.bEnableDataPartitioning = OMX_FALSE; 2065 errorCorrectionType.bEnableRVLC = OMX_FALSE; 2066 2067 return mOMX->setParameter( 2068 mNode, OMX_IndexParamVideoErrorCorrection, 2069 &errorCorrectionType, sizeof(errorCorrectionType)); 2070} 2071 2072status_t ACodec::setVideoFormatOnPort( 2073 OMX_U32 portIndex, 2074 int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) { 2075 OMX_PARAM_PORTDEFINITIONTYPE def; 2076 InitOMXParams(&def); 2077 def.nPortIndex = portIndex; 2078 2079 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 2080 2081 status_t err = mOMX->getParameter( 2082 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2083 2084 CHECK_EQ(err, (status_t)OK); 2085 2086 if (portIndex == kPortIndexInput) { 2087 // XXX Need a (much) better heuristic to compute input buffer sizes. 2088 const size_t X = 64 * 1024; 2089 if (def.nBufferSize < X) { 2090 def.nBufferSize = X; 2091 } 2092 } 2093 2094 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo); 2095 2096 video_def->nFrameWidth = width; 2097 video_def->nFrameHeight = height; 2098 2099 if (portIndex == kPortIndexInput) { 2100 video_def->eCompressionFormat = compressionFormat; 2101 video_def->eColorFormat = OMX_COLOR_FormatUnused; 2102 } 2103 2104 err = mOMX->setParameter( 2105 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2106 2107 return err; 2108} 2109 2110status_t ACodec::initNativeWindow() { 2111 if (mNativeWindow != NULL) { 2112 return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE); 2113 } 2114 2115 mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE); 2116 return OK; 2117} 2118 2119size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const { 2120 size_t n = 0; 2121 2122 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 2123 const BufferInfo &info = mBuffers[portIndex].itemAt(i); 2124 2125 if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) { 2126 ++n; 2127 } 2128 } 2129 2130 return n; 2131} 2132 2133bool ACodec::allYourBuffersAreBelongToUs( 2134 OMX_U32 portIndex) { 2135 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 2136 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 2137 2138 if (info->mStatus != BufferInfo::OWNED_BY_US 2139 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) { 2140 ALOGV("[%s] Buffer %p on port %ld still has status %d", 2141 mComponentName.c_str(), 2142 info->mBufferID, portIndex, info->mStatus); 2143 return false; 2144 } 2145 } 2146 2147 return true; 2148} 2149 2150bool ACodec::allYourBuffersAreBelongToUs() { 2151 return allYourBuffersAreBelongToUs(kPortIndexInput) 2152 && allYourBuffersAreBelongToUs(kPortIndexOutput); 2153} 2154 2155void ACodec::deferMessage(const sp<AMessage> &msg) { 2156 bool wasEmptyBefore = mDeferredQueue.empty(); 2157 mDeferredQueue.push_back(msg); 2158} 2159 2160void ACodec::processDeferredMessages() { 2161 List<sp<AMessage> > queue = mDeferredQueue; 2162 mDeferredQueue.clear(); 2163 2164 List<sp<AMessage> >::iterator it = queue.begin(); 2165 while (it != queue.end()) { 2166 onMessageReceived(*it++); 2167 } 2168} 2169 2170void ACodec::sendFormatChange() { 2171 sp<AMessage> notify = mNotify->dup(); 2172 notify->setInt32("what", kWhatOutputFormatChanged); 2173 2174 OMX_PARAM_PORTDEFINITIONTYPE def; 2175 InitOMXParams(&def); 2176 def.nPortIndex = kPortIndexOutput; 2177 2178 CHECK_EQ(mOMX->getParameter( 2179 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)), 2180 (status_t)OK); 2181 2182 CHECK_EQ((int)def.eDir, (int)OMX_DirOutput); 2183 2184 switch (def.eDomain) { 2185 case OMX_PortDomainVideo: 2186 { 2187 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video; 2188 2189 notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW); 2190 notify->setInt32("width", videoDef->nFrameWidth); 2191 notify->setInt32("height", videoDef->nFrameHeight); 2192 notify->setInt32("stride", videoDef->nStride); 2193 notify->setInt32("slice-height", videoDef->nSliceHeight); 2194 notify->setInt32("color-format", videoDef->eColorFormat); 2195 2196 OMX_CONFIG_RECTTYPE rect; 2197 InitOMXParams(&rect); 2198 rect.nPortIndex = kPortIndexOutput; 2199 2200 if (mOMX->getConfig( 2201 mNode, OMX_IndexConfigCommonOutputCrop, 2202 &rect, sizeof(rect)) != OK) { 2203 rect.nLeft = 0; 2204 rect.nTop = 0; 2205 rect.nWidth = videoDef->nFrameWidth; 2206 rect.nHeight = videoDef->nFrameHeight; 2207 } 2208 2209 CHECK_GE(rect.nLeft, 0); 2210 CHECK_GE(rect.nTop, 0); 2211 CHECK_GE(rect.nWidth, 0u); 2212 CHECK_GE(rect.nHeight, 0u); 2213 CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth); 2214 CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight); 2215 2216 notify->setRect( 2217 "crop", 2218 rect.nLeft, 2219 rect.nTop, 2220 rect.nLeft + rect.nWidth - 1, 2221 rect.nTop + rect.nHeight - 1); 2222 2223 if (mNativeWindow != NULL) { 2224 android_native_rect_t crop; 2225 crop.left = rect.nLeft; 2226 crop.top = rect.nTop; 2227 crop.right = rect.nLeft + rect.nWidth; 2228 crop.bottom = rect.nTop + rect.nHeight; 2229 2230 CHECK_EQ(0, native_window_set_crop( 2231 mNativeWindow.get(), &crop)); 2232 } 2233 break; 2234 } 2235 2236 case OMX_PortDomainAudio: 2237 { 2238 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio; 2239 CHECK_EQ((int)audioDef->eEncoding, (int)OMX_AUDIO_CodingPCM); 2240 2241 OMX_AUDIO_PARAM_PCMMODETYPE params; 2242 InitOMXParams(¶ms); 2243 params.nPortIndex = kPortIndexOutput; 2244 2245 CHECK_EQ(mOMX->getParameter( 2246 mNode, OMX_IndexParamAudioPcm, 2247 ¶ms, sizeof(params)), 2248 (status_t)OK); 2249 2250 CHECK(params.nChannels == 1 || params.bInterleaved); 2251 CHECK_EQ(params.nBitPerSample, 16u); 2252 CHECK_EQ((int)params.eNumData, (int)OMX_NumericalDataSigned); 2253 CHECK_EQ((int)params.ePCMMode, (int)OMX_AUDIO_PCMModeLinear); 2254 2255 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW); 2256 notify->setInt32("channel-count", params.nChannels); 2257 notify->setInt32("sample-rate", params.nSamplingRate); 2258 if (mEncoderDelay + mEncoderPadding) { 2259 size_t frameSize = params.nChannels * sizeof(int16_t); 2260 if (mSkipCutBuffer != NULL) { 2261 size_t prevbufsize = mSkipCutBuffer->size(); 2262 if (prevbufsize != 0) { 2263 ALOGW("Replacing SkipCutBuffer holding %d bytes", prevbufsize); 2264 } 2265 } 2266 mSkipCutBuffer = new SkipCutBuffer(mEncoderDelay * frameSize, 2267 mEncoderPadding * frameSize); 2268 } 2269 2270 if (mChannelMaskPresent) { 2271 notify->setInt32("channel-mask", mChannelMask); 2272 } 2273 2274 break; 2275 } 2276 2277 default: 2278 TRESPASS(); 2279 } 2280 2281 notify->post(); 2282 2283 mSentFormat = true; 2284} 2285 2286void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) { 2287 sp<AMessage> notify = mNotify->dup(); 2288 notify->setInt32("what", ACodec::kWhatError); 2289 notify->setInt32("omx-error", error); 2290 notify->setInt32("err", internalError); 2291 notify->post(); 2292} 2293 2294status_t ACodec::pushBlankBuffersToNativeWindow() { 2295 status_t err = NO_ERROR; 2296 ANativeWindowBuffer* anb = NULL; 2297 int numBufs = 0; 2298 int minUndequeuedBufs = 0; 2299 2300 // We need to reconnect to the ANativeWindow as a CPU client to ensure that 2301 // no frames get dropped by SurfaceFlinger assuming that these are video 2302 // frames. 2303 err = native_window_api_disconnect(mNativeWindow.get(), 2304 NATIVE_WINDOW_API_MEDIA); 2305 if (err != NO_ERROR) { 2306 ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)", 2307 strerror(-err), -err); 2308 return err; 2309 } 2310 2311 err = native_window_api_connect(mNativeWindow.get(), 2312 NATIVE_WINDOW_API_CPU); 2313 if (err != NO_ERROR) { 2314 ALOGE("error pushing blank frames: api_connect failed: %s (%d)", 2315 strerror(-err), -err); 2316 return err; 2317 } 2318 2319 err = native_window_set_buffers_geometry(mNativeWindow.get(), 1, 1, 2320 HAL_PIXEL_FORMAT_RGBX_8888); 2321 if (err != NO_ERROR) { 2322 ALOGE("error pushing blank frames: set_buffers_geometry failed: %s (%d)", 2323 strerror(-err), -err); 2324 goto error; 2325 } 2326 2327 err = native_window_set_usage(mNativeWindow.get(), 2328 GRALLOC_USAGE_SW_WRITE_OFTEN); 2329 if (err != NO_ERROR) { 2330 ALOGE("error pushing blank frames: set_usage failed: %s (%d)", 2331 strerror(-err), -err); 2332 goto error; 2333 } 2334 2335 err = mNativeWindow->query(mNativeWindow.get(), 2336 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs); 2337 if (err != NO_ERROR) { 2338 ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query " 2339 "failed: %s (%d)", strerror(-err), -err); 2340 goto error; 2341 } 2342 2343 numBufs = minUndequeuedBufs + 1; 2344 err = native_window_set_buffer_count(mNativeWindow.get(), numBufs); 2345 if (err != NO_ERROR) { 2346 ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)", 2347 strerror(-err), -err); 2348 goto error; 2349 } 2350 2351 // We push numBufs + 1 buffers to ensure that we've drawn into the same 2352 // buffer twice. This should guarantee that the buffer has been displayed 2353 // on the screen and then been replaced, so an previous video frames are 2354 // guaranteed NOT to be currently displayed. 2355 for (int i = 0; i < numBufs + 1; i++) { 2356 int fenceFd = -1; 2357 err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &anb); 2358 if (err != NO_ERROR) { 2359 ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)", 2360 strerror(-err), -err); 2361 goto error; 2362 } 2363 2364 sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); 2365 2366 // Fill the buffer with the a 1x1 checkerboard pattern ;) 2367 uint32_t* img = NULL; 2368 err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); 2369 if (err != NO_ERROR) { 2370 ALOGE("error pushing blank frames: lock failed: %s (%d)", 2371 strerror(-err), -err); 2372 goto error; 2373 } 2374 2375 *img = 0; 2376 2377 err = buf->unlock(); 2378 if (err != NO_ERROR) { 2379 ALOGE("error pushing blank frames: unlock failed: %s (%d)", 2380 strerror(-err), -err); 2381 goto error; 2382 } 2383 2384 err = mNativeWindow->queueBuffer(mNativeWindow.get(), 2385 buf->getNativeBuffer(), -1); 2386 if (err != NO_ERROR) { 2387 ALOGE("error pushing blank frames: queueBuffer failed: %s (%d)", 2388 strerror(-err), -err); 2389 goto error; 2390 } 2391 2392 anb = NULL; 2393 } 2394 2395error: 2396 2397 if (err != NO_ERROR) { 2398 // Clean up after an error. 2399 if (anb != NULL) { 2400 mNativeWindow->cancelBuffer(mNativeWindow.get(), anb, -1); 2401 } 2402 2403 native_window_api_disconnect(mNativeWindow.get(), 2404 NATIVE_WINDOW_API_CPU); 2405 native_window_api_connect(mNativeWindow.get(), 2406 NATIVE_WINDOW_API_MEDIA); 2407 2408 return err; 2409 } else { 2410 // Clean up after success. 2411 err = native_window_api_disconnect(mNativeWindow.get(), 2412 NATIVE_WINDOW_API_CPU); 2413 if (err != NO_ERROR) { 2414 ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)", 2415 strerror(-err), -err); 2416 return err; 2417 } 2418 2419 err = native_window_api_connect(mNativeWindow.get(), 2420 NATIVE_WINDOW_API_MEDIA); 2421 if (err != NO_ERROR) { 2422 ALOGE("error pushing blank frames: api_connect failed: %s (%d)", 2423 strerror(-err), -err); 2424 return err; 2425 } 2426 2427 return NO_ERROR; 2428 } 2429} 2430 2431//////////////////////////////////////////////////////////////////////////////// 2432 2433ACodec::PortDescription::PortDescription() { 2434} 2435 2436status_t ACodec::requestIDRFrame() { 2437 if (!mIsEncoder) { 2438 return ERROR_UNSUPPORTED; 2439 } 2440 2441 OMX_CONFIG_INTRAREFRESHVOPTYPE params; 2442 InitOMXParams(¶ms); 2443 2444 params.nPortIndex = kPortIndexOutput; 2445 params.IntraRefreshVOP = OMX_TRUE; 2446 2447 return mOMX->setConfig( 2448 mNode, 2449 OMX_IndexConfigVideoIntraVOPRefresh, 2450 ¶ms, 2451 sizeof(params)); 2452} 2453 2454void ACodec::PortDescription::addBuffer( 2455 IOMX::buffer_id id, const sp<ABuffer> &buffer) { 2456 mBufferIDs.push_back(id); 2457 mBuffers.push_back(buffer); 2458} 2459 2460size_t ACodec::PortDescription::countBuffers() { 2461 return mBufferIDs.size(); 2462} 2463 2464IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const { 2465 return mBufferIDs.itemAt(index); 2466} 2467 2468sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const { 2469 return mBuffers.itemAt(index); 2470} 2471 2472//////////////////////////////////////////////////////////////////////////////// 2473 2474ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState) 2475 : AState(parentState), 2476 mCodec(codec) { 2477} 2478 2479ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(OMX_U32 portIndex) { 2480 return KEEP_BUFFERS; 2481} 2482 2483bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) { 2484 switch (msg->what()) { 2485 case kWhatInputBufferFilled: 2486 { 2487 onInputBufferFilled(msg); 2488 break; 2489 } 2490 2491 case kWhatOutputBufferDrained: 2492 { 2493 onOutputBufferDrained(msg); 2494 break; 2495 } 2496 2497 case ACodec::kWhatOMXMessage: 2498 { 2499 return onOMXMessage(msg); 2500 } 2501 2502 case ACodec::kWhatCreateInputSurface: 2503 case ACodec::kWhatSignalEndOfInputStream: 2504 { 2505 ALOGE("Message 0x%x was not handled", msg->what()); 2506 mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION); 2507 return true; 2508 } 2509 2510 case ACodec::kWhatOMXDied: 2511 { 2512 ALOGE("OMX/mediaserver died, signalling error!"); 2513 mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT); 2514 break; 2515 } 2516 2517 default: 2518 return false; 2519 } 2520 2521 return true; 2522} 2523 2524bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) { 2525 int32_t type; 2526 CHECK(msg->findInt32("type", &type)); 2527 2528 IOMX::node_id nodeID; 2529 CHECK(msg->findPointer("node", &nodeID)); 2530 CHECK_EQ(nodeID, mCodec->mNode); 2531 2532 switch (type) { 2533 case omx_message::EVENT: 2534 { 2535 int32_t event, data1, data2; 2536 CHECK(msg->findInt32("event", &event)); 2537 CHECK(msg->findInt32("data1", &data1)); 2538 CHECK(msg->findInt32("data2", &data2)); 2539 2540 if (event == OMX_EventCmdComplete 2541 && data1 == OMX_CommandFlush 2542 && data2 == (int32_t)OMX_ALL) { 2543 // Use of this notification is not consistent across 2544 // implementations. We'll drop this notification and rely 2545 // on flush-complete notifications on the individual port 2546 // indices instead. 2547 2548 return true; 2549 } 2550 2551 return onOMXEvent( 2552 static_cast<OMX_EVENTTYPE>(event), 2553 static_cast<OMX_U32>(data1), 2554 static_cast<OMX_U32>(data2)); 2555 } 2556 2557 case omx_message::EMPTY_BUFFER_DONE: 2558 { 2559 IOMX::buffer_id bufferID; 2560 CHECK(msg->findPointer("buffer", &bufferID)); 2561 2562 return onOMXEmptyBufferDone(bufferID); 2563 } 2564 2565 case omx_message::FILL_BUFFER_DONE: 2566 { 2567 IOMX::buffer_id bufferID; 2568 CHECK(msg->findPointer("buffer", &bufferID)); 2569 2570 int32_t rangeOffset, rangeLength, flags; 2571 int64_t timeUs; 2572 void *platformPrivate; 2573 void *dataPtr; 2574 2575 CHECK(msg->findInt32("range_offset", &rangeOffset)); 2576 CHECK(msg->findInt32("range_length", &rangeLength)); 2577 CHECK(msg->findInt32("flags", &flags)); 2578 CHECK(msg->findInt64("timestamp", &timeUs)); 2579 CHECK(msg->findPointer("platform_private", &platformPrivate)); 2580 CHECK(msg->findPointer("data_ptr", &dataPtr)); 2581 2582 return onOMXFillBufferDone( 2583 bufferID, 2584 (size_t)rangeOffset, (size_t)rangeLength, 2585 (OMX_U32)flags, 2586 timeUs, 2587 platformPrivate, 2588 dataPtr); 2589 } 2590 2591 default: 2592 TRESPASS(); 2593 break; 2594 } 2595} 2596 2597bool ACodec::BaseState::onOMXEvent( 2598 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 2599 if (event != OMX_EventError) { 2600 ALOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)", 2601 mCodec->mComponentName.c_str(), event, data1, data2); 2602 2603 return false; 2604 } 2605 2606 ALOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1); 2607 2608 mCodec->signalError((OMX_ERRORTYPE)data1); 2609 2610 return true; 2611} 2612 2613bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) { 2614 ALOGV("[%s] onOMXEmptyBufferDone %p", 2615 mCodec->mComponentName.c_str(), bufferID); 2616 2617 BufferInfo *info = 2618 mCodec->findBufferByID(kPortIndexInput, bufferID); 2619 2620 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); 2621 info->mStatus = BufferInfo::OWNED_BY_US; 2622 2623 const sp<AMessage> &bufferMeta = info->mData->meta(); 2624 void *mediaBuffer; 2625 if (bufferMeta->findPointer("mediaBuffer", &mediaBuffer) 2626 && mediaBuffer != NULL) { 2627 // We're in "store-metadata-in-buffers" mode, the underlying 2628 // OMX component had access to data that's implicitly refcounted 2629 // by this "mediaBuffer" object. Now that the OMX component has 2630 // told us that it's done with the input buffer, we can decrement 2631 // the mediaBuffer's reference count. 2632 2633 ALOGV("releasing mbuf %p", mediaBuffer); 2634 2635 ((MediaBuffer *)mediaBuffer)->release(); 2636 mediaBuffer = NULL; 2637 2638 bufferMeta->setPointer("mediaBuffer", NULL); 2639 } 2640 2641 PortMode mode = getPortMode(kPortIndexInput); 2642 2643 switch (mode) { 2644 case KEEP_BUFFERS: 2645 break; 2646 2647 case RESUBMIT_BUFFERS: 2648 postFillThisBuffer(info); 2649 break; 2650 2651 default: 2652 { 2653 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 2654 TRESPASS(); // Not currently used 2655 break; 2656 } 2657 } 2658 2659 return true; 2660} 2661 2662void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) { 2663 if (mCodec->mPortEOS[kPortIndexInput]) { 2664 return; 2665 } 2666 2667 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 2668 2669 sp<AMessage> notify = mCodec->mNotify->dup(); 2670 notify->setInt32("what", ACodec::kWhatFillThisBuffer); 2671 notify->setPointer("buffer-id", info->mBufferID); 2672 2673 info->mData->meta()->clear(); 2674 notify->setBuffer("buffer", info->mData); 2675 2676 sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id()); 2677 reply->setPointer("buffer-id", info->mBufferID); 2678 2679 notify->setMessage("reply", reply); 2680 2681 notify->post(); 2682 2683 info->mStatus = BufferInfo::OWNED_BY_UPSTREAM; 2684} 2685 2686void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { 2687 IOMX::buffer_id bufferID; 2688 CHECK(msg->findPointer("buffer-id", &bufferID)); 2689 2690 sp<ABuffer> buffer; 2691 int32_t err = OK; 2692 bool eos = false; 2693 2694 if (!msg->findBuffer("buffer", &buffer)) { 2695 CHECK(msg->findInt32("err", &err)); 2696 2697 ALOGV("[%s] saw error %d instead of an input buffer", 2698 mCodec->mComponentName.c_str(), err); 2699 2700 buffer.clear(); 2701 2702 eos = true; 2703 } 2704 2705 int32_t tmp; 2706 if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) { 2707 eos = true; 2708 err = ERROR_END_OF_STREAM; 2709 } 2710 2711 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID); 2712 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM); 2713 2714 info->mStatus = BufferInfo::OWNED_BY_US; 2715 2716 PortMode mode = getPortMode(kPortIndexInput); 2717 2718 switch (mode) { 2719 case KEEP_BUFFERS: 2720 { 2721 if (eos) { 2722 if (!mCodec->mPortEOS[kPortIndexInput]) { 2723 mCodec->mPortEOS[kPortIndexInput] = true; 2724 mCodec->mInputEOSResult = err; 2725 } 2726 } 2727 break; 2728 } 2729 2730 case RESUBMIT_BUFFERS: 2731 { 2732 if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) { 2733 int64_t timeUs; 2734 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 2735 2736 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME; 2737 2738 int32_t isCSD; 2739 if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) { 2740 flags |= OMX_BUFFERFLAG_CODECCONFIG; 2741 } 2742 2743 if (eos) { 2744 flags |= OMX_BUFFERFLAG_EOS; 2745 } 2746 2747 if (buffer != info->mData) { 2748 ALOGV("[%s] Needs to copy input data for buffer %p. (%p != %p)", 2749 mCodec->mComponentName.c_str(), 2750 bufferID, 2751 buffer.get(), info->mData.get()); 2752 2753 CHECK_LE(buffer->size(), info->mData->capacity()); 2754 memcpy(info->mData->data(), buffer->data(), buffer->size()); 2755 } 2756 2757 if (flags & OMX_BUFFERFLAG_CODECCONFIG) { 2758 ALOGV("[%s] calling emptyBuffer %p w/ codec specific data", 2759 mCodec->mComponentName.c_str(), bufferID); 2760 } else if (flags & OMX_BUFFERFLAG_EOS) { 2761 ALOGV("[%s] calling emptyBuffer %p w/ EOS", 2762 mCodec->mComponentName.c_str(), bufferID); 2763 } else { 2764#if TRACK_BUFFER_TIMING 2765 ALOGI("[%s] calling emptyBuffer %p w/ time %lld us", 2766 mCodec->mComponentName.c_str(), bufferID, timeUs); 2767#else 2768 ALOGV("[%s] calling emptyBuffer %p w/ time %lld us", 2769 mCodec->mComponentName.c_str(), bufferID, timeUs); 2770#endif 2771 } 2772 2773#if TRACK_BUFFER_TIMING 2774 ACodec::BufferStats stats; 2775 stats.mEmptyBufferTimeUs = ALooper::GetNowUs(); 2776 stats.mFillBufferDoneTimeUs = -1ll; 2777 mCodec->mBufferStats.add(timeUs, stats); 2778#endif 2779 2780 CHECK_EQ(mCodec->mOMX->emptyBuffer( 2781 mCodec->mNode, 2782 bufferID, 2783 0, 2784 buffer->size(), 2785 flags, 2786 timeUs), 2787 (status_t)OK); 2788 2789 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 2790 2791 if (!eos) { 2792 getMoreInputDataIfPossible(); 2793 } else { 2794 ALOGV("[%s] Signalled EOS on the input port", 2795 mCodec->mComponentName.c_str()); 2796 2797 mCodec->mPortEOS[kPortIndexInput] = true; 2798 mCodec->mInputEOSResult = err; 2799 } 2800 } else if (!mCodec->mPortEOS[kPortIndexInput]) { 2801 if (err != ERROR_END_OF_STREAM) { 2802 ALOGV("[%s] Signalling EOS on the input port " 2803 "due to error %d", 2804 mCodec->mComponentName.c_str(), err); 2805 } else { 2806 ALOGV("[%s] Signalling EOS on the input port", 2807 mCodec->mComponentName.c_str()); 2808 } 2809 2810 ALOGV("[%s] calling emptyBuffer %p signalling EOS", 2811 mCodec->mComponentName.c_str(), bufferID); 2812 2813 CHECK_EQ(mCodec->mOMX->emptyBuffer( 2814 mCodec->mNode, 2815 bufferID, 2816 0, 2817 0, 2818 OMX_BUFFERFLAG_EOS, 2819 0), 2820 (status_t)OK); 2821 2822 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 2823 2824 mCodec->mPortEOS[kPortIndexInput] = true; 2825 mCodec->mInputEOSResult = err; 2826 } 2827 break; 2828 2829 default: 2830 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 2831 break; 2832 } 2833 } 2834} 2835 2836void ACodec::BaseState::getMoreInputDataIfPossible() { 2837 if (mCodec->mPortEOS[kPortIndexInput]) { 2838 return; 2839 } 2840 2841 BufferInfo *eligible = NULL; 2842 2843 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 2844 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 2845 2846#if 0 2847 if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) { 2848 // There's already a "read" pending. 2849 return; 2850 } 2851#endif 2852 2853 if (info->mStatus == BufferInfo::OWNED_BY_US) { 2854 eligible = info; 2855 } 2856 } 2857 2858 if (eligible == NULL) { 2859 return; 2860 } 2861 2862 postFillThisBuffer(eligible); 2863} 2864 2865bool ACodec::BaseState::onOMXFillBufferDone( 2866 IOMX::buffer_id bufferID, 2867 size_t rangeOffset, size_t rangeLength, 2868 OMX_U32 flags, 2869 int64_t timeUs, 2870 void *platformPrivate, 2871 void *dataPtr) { 2872 ALOGV("[%s] onOMXFillBufferDone %p time %lld us, flags = 0x%08lx", 2873 mCodec->mComponentName.c_str(), bufferID, timeUs, flags); 2874 2875 ssize_t index; 2876 2877#if TRACK_BUFFER_TIMING 2878 index = mCodec->mBufferStats.indexOfKey(timeUs); 2879 if (index >= 0) { 2880 ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index); 2881 stats->mFillBufferDoneTimeUs = ALooper::GetNowUs(); 2882 2883 ALOGI("frame PTS %lld: %lld", 2884 timeUs, 2885 stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs); 2886 2887 mCodec->mBufferStats.removeItemsAt(index); 2888 stats = NULL; 2889 } 2890#endif 2891 2892 BufferInfo *info = 2893 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 2894 2895 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); 2896 2897 info->mStatus = BufferInfo::OWNED_BY_US; 2898 2899 PortMode mode = getPortMode(kPortIndexOutput); 2900 2901 switch (mode) { 2902 case KEEP_BUFFERS: 2903 break; 2904 2905 case RESUBMIT_BUFFERS: 2906 { 2907 if (rangeLength == 0 && !(flags & OMX_BUFFERFLAG_EOS)) { 2908 ALOGV("[%s] calling fillBuffer %p", 2909 mCodec->mComponentName.c_str(), info->mBufferID); 2910 2911 CHECK_EQ(mCodec->mOMX->fillBuffer( 2912 mCodec->mNode, info->mBufferID), 2913 (status_t)OK); 2914 2915 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 2916 break; 2917 } 2918 2919 if (!mCodec->mIsEncoder && !mCodec->mSentFormat) { 2920 mCodec->sendFormatChange(); 2921 } 2922 2923 info->mData->setRange(rangeOffset, rangeLength); 2924#if 0 2925 if (mCodec->mNativeWindow == NULL) { 2926 if (IsIDR(info->mData)) { 2927 ALOGI("IDR frame"); 2928 } 2929 } 2930#endif 2931 2932 if (mCodec->mSkipCutBuffer != NULL) { 2933 mCodec->mSkipCutBuffer->submit(info->mData); 2934 } 2935 info->mData->meta()->setInt64("timeUs", timeUs); 2936 2937 sp<AMessage> notify = mCodec->mNotify->dup(); 2938 notify->setInt32("what", ACodec::kWhatDrainThisBuffer); 2939 notify->setPointer("buffer-id", info->mBufferID); 2940 notify->setBuffer("buffer", info->mData); 2941 notify->setInt32("flags", flags); 2942 2943 sp<AMessage> reply = 2944 new AMessage(kWhatOutputBufferDrained, mCodec->id()); 2945 2946 reply->setPointer("buffer-id", info->mBufferID); 2947 2948 notify->setMessage("reply", reply); 2949 2950 notify->post(); 2951 2952 info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM; 2953 2954 if (flags & OMX_BUFFERFLAG_EOS) { 2955 ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str()); 2956 2957 sp<AMessage> notify = mCodec->mNotify->dup(); 2958 notify->setInt32("what", ACodec::kWhatEOS); 2959 notify->setInt32("err", mCodec->mInputEOSResult); 2960 notify->post(); 2961 2962 mCodec->mPortEOS[kPortIndexOutput] = true; 2963 } 2964 break; 2965 } 2966 2967 default: 2968 { 2969 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 2970 2971 CHECK_EQ((status_t)OK, 2972 mCodec->freeBuffer(kPortIndexOutput, index)); 2973 break; 2974 } 2975 } 2976 2977 return true; 2978} 2979 2980void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { 2981 IOMX::buffer_id bufferID; 2982 CHECK(msg->findPointer("buffer-id", &bufferID)); 2983 2984 ssize_t index; 2985 BufferInfo *info = 2986 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 2987 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM); 2988 2989 int32_t render; 2990 if (mCodec->mNativeWindow != NULL 2991 && msg->findInt32("render", &render) && render != 0) { 2992 // The client wants this buffer to be rendered. 2993 2994 status_t err; 2995 if ((err = mCodec->mNativeWindow->queueBuffer( 2996 mCodec->mNativeWindow.get(), 2997 info->mGraphicBuffer.get(), -1)) == OK) { 2998 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 2999 } else { 3000 mCodec->signalError(OMX_ErrorUndefined, err); 3001 info->mStatus = BufferInfo::OWNED_BY_US; 3002 } 3003 } else { 3004 info->mStatus = BufferInfo::OWNED_BY_US; 3005 } 3006 3007 PortMode mode = getPortMode(kPortIndexOutput); 3008 3009 switch (mode) { 3010 case KEEP_BUFFERS: 3011 { 3012 // XXX fishy, revisit!!! What about the FREE_BUFFERS case below? 3013 3014 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 3015 // We cannot resubmit the buffer we just rendered, dequeue 3016 // the spare instead. 3017 3018 info = mCodec->dequeueBufferFromNativeWindow(); 3019 } 3020 break; 3021 } 3022 3023 case RESUBMIT_BUFFERS: 3024 { 3025 if (!mCodec->mPortEOS[kPortIndexOutput]) { 3026 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 3027 // We cannot resubmit the buffer we just rendered, dequeue 3028 // the spare instead. 3029 3030 info = mCodec->dequeueBufferFromNativeWindow(); 3031 } 3032 3033 if (info != NULL) { 3034 ALOGV("[%s] calling fillBuffer %p", 3035 mCodec->mComponentName.c_str(), info->mBufferID); 3036 3037 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), 3038 (status_t)OK); 3039 3040 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 3041 } 3042 } 3043 break; 3044 } 3045 3046 default: 3047 { 3048 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 3049 3050 CHECK_EQ((status_t)OK, 3051 mCodec->freeBuffer(kPortIndexOutput, index)); 3052 break; 3053 } 3054 } 3055} 3056 3057//////////////////////////////////////////////////////////////////////////////// 3058 3059ACodec::UninitializedState::UninitializedState(ACodec *codec) 3060 : BaseState(codec) { 3061} 3062 3063void ACodec::UninitializedState::stateEntered() { 3064 ALOGV("Now uninitialized"); 3065 3066 if (mDeathNotifier != NULL) { 3067 mCodec->mOMX->asBinder()->unlinkToDeath(mDeathNotifier); 3068 mDeathNotifier.clear(); 3069 } 3070 3071 mCodec->mNativeWindow.clear(); 3072 mCodec->mNode = NULL; 3073 mCodec->mOMX.clear(); 3074 mCodec->mQuirks = 0; 3075 mCodec->mFlags = 0; 3076 mCodec->mComponentName.clear(); 3077} 3078 3079bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) { 3080 bool handled = false; 3081 3082 switch (msg->what()) { 3083 case ACodec::kWhatSetup: 3084 { 3085 onSetup(msg); 3086 3087 handled = true; 3088 break; 3089 } 3090 3091 case ACodec::kWhatAllocateComponent: 3092 { 3093 onAllocateComponent(msg); 3094 handled = true; 3095 break; 3096 } 3097 3098 case ACodec::kWhatShutdown: 3099 { 3100 int32_t keepComponentAllocated; 3101 CHECK(msg->findInt32( 3102 "keepComponentAllocated", &keepComponentAllocated)); 3103 CHECK(!keepComponentAllocated); 3104 3105 sp<AMessage> notify = mCodec->mNotify->dup(); 3106 notify->setInt32("what", ACodec::kWhatShutdownCompleted); 3107 notify->post(); 3108 3109 handled = true; 3110 break; 3111 } 3112 3113 case ACodec::kWhatFlush: 3114 { 3115 sp<AMessage> notify = mCodec->mNotify->dup(); 3116 notify->setInt32("what", ACodec::kWhatFlushCompleted); 3117 notify->post(); 3118 3119 handled = true; 3120 break; 3121 } 3122 3123 default: 3124 return BaseState::onMessageReceived(msg); 3125 } 3126 3127 return handled; 3128} 3129 3130void ACodec::UninitializedState::onSetup( 3131 const sp<AMessage> &msg) { 3132 if (onAllocateComponent(msg) 3133 && mCodec->mLoadedState->onConfigureComponent(msg)) { 3134 mCodec->mLoadedState->onStart(); 3135 } 3136} 3137 3138bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) { 3139 ALOGV("onAllocateComponent"); 3140 3141 CHECK(mCodec->mNode == NULL); 3142 3143 OMXClient client; 3144 CHECK_EQ(client.connect(), (status_t)OK); 3145 3146 sp<IOMX> omx = client.interface(); 3147 3148 sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec->id()); 3149 3150 mDeathNotifier = new DeathNotifier(notify); 3151 if (omx->asBinder()->linkToDeath(mDeathNotifier) != OK) { 3152 // This was a local binder, if it dies so do we, we won't care 3153 // about any notifications in the afterlife. 3154 mDeathNotifier.clear(); 3155 } 3156 3157 Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs; 3158 3159 AString mime; 3160 3161 AString componentName; 3162 uint32_t quirks = 0; 3163 if (msg->findString("componentName", &componentName)) { 3164 ssize_t index = matchingCodecs.add(); 3165 OMXCodec::CodecNameAndQuirks *entry = &matchingCodecs.editItemAt(index); 3166 entry->mName = String8(componentName.c_str()); 3167 3168 if (!OMXCodec::findCodecQuirks( 3169 componentName.c_str(), &entry->mQuirks)) { 3170 entry->mQuirks = 0; 3171 } 3172 } else { 3173 CHECK(msg->findString("mime", &mime)); 3174 3175 int32_t encoder; 3176 if (!msg->findInt32("encoder", &encoder)) { 3177 encoder = false; 3178 } 3179 3180 OMXCodec::findMatchingCodecs( 3181 mime.c_str(), 3182 encoder, // createEncoder 3183 NULL, // matchComponentName 3184 0, // flags 3185 &matchingCodecs); 3186 } 3187 3188 sp<CodecObserver> observer = new CodecObserver; 3189 IOMX::node_id node = NULL; 3190 3191 for (size_t matchIndex = 0; matchIndex < matchingCodecs.size(); 3192 ++matchIndex) { 3193 componentName = matchingCodecs.itemAt(matchIndex).mName.string(); 3194 quirks = matchingCodecs.itemAt(matchIndex).mQuirks; 3195 3196 pid_t tid = androidGetTid(); 3197 int prevPriority = androidGetThreadPriority(tid); 3198 androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND); 3199 status_t err = omx->allocateNode(componentName.c_str(), observer, &node); 3200 androidSetThreadPriority(tid, prevPriority); 3201 3202 if (err == OK) { 3203 break; 3204 } 3205 3206 node = NULL; 3207 } 3208 3209 if (node == NULL) { 3210 if (!mime.empty()) { 3211 ALOGE("Unable to instantiate a decoder for type '%s'.", 3212 mime.c_str()); 3213 } else { 3214 ALOGE("Unable to instantiate decoder '%s'.", componentName.c_str()); 3215 } 3216 3217 mCodec->signalError(OMX_ErrorComponentNotFound); 3218 return false; 3219 } 3220 3221 notify = new AMessage(kWhatOMXMessage, mCodec->id()); 3222 observer->setNotificationMessage(notify); 3223 3224 mCodec->mComponentName = componentName; 3225 mCodec->mFlags = 0; 3226 3227 if (componentName.endsWith(".secure")) { 3228 mCodec->mFlags |= kFlagIsSecure; 3229 } 3230 3231 mCodec->mQuirks = quirks; 3232 mCodec->mOMX = omx; 3233 mCodec->mNode = node; 3234 3235 { 3236 sp<AMessage> notify = mCodec->mNotify->dup(); 3237 notify->setInt32("what", ACodec::kWhatComponentAllocated); 3238 notify->setString("componentName", mCodec->mComponentName.c_str()); 3239 notify->post(); 3240 } 3241 3242 mCodec->changeState(mCodec->mLoadedState); 3243 3244 return true; 3245} 3246 3247//////////////////////////////////////////////////////////////////////////////// 3248 3249ACodec::LoadedState::LoadedState(ACodec *codec) 3250 : BaseState(codec) { 3251} 3252 3253void ACodec::LoadedState::stateEntered() { 3254 ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str()); 3255 3256 mCodec->mPortEOS[kPortIndexInput] = 3257 mCodec->mPortEOS[kPortIndexOutput] = false; 3258 3259 mCodec->mInputEOSResult = OK; 3260 3261 if (mCodec->mShutdownInProgress) { 3262 bool keepComponentAllocated = mCodec->mKeepComponentAllocated; 3263 3264 mCodec->mShutdownInProgress = false; 3265 mCodec->mKeepComponentAllocated = false; 3266 3267 onShutdown(keepComponentAllocated); 3268 } 3269} 3270 3271void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) { 3272 if (!keepComponentAllocated) { 3273 CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK); 3274 3275 mCodec->changeState(mCodec->mUninitializedState); 3276 } 3277 3278 sp<AMessage> notify = mCodec->mNotify->dup(); 3279 notify->setInt32("what", ACodec::kWhatShutdownCompleted); 3280 notify->post(); 3281} 3282 3283bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) { 3284 bool handled = false; 3285 3286 switch (msg->what()) { 3287 case ACodec::kWhatConfigureComponent: 3288 { 3289 onConfigureComponent(msg); 3290 handled = true; 3291 break; 3292 } 3293 3294 case ACodec::kWhatCreateInputSurface: 3295 { 3296 onCreateInputSurface(msg); 3297 handled = true; 3298 break; 3299 } 3300 3301 case ACodec::kWhatStart: 3302 { 3303 onStart(); 3304 handled = true; 3305 break; 3306 } 3307 3308 case ACodec::kWhatShutdown: 3309 { 3310 int32_t keepComponentAllocated; 3311 CHECK(msg->findInt32( 3312 "keepComponentAllocated", &keepComponentAllocated)); 3313 3314 onShutdown(keepComponentAllocated); 3315 3316 handled = true; 3317 break; 3318 } 3319 3320 case ACodec::kWhatFlush: 3321 { 3322 sp<AMessage> notify = mCodec->mNotify->dup(); 3323 notify->setInt32("what", ACodec::kWhatFlushCompleted); 3324 notify->post(); 3325 3326 handled = true; 3327 break; 3328 } 3329 3330 default: 3331 return BaseState::onMessageReceived(msg); 3332 } 3333 3334 return handled; 3335} 3336 3337bool ACodec::LoadedState::onConfigureComponent( 3338 const sp<AMessage> &msg) { 3339 ALOGV("onConfigureComponent"); 3340 3341 CHECK(mCodec->mNode != NULL); 3342 3343 AString mime; 3344 CHECK(msg->findString("mime", &mime)); 3345 3346 status_t err = mCodec->configureCodec(mime.c_str(), msg); 3347 3348 if (err != OK) { 3349 ALOGE("[%s] configureCodec returning error %d", 3350 mCodec->mComponentName.c_str(), err); 3351 3352 mCodec->signalError(OMX_ErrorUndefined, err); 3353 return false; 3354 } 3355 3356 sp<RefBase> obj; 3357 if (msg->findObject("native-window", &obj) 3358 && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) { 3359 sp<NativeWindowWrapper> nativeWindow( 3360 static_cast<NativeWindowWrapper *>(obj.get())); 3361 CHECK(nativeWindow != NULL); 3362 mCodec->mNativeWindow = nativeWindow->getNativeWindow(); 3363 3364 native_window_set_scaling_mode( 3365 mCodec->mNativeWindow.get(), 3366 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); 3367 } 3368 CHECK_EQ((status_t)OK, mCodec->initNativeWindow()); 3369 3370 { 3371 sp<AMessage> notify = mCodec->mNotify->dup(); 3372 notify->setInt32("what", ACodec::kWhatComponentConfigured); 3373 notify->post(); 3374 } 3375 3376 return true; 3377} 3378 3379void ACodec::LoadedState::onCreateInputSurface( 3380 const sp<AMessage> &msg) { 3381 ALOGV("onCreateInputSurface"); 3382 3383 sp<AMessage> notify = mCodec->mNotify->dup(); 3384 notify->setInt32("what", ACodec::kWhatInputSurfaceCreated); 3385 3386 sp<IGraphicBufferProducer> bufferProducer; 3387 status_t err; 3388 3389 err = mCodec->mOMX->createInputSurface(mCodec->mNode, kPortIndexInput, 3390 &bufferProducer); 3391 if (err == OK) { 3392 notify->setObject("input-surface", 3393 new BufferProducerWrapper(bufferProducer)); 3394 } else { 3395 // Can't use mCodec->signalError() here -- MediaCodec won't forward 3396 // the error through because it's in the "configured" state. We 3397 // send a kWhatInputSurfaceCreated with an error value instead. 3398 ALOGE("[%s] onCreateInputSurface returning error %d", 3399 mCodec->mComponentName.c_str(), err); 3400 notify->setInt32("err", err); 3401 } 3402 notify->post(); 3403} 3404 3405void ACodec::LoadedState::onStart() { 3406 ALOGV("onStart"); 3407 3408 CHECK_EQ(mCodec->mOMX->sendCommand( 3409 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle), 3410 (status_t)OK); 3411 3412 mCodec->changeState(mCodec->mLoadedToIdleState); 3413} 3414 3415//////////////////////////////////////////////////////////////////////////////// 3416 3417ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec) 3418 : BaseState(codec) { 3419} 3420 3421void ACodec::LoadedToIdleState::stateEntered() { 3422 ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str()); 3423 3424 status_t err; 3425 if ((err = allocateBuffers()) != OK) { 3426 ALOGE("Failed to allocate buffers after transitioning to IDLE state " 3427 "(error 0x%08x)", 3428 err); 3429 3430 mCodec->signalError(OMX_ErrorUndefined, err); 3431 3432 mCodec->changeState(mCodec->mLoadedState); 3433 } 3434} 3435 3436status_t ACodec::LoadedToIdleState::allocateBuffers() { 3437 status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput); 3438 3439 if (err != OK) { 3440 return err; 3441 } 3442 3443 return mCodec->allocateBuffersOnPort(kPortIndexOutput); 3444} 3445 3446bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) { 3447 switch (msg->what()) { 3448 case kWhatShutdown: 3449 { 3450 mCodec->deferMessage(msg); 3451 return true; 3452 } 3453 3454 case kWhatSignalEndOfInputStream: 3455 { 3456 mCodec->onSignalEndOfInputStream(); 3457 return true; 3458 } 3459 3460 case kWhatResume: 3461 { 3462 // We'll be active soon enough. 3463 return true; 3464 } 3465 3466 case kWhatFlush: 3467 { 3468 // We haven't even started yet, so we're flushed alright... 3469 sp<AMessage> notify = mCodec->mNotify->dup(); 3470 notify->setInt32("what", ACodec::kWhatFlushCompleted); 3471 notify->post(); 3472 return true; 3473 } 3474 3475 default: 3476 return BaseState::onMessageReceived(msg); 3477 } 3478} 3479 3480bool ACodec::LoadedToIdleState::onOMXEvent( 3481 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3482 switch (event) { 3483 case OMX_EventCmdComplete: 3484 { 3485 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 3486 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); 3487 3488 CHECK_EQ(mCodec->mOMX->sendCommand( 3489 mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting), 3490 (status_t)OK); 3491 3492 mCodec->changeState(mCodec->mIdleToExecutingState); 3493 3494 return true; 3495 } 3496 3497 default: 3498 return BaseState::onOMXEvent(event, data1, data2); 3499 } 3500} 3501 3502//////////////////////////////////////////////////////////////////////////////// 3503 3504ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec) 3505 : BaseState(codec) { 3506} 3507 3508void ACodec::IdleToExecutingState::stateEntered() { 3509 ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str()); 3510} 3511 3512bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) { 3513 switch (msg->what()) { 3514 case kWhatShutdown: 3515 { 3516 mCodec->deferMessage(msg); 3517 return true; 3518 } 3519 3520 case kWhatResume: 3521 { 3522 // We'll be active soon enough. 3523 return true; 3524 } 3525 3526 case kWhatFlush: 3527 { 3528 // We haven't even started yet, so we're flushed alright... 3529 sp<AMessage> notify = mCodec->mNotify->dup(); 3530 notify->setInt32("what", ACodec::kWhatFlushCompleted); 3531 notify->post(); 3532 3533 return true; 3534 } 3535 3536 case kWhatSignalEndOfInputStream: 3537 { 3538 mCodec->onSignalEndOfInputStream(); 3539 return true; 3540 } 3541 3542 default: 3543 return BaseState::onMessageReceived(msg); 3544 } 3545} 3546 3547bool ACodec::IdleToExecutingState::onOMXEvent( 3548 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3549 switch (event) { 3550 case OMX_EventCmdComplete: 3551 { 3552 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 3553 CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting); 3554 3555 mCodec->mExecutingState->resume(); 3556 mCodec->changeState(mCodec->mExecutingState); 3557 3558 return true; 3559 } 3560 3561 default: 3562 return BaseState::onOMXEvent(event, data1, data2); 3563 } 3564} 3565 3566//////////////////////////////////////////////////////////////////////////////// 3567 3568ACodec::ExecutingState::ExecutingState(ACodec *codec) 3569 : BaseState(codec), 3570 mActive(false) { 3571} 3572 3573ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode( 3574 OMX_U32 portIndex) { 3575 return RESUBMIT_BUFFERS; 3576} 3577 3578void ACodec::ExecutingState::submitOutputBuffers() { 3579 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) { 3580 BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i); 3581 3582 if (mCodec->mNativeWindow != NULL) { 3583 CHECK(info->mStatus == BufferInfo::OWNED_BY_US 3584 || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW); 3585 3586 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 3587 continue; 3588 } 3589 } else { 3590 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 3591 } 3592 3593 ALOGV("[%s] calling fillBuffer %p", 3594 mCodec->mComponentName.c_str(), info->mBufferID); 3595 3596 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), 3597 (status_t)OK); 3598 3599 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 3600 } 3601} 3602 3603void ACodec::ExecutingState::resume() { 3604 if (mActive) { 3605 ALOGV("[%s] We're already active, no need to resume.", 3606 mCodec->mComponentName.c_str()); 3607 3608 return; 3609 } 3610 3611 submitOutputBuffers(); 3612 3613 // Post the first input buffer. 3614 CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u); 3615 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0); 3616 3617 postFillThisBuffer(info); 3618 3619 mActive = true; 3620} 3621 3622void ACodec::ExecutingState::stateEntered() { 3623 ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str()); 3624 3625 mCodec->processDeferredMessages(); 3626} 3627 3628bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) { 3629 bool handled = false; 3630 3631 switch (msg->what()) { 3632 case kWhatShutdown: 3633 { 3634 int32_t keepComponentAllocated; 3635 CHECK(msg->findInt32( 3636 "keepComponentAllocated", &keepComponentAllocated)); 3637 3638 mCodec->mShutdownInProgress = true; 3639 mCodec->mKeepComponentAllocated = keepComponentAllocated; 3640 3641 mActive = false; 3642 3643 CHECK_EQ(mCodec->mOMX->sendCommand( 3644 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle), 3645 (status_t)OK); 3646 3647 mCodec->changeState(mCodec->mExecutingToIdleState); 3648 3649 handled = true; 3650 break; 3651 } 3652 3653 case kWhatFlush: 3654 { 3655 ALOGV("[%s] ExecutingState flushing now " 3656 "(codec owns %d/%d input, %d/%d output).", 3657 mCodec->mComponentName.c_str(), 3658 mCodec->countBuffersOwnedByComponent(kPortIndexInput), 3659 mCodec->mBuffers[kPortIndexInput].size(), 3660 mCodec->countBuffersOwnedByComponent(kPortIndexOutput), 3661 mCodec->mBuffers[kPortIndexOutput].size()); 3662 3663 mActive = false; 3664 3665 CHECK_EQ(mCodec->mOMX->sendCommand( 3666 mCodec->mNode, OMX_CommandFlush, OMX_ALL), 3667 (status_t)OK); 3668 3669 mCodec->changeState(mCodec->mFlushingState); 3670 3671 handled = true; 3672 break; 3673 } 3674 3675 case kWhatResume: 3676 { 3677 resume(); 3678 3679 handled = true; 3680 break; 3681 } 3682 3683 case kWhatRequestIDRFrame: 3684 { 3685 status_t err = mCodec->requestIDRFrame(); 3686 if (err != OK) { 3687 ALOGW("Requesting an IDR frame failed."); 3688 } 3689 3690 handled = true; 3691 break; 3692 } 3693 3694 case kWhatSetParameters: 3695 { 3696 sp<AMessage> params; 3697 CHECK(msg->findMessage("params", ¶ms)); 3698 3699 status_t err = mCodec->setParameters(params); 3700 3701 sp<AMessage> reply; 3702 if (msg->findMessage("reply", &reply)) { 3703 reply->setInt32("err", err); 3704 reply->post(); 3705 } 3706 3707 handled = true; 3708 break; 3709 } 3710 3711 case ACodec::kWhatSignalEndOfInputStream: 3712 { 3713 mCodec->onSignalEndOfInputStream(); 3714 handled = true; 3715 break; 3716 } 3717 3718 default: 3719 handled = BaseState::onMessageReceived(msg); 3720 break; 3721 } 3722 3723 return handled; 3724} 3725 3726status_t ACodec::setParameters(const sp<AMessage> ¶ms) { 3727 int32_t videoBitrate; 3728 if (params->findInt32("videoBitrate", &videoBitrate)) { 3729 OMX_VIDEO_CONFIG_BITRATETYPE configParams; 3730 InitOMXParams(&configParams); 3731 configParams.nPortIndex = kPortIndexOutput; 3732 configParams.nEncodeBitrate = videoBitrate; 3733 3734 status_t err = mOMX->setConfig( 3735 mNode, 3736 OMX_IndexConfigVideoBitrate, 3737 &configParams, 3738 sizeof(configParams)); 3739 3740 if (err != OK) { 3741 ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d", 3742 videoBitrate, err); 3743 3744 return err; 3745 } 3746 } 3747 3748 return OK; 3749} 3750 3751void ACodec::onSignalEndOfInputStream() { 3752 sp<AMessage> notify = mNotify->dup(); 3753 notify->setInt32("what", ACodec::kWhatSignaledInputEOS); 3754 3755 status_t err = mOMX->signalEndOfInputStream(mNode); 3756 if (err != OK) { 3757 notify->setInt32("err", err); 3758 } 3759 notify->post(); 3760} 3761 3762bool ACodec::ExecutingState::onOMXEvent( 3763 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3764 switch (event) { 3765 case OMX_EventPortSettingsChanged: 3766 { 3767 CHECK_EQ(data1, (OMX_U32)kPortIndexOutput); 3768 3769 if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) { 3770 CHECK_EQ(mCodec->mOMX->sendCommand( 3771 mCodec->mNode, 3772 OMX_CommandPortDisable, kPortIndexOutput), 3773 (status_t)OK); 3774 3775 mCodec->freeOutputBuffersNotOwnedByComponent(); 3776 3777 mCodec->changeState(mCodec->mOutputPortSettingsChangedState); 3778 } else if (data2 == OMX_IndexConfigCommonOutputCrop) { 3779 mCodec->mSentFormat = false; 3780 } else { 3781 ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx", 3782 mCodec->mComponentName.c_str(), data2); 3783 } 3784 3785 return true; 3786 } 3787 3788 case OMX_EventBufferFlag: 3789 { 3790 return true; 3791 } 3792 3793 default: 3794 return BaseState::onOMXEvent(event, data1, data2); 3795 } 3796} 3797 3798//////////////////////////////////////////////////////////////////////////////// 3799 3800ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState( 3801 ACodec *codec) 3802 : BaseState(codec) { 3803} 3804 3805ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode( 3806 OMX_U32 portIndex) { 3807 if (portIndex == kPortIndexOutput) { 3808 return FREE_BUFFERS; 3809 } 3810 3811 CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput); 3812 3813 return RESUBMIT_BUFFERS; 3814} 3815 3816bool ACodec::OutputPortSettingsChangedState::onMessageReceived( 3817 const sp<AMessage> &msg) { 3818 bool handled = false; 3819 3820 switch (msg->what()) { 3821 case kWhatFlush: 3822 case kWhatShutdown: 3823 case kWhatResume: 3824 { 3825 if (msg->what() == kWhatResume) { 3826 ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str()); 3827 } 3828 3829 mCodec->deferMessage(msg); 3830 handled = true; 3831 break; 3832 } 3833 3834 default: 3835 handled = BaseState::onMessageReceived(msg); 3836 break; 3837 } 3838 3839 return handled; 3840} 3841 3842void ACodec::OutputPortSettingsChangedState::stateEntered() { 3843 ALOGV("[%s] Now handling output port settings change", 3844 mCodec->mComponentName.c_str()); 3845} 3846 3847bool ACodec::OutputPortSettingsChangedState::onOMXEvent( 3848 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3849 switch (event) { 3850 case OMX_EventCmdComplete: 3851 { 3852 if (data1 == (OMX_U32)OMX_CommandPortDisable) { 3853 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput); 3854 3855 ALOGV("[%s] Output port now disabled.", 3856 mCodec->mComponentName.c_str()); 3857 3858 CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty()); 3859 mCodec->mDealer[kPortIndexOutput].clear(); 3860 3861 CHECK_EQ(mCodec->mOMX->sendCommand( 3862 mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput), 3863 (status_t)OK); 3864 3865 status_t err; 3866 if ((err = mCodec->allocateBuffersOnPort( 3867 kPortIndexOutput)) != OK) { 3868 ALOGE("Failed to allocate output port buffers after " 3869 "port reconfiguration (error 0x%08x)", 3870 err); 3871 3872 mCodec->signalError(OMX_ErrorUndefined, err); 3873 3874 // This is technically not correct, but appears to be 3875 // the only way to free the component instance. 3876 // Controlled transitioning from excecuting->idle 3877 // and idle->loaded seem impossible probably because 3878 // the output port never finishes re-enabling. 3879 mCodec->mShutdownInProgress = true; 3880 mCodec->mKeepComponentAllocated = false; 3881 mCodec->changeState(mCodec->mLoadedState); 3882 } 3883 3884 return true; 3885 } else if (data1 == (OMX_U32)OMX_CommandPortEnable) { 3886 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput); 3887 3888 mCodec->mSentFormat = false; 3889 3890 ALOGV("[%s] Output port now reenabled.", 3891 mCodec->mComponentName.c_str()); 3892 3893 if (mCodec->mExecutingState->active()) { 3894 mCodec->mExecutingState->submitOutputBuffers(); 3895 } 3896 3897 mCodec->changeState(mCodec->mExecutingState); 3898 3899 return true; 3900 } 3901 3902 return false; 3903 } 3904 3905 default: 3906 return false; 3907 } 3908} 3909 3910//////////////////////////////////////////////////////////////////////////////// 3911 3912ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec) 3913 : BaseState(codec), 3914 mComponentNowIdle(false) { 3915} 3916 3917bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) { 3918 bool handled = false; 3919 3920 switch (msg->what()) { 3921 case kWhatFlush: 3922 { 3923 // Don't send me a flush request if you previously wanted me 3924 // to shutdown. 3925 TRESPASS(); 3926 break; 3927 } 3928 3929 case kWhatShutdown: 3930 { 3931 // We're already doing that... 3932 3933 handled = true; 3934 break; 3935 } 3936 3937 default: 3938 handled = BaseState::onMessageReceived(msg); 3939 break; 3940 } 3941 3942 return handled; 3943} 3944 3945void ACodec::ExecutingToIdleState::stateEntered() { 3946 ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str()); 3947 3948 mComponentNowIdle = false; 3949 mCodec->mSentFormat = false; 3950} 3951 3952bool ACodec::ExecutingToIdleState::onOMXEvent( 3953 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3954 switch (event) { 3955 case OMX_EventCmdComplete: 3956 { 3957 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 3958 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); 3959 3960 mComponentNowIdle = true; 3961 3962 changeStateIfWeOwnAllBuffers(); 3963 3964 return true; 3965 } 3966 3967 case OMX_EventPortSettingsChanged: 3968 case OMX_EventBufferFlag: 3969 { 3970 // We're shutting down and don't care about this anymore. 3971 return true; 3972 } 3973 3974 default: 3975 return BaseState::onOMXEvent(event, data1, data2); 3976 } 3977} 3978 3979void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() { 3980 if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) { 3981 CHECK_EQ(mCodec->mOMX->sendCommand( 3982 mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded), 3983 (status_t)OK); 3984 3985 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK); 3986 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK); 3987 3988 if (mCodec->mFlags & kFlagIsSecure && mCodec->mNativeWindow != NULL) { 3989 // We push enough 1x1 blank buffers to ensure that one of 3990 // them has made it to the display. This allows the OMX 3991 // component teardown to zero out any protected buffers 3992 // without the risk of scanning out one of those buffers. 3993 mCodec->pushBlankBuffersToNativeWindow(); 3994 } 3995 3996 mCodec->changeState(mCodec->mIdleToLoadedState); 3997 } 3998} 3999 4000void ACodec::ExecutingToIdleState::onInputBufferFilled( 4001 const sp<AMessage> &msg) { 4002 BaseState::onInputBufferFilled(msg); 4003 4004 changeStateIfWeOwnAllBuffers(); 4005} 4006 4007void ACodec::ExecutingToIdleState::onOutputBufferDrained( 4008 const sp<AMessage> &msg) { 4009 BaseState::onOutputBufferDrained(msg); 4010 4011 changeStateIfWeOwnAllBuffers(); 4012} 4013 4014//////////////////////////////////////////////////////////////////////////////// 4015 4016ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec) 4017 : BaseState(codec) { 4018} 4019 4020bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) { 4021 bool handled = false; 4022 4023 switch (msg->what()) { 4024 case kWhatShutdown: 4025 { 4026 // We're already doing that... 4027 4028 handled = true; 4029 break; 4030 } 4031 4032 case kWhatFlush: 4033 { 4034 // Don't send me a flush request if you previously wanted me 4035 // to shutdown. 4036 TRESPASS(); 4037 break; 4038 } 4039 4040 default: 4041 handled = BaseState::onMessageReceived(msg); 4042 break; 4043 } 4044 4045 return handled; 4046} 4047 4048void ACodec::IdleToLoadedState::stateEntered() { 4049 ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str()); 4050} 4051 4052bool ACodec::IdleToLoadedState::onOMXEvent( 4053 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 4054 switch (event) { 4055 case OMX_EventCmdComplete: 4056 { 4057 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 4058 CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded); 4059 4060 mCodec->changeState(mCodec->mLoadedState); 4061 4062 return true; 4063 } 4064 4065 default: 4066 return BaseState::onOMXEvent(event, data1, data2); 4067 } 4068} 4069 4070//////////////////////////////////////////////////////////////////////////////// 4071 4072ACodec::FlushingState::FlushingState(ACodec *codec) 4073 : BaseState(codec) { 4074} 4075 4076void ACodec::FlushingState::stateEntered() { 4077 ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str()); 4078 4079 mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false; 4080} 4081 4082bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) { 4083 bool handled = false; 4084 4085 switch (msg->what()) { 4086 case kWhatShutdown: 4087 { 4088 mCodec->deferMessage(msg); 4089 break; 4090 } 4091 4092 case kWhatFlush: 4093 { 4094 // We're already doing this right now. 4095 handled = true; 4096 break; 4097 } 4098 4099 default: 4100 handled = BaseState::onMessageReceived(msg); 4101 break; 4102 } 4103 4104 return handled; 4105} 4106 4107bool ACodec::FlushingState::onOMXEvent( 4108 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 4109 ALOGV("[%s] FlushingState onOMXEvent(%d,%ld)", 4110 mCodec->mComponentName.c_str(), event, data1); 4111 4112 switch (event) { 4113 case OMX_EventCmdComplete: 4114 { 4115 CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush); 4116 4117 if (data2 == kPortIndexInput || data2 == kPortIndexOutput) { 4118 CHECK(!mFlushComplete[data2]); 4119 mFlushComplete[data2] = true; 4120 4121 if (mFlushComplete[kPortIndexInput] 4122 && mFlushComplete[kPortIndexOutput]) { 4123 changeStateIfWeOwnAllBuffers(); 4124 } 4125 } else { 4126 CHECK_EQ(data2, OMX_ALL); 4127 CHECK(mFlushComplete[kPortIndexInput]); 4128 CHECK(mFlushComplete[kPortIndexOutput]); 4129 4130 changeStateIfWeOwnAllBuffers(); 4131 } 4132 4133 return true; 4134 } 4135 4136 case OMX_EventPortSettingsChanged: 4137 { 4138 sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id()); 4139 msg->setInt32("type", omx_message::EVENT); 4140 msg->setPointer("node", mCodec->mNode); 4141 msg->setInt32("event", event); 4142 msg->setInt32("data1", data1); 4143 msg->setInt32("data2", data2); 4144 4145 ALOGV("[%s] Deferring OMX_EventPortSettingsChanged", 4146 mCodec->mComponentName.c_str()); 4147 4148 mCodec->deferMessage(msg); 4149 4150 return true; 4151 } 4152 4153 default: 4154 return BaseState::onOMXEvent(event, data1, data2); 4155 } 4156 4157 return true; 4158} 4159 4160void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) { 4161 BaseState::onOutputBufferDrained(msg); 4162 4163 changeStateIfWeOwnAllBuffers(); 4164} 4165 4166void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) { 4167 BaseState::onInputBufferFilled(msg); 4168 4169 changeStateIfWeOwnAllBuffers(); 4170} 4171 4172void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() { 4173 if (mFlushComplete[kPortIndexInput] 4174 && mFlushComplete[kPortIndexOutput] 4175 && mCodec->allYourBuffersAreBelongToUs()) { 4176 sp<AMessage> notify = mCodec->mNotify->dup(); 4177 notify->setInt32("what", ACodec::kWhatFlushCompleted); 4178 notify->post(); 4179 4180 mCodec->mPortEOS[kPortIndexInput] = 4181 mCodec->mPortEOS[kPortIndexOutput] = false; 4182 4183 mCodec->mInputEOSResult = OK; 4184 4185 mCodec->changeState(mCodec->mExecutingState); 4186 } 4187} 4188 4189} // namespace android 4190