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