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