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