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