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