ACodec.cpp revision cc54fbaa69c0b69929467449d2c19192f15b5039
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 1134void ACodec::signalError(OMX_ERRORTYPE error) { 1135 sp<AMessage> notify = mNotify->dup(); 1136 notify->setInt32("what", ACodec::kWhatError); 1137 notify->setInt32("omx-error", error); 1138 notify->post(); 1139} 1140 1141//////////////////////////////////////////////////////////////////////////////// 1142 1143ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState) 1144 : AState(parentState), 1145 mCodec(codec) { 1146} 1147 1148ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(OMX_U32 portIndex) { 1149 return KEEP_BUFFERS; 1150} 1151 1152bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) { 1153 switch (msg->what()) { 1154 case kWhatInputBufferFilled: 1155 { 1156 onInputBufferFilled(msg); 1157 break; 1158 } 1159 1160 case kWhatOutputBufferDrained: 1161 { 1162 onOutputBufferDrained(msg); 1163 break; 1164 } 1165 1166 case ACodec::kWhatOMXMessage: 1167 { 1168 return onOMXMessage(msg); 1169 } 1170 1171 default: 1172 return false; 1173 } 1174 1175 return true; 1176} 1177 1178bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) { 1179 int32_t type; 1180 CHECK(msg->findInt32("type", &type)); 1181 1182 IOMX::node_id nodeID; 1183 CHECK(msg->findPointer("node", &nodeID)); 1184 CHECK_EQ(nodeID, mCodec->mNode); 1185 1186 switch (type) { 1187 case omx_message::EVENT: 1188 { 1189 int32_t event, data1, data2; 1190 CHECK(msg->findInt32("event", &event)); 1191 CHECK(msg->findInt32("data1", &data1)); 1192 CHECK(msg->findInt32("data2", &data2)); 1193 1194 if (event == OMX_EventCmdComplete 1195 && data1 == OMX_CommandFlush 1196 && data2 == (int32_t)OMX_ALL) { 1197 // Use of this notification is not consistent across 1198 // implementations. We'll drop this notification and rely 1199 // on flush-complete notifications on the individual port 1200 // indices instead. 1201 1202 return true; 1203 } 1204 1205 return onOMXEvent( 1206 static_cast<OMX_EVENTTYPE>(event), 1207 static_cast<OMX_U32>(data1), 1208 static_cast<OMX_U32>(data2)); 1209 } 1210 1211 case omx_message::EMPTY_BUFFER_DONE: 1212 { 1213 IOMX::buffer_id bufferID; 1214 CHECK(msg->findPointer("buffer", &bufferID)); 1215 1216 return onOMXEmptyBufferDone(bufferID); 1217 } 1218 1219 case omx_message::FILL_BUFFER_DONE: 1220 { 1221 IOMX::buffer_id bufferID; 1222 CHECK(msg->findPointer("buffer", &bufferID)); 1223 1224 int32_t rangeOffset, rangeLength, flags; 1225 int64_t timeUs; 1226 void *platformPrivate; 1227 void *dataPtr; 1228 1229 CHECK(msg->findInt32("range_offset", &rangeOffset)); 1230 CHECK(msg->findInt32("range_length", &rangeLength)); 1231 CHECK(msg->findInt32("flags", &flags)); 1232 CHECK(msg->findInt64("timestamp", &timeUs)); 1233 CHECK(msg->findPointer("platform_private", &platformPrivate)); 1234 CHECK(msg->findPointer("data_ptr", &dataPtr)); 1235 1236 return onOMXFillBufferDone( 1237 bufferID, 1238 (size_t)rangeOffset, (size_t)rangeLength, 1239 (OMX_U32)flags, 1240 timeUs, 1241 platformPrivate, 1242 dataPtr); 1243 } 1244 1245 default: 1246 TRESPASS(); 1247 break; 1248 } 1249} 1250 1251bool ACodec::BaseState::onOMXEvent( 1252 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 1253 if (event != OMX_EventError) { 1254 LOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)", 1255 mCodec->mComponentName.c_str(), event, data1, data2); 1256 1257 return false; 1258 } 1259 1260 LOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1); 1261 1262 mCodec->signalError((OMX_ERRORTYPE)data1); 1263 1264 return true; 1265} 1266 1267bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) { 1268 LOGV("[%s] onOMXEmptyBufferDone %p", 1269 mCodec->mComponentName.c_str(), bufferID); 1270 1271 BufferInfo *info = 1272 mCodec->findBufferByID(kPortIndexInput, bufferID); 1273 1274 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); 1275 info->mStatus = BufferInfo::OWNED_BY_US; 1276 1277 PortMode mode = getPortMode(kPortIndexInput); 1278 1279 switch (mode) { 1280 case KEEP_BUFFERS: 1281 break; 1282 1283 case RESUBMIT_BUFFERS: 1284 postFillThisBuffer(info); 1285 break; 1286 1287 default: 1288 { 1289 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 1290 TRESPASS(); // Not currently used 1291 break; 1292 } 1293 } 1294 1295 return true; 1296} 1297 1298void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) { 1299 if (mCodec->mPortEOS[kPortIndexInput]) { 1300 return; 1301 } 1302 1303 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 1304 1305 sp<AMessage> notify = mCodec->mNotify->dup(); 1306 notify->setInt32("what", ACodec::kWhatFillThisBuffer); 1307 notify->setPointer("buffer-id", info->mBufferID); 1308 1309 info->mData->meta()->clear(); 1310 notify->setObject("buffer", info->mData); 1311 1312 sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id()); 1313 reply->setPointer("buffer-id", info->mBufferID); 1314 1315 notify->setMessage("reply", reply); 1316 1317 notify->post(); 1318 1319 info->mStatus = BufferInfo::OWNED_BY_UPSTREAM; 1320} 1321 1322void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { 1323 IOMX::buffer_id bufferID; 1324 CHECK(msg->findPointer("buffer-id", &bufferID)); 1325 1326 sp<RefBase> obj; 1327 int32_t err = OK; 1328 if (!msg->findObject("buffer", &obj)) { 1329 CHECK(msg->findInt32("err", &err)); 1330 1331 LOGV("[%s] saw error %d instead of an input buffer", 1332 mCodec->mComponentName.c_str(), err); 1333 1334 obj.clear(); 1335 } 1336 1337 sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get()); 1338 1339 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID); 1340 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM); 1341 1342 info->mStatus = BufferInfo::OWNED_BY_US; 1343 1344 PortMode mode = getPortMode(kPortIndexInput); 1345 1346 switch (mode) { 1347 case KEEP_BUFFERS: 1348 { 1349 if (buffer == NULL) { 1350 mCodec->mPortEOS[kPortIndexInput] = true; 1351 } 1352 break; 1353 } 1354 1355 case RESUBMIT_BUFFERS: 1356 { 1357 if (buffer != NULL) { 1358 CHECK(!mCodec->mPortEOS[kPortIndexInput]); 1359 1360 int64_t timeUs; 1361 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 1362 1363 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME; 1364 1365 int32_t isCSD; 1366 if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) { 1367 flags |= OMX_BUFFERFLAG_CODECCONFIG; 1368 } 1369 1370 if (buffer != info->mData) { 1371 if (0 && !(flags & OMX_BUFFERFLAG_CODECCONFIG)) { 1372 LOGV("[%s] Needs to copy input data.", 1373 mCodec->mComponentName.c_str()); 1374 } 1375 1376 CHECK_LE(buffer->size(), info->mData->capacity()); 1377 memcpy(info->mData->data(), buffer->data(), buffer->size()); 1378 } 1379 1380 LOGV("[%s] calling emptyBuffer %p", 1381 mCodec->mComponentName.c_str(), bufferID); 1382 1383 CHECK_EQ(mCodec->mOMX->emptyBuffer( 1384 mCodec->mNode, 1385 bufferID, 1386 0, 1387 buffer->size(), 1388 flags, 1389 timeUs), 1390 (status_t)OK); 1391 1392 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 1393 1394 getMoreInputDataIfPossible(); 1395 } else if (!mCodec->mPortEOS[kPortIndexInput]) { 1396 LOGV("[%s] Signalling EOS on the input port", 1397 mCodec->mComponentName.c_str()); 1398 1399 LOGV("[%s] calling emptyBuffer %p", 1400 mCodec->mComponentName.c_str(), bufferID); 1401 1402 CHECK_EQ(mCodec->mOMX->emptyBuffer( 1403 mCodec->mNode, 1404 bufferID, 1405 0, 1406 0, 1407 OMX_BUFFERFLAG_EOS, 1408 0), 1409 (status_t)OK); 1410 1411 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 1412 1413 mCodec->mPortEOS[kPortIndexInput] = true; 1414 } 1415 break; 1416 1417 default: 1418 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 1419 break; 1420 } 1421 } 1422} 1423 1424void ACodec::BaseState::getMoreInputDataIfPossible() { 1425 if (mCodec->mPortEOS[kPortIndexInput]) { 1426 return; 1427 } 1428 1429 BufferInfo *eligible = NULL; 1430 1431 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 1432 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 1433 1434#if 0 1435 if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) { 1436 // There's already a "read" pending. 1437 return; 1438 } 1439#endif 1440 1441 if (info->mStatus == BufferInfo::OWNED_BY_US) { 1442 eligible = info; 1443 } 1444 } 1445 1446 if (eligible == NULL) { 1447 return; 1448 } 1449 1450 postFillThisBuffer(eligible); 1451} 1452 1453bool ACodec::BaseState::onOMXFillBufferDone( 1454 IOMX::buffer_id bufferID, 1455 size_t rangeOffset, size_t rangeLength, 1456 OMX_U32 flags, 1457 int64_t timeUs, 1458 void *platformPrivate, 1459 void *dataPtr) { 1460 LOGV("[%s] onOMXFillBufferDone %p", 1461 mCodec->mComponentName.c_str(), bufferID); 1462 1463 ssize_t index; 1464 BufferInfo *info = 1465 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 1466 1467 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); 1468 1469 info->mStatus = BufferInfo::OWNED_BY_US; 1470 1471 PortMode mode = getPortMode(kPortIndexOutput); 1472 1473 switch (mode) { 1474 case KEEP_BUFFERS: 1475 break; 1476 1477 case RESUBMIT_BUFFERS: 1478 { 1479 if (rangeLength == 0) { 1480 if (!(flags & OMX_BUFFERFLAG_EOS)) { 1481 LOGV("[%s] calling fillBuffer %p", 1482 mCodec->mComponentName.c_str(), info->mBufferID); 1483 1484 CHECK_EQ(mCodec->mOMX->fillBuffer( 1485 mCodec->mNode, info->mBufferID), 1486 (status_t)OK); 1487 1488 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 1489 } 1490 } else { 1491 if (!mCodec->mSentFormat) { 1492 mCodec->sendFormatChange(); 1493 } 1494 1495 if (mCodec->mNativeWindow == NULL) { 1496 info->mData->setRange(rangeOffset, rangeLength); 1497 } 1498 1499 info->mData->meta()->setInt64("timeUs", timeUs); 1500 1501 sp<AMessage> notify = mCodec->mNotify->dup(); 1502 notify->setInt32("what", ACodec::kWhatDrainThisBuffer); 1503 notify->setPointer("buffer-id", info->mBufferID); 1504 notify->setObject("buffer", info->mData); 1505 1506 sp<AMessage> reply = 1507 new AMessage(kWhatOutputBufferDrained, mCodec->id()); 1508 1509 reply->setPointer("buffer-id", info->mBufferID); 1510 1511 notify->setMessage("reply", reply); 1512 1513 notify->post(); 1514 1515 info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM; 1516 } 1517 1518 if (flags & OMX_BUFFERFLAG_EOS) { 1519 sp<AMessage> notify = mCodec->mNotify->dup(); 1520 notify->setInt32("what", ACodec::kWhatEOS); 1521 notify->post(); 1522 1523 mCodec->mPortEOS[kPortIndexOutput] = true; 1524 } 1525 break; 1526 } 1527 1528 default: 1529 { 1530 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 1531 1532 CHECK_EQ((status_t)OK, 1533 mCodec->freeBuffer(kPortIndexOutput, index)); 1534 break; 1535 } 1536 } 1537 1538 return true; 1539} 1540 1541void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { 1542 IOMX::buffer_id bufferID; 1543 CHECK(msg->findPointer("buffer-id", &bufferID)); 1544 1545 ssize_t index; 1546 BufferInfo *info = 1547 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 1548 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM); 1549 1550 int32_t render; 1551 if (mCodec->mNativeWindow != NULL 1552 && msg->findInt32("render", &render) && render != 0) { 1553 // The client wants this buffer to be rendered. 1554 1555 if (mCodec->mNativeWindow->queueBuffer( 1556 mCodec->mNativeWindow.get(), 1557 info->mGraphicBuffer.get()) == OK) { 1558 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 1559 } else { 1560 mCodec->signalError(); 1561 info->mStatus = BufferInfo::OWNED_BY_US; 1562 } 1563 } else { 1564 info->mStatus = BufferInfo::OWNED_BY_US; 1565 } 1566 1567 PortMode mode = getPortMode(kPortIndexOutput); 1568 1569 switch (mode) { 1570 case KEEP_BUFFERS: 1571 { 1572 // XXX fishy, revisit!!! What about the FREE_BUFFERS case below? 1573 1574 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 1575 // We cannot resubmit the buffer we just rendered, dequeue 1576 // the spare instead. 1577 1578 info = mCodec->dequeueBufferFromNativeWindow(); 1579 } 1580 break; 1581 } 1582 1583 case RESUBMIT_BUFFERS: 1584 { 1585 if (!mCodec->mPortEOS[kPortIndexOutput]) { 1586 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 1587 // We cannot resubmit the buffer we just rendered, dequeue 1588 // the spare instead. 1589 1590 info = mCodec->dequeueBufferFromNativeWindow(); 1591 } 1592 1593 if (info != NULL) { 1594 LOGV("[%s] calling fillBuffer %p", 1595 mCodec->mComponentName.c_str(), info->mBufferID); 1596 1597 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), 1598 (status_t)OK); 1599 1600 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 1601 } 1602 } 1603 break; 1604 } 1605 1606 default: 1607 { 1608 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 1609 1610 CHECK_EQ((status_t)OK, 1611 mCodec->freeBuffer(kPortIndexOutput, index)); 1612 break; 1613 } 1614 } 1615} 1616 1617//////////////////////////////////////////////////////////////////////////////// 1618 1619ACodec::UninitializedState::UninitializedState(ACodec *codec) 1620 : BaseState(codec) { 1621} 1622 1623bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) { 1624 bool handled = false; 1625 1626 switch (msg->what()) { 1627 case ACodec::kWhatSetup: 1628 { 1629 onSetup(msg); 1630 1631 handled = true; 1632 break; 1633 } 1634 1635 case ACodec::kWhatShutdown: 1636 { 1637 sp<AMessage> notify = mCodec->mNotify->dup(); 1638 notify->setInt32("what", ACodec::kWhatShutdownCompleted); 1639 notify->post(); 1640 1641 handled = true; 1642 break; 1643 } 1644 1645 case ACodec::kWhatFlush: 1646 { 1647 sp<AMessage> notify = mCodec->mNotify->dup(); 1648 notify->setInt32("what", ACodec::kWhatFlushCompleted); 1649 notify->post(); 1650 1651 handled = true; 1652 break; 1653 } 1654 1655 default: 1656 return BaseState::onMessageReceived(msg); 1657 } 1658 1659 return handled; 1660} 1661 1662void ACodec::UninitializedState::onSetup( 1663 const sp<AMessage> &msg) { 1664 OMXClient client; 1665 CHECK_EQ(client.connect(), (status_t)OK); 1666 1667 sp<IOMX> omx = client.interface(); 1668 1669 AString mime; 1670 CHECK(msg->findString("mime", &mime)); 1671 1672 Vector<String8> matchingCodecs; 1673 OMXCodec::findMatchingCodecs( 1674 mime.c_str(), 1675 false, // createEncoder 1676 NULL, // matchComponentName 1677 0, // flags 1678 &matchingCodecs); 1679 1680 sp<CodecObserver> observer = new CodecObserver; 1681 IOMX::node_id node = NULL; 1682 1683 AString componentName; 1684 1685 for (size_t matchIndex = 0; matchIndex < matchingCodecs.size(); 1686 ++matchIndex) { 1687 componentName = matchingCodecs.itemAt(matchIndex).string(); 1688 1689 status_t err = omx->allocateNode(componentName.c_str(), observer, &node); 1690 1691 if (err == OK) { 1692 break; 1693 } 1694 1695 node = NULL; 1696 } 1697 1698 if (node == NULL) { 1699 LOGE("Unable to instantiate a decoder for type '%s'.", mime.c_str()); 1700 1701 mCodec->signalError(OMX_ErrorComponentNotFound); 1702 return; 1703 } 1704 1705 sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id()); 1706 observer->setNotificationMessage(notify); 1707 1708 mCodec->mComponentName = componentName; 1709 mCodec->mOMX = omx; 1710 mCodec->mNode = node; 1711 1712 mCodec->mPortEOS[kPortIndexInput] = 1713 mCodec->mPortEOS[kPortIndexOutput] = false; 1714 1715 mCodec->configureCodec(mime.c_str(), msg); 1716 1717 sp<RefBase> obj; 1718 if (msg->findObject("native-window", &obj) 1719 && strncmp("OMX.google.", componentName.c_str(), 11)) { 1720 sp<NativeWindowWrapper> nativeWindow( 1721 static_cast<NativeWindowWrapper *>(obj.get())); 1722 CHECK(nativeWindow != NULL); 1723 mCodec->mNativeWindow = nativeWindow->getNativeWindow(); 1724 } 1725 1726 CHECK_EQ((status_t)OK, mCodec->initNativeWindow()); 1727 1728 CHECK_EQ(omx->sendCommand(node, OMX_CommandStateSet, OMX_StateIdle), 1729 (status_t)OK); 1730 1731 mCodec->changeState(mCodec->mLoadedToIdleState); 1732} 1733 1734//////////////////////////////////////////////////////////////////////////////// 1735 1736ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec) 1737 : BaseState(codec) { 1738} 1739 1740void ACodec::LoadedToIdleState::stateEntered() { 1741 LOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str()); 1742 1743 status_t err; 1744 if ((err = allocateBuffers()) != OK) { 1745 LOGE("Failed to allocate buffers after transitioning to IDLE state " 1746 "(error 0x%08x)", 1747 err); 1748 1749 mCodec->signalError(); 1750 } 1751} 1752 1753status_t ACodec::LoadedToIdleState::allocateBuffers() { 1754 status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput); 1755 1756 if (err != OK) { 1757 return err; 1758 } 1759 1760 return mCodec->allocateBuffersOnPort(kPortIndexOutput); 1761} 1762 1763bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) { 1764 switch (msg->what()) { 1765 case kWhatShutdown: 1766 { 1767 mCodec->deferMessage(msg); 1768 return true; 1769 } 1770 1771 default: 1772 return BaseState::onMessageReceived(msg); 1773 } 1774} 1775 1776bool ACodec::LoadedToIdleState::onOMXEvent( 1777 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 1778 switch (event) { 1779 case OMX_EventCmdComplete: 1780 { 1781 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 1782 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); 1783 1784 CHECK_EQ(mCodec->mOMX->sendCommand( 1785 mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting), 1786 (status_t)OK); 1787 1788 mCodec->changeState(mCodec->mIdleToExecutingState); 1789 1790 return true; 1791 } 1792 1793 default: 1794 return BaseState::onOMXEvent(event, data1, data2); 1795 } 1796} 1797 1798//////////////////////////////////////////////////////////////////////////////// 1799 1800ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec) 1801 : BaseState(codec) { 1802} 1803 1804void ACodec::IdleToExecutingState::stateEntered() { 1805 LOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str()); 1806} 1807 1808bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) { 1809 switch (msg->what()) { 1810 case kWhatShutdown: 1811 { 1812 mCodec->deferMessage(msg); 1813 return true; 1814 } 1815 1816 default: 1817 return BaseState::onMessageReceived(msg); 1818 } 1819} 1820 1821bool ACodec::IdleToExecutingState::onOMXEvent( 1822 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 1823 switch (event) { 1824 case OMX_EventCmdComplete: 1825 { 1826 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 1827 CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting); 1828 1829 mCodec->mExecutingState->resume(); 1830 mCodec->changeState(mCodec->mExecutingState); 1831 1832 return true; 1833 } 1834 1835 default: 1836 return BaseState::onOMXEvent(event, data1, data2); 1837 } 1838} 1839 1840//////////////////////////////////////////////////////////////////////////////// 1841 1842ACodec::ExecutingState::ExecutingState(ACodec *codec) 1843 : BaseState(codec), 1844 mActive(false) { 1845} 1846 1847ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode( 1848 OMX_U32 portIndex) { 1849 return RESUBMIT_BUFFERS; 1850} 1851 1852void ACodec::ExecutingState::submitOutputBuffers() { 1853 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) { 1854 BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i); 1855 1856 if (mCodec->mNativeWindow != NULL) { 1857 CHECK(info->mStatus == BufferInfo::OWNED_BY_US 1858 || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW); 1859 1860 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 1861 continue; 1862 } 1863 1864 status_t err = mCodec->mNativeWindow->lockBuffer( 1865 mCodec->mNativeWindow.get(), 1866 info->mGraphicBuffer.get()); 1867 CHECK_EQ(err, (status_t)OK); 1868 } else { 1869 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 1870 } 1871 1872 LOGV("[%s] calling fillBuffer %p", 1873 mCodec->mComponentName.c_str(), info->mBufferID); 1874 1875 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), 1876 (status_t)OK); 1877 1878 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 1879 } 1880} 1881 1882void ACodec::ExecutingState::resume() { 1883 if (mActive) { 1884 LOGV("[%s] We're already active, no need to resume.", 1885 mCodec->mComponentName.c_str()); 1886 1887 return; 1888 } 1889 1890 submitOutputBuffers(); 1891 1892 // Post the first input buffer. 1893 CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u); 1894 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0); 1895 1896 postFillThisBuffer(info); 1897 1898 mActive = true; 1899} 1900 1901void ACodec::ExecutingState::stateEntered() { 1902 LOGV("[%s] Now Executing", mCodec->mComponentName.c_str()); 1903 1904 mCodec->processDeferredMessages(); 1905} 1906 1907bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) { 1908 bool handled = false; 1909 1910 switch (msg->what()) { 1911 case kWhatShutdown: 1912 { 1913 mActive = false; 1914 1915 CHECK_EQ(mCodec->mOMX->sendCommand( 1916 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle), 1917 (status_t)OK); 1918 1919 mCodec->changeState(mCodec->mExecutingToIdleState); 1920 1921 handled = true; 1922 break; 1923 } 1924 1925 case kWhatFlush: 1926 { 1927 mActive = false; 1928 1929 CHECK_EQ(mCodec->mOMX->sendCommand( 1930 mCodec->mNode, OMX_CommandFlush, OMX_ALL), 1931 (status_t)OK); 1932 1933 mCodec->changeState(mCodec->mFlushingState); 1934 1935 handled = true; 1936 break; 1937 } 1938 1939 case kWhatResume: 1940 { 1941 resume(); 1942 1943 handled = true; 1944 break; 1945 } 1946 1947 default: 1948 handled = BaseState::onMessageReceived(msg); 1949 break; 1950 } 1951 1952 return handled; 1953} 1954 1955bool ACodec::ExecutingState::onOMXEvent( 1956 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 1957 switch (event) { 1958 case OMX_EventPortSettingsChanged: 1959 { 1960 CHECK_EQ(data1, (OMX_U32)kPortIndexOutput); 1961 1962 if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) { 1963 CHECK_EQ(mCodec->mOMX->sendCommand( 1964 mCodec->mNode, 1965 OMX_CommandPortDisable, kPortIndexOutput), 1966 (status_t)OK); 1967 1968 mCodec->freeOutputBuffersNotOwnedByComponent(); 1969 1970 mCodec->changeState(mCodec->mOutputPortSettingsChangedState); 1971 } else if (data2 == OMX_IndexConfigCommonOutputCrop) { 1972 mCodec->mSentFormat = false; 1973 } else { 1974 LOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx", 1975 mCodec->mComponentName.c_str(), data2); 1976 } 1977 1978 return true; 1979 } 1980 1981 case OMX_EventBufferFlag: 1982 { 1983 return true; 1984 } 1985 1986 default: 1987 return BaseState::onOMXEvent(event, data1, data2); 1988 } 1989} 1990 1991//////////////////////////////////////////////////////////////////////////////// 1992 1993ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState( 1994 ACodec *codec) 1995 : BaseState(codec) { 1996} 1997 1998ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode( 1999 OMX_U32 portIndex) { 2000 if (portIndex == kPortIndexOutput) { 2001 return FREE_BUFFERS; 2002 } 2003 2004 CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput); 2005 2006 return RESUBMIT_BUFFERS; 2007} 2008 2009bool ACodec::OutputPortSettingsChangedState::onMessageReceived( 2010 const sp<AMessage> &msg) { 2011 bool handled = false; 2012 2013 switch (msg->what()) { 2014 case kWhatFlush: 2015 case kWhatShutdown: 2016 case kWhatResume: 2017 { 2018 if (msg->what() == kWhatResume) { 2019 LOGV("[%s] Deferring resume", mCodec->mComponentName.c_str()); 2020 } 2021 2022 mCodec->deferMessage(msg); 2023 handled = true; 2024 break; 2025 } 2026 2027 default: 2028 handled = BaseState::onMessageReceived(msg); 2029 break; 2030 } 2031 2032 return handled; 2033} 2034 2035void ACodec::OutputPortSettingsChangedState::stateEntered() { 2036 LOGV("[%s] Now handling output port settings change", 2037 mCodec->mComponentName.c_str()); 2038} 2039 2040bool ACodec::OutputPortSettingsChangedState::onOMXEvent( 2041 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 2042 switch (event) { 2043 case OMX_EventCmdComplete: 2044 { 2045 if (data1 == (OMX_U32)OMX_CommandPortDisable) { 2046 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput); 2047 2048 LOGV("[%s] Output port now disabled.", 2049 mCodec->mComponentName.c_str()); 2050 2051 CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty()); 2052 mCodec->mDealer[kPortIndexOutput].clear(); 2053 2054 CHECK_EQ(mCodec->mOMX->sendCommand( 2055 mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput), 2056 (status_t)OK); 2057 2058 status_t err; 2059 if ((err = mCodec->allocateBuffersOnPort( 2060 kPortIndexOutput)) != OK) { 2061 LOGE("Failed to allocate output port buffers after " 2062 "port reconfiguration (error 0x%08x)", 2063 err); 2064 2065 mCodec->signalError(); 2066 } 2067 2068 return true; 2069 } else if (data1 == (OMX_U32)OMX_CommandPortEnable) { 2070 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput); 2071 2072 mCodec->mSentFormat = false; 2073 2074 LOGV("[%s] Output port now reenabled.", 2075 mCodec->mComponentName.c_str()); 2076 2077 if (mCodec->mExecutingState->active()) { 2078 mCodec->mExecutingState->submitOutputBuffers(); 2079 } 2080 2081 mCodec->changeState(mCodec->mExecutingState); 2082 2083 return true; 2084 } 2085 2086 return false; 2087 } 2088 2089 default: 2090 return false; 2091 } 2092} 2093 2094//////////////////////////////////////////////////////////////////////////////// 2095 2096ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec) 2097 : BaseState(codec) { 2098} 2099 2100bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) { 2101 bool handled = false; 2102 2103 switch (msg->what()) { 2104 case kWhatFlush: 2105 { 2106 // Don't send me a flush request if you previously wanted me 2107 // to shutdown. 2108 TRESPASS(); 2109 break; 2110 } 2111 2112 case kWhatShutdown: 2113 { 2114 // We're already doing that... 2115 2116 handled = true; 2117 break; 2118 } 2119 2120 default: 2121 handled = BaseState::onMessageReceived(msg); 2122 break; 2123 } 2124 2125 return handled; 2126} 2127 2128void ACodec::ExecutingToIdleState::stateEntered() { 2129 LOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str()); 2130 2131 mCodec->mSentFormat = false; 2132} 2133 2134bool ACodec::ExecutingToIdleState::onOMXEvent( 2135 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 2136 switch (event) { 2137 case OMX_EventCmdComplete: 2138 { 2139 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 2140 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); 2141 2142 changeStateIfWeOwnAllBuffers(); 2143 2144 return true; 2145 } 2146 2147 case OMX_EventPortSettingsChanged: 2148 case OMX_EventBufferFlag: 2149 { 2150 // We're shutting down and don't care about this anymore. 2151 return true; 2152 } 2153 2154 default: 2155 return BaseState::onOMXEvent(event, data1, data2); 2156 } 2157} 2158 2159void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() { 2160 if (mCodec->allYourBuffersAreBelongToUs()) { 2161 CHECK_EQ(mCodec->mOMX->sendCommand( 2162 mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded), 2163 (status_t)OK); 2164 2165 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK); 2166 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK); 2167 2168 mCodec->changeState(mCodec->mIdleToLoadedState); 2169 } 2170} 2171 2172void ACodec::ExecutingToIdleState::onInputBufferFilled( 2173 const sp<AMessage> &msg) { 2174 BaseState::onInputBufferFilled(msg); 2175 2176 changeStateIfWeOwnAllBuffers(); 2177} 2178 2179void ACodec::ExecutingToIdleState::onOutputBufferDrained( 2180 const sp<AMessage> &msg) { 2181 BaseState::onOutputBufferDrained(msg); 2182 2183 changeStateIfWeOwnAllBuffers(); 2184} 2185 2186//////////////////////////////////////////////////////////////////////////////// 2187 2188ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec) 2189 : BaseState(codec) { 2190} 2191 2192bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) { 2193 bool handled = false; 2194 2195 switch (msg->what()) { 2196 case kWhatShutdown: 2197 { 2198 // We're already doing that... 2199 2200 handled = true; 2201 break; 2202 } 2203 2204 case kWhatFlush: 2205 { 2206 // Don't send me a flush request if you previously wanted me 2207 // to shutdown. 2208 TRESPASS(); 2209 break; 2210 } 2211 2212 default: 2213 handled = BaseState::onMessageReceived(msg); 2214 break; 2215 } 2216 2217 return handled; 2218} 2219 2220void ACodec::IdleToLoadedState::stateEntered() { 2221 LOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str()); 2222} 2223 2224bool ACodec::IdleToLoadedState::onOMXEvent( 2225 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 2226 switch (event) { 2227 case OMX_EventCmdComplete: 2228 { 2229 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 2230 CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded); 2231 2232 LOGV("[%s] Now Loaded", mCodec->mComponentName.c_str()); 2233 2234 CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK); 2235 2236 mCodec->mNativeWindow.clear(); 2237 mCodec->mNode = NULL; 2238 mCodec->mOMX.clear(); 2239 mCodec->mComponentName.clear(); 2240 2241 mCodec->changeState(mCodec->mUninitializedState); 2242 2243 sp<AMessage> notify = mCodec->mNotify->dup(); 2244 notify->setInt32("what", ACodec::kWhatShutdownCompleted); 2245 notify->post(); 2246 2247 return true; 2248 } 2249 2250 default: 2251 return BaseState::onOMXEvent(event, data1, data2); 2252 } 2253} 2254 2255//////////////////////////////////////////////////////////////////////////////// 2256 2257ACodec::FlushingState::FlushingState(ACodec *codec) 2258 : BaseState(codec) { 2259} 2260 2261void ACodec::FlushingState::stateEntered() { 2262 LOGV("[%s] Now Flushing", mCodec->mComponentName.c_str()); 2263 2264 mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false; 2265} 2266 2267bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) { 2268 bool handled = false; 2269 2270 switch (msg->what()) { 2271 case kWhatShutdown: 2272 { 2273 mCodec->deferMessage(msg); 2274 break; 2275 } 2276 2277 case kWhatFlush: 2278 { 2279 // We're already doing this right now. 2280 handled = true; 2281 break; 2282 } 2283 2284 default: 2285 handled = BaseState::onMessageReceived(msg); 2286 break; 2287 } 2288 2289 return handled; 2290} 2291 2292bool ACodec::FlushingState::onOMXEvent( 2293 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 2294 switch (event) { 2295 case OMX_EventCmdComplete: 2296 { 2297 CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush); 2298 2299 if (data2 == kPortIndexInput || data2 == kPortIndexOutput) { 2300 CHECK(!mFlushComplete[data2]); 2301 mFlushComplete[data2] = true; 2302 2303 if (mFlushComplete[kPortIndexInput] 2304 && mFlushComplete[kPortIndexOutput]) { 2305 changeStateIfWeOwnAllBuffers(); 2306 } 2307 } else { 2308 CHECK_EQ(data2, OMX_ALL); 2309 CHECK(mFlushComplete[kPortIndexInput]); 2310 CHECK(mFlushComplete[kPortIndexOutput]); 2311 2312 changeStateIfWeOwnAllBuffers(); 2313 } 2314 2315 return true; 2316 } 2317 2318 case OMX_EventPortSettingsChanged: 2319 { 2320 sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id()); 2321 msg->setInt32("type", omx_message::EVENT); 2322 msg->setPointer("node", mCodec->mNode); 2323 msg->setInt32("event", event); 2324 msg->setInt32("data1", data1); 2325 msg->setInt32("data2", data2); 2326 2327 LOGV("[%s] Deferring OMX_EventPortSettingsChanged", 2328 mCodec->mComponentName.c_str()); 2329 2330 mCodec->deferMessage(msg); 2331 2332 return true; 2333 } 2334 2335 default: 2336 return BaseState::onOMXEvent(event, data1, data2); 2337 } 2338 2339 return true; 2340} 2341 2342void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) { 2343 BaseState::onOutputBufferDrained(msg); 2344 2345 changeStateIfWeOwnAllBuffers(); 2346} 2347 2348void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) { 2349 BaseState::onInputBufferFilled(msg); 2350 2351 changeStateIfWeOwnAllBuffers(); 2352} 2353 2354void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() { 2355 if (mFlushComplete[kPortIndexInput] 2356 && mFlushComplete[kPortIndexOutput] 2357 && mCodec->allYourBuffersAreBelongToUs()) { 2358 sp<AMessage> notify = mCodec->mNotify->dup(); 2359 notify->setInt32("what", ACodec::kWhatFlushCompleted); 2360 notify->post(); 2361 2362 mCodec->mPortEOS[kPortIndexInput] = 2363 mCodec->mPortEOS[kPortIndexOutput] = false; 2364 2365 mCodec->changeState(mCodec->mExecutingState); 2366 } 2367} 2368 2369} // namespace android 2370