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