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