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