ACodec.cpp revision 1173118eace0e9e347cb007f0da817cee87579ed
1//#define LOG_NDEBUG 0 2#define LOG_TAG "ACodec" 3 4#include <media/stagefright/ACodec.h> 5 6#include <binder/MemoryDealer.h> 7 8#include <media/stagefright/foundation/hexdump.h> 9#include <media/stagefright/foundation/ABuffer.h> 10#include <media/stagefright/foundation/ADebug.h> 11#include <media/stagefright/foundation/AMessage.h> 12 13#include <media/stagefright/MediaDefs.h> 14#include <media/stagefright/NativeWindowWrapper.h> 15#include <media/stagefright/OMXClient.h> 16 17#include <surfaceflinger/Surface.h> 18#include <gui/SurfaceTextureClient.h> 19 20#include <OMX_Component.h> 21 22namespace android { 23 24template<class T> 25static void InitOMXParams(T *params) { 26 params->nSize = sizeof(T); 27 params->nVersion.s.nVersionMajor = 1; 28 params->nVersion.s.nVersionMinor = 0; 29 params->nVersion.s.nRevision = 0; 30 params->nVersion.s.nStep = 0; 31} 32 33struct CodecObserver : public BnOMXObserver { 34 CodecObserver() {} 35 36 void setNotificationMessage(const sp<AMessage> &msg) { 37 mNotify = msg; 38 } 39 40 // from IOMXObserver 41 virtual void onMessage(const omx_message &omx_msg) { 42 sp<AMessage> msg = mNotify->dup(); 43 44 msg->setInt32("type", omx_msg.type); 45 msg->setPointer("node", omx_msg.node); 46 47 switch (omx_msg.type) { 48 case omx_message::EVENT: 49 { 50 msg->setInt32("event", omx_msg.u.event_data.event); 51 msg->setInt32("data1", omx_msg.u.event_data.data1); 52 msg->setInt32("data2", omx_msg.u.event_data.data2); 53 break; 54 } 55 56 case omx_message::EMPTY_BUFFER_DONE: 57 { 58 msg->setPointer("buffer", omx_msg.u.buffer_data.buffer); 59 break; 60 } 61 62 case omx_message::FILL_BUFFER_DONE: 63 { 64 msg->setPointer( 65 "buffer", omx_msg.u.extended_buffer_data.buffer); 66 msg->setInt32( 67 "range_offset", 68 omx_msg.u.extended_buffer_data.range_offset); 69 msg->setInt32( 70 "range_length", 71 omx_msg.u.extended_buffer_data.range_length); 72 msg->setInt32( 73 "flags", 74 omx_msg.u.extended_buffer_data.flags); 75 msg->setInt64( 76 "timestamp", 77 omx_msg.u.extended_buffer_data.timestamp); 78 msg->setPointer( 79 "platform_private", 80 omx_msg.u.extended_buffer_data.platform_private); 81 msg->setPointer( 82 "data_ptr", 83 omx_msg.u.extended_buffer_data.data_ptr); 84 break; 85 } 86 87 default: 88 TRESPASS(); 89 break; 90 } 91 92 msg->post(); 93 } 94 95protected: 96 virtual ~CodecObserver() {} 97 98private: 99 sp<AMessage> mNotify; 100 101 DISALLOW_EVIL_CONSTRUCTORS(CodecObserver); 102}; 103 104//////////////////////////////////////////////////////////////////////////////// 105 106struct ACodec::BaseState : public AState { 107 BaseState(ACodec *codec, const sp<AState> &parentState = NULL); 108 109protected: 110 enum PortMode { 111 KEEP_BUFFERS, 112 RESUBMIT_BUFFERS, 113 FREE_BUFFERS, 114 }; 115 116 ACodec *mCodec; 117 118 virtual PortMode getPortMode(OMX_U32 portIndex); 119 120 virtual bool onMessageReceived(const sp<AMessage> &msg); 121 122 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 123 124 virtual void onOutputBufferDrained(const sp<AMessage> &msg); 125 virtual void onInputBufferFilled(const sp<AMessage> &msg); 126 127 void postFillThisBuffer(BufferInfo *info); 128 129private: 130 bool onOMXMessage(const sp<AMessage> &msg); 131 132 bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID); 133 134 bool onOMXFillBufferDone( 135 IOMX::buffer_id bufferID, 136 size_t rangeOffset, size_t rangeLength, 137 OMX_U32 flags, 138 int64_t timeUs, 139 void *platformPrivate, 140 void *dataPtr); 141 142 void getMoreInputDataIfPossible(); 143 144 DISALLOW_EVIL_CONSTRUCTORS(BaseState); 145}; 146 147//////////////////////////////////////////////////////////////////////////////// 148 149struct ACodec::UninitializedState : public ACodec::BaseState { 150 UninitializedState(ACodec *codec); 151 152protected: 153 virtual bool onMessageReceived(const sp<AMessage> &msg); 154 155private: 156 void onSetup(const sp<AMessage> &msg); 157 158 DISALLOW_EVIL_CONSTRUCTORS(UninitializedState); 159}; 160 161//////////////////////////////////////////////////////////////////////////////// 162 163struct ACodec::LoadedToIdleState : public ACodec::BaseState { 164 LoadedToIdleState(ACodec *codec); 165 166protected: 167 virtual bool onMessageReceived(const sp<AMessage> &msg); 168 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 169 virtual void stateEntered(); 170 171private: 172 status_t allocateBuffers(); 173 174 DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState); 175}; 176 177//////////////////////////////////////////////////////////////////////////////// 178 179struct ACodec::IdleToExecutingState : public ACodec::BaseState { 180 IdleToExecutingState(ACodec *codec); 181 182protected: 183 virtual bool onMessageReceived(const sp<AMessage> &msg); 184 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 185 virtual void stateEntered(); 186 187private: 188 DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState); 189}; 190 191//////////////////////////////////////////////////////////////////////////////// 192 193struct ACodec::ExecutingState : public ACodec::BaseState { 194 ExecutingState(ACodec *codec); 195 196 void submitOutputBuffers(); 197 198 // Submit output buffers to the decoder, submit input buffers to client 199 // to fill with data. 200 void resume(); 201 202 // Returns true iff input and output buffers are in play. 203 bool active() const { return mActive; } 204 205protected: 206 virtual PortMode getPortMode(OMX_U32 portIndex); 207 virtual bool onMessageReceived(const sp<AMessage> &msg); 208 virtual void stateEntered(); 209 210 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 211 212private: 213 bool mActive; 214 215 DISALLOW_EVIL_CONSTRUCTORS(ExecutingState); 216}; 217 218//////////////////////////////////////////////////////////////////////////////// 219 220struct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState { 221 OutputPortSettingsChangedState(ACodec *codec); 222 223protected: 224 virtual PortMode getPortMode(OMX_U32 portIndex); 225 virtual bool onMessageReceived(const sp<AMessage> &msg); 226 virtual void stateEntered(); 227 228 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 229 230private: 231 DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState); 232}; 233 234//////////////////////////////////////////////////////////////////////////////// 235 236struct ACodec::ExecutingToIdleState : public ACodec::BaseState { 237 ExecutingToIdleState(ACodec *codec); 238 239protected: 240 virtual bool onMessageReceived(const sp<AMessage> &msg); 241 virtual void stateEntered(); 242 243 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 244 245 virtual void onOutputBufferDrained(const sp<AMessage> &msg); 246 virtual void onInputBufferFilled(const sp<AMessage> &msg); 247 248private: 249 void changeStateIfWeOwnAllBuffers(); 250 251 DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState); 252}; 253 254//////////////////////////////////////////////////////////////////////////////// 255 256struct ACodec::IdleToLoadedState : public ACodec::BaseState { 257 IdleToLoadedState(ACodec *codec); 258 259protected: 260 virtual bool onMessageReceived(const sp<AMessage> &msg); 261 virtual void stateEntered(); 262 263 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 264 265private: 266 DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState); 267}; 268 269//////////////////////////////////////////////////////////////////////////////// 270 271struct ACodec::ErrorState : public ACodec::BaseState { 272 ErrorState(ACodec *codec); 273 274protected: 275 virtual bool onMessageReceived(const sp<AMessage> &msg); 276 virtual void stateEntered(); 277 278 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 279 280private: 281 DISALLOW_EVIL_CONSTRUCTORS(ErrorState); 282}; 283 284//////////////////////////////////////////////////////////////////////////////// 285 286struct ACodec::FlushingState : public ACodec::BaseState { 287 FlushingState(ACodec *codec); 288 289protected: 290 virtual bool onMessageReceived(const sp<AMessage> &msg); 291 virtual void stateEntered(); 292 293 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 294 295 virtual void onOutputBufferDrained(const sp<AMessage> &msg); 296 virtual void onInputBufferFilled(const sp<AMessage> &msg); 297 298private: 299 bool mFlushComplete[2]; 300 301 void changeStateIfWeOwnAllBuffers(); 302 303 DISALLOW_EVIL_CONSTRUCTORS(FlushingState); 304}; 305 306//////////////////////////////////////////////////////////////////////////////// 307 308ACodec::ACodec() 309 : mNode(NULL), 310 mSentFormat(false) { 311 mUninitializedState = new UninitializedState(this); 312 mLoadedToIdleState = new LoadedToIdleState(this); 313 mIdleToExecutingState = new IdleToExecutingState(this); 314 mExecutingState = new ExecutingState(this); 315 316 mOutputPortSettingsChangedState = 317 new OutputPortSettingsChangedState(this); 318 319 mExecutingToIdleState = new ExecutingToIdleState(this); 320 mIdleToLoadedState = new IdleToLoadedState(this); 321 mErrorState = new ErrorState(this); 322 mFlushingState = new FlushingState(this); 323 324 mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false; 325 326 changeState(mUninitializedState); 327} 328 329ACodec::~ACodec() { 330} 331 332void ACodec::setNotificationMessage(const sp<AMessage> &msg) { 333 mNotify = msg; 334} 335 336void ACodec::initiateSetup(const sp<AMessage> &msg) { 337 msg->setWhat(kWhatSetup); 338 msg->setTarget(id()); 339 msg->post(); 340} 341 342void ACodec::signalFlush() { 343 (new AMessage(kWhatFlush, id()))->post(); 344} 345 346void ACodec::signalResume() { 347 (new AMessage(kWhatResume, id()))->post(); 348} 349 350void ACodec::initiateShutdown() { 351 (new AMessage(kWhatShutdown, id()))->post(); 352} 353 354status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) { 355 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 356 357 CHECK(mDealer[portIndex] == NULL); 358 CHECK(mBuffers[portIndex].isEmpty()); 359 360 if (mNativeWindow != NULL && portIndex == kPortIndexOutput) { 361 return allocateOutputBuffersFromNativeWindow(); 362 } 363 364 OMX_PARAM_PORTDEFINITIONTYPE def; 365 InitOMXParams(&def); 366 def.nPortIndex = portIndex; 367 368 status_t err = mOMX->getParameter( 369 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 370 371 if (err != OK) { 372 return err; 373 } 374 375 LOGV("[%s] Allocating %lu buffers of size %lu on %s port", 376 mComponentName.c_str(), 377 def.nBufferCountActual, def.nBufferSize, 378 portIndex == kPortIndexInput ? "input" : "output"); 379 380 size_t totalSize = def.nBufferCountActual * def.nBufferSize; 381 mDealer[portIndex] = new MemoryDealer(totalSize, "OMXCodec"); 382 383 for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) { 384 sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize); 385 CHECK(mem.get() != NULL); 386 387 IOMX::buffer_id buffer; 388#if 0 389 err = mOMX->allocateBufferWithBackup(mNode, portIndex, mem, &buffer); 390#else 391 err = mOMX->useBuffer(mNode, portIndex, mem, &buffer); 392#endif 393 394 if (err != OK) { 395 return err; 396 } 397 398 BufferInfo info; 399 info.mBufferID = buffer; 400 info.mStatus = BufferInfo::OWNED_BY_US; 401 info.mData = new ABuffer(mem->pointer(), def.nBufferSize); 402 mBuffers[portIndex].push(info); 403 } 404 405 return OK; 406} 407 408status_t ACodec::allocateOutputBuffersFromNativeWindow() { 409 OMX_PARAM_PORTDEFINITIONTYPE def; 410 InitOMXParams(&def); 411 def.nPortIndex = kPortIndexOutput; 412 413 status_t err = mOMX->getParameter( 414 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 415 416 if (err != OK) { 417 return err; 418 } 419 420 err = native_window_set_buffers_geometry( 421 mNativeWindow.get(), 422 def.format.video.nFrameWidth, 423 def.format.video.nFrameHeight, 424 def.format.video.eColorFormat); 425 426 if (err != 0) { 427 LOGE("native_window_set_buffers_geometry failed: %s (%d)", 428 strerror(-err), -err); 429 return err; 430 } 431 432 // Increase the buffer count by one to allow for the ANativeWindow to hold 433 // on to one of the buffers. 434 def.nBufferCountActual++; 435 err = mOMX->setParameter( 436 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 437 438 if (err != OK) { 439 return err; 440 } 441 442 // Set up the native window. 443 // XXX TODO: Get the gralloc usage flags from the OMX plugin! 444 err = native_window_set_usage( 445 mNativeWindow.get(), 446 GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP); 447 448 if (err != 0) { 449 LOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err); 450 return err; 451 } 452 453 err = native_window_set_buffer_count( 454 mNativeWindow.get(), def.nBufferCountActual); 455 456 if (err != 0) { 457 LOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), 458 -err); 459 return err; 460 } 461 462 // XXX TODO: Do something so the ANativeWindow knows that we'll need to get 463 // the same set of buffers. 464 465 LOGV("[%s] Allocating %lu buffers from a native window of size %lu on " 466 "output port", 467 mComponentName.c_str(), def.nBufferCountActual, def.nBufferSize); 468 469 // Dequeue buffers and send them to OMX 470 OMX_U32 i; 471 for (i = 0; i < def.nBufferCountActual; i++) { 472 android_native_buffer_t *buf; 473 err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf); 474 if (err != 0) { 475 LOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err); 476 break; 477 } 478 479 sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false)); 480 IOMX::buffer_id bufferId; 481 err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer, 482 &bufferId); 483 if (err != 0) { 484 break; 485 } 486 487 LOGV("[%s] Registered graphic buffer with ID %p (pointer = %p)", 488 mComponentName.c_str(), 489 bufferId, graphicBuffer.get()); 490 491 BufferInfo info; 492 info.mBufferID = bufferId; 493 info.mStatus = BufferInfo::OWNED_BY_US; 494 info.mData = new ABuffer(0); 495 info.mGraphicBuffer = graphicBuffer; 496 mBuffers[kPortIndexOutput].push(info); 497 } 498 499 OMX_U32 cancelStart; 500 OMX_U32 cancelEnd; 501 502 if (err != 0) { 503 // If an error occurred while dequeuing we need to cancel any buffers 504 // that were dequeued. 505 cancelStart = 0; 506 cancelEnd = i; 507 } else { 508 // Return the last two buffers to the native window. 509 // XXX TODO: The number of buffers the native window owns should 510 // probably be queried from it when we put the native window in 511 // fixed buffer pool mode (which needs to be implemented). 512 // Currently it's hard-coded to 2. 513 cancelStart = def.nBufferCountActual - 2; 514 cancelEnd = def.nBufferCountActual; 515 } 516 517 for (OMX_U32 i = cancelStart; i < cancelEnd; i++) { 518 BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i); 519 cancelBufferToNativeWindow(info); 520 } 521 522 return err; 523} 524 525status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) { 526 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 527 528 LOGV("[%s] Calling cancelBuffer on buffer %p", 529 mComponentName.c_str(), info->mBufferID); 530 531 int err = mNativeWindow->cancelBuffer( 532 mNativeWindow.get(), info->mGraphicBuffer.get()); 533 534 CHECK_EQ(err, 0); 535 536 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 537 538 return OK; 539} 540 541ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() { 542 android_native_buffer_t *buf; 543 CHECK_EQ(mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf), 0); 544 545 for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) { 546 BufferInfo *info = 547 &mBuffers[kPortIndexOutput].editItemAt(i); 548 549 if (info->mGraphicBuffer->handle == buf->handle) { 550 CHECK_EQ((int)info->mStatus, 551 (int)BufferInfo::OWNED_BY_NATIVE_WINDOW); 552 553 info->mStatus = BufferInfo::OWNED_BY_US; 554 555 return info; 556 } 557 } 558 559 TRESPASS(); 560 561 return NULL; 562} 563 564status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) { 565 for (size_t i = mBuffers[portIndex].size(); i-- > 0;) { 566 CHECK_EQ((status_t)OK, freeBuffer(portIndex, i)); 567 } 568 569 mDealer[portIndex].clear(); 570 571 return OK; 572} 573 574status_t ACodec::freeOutputBuffersNotOwnedByComponent() { 575 for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) { 576 BufferInfo *info = 577 &mBuffers[kPortIndexOutput].editItemAt(i); 578 579 if (info->mStatus != 580 BufferInfo::OWNED_BY_COMPONENT) { 581 // We shouldn't have sent out any buffers to the client at this 582 // point. 583 CHECK_NE((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM); 584 585 CHECK_EQ((status_t)OK, freeBuffer(kPortIndexOutput, i)); 586 } 587 } 588 589 return OK; 590} 591 592status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) { 593 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 594 595 CHECK(info->mStatus == BufferInfo::OWNED_BY_US 596 || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW); 597 598 if (portIndex == kPortIndexOutput && mNativeWindow != NULL 599 && info->mStatus == BufferInfo::OWNED_BY_US) { 600 CHECK_EQ((status_t)OK, cancelBufferToNativeWindow(info)); 601 } 602 603 CHECK_EQ(mOMX->freeBuffer( 604 mNode, portIndex, info->mBufferID), 605 (status_t)OK); 606 607 mBuffers[portIndex].removeAt(i); 608 609 return OK; 610} 611 612ACodec::BufferInfo *ACodec::findBufferByID( 613 uint32_t portIndex, IOMX::buffer_id bufferID, 614 ssize_t *index) { 615 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 616 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 617 618 if (info->mBufferID == bufferID) { 619 if (index != NULL) { 620 *index = i; 621 } 622 return info; 623 } 624 } 625 626 TRESPASS(); 627 628 return NULL; 629} 630 631void ACodec::setComponentRole( 632 bool isEncoder, const char *mime) { 633 struct MimeToRole { 634 const char *mime; 635 const char *decoderRole; 636 const char *encoderRole; 637 }; 638 639 static const MimeToRole kMimeToRole[] = { 640 { MEDIA_MIMETYPE_AUDIO_MPEG, 641 "audio_decoder.mp3", "audio_encoder.mp3" }, 642 { MEDIA_MIMETYPE_AUDIO_AMR_NB, 643 "audio_decoder.amrnb", "audio_encoder.amrnb" }, 644 { MEDIA_MIMETYPE_AUDIO_AMR_WB, 645 "audio_decoder.amrwb", "audio_encoder.amrwb" }, 646 { MEDIA_MIMETYPE_AUDIO_AAC, 647 "audio_decoder.aac", "audio_encoder.aac" }, 648 { MEDIA_MIMETYPE_VIDEO_AVC, 649 "video_decoder.avc", "video_encoder.avc" }, 650 { MEDIA_MIMETYPE_VIDEO_MPEG4, 651 "video_decoder.mpeg4", "video_encoder.mpeg4" }, 652 { MEDIA_MIMETYPE_VIDEO_H263, 653 "video_decoder.h263", "video_encoder.h263" }, 654 }; 655 656 static const size_t kNumMimeToRole = 657 sizeof(kMimeToRole) / sizeof(kMimeToRole[0]); 658 659 size_t i; 660 for (i = 0; i < kNumMimeToRole; ++i) { 661 if (!strcasecmp(mime, kMimeToRole[i].mime)) { 662 break; 663 } 664 } 665 666 if (i == kNumMimeToRole) { 667 return; 668 } 669 670 const char *role = 671 isEncoder ? kMimeToRole[i].encoderRole 672 : kMimeToRole[i].decoderRole; 673 674 if (role != NULL) { 675 OMX_PARAM_COMPONENTROLETYPE roleParams; 676 InitOMXParams(&roleParams); 677 678 strncpy((char *)roleParams.cRole, 679 role, OMX_MAX_STRINGNAME_SIZE - 1); 680 681 roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0'; 682 683 status_t err = mOMX->setParameter( 684 mNode, OMX_IndexParamStandardComponentRole, 685 &roleParams, sizeof(roleParams)); 686 687 if (err != OK) { 688 LOGW("[%s] Failed to set standard component role '%s'.", 689 mComponentName.c_str(), role); 690 } 691 } 692} 693 694void ACodec::configureCodec( 695 const char *mime, const sp<AMessage> &msg) { 696 setComponentRole(false /* isEncoder */, mime); 697 698 if (!strncasecmp(mime, "video/", 6)) { 699 int32_t width, height; 700 CHECK(msg->findInt32("width", &width)); 701 CHECK(msg->findInt32("height", &height)); 702 703 CHECK_EQ(setupVideoDecoder(mime, width, height), 704 (status_t)OK); 705 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 706 int32_t numChannels, sampleRate; 707 CHECK(msg->findInt32("channel-count", &numChannels)); 708 CHECK(msg->findInt32("sample-rate", &sampleRate)); 709 710 CHECK_EQ(setupAACDecoder(numChannels, sampleRate), (status_t)OK); 711 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) { 712 } else { 713 TRESPASS(); 714 } 715 716 int32_t maxInputSize; 717 if (msg->findInt32("max-input-size", &maxInputSize)) { 718 CHECK_EQ(setMinBufferSize(kPortIndexInput, (size_t)maxInputSize), 719 (status_t)OK); 720 } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) { 721 CHECK_EQ(setMinBufferSize(kPortIndexInput, 8192), // XXX 722 (status_t)OK); 723 } 724} 725 726status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) { 727 OMX_PARAM_PORTDEFINITIONTYPE def; 728 InitOMXParams(&def); 729 def.nPortIndex = portIndex; 730 731 status_t err = mOMX->getParameter( 732 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 733 734 if (err != OK) { 735 return err; 736 } 737 738 if (def.nBufferSize >= size) { 739 return OK; 740 } 741 742 def.nBufferSize = size; 743 744 err = mOMX->setParameter( 745 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 746 747 if (err != OK) { 748 return err; 749 } 750 751 err = mOMX->getParameter( 752 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 753 754 if (err != OK) { 755 return err; 756 } 757 758 CHECK(def.nBufferSize >= size); 759 760 return OK; 761} 762 763status_t ACodec::setupAACDecoder(int32_t numChannels, int32_t sampleRate) { 764 OMX_AUDIO_PARAM_AACPROFILETYPE profile; 765 InitOMXParams(&profile); 766 profile.nPortIndex = kPortIndexInput; 767 768 status_t err = mOMX->getParameter( 769 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 770 771 if (err != OK) { 772 return err; 773 } 774 775 profile.nChannels = numChannels; 776 profile.nSampleRate = sampleRate; 777 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS; 778 779 err = mOMX->setParameter( 780 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 781 782 return err; 783} 784 785status_t ACodec::setVideoPortFormatType( 786 OMX_U32 portIndex, 787 OMX_VIDEO_CODINGTYPE compressionFormat, 788 OMX_COLOR_FORMATTYPE colorFormat) { 789 OMX_VIDEO_PARAM_PORTFORMATTYPE format; 790 InitOMXParams(&format); 791 format.nPortIndex = portIndex; 792 format.nIndex = 0; 793 bool found = false; 794 795 OMX_U32 index = 0; 796 for (;;) { 797 format.nIndex = index; 798 status_t err = mOMX->getParameter( 799 mNode, OMX_IndexParamVideoPortFormat, 800 &format, sizeof(format)); 801 802 if (err != OK) { 803 return err; 804 } 805 806 // The following assertion is violated by TI's video decoder. 807 // CHECK_EQ(format.nIndex, index); 808 809 if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) { 810 if (portIndex == kPortIndexInput 811 && colorFormat == format.eColorFormat) { 812 // eCompressionFormat does not seem right. 813 found = true; 814 break; 815 } 816 if (portIndex == kPortIndexOutput 817 && compressionFormat == format.eCompressionFormat) { 818 // eColorFormat does not seem right. 819 found = true; 820 break; 821 } 822 } 823 824 if (format.eCompressionFormat == compressionFormat 825 && format.eColorFormat == colorFormat) { 826 found = true; 827 break; 828 } 829 830 ++index; 831 } 832 833 if (!found) { 834 return UNKNOWN_ERROR; 835 } 836 837 status_t err = mOMX->setParameter( 838 mNode, OMX_IndexParamVideoPortFormat, 839 &format, sizeof(format)); 840 841 return err; 842} 843 844status_t ACodec::setSupportedOutputFormat() { 845 OMX_VIDEO_PARAM_PORTFORMATTYPE format; 846 InitOMXParams(&format); 847 format.nPortIndex = kPortIndexOutput; 848 format.nIndex = 0; 849 850 status_t err = mOMX->getParameter( 851 mNode, OMX_IndexParamVideoPortFormat, 852 &format, sizeof(format)); 853 CHECK_EQ(err, (status_t)OK); 854 CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused); 855 856 static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00; 857 858 CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar 859 || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar 860 || format.eColorFormat == OMX_COLOR_FormatCbYCrY 861 || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar); 862 863 return mOMX->setParameter( 864 mNode, OMX_IndexParamVideoPortFormat, 865 &format, sizeof(format)); 866} 867 868status_t ACodec::setupVideoDecoder( 869 const char *mime, int32_t width, int32_t height) { 870 OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused; 871 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 872 compressionFormat = OMX_VIDEO_CodingAVC; 873 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 874 compressionFormat = OMX_VIDEO_CodingMPEG4; 875 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 876 compressionFormat = OMX_VIDEO_CodingH263; 877 } else { 878 TRESPASS(); 879 } 880 881 status_t err = setVideoPortFormatType( 882 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused); 883 884 if (err != OK) { 885 return err; 886 } 887 888 err = setSupportedOutputFormat(); 889 890 if (err != OK) { 891 return err; 892 } 893 894 err = setVideoFormatOnPort( 895 kPortIndexInput, width, height, compressionFormat); 896 897 if (err != OK) { 898 return err; 899 } 900 901 err = setVideoFormatOnPort( 902 kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused); 903 904 if (err != OK) { 905 return err; 906 } 907 908 return OK; 909} 910 911status_t ACodec::setVideoFormatOnPort( 912 OMX_U32 portIndex, 913 int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) { 914 OMX_PARAM_PORTDEFINITIONTYPE def; 915 InitOMXParams(&def); 916 def.nPortIndex = portIndex; 917 918 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 919 920 status_t err = mOMX->getParameter( 921 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 922 923 CHECK_EQ(err, (status_t)OK); 924 925 if (portIndex == kPortIndexInput) { 926 // XXX Need a (much) better heuristic to compute input buffer sizes. 927 const size_t X = 64 * 1024; 928 if (def.nBufferSize < X) { 929 def.nBufferSize = X; 930 } 931 } 932 933 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo); 934 935 video_def->nFrameWidth = width; 936 video_def->nFrameHeight = height; 937 938 if (portIndex == kPortIndexInput) { 939 video_def->eCompressionFormat = compressionFormat; 940 video_def->eColorFormat = OMX_COLOR_FormatUnused; 941 } 942 943 err = mOMX->setParameter( 944 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 945 946 return err; 947} 948 949status_t ACodec::initNativeWindow() { 950 if (mNativeWindow != NULL) { 951 return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE); 952 } 953 954 mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE); 955 return OK; 956} 957 958bool ACodec::allYourBuffersAreBelongToUs( 959 OMX_U32 portIndex) { 960 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 961 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 962 963 if (info->mStatus != BufferInfo::OWNED_BY_US 964 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) { 965 LOGV("[%s] Buffer %p on port %ld still has status %d", 966 mComponentName.c_str(), 967 info->mBufferID, portIndex, info->mStatus); 968 return false; 969 } 970 } 971 972 return true; 973} 974 975bool ACodec::allYourBuffersAreBelongToUs() { 976 return allYourBuffersAreBelongToUs(kPortIndexInput) 977 && allYourBuffersAreBelongToUs(kPortIndexOutput); 978} 979 980void ACodec::deferMessage(const sp<AMessage> &msg) { 981 bool wasEmptyBefore = mDeferredQueue.empty(); 982 mDeferredQueue.push_back(msg); 983} 984 985void ACodec::processDeferredMessages() { 986 List<sp<AMessage> > queue = mDeferredQueue; 987 mDeferredQueue.clear(); 988 989 List<sp<AMessage> >::iterator it = queue.begin(); 990 while (it != queue.end()) { 991 onMessageReceived(*it++); 992 } 993} 994 995void ACodec::sendFormatChange() { 996 sp<AMessage> notify = mNotify->dup(); 997 notify->setInt32("what", kWhatOutputFormatChanged); 998 999 OMX_PARAM_PORTDEFINITIONTYPE def; 1000 InitOMXParams(&def); 1001 def.nPortIndex = kPortIndexOutput; 1002 1003 CHECK_EQ(mOMX->getParameter( 1004 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)), 1005 (status_t)OK); 1006 1007 CHECK_EQ((int)def.eDir, (int)OMX_DirOutput); 1008 1009 switch (def.eDomain) { 1010 case OMX_PortDomainVideo: 1011 { 1012 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video; 1013 1014 notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW); 1015 notify->setInt32("width", videoDef->nFrameWidth); 1016 notify->setInt32("height", videoDef->nFrameHeight); 1017 1018 OMX_CONFIG_RECTTYPE rect; 1019 InitOMXParams(&rect); 1020 rect.nPortIndex = kPortIndexOutput; 1021 1022 if (mOMX->getConfig( 1023 mNode, OMX_IndexConfigCommonOutputCrop, 1024 &rect, sizeof(rect)) != OK) { 1025 rect.nLeft = 0; 1026 rect.nTop = 0; 1027 rect.nWidth = videoDef->nFrameWidth; 1028 rect.nHeight = videoDef->nFrameHeight; 1029 } 1030 1031 CHECK_GE(rect.nLeft, 0); 1032 CHECK_GE(rect.nTop, 0); 1033 CHECK_GE(rect.nWidth, 0u); 1034 CHECK_GE(rect.nHeight, 0u); 1035 CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth); 1036 CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight); 1037 1038 notify->setRect( 1039 "crop", 1040 rect.nLeft, 1041 rect.nTop, 1042 rect.nLeft + rect.nWidth - 1, 1043 rect.nTop + rect.nHeight - 1); 1044 1045 if (mNativeWindow != NULL) { 1046 android_native_rect_t crop; 1047 crop.left = rect.nLeft; 1048 crop.top = rect.nTop; 1049 crop.right = rect.nLeft + rect.nWidth - 1; 1050 crop.bottom = rect.nTop + rect.nHeight - 1; 1051 1052 CHECK_EQ(0, native_window_set_crop( 1053 mNativeWindow.get(), &crop)); 1054 } 1055 break; 1056 } 1057 1058 case OMX_PortDomainAudio: 1059 { 1060 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio; 1061 CHECK_EQ((int)audioDef->eEncoding, (int)OMX_AUDIO_CodingPCM); 1062 1063 OMX_AUDIO_PARAM_PCMMODETYPE params; 1064 InitOMXParams(¶ms); 1065 params.nPortIndex = kPortIndexOutput; 1066 1067 CHECK_EQ(mOMX->getParameter( 1068 mNode, OMX_IndexParamAudioPcm, 1069 ¶ms, sizeof(params)), 1070 (status_t)OK); 1071 1072 CHECK(params.nChannels == 1 || params.bInterleaved); 1073 CHECK_EQ(params.nBitPerSample, 16u); 1074 CHECK_EQ((int)params.eNumData, (int)OMX_NumericalDataSigned); 1075 CHECK_EQ((int)params.ePCMMode, (int)OMX_AUDIO_PCMModeLinear); 1076 1077 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW); 1078 notify->setInt32("channel-count", params.nChannels); 1079 notify->setInt32("sample-rate", params.nSamplingRate); 1080 break; 1081 } 1082 1083 default: 1084 TRESPASS(); 1085 } 1086 1087 notify->post(); 1088 1089 mSentFormat = true; 1090} 1091 1092//////////////////////////////////////////////////////////////////////////////// 1093 1094ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState) 1095 : AState(parentState), 1096 mCodec(codec) { 1097} 1098 1099ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(OMX_U32 portIndex) { 1100 return KEEP_BUFFERS; 1101} 1102 1103bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) { 1104 switch (msg->what()) { 1105 case kWhatInputBufferFilled: 1106 { 1107 onInputBufferFilled(msg); 1108 break; 1109 } 1110 1111 case kWhatOutputBufferDrained: 1112 { 1113 onOutputBufferDrained(msg); 1114 break; 1115 } 1116 1117 case ACodec::kWhatOMXMessage: 1118 { 1119 return onOMXMessage(msg); 1120 } 1121 1122 default: 1123 return false; 1124 } 1125 1126 return true; 1127} 1128 1129bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) { 1130 int32_t type; 1131 CHECK(msg->findInt32("type", &type)); 1132 1133 IOMX::node_id nodeID; 1134 CHECK(msg->findPointer("node", &nodeID)); 1135 CHECK_EQ(nodeID, mCodec->mNode); 1136 1137 switch (type) { 1138 case omx_message::EVENT: 1139 { 1140 int32_t event, data1, data2; 1141 CHECK(msg->findInt32("event", &event)); 1142 CHECK(msg->findInt32("data1", &data1)); 1143 CHECK(msg->findInt32("data2", &data2)); 1144 1145 return onOMXEvent( 1146 static_cast<OMX_EVENTTYPE>(event), 1147 static_cast<OMX_U32>(data1), 1148 static_cast<OMX_U32>(data2)); 1149 } 1150 1151 case omx_message::EMPTY_BUFFER_DONE: 1152 { 1153 IOMX::buffer_id bufferID; 1154 CHECK(msg->findPointer("buffer", &bufferID)); 1155 1156 return onOMXEmptyBufferDone(bufferID); 1157 } 1158 1159 case omx_message::FILL_BUFFER_DONE: 1160 { 1161 IOMX::buffer_id bufferID; 1162 CHECK(msg->findPointer("buffer", &bufferID)); 1163 1164 int32_t rangeOffset, rangeLength, flags; 1165 int64_t timeUs; 1166 void *platformPrivate; 1167 void *dataPtr; 1168 1169 CHECK(msg->findInt32("range_offset", &rangeOffset)); 1170 CHECK(msg->findInt32("range_length", &rangeLength)); 1171 CHECK(msg->findInt32("flags", &flags)); 1172 CHECK(msg->findInt64("timestamp", &timeUs)); 1173 CHECK(msg->findPointer("platform_private", &platformPrivate)); 1174 CHECK(msg->findPointer("data_ptr", &dataPtr)); 1175 1176 return onOMXFillBufferDone( 1177 bufferID, 1178 (size_t)rangeOffset, (size_t)rangeLength, 1179 (OMX_U32)flags, 1180 timeUs, 1181 platformPrivate, 1182 dataPtr); 1183 } 1184 1185 default: 1186 TRESPASS(); 1187 break; 1188 } 1189} 1190 1191bool ACodec::BaseState::onOMXEvent( 1192 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 1193 if (event != OMX_EventError) { 1194 LOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)", 1195 mCodec->mComponentName.c_str(), event, data1, data2); 1196 1197 return false; 1198 } 1199 1200 LOGE("[%s] ERROR(0x%08lx, 0x%08lx)", 1201 mCodec->mComponentName.c_str(), data1, data2); 1202 1203 mCodec->changeState(mCodec->mErrorState); 1204 1205 return true; 1206} 1207 1208bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) { 1209 LOGV("[%s] onOMXEmptyBufferDone %p", 1210 mCodec->mComponentName.c_str(), bufferID); 1211 1212 BufferInfo *info = 1213 mCodec->findBufferByID(kPortIndexInput, bufferID); 1214 1215 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); 1216 info->mStatus = BufferInfo::OWNED_BY_US; 1217 1218 PortMode mode = getPortMode(kPortIndexInput); 1219 1220 switch (mode) { 1221 case KEEP_BUFFERS: 1222 break; 1223 1224 case RESUBMIT_BUFFERS: 1225 postFillThisBuffer(info); 1226 break; 1227 1228 default: 1229 { 1230 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 1231 TRESPASS(); // Not currently used 1232 break; 1233 } 1234 } 1235 1236 return true; 1237} 1238 1239void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) { 1240 if (mCodec->mPortEOS[kPortIndexInput]) { 1241 return; 1242 } 1243 1244 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 1245 1246 sp<AMessage> notify = mCodec->mNotify->dup(); 1247 notify->setInt32("what", ACodec::kWhatFillThisBuffer); 1248 notify->setPointer("buffer-id", info->mBufferID); 1249 1250 info->mData->meta()->clear(); 1251 notify->setObject("buffer", info->mData); 1252 1253 sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id()); 1254 reply->setPointer("buffer-id", info->mBufferID); 1255 1256 notify->setMessage("reply", reply); 1257 1258 notify->post(); 1259 1260 info->mStatus = BufferInfo::OWNED_BY_UPSTREAM; 1261} 1262 1263void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { 1264 IOMX::buffer_id bufferID; 1265 CHECK(msg->findPointer("buffer-id", &bufferID)); 1266 1267 sp<RefBase> obj; 1268 int32_t err = OK; 1269 if (!msg->findObject("buffer", &obj)) { 1270 CHECK(msg->findInt32("err", &err)); 1271 1272 LOGV("[%s] saw error %d instead of an input buffer", 1273 mCodec->mComponentName.c_str(), err); 1274 1275 obj.clear(); 1276 } 1277 1278 sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get()); 1279 1280 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID); 1281 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM); 1282 1283 info->mStatus = BufferInfo::OWNED_BY_US; 1284 1285 PortMode mode = getPortMode(kPortIndexInput); 1286 1287 switch (mode) { 1288 case KEEP_BUFFERS: 1289 { 1290 if (buffer == NULL) { 1291 mCodec->mPortEOS[kPortIndexInput] = true; 1292 } 1293 break; 1294 } 1295 1296 case RESUBMIT_BUFFERS: 1297 { 1298 if (buffer != NULL) { 1299 CHECK(!mCodec->mPortEOS[kPortIndexInput]); 1300 1301 int64_t timeUs; 1302 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 1303 1304 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME; 1305 1306 int32_t isCSD; 1307 if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) { 1308 flags |= OMX_BUFFERFLAG_CODECCONFIG; 1309 } 1310 1311 if (buffer != info->mData) { 1312 if (0 && !(flags & OMX_BUFFERFLAG_CODECCONFIG)) { 1313 LOGV("[%s] Needs to copy input data.", 1314 mCodec->mComponentName.c_str()); 1315 } 1316 1317 CHECK_LE(buffer->size(), info->mData->capacity()); 1318 memcpy(info->mData->data(), buffer->data(), buffer->size()); 1319 } 1320 1321 LOGV("[%s] calling emptyBuffer %p", 1322 mCodec->mComponentName.c_str(), bufferID); 1323 1324 CHECK_EQ(mCodec->mOMX->emptyBuffer( 1325 mCodec->mNode, 1326 bufferID, 1327 0, 1328 buffer->size(), 1329 flags, 1330 timeUs), 1331 (status_t)OK); 1332 1333 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 1334 1335 getMoreInputDataIfPossible(); 1336 } else if (!mCodec->mPortEOS[kPortIndexInput]) { 1337 LOGV("[%s] Signalling EOS on the input port", 1338 mCodec->mComponentName.c_str()); 1339 1340 LOGV("[%s] calling emptyBuffer %p", 1341 mCodec->mComponentName.c_str(), bufferID); 1342 1343 CHECK_EQ(mCodec->mOMX->emptyBuffer( 1344 mCodec->mNode, 1345 bufferID, 1346 0, 1347 0, 1348 OMX_BUFFERFLAG_EOS, 1349 0), 1350 (status_t)OK); 1351 1352 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 1353 1354 mCodec->mPortEOS[kPortIndexInput] = true; 1355 } 1356 break; 1357 1358 default: 1359 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 1360 break; 1361 } 1362 } 1363} 1364 1365void ACodec::BaseState::getMoreInputDataIfPossible() { 1366 if (mCodec->mPortEOS[kPortIndexInput]) { 1367 return; 1368 } 1369 1370 BufferInfo *eligible = NULL; 1371 1372 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 1373 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 1374 1375#if 0 1376 if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) { 1377 // There's already a "read" pending. 1378 return; 1379 } 1380#endif 1381 1382 if (info->mStatus == BufferInfo::OWNED_BY_US) { 1383 eligible = info; 1384 } 1385 } 1386 1387 if (eligible == NULL) { 1388 return; 1389 } 1390 1391 postFillThisBuffer(eligible); 1392} 1393 1394bool ACodec::BaseState::onOMXFillBufferDone( 1395 IOMX::buffer_id bufferID, 1396 size_t rangeOffset, size_t rangeLength, 1397 OMX_U32 flags, 1398 int64_t timeUs, 1399 void *platformPrivate, 1400 void *dataPtr) { 1401 LOGV("[%s] onOMXFillBufferDone %p", 1402 mCodec->mComponentName.c_str(), bufferID); 1403 1404 ssize_t index; 1405 BufferInfo *info = 1406 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 1407 1408 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); 1409 1410 info->mStatus = BufferInfo::OWNED_BY_US; 1411 1412 PortMode mode = getPortMode(kPortIndexOutput); 1413 1414 switch (mode) { 1415 case KEEP_BUFFERS: 1416 break; 1417 1418 case RESUBMIT_BUFFERS: 1419 { 1420 if (rangeLength == 0) { 1421 if (!(flags & OMX_BUFFERFLAG_EOS)) { 1422 LOGV("[%s] calling fillBuffer %p", 1423 mCodec->mComponentName.c_str(), info->mBufferID); 1424 1425 CHECK_EQ(mCodec->mOMX->fillBuffer( 1426 mCodec->mNode, info->mBufferID), 1427 (status_t)OK); 1428 1429 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 1430 } 1431 } else { 1432 if (!mCodec->mSentFormat) { 1433 mCodec->sendFormatChange(); 1434 } 1435 1436 if (mCodec->mNativeWindow == NULL) { 1437 info->mData->setRange(rangeOffset, rangeLength); 1438 } 1439 1440 info->mData->meta()->setInt64("timeUs", timeUs); 1441 1442 sp<AMessage> notify = mCodec->mNotify->dup(); 1443 notify->setInt32("what", ACodec::kWhatDrainThisBuffer); 1444 notify->setPointer("buffer-id", info->mBufferID); 1445 notify->setObject("buffer", info->mData); 1446 1447 sp<AMessage> reply = 1448 new AMessage(kWhatOutputBufferDrained, mCodec->id()); 1449 1450 reply->setPointer("buffer-id", info->mBufferID); 1451 1452 notify->setMessage("reply", reply); 1453 1454 notify->post(); 1455 1456 info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM; 1457 } 1458 1459 if (flags & OMX_BUFFERFLAG_EOS) { 1460 sp<AMessage> notify = mCodec->mNotify->dup(); 1461 notify->setInt32("what", ACodec::kWhatEOS); 1462 notify->post(); 1463 1464 mCodec->mPortEOS[kPortIndexOutput] = true; 1465 } 1466 break; 1467 } 1468 1469 default: 1470 { 1471 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 1472 1473 CHECK_EQ((status_t)OK, 1474 mCodec->freeBuffer(kPortIndexOutput, index)); 1475 break; 1476 } 1477 } 1478 1479 return true; 1480} 1481 1482void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { 1483 IOMX::buffer_id bufferID; 1484 CHECK(msg->findPointer("buffer-id", &bufferID)); 1485 1486 ssize_t index; 1487 BufferInfo *info = 1488 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 1489 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM); 1490 1491 int32_t render; 1492 if (mCodec->mNativeWindow != NULL 1493 && msg->findInt32("render", &render) && render != 0) { 1494 // The client wants this buffer to be rendered. 1495 1496 CHECK_EQ(mCodec->mNativeWindow->queueBuffer( 1497 mCodec->mNativeWindow.get(), 1498 info->mGraphicBuffer.get()), 1499 0); 1500 1501 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 1502 } else { 1503 info->mStatus = BufferInfo::OWNED_BY_US; 1504 } 1505 1506 PortMode mode = getPortMode(kPortIndexOutput); 1507 1508 switch (mode) { 1509 case KEEP_BUFFERS: 1510 { 1511 // XXX fishy, revisit!!! What about the FREE_BUFFERS case below? 1512 1513 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 1514 // We cannot resubmit the buffer we just rendered, dequeue 1515 // the spare instead. 1516 1517 info = mCodec->dequeueBufferFromNativeWindow(); 1518 } 1519 break; 1520 } 1521 1522 case RESUBMIT_BUFFERS: 1523 { 1524 if (!mCodec->mPortEOS[kPortIndexOutput]) { 1525 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 1526 // We cannot resubmit the buffer we just rendered, dequeue 1527 // the spare instead. 1528 1529 info = mCodec->dequeueBufferFromNativeWindow(); 1530 } 1531 1532 LOGV("[%s] calling fillBuffer %p", 1533 mCodec->mComponentName.c_str(), info->mBufferID); 1534 1535 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), 1536 (status_t)OK); 1537 1538 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 1539 } 1540 break; 1541 } 1542 1543 default: 1544 { 1545 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 1546 1547 CHECK_EQ((status_t)OK, 1548 mCodec->freeBuffer(kPortIndexOutput, index)); 1549 break; 1550 } 1551 } 1552} 1553 1554//////////////////////////////////////////////////////////////////////////////// 1555 1556ACodec::UninitializedState::UninitializedState(ACodec *codec) 1557 : BaseState(codec) { 1558} 1559 1560bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) { 1561 bool handled = false; 1562 1563 switch (msg->what()) { 1564 case ACodec::kWhatSetup: 1565 { 1566 onSetup(msg); 1567 1568 handled = true; 1569 break; 1570 } 1571 1572 case ACodec::kWhatShutdown: 1573 { 1574 sp<AMessage> notify = mCodec->mNotify->dup(); 1575 notify->setInt32("what", ACodec::kWhatShutdownCompleted); 1576 notify->post(); 1577 1578 handled = true; 1579 } 1580 1581 case ACodec::kWhatFlush: 1582 { 1583 sp<AMessage> notify = mCodec->mNotify->dup(); 1584 notify->setInt32("what", ACodec::kWhatFlushCompleted); 1585 notify->post(); 1586 1587 handled = true; 1588 } 1589 1590 default: 1591 return BaseState::onMessageReceived(msg); 1592 } 1593 1594 return handled; 1595} 1596 1597void ACodec::UninitializedState::onSetup( 1598 const sp<AMessage> &msg) { 1599 OMXClient client; 1600 CHECK_EQ(client.connect(), (status_t)OK); 1601 1602 sp<IOMX> omx = client.interface(); 1603 1604 AString mime; 1605 CHECK(msg->findString("mime", &mime)); 1606 1607 AString componentName; 1608 1609 if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) { 1610 componentName = "OMX.Nvidia.h264.decode"; 1611 } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) { 1612 componentName = "OMX.Nvidia.aac.decoder"; 1613 } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_MPEG)) { 1614 componentName = "OMX.Nvidia.mp3.decoder"; 1615 } else { 1616 TRESPASS(); 1617 } 1618 1619 sp<CodecObserver> observer = new CodecObserver; 1620 1621 IOMX::node_id node; 1622 CHECK_EQ(omx->allocateNode(componentName.c_str(), observer, &node), 1623 (status_t)OK); 1624 1625 sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id()); 1626 observer->setNotificationMessage(notify); 1627 1628 mCodec->mComponentName = componentName; 1629 mCodec->mOMX = omx; 1630 mCodec->mNode = node; 1631 1632 mCodec->mPortEOS[kPortIndexInput] = 1633 mCodec->mPortEOS[kPortIndexOutput] = false; 1634 1635 mCodec->configureCodec(mime.c_str(), msg); 1636 1637 sp<RefBase> obj; 1638 if (msg->findObject("native-window", &obj)) { 1639 sp<NativeWindowWrapper> nativeWindow( 1640 static_cast<NativeWindowWrapper *>(obj.get())); 1641 CHECK(nativeWindow != NULL); 1642 mCodec->mNativeWindow = nativeWindow->getNativeWindow(); 1643 } 1644 1645 CHECK_EQ((status_t)OK, mCodec->initNativeWindow()); 1646 1647 CHECK_EQ(omx->sendCommand(node, OMX_CommandStateSet, OMX_StateIdle), 1648 (status_t)OK); 1649 1650 mCodec->changeState(mCodec->mLoadedToIdleState); 1651} 1652 1653//////////////////////////////////////////////////////////////////////////////// 1654 1655ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec) 1656 : BaseState(codec) { 1657} 1658 1659void ACodec::LoadedToIdleState::stateEntered() { 1660 LOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str()); 1661 1662 CHECK_EQ(allocateBuffers(), (status_t)OK); 1663} 1664 1665status_t ACodec::LoadedToIdleState::allocateBuffers() { 1666 status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput); 1667 1668 if (err != OK) { 1669 return err; 1670 } 1671 1672 return mCodec->allocateBuffersOnPort(kPortIndexOutput); 1673} 1674 1675bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) { 1676 switch (msg->what()) { 1677 case kWhatShutdown: 1678 { 1679 mCodec->deferMessage(msg); 1680 return true; 1681 } 1682 1683 default: 1684 return BaseState::onMessageReceived(msg); 1685 } 1686} 1687 1688bool ACodec::LoadedToIdleState::onOMXEvent( 1689 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 1690 switch (event) { 1691 case OMX_EventCmdComplete: 1692 { 1693 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 1694 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); 1695 1696 CHECK_EQ(mCodec->mOMX->sendCommand( 1697 mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting), 1698 (status_t)OK); 1699 1700 mCodec->changeState(mCodec->mIdleToExecutingState); 1701 1702 return true; 1703 } 1704 1705 default: 1706 return BaseState::onOMXEvent(event, data1, data2); 1707 } 1708} 1709 1710//////////////////////////////////////////////////////////////////////////////// 1711 1712ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec) 1713 : BaseState(codec) { 1714} 1715 1716void ACodec::IdleToExecutingState::stateEntered() { 1717 LOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str()); 1718} 1719 1720bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) { 1721 switch (msg->what()) { 1722 case kWhatShutdown: 1723 { 1724 mCodec->deferMessage(msg); 1725 return true; 1726 } 1727 1728 default: 1729 return BaseState::onMessageReceived(msg); 1730 } 1731} 1732 1733bool ACodec::IdleToExecutingState::onOMXEvent( 1734 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 1735 switch (event) { 1736 case OMX_EventCmdComplete: 1737 { 1738 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 1739 CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting); 1740 1741 mCodec->mExecutingState->resume(); 1742 mCodec->changeState(mCodec->mExecutingState); 1743 1744 return true; 1745 } 1746 1747 default: 1748 return BaseState::onOMXEvent(event, data1, data2); 1749 } 1750} 1751 1752//////////////////////////////////////////////////////////////////////////////// 1753 1754ACodec::ExecutingState::ExecutingState(ACodec *codec) 1755 : BaseState(codec), 1756 mActive(false) { 1757} 1758 1759ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode( 1760 OMX_U32 portIndex) { 1761 return RESUBMIT_BUFFERS; 1762} 1763 1764void ACodec::ExecutingState::submitOutputBuffers() { 1765 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) { 1766 BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i); 1767 1768 if (mCodec->mNativeWindow != NULL) { 1769 CHECK(info->mStatus == BufferInfo::OWNED_BY_US 1770 || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW); 1771 1772 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 1773 continue; 1774 } 1775 1776 status_t err = mCodec->mNativeWindow->lockBuffer( 1777 mCodec->mNativeWindow.get(), 1778 info->mGraphicBuffer.get()); 1779 CHECK_EQ(err, (status_t)OK); 1780 } else { 1781 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 1782 } 1783 1784 LOGV("[%s] calling fillBuffer %p", 1785 mCodec->mComponentName.c_str(), info->mBufferID); 1786 1787 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), 1788 (status_t)OK); 1789 1790 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 1791 } 1792} 1793 1794void ACodec::ExecutingState::resume() { 1795 if (mActive) { 1796 LOGV("[%s] We're already active, no need to resume.", 1797 mCodec->mComponentName.c_str()); 1798 1799 return; 1800 } 1801 1802 submitOutputBuffers(); 1803 1804 // Post the first input buffer. 1805 CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u); 1806 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0); 1807 1808 postFillThisBuffer(info); 1809 1810 mActive = true; 1811} 1812 1813void ACodec::ExecutingState::stateEntered() { 1814 LOGV("[%s] Now Executing", mCodec->mComponentName.c_str()); 1815 1816 mCodec->processDeferredMessages(); 1817} 1818 1819bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) { 1820 bool handled = false; 1821 1822 switch (msg->what()) { 1823 case kWhatShutdown: 1824 { 1825 mActive = false; 1826 1827 CHECK_EQ(mCodec->mOMX->sendCommand( 1828 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle), 1829 (status_t)OK); 1830 1831 mCodec->changeState(mCodec->mExecutingToIdleState); 1832 1833 handled = true; 1834 break; 1835 } 1836 1837 case kWhatFlush: 1838 { 1839 mActive = false; 1840 1841 CHECK_EQ(mCodec->mOMX->sendCommand( 1842 mCodec->mNode, OMX_CommandFlush, OMX_ALL), 1843 (status_t)OK); 1844 1845 mCodec->changeState(mCodec->mFlushingState); 1846 1847 handled = true; 1848 break; 1849 } 1850 1851 case kWhatResume: 1852 { 1853 resume(); 1854 1855 handled = true; 1856 break; 1857 } 1858 1859 default: 1860 handled = BaseState::onMessageReceived(msg); 1861 break; 1862 } 1863 1864 return handled; 1865} 1866 1867bool ACodec::ExecutingState::onOMXEvent( 1868 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 1869 switch (event) { 1870 case OMX_EventPortSettingsChanged: 1871 { 1872 CHECK_EQ(data1, (OMX_U32)kPortIndexOutput); 1873 1874 if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) { 1875 CHECK_EQ(mCodec->mOMX->sendCommand( 1876 mCodec->mNode, 1877 OMX_CommandPortDisable, kPortIndexOutput), 1878 (status_t)OK); 1879 1880 mCodec->freeOutputBuffersNotOwnedByComponent(); 1881 1882 mCodec->changeState(mCodec->mOutputPortSettingsChangedState); 1883 } else if (data2 == OMX_IndexConfigCommonOutputCrop) { 1884 mCodec->mSentFormat = false; 1885 } else { 1886 LOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx", 1887 mCodec->mComponentName.c_str(), data2); 1888 } 1889 1890 return true; 1891 } 1892 1893 case OMX_EventBufferFlag: 1894 { 1895 return true; 1896 } 1897 1898 default: 1899 return BaseState::onOMXEvent(event, data1, data2); 1900 } 1901} 1902 1903//////////////////////////////////////////////////////////////////////////////// 1904 1905ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState( 1906 ACodec *codec) 1907 : BaseState(codec) { 1908} 1909 1910ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode( 1911 OMX_U32 portIndex) { 1912 if (portIndex == kPortIndexOutput) { 1913 return FREE_BUFFERS; 1914 } 1915 1916 CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput); 1917 1918 return RESUBMIT_BUFFERS; 1919} 1920 1921bool ACodec::OutputPortSettingsChangedState::onMessageReceived( 1922 const sp<AMessage> &msg) { 1923 bool handled = false; 1924 1925 switch (msg->what()) { 1926 case kWhatFlush: 1927 case kWhatShutdown: 1928 case kWhatResume: 1929 { 1930 if (msg->what() == kWhatResume) { 1931 LOGV("[%s] Deferring resume", mCodec->mComponentName.c_str()); 1932 } 1933 1934 mCodec->deferMessage(msg); 1935 handled = true; 1936 break; 1937 } 1938 1939 default: 1940 handled = BaseState::onMessageReceived(msg); 1941 break; 1942 } 1943 1944 return handled; 1945} 1946 1947void ACodec::OutputPortSettingsChangedState::stateEntered() { 1948 LOGV("[%s] Now handling output port settings change", 1949 mCodec->mComponentName.c_str()); 1950} 1951 1952bool ACodec::OutputPortSettingsChangedState::onOMXEvent( 1953 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 1954 switch (event) { 1955 case OMX_EventCmdComplete: 1956 { 1957 if (data1 == (OMX_U32)OMX_CommandPortDisable) { 1958 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput); 1959 1960 LOGV("[%s] Output port now disabled.", 1961 mCodec->mComponentName.c_str()); 1962 1963 CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty()); 1964 mCodec->mDealer[kPortIndexOutput].clear(); 1965 1966 CHECK_EQ(mCodec->mOMX->sendCommand( 1967 mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput), 1968 (status_t)OK); 1969 1970 CHECK_EQ(mCodec->allocateBuffersOnPort(kPortIndexOutput), 1971 (status_t)OK); 1972 1973 return true; 1974 } else if (data1 == (OMX_U32)OMX_CommandPortEnable) { 1975 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput); 1976 1977 mCodec->mSentFormat = false; 1978 1979 LOGV("[%s] Output port now reenabled.", 1980 mCodec->mComponentName.c_str()); 1981 1982 if (mCodec->mExecutingState->active()) { 1983 mCodec->mExecutingState->submitOutputBuffers(); 1984 } 1985 1986 mCodec->changeState(mCodec->mExecutingState); 1987 1988 return true; 1989 } 1990 1991 return false; 1992 } 1993 1994 default: 1995 return false; 1996 } 1997} 1998 1999//////////////////////////////////////////////////////////////////////////////// 2000 2001ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec) 2002 : BaseState(codec) { 2003} 2004 2005bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) { 2006 bool handled = false; 2007 2008 switch (msg->what()) { 2009 case kWhatFlush: 2010 { 2011 // Don't send me a flush request if you previously wanted me 2012 // to shutdown. 2013 TRESPASS(); 2014 break; 2015 } 2016 2017 case kWhatShutdown: 2018 { 2019 // We're already doing that... 2020 2021 handled = true; 2022 break; 2023 } 2024 2025 default: 2026 handled = BaseState::onMessageReceived(msg); 2027 break; 2028 } 2029 2030 return handled; 2031} 2032 2033void ACodec::ExecutingToIdleState::stateEntered() { 2034 LOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str()); 2035 2036 mCodec->mSentFormat = false; 2037} 2038 2039bool ACodec::ExecutingToIdleState::onOMXEvent( 2040 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 2041 switch (event) { 2042 case OMX_EventCmdComplete: 2043 { 2044 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 2045 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); 2046 2047 changeStateIfWeOwnAllBuffers(); 2048 2049 return true; 2050 } 2051 2052 case OMX_EventPortSettingsChanged: 2053 case OMX_EventBufferFlag: 2054 { 2055 // We're shutting down and don't care about this anymore. 2056 return true; 2057 } 2058 2059 default: 2060 return BaseState::onOMXEvent(event, data1, data2); 2061 } 2062} 2063void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() { 2064 if (mCodec->allYourBuffersAreBelongToUs()) { 2065 CHECK_EQ(mCodec->mOMX->sendCommand( 2066 mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded), 2067 (status_t)OK); 2068 2069 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK); 2070 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK); 2071 2072 mCodec->changeState(mCodec->mIdleToLoadedState); 2073 } 2074} 2075 2076void ACodec::ExecutingToIdleState::onInputBufferFilled( 2077 const sp<AMessage> &msg) { 2078 BaseState::onInputBufferFilled(msg); 2079 2080 changeStateIfWeOwnAllBuffers(); 2081} 2082 2083void ACodec::ExecutingToIdleState::onOutputBufferDrained( 2084 const sp<AMessage> &msg) { 2085 BaseState::onOutputBufferDrained(msg); 2086 2087 changeStateIfWeOwnAllBuffers(); 2088} 2089 2090//////////////////////////////////////////////////////////////////////////////// 2091 2092ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec) 2093 : BaseState(codec) { 2094} 2095 2096bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) { 2097 bool handled = false; 2098 2099 switch (msg->what()) { 2100 case kWhatShutdown: 2101 { 2102 // We're already doing that... 2103 2104 handled = true; 2105 break; 2106 } 2107 2108 case kWhatFlush: 2109 { 2110 // Don't send me a flush request if you previously wanted me 2111 // to shutdown. 2112 TRESPASS(); 2113 break; 2114 } 2115 2116 default: 2117 handled = BaseState::onMessageReceived(msg); 2118 break; 2119 } 2120 2121 return handled; 2122} 2123 2124void ACodec::IdleToLoadedState::stateEntered() { 2125 LOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str()); 2126} 2127 2128bool ACodec::IdleToLoadedState::onOMXEvent( 2129 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 2130 switch (event) { 2131 case OMX_EventCmdComplete: 2132 { 2133 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 2134 CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded); 2135 2136 LOGV("[%s] Now Loaded", mCodec->mComponentName.c_str()); 2137 2138 CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK); 2139 2140 mCodec->mNativeWindow.clear(); 2141 mCodec->mNode = NULL; 2142 mCodec->mOMX.clear(); 2143 mCodec->mComponentName.clear(); 2144 2145 mCodec->changeState(mCodec->mUninitializedState); 2146 2147 sp<AMessage> notify = mCodec->mNotify->dup(); 2148 notify->setInt32("what", ACodec::kWhatShutdownCompleted); 2149 notify->post(); 2150 2151 return true; 2152 } 2153 2154 default: 2155 return BaseState::onOMXEvent(event, data1, data2); 2156 } 2157} 2158 2159//////////////////////////////////////////////////////////////////////////////// 2160 2161ACodec::ErrorState::ErrorState(ACodec *codec) 2162 : BaseState(codec) { 2163} 2164 2165bool ACodec::ErrorState::onMessageReceived(const sp<AMessage> &msg) { 2166 return BaseState::onMessageReceived(msg); 2167} 2168 2169void ACodec::ErrorState::stateEntered() { 2170 LOGV("[%s] Now in ErrorState", mCodec->mComponentName.c_str()); 2171} 2172 2173bool ACodec::ErrorState::onOMXEvent( 2174 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 2175 LOGV("EVENT(%d, 0x%08lx, 0x%08lx)", event, data1, data2); 2176 return true; 2177} 2178 2179//////////////////////////////////////////////////////////////////////////////// 2180 2181ACodec::FlushingState::FlushingState(ACodec *codec) 2182 : BaseState(codec) { 2183} 2184 2185void ACodec::FlushingState::stateEntered() { 2186 LOGV("[%s] Now Flushing", mCodec->mComponentName.c_str()); 2187 2188 mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false; 2189} 2190 2191bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) { 2192 bool handled = false; 2193 2194 switch (msg->what()) { 2195 case kWhatShutdown: 2196 { 2197 mCodec->deferMessage(msg); 2198 break; 2199 } 2200 2201 case kWhatFlush: 2202 { 2203 // We're already doing this right now. 2204 handled = true; 2205 break; 2206 } 2207 2208 default: 2209 handled = BaseState::onMessageReceived(msg); 2210 break; 2211 } 2212 2213 return handled; 2214} 2215 2216bool ACodec::FlushingState::onOMXEvent( 2217 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 2218 switch (event) { 2219 case OMX_EventCmdComplete: 2220 { 2221 CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush); 2222 2223 if (data2 == kPortIndexInput || data2 == kPortIndexOutput) { 2224 CHECK(!mFlushComplete[data2]); 2225 mFlushComplete[data2] = true; 2226 } else { 2227 CHECK_EQ(data2, OMX_ALL); 2228 CHECK(mFlushComplete[kPortIndexInput]); 2229 CHECK(mFlushComplete[kPortIndexOutput]); 2230 2231 changeStateIfWeOwnAllBuffers(); 2232 } 2233 2234 return true; 2235 } 2236 2237 case OMX_EventPortSettingsChanged: 2238 { 2239 sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id()); 2240 msg->setInt32("type", omx_message::EVENT); 2241 msg->setPointer("node", mCodec->mNode); 2242 msg->setInt32("event", event); 2243 msg->setInt32("data1", data1); 2244 msg->setInt32("data2", data2); 2245 2246 LOGV("[%s] Deferring OMX_EventPortSettingsChanged", 2247 mCodec->mComponentName.c_str()); 2248 2249 mCodec->deferMessage(msg); 2250 2251 return true; 2252 } 2253 2254 default: 2255 return BaseState::onOMXEvent(event, data1, data2); 2256 } 2257 2258 return true; 2259} 2260 2261void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) { 2262 BaseState::onOutputBufferDrained(msg); 2263 2264 changeStateIfWeOwnAllBuffers(); 2265} 2266 2267void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) { 2268 BaseState::onInputBufferFilled(msg); 2269 2270 changeStateIfWeOwnAllBuffers(); 2271} 2272 2273void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() { 2274 if (mFlushComplete[kPortIndexInput] 2275 && mFlushComplete[kPortIndexOutput] 2276 && mCodec->allYourBuffersAreBelongToUs()) { 2277 sp<AMessage> notify = mCodec->mNotify->dup(); 2278 notify->setInt32("what", ACodec::kWhatFlushCompleted); 2279 notify->post(); 2280 2281 mCodec->mPortEOS[kPortIndexInput] = 2282 mCodec->mPortEOS[kPortIndexOutput] = false; 2283 2284 mCodec->changeState(mCodec->mExecutingState); 2285 } 2286} 2287 2288} // namespace android 2289 2290