ACodec.cpp revision aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5b
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/MediaCodecList.h> 30#include <media/stagefright/MediaDefs.h> 31#include <media/stagefright/NativeWindowWrapper.h> 32#include <media/stagefright/OMXClient.h> 33#include <media/stagefright/OMXCodec.h> 34 35#include <OMX_Component.h> 36 37namespace android { 38 39template<class T> 40static void InitOMXParams(T *params) { 41 params->nSize = sizeof(T); 42 params->nVersion.s.nVersionMajor = 1; 43 params->nVersion.s.nVersionMinor = 0; 44 params->nVersion.s.nRevision = 0; 45 params->nVersion.s.nStep = 0; 46} 47 48struct CodecObserver : public BnOMXObserver { 49 CodecObserver() {} 50 51 void setNotificationMessage(const sp<AMessage> &msg) { 52 mNotify = msg; 53 } 54 55 // from IOMXObserver 56 virtual void onMessage(const omx_message &omx_msg) { 57 sp<AMessage> msg = mNotify->dup(); 58 59 msg->setInt32("type", omx_msg.type); 60 msg->setPointer("node", omx_msg.node); 61 62 switch (omx_msg.type) { 63 case omx_message::EVENT: 64 { 65 msg->setInt32("event", omx_msg.u.event_data.event); 66 msg->setInt32("data1", omx_msg.u.event_data.data1); 67 msg->setInt32("data2", omx_msg.u.event_data.data2); 68 break; 69 } 70 71 case omx_message::EMPTY_BUFFER_DONE: 72 { 73 msg->setPointer("buffer", omx_msg.u.buffer_data.buffer); 74 break; 75 } 76 77 case omx_message::FILL_BUFFER_DONE: 78 { 79 msg->setPointer( 80 "buffer", omx_msg.u.extended_buffer_data.buffer); 81 msg->setInt32( 82 "range_offset", 83 omx_msg.u.extended_buffer_data.range_offset); 84 msg->setInt32( 85 "range_length", 86 omx_msg.u.extended_buffer_data.range_length); 87 msg->setInt32( 88 "flags", 89 omx_msg.u.extended_buffer_data.flags); 90 msg->setInt64( 91 "timestamp", 92 omx_msg.u.extended_buffer_data.timestamp); 93 msg->setPointer( 94 "platform_private", 95 omx_msg.u.extended_buffer_data.platform_private); 96 msg->setPointer( 97 "data_ptr", 98 omx_msg.u.extended_buffer_data.data_ptr); 99 break; 100 } 101 102 default: 103 TRESPASS(); 104 break; 105 } 106 107 msg->post(); 108 } 109 110protected: 111 virtual ~CodecObserver() {} 112 113private: 114 sp<AMessage> mNotify; 115 116 DISALLOW_EVIL_CONSTRUCTORS(CodecObserver); 117}; 118 119//////////////////////////////////////////////////////////////////////////////// 120 121struct ACodec::BaseState : public AState { 122 BaseState(ACodec *codec, const sp<AState> &parentState = NULL); 123 124protected: 125 enum PortMode { 126 KEEP_BUFFERS, 127 RESUBMIT_BUFFERS, 128 FREE_BUFFERS, 129 }; 130 131 ACodec *mCodec; 132 133 virtual PortMode getPortMode(OMX_U32 portIndex); 134 135 virtual bool onMessageReceived(const sp<AMessage> &msg); 136 137 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 138 139 virtual void onOutputBufferDrained(const sp<AMessage> &msg); 140 virtual void onInputBufferFilled(const sp<AMessage> &msg); 141 142 void postFillThisBuffer(BufferInfo *info); 143 144private: 145 bool onOMXMessage(const sp<AMessage> &msg); 146 147 bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID); 148 149 bool onOMXFillBufferDone( 150 IOMX::buffer_id bufferID, 151 size_t rangeOffset, size_t rangeLength, 152 OMX_U32 flags, 153 int64_t timeUs, 154 void *platformPrivate, 155 void *dataPtr); 156 157 void getMoreInputDataIfPossible(); 158 159 DISALLOW_EVIL_CONSTRUCTORS(BaseState); 160}; 161 162//////////////////////////////////////////////////////////////////////////////// 163 164struct ACodec::UninitializedState : public ACodec::BaseState { 165 UninitializedState(ACodec *codec); 166 167protected: 168 virtual bool onMessageReceived(const sp<AMessage> &msg); 169 virtual void stateEntered(); 170 171private: 172 void onSetup(const sp<AMessage> &msg); 173 bool onAllocateComponent(const sp<AMessage> &msg); 174 175 DISALLOW_EVIL_CONSTRUCTORS(UninitializedState); 176}; 177 178//////////////////////////////////////////////////////////////////////////////// 179 180struct ACodec::LoadedState : public ACodec::BaseState { 181 LoadedState(ACodec *codec); 182 183protected: 184 virtual bool onMessageReceived(const sp<AMessage> &msg); 185 virtual void stateEntered(); 186 187private: 188 friend struct ACodec::UninitializedState; 189 190 bool onConfigureComponent(const sp<AMessage> &msg); 191 void onStart(); 192 void onShutdown(bool keepComponentAllocated); 193 194 DISALLOW_EVIL_CONSTRUCTORS(LoadedState); 195}; 196 197//////////////////////////////////////////////////////////////////////////////// 198 199struct ACodec::LoadedToIdleState : public ACodec::BaseState { 200 LoadedToIdleState(ACodec *codec); 201 202protected: 203 virtual bool onMessageReceived(const sp<AMessage> &msg); 204 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 205 virtual void stateEntered(); 206 207private: 208 status_t allocateBuffers(); 209 210 DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState); 211}; 212 213//////////////////////////////////////////////////////////////////////////////// 214 215struct ACodec::IdleToExecutingState : public ACodec::BaseState { 216 IdleToExecutingState(ACodec *codec); 217 218protected: 219 virtual bool onMessageReceived(const sp<AMessage> &msg); 220 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 221 virtual void stateEntered(); 222 223private: 224 DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState); 225}; 226 227//////////////////////////////////////////////////////////////////////////////// 228 229struct ACodec::ExecutingState : public ACodec::BaseState { 230 ExecutingState(ACodec *codec); 231 232 void submitOutputBuffers(); 233 234 // Submit output buffers to the decoder, submit input buffers to client 235 // to fill with data. 236 void resume(); 237 238 // Returns true iff input and output buffers are in play. 239 bool active() const { return mActive; } 240 241protected: 242 virtual PortMode getPortMode(OMX_U32 portIndex); 243 virtual bool onMessageReceived(const sp<AMessage> &msg); 244 virtual void stateEntered(); 245 246 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 247 248private: 249 bool mActive; 250 251 DISALLOW_EVIL_CONSTRUCTORS(ExecutingState); 252}; 253 254//////////////////////////////////////////////////////////////////////////////// 255 256struct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState { 257 OutputPortSettingsChangedState(ACodec *codec); 258 259protected: 260 virtual PortMode getPortMode(OMX_U32 portIndex); 261 virtual bool onMessageReceived(const sp<AMessage> &msg); 262 virtual void stateEntered(); 263 264 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 265 266private: 267 DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState); 268}; 269 270//////////////////////////////////////////////////////////////////////////////// 271 272struct ACodec::ExecutingToIdleState : public ACodec::BaseState { 273 ExecutingToIdleState(ACodec *codec); 274 275protected: 276 virtual bool onMessageReceived(const sp<AMessage> &msg); 277 virtual void stateEntered(); 278 279 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 280 281 virtual void onOutputBufferDrained(const sp<AMessage> &msg); 282 virtual void onInputBufferFilled(const sp<AMessage> &msg); 283 284private: 285 void changeStateIfWeOwnAllBuffers(); 286 287 bool mComponentNowIdle; 288 289 DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState); 290}; 291 292//////////////////////////////////////////////////////////////////////////////// 293 294struct ACodec::IdleToLoadedState : public ACodec::BaseState { 295 IdleToLoadedState(ACodec *codec); 296 297protected: 298 virtual bool onMessageReceived(const sp<AMessage> &msg); 299 virtual void stateEntered(); 300 301 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 302 303private: 304 DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState); 305}; 306 307//////////////////////////////////////////////////////////////////////////////// 308 309struct ACodec::FlushingState : public ACodec::BaseState { 310 FlushingState(ACodec *codec); 311 312protected: 313 virtual bool onMessageReceived(const sp<AMessage> &msg); 314 virtual void stateEntered(); 315 316 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 317 318 virtual void onOutputBufferDrained(const sp<AMessage> &msg); 319 virtual void onInputBufferFilled(const sp<AMessage> &msg); 320 321private: 322 bool mFlushComplete[2]; 323 324 void changeStateIfWeOwnAllBuffers(); 325 326 DISALLOW_EVIL_CONSTRUCTORS(FlushingState); 327}; 328 329//////////////////////////////////////////////////////////////////////////////// 330 331ACodec::ACodec() 332 : mQuirks(0), 333 mNode(NULL), 334 mSentFormat(false), 335 mIsEncoder(false), 336 mShutdownInProgress(false) { 337 mUninitializedState = new UninitializedState(this); 338 mLoadedState = new LoadedState(this); 339 mLoadedToIdleState = new LoadedToIdleState(this); 340 mIdleToExecutingState = new IdleToExecutingState(this); 341 mExecutingState = new ExecutingState(this); 342 343 mOutputPortSettingsChangedState = 344 new OutputPortSettingsChangedState(this); 345 346 mExecutingToIdleState = new ExecutingToIdleState(this); 347 mIdleToLoadedState = new IdleToLoadedState(this); 348 mFlushingState = new FlushingState(this); 349 350 mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false; 351 mInputEOSResult = OK; 352 353 changeState(mUninitializedState); 354} 355 356ACodec::~ACodec() { 357} 358 359void ACodec::setNotificationMessage(const sp<AMessage> &msg) { 360 mNotify = msg; 361} 362 363void ACodec::initiateSetup(const sp<AMessage> &msg) { 364 msg->setWhat(kWhatSetup); 365 msg->setTarget(id()); 366 msg->post(); 367} 368 369void ACodec::initiateAllocateComponent(const sp<AMessage> &msg) { 370 msg->setWhat(kWhatAllocateComponent); 371 msg->setTarget(id()); 372 msg->post(); 373} 374 375void ACodec::initiateConfigureComponent(const sp<AMessage> &msg) { 376 msg->setWhat(kWhatConfigureComponent); 377 msg->setTarget(id()); 378 msg->post(); 379} 380 381void ACodec::initiateStart() { 382 (new AMessage(kWhatStart, id()))->post(); 383} 384 385void ACodec::signalFlush() { 386 ALOGV("[%s] signalFlush", mComponentName.c_str()); 387 (new AMessage(kWhatFlush, id()))->post(); 388} 389 390void ACodec::signalResume() { 391 (new AMessage(kWhatResume, id()))->post(); 392} 393 394void ACodec::initiateShutdown(bool keepComponentAllocated) { 395 sp<AMessage> msg = new AMessage(kWhatShutdown, id()); 396 msg->setInt32("keepComponentAllocated", keepComponentAllocated); 397 msg->post(); 398} 399 400status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) { 401 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 402 403 CHECK(mDealer[portIndex] == NULL); 404 CHECK(mBuffers[portIndex].isEmpty()); 405 406 status_t err; 407 if (mNativeWindow != NULL && portIndex == kPortIndexOutput) { 408 err = allocateOutputBuffersFromNativeWindow(); 409 } else { 410 OMX_PARAM_PORTDEFINITIONTYPE def; 411 InitOMXParams(&def); 412 def.nPortIndex = portIndex; 413 414 err = mOMX->getParameter( 415 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 416 417 if (err == OK) { 418 ALOGV("[%s] Allocating %lu buffers of size %lu on %s port", 419 mComponentName.c_str(), 420 def.nBufferCountActual, def.nBufferSize, 421 portIndex == kPortIndexInput ? "input" : "output"); 422 423 size_t totalSize = def.nBufferCountActual * def.nBufferSize; 424 mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec"); 425 426 for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) { 427 sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize); 428 CHECK(mem.get() != NULL); 429 430 BufferInfo info; 431 info.mStatus = BufferInfo::OWNED_BY_US; 432 433 uint32_t requiresAllocateBufferBit = 434 (portIndex == kPortIndexInput) 435 ? OMXCodec::kRequiresAllocateBufferOnInputPorts 436 : OMXCodec::kRequiresAllocateBufferOnOutputPorts; 437 438 if (portIndex == kPortIndexInput && (mFlags & kFlagIsSecure)) { 439 mem.clear(); 440 441 void *ptr; 442 err = mOMX->allocateBuffer( 443 mNode, portIndex, def.nBufferSize, &info.mBufferID, 444 &ptr); 445 446 info.mData = new ABuffer(ptr, def.nBufferSize); 447 } else if (mQuirks & requiresAllocateBufferBit) { 448 err = mOMX->allocateBufferWithBackup( 449 mNode, portIndex, mem, &info.mBufferID); 450 } else { 451 err = mOMX->useBuffer(mNode, portIndex, mem, &info.mBufferID); 452 } 453 454 if (mem != NULL) { 455 info.mData = new ABuffer(mem->pointer(), def.nBufferSize); 456 } 457 458 mBuffers[portIndex].push(info); 459 } 460 } 461 } 462 463 if (err != OK) { 464 return err; 465 } 466 467 sp<AMessage> notify = mNotify->dup(); 468 notify->setInt32("what", ACodec::kWhatBuffersAllocated); 469 470 notify->setInt32("portIndex", portIndex); 471 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 472 AString name = StringPrintf("buffer-id_%d", i); 473 notify->setPointer(name.c_str(), mBuffers[portIndex][i].mBufferID); 474 475 name = StringPrintf("data_%d", i); 476 notify->setBuffer(name.c_str(), mBuffers[portIndex][i].mData); 477 } 478 479 notify->post(); 480 481 return OK; 482} 483 484status_t ACodec::allocateOutputBuffersFromNativeWindow() { 485 OMX_PARAM_PORTDEFINITIONTYPE def; 486 InitOMXParams(&def); 487 def.nPortIndex = kPortIndexOutput; 488 489 status_t err = mOMX->getParameter( 490 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 491 492 if (err != OK) { 493 return err; 494 } 495 496 err = native_window_set_scaling_mode(mNativeWindow.get(), 497 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); 498 499 if (err != OK) { 500 return err; 501 } 502 503 err = native_window_set_buffers_geometry( 504 mNativeWindow.get(), 505 def.format.video.nFrameWidth, 506 def.format.video.nFrameHeight, 507 def.format.video.eColorFormat); 508 509 if (err != 0) { 510 ALOGE("native_window_set_buffers_geometry failed: %s (%d)", 511 strerror(-err), -err); 512 return err; 513 } 514 515 // Set up the native window. 516 OMX_U32 usage = 0; 517 err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage); 518 if (err != 0) { 519 ALOGW("querying usage flags from OMX IL component failed: %d", err); 520 // XXX: Currently this error is logged, but not fatal. 521 usage = 0; 522 } 523 524 err = native_window_set_usage( 525 mNativeWindow.get(), 526 usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP); 527 528 if (err != 0) { 529 ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err); 530 return err; 531 } 532 533 int minUndequeuedBufs = 0; 534 err = mNativeWindow->query( 535 mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, 536 &minUndequeuedBufs); 537 538 if (err != 0) { 539 ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)", 540 strerror(-err), -err); 541 return err; 542 } 543 544 // XXX: Is this the right logic to use? It's not clear to me what the OMX 545 // buffer counts refer to - how do they account for the renderer holding on 546 // to buffers? 547 if (def.nBufferCountActual < def.nBufferCountMin + minUndequeuedBufs) { 548 OMX_U32 newBufferCount = def.nBufferCountMin + minUndequeuedBufs; 549 def.nBufferCountActual = newBufferCount; 550 err = mOMX->setParameter( 551 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 552 553 if (err != OK) { 554 ALOGE("[%s] setting nBufferCountActual to %lu failed: %d", 555 mComponentName.c_str(), newBufferCount, err); 556 return err; 557 } 558 } 559 560 err = native_window_set_buffer_count( 561 mNativeWindow.get(), def.nBufferCountActual); 562 563 if (err != 0) { 564 ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), 565 -err); 566 return err; 567 } 568 569 ALOGV("[%s] Allocating %lu buffers from a native window of size %lu on " 570 "output port", 571 mComponentName.c_str(), def.nBufferCountActual, def.nBufferSize); 572 573 // Dequeue buffers and send them to OMX 574 for (OMX_U32 i = 0; i < def.nBufferCountActual; i++) { 575 ANativeWindowBuffer *buf; 576 err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf); 577 if (err != 0) { 578 ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err); 579 break; 580 } 581 582 sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false)); 583 BufferInfo info; 584 info.mStatus = BufferInfo::OWNED_BY_US; 585 info.mData = new ABuffer(0); 586 info.mGraphicBuffer = graphicBuffer; 587 mBuffers[kPortIndexOutput].push(info); 588 589 IOMX::buffer_id bufferId; 590 err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer, 591 &bufferId); 592 if (err != 0) { 593 ALOGE("registering GraphicBuffer %lu with OMX IL component failed: " 594 "%d", i, err); 595 break; 596 } 597 598 mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId; 599 600 ALOGV("[%s] Registered graphic buffer with ID %p (pointer = %p)", 601 mComponentName.c_str(), 602 bufferId, graphicBuffer.get()); 603 } 604 605 OMX_U32 cancelStart; 606 OMX_U32 cancelEnd; 607 608 if (err != 0) { 609 // If an error occurred while dequeuing we need to cancel any buffers 610 // that were dequeued. 611 cancelStart = 0; 612 cancelEnd = mBuffers[kPortIndexOutput].size(); 613 } else { 614 // Return the last two buffers to the native window. 615 cancelStart = def.nBufferCountActual - minUndequeuedBufs; 616 cancelEnd = def.nBufferCountActual; 617 } 618 619 for (OMX_U32 i = cancelStart; i < cancelEnd; i++) { 620 BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i); 621 cancelBufferToNativeWindow(info); 622 } 623 624 return err; 625} 626 627status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) { 628 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 629 630 ALOGV("[%s] Calling cancelBuffer on buffer %p", 631 mComponentName.c_str(), info->mBufferID); 632 633 int err = mNativeWindow->cancelBuffer( 634 mNativeWindow.get(), info->mGraphicBuffer.get()); 635 636 CHECK_EQ(err, 0); 637 638 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 639 640 return OK; 641} 642 643ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() { 644 ANativeWindowBuffer *buf; 645 if (mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf) != 0) { 646 ALOGE("dequeueBuffer failed."); 647 return NULL; 648 } 649 650 for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) { 651 BufferInfo *info = 652 &mBuffers[kPortIndexOutput].editItemAt(i); 653 654 if (info->mGraphicBuffer->handle == buf->handle) { 655 CHECK_EQ((int)info->mStatus, 656 (int)BufferInfo::OWNED_BY_NATIVE_WINDOW); 657 658 info->mStatus = BufferInfo::OWNED_BY_US; 659 660 return info; 661 } 662 } 663 664 TRESPASS(); 665 666 return NULL; 667} 668 669status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) { 670 for (size_t i = mBuffers[portIndex].size(); i-- > 0;) { 671 CHECK_EQ((status_t)OK, freeBuffer(portIndex, i)); 672 } 673 674 mDealer[portIndex].clear(); 675 676 return OK; 677} 678 679status_t ACodec::freeOutputBuffersNotOwnedByComponent() { 680 for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) { 681 BufferInfo *info = 682 &mBuffers[kPortIndexOutput].editItemAt(i); 683 684 if (info->mStatus != 685 BufferInfo::OWNED_BY_COMPONENT) { 686 // We shouldn't have sent out any buffers to the client at this 687 // point. 688 CHECK_NE((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM); 689 690 CHECK_EQ((status_t)OK, freeBuffer(kPortIndexOutput, i)); 691 } 692 } 693 694 return OK; 695} 696 697status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) { 698 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 699 700 CHECK(info->mStatus == BufferInfo::OWNED_BY_US 701 || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW); 702 703 if (portIndex == kPortIndexOutput && mNativeWindow != NULL 704 && info->mStatus == BufferInfo::OWNED_BY_US) { 705 CHECK_EQ((status_t)OK, cancelBufferToNativeWindow(info)); 706 } 707 708 CHECK_EQ(mOMX->freeBuffer( 709 mNode, portIndex, info->mBufferID), 710 (status_t)OK); 711 712 mBuffers[portIndex].removeAt(i); 713 714 return OK; 715} 716 717ACodec::BufferInfo *ACodec::findBufferByID( 718 uint32_t portIndex, IOMX::buffer_id bufferID, 719 ssize_t *index) { 720 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 721 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 722 723 if (info->mBufferID == bufferID) { 724 if (index != NULL) { 725 *index = i; 726 } 727 return info; 728 } 729 } 730 731 TRESPASS(); 732 733 return NULL; 734} 735 736status_t ACodec::setComponentRole( 737 bool isEncoder, const char *mime) { 738 struct MimeToRole { 739 const char *mime; 740 const char *decoderRole; 741 const char *encoderRole; 742 }; 743 744 static const MimeToRole kMimeToRole[] = { 745 { MEDIA_MIMETYPE_AUDIO_MPEG, 746 "audio_decoder.mp3", "audio_encoder.mp3" }, 747 { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I, 748 "audio_decoder.mp1", "audio_encoder.mp1" }, 749 { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II, 750 "audio_decoder.mp2", "audio_encoder.mp2" }, 751 { MEDIA_MIMETYPE_AUDIO_AMR_NB, 752 "audio_decoder.amrnb", "audio_encoder.amrnb" }, 753 { MEDIA_MIMETYPE_AUDIO_AMR_WB, 754 "audio_decoder.amrwb", "audio_encoder.amrwb" }, 755 { MEDIA_MIMETYPE_AUDIO_AAC, 756 "audio_decoder.aac", "audio_encoder.aac" }, 757 { MEDIA_MIMETYPE_AUDIO_VORBIS, 758 "audio_decoder.vorbis", "audio_encoder.vorbis" }, 759 { MEDIA_MIMETYPE_AUDIO_G711_MLAW, 760 "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" }, 761 { MEDIA_MIMETYPE_AUDIO_G711_ALAW, 762 "audio_decoder.g711alaw", "audio_encoder.g711alaw" }, 763 { MEDIA_MIMETYPE_VIDEO_AVC, 764 "video_decoder.avc", "video_encoder.avc" }, 765 { MEDIA_MIMETYPE_VIDEO_MPEG4, 766 "video_decoder.mpeg4", "video_encoder.mpeg4" }, 767 { MEDIA_MIMETYPE_VIDEO_H263, 768 "video_decoder.h263", "video_encoder.h263" }, 769 { MEDIA_MIMETYPE_VIDEO_VPX, 770 "video_decoder.vpx", "video_encoder.vpx" }, 771 { MEDIA_MIMETYPE_AUDIO_RAW, 772 "audio_decoder.raw", "audio_encoder.raw" }, 773 }; 774 775 static const size_t kNumMimeToRole = 776 sizeof(kMimeToRole) / sizeof(kMimeToRole[0]); 777 778 size_t i; 779 for (i = 0; i < kNumMimeToRole; ++i) { 780 if (!strcasecmp(mime, kMimeToRole[i].mime)) { 781 break; 782 } 783 } 784 785 if (i == kNumMimeToRole) { 786 return ERROR_UNSUPPORTED; 787 } 788 789 const char *role = 790 isEncoder ? kMimeToRole[i].encoderRole 791 : kMimeToRole[i].decoderRole; 792 793 if (role != NULL) { 794 OMX_PARAM_COMPONENTROLETYPE roleParams; 795 InitOMXParams(&roleParams); 796 797 strncpy((char *)roleParams.cRole, 798 role, OMX_MAX_STRINGNAME_SIZE - 1); 799 800 roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0'; 801 802 status_t err = mOMX->setParameter( 803 mNode, OMX_IndexParamStandardComponentRole, 804 &roleParams, sizeof(roleParams)); 805 806 if (err != OK) { 807 ALOGW("[%s] Failed to set standard component role '%s'.", 808 mComponentName.c_str(), role); 809 810 return err; 811 } 812 } 813 814 return OK; 815} 816 817status_t ACodec::configureCodec( 818 const char *mime, const sp<AMessage> &msg) { 819 int32_t encoder; 820 if (!msg->findInt32("encoder", &encoder)) { 821 encoder = false; 822 } 823 824 mIsEncoder = encoder; 825 826 status_t err = setComponentRole(encoder /* isEncoder */, mime); 827 828 if (err != OK) { 829 return err; 830 } 831 832 int32_t bitRate = 0; 833 if (encoder && !msg->findInt32("bitrate", &bitRate)) { 834 return INVALID_OPERATION; 835 } 836 837 if (!strncasecmp(mime, "video/", 6)) { 838 if (encoder) { 839 err = setupVideoEncoder(mime, msg); 840 } else { 841 int32_t width, height; 842 if (!msg->findInt32("width", &width) 843 || !msg->findInt32("height", &height)) { 844 err = INVALID_OPERATION; 845 } else { 846 err = setupVideoDecoder(mime, width, height); 847 } 848 } 849 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 850 int32_t numChannels, sampleRate; 851 if (!msg->findInt32("channel-count", &numChannels) 852 || !msg->findInt32("sample-rate", &sampleRate)) { 853 err = INVALID_OPERATION; 854 } else { 855 int32_t isADTS, aacProfile; 856 if (!msg->findInt32("is-adts", &isADTS)) { 857 isADTS = 0; 858 } 859 if (!msg->findInt32("aac-profile", &aacProfile)) { 860 aacProfile = OMX_AUDIO_AACObjectNull; 861 } 862 863 err = setupAACCodec( 864 encoder, numChannels, sampleRate, bitRate, aacProfile, isADTS != 0); 865 } 866 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) { 867 err = setupAMRCodec(encoder, false /* isWAMR */, bitRate); 868 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) { 869 err = setupAMRCodec(encoder, true /* isWAMR */, bitRate); 870 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW) 871 || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) { 872 // These are PCM-like formats with a fixed sample rate but 873 // a variable number of channels. 874 875 int32_t numChannels; 876 if (!msg->findInt32("channel-count", &numChannels)) { 877 err = INVALID_OPERATION; 878 } else { 879 err = setupG711Codec(encoder, numChannels); 880 } 881 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) { 882 int32_t numChannels, sampleRate; 883 if (encoder 884 || !msg->findInt32("channel-count", &numChannels) 885 || !msg->findInt32("sample-rate", &sampleRate)) { 886 err = INVALID_OPERATION; 887 } else { 888 err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels); 889 } 890 } 891 892 int32_t maxInputSize; 893 if (msg->findInt32("max-input-size", &maxInputSize)) { 894 err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize); 895 } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) { 896 err = setMinBufferSize(kPortIndexInput, 8192); // XXX 897 } 898 899 return err; 900} 901 902status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) { 903 OMX_PARAM_PORTDEFINITIONTYPE def; 904 InitOMXParams(&def); 905 def.nPortIndex = portIndex; 906 907 status_t err = mOMX->getParameter( 908 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 909 910 if (err != OK) { 911 return err; 912 } 913 914 if (def.nBufferSize >= size) { 915 return OK; 916 } 917 918 def.nBufferSize = size; 919 920 err = mOMX->setParameter( 921 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 922 923 if (err != OK) { 924 return err; 925 } 926 927 err = mOMX->getParameter( 928 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 929 930 if (err != OK) { 931 return err; 932 } 933 934 CHECK(def.nBufferSize >= size); 935 936 return OK; 937} 938 939status_t ACodec::selectAudioPortFormat( 940 OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) { 941 OMX_AUDIO_PARAM_PORTFORMATTYPE format; 942 InitOMXParams(&format); 943 944 format.nPortIndex = portIndex; 945 for (OMX_U32 index = 0;; ++index) { 946 format.nIndex = index; 947 948 status_t err = mOMX->getParameter( 949 mNode, OMX_IndexParamAudioPortFormat, 950 &format, sizeof(format)); 951 952 if (err != OK) { 953 return err; 954 } 955 956 if (format.eEncoding == desiredFormat) { 957 break; 958 } 959 } 960 961 return mOMX->setParameter( 962 mNode, OMX_IndexParamAudioPortFormat, &format, sizeof(format)); 963} 964 965status_t ACodec::setupAACCodec( 966 bool encoder, int32_t numChannels, int32_t sampleRate, 967 int32_t bitRate, int32_t aacProfile, bool isADTS) { 968 if (encoder && isADTS) { 969 return -EINVAL; 970 } 971 972 status_t err = setupRawAudioFormat( 973 encoder ? kPortIndexInput : kPortIndexOutput, 974 sampleRate, 975 numChannels); 976 977 if (err != OK) { 978 return err; 979 } 980 981 if (encoder) { 982 err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC); 983 984 if (err != OK) { 985 return err; 986 } 987 988 OMX_PARAM_PORTDEFINITIONTYPE def; 989 InitOMXParams(&def); 990 def.nPortIndex = kPortIndexOutput; 991 992 err = mOMX->getParameter( 993 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 994 995 if (err != OK) { 996 return err; 997 } 998 999 def.format.audio.bFlagErrorConcealment = OMX_TRUE; 1000 def.format.audio.eEncoding = OMX_AUDIO_CodingAAC; 1001 1002 err = mOMX->setParameter( 1003 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1004 1005 if (err != OK) { 1006 return err; 1007 } 1008 1009 OMX_AUDIO_PARAM_AACPROFILETYPE profile; 1010 InitOMXParams(&profile); 1011 profile.nPortIndex = kPortIndexOutput; 1012 1013 err = mOMX->getParameter( 1014 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 1015 1016 if (err != OK) { 1017 return err; 1018 } 1019 1020 profile.nChannels = numChannels; 1021 1022 profile.eChannelMode = 1023 (numChannels == 1) 1024 ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo; 1025 1026 profile.nSampleRate = sampleRate; 1027 profile.nBitRate = bitRate; 1028 profile.nAudioBandWidth = 0; 1029 profile.nFrameLength = 0; 1030 profile.nAACtools = OMX_AUDIO_AACToolAll; 1031 profile.nAACERtools = OMX_AUDIO_AACERNone; 1032 profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile; 1033 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF; 1034 1035 err = mOMX->setParameter( 1036 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 1037 1038 if (err != OK) { 1039 return err; 1040 } 1041 1042 return err; 1043 } 1044 1045 OMX_AUDIO_PARAM_AACPROFILETYPE profile; 1046 InitOMXParams(&profile); 1047 profile.nPortIndex = kPortIndexInput; 1048 1049 err = mOMX->getParameter( 1050 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 1051 1052 if (err != OK) { 1053 return err; 1054 } 1055 1056 profile.nChannels = numChannels; 1057 profile.nSampleRate = sampleRate; 1058 1059 profile.eAACStreamFormat = 1060 isADTS 1061 ? OMX_AUDIO_AACStreamFormatMP4ADTS 1062 : OMX_AUDIO_AACStreamFormatMP4FF; 1063 1064 return mOMX->setParameter( 1065 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 1066} 1067 1068static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate( 1069 bool isAMRWB, int32_t bps) { 1070 if (isAMRWB) { 1071 if (bps <= 6600) { 1072 return OMX_AUDIO_AMRBandModeWB0; 1073 } else if (bps <= 8850) { 1074 return OMX_AUDIO_AMRBandModeWB1; 1075 } else if (bps <= 12650) { 1076 return OMX_AUDIO_AMRBandModeWB2; 1077 } else if (bps <= 14250) { 1078 return OMX_AUDIO_AMRBandModeWB3; 1079 } else if (bps <= 15850) { 1080 return OMX_AUDIO_AMRBandModeWB4; 1081 } else if (bps <= 18250) { 1082 return OMX_AUDIO_AMRBandModeWB5; 1083 } else if (bps <= 19850) { 1084 return OMX_AUDIO_AMRBandModeWB6; 1085 } else if (bps <= 23050) { 1086 return OMX_AUDIO_AMRBandModeWB7; 1087 } 1088 1089 // 23850 bps 1090 return OMX_AUDIO_AMRBandModeWB8; 1091 } else { // AMRNB 1092 if (bps <= 4750) { 1093 return OMX_AUDIO_AMRBandModeNB0; 1094 } else if (bps <= 5150) { 1095 return OMX_AUDIO_AMRBandModeNB1; 1096 } else if (bps <= 5900) { 1097 return OMX_AUDIO_AMRBandModeNB2; 1098 } else if (bps <= 6700) { 1099 return OMX_AUDIO_AMRBandModeNB3; 1100 } else if (bps <= 7400) { 1101 return OMX_AUDIO_AMRBandModeNB4; 1102 } else if (bps <= 7950) { 1103 return OMX_AUDIO_AMRBandModeNB5; 1104 } else if (bps <= 10200) { 1105 return OMX_AUDIO_AMRBandModeNB6; 1106 } 1107 1108 // 12200 bps 1109 return OMX_AUDIO_AMRBandModeNB7; 1110 } 1111} 1112 1113status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) { 1114 OMX_AUDIO_PARAM_AMRTYPE def; 1115 InitOMXParams(&def); 1116 def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput; 1117 1118 status_t err = 1119 mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); 1120 1121 if (err != OK) { 1122 return err; 1123 } 1124 1125 def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF; 1126 def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate); 1127 1128 err = mOMX->setParameter( 1129 mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); 1130 1131 if (err != OK) { 1132 return err; 1133 } 1134 1135 return setupRawAudioFormat( 1136 encoder ? kPortIndexInput : kPortIndexOutput, 1137 isWAMR ? 16000 : 8000 /* sampleRate */, 1138 1 /* numChannels */); 1139} 1140 1141status_t ACodec::setupG711Codec(bool encoder, int32_t numChannels) { 1142 CHECK(!encoder); // XXX TODO 1143 1144 return setupRawAudioFormat( 1145 kPortIndexInput, 8000 /* sampleRate */, numChannels); 1146} 1147 1148status_t ACodec::setupRawAudioFormat( 1149 OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) { 1150 OMX_PARAM_PORTDEFINITIONTYPE def; 1151 InitOMXParams(&def); 1152 def.nPortIndex = portIndex; 1153 1154 status_t err = mOMX->getParameter( 1155 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1156 1157 if (err != OK) { 1158 return err; 1159 } 1160 1161 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; 1162 1163 err = mOMX->setParameter( 1164 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1165 1166 if (err != OK) { 1167 return err; 1168 } 1169 1170 OMX_AUDIO_PARAM_PCMMODETYPE pcmParams; 1171 InitOMXParams(&pcmParams); 1172 pcmParams.nPortIndex = portIndex; 1173 1174 err = mOMX->getParameter( 1175 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); 1176 1177 if (err != OK) { 1178 return err; 1179 } 1180 1181 pcmParams.nChannels = numChannels; 1182 pcmParams.eNumData = OMX_NumericalDataSigned; 1183 pcmParams.bInterleaved = OMX_TRUE; 1184 pcmParams.nBitPerSample = 16; 1185 pcmParams.nSamplingRate = sampleRate; 1186 pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear; 1187 1188 if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) { 1189 return OMX_ErrorNone; 1190 } 1191 1192 return mOMX->setParameter( 1193 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); 1194} 1195 1196status_t ACodec::setVideoPortFormatType( 1197 OMX_U32 portIndex, 1198 OMX_VIDEO_CODINGTYPE compressionFormat, 1199 OMX_COLOR_FORMATTYPE colorFormat) { 1200 OMX_VIDEO_PARAM_PORTFORMATTYPE format; 1201 InitOMXParams(&format); 1202 format.nPortIndex = portIndex; 1203 format.nIndex = 0; 1204 bool found = false; 1205 1206 OMX_U32 index = 0; 1207 for (;;) { 1208 format.nIndex = index; 1209 status_t err = mOMX->getParameter( 1210 mNode, OMX_IndexParamVideoPortFormat, 1211 &format, sizeof(format)); 1212 1213 if (err != OK) { 1214 return err; 1215 } 1216 1217 // The following assertion is violated by TI's video decoder. 1218 // CHECK_EQ(format.nIndex, index); 1219 1220 if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) { 1221 if (portIndex == kPortIndexInput 1222 && colorFormat == format.eColorFormat) { 1223 // eCompressionFormat does not seem right. 1224 found = true; 1225 break; 1226 } 1227 if (portIndex == kPortIndexOutput 1228 && compressionFormat == format.eCompressionFormat) { 1229 // eColorFormat does not seem right. 1230 found = true; 1231 break; 1232 } 1233 } 1234 1235 if (format.eCompressionFormat == compressionFormat 1236 && format.eColorFormat == colorFormat) { 1237 found = true; 1238 break; 1239 } 1240 1241 ++index; 1242 } 1243 1244 if (!found) { 1245 return UNKNOWN_ERROR; 1246 } 1247 1248 status_t err = mOMX->setParameter( 1249 mNode, OMX_IndexParamVideoPortFormat, 1250 &format, sizeof(format)); 1251 1252 return err; 1253} 1254 1255status_t ACodec::setSupportedOutputFormat() { 1256 OMX_VIDEO_PARAM_PORTFORMATTYPE format; 1257 InitOMXParams(&format); 1258 format.nPortIndex = kPortIndexOutput; 1259 format.nIndex = 0; 1260 1261 status_t err = mOMX->getParameter( 1262 mNode, OMX_IndexParamVideoPortFormat, 1263 &format, sizeof(format)); 1264 CHECK_EQ(err, (status_t)OK); 1265 CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused); 1266 1267 CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar 1268 || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar 1269 || format.eColorFormat == OMX_COLOR_FormatCbYCrY 1270 || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar 1271 || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar); 1272 1273 return mOMX->setParameter( 1274 mNode, OMX_IndexParamVideoPortFormat, 1275 &format, sizeof(format)); 1276} 1277 1278static status_t GetVideoCodingTypeFromMime( 1279 const char *mime, OMX_VIDEO_CODINGTYPE *codingType) { 1280 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 1281 *codingType = OMX_VIDEO_CodingAVC; 1282 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 1283 *codingType = OMX_VIDEO_CodingMPEG4; 1284 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 1285 *codingType = OMX_VIDEO_CodingH263; 1286 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG2, mime)) { 1287 *codingType = OMX_VIDEO_CodingMPEG2; 1288 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_VPX, mime)) { 1289 *codingType = OMX_VIDEO_CodingVPX; 1290 } else { 1291 *codingType = OMX_VIDEO_CodingUnused; 1292 return ERROR_UNSUPPORTED; 1293 } 1294 1295 return OK; 1296} 1297 1298status_t ACodec::setupVideoDecoder( 1299 const char *mime, int32_t width, int32_t height) { 1300 OMX_VIDEO_CODINGTYPE compressionFormat; 1301 status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat); 1302 1303 if (err != OK) { 1304 return err; 1305 } 1306 1307 err = setVideoPortFormatType( 1308 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused); 1309 1310 if (err != OK) { 1311 return err; 1312 } 1313 1314 err = setSupportedOutputFormat(); 1315 1316 if (err != OK) { 1317 return err; 1318 } 1319 1320 err = setVideoFormatOnPort( 1321 kPortIndexInput, width, height, compressionFormat); 1322 1323 if (err != OK) { 1324 return err; 1325 } 1326 1327 err = setVideoFormatOnPort( 1328 kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused); 1329 1330 if (err != OK) { 1331 return err; 1332 } 1333 1334 return OK; 1335} 1336 1337status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) { 1338 int32_t tmp; 1339 if (!msg->findInt32("color-format", &tmp)) { 1340 return INVALID_OPERATION; 1341 } 1342 1343 OMX_COLOR_FORMATTYPE colorFormat = 1344 static_cast<OMX_COLOR_FORMATTYPE>(tmp); 1345 1346 status_t err = setVideoPortFormatType( 1347 kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat); 1348 1349 if (err != OK) { 1350 ALOGE("[%s] does not support color format %d", 1351 mComponentName.c_str(), colorFormat); 1352 1353 return err; 1354 } 1355 1356 /* Input port configuration */ 1357 1358 OMX_PARAM_PORTDEFINITIONTYPE def; 1359 InitOMXParams(&def); 1360 1361 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 1362 1363 def.nPortIndex = kPortIndexInput; 1364 1365 err = mOMX->getParameter( 1366 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1367 1368 if (err != OK) { 1369 return err; 1370 } 1371 1372 int32_t width, height, bitrate; 1373 if (!msg->findInt32("width", &width) 1374 || !msg->findInt32("height", &height) 1375 || !msg->findInt32("bitrate", &bitrate)) { 1376 return INVALID_OPERATION; 1377 } 1378 1379 video_def->nFrameWidth = width; 1380 video_def->nFrameHeight = height; 1381 1382 int32_t stride; 1383 if (!msg->findInt32("stride", &stride)) { 1384 stride = width; 1385 } 1386 1387 video_def->nStride = stride; 1388 1389 int32_t sliceHeight; 1390 if (!msg->findInt32("slice-height", &sliceHeight)) { 1391 sliceHeight = height; 1392 } 1393 1394 video_def->nSliceHeight = sliceHeight; 1395 1396 def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2; 1397 1398 float frameRate; 1399 if (!msg->findFloat("frame-rate", &frameRate)) { 1400 int32_t tmp; 1401 if (!msg->findInt32("frame-rate", &tmp)) { 1402 return INVALID_OPERATION; 1403 } 1404 frameRate = (float)tmp; 1405 } 1406 1407 video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f); 1408 video_def->eCompressionFormat = OMX_VIDEO_CodingUnused; 1409 video_def->eColorFormat = colorFormat; 1410 1411 err = mOMX->setParameter( 1412 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1413 1414 if (err != OK) { 1415 ALOGE("[%s] failed to set input port definition parameters.", 1416 mComponentName.c_str()); 1417 1418 return err; 1419 } 1420 1421 /* Output port configuration */ 1422 1423 OMX_VIDEO_CODINGTYPE compressionFormat; 1424 err = GetVideoCodingTypeFromMime(mime, &compressionFormat); 1425 1426 if (err != OK) { 1427 return err; 1428 } 1429 1430 err = setVideoPortFormatType( 1431 kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused); 1432 1433 if (err != OK) { 1434 ALOGE("[%s] does not support compression format %d", 1435 mComponentName.c_str(), compressionFormat); 1436 1437 return err; 1438 } 1439 1440 def.nPortIndex = kPortIndexOutput; 1441 1442 err = mOMX->getParameter( 1443 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1444 1445 if (err != OK) { 1446 return err; 1447 } 1448 1449 video_def->nFrameWidth = width; 1450 video_def->nFrameHeight = height; 1451 video_def->xFramerate = 0; 1452 video_def->nBitrate = bitrate; 1453 video_def->eCompressionFormat = compressionFormat; 1454 video_def->eColorFormat = OMX_COLOR_FormatUnused; 1455 1456 err = mOMX->setParameter( 1457 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1458 1459 if (err != OK) { 1460 ALOGE("[%s] failed to set output port definition parameters.", 1461 mComponentName.c_str()); 1462 1463 return err; 1464 } 1465 1466 switch (compressionFormat) { 1467 case OMX_VIDEO_CodingMPEG4: 1468 err = setupMPEG4EncoderParameters(msg); 1469 break; 1470 1471 case OMX_VIDEO_CodingH263: 1472 err = setupH263EncoderParameters(msg); 1473 break; 1474 1475 case OMX_VIDEO_CodingAVC: 1476 err = setupAVCEncoderParameters(msg); 1477 break; 1478 1479 default: 1480 break; 1481 } 1482 1483 ALOGI("setupVideoEncoder succeeded"); 1484 1485 return err; 1486} 1487 1488static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) { 1489 if (iFramesInterval < 0) { 1490 return 0xFFFFFFFF; 1491 } else if (iFramesInterval == 0) { 1492 return 0; 1493 } 1494 OMX_U32 ret = frameRate * iFramesInterval; 1495 CHECK(ret > 1); 1496 return ret; 1497} 1498 1499status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) { 1500 int32_t bitrate, iFrameInterval; 1501 if (!msg->findInt32("bitrate", &bitrate) 1502 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 1503 return INVALID_OPERATION; 1504 } 1505 1506 float frameRate; 1507 if (!msg->findFloat("frame-rate", &frameRate)) { 1508 int32_t tmp; 1509 if (!msg->findInt32("frame-rate", &tmp)) { 1510 return INVALID_OPERATION; 1511 } 1512 frameRate = (float)tmp; 1513 } 1514 1515 OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type; 1516 InitOMXParams(&mpeg4type); 1517 mpeg4type.nPortIndex = kPortIndexOutput; 1518 1519 status_t err = mOMX->getParameter( 1520 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); 1521 1522 if (err != OK) { 1523 return err; 1524 } 1525 1526 mpeg4type.nSliceHeaderSpacing = 0; 1527 mpeg4type.bSVH = OMX_FALSE; 1528 mpeg4type.bGov = OMX_FALSE; 1529 1530 mpeg4type.nAllowedPictureTypes = 1531 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 1532 1533 mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 1534 if (mpeg4type.nPFrames == 0) { 1535 mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 1536 } 1537 mpeg4type.nBFrames = 0; 1538 mpeg4type.nIDCVLCThreshold = 0; 1539 mpeg4type.bACPred = OMX_TRUE; 1540 mpeg4type.nMaxPacketSize = 256; 1541 mpeg4type.nTimeIncRes = 1000; 1542 mpeg4type.nHeaderExtension = 0; 1543 mpeg4type.bReversibleVLC = OMX_FALSE; 1544 1545 int32_t profile; 1546 if (msg->findInt32("profile", &profile)) { 1547 int32_t level; 1548 if (!msg->findInt32("level", &level)) { 1549 return INVALID_OPERATION; 1550 } 1551 1552 err = verifySupportForProfileAndLevel(profile, level); 1553 1554 if (err != OK) { 1555 return err; 1556 } 1557 1558 mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile); 1559 mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level); 1560 } 1561 1562 err = mOMX->setParameter( 1563 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); 1564 1565 if (err != OK) { 1566 return err; 1567 } 1568 1569 err = configureBitrate(bitrate); 1570 1571 if (err != OK) { 1572 return err; 1573 } 1574 1575 return setupErrorCorrectionParameters(); 1576} 1577 1578status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) { 1579 int32_t bitrate, iFrameInterval; 1580 if (!msg->findInt32("bitrate", &bitrate) 1581 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 1582 return INVALID_OPERATION; 1583 } 1584 1585 float frameRate; 1586 if (!msg->findFloat("frame-rate", &frameRate)) { 1587 int32_t tmp; 1588 if (!msg->findInt32("frame-rate", &tmp)) { 1589 return INVALID_OPERATION; 1590 } 1591 frameRate = (float)tmp; 1592 } 1593 1594 OMX_VIDEO_PARAM_H263TYPE h263type; 1595 InitOMXParams(&h263type); 1596 h263type.nPortIndex = kPortIndexOutput; 1597 1598 status_t err = mOMX->getParameter( 1599 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); 1600 1601 if (err != OK) { 1602 return err; 1603 } 1604 1605 h263type.nAllowedPictureTypes = 1606 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 1607 1608 h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 1609 if (h263type.nPFrames == 0) { 1610 h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 1611 } 1612 h263type.nBFrames = 0; 1613 1614 int32_t profile; 1615 if (msg->findInt32("profile", &profile)) { 1616 int32_t level; 1617 if (!msg->findInt32("level", &level)) { 1618 return INVALID_OPERATION; 1619 } 1620 1621 err = verifySupportForProfileAndLevel(profile, level); 1622 1623 if (err != OK) { 1624 return err; 1625 } 1626 1627 h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile); 1628 h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level); 1629 } 1630 1631 h263type.bPLUSPTYPEAllowed = OMX_FALSE; 1632 h263type.bForceRoundingTypeToZero = OMX_FALSE; 1633 h263type.nPictureHeaderRepetition = 0; 1634 h263type.nGOBHeaderInterval = 0; 1635 1636 err = mOMX->setParameter( 1637 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); 1638 1639 if (err != OK) { 1640 return err; 1641 } 1642 1643 err = configureBitrate(bitrate); 1644 1645 if (err != OK) { 1646 return err; 1647 } 1648 1649 return setupErrorCorrectionParameters(); 1650} 1651 1652status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) { 1653 int32_t bitrate, iFrameInterval; 1654 if (!msg->findInt32("bitrate", &bitrate) 1655 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 1656 return INVALID_OPERATION; 1657 } 1658 1659 float frameRate; 1660 if (!msg->findFloat("frame-rate", &frameRate)) { 1661 int32_t tmp; 1662 if (!msg->findInt32("frame-rate", &tmp)) { 1663 return INVALID_OPERATION; 1664 } 1665 frameRate = (float)tmp; 1666 } 1667 1668 OMX_VIDEO_PARAM_AVCTYPE h264type; 1669 InitOMXParams(&h264type); 1670 h264type.nPortIndex = kPortIndexOutput; 1671 1672 status_t err = mOMX->getParameter( 1673 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 1674 1675 if (err != OK) { 1676 return err; 1677 } 1678 1679 h264type.nAllowedPictureTypes = 1680 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 1681 1682 int32_t profile; 1683 if (msg->findInt32("profile", &profile)) { 1684 int32_t level; 1685 if (!msg->findInt32("level", &level)) { 1686 return INVALID_OPERATION; 1687 } 1688 1689 err = verifySupportForProfileAndLevel(profile, level); 1690 1691 if (err != OK) { 1692 return err; 1693 } 1694 1695 h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile); 1696 h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level); 1697 } 1698 1699 // XXX 1700 if (!strncmp(mComponentName.c_str(), "OMX.TI.DUCATI1", 14)) { 1701 h264type.eProfile = OMX_VIDEO_AVCProfileBaseline; 1702 } 1703 1704 if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) { 1705 h264type.nSliceHeaderSpacing = 0; 1706 h264type.bUseHadamard = OMX_TRUE; 1707 h264type.nRefFrames = 1; 1708 h264type.nBFrames = 0; 1709 h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 1710 if (h264type.nPFrames == 0) { 1711 h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 1712 } 1713 h264type.nRefIdx10ActiveMinus1 = 0; 1714 h264type.nRefIdx11ActiveMinus1 = 0; 1715 h264type.bEntropyCodingCABAC = OMX_FALSE; 1716 h264type.bWeightedPPrediction = OMX_FALSE; 1717 h264type.bconstIpred = OMX_FALSE; 1718 h264type.bDirect8x8Inference = OMX_FALSE; 1719 h264type.bDirectSpatialTemporal = OMX_FALSE; 1720 h264type.nCabacInitIdc = 0; 1721 } 1722 1723 if (h264type.nBFrames != 0) { 1724 h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB; 1725 } 1726 1727 h264type.bEnableUEP = OMX_FALSE; 1728 h264type.bEnableFMO = OMX_FALSE; 1729 h264type.bEnableASO = OMX_FALSE; 1730 h264type.bEnableRS = OMX_FALSE; 1731 h264type.bFrameMBsOnly = OMX_TRUE; 1732 h264type.bMBAFF = OMX_FALSE; 1733 h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; 1734 1735 if (!strcasecmp("OMX.Nvidia.h264.encoder", mComponentName.c_str())) { 1736 h264type.eLevel = OMX_VIDEO_AVCLevelMax; 1737 } 1738 1739 err = mOMX->setParameter( 1740 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 1741 1742 if (err != OK) { 1743 return err; 1744 } 1745 1746 return configureBitrate(bitrate); 1747} 1748 1749status_t ACodec::verifySupportForProfileAndLevel( 1750 int32_t profile, int32_t level) { 1751 OMX_VIDEO_PARAM_PROFILELEVELTYPE params; 1752 InitOMXParams(¶ms); 1753 params.nPortIndex = kPortIndexOutput; 1754 1755 for (params.nProfileIndex = 0;; ++params.nProfileIndex) { 1756 status_t err = mOMX->getParameter( 1757 mNode, 1758 OMX_IndexParamVideoProfileLevelQuerySupported, 1759 ¶ms, 1760 sizeof(params)); 1761 1762 if (err != OK) { 1763 return err; 1764 } 1765 1766 int32_t supportedProfile = static_cast<int32_t>(params.eProfile); 1767 int32_t supportedLevel = static_cast<int32_t>(params.eLevel); 1768 1769 if (profile == supportedProfile && level <= supportedLevel) { 1770 return OK; 1771 } 1772 } 1773} 1774 1775status_t ACodec::configureBitrate(int32_t bitrate) { 1776 OMX_VIDEO_PARAM_BITRATETYPE bitrateType; 1777 InitOMXParams(&bitrateType); 1778 bitrateType.nPortIndex = kPortIndexOutput; 1779 1780 status_t err = mOMX->getParameter( 1781 mNode, OMX_IndexParamVideoBitrate, 1782 &bitrateType, sizeof(bitrateType)); 1783 1784 if (err != OK) { 1785 return err; 1786 } 1787 1788 bitrateType.eControlRate = OMX_Video_ControlRateVariable; 1789 bitrateType.nTargetBitrate = bitrate; 1790 1791 return mOMX->setParameter( 1792 mNode, OMX_IndexParamVideoBitrate, 1793 &bitrateType, sizeof(bitrateType)); 1794} 1795 1796status_t ACodec::setupErrorCorrectionParameters() { 1797 OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType; 1798 InitOMXParams(&errorCorrectionType); 1799 errorCorrectionType.nPortIndex = kPortIndexOutput; 1800 1801 status_t err = mOMX->getParameter( 1802 mNode, OMX_IndexParamVideoErrorCorrection, 1803 &errorCorrectionType, sizeof(errorCorrectionType)); 1804 1805 if (err != OK) { 1806 return OK; // Optional feature. Ignore this failure 1807 } 1808 1809 errorCorrectionType.bEnableHEC = OMX_FALSE; 1810 errorCorrectionType.bEnableResync = OMX_TRUE; 1811 errorCorrectionType.nResynchMarkerSpacing = 256; 1812 errorCorrectionType.bEnableDataPartitioning = OMX_FALSE; 1813 errorCorrectionType.bEnableRVLC = OMX_FALSE; 1814 1815 return mOMX->setParameter( 1816 mNode, OMX_IndexParamVideoErrorCorrection, 1817 &errorCorrectionType, sizeof(errorCorrectionType)); 1818} 1819 1820status_t ACodec::setVideoFormatOnPort( 1821 OMX_U32 portIndex, 1822 int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) { 1823 OMX_PARAM_PORTDEFINITIONTYPE def; 1824 InitOMXParams(&def); 1825 def.nPortIndex = portIndex; 1826 1827 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 1828 1829 status_t err = mOMX->getParameter( 1830 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1831 1832 CHECK_EQ(err, (status_t)OK); 1833 1834 if (portIndex == kPortIndexInput) { 1835 // XXX Need a (much) better heuristic to compute input buffer sizes. 1836 const size_t X = 64 * 1024; 1837 if (def.nBufferSize < X) { 1838 def.nBufferSize = X; 1839 } 1840 } 1841 1842 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo); 1843 1844 video_def->nFrameWidth = width; 1845 video_def->nFrameHeight = height; 1846 1847 if (portIndex == kPortIndexInput) { 1848 video_def->eCompressionFormat = compressionFormat; 1849 video_def->eColorFormat = OMX_COLOR_FormatUnused; 1850 } 1851 1852 err = mOMX->setParameter( 1853 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1854 1855 return err; 1856} 1857 1858status_t ACodec::initNativeWindow() { 1859 if (mNativeWindow != NULL) { 1860 return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE); 1861 } 1862 1863 mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE); 1864 return OK; 1865} 1866 1867size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const { 1868 size_t n = 0; 1869 1870 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 1871 const BufferInfo &info = mBuffers[portIndex].itemAt(i); 1872 1873 if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) { 1874 ++n; 1875 } 1876 } 1877 1878 return n; 1879} 1880 1881bool ACodec::allYourBuffersAreBelongToUs( 1882 OMX_U32 portIndex) { 1883 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 1884 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 1885 1886 if (info->mStatus != BufferInfo::OWNED_BY_US 1887 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) { 1888 ALOGV("[%s] Buffer %p on port %ld still has status %d", 1889 mComponentName.c_str(), 1890 info->mBufferID, portIndex, info->mStatus); 1891 return false; 1892 } 1893 } 1894 1895 return true; 1896} 1897 1898bool ACodec::allYourBuffersAreBelongToUs() { 1899 return allYourBuffersAreBelongToUs(kPortIndexInput) 1900 && allYourBuffersAreBelongToUs(kPortIndexOutput); 1901} 1902 1903void ACodec::deferMessage(const sp<AMessage> &msg) { 1904 bool wasEmptyBefore = mDeferredQueue.empty(); 1905 mDeferredQueue.push_back(msg); 1906} 1907 1908void ACodec::processDeferredMessages() { 1909 List<sp<AMessage> > queue = mDeferredQueue; 1910 mDeferredQueue.clear(); 1911 1912 List<sp<AMessage> >::iterator it = queue.begin(); 1913 while (it != queue.end()) { 1914 onMessageReceived(*it++); 1915 } 1916} 1917 1918void ACodec::sendFormatChange() { 1919 sp<AMessage> notify = mNotify->dup(); 1920 notify->setInt32("what", kWhatOutputFormatChanged); 1921 1922 OMX_PARAM_PORTDEFINITIONTYPE def; 1923 InitOMXParams(&def); 1924 def.nPortIndex = kPortIndexOutput; 1925 1926 CHECK_EQ(mOMX->getParameter( 1927 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)), 1928 (status_t)OK); 1929 1930 CHECK_EQ((int)def.eDir, (int)OMX_DirOutput); 1931 1932 switch (def.eDomain) { 1933 case OMX_PortDomainVideo: 1934 { 1935 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video; 1936 1937 notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW); 1938 notify->setInt32("width", videoDef->nFrameWidth); 1939 notify->setInt32("height", videoDef->nFrameHeight); 1940 notify->setInt32("stride", videoDef->nStride); 1941 notify->setInt32("slice-height", videoDef->nSliceHeight); 1942 notify->setInt32("color-format", videoDef->eColorFormat); 1943 1944 OMX_CONFIG_RECTTYPE rect; 1945 InitOMXParams(&rect); 1946 rect.nPortIndex = kPortIndexOutput; 1947 1948 if (mOMX->getConfig( 1949 mNode, OMX_IndexConfigCommonOutputCrop, 1950 &rect, sizeof(rect)) != OK) { 1951 rect.nLeft = 0; 1952 rect.nTop = 0; 1953 rect.nWidth = videoDef->nFrameWidth; 1954 rect.nHeight = videoDef->nFrameHeight; 1955 } 1956 1957 CHECK_GE(rect.nLeft, 0); 1958 CHECK_GE(rect.nTop, 0); 1959 CHECK_GE(rect.nWidth, 0u); 1960 CHECK_GE(rect.nHeight, 0u); 1961 CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth); 1962 CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight); 1963 1964 notify->setRect( 1965 "crop", 1966 rect.nLeft, 1967 rect.nTop, 1968 rect.nLeft + rect.nWidth - 1, 1969 rect.nTop + rect.nHeight - 1); 1970 1971 if (mNativeWindow != NULL) { 1972 android_native_rect_t crop; 1973 crop.left = rect.nLeft; 1974 crop.top = rect.nTop; 1975 crop.right = rect.nLeft + rect.nWidth; 1976 crop.bottom = rect.nTop + rect.nHeight; 1977 1978 CHECK_EQ(0, native_window_set_crop( 1979 mNativeWindow.get(), &crop)); 1980 } 1981 break; 1982 } 1983 1984 case OMX_PortDomainAudio: 1985 { 1986 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio; 1987 CHECK_EQ((int)audioDef->eEncoding, (int)OMX_AUDIO_CodingPCM); 1988 1989 OMX_AUDIO_PARAM_PCMMODETYPE params; 1990 InitOMXParams(¶ms); 1991 params.nPortIndex = kPortIndexOutput; 1992 1993 CHECK_EQ(mOMX->getParameter( 1994 mNode, OMX_IndexParamAudioPcm, 1995 ¶ms, sizeof(params)), 1996 (status_t)OK); 1997 1998 CHECK(params.nChannels == 1 || params.bInterleaved); 1999 CHECK_EQ(params.nBitPerSample, 16u); 2000 CHECK_EQ((int)params.eNumData, (int)OMX_NumericalDataSigned); 2001 CHECK_EQ((int)params.ePCMMode, (int)OMX_AUDIO_PCMModeLinear); 2002 2003 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW); 2004 notify->setInt32("channel-count", params.nChannels); 2005 notify->setInt32("sample-rate", params.nSamplingRate); 2006 break; 2007 } 2008 2009 default: 2010 TRESPASS(); 2011 } 2012 2013 notify->post(); 2014 2015 mSentFormat = true; 2016} 2017 2018void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) { 2019 sp<AMessage> notify = mNotify->dup(); 2020 notify->setInt32("what", ACodec::kWhatError); 2021 notify->setInt32("omx-error", error); 2022 notify->setInt32("err", internalError); 2023 notify->post(); 2024} 2025 2026//////////////////////////////////////////////////////////////////////////////// 2027 2028ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState) 2029 : AState(parentState), 2030 mCodec(codec) { 2031} 2032 2033ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(OMX_U32 portIndex) { 2034 return KEEP_BUFFERS; 2035} 2036 2037bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) { 2038 switch (msg->what()) { 2039 case kWhatInputBufferFilled: 2040 { 2041 onInputBufferFilled(msg); 2042 break; 2043 } 2044 2045 case kWhatOutputBufferDrained: 2046 { 2047 onOutputBufferDrained(msg); 2048 break; 2049 } 2050 2051 case ACodec::kWhatOMXMessage: 2052 { 2053 return onOMXMessage(msg); 2054 } 2055 2056 default: 2057 return false; 2058 } 2059 2060 return true; 2061} 2062 2063bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) { 2064 int32_t type; 2065 CHECK(msg->findInt32("type", &type)); 2066 2067 IOMX::node_id nodeID; 2068 CHECK(msg->findPointer("node", &nodeID)); 2069 CHECK_EQ(nodeID, mCodec->mNode); 2070 2071 switch (type) { 2072 case omx_message::EVENT: 2073 { 2074 int32_t event, data1, data2; 2075 CHECK(msg->findInt32("event", &event)); 2076 CHECK(msg->findInt32("data1", &data1)); 2077 CHECK(msg->findInt32("data2", &data2)); 2078 2079 if (event == OMX_EventCmdComplete 2080 && data1 == OMX_CommandFlush 2081 && data2 == (int32_t)OMX_ALL) { 2082 // Use of this notification is not consistent across 2083 // implementations. We'll drop this notification and rely 2084 // on flush-complete notifications on the individual port 2085 // indices instead. 2086 2087 return true; 2088 } 2089 2090 return onOMXEvent( 2091 static_cast<OMX_EVENTTYPE>(event), 2092 static_cast<OMX_U32>(data1), 2093 static_cast<OMX_U32>(data2)); 2094 } 2095 2096 case omx_message::EMPTY_BUFFER_DONE: 2097 { 2098 IOMX::buffer_id bufferID; 2099 CHECK(msg->findPointer("buffer", &bufferID)); 2100 2101 return onOMXEmptyBufferDone(bufferID); 2102 } 2103 2104 case omx_message::FILL_BUFFER_DONE: 2105 { 2106 IOMX::buffer_id bufferID; 2107 CHECK(msg->findPointer("buffer", &bufferID)); 2108 2109 int32_t rangeOffset, rangeLength, flags; 2110 int64_t timeUs; 2111 void *platformPrivate; 2112 void *dataPtr; 2113 2114 CHECK(msg->findInt32("range_offset", &rangeOffset)); 2115 CHECK(msg->findInt32("range_length", &rangeLength)); 2116 CHECK(msg->findInt32("flags", &flags)); 2117 CHECK(msg->findInt64("timestamp", &timeUs)); 2118 CHECK(msg->findPointer("platform_private", &platformPrivate)); 2119 CHECK(msg->findPointer("data_ptr", &dataPtr)); 2120 2121 return onOMXFillBufferDone( 2122 bufferID, 2123 (size_t)rangeOffset, (size_t)rangeLength, 2124 (OMX_U32)flags, 2125 timeUs, 2126 platformPrivate, 2127 dataPtr); 2128 } 2129 2130 default: 2131 TRESPASS(); 2132 break; 2133 } 2134} 2135 2136bool ACodec::BaseState::onOMXEvent( 2137 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 2138 if (event != OMX_EventError) { 2139 ALOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)", 2140 mCodec->mComponentName.c_str(), event, data1, data2); 2141 2142 return false; 2143 } 2144 2145 ALOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1); 2146 2147 mCodec->signalError((OMX_ERRORTYPE)data1); 2148 2149 return true; 2150} 2151 2152bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) { 2153 ALOGV("[%s] onOMXEmptyBufferDone %p", 2154 mCodec->mComponentName.c_str(), bufferID); 2155 2156 BufferInfo *info = 2157 mCodec->findBufferByID(kPortIndexInput, bufferID); 2158 2159 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); 2160 info->mStatus = BufferInfo::OWNED_BY_US; 2161 2162 PortMode mode = getPortMode(kPortIndexInput); 2163 2164 switch (mode) { 2165 case KEEP_BUFFERS: 2166 break; 2167 2168 case RESUBMIT_BUFFERS: 2169 postFillThisBuffer(info); 2170 break; 2171 2172 default: 2173 { 2174 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 2175 TRESPASS(); // Not currently used 2176 break; 2177 } 2178 } 2179 2180 return true; 2181} 2182 2183void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) { 2184 if (mCodec->mPortEOS[kPortIndexInput]) { 2185 return; 2186 } 2187 2188 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 2189 2190 sp<AMessage> notify = mCodec->mNotify->dup(); 2191 notify->setInt32("what", ACodec::kWhatFillThisBuffer); 2192 notify->setPointer("buffer-id", info->mBufferID); 2193 2194 info->mData->meta()->clear(); 2195 notify->setBuffer("buffer", info->mData); 2196 2197 sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id()); 2198 reply->setPointer("buffer-id", info->mBufferID); 2199 2200 notify->setMessage("reply", reply); 2201 2202 notify->post(); 2203 2204 info->mStatus = BufferInfo::OWNED_BY_UPSTREAM; 2205} 2206 2207void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { 2208 IOMX::buffer_id bufferID; 2209 CHECK(msg->findPointer("buffer-id", &bufferID)); 2210 2211 sp<ABuffer> buffer; 2212 int32_t err = OK; 2213 bool eos = false; 2214 2215 if (!msg->findBuffer("buffer", &buffer)) { 2216 CHECK(msg->findInt32("err", &err)); 2217 2218 ALOGV("[%s] saw error %d instead of an input buffer", 2219 mCodec->mComponentName.c_str(), err); 2220 2221 buffer.clear(); 2222 2223 eos = true; 2224 } 2225 2226 int32_t tmp; 2227 if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) { 2228 eos = true; 2229 err = ERROR_END_OF_STREAM; 2230 } 2231 2232 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID); 2233 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM); 2234 2235 info->mStatus = BufferInfo::OWNED_BY_US; 2236 2237 PortMode mode = getPortMode(kPortIndexInput); 2238 2239 switch (mode) { 2240 case KEEP_BUFFERS: 2241 { 2242 if (eos) { 2243 if (!mCodec->mPortEOS[kPortIndexInput]) { 2244 mCodec->mPortEOS[kPortIndexInput] = true; 2245 mCodec->mInputEOSResult = err; 2246 } 2247 } 2248 break; 2249 } 2250 2251 case RESUBMIT_BUFFERS: 2252 { 2253 if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) { 2254 int64_t timeUs; 2255 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 2256 2257 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME; 2258 2259 int32_t isCSD; 2260 if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) { 2261 flags |= OMX_BUFFERFLAG_CODECCONFIG; 2262 } 2263 2264 if (eos) { 2265 flags |= OMX_BUFFERFLAG_EOS; 2266 } 2267 2268 if (buffer != info->mData) { 2269 if (0 && !(flags & OMX_BUFFERFLAG_CODECCONFIG)) { 2270 ALOGV("[%s] Needs to copy input data.", 2271 mCodec->mComponentName.c_str()); 2272 } 2273 2274 CHECK_LE(buffer->size(), info->mData->capacity()); 2275 memcpy(info->mData->data(), buffer->data(), buffer->size()); 2276 } 2277 2278 if (flags & OMX_BUFFERFLAG_CODECCONFIG) { 2279 ALOGV("[%s] calling emptyBuffer %p w/ codec specific data", 2280 mCodec->mComponentName.c_str(), bufferID); 2281 } else if (flags & OMX_BUFFERFLAG_EOS) { 2282 ALOGV("[%s] calling emptyBuffer %p w/ EOS", 2283 mCodec->mComponentName.c_str(), bufferID); 2284 } else { 2285 ALOGV("[%s] calling emptyBuffer %p w/ time %lld us", 2286 mCodec->mComponentName.c_str(), bufferID, timeUs); 2287 } 2288 2289 CHECK_EQ(mCodec->mOMX->emptyBuffer( 2290 mCodec->mNode, 2291 bufferID, 2292 0, 2293 buffer->size(), 2294 flags, 2295 timeUs), 2296 (status_t)OK); 2297 2298 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 2299 2300 if (!eos) { 2301 getMoreInputDataIfPossible(); 2302 } else { 2303 ALOGV("[%s] Signalled EOS on the input port", 2304 mCodec->mComponentName.c_str()); 2305 2306 mCodec->mPortEOS[kPortIndexInput] = true; 2307 mCodec->mInputEOSResult = err; 2308 } 2309 } else if (!mCodec->mPortEOS[kPortIndexInput]) { 2310 if (err != ERROR_END_OF_STREAM) { 2311 ALOGV("[%s] Signalling EOS on the input port " 2312 "due to error %d", 2313 mCodec->mComponentName.c_str(), err); 2314 } else { 2315 ALOGV("[%s] Signalling EOS on the input port", 2316 mCodec->mComponentName.c_str()); 2317 } 2318 2319 ALOGV("[%s] calling emptyBuffer %p signalling EOS", 2320 mCodec->mComponentName.c_str(), bufferID); 2321 2322 CHECK_EQ(mCodec->mOMX->emptyBuffer( 2323 mCodec->mNode, 2324 bufferID, 2325 0, 2326 0, 2327 OMX_BUFFERFLAG_EOS, 2328 0), 2329 (status_t)OK); 2330 2331 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 2332 2333 mCodec->mPortEOS[kPortIndexInput] = true; 2334 mCodec->mInputEOSResult = err; 2335 } 2336 break; 2337 2338 default: 2339 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 2340 break; 2341 } 2342 } 2343} 2344 2345void ACodec::BaseState::getMoreInputDataIfPossible() { 2346 if (mCodec->mPortEOS[kPortIndexInput]) { 2347 return; 2348 } 2349 2350 BufferInfo *eligible = NULL; 2351 2352 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 2353 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 2354 2355#if 0 2356 if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) { 2357 // There's already a "read" pending. 2358 return; 2359 } 2360#endif 2361 2362 if (info->mStatus == BufferInfo::OWNED_BY_US) { 2363 eligible = info; 2364 } 2365 } 2366 2367 if (eligible == NULL) { 2368 return; 2369 } 2370 2371 postFillThisBuffer(eligible); 2372} 2373 2374bool ACodec::BaseState::onOMXFillBufferDone( 2375 IOMX::buffer_id bufferID, 2376 size_t rangeOffset, size_t rangeLength, 2377 OMX_U32 flags, 2378 int64_t timeUs, 2379 void *platformPrivate, 2380 void *dataPtr) { 2381 ALOGV("[%s] onOMXFillBufferDone %p time %lld us, flags = 0x%08lx", 2382 mCodec->mComponentName.c_str(), bufferID, timeUs, flags); 2383 2384 ssize_t index; 2385 BufferInfo *info = 2386 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 2387 2388 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); 2389 2390 info->mStatus = BufferInfo::OWNED_BY_US; 2391 2392 PortMode mode = getPortMode(kPortIndexOutput); 2393 2394 switch (mode) { 2395 case KEEP_BUFFERS: 2396 break; 2397 2398 case RESUBMIT_BUFFERS: 2399 { 2400 if (rangeLength == 0 && !(flags & OMX_BUFFERFLAG_EOS)) { 2401 ALOGV("[%s] calling fillBuffer %p", 2402 mCodec->mComponentName.c_str(), info->mBufferID); 2403 2404 CHECK_EQ(mCodec->mOMX->fillBuffer( 2405 mCodec->mNode, info->mBufferID), 2406 (status_t)OK); 2407 2408 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 2409 break; 2410 } 2411 2412 if (!mCodec->mIsEncoder && !mCodec->mSentFormat) { 2413 mCodec->sendFormatChange(); 2414 } 2415 2416 if (mCodec->mNativeWindow == NULL) { 2417 info->mData->setRange(rangeOffset, rangeLength); 2418 } 2419 2420 info->mData->meta()->setInt64("timeUs", timeUs); 2421 2422 sp<AMessage> notify = mCodec->mNotify->dup(); 2423 notify->setInt32("what", ACodec::kWhatDrainThisBuffer); 2424 notify->setPointer("buffer-id", info->mBufferID); 2425 notify->setBuffer("buffer", info->mData); 2426 notify->setInt32("flags", flags); 2427 2428 sp<AMessage> reply = 2429 new AMessage(kWhatOutputBufferDrained, mCodec->id()); 2430 2431 reply->setPointer("buffer-id", info->mBufferID); 2432 2433 notify->setMessage("reply", reply); 2434 2435 notify->post(); 2436 2437 info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM; 2438 2439 if (flags & OMX_BUFFERFLAG_EOS) { 2440 ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str()); 2441 2442 sp<AMessage> notify = mCodec->mNotify->dup(); 2443 notify->setInt32("what", ACodec::kWhatEOS); 2444 notify->setInt32("err", mCodec->mInputEOSResult); 2445 notify->post(); 2446 2447 mCodec->mPortEOS[kPortIndexOutput] = true; 2448 } 2449 break; 2450 } 2451 2452 default: 2453 { 2454 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 2455 2456 CHECK_EQ((status_t)OK, 2457 mCodec->freeBuffer(kPortIndexOutput, index)); 2458 break; 2459 } 2460 } 2461 2462 return true; 2463} 2464 2465void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { 2466 IOMX::buffer_id bufferID; 2467 CHECK(msg->findPointer("buffer-id", &bufferID)); 2468 2469 ssize_t index; 2470 BufferInfo *info = 2471 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 2472 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM); 2473 2474 int32_t render; 2475 if (mCodec->mNativeWindow != NULL 2476 && msg->findInt32("render", &render) && render != 0) { 2477 // The client wants this buffer to be rendered. 2478 2479 status_t err; 2480 if ((err = mCodec->mNativeWindow->queueBuffer( 2481 mCodec->mNativeWindow.get(), 2482 info->mGraphicBuffer.get())) == OK) { 2483 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 2484 } else { 2485 mCodec->signalError(OMX_ErrorUndefined, err); 2486 info->mStatus = BufferInfo::OWNED_BY_US; 2487 } 2488 } else { 2489 info->mStatus = BufferInfo::OWNED_BY_US; 2490 } 2491 2492 PortMode mode = getPortMode(kPortIndexOutput); 2493 2494 switch (mode) { 2495 case KEEP_BUFFERS: 2496 { 2497 // XXX fishy, revisit!!! What about the FREE_BUFFERS case below? 2498 2499 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 2500 // We cannot resubmit the buffer we just rendered, dequeue 2501 // the spare instead. 2502 2503 info = mCodec->dequeueBufferFromNativeWindow(); 2504 } 2505 break; 2506 } 2507 2508 case RESUBMIT_BUFFERS: 2509 { 2510 if (!mCodec->mPortEOS[kPortIndexOutput]) { 2511 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 2512 // We cannot resubmit the buffer we just rendered, dequeue 2513 // the spare instead. 2514 2515 info = mCodec->dequeueBufferFromNativeWindow(); 2516 } 2517 2518 if (info != NULL) { 2519 ALOGV("[%s] calling fillBuffer %p", 2520 mCodec->mComponentName.c_str(), info->mBufferID); 2521 2522 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), 2523 (status_t)OK); 2524 2525 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 2526 } 2527 } 2528 break; 2529 } 2530 2531 default: 2532 { 2533 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 2534 2535 CHECK_EQ((status_t)OK, 2536 mCodec->freeBuffer(kPortIndexOutput, index)); 2537 break; 2538 } 2539 } 2540} 2541 2542//////////////////////////////////////////////////////////////////////////////// 2543 2544ACodec::UninitializedState::UninitializedState(ACodec *codec) 2545 : BaseState(codec) { 2546} 2547 2548void ACodec::UninitializedState::stateEntered() { 2549 ALOGV("Now uninitialized"); 2550} 2551 2552bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) { 2553 bool handled = false; 2554 2555 switch (msg->what()) { 2556 case ACodec::kWhatSetup: 2557 { 2558 onSetup(msg); 2559 2560 handled = true; 2561 break; 2562 } 2563 2564 case ACodec::kWhatAllocateComponent: 2565 { 2566 onAllocateComponent(msg); 2567 handled = true; 2568 break; 2569 } 2570 2571 case ACodec::kWhatShutdown: 2572 { 2573 int32_t keepComponentAllocated; 2574 CHECK(msg->findInt32( 2575 "keepComponentAllocated", &keepComponentAllocated)); 2576 CHECK(!keepComponentAllocated); 2577 2578 sp<AMessage> notify = mCodec->mNotify->dup(); 2579 notify->setInt32("what", ACodec::kWhatShutdownCompleted); 2580 notify->post(); 2581 2582 handled = true; 2583 break; 2584 } 2585 2586 case ACodec::kWhatFlush: 2587 { 2588 sp<AMessage> notify = mCodec->mNotify->dup(); 2589 notify->setInt32("what", ACodec::kWhatFlushCompleted); 2590 notify->post(); 2591 2592 handled = true; 2593 break; 2594 } 2595 2596 default: 2597 return BaseState::onMessageReceived(msg); 2598 } 2599 2600 return handled; 2601} 2602 2603void ACodec::UninitializedState::onSetup( 2604 const sp<AMessage> &msg) { 2605 if (onAllocateComponent(msg) 2606 && mCodec->mLoadedState->onConfigureComponent(msg)) { 2607 mCodec->mLoadedState->onStart(); 2608 } 2609} 2610 2611bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) { 2612 ALOGV("onAllocateComponent"); 2613 2614 CHECK(mCodec->mNode == NULL); 2615 2616 OMXClient client; 2617 CHECK_EQ(client.connect(), (status_t)OK); 2618 2619 sp<IOMX> omx = client.interface(); 2620 2621 Vector<String8> matchingCodecs; 2622 Vector<uint32_t> matchingCodecQuirks; 2623 2624 AString mime; 2625 2626 AString componentName; 2627 uint32_t quirks; 2628 if (msg->findString("componentName", &componentName)) { 2629 matchingCodecs.push_back(String8(componentName.c_str())); 2630 2631 if (!OMXCodec::findCodecQuirks(componentName.c_str(), &quirks)) { 2632 quirks = 0; 2633 } 2634 matchingCodecQuirks.push_back(quirks); 2635 } else { 2636 CHECK(msg->findString("mime", &mime)); 2637 2638 int32_t encoder; 2639 if (!msg->findInt32("encoder", &encoder)) { 2640 encoder = false; 2641 } 2642 2643 OMXCodec::findMatchingCodecs( 2644 mime.c_str(), 2645 encoder, // createEncoder 2646 NULL, // matchComponentName 2647 0, // flags 2648 &matchingCodecs, 2649 &matchingCodecQuirks); 2650 } 2651 2652 sp<CodecObserver> observer = new CodecObserver; 2653 IOMX::node_id node = NULL; 2654 2655 for (size_t matchIndex = 0; matchIndex < matchingCodecs.size(); 2656 ++matchIndex) { 2657 componentName = matchingCodecs.itemAt(matchIndex).string(); 2658 quirks = matchingCodecQuirks.itemAt(matchIndex); 2659 2660 pid_t tid = androidGetTid(); 2661 int prevPriority = androidGetThreadPriority(tid); 2662 androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND); 2663 status_t err = omx->allocateNode(componentName.c_str(), observer, &node); 2664 androidSetThreadPriority(tid, prevPriority); 2665 2666 if (err == OK) { 2667 break; 2668 } 2669 2670 node = NULL; 2671 } 2672 2673 if (node == NULL) { 2674 if (!mime.empty()) { 2675 ALOGE("Unable to instantiate a decoder for type '%s'.", 2676 mime.c_str()); 2677 } else { 2678 ALOGE("Unable to instantiate decoder '%s'.", componentName.c_str()); 2679 } 2680 2681 mCodec->signalError(OMX_ErrorComponentNotFound); 2682 return false; 2683 } 2684 2685 sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id()); 2686 observer->setNotificationMessage(notify); 2687 2688 mCodec->mComponentName = componentName; 2689 mCodec->mFlags = 0; 2690 2691 if (componentName.endsWith(".secure")) { 2692 mCodec->mFlags |= kFlagIsSecure; 2693 } 2694 2695 mCodec->mQuirks = quirks; 2696 mCodec->mOMX = omx; 2697 mCodec->mNode = node; 2698 2699 mCodec->mPortEOS[kPortIndexInput] = 2700 mCodec->mPortEOS[kPortIndexOutput] = false; 2701 2702 mCodec->mInputEOSResult = OK; 2703 2704 { 2705 sp<AMessage> notify = mCodec->mNotify->dup(); 2706 notify->setInt32("what", ACodec::kWhatComponentAllocated); 2707 notify->setString("componentName", mCodec->mComponentName.c_str()); 2708 notify->post(); 2709 } 2710 2711 mCodec->changeState(mCodec->mLoadedState); 2712 2713 return true; 2714} 2715 2716//////////////////////////////////////////////////////////////////////////////// 2717 2718ACodec::LoadedState::LoadedState(ACodec *codec) 2719 : BaseState(codec) { 2720} 2721 2722void ACodec::LoadedState::stateEntered() { 2723 ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str()); 2724 2725 if (mCodec->mShutdownInProgress) { 2726 bool keepComponentAllocated = mCodec->mKeepComponentAllocated; 2727 2728 mCodec->mShutdownInProgress = false; 2729 mCodec->mKeepComponentAllocated = false; 2730 2731 onShutdown(keepComponentAllocated); 2732 } 2733} 2734 2735void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) { 2736 if (!keepComponentAllocated) { 2737 CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK); 2738 2739 mCodec->mNativeWindow.clear(); 2740 mCodec->mNode = NULL; 2741 mCodec->mOMX.clear(); 2742 mCodec->mQuirks = 0; 2743 mCodec->mFlags = 0; 2744 mCodec->mComponentName.clear(); 2745 2746 mCodec->changeState(mCodec->mUninitializedState); 2747 } 2748 2749 sp<AMessage> notify = mCodec->mNotify->dup(); 2750 notify->setInt32("what", ACodec::kWhatShutdownCompleted); 2751 notify->post(); 2752} 2753 2754bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) { 2755 bool handled = false; 2756 2757 switch (msg->what()) { 2758 case ACodec::kWhatConfigureComponent: 2759 { 2760 onConfigureComponent(msg); 2761 handled = true; 2762 break; 2763 } 2764 2765 case ACodec::kWhatStart: 2766 { 2767 onStart(); 2768 handled = true; 2769 break; 2770 } 2771 2772 case ACodec::kWhatShutdown: 2773 { 2774 int32_t keepComponentAllocated; 2775 CHECK(msg->findInt32( 2776 "keepComponentAllocated", &keepComponentAllocated)); 2777 2778 onShutdown(keepComponentAllocated); 2779 2780 handled = true; 2781 break; 2782 } 2783 2784 case ACodec::kWhatFlush: 2785 { 2786 sp<AMessage> notify = mCodec->mNotify->dup(); 2787 notify->setInt32("what", ACodec::kWhatFlushCompleted); 2788 notify->post(); 2789 2790 handled = true; 2791 break; 2792 } 2793 2794 default: 2795 return BaseState::onMessageReceived(msg); 2796 } 2797 2798 return handled; 2799} 2800 2801bool ACodec::LoadedState::onConfigureComponent( 2802 const sp<AMessage> &msg) { 2803 ALOGV("onConfigureComponent"); 2804 2805 CHECK(mCodec->mNode != NULL); 2806 2807 AString mime; 2808 CHECK(msg->findString("mime", &mime)); 2809 2810 status_t err = mCodec->configureCodec(mime.c_str(), msg); 2811 2812 if (err != OK) { 2813 ALOGE("[%s] configureCodec returning error %d", 2814 mCodec->mComponentName.c_str(), err); 2815 2816 mCodec->signalError(OMX_ErrorUndefined, err); 2817 return false; 2818 } 2819 2820 sp<RefBase> obj; 2821 if (msg->findObject("native-window", &obj) 2822 && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) { 2823 sp<NativeWindowWrapper> nativeWindow( 2824 static_cast<NativeWindowWrapper *>(obj.get())); 2825 CHECK(nativeWindow != NULL); 2826 mCodec->mNativeWindow = nativeWindow->getNativeWindow(); 2827 } 2828 CHECK_EQ((status_t)OK, mCodec->initNativeWindow()); 2829 2830 { 2831 sp<AMessage> notify = mCodec->mNotify->dup(); 2832 notify->setInt32("what", ACodec::kWhatComponentConfigured); 2833 notify->post(); 2834 } 2835 2836 return true; 2837} 2838 2839void ACodec::LoadedState::onStart() { 2840 ALOGV("onStart"); 2841 2842 CHECK_EQ(mCodec->mOMX->sendCommand( 2843 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle), 2844 (status_t)OK); 2845 2846 mCodec->changeState(mCodec->mLoadedToIdleState); 2847} 2848 2849//////////////////////////////////////////////////////////////////////////////// 2850 2851ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec) 2852 : BaseState(codec) { 2853} 2854 2855void ACodec::LoadedToIdleState::stateEntered() { 2856 ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str()); 2857 2858 status_t err; 2859 if ((err = allocateBuffers()) != OK) { 2860 ALOGE("Failed to allocate buffers after transitioning to IDLE state " 2861 "(error 0x%08x)", 2862 err); 2863 2864 mCodec->signalError(OMX_ErrorUndefined, err); 2865 } 2866} 2867 2868status_t ACodec::LoadedToIdleState::allocateBuffers() { 2869 status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput); 2870 2871 if (err != OK) { 2872 return err; 2873 } 2874 2875 return mCodec->allocateBuffersOnPort(kPortIndexOutput); 2876} 2877 2878bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) { 2879 switch (msg->what()) { 2880 case kWhatShutdown: 2881 { 2882 mCodec->deferMessage(msg); 2883 return true; 2884 } 2885 2886 default: 2887 return BaseState::onMessageReceived(msg); 2888 } 2889} 2890 2891bool ACodec::LoadedToIdleState::onOMXEvent( 2892 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 2893 switch (event) { 2894 case OMX_EventCmdComplete: 2895 { 2896 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 2897 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); 2898 2899 CHECK_EQ(mCodec->mOMX->sendCommand( 2900 mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting), 2901 (status_t)OK); 2902 2903 mCodec->changeState(mCodec->mIdleToExecutingState); 2904 2905 return true; 2906 } 2907 2908 default: 2909 return BaseState::onOMXEvent(event, data1, data2); 2910 } 2911} 2912 2913//////////////////////////////////////////////////////////////////////////////// 2914 2915ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec) 2916 : BaseState(codec) { 2917} 2918 2919void ACodec::IdleToExecutingState::stateEntered() { 2920 ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str()); 2921} 2922 2923bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) { 2924 switch (msg->what()) { 2925 case kWhatShutdown: 2926 { 2927 mCodec->deferMessage(msg); 2928 return true; 2929 } 2930 2931 default: 2932 return BaseState::onMessageReceived(msg); 2933 } 2934} 2935 2936bool ACodec::IdleToExecutingState::onOMXEvent( 2937 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 2938 switch (event) { 2939 case OMX_EventCmdComplete: 2940 { 2941 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 2942 CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting); 2943 2944 mCodec->mExecutingState->resume(); 2945 mCodec->changeState(mCodec->mExecutingState); 2946 2947 return true; 2948 } 2949 2950 default: 2951 return BaseState::onOMXEvent(event, data1, data2); 2952 } 2953} 2954 2955//////////////////////////////////////////////////////////////////////////////// 2956 2957ACodec::ExecutingState::ExecutingState(ACodec *codec) 2958 : BaseState(codec), 2959 mActive(false) { 2960} 2961 2962ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode( 2963 OMX_U32 portIndex) { 2964 return RESUBMIT_BUFFERS; 2965} 2966 2967void ACodec::ExecutingState::submitOutputBuffers() { 2968 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) { 2969 BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i); 2970 2971 if (mCodec->mNativeWindow != NULL) { 2972 CHECK(info->mStatus == BufferInfo::OWNED_BY_US 2973 || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW); 2974 2975 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 2976 continue; 2977 } 2978 2979 status_t err = mCodec->mNativeWindow->lockBuffer( 2980 mCodec->mNativeWindow.get(), 2981 info->mGraphicBuffer.get()); 2982 CHECK_EQ(err, (status_t)OK); 2983 } else { 2984 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 2985 } 2986 2987 ALOGV("[%s] calling fillBuffer %p", 2988 mCodec->mComponentName.c_str(), info->mBufferID); 2989 2990 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), 2991 (status_t)OK); 2992 2993 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 2994 } 2995} 2996 2997void ACodec::ExecutingState::resume() { 2998 if (mActive) { 2999 ALOGV("[%s] We're already active, no need to resume.", 3000 mCodec->mComponentName.c_str()); 3001 3002 return; 3003 } 3004 3005 submitOutputBuffers(); 3006 3007 // Post the first input buffer. 3008 CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u); 3009 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0); 3010 3011 postFillThisBuffer(info); 3012 3013 mActive = true; 3014} 3015 3016void ACodec::ExecutingState::stateEntered() { 3017 ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str()); 3018 3019 mCodec->processDeferredMessages(); 3020} 3021 3022bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) { 3023 bool handled = false; 3024 3025 switch (msg->what()) { 3026 case kWhatShutdown: 3027 { 3028 int32_t keepComponentAllocated; 3029 CHECK(msg->findInt32( 3030 "keepComponentAllocated", &keepComponentAllocated)); 3031 3032 mCodec->mShutdownInProgress = true; 3033 mCodec->mKeepComponentAllocated = keepComponentAllocated; 3034 3035 mActive = false; 3036 3037 CHECK_EQ(mCodec->mOMX->sendCommand( 3038 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle), 3039 (status_t)OK); 3040 3041 mCodec->changeState(mCodec->mExecutingToIdleState); 3042 3043 handled = true; 3044 break; 3045 } 3046 3047 case kWhatFlush: 3048 { 3049 ALOGV("[%s] ExecutingState flushing now " 3050 "(codec owns %d/%d input, %d/%d output).", 3051 mCodec->mComponentName.c_str(), 3052 mCodec->countBuffersOwnedByComponent(kPortIndexInput), 3053 mCodec->mBuffers[kPortIndexInput].size(), 3054 mCodec->countBuffersOwnedByComponent(kPortIndexOutput), 3055 mCodec->mBuffers[kPortIndexOutput].size()); 3056 3057 mActive = false; 3058 3059 CHECK_EQ(mCodec->mOMX->sendCommand( 3060 mCodec->mNode, OMX_CommandFlush, OMX_ALL), 3061 (status_t)OK); 3062 3063 mCodec->changeState(mCodec->mFlushingState); 3064 3065 handled = true; 3066 break; 3067 } 3068 3069 case kWhatResume: 3070 { 3071 resume(); 3072 3073 handled = true; 3074 break; 3075 } 3076 3077 default: 3078 handled = BaseState::onMessageReceived(msg); 3079 break; 3080 } 3081 3082 return handled; 3083} 3084 3085bool ACodec::ExecutingState::onOMXEvent( 3086 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3087 switch (event) { 3088 case OMX_EventPortSettingsChanged: 3089 { 3090 CHECK_EQ(data1, (OMX_U32)kPortIndexOutput); 3091 3092 if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) { 3093 CHECK_EQ(mCodec->mOMX->sendCommand( 3094 mCodec->mNode, 3095 OMX_CommandPortDisable, kPortIndexOutput), 3096 (status_t)OK); 3097 3098 mCodec->freeOutputBuffersNotOwnedByComponent(); 3099 3100 mCodec->changeState(mCodec->mOutputPortSettingsChangedState); 3101 } else if (data2 == OMX_IndexConfigCommonOutputCrop) { 3102 mCodec->mSentFormat = false; 3103 } else { 3104 ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx", 3105 mCodec->mComponentName.c_str(), data2); 3106 } 3107 3108 return true; 3109 } 3110 3111 case OMX_EventBufferFlag: 3112 { 3113 return true; 3114 } 3115 3116 default: 3117 return BaseState::onOMXEvent(event, data1, data2); 3118 } 3119} 3120 3121//////////////////////////////////////////////////////////////////////////////// 3122 3123ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState( 3124 ACodec *codec) 3125 : BaseState(codec) { 3126} 3127 3128ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode( 3129 OMX_U32 portIndex) { 3130 if (portIndex == kPortIndexOutput) { 3131 return FREE_BUFFERS; 3132 } 3133 3134 CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput); 3135 3136 return RESUBMIT_BUFFERS; 3137} 3138 3139bool ACodec::OutputPortSettingsChangedState::onMessageReceived( 3140 const sp<AMessage> &msg) { 3141 bool handled = false; 3142 3143 switch (msg->what()) { 3144 case kWhatFlush: 3145 case kWhatShutdown: 3146 case kWhatResume: 3147 { 3148 if (msg->what() == kWhatResume) { 3149 ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str()); 3150 } 3151 3152 mCodec->deferMessage(msg); 3153 handled = true; 3154 break; 3155 } 3156 3157 default: 3158 handled = BaseState::onMessageReceived(msg); 3159 break; 3160 } 3161 3162 return handled; 3163} 3164 3165void ACodec::OutputPortSettingsChangedState::stateEntered() { 3166 ALOGV("[%s] Now handling output port settings change", 3167 mCodec->mComponentName.c_str()); 3168} 3169 3170bool ACodec::OutputPortSettingsChangedState::onOMXEvent( 3171 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3172 switch (event) { 3173 case OMX_EventCmdComplete: 3174 { 3175 if (data1 == (OMX_U32)OMX_CommandPortDisable) { 3176 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput); 3177 3178 ALOGV("[%s] Output port now disabled.", 3179 mCodec->mComponentName.c_str()); 3180 3181 CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty()); 3182 mCodec->mDealer[kPortIndexOutput].clear(); 3183 3184 CHECK_EQ(mCodec->mOMX->sendCommand( 3185 mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput), 3186 (status_t)OK); 3187 3188 status_t err; 3189 if ((err = mCodec->allocateBuffersOnPort( 3190 kPortIndexOutput)) != OK) { 3191 ALOGE("Failed to allocate output port buffers after " 3192 "port reconfiguration (error 0x%08x)", 3193 err); 3194 3195 mCodec->signalError(OMX_ErrorUndefined, err); 3196 3197 // This is technically not correct, since we were unable 3198 // to allocate output buffers and therefore the output port 3199 // remains disabled. It is necessary however to allow us 3200 // to shutdown the codec properly. 3201 mCodec->changeState(mCodec->mExecutingState); 3202 } 3203 3204 return true; 3205 } else if (data1 == (OMX_U32)OMX_CommandPortEnable) { 3206 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput); 3207 3208 mCodec->mSentFormat = false; 3209 3210 ALOGV("[%s] Output port now reenabled.", 3211 mCodec->mComponentName.c_str()); 3212 3213 if (mCodec->mExecutingState->active()) { 3214 mCodec->mExecutingState->submitOutputBuffers(); 3215 } 3216 3217 mCodec->changeState(mCodec->mExecutingState); 3218 3219 return true; 3220 } 3221 3222 return false; 3223 } 3224 3225 default: 3226 return false; 3227 } 3228} 3229 3230//////////////////////////////////////////////////////////////////////////////// 3231 3232ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec) 3233 : BaseState(codec), 3234 mComponentNowIdle(false) { 3235} 3236 3237bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) { 3238 bool handled = false; 3239 3240 switch (msg->what()) { 3241 case kWhatFlush: 3242 { 3243 // Don't send me a flush request if you previously wanted me 3244 // to shutdown. 3245 TRESPASS(); 3246 break; 3247 } 3248 3249 case kWhatShutdown: 3250 { 3251 // We're already doing that... 3252 3253 handled = true; 3254 break; 3255 } 3256 3257 default: 3258 handled = BaseState::onMessageReceived(msg); 3259 break; 3260 } 3261 3262 return handled; 3263} 3264 3265void ACodec::ExecutingToIdleState::stateEntered() { 3266 ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str()); 3267 3268 mComponentNowIdle = false; 3269 mCodec->mSentFormat = false; 3270} 3271 3272bool ACodec::ExecutingToIdleState::onOMXEvent( 3273 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3274 switch (event) { 3275 case OMX_EventCmdComplete: 3276 { 3277 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 3278 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); 3279 3280 mComponentNowIdle = true; 3281 3282 changeStateIfWeOwnAllBuffers(); 3283 3284 return true; 3285 } 3286 3287 case OMX_EventPortSettingsChanged: 3288 case OMX_EventBufferFlag: 3289 { 3290 // We're shutting down and don't care about this anymore. 3291 return true; 3292 } 3293 3294 default: 3295 return BaseState::onOMXEvent(event, data1, data2); 3296 } 3297} 3298 3299void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() { 3300 if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) { 3301 CHECK_EQ(mCodec->mOMX->sendCommand( 3302 mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded), 3303 (status_t)OK); 3304 3305 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK); 3306 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK); 3307 3308 mCodec->changeState(mCodec->mIdleToLoadedState); 3309 } 3310} 3311 3312void ACodec::ExecutingToIdleState::onInputBufferFilled( 3313 const sp<AMessage> &msg) { 3314 BaseState::onInputBufferFilled(msg); 3315 3316 changeStateIfWeOwnAllBuffers(); 3317} 3318 3319void ACodec::ExecutingToIdleState::onOutputBufferDrained( 3320 const sp<AMessage> &msg) { 3321 BaseState::onOutputBufferDrained(msg); 3322 3323 changeStateIfWeOwnAllBuffers(); 3324} 3325 3326//////////////////////////////////////////////////////////////////////////////// 3327 3328ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec) 3329 : BaseState(codec) { 3330} 3331 3332bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) { 3333 bool handled = false; 3334 3335 switch (msg->what()) { 3336 case kWhatShutdown: 3337 { 3338 // We're already doing that... 3339 3340 handled = true; 3341 break; 3342 } 3343 3344 case kWhatFlush: 3345 { 3346 // Don't send me a flush request if you previously wanted me 3347 // to shutdown. 3348 TRESPASS(); 3349 break; 3350 } 3351 3352 default: 3353 handled = BaseState::onMessageReceived(msg); 3354 break; 3355 } 3356 3357 return handled; 3358} 3359 3360void ACodec::IdleToLoadedState::stateEntered() { 3361 ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str()); 3362} 3363 3364bool ACodec::IdleToLoadedState::onOMXEvent( 3365 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3366 switch (event) { 3367 case OMX_EventCmdComplete: 3368 { 3369 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 3370 CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded); 3371 3372 mCodec->changeState(mCodec->mLoadedState); 3373 3374 return true; 3375 } 3376 3377 default: 3378 return BaseState::onOMXEvent(event, data1, data2); 3379 } 3380} 3381 3382//////////////////////////////////////////////////////////////////////////////// 3383 3384ACodec::FlushingState::FlushingState(ACodec *codec) 3385 : BaseState(codec) { 3386} 3387 3388void ACodec::FlushingState::stateEntered() { 3389 ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str()); 3390 3391 mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false; 3392} 3393 3394bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) { 3395 bool handled = false; 3396 3397 switch (msg->what()) { 3398 case kWhatShutdown: 3399 { 3400 mCodec->deferMessage(msg); 3401 break; 3402 } 3403 3404 case kWhatFlush: 3405 { 3406 // We're already doing this right now. 3407 handled = true; 3408 break; 3409 } 3410 3411 default: 3412 handled = BaseState::onMessageReceived(msg); 3413 break; 3414 } 3415 3416 return handled; 3417} 3418 3419bool ACodec::FlushingState::onOMXEvent( 3420 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3421 ALOGV("[%s] FlushingState onOMXEvent(%d,%ld)", 3422 mCodec->mComponentName.c_str(), event, data1); 3423 3424 switch (event) { 3425 case OMX_EventCmdComplete: 3426 { 3427 CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush); 3428 3429 if (data2 == kPortIndexInput || data2 == kPortIndexOutput) { 3430 CHECK(!mFlushComplete[data2]); 3431 mFlushComplete[data2] = true; 3432 3433 if (mFlushComplete[kPortIndexInput] 3434 && mFlushComplete[kPortIndexOutput]) { 3435 changeStateIfWeOwnAllBuffers(); 3436 } 3437 } else { 3438 CHECK_EQ(data2, OMX_ALL); 3439 CHECK(mFlushComplete[kPortIndexInput]); 3440 CHECK(mFlushComplete[kPortIndexOutput]); 3441 3442 changeStateIfWeOwnAllBuffers(); 3443 } 3444 3445 return true; 3446 } 3447 3448 case OMX_EventPortSettingsChanged: 3449 { 3450 sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id()); 3451 msg->setInt32("type", omx_message::EVENT); 3452 msg->setPointer("node", mCodec->mNode); 3453 msg->setInt32("event", event); 3454 msg->setInt32("data1", data1); 3455 msg->setInt32("data2", data2); 3456 3457 ALOGV("[%s] Deferring OMX_EventPortSettingsChanged", 3458 mCodec->mComponentName.c_str()); 3459 3460 mCodec->deferMessage(msg); 3461 3462 return true; 3463 } 3464 3465 default: 3466 return BaseState::onOMXEvent(event, data1, data2); 3467 } 3468 3469 return true; 3470} 3471 3472void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) { 3473 BaseState::onOutputBufferDrained(msg); 3474 3475 changeStateIfWeOwnAllBuffers(); 3476} 3477 3478void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) { 3479 BaseState::onInputBufferFilled(msg); 3480 3481 changeStateIfWeOwnAllBuffers(); 3482} 3483 3484void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() { 3485 if (mFlushComplete[kPortIndexInput] 3486 && mFlushComplete[kPortIndexOutput] 3487 && mCodec->allYourBuffersAreBelongToUs()) { 3488 sp<AMessage> notify = mCodec->mNotify->dup(); 3489 notify->setInt32("what", ACodec::kWhatFlushCompleted); 3490 notify->post(); 3491 3492 mCodec->mPortEOS[kPortIndexInput] = 3493 mCodec->mPortEOS[kPortIndexOutput] = false; 3494 3495 mCodec->mInputEOSResult = OK; 3496 3497 mCodec->changeState(mCodec->mExecutingState); 3498 } 3499} 3500 3501} // namespace android 3502