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