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