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