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