ACodec.cpp revision 2d8bedd05437b6fccdbc6bf70f673ffd86744d59
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 void onAllocateComponent(const sp<AMessage> &msg); 175 void onConfigureComponent(const sp<AMessage> &msg); 176 void onStart(); 177 178 DISALLOW_EVIL_CONSTRUCTORS(UninitializedState); 179}; 180 181//////////////////////////////////////////////////////////////////////////////// 182 183struct ACodec::LoadedToIdleState : public ACodec::BaseState { 184 LoadedToIdleState(ACodec *codec); 185 186protected: 187 virtual bool onMessageReceived(const sp<AMessage> &msg); 188 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 189 virtual void stateEntered(); 190 191private: 192 status_t allocateBuffers(); 193 194 DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState); 195}; 196 197//////////////////////////////////////////////////////////////////////////////// 198 199struct ACodec::IdleToExecutingState : public ACodec::BaseState { 200 IdleToExecutingState(ACodec *codec); 201 202protected: 203 virtual bool onMessageReceived(const sp<AMessage> &msg); 204 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 205 virtual void stateEntered(); 206 207private: 208 DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState); 209}; 210 211//////////////////////////////////////////////////////////////////////////////// 212 213struct ACodec::ExecutingState : public ACodec::BaseState { 214 ExecutingState(ACodec *codec); 215 216 void submitOutputBuffers(); 217 218 // Submit output buffers to the decoder, submit input buffers to client 219 // to fill with data. 220 void resume(); 221 222 // Returns true iff input and output buffers are in play. 223 bool active() const { return mActive; } 224 225protected: 226 virtual PortMode getPortMode(OMX_U32 portIndex); 227 virtual bool onMessageReceived(const sp<AMessage> &msg); 228 virtual void stateEntered(); 229 230 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 231 232private: 233 bool mActive; 234 235 DISALLOW_EVIL_CONSTRUCTORS(ExecutingState); 236}; 237 238//////////////////////////////////////////////////////////////////////////////// 239 240struct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState { 241 OutputPortSettingsChangedState(ACodec *codec); 242 243protected: 244 virtual PortMode getPortMode(OMX_U32 portIndex); 245 virtual bool onMessageReceived(const sp<AMessage> &msg); 246 virtual void stateEntered(); 247 248 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 249 250private: 251 DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState); 252}; 253 254//////////////////////////////////////////////////////////////////////////////// 255 256struct ACodec::ExecutingToIdleState : public ACodec::BaseState { 257 ExecutingToIdleState(ACodec *codec); 258 259protected: 260 virtual bool onMessageReceived(const sp<AMessage> &msg); 261 virtual void stateEntered(); 262 263 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 264 265 virtual void onOutputBufferDrained(const sp<AMessage> &msg); 266 virtual void onInputBufferFilled(const sp<AMessage> &msg); 267 268private: 269 void changeStateIfWeOwnAllBuffers(); 270 271 bool mComponentNowIdle; 272 273 DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState); 274}; 275 276//////////////////////////////////////////////////////////////////////////////// 277 278struct ACodec::IdleToLoadedState : public ACodec::BaseState { 279 IdleToLoadedState(ACodec *codec); 280 281protected: 282 virtual bool onMessageReceived(const sp<AMessage> &msg); 283 virtual void stateEntered(); 284 285 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 286 287private: 288 DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState); 289}; 290 291//////////////////////////////////////////////////////////////////////////////// 292 293struct ACodec::FlushingState : public ACodec::BaseState { 294 FlushingState(ACodec *codec); 295 296protected: 297 virtual bool onMessageReceived(const sp<AMessage> &msg); 298 virtual void stateEntered(); 299 300 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 301 302 virtual void onOutputBufferDrained(const sp<AMessage> &msg); 303 virtual void onInputBufferFilled(const sp<AMessage> &msg); 304 305private: 306 bool mFlushComplete[2]; 307 308 void changeStateIfWeOwnAllBuffers(); 309 310 DISALLOW_EVIL_CONSTRUCTORS(FlushingState); 311}; 312 313//////////////////////////////////////////////////////////////////////////////// 314 315ACodec::ACodec() 316 : mNode(NULL), 317 mSentFormat(false), 318 mIsEncoder(false) { 319 mUninitializedState = new UninitializedState(this); 320 mLoadedToIdleState = new LoadedToIdleState(this); 321 mIdleToExecutingState = new IdleToExecutingState(this); 322 mExecutingState = new ExecutingState(this); 323 324 mOutputPortSettingsChangedState = 325 new OutputPortSettingsChangedState(this); 326 327 mExecutingToIdleState = new ExecutingToIdleState(this); 328 mIdleToLoadedState = new IdleToLoadedState(this); 329 mFlushingState = new FlushingState(this); 330 331 mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false; 332 mInputEOSResult = OK; 333 334 changeState(mUninitializedState); 335} 336 337ACodec::~ACodec() { 338} 339 340void ACodec::setNotificationMessage(const sp<AMessage> &msg) { 341 mNotify = msg; 342} 343 344void ACodec::initiateSetup(const sp<AMessage> &msg) { 345 msg->setWhat(kWhatSetup); 346 msg->setTarget(id()); 347 msg->post(); 348} 349 350void ACodec::initiateAllocateComponent(const sp<AMessage> &msg) { 351 msg->setWhat(kWhatAllocateComponent); 352 msg->setTarget(id()); 353 msg->post(); 354} 355 356void ACodec::initiateConfigureComponent(const sp<AMessage> &msg) { 357 msg->setWhat(kWhatConfigureComponent); 358 msg->setTarget(id()); 359 msg->post(); 360} 361 362void ACodec::initiateStart() { 363 (new AMessage(kWhatStart, id()))->post(); 364} 365 366void ACodec::signalFlush() { 367 ALOGV("[%s] signalFlush", mComponentName.c_str()); 368 (new AMessage(kWhatFlush, id()))->post(); 369} 370 371void ACodec::signalResume() { 372 (new AMessage(kWhatResume, id()))->post(); 373} 374 375void ACodec::initiateShutdown() { 376 (new AMessage(kWhatShutdown, id()))->post(); 377} 378 379status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) { 380 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 381 382 CHECK(mDealer[portIndex] == NULL); 383 CHECK(mBuffers[portIndex].isEmpty()); 384 385 status_t err; 386 if (mNativeWindow != NULL && portIndex == kPortIndexOutput) { 387 err = allocateOutputBuffersFromNativeWindow(); 388 } else { 389 OMX_PARAM_PORTDEFINITIONTYPE def; 390 InitOMXParams(&def); 391 def.nPortIndex = portIndex; 392 393 err = mOMX->getParameter( 394 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 395 396 if (err == OK) { 397 ALOGV("[%s] Allocating %lu buffers of size %lu on %s port", 398 mComponentName.c_str(), 399 def.nBufferCountActual, def.nBufferSize, 400 portIndex == kPortIndexInput ? "input" : "output"); 401 402 size_t totalSize = def.nBufferCountActual * def.nBufferSize; 403 mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec"); 404 405 for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) { 406 sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize); 407 CHECK(mem.get() != NULL); 408 409 IOMX::buffer_id buffer; 410 411 if (!strncasecmp( 412 mComponentName.c_str(), "OMX.TI.DUCATI1.VIDEO.", 21)) { 413 if (portIndex == kPortIndexInput && i == 0) { 414 // Only log this warning once per allocation round. 415 416 ALOGW("OMX.TI.DUCATI1.VIDEO.* require the use of " 417 "OMX_AllocateBuffer instead of the preferred " 418 "OMX_UseBuffer. Vendor must fix this."); 419 } 420 421 err = mOMX->allocateBufferWithBackup( 422 mNode, portIndex, mem, &buffer); 423 } else { 424 err = mOMX->useBuffer(mNode, portIndex, mem, &buffer); 425 } 426 427 BufferInfo info; 428 info.mBufferID = buffer; 429 info.mStatus = BufferInfo::OWNED_BY_US; 430 info.mData = new ABuffer(mem->pointer(), def.nBufferSize); 431 mBuffers[portIndex].push(info); 432 } 433 } 434 } 435 436 if (err != OK) { 437 return err; 438 } 439 440 sp<AMessage> notify = mNotify->dup(); 441 notify->setInt32("what", ACodec::kWhatBuffersAllocated); 442 443 notify->setInt32("portIndex", portIndex); 444 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 445 AString name = StringPrintf("buffer-id_%d", i); 446 notify->setPointer(name.c_str(), mBuffers[portIndex][i].mBufferID); 447 448 name = StringPrintf("data_%d", i); 449 notify->setBuffer(name.c_str(), mBuffers[portIndex][i].mData); 450 } 451 452 notify->post(); 453 454 return OK; 455} 456 457status_t ACodec::allocateOutputBuffersFromNativeWindow() { 458 OMX_PARAM_PORTDEFINITIONTYPE def; 459 InitOMXParams(&def); 460 def.nPortIndex = kPortIndexOutput; 461 462 status_t err = mOMX->getParameter( 463 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 464 465 if (err != OK) { 466 return err; 467 } 468 469 err = native_window_set_scaling_mode(mNativeWindow.get(), 470 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); 471 472 if (err != OK) { 473 return err; 474 } 475 476 err = native_window_set_buffers_geometry( 477 mNativeWindow.get(), 478 def.format.video.nFrameWidth, 479 def.format.video.nFrameHeight, 480 def.format.video.eColorFormat); 481 482 if (err != 0) { 483 ALOGE("native_window_set_buffers_geometry failed: %s (%d)", 484 strerror(-err), -err); 485 return err; 486 } 487 488 // Set up the native window. 489 OMX_U32 usage = 0; 490 err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage); 491 if (err != 0) { 492 ALOGW("querying usage flags from OMX IL component failed: %d", err); 493 // XXX: Currently this error is logged, but not fatal. 494 usage = 0; 495 } 496 497 err = native_window_set_usage( 498 mNativeWindow.get(), 499 usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP); 500 501 if (err != 0) { 502 ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err); 503 return err; 504 } 505 506 int minUndequeuedBufs = 0; 507 err = mNativeWindow->query( 508 mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, 509 &minUndequeuedBufs); 510 511 if (err != 0) { 512 ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)", 513 strerror(-err), -err); 514 return err; 515 } 516 517 // XXX: Is this the right logic to use? It's not clear to me what the OMX 518 // buffer counts refer to - how do they account for the renderer holding on 519 // to buffers? 520 if (def.nBufferCountActual < def.nBufferCountMin + minUndequeuedBufs) { 521 OMX_U32 newBufferCount = def.nBufferCountMin + minUndequeuedBufs; 522 def.nBufferCountActual = newBufferCount; 523 err = mOMX->setParameter( 524 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 525 526 if (err != OK) { 527 ALOGE("[%s] setting nBufferCountActual to %lu failed: %d", 528 mComponentName.c_str(), newBufferCount, err); 529 return err; 530 } 531 } 532 533 err = native_window_set_buffer_count( 534 mNativeWindow.get(), def.nBufferCountActual); 535 536 if (err != 0) { 537 ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), 538 -err); 539 return err; 540 } 541 542 ALOGV("[%s] Allocating %lu buffers from a native window of size %lu on " 543 "output port", 544 mComponentName.c_str(), def.nBufferCountActual, def.nBufferSize); 545 546 // Dequeue buffers and send them to OMX 547 for (OMX_U32 i = 0; i < def.nBufferCountActual; i++) { 548 ANativeWindowBuffer *buf; 549 err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf); 550 if (err != 0) { 551 ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err); 552 break; 553 } 554 555 sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false)); 556 BufferInfo info; 557 info.mStatus = BufferInfo::OWNED_BY_US; 558 info.mData = new ABuffer(0); 559 info.mGraphicBuffer = graphicBuffer; 560 mBuffers[kPortIndexOutput].push(info); 561 562 IOMX::buffer_id bufferId; 563 err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer, 564 &bufferId); 565 if (err != 0) { 566 ALOGE("registering GraphicBuffer %lu with OMX IL component failed: " 567 "%d", i, err); 568 break; 569 } 570 571 mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId; 572 573 ALOGV("[%s] Registered graphic buffer with ID %p (pointer = %p)", 574 mComponentName.c_str(), 575 bufferId, graphicBuffer.get()); 576 } 577 578 OMX_U32 cancelStart; 579 OMX_U32 cancelEnd; 580 581 if (err != 0) { 582 // If an error occurred while dequeuing we need to cancel any buffers 583 // that were dequeued. 584 cancelStart = 0; 585 cancelEnd = mBuffers[kPortIndexOutput].size(); 586 } else { 587 // Return the last two buffers to the native window. 588 cancelStart = def.nBufferCountActual - minUndequeuedBufs; 589 cancelEnd = def.nBufferCountActual; 590 } 591 592 for (OMX_U32 i = cancelStart; i < cancelEnd; i++) { 593 BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i); 594 cancelBufferToNativeWindow(info); 595 } 596 597 return err; 598} 599 600status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) { 601 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 602 603 ALOGV("[%s] Calling cancelBuffer on buffer %p", 604 mComponentName.c_str(), info->mBufferID); 605 606 int err = mNativeWindow->cancelBuffer( 607 mNativeWindow.get(), info->mGraphicBuffer.get()); 608 609 CHECK_EQ(err, 0); 610 611 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 612 613 return OK; 614} 615 616ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() { 617 ANativeWindowBuffer *buf; 618 if (mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf) != 0) { 619 ALOGE("dequeueBuffer failed."); 620 return NULL; 621 } 622 623 for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) { 624 BufferInfo *info = 625 &mBuffers[kPortIndexOutput].editItemAt(i); 626 627 if (info->mGraphicBuffer->handle == buf->handle) { 628 CHECK_EQ((int)info->mStatus, 629 (int)BufferInfo::OWNED_BY_NATIVE_WINDOW); 630 631 info->mStatus = BufferInfo::OWNED_BY_US; 632 633 return info; 634 } 635 } 636 637 TRESPASS(); 638 639 return NULL; 640} 641 642status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) { 643 for (size_t i = mBuffers[portIndex].size(); i-- > 0;) { 644 CHECK_EQ((status_t)OK, freeBuffer(portIndex, i)); 645 } 646 647 mDealer[portIndex].clear(); 648 649 return OK; 650} 651 652status_t ACodec::freeOutputBuffersNotOwnedByComponent() { 653 for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) { 654 BufferInfo *info = 655 &mBuffers[kPortIndexOutput].editItemAt(i); 656 657 if (info->mStatus != 658 BufferInfo::OWNED_BY_COMPONENT) { 659 // We shouldn't have sent out any buffers to the client at this 660 // point. 661 CHECK_NE((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM); 662 663 CHECK_EQ((status_t)OK, freeBuffer(kPortIndexOutput, i)); 664 } 665 } 666 667 return OK; 668} 669 670status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) { 671 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 672 673 CHECK(info->mStatus == BufferInfo::OWNED_BY_US 674 || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW); 675 676 if (portIndex == kPortIndexOutput && mNativeWindow != NULL 677 && info->mStatus == BufferInfo::OWNED_BY_US) { 678 CHECK_EQ((status_t)OK, cancelBufferToNativeWindow(info)); 679 } 680 681 CHECK_EQ(mOMX->freeBuffer( 682 mNode, portIndex, info->mBufferID), 683 (status_t)OK); 684 685 mBuffers[portIndex].removeAt(i); 686 687 return OK; 688} 689 690ACodec::BufferInfo *ACodec::findBufferByID( 691 uint32_t portIndex, IOMX::buffer_id bufferID, 692 ssize_t *index) { 693 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 694 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 695 696 if (info->mBufferID == bufferID) { 697 if (index != NULL) { 698 *index = i; 699 } 700 return info; 701 } 702 } 703 704 TRESPASS(); 705 706 return NULL; 707} 708 709status_t ACodec::setComponentRole( 710 bool isEncoder, const char *mime) { 711 struct MimeToRole { 712 const char *mime; 713 const char *decoderRole; 714 const char *encoderRole; 715 }; 716 717 static const MimeToRole kMimeToRole[] = { 718 { MEDIA_MIMETYPE_AUDIO_MPEG, 719 "audio_decoder.mp3", "audio_encoder.mp3" }, 720 { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I, 721 "audio_decoder.mp1", "audio_encoder.mp1" }, 722 { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II, 723 "audio_decoder.mp2", "audio_encoder.mp2" }, 724 { MEDIA_MIMETYPE_AUDIO_AMR_NB, 725 "audio_decoder.amrnb", "audio_encoder.amrnb" }, 726 { MEDIA_MIMETYPE_AUDIO_AMR_WB, 727 "audio_decoder.amrwb", "audio_encoder.amrwb" }, 728 { MEDIA_MIMETYPE_AUDIO_AAC, 729 "audio_decoder.aac", "audio_encoder.aac" }, 730 { MEDIA_MIMETYPE_AUDIO_VORBIS, 731 "audio_decoder.vorbis", "audio_encoder.vorbis" }, 732 { MEDIA_MIMETYPE_VIDEO_AVC, 733 "video_decoder.avc", "video_encoder.avc" }, 734 { MEDIA_MIMETYPE_VIDEO_MPEG4, 735 "video_decoder.mpeg4", "video_encoder.mpeg4" }, 736 { MEDIA_MIMETYPE_VIDEO_H263, 737 "video_decoder.h263", "video_encoder.h263" }, 738 { MEDIA_MIMETYPE_VIDEO_VPX, 739 "video_decoder.vpx", "video_encoder.vpx" }, 740 }; 741 742 static const size_t kNumMimeToRole = 743 sizeof(kMimeToRole) / sizeof(kMimeToRole[0]); 744 745 size_t i; 746 for (i = 0; i < kNumMimeToRole; ++i) { 747 if (!strcasecmp(mime, kMimeToRole[i].mime)) { 748 break; 749 } 750 } 751 752 if (i == kNumMimeToRole) { 753 return ERROR_UNSUPPORTED; 754 } 755 756 const char *role = 757 isEncoder ? kMimeToRole[i].encoderRole 758 : kMimeToRole[i].decoderRole; 759 760 if (role != NULL) { 761 OMX_PARAM_COMPONENTROLETYPE roleParams; 762 InitOMXParams(&roleParams); 763 764 strncpy((char *)roleParams.cRole, 765 role, OMX_MAX_STRINGNAME_SIZE - 1); 766 767 roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0'; 768 769 status_t err = mOMX->setParameter( 770 mNode, OMX_IndexParamStandardComponentRole, 771 &roleParams, sizeof(roleParams)); 772 773 if (err != OK) { 774 ALOGW("[%s] Failed to set standard component role '%s'.", 775 mComponentName.c_str(), role); 776 777 return err; 778 } 779 } 780 781 return OK; 782} 783 784status_t ACodec::configureCodec( 785 const char *mime, const sp<AMessage> &msg) { 786 int32_t encoder; 787 if (!msg->findInt32("encoder", &encoder)) { 788 encoder = false; 789 } 790 791 mIsEncoder = encoder; 792 793 status_t err = setComponentRole(encoder /* isEncoder */, mime); 794 795 if (err != OK) { 796 return err; 797 } 798 799 int32_t bitRate = 0; 800 if (encoder && !msg->findInt32("bitrate", &bitRate)) { 801 return INVALID_OPERATION; 802 } 803 804 if (!strncasecmp(mime, "video/", 6)) { 805 if (encoder) { 806 err = setupVideoEncoder(mime, msg); 807 } else { 808 int32_t width, height; 809 if (!msg->findInt32("width", &width) 810 || !msg->findInt32("height", &height)) { 811 err = INVALID_OPERATION; 812 } else { 813 err = setupVideoDecoder(mime, width, height); 814 } 815 } 816 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 817 int32_t numChannels, sampleRate; 818 if (!msg->findInt32("channel-count", &numChannels) 819 || !msg->findInt32("sample-rate", &sampleRate)) { 820 err = INVALID_OPERATION; 821 } else { 822 err = setupAACCodec(encoder, numChannels, sampleRate, bitRate); 823 } 824 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) { 825 err = setupAMRCodec(encoder, false /* isWAMR */, bitRate); 826 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) { 827 err = setupAMRCodec(encoder, true /* isWAMR */, bitRate); 828 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW) 829 || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) { 830 // These are PCM-like formats with a fixed sample rate but 831 // a variable number of channels. 832 833 int32_t numChannels; 834 if (!msg->findInt32("channel-count", &numChannels)) { 835 err = INVALID_OPERATION; 836 } else { 837 err = setupG711Codec(encoder, numChannels); 838 } 839 } 840 841 if (err != OK) { 842 return err; 843 } 844 845 int32_t maxInputSize; 846 if (msg->findInt32("max-input-size", &maxInputSize)) { 847 err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize); 848 } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) { 849 err = setMinBufferSize(kPortIndexInput, 8192); // XXX 850 } 851 852 return err; 853} 854 855status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) { 856 OMX_PARAM_PORTDEFINITIONTYPE def; 857 InitOMXParams(&def); 858 def.nPortIndex = portIndex; 859 860 status_t err = mOMX->getParameter( 861 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 862 863 if (err != OK) { 864 return err; 865 } 866 867 if (def.nBufferSize >= size) { 868 return OK; 869 } 870 871 def.nBufferSize = size; 872 873 err = mOMX->setParameter( 874 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 875 876 if (err != OK) { 877 return err; 878 } 879 880 err = mOMX->getParameter( 881 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 882 883 if (err != OK) { 884 return err; 885 } 886 887 CHECK(def.nBufferSize >= size); 888 889 return OK; 890} 891 892status_t ACodec::selectAudioPortFormat( 893 OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) { 894 OMX_AUDIO_PARAM_PORTFORMATTYPE format; 895 InitOMXParams(&format); 896 897 format.nPortIndex = portIndex; 898 for (OMX_U32 index = 0;; ++index) { 899 format.nIndex = index; 900 901 status_t err = mOMX->getParameter( 902 mNode, OMX_IndexParamAudioPortFormat, 903 &format, sizeof(format)); 904 905 if (err != OK) { 906 return err; 907 } 908 909 if (format.eEncoding == desiredFormat) { 910 break; 911 } 912 } 913 914 return mOMX->setParameter( 915 mNode, OMX_IndexParamAudioPortFormat, &format, sizeof(format)); 916} 917 918status_t ACodec::setupAACCodec( 919 bool encoder, 920 int32_t numChannels, int32_t sampleRate, int32_t bitRate) { 921 status_t err = setupRawAudioFormat( 922 encoder ? kPortIndexInput : kPortIndexOutput, 923 sampleRate, 924 numChannels); 925 926 if (err != OK) { 927 return err; 928 } 929 930 if (encoder) { 931 err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC); 932 933 if (err != OK) { 934 return err; 935 } 936 937 OMX_PARAM_PORTDEFINITIONTYPE def; 938 InitOMXParams(&def); 939 def.nPortIndex = kPortIndexOutput; 940 941 err = mOMX->getParameter( 942 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 943 944 if (err != OK) { 945 return err; 946 } 947 948 def.format.audio.bFlagErrorConcealment = OMX_TRUE; 949 def.format.audio.eEncoding = OMX_AUDIO_CodingAAC; 950 951 err = mOMX->setParameter( 952 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 953 954 if (err != OK) { 955 return err; 956 } 957 958 OMX_AUDIO_PARAM_AACPROFILETYPE profile; 959 InitOMXParams(&profile); 960 profile.nPortIndex = kPortIndexOutput; 961 962 err = mOMX->getParameter( 963 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 964 965 if (err != OK) { 966 return err; 967 } 968 969 profile.nChannels = numChannels; 970 971 profile.eChannelMode = 972 (numChannels == 1) 973 ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo; 974 975 profile.nSampleRate = sampleRate; 976 profile.nBitRate = bitRate; 977 profile.nAudioBandWidth = 0; 978 profile.nFrameLength = 0; 979 profile.nAACtools = OMX_AUDIO_AACToolAll; 980 profile.nAACERtools = OMX_AUDIO_AACERNone; 981 profile.eAACProfile = OMX_AUDIO_AACObjectLC; 982 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF; 983 984 err = mOMX->setParameter( 985 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 986 987 if (err != OK) { 988 return err; 989 } 990 991 return err; 992 } 993 994 OMX_AUDIO_PARAM_AACPROFILETYPE profile; 995 InitOMXParams(&profile); 996 profile.nPortIndex = kPortIndexInput; 997 998 err = mOMX->getParameter( 999 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 1000 1001 if (err != OK) { 1002 return err; 1003 } 1004 1005 profile.nChannels = numChannels; 1006 profile.nSampleRate = sampleRate; 1007 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS; 1008 1009 return mOMX->setParameter( 1010 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 1011} 1012 1013static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate( 1014 bool isAMRWB, int32_t bps) { 1015 if (isAMRWB) { 1016 if (bps <= 6600) { 1017 return OMX_AUDIO_AMRBandModeWB0; 1018 } else if (bps <= 8850) { 1019 return OMX_AUDIO_AMRBandModeWB1; 1020 } else if (bps <= 12650) { 1021 return OMX_AUDIO_AMRBandModeWB2; 1022 } else if (bps <= 14250) { 1023 return OMX_AUDIO_AMRBandModeWB3; 1024 } else if (bps <= 15850) { 1025 return OMX_AUDIO_AMRBandModeWB4; 1026 } else if (bps <= 18250) { 1027 return OMX_AUDIO_AMRBandModeWB5; 1028 } else if (bps <= 19850) { 1029 return OMX_AUDIO_AMRBandModeWB6; 1030 } else if (bps <= 23050) { 1031 return OMX_AUDIO_AMRBandModeWB7; 1032 } 1033 1034 // 23850 bps 1035 return OMX_AUDIO_AMRBandModeWB8; 1036 } else { // AMRNB 1037 if (bps <= 4750) { 1038 return OMX_AUDIO_AMRBandModeNB0; 1039 } else if (bps <= 5150) { 1040 return OMX_AUDIO_AMRBandModeNB1; 1041 } else if (bps <= 5900) { 1042 return OMX_AUDIO_AMRBandModeNB2; 1043 } else if (bps <= 6700) { 1044 return OMX_AUDIO_AMRBandModeNB3; 1045 } else if (bps <= 7400) { 1046 return OMX_AUDIO_AMRBandModeNB4; 1047 } else if (bps <= 7950) { 1048 return OMX_AUDIO_AMRBandModeNB5; 1049 } else if (bps <= 10200) { 1050 return OMX_AUDIO_AMRBandModeNB6; 1051 } 1052 1053 // 12200 bps 1054 return OMX_AUDIO_AMRBandModeNB7; 1055 } 1056} 1057 1058status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) { 1059 OMX_AUDIO_PARAM_AMRTYPE def; 1060 InitOMXParams(&def); 1061 def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput; 1062 1063 status_t err = 1064 mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); 1065 1066 if (err != OK) { 1067 return err; 1068 } 1069 1070 def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF; 1071 def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate); 1072 1073 err = mOMX->setParameter( 1074 mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); 1075 1076 if (err != OK) { 1077 return err; 1078 } 1079 1080 return setupRawAudioFormat( 1081 encoder ? kPortIndexInput : kPortIndexOutput, 1082 isWAMR ? 16000 : 8000 /* sampleRate */, 1083 1 /* numChannels */); 1084} 1085 1086status_t ACodec::setupG711Codec(bool encoder, int32_t numChannels) { 1087 CHECK(!encoder); // XXX TODO 1088 1089 return setupRawAudioFormat( 1090 kPortIndexInput, 8000 /* sampleRate */, numChannels); 1091} 1092 1093status_t ACodec::setupRawAudioFormat( 1094 OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) { 1095 OMX_PARAM_PORTDEFINITIONTYPE def; 1096 InitOMXParams(&def); 1097 def.nPortIndex = portIndex; 1098 1099 status_t err = mOMX->getParameter( 1100 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1101 1102 if (err != OK) { 1103 return err; 1104 } 1105 1106 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; 1107 1108 err = mOMX->setParameter( 1109 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1110 1111 if (err != OK) { 1112 return err; 1113 } 1114 1115 OMX_AUDIO_PARAM_PCMMODETYPE pcmParams; 1116 InitOMXParams(&pcmParams); 1117 pcmParams.nPortIndex = portIndex; 1118 1119 err = mOMX->getParameter( 1120 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); 1121 1122 if (err != OK) { 1123 return err; 1124 } 1125 1126 pcmParams.nChannels = numChannels; 1127 pcmParams.eNumData = OMX_NumericalDataSigned; 1128 pcmParams.bInterleaved = OMX_TRUE; 1129 pcmParams.nBitPerSample = 16; 1130 pcmParams.nSamplingRate = sampleRate; 1131 pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear; 1132 1133 if (numChannels == 1) { 1134 pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelCF; 1135 } else { 1136 CHECK_EQ(numChannels, 2); 1137 1138 pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelLF; 1139 pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF; 1140 } 1141 1142 return mOMX->setParameter( 1143 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); 1144} 1145 1146status_t ACodec::setVideoPortFormatType( 1147 OMX_U32 portIndex, 1148 OMX_VIDEO_CODINGTYPE compressionFormat, 1149 OMX_COLOR_FORMATTYPE colorFormat) { 1150 OMX_VIDEO_PARAM_PORTFORMATTYPE format; 1151 InitOMXParams(&format); 1152 format.nPortIndex = portIndex; 1153 format.nIndex = 0; 1154 bool found = false; 1155 1156 OMX_U32 index = 0; 1157 for (;;) { 1158 format.nIndex = index; 1159 status_t err = mOMX->getParameter( 1160 mNode, OMX_IndexParamVideoPortFormat, 1161 &format, sizeof(format)); 1162 1163 if (err != OK) { 1164 return err; 1165 } 1166 1167 // The following assertion is violated by TI's video decoder. 1168 // CHECK_EQ(format.nIndex, index); 1169 1170 if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) { 1171 if (portIndex == kPortIndexInput 1172 && colorFormat == format.eColorFormat) { 1173 // eCompressionFormat does not seem right. 1174 found = true; 1175 break; 1176 } 1177 if (portIndex == kPortIndexOutput 1178 && compressionFormat == format.eCompressionFormat) { 1179 // eColorFormat does not seem right. 1180 found = true; 1181 break; 1182 } 1183 } 1184 1185 if (format.eCompressionFormat == compressionFormat 1186 && format.eColorFormat == colorFormat) { 1187 found = true; 1188 break; 1189 } 1190 1191 ++index; 1192 } 1193 1194 if (!found) { 1195 return UNKNOWN_ERROR; 1196 } 1197 1198 status_t err = mOMX->setParameter( 1199 mNode, OMX_IndexParamVideoPortFormat, 1200 &format, sizeof(format)); 1201 1202 return err; 1203} 1204 1205status_t ACodec::setSupportedOutputFormat() { 1206 OMX_VIDEO_PARAM_PORTFORMATTYPE format; 1207 InitOMXParams(&format); 1208 format.nPortIndex = kPortIndexOutput; 1209 format.nIndex = 0; 1210 1211 status_t err = mOMX->getParameter( 1212 mNode, OMX_IndexParamVideoPortFormat, 1213 &format, sizeof(format)); 1214 CHECK_EQ(err, (status_t)OK); 1215 CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused); 1216 1217 CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar 1218 || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar 1219 || format.eColorFormat == OMX_COLOR_FormatCbYCrY 1220 || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar 1221 || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar); 1222 1223 return mOMX->setParameter( 1224 mNode, OMX_IndexParamVideoPortFormat, 1225 &format, sizeof(format)); 1226} 1227 1228static status_t GetVideoCodingTypeFromMime( 1229 const char *mime, OMX_VIDEO_CODINGTYPE *codingType) { 1230 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 1231 *codingType = OMX_VIDEO_CodingAVC; 1232 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 1233 *codingType = OMX_VIDEO_CodingMPEG4; 1234 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 1235 *codingType = OMX_VIDEO_CodingH263; 1236 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG2, mime)) { 1237 *codingType = OMX_VIDEO_CodingMPEG2; 1238 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_VPX, mime)) { 1239 *codingType = OMX_VIDEO_CodingVPX; 1240 } else { 1241 *codingType = OMX_VIDEO_CodingUnused; 1242 return ERROR_UNSUPPORTED; 1243 } 1244 1245 return OK; 1246} 1247 1248status_t ACodec::setupVideoDecoder( 1249 const char *mime, int32_t width, int32_t height) { 1250 OMX_VIDEO_CODINGTYPE compressionFormat; 1251 status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat); 1252 1253 if (err != OK) { 1254 return err; 1255 } 1256 1257 err = setVideoPortFormatType( 1258 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused); 1259 1260 if (err != OK) { 1261 return err; 1262 } 1263 1264 err = setSupportedOutputFormat(); 1265 1266 if (err != OK) { 1267 return err; 1268 } 1269 1270 err = setVideoFormatOnPort( 1271 kPortIndexInput, width, height, compressionFormat); 1272 1273 if (err != OK) { 1274 return err; 1275 } 1276 1277 err = setVideoFormatOnPort( 1278 kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused); 1279 1280 if (err != OK) { 1281 return err; 1282 } 1283 1284 return OK; 1285} 1286 1287status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) { 1288 int32_t tmp; 1289 if (!msg->findInt32("color-format", &tmp)) { 1290 return INVALID_OPERATION; 1291 } 1292 1293 OMX_COLOR_FORMATTYPE colorFormat = 1294 static_cast<OMX_COLOR_FORMATTYPE>(tmp); 1295 1296 status_t err = setVideoPortFormatType( 1297 kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat); 1298 1299 if (err != OK) { 1300 ALOGE("[%s] does not support color format %d", 1301 mComponentName.c_str(), colorFormat); 1302 1303 return err; 1304 } 1305 1306 /* Input port configuration */ 1307 1308 OMX_PARAM_PORTDEFINITIONTYPE def; 1309 InitOMXParams(&def); 1310 1311 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 1312 1313 def.nPortIndex = kPortIndexInput; 1314 1315 err = mOMX->getParameter( 1316 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1317 1318 if (err != OK) { 1319 return err; 1320 } 1321 1322 int32_t width, height, bitrate; 1323 if (!msg->findInt32("width", &width) 1324 || !msg->findInt32("height", &height) 1325 || !msg->findInt32("bitrate", &bitrate)) { 1326 return INVALID_OPERATION; 1327 } 1328 1329 video_def->nFrameWidth = width; 1330 video_def->nFrameHeight = height; 1331 1332 int32_t stride; 1333 if (!msg->findInt32("stride", &stride)) { 1334 stride = width; 1335 } 1336 1337 video_def->nStride = stride; 1338 1339 int32_t sliceHeight; 1340 if (!msg->findInt32("slice-height", &sliceHeight)) { 1341 sliceHeight = height; 1342 } 1343 1344 video_def->nSliceHeight = sliceHeight; 1345 1346 def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2; 1347 1348 float frameRate; 1349 if (!msg->findFloat("frame-rate", &frameRate)) { 1350 int32_t tmp; 1351 if (!msg->findInt32("frame-rate", &tmp)) { 1352 return INVALID_OPERATION; 1353 } 1354 frameRate = (float)tmp; 1355 } 1356 1357 video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f); 1358 video_def->eCompressionFormat = OMX_VIDEO_CodingUnused; 1359 video_def->eColorFormat = colorFormat; 1360 1361 err = mOMX->setParameter( 1362 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1363 1364 if (err != OK) { 1365 ALOGE("[%s] failed to set input port definition parameters.", 1366 mComponentName.c_str()); 1367 1368 return err; 1369 } 1370 1371 /* Output port configuration */ 1372 1373 OMX_VIDEO_CODINGTYPE compressionFormat; 1374 err = GetVideoCodingTypeFromMime(mime, &compressionFormat); 1375 1376 if (err != OK) { 1377 return err; 1378 } 1379 1380 err = setVideoPortFormatType( 1381 kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused); 1382 1383 if (err != OK) { 1384 ALOGE("[%s] does not support compression format %d", 1385 mComponentName.c_str(), compressionFormat); 1386 1387 return err; 1388 } 1389 1390 def.nPortIndex = kPortIndexOutput; 1391 1392 err = mOMX->getParameter( 1393 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1394 1395 if (err != OK) { 1396 return err; 1397 } 1398 1399 video_def->nFrameWidth = width; 1400 video_def->nFrameHeight = height; 1401 video_def->xFramerate = 0; 1402 video_def->nBitrate = bitrate; 1403 video_def->eCompressionFormat = compressionFormat; 1404 video_def->eColorFormat = OMX_COLOR_FormatUnused; 1405 1406 err = mOMX->setParameter( 1407 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1408 1409 if (err != OK) { 1410 ALOGE("[%s] failed to set output port definition parameters.", 1411 mComponentName.c_str()); 1412 1413 return err; 1414 } 1415 1416 switch (compressionFormat) { 1417 case OMX_VIDEO_CodingMPEG4: 1418 err = setupMPEG4EncoderParameters(msg); 1419 break; 1420 1421 case OMX_VIDEO_CodingH263: 1422 err = setupH263EncoderParameters(msg); 1423 break; 1424 1425 case OMX_VIDEO_CodingAVC: 1426 err = setupAVCEncoderParameters(msg); 1427 break; 1428 1429 default: 1430 break; 1431 } 1432 1433 ALOGI("setupVideoEncoder succeeded"); 1434 1435 return err; 1436} 1437 1438static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) { 1439 if (iFramesInterval < 0) { 1440 return 0xFFFFFFFF; 1441 } else if (iFramesInterval == 0) { 1442 return 0; 1443 } 1444 OMX_U32 ret = frameRate * iFramesInterval; 1445 CHECK(ret > 1); 1446 return ret; 1447} 1448 1449status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) { 1450 int32_t bitrate, iFrameInterval; 1451 if (!msg->findInt32("bitrate", &bitrate) 1452 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 1453 return INVALID_OPERATION; 1454 } 1455 1456 float frameRate; 1457 if (!msg->findFloat("frame-rate", &frameRate)) { 1458 int32_t tmp; 1459 if (!msg->findInt32("frame-rate", &tmp)) { 1460 return INVALID_OPERATION; 1461 } 1462 frameRate = (float)tmp; 1463 } 1464 1465 OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type; 1466 InitOMXParams(&mpeg4type); 1467 mpeg4type.nPortIndex = kPortIndexOutput; 1468 1469 status_t err = mOMX->getParameter( 1470 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); 1471 1472 if (err != OK) { 1473 return err; 1474 } 1475 1476 mpeg4type.nSliceHeaderSpacing = 0; 1477 mpeg4type.bSVH = OMX_FALSE; 1478 mpeg4type.bGov = OMX_FALSE; 1479 1480 mpeg4type.nAllowedPictureTypes = 1481 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 1482 1483 mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 1484 if (mpeg4type.nPFrames == 0) { 1485 mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 1486 } 1487 mpeg4type.nBFrames = 0; 1488 mpeg4type.nIDCVLCThreshold = 0; 1489 mpeg4type.bACPred = OMX_TRUE; 1490 mpeg4type.nMaxPacketSize = 256; 1491 mpeg4type.nTimeIncRes = 1000; 1492 mpeg4type.nHeaderExtension = 0; 1493 mpeg4type.bReversibleVLC = OMX_FALSE; 1494 1495 int32_t profile; 1496 if (msg->findInt32("profile", &profile)) { 1497 int32_t level; 1498 if (!msg->findInt32("level", &level)) { 1499 return INVALID_OPERATION; 1500 } 1501 1502 err = verifySupportForProfileAndLevel(profile, level); 1503 1504 if (err != OK) { 1505 return err; 1506 } 1507 1508 mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile); 1509 mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level); 1510 } 1511 1512 err = mOMX->setParameter( 1513 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); 1514 1515 if (err != OK) { 1516 return err; 1517 } 1518 1519 err = configureBitrate(bitrate); 1520 1521 if (err != OK) { 1522 return err; 1523 } 1524 1525 return setupErrorCorrectionParameters(); 1526} 1527 1528status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) { 1529 int32_t bitrate, iFrameInterval; 1530 if (!msg->findInt32("bitrate", &bitrate) 1531 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 1532 return INVALID_OPERATION; 1533 } 1534 1535 float frameRate; 1536 if (!msg->findFloat("frame-rate", &frameRate)) { 1537 int32_t tmp; 1538 if (!msg->findInt32("frame-rate", &tmp)) { 1539 return INVALID_OPERATION; 1540 } 1541 frameRate = (float)tmp; 1542 } 1543 1544 OMX_VIDEO_PARAM_H263TYPE h263type; 1545 InitOMXParams(&h263type); 1546 h263type.nPortIndex = kPortIndexOutput; 1547 1548 status_t err = mOMX->getParameter( 1549 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); 1550 1551 if (err != OK) { 1552 return err; 1553 } 1554 1555 h263type.nAllowedPictureTypes = 1556 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 1557 1558 h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 1559 if (h263type.nPFrames == 0) { 1560 h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 1561 } 1562 h263type.nBFrames = 0; 1563 1564 int32_t profile; 1565 if (msg->findInt32("profile", &profile)) { 1566 int32_t level; 1567 if (!msg->findInt32("level", &level)) { 1568 return INVALID_OPERATION; 1569 } 1570 1571 err = verifySupportForProfileAndLevel(profile, level); 1572 1573 if (err != OK) { 1574 return err; 1575 } 1576 1577 h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile); 1578 h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level); 1579 } 1580 1581 h263type.bPLUSPTYPEAllowed = OMX_FALSE; 1582 h263type.bForceRoundingTypeToZero = OMX_FALSE; 1583 h263type.nPictureHeaderRepetition = 0; 1584 h263type.nGOBHeaderInterval = 0; 1585 1586 err = mOMX->setParameter( 1587 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); 1588 1589 if (err != OK) { 1590 return err; 1591 } 1592 1593 err = configureBitrate(bitrate); 1594 1595 if (err != OK) { 1596 return err; 1597 } 1598 1599 return setupErrorCorrectionParameters(); 1600} 1601 1602status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) { 1603 int32_t bitrate, iFrameInterval; 1604 if (!msg->findInt32("bitrate", &bitrate) 1605 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 1606 return INVALID_OPERATION; 1607 } 1608 1609 float frameRate; 1610 if (!msg->findFloat("frame-rate", &frameRate)) { 1611 int32_t tmp; 1612 if (!msg->findInt32("frame-rate", &tmp)) { 1613 return INVALID_OPERATION; 1614 } 1615 frameRate = (float)tmp; 1616 } 1617 1618 OMX_VIDEO_PARAM_AVCTYPE h264type; 1619 InitOMXParams(&h264type); 1620 h264type.nPortIndex = kPortIndexOutput; 1621 1622 status_t err = mOMX->getParameter( 1623 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 1624 1625 if (err != OK) { 1626 return err; 1627 } 1628 1629 h264type.nAllowedPictureTypes = 1630 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 1631 1632 int32_t profile; 1633 if (msg->findInt32("profile", &profile)) { 1634 int32_t level; 1635 if (!msg->findInt32("level", &level)) { 1636 return INVALID_OPERATION; 1637 } 1638 1639 err = verifySupportForProfileAndLevel(profile, level); 1640 1641 if (err != OK) { 1642 return err; 1643 } 1644 1645 h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile); 1646 h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level); 1647 } 1648 1649 // XXX 1650 if (!strncmp(mComponentName.c_str(), "OMX.TI.DUCATI1", 14)) { 1651 h264type.eProfile = OMX_VIDEO_AVCProfileBaseline; 1652 } 1653 1654 if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) { 1655 h264type.nSliceHeaderSpacing = 0; 1656 h264type.bUseHadamard = OMX_TRUE; 1657 h264type.nRefFrames = 1; 1658 h264type.nBFrames = 0; 1659 h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 1660 if (h264type.nPFrames == 0) { 1661 h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 1662 } 1663 h264type.nRefIdx10ActiveMinus1 = 0; 1664 h264type.nRefIdx11ActiveMinus1 = 0; 1665 h264type.bEntropyCodingCABAC = OMX_FALSE; 1666 h264type.bWeightedPPrediction = OMX_FALSE; 1667 h264type.bconstIpred = OMX_FALSE; 1668 h264type.bDirect8x8Inference = OMX_FALSE; 1669 h264type.bDirectSpatialTemporal = OMX_FALSE; 1670 h264type.nCabacInitIdc = 0; 1671 } 1672 1673 if (h264type.nBFrames != 0) { 1674 h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB; 1675 } 1676 1677 h264type.bEnableUEP = OMX_FALSE; 1678 h264type.bEnableFMO = OMX_FALSE; 1679 h264type.bEnableASO = OMX_FALSE; 1680 h264type.bEnableRS = OMX_FALSE; 1681 h264type.bFrameMBsOnly = OMX_TRUE; 1682 h264type.bMBAFF = OMX_FALSE; 1683 h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; 1684 1685 if (!strcasecmp("OMX.Nvidia.h264.encoder", mComponentName.c_str())) { 1686 h264type.eLevel = OMX_VIDEO_AVCLevelMax; 1687 } 1688 1689 err = mOMX->setParameter( 1690 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 1691 1692 if (err != OK) { 1693 return err; 1694 } 1695 1696 return configureBitrate(bitrate); 1697} 1698 1699status_t ACodec::verifySupportForProfileAndLevel( 1700 int32_t profile, int32_t level) { 1701 OMX_VIDEO_PARAM_PROFILELEVELTYPE params; 1702 InitOMXParams(¶ms); 1703 params.nPortIndex = kPortIndexOutput; 1704 1705 for (params.nProfileIndex = 0;; ++params.nProfileIndex) { 1706 status_t err = mOMX->getParameter( 1707 mNode, 1708 OMX_IndexParamVideoProfileLevelQuerySupported, 1709 ¶ms, 1710 sizeof(params)); 1711 1712 if (err != OK) { 1713 return err; 1714 } 1715 1716 int32_t supportedProfile = static_cast<int32_t>(params.eProfile); 1717 int32_t supportedLevel = static_cast<int32_t>(params.eLevel); 1718 1719 if (profile == supportedProfile && level <= supportedLevel) { 1720 return OK; 1721 } 1722 } 1723} 1724 1725status_t ACodec::configureBitrate(int32_t bitrate) { 1726 OMX_VIDEO_PARAM_BITRATETYPE bitrateType; 1727 InitOMXParams(&bitrateType); 1728 bitrateType.nPortIndex = kPortIndexOutput; 1729 1730 status_t err = mOMX->getParameter( 1731 mNode, OMX_IndexParamVideoBitrate, 1732 &bitrateType, sizeof(bitrateType)); 1733 1734 if (err != OK) { 1735 return err; 1736 } 1737 1738 bitrateType.eControlRate = OMX_Video_ControlRateVariable; 1739 bitrateType.nTargetBitrate = bitrate; 1740 1741 return mOMX->setParameter( 1742 mNode, OMX_IndexParamVideoBitrate, 1743 &bitrateType, sizeof(bitrateType)); 1744} 1745 1746status_t ACodec::setupErrorCorrectionParameters() { 1747 OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType; 1748 InitOMXParams(&errorCorrectionType); 1749 errorCorrectionType.nPortIndex = kPortIndexOutput; 1750 1751 status_t err = mOMX->getParameter( 1752 mNode, OMX_IndexParamVideoErrorCorrection, 1753 &errorCorrectionType, sizeof(errorCorrectionType)); 1754 1755 if (err != OK) { 1756 return OK; // Optional feature. Ignore this failure 1757 } 1758 1759 errorCorrectionType.bEnableHEC = OMX_FALSE; 1760 errorCorrectionType.bEnableResync = OMX_TRUE; 1761 errorCorrectionType.nResynchMarkerSpacing = 256; 1762 errorCorrectionType.bEnableDataPartitioning = OMX_FALSE; 1763 errorCorrectionType.bEnableRVLC = OMX_FALSE; 1764 1765 return mOMX->setParameter( 1766 mNode, OMX_IndexParamVideoErrorCorrection, 1767 &errorCorrectionType, sizeof(errorCorrectionType)); 1768} 1769 1770status_t ACodec::setVideoFormatOnPort( 1771 OMX_U32 portIndex, 1772 int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) { 1773 OMX_PARAM_PORTDEFINITIONTYPE def; 1774 InitOMXParams(&def); 1775 def.nPortIndex = portIndex; 1776 1777 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 1778 1779 status_t err = mOMX->getParameter( 1780 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1781 1782 CHECK_EQ(err, (status_t)OK); 1783 1784 if (portIndex == kPortIndexInput) { 1785 // XXX Need a (much) better heuristic to compute input buffer sizes. 1786 const size_t X = 64 * 1024; 1787 if (def.nBufferSize < X) { 1788 def.nBufferSize = X; 1789 } 1790 } 1791 1792 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo); 1793 1794 video_def->nFrameWidth = width; 1795 video_def->nFrameHeight = height; 1796 1797 if (portIndex == kPortIndexInput) { 1798 video_def->eCompressionFormat = compressionFormat; 1799 video_def->eColorFormat = OMX_COLOR_FormatUnused; 1800 } 1801 1802 err = mOMX->setParameter( 1803 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1804 1805 return err; 1806} 1807 1808status_t ACodec::initNativeWindow() { 1809 if (mNativeWindow != NULL) { 1810 return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE); 1811 } 1812 1813 mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE); 1814 return OK; 1815} 1816 1817size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const { 1818 size_t n = 0; 1819 1820 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 1821 const BufferInfo &info = mBuffers[portIndex].itemAt(i); 1822 1823 if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) { 1824 ++n; 1825 } 1826 } 1827 1828 return n; 1829} 1830 1831bool ACodec::allYourBuffersAreBelongToUs( 1832 OMX_U32 portIndex) { 1833 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 1834 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 1835 1836 if (info->mStatus != BufferInfo::OWNED_BY_US 1837 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) { 1838 ALOGV("[%s] Buffer %p on port %ld still has status %d", 1839 mComponentName.c_str(), 1840 info->mBufferID, portIndex, info->mStatus); 1841 return false; 1842 } 1843 } 1844 1845 return true; 1846} 1847 1848bool ACodec::allYourBuffersAreBelongToUs() { 1849 return allYourBuffersAreBelongToUs(kPortIndexInput) 1850 && allYourBuffersAreBelongToUs(kPortIndexOutput); 1851} 1852 1853void ACodec::deferMessage(const sp<AMessage> &msg) { 1854 bool wasEmptyBefore = mDeferredQueue.empty(); 1855 mDeferredQueue.push_back(msg); 1856} 1857 1858void ACodec::processDeferredMessages() { 1859 List<sp<AMessage> > queue = mDeferredQueue; 1860 mDeferredQueue.clear(); 1861 1862 List<sp<AMessage> >::iterator it = queue.begin(); 1863 while (it != queue.end()) { 1864 onMessageReceived(*it++); 1865 } 1866} 1867 1868void ACodec::sendFormatChange() { 1869 sp<AMessage> notify = mNotify->dup(); 1870 notify->setInt32("what", kWhatOutputFormatChanged); 1871 1872 OMX_PARAM_PORTDEFINITIONTYPE def; 1873 InitOMXParams(&def); 1874 def.nPortIndex = kPortIndexOutput; 1875 1876 CHECK_EQ(mOMX->getParameter( 1877 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)), 1878 (status_t)OK); 1879 1880 CHECK_EQ((int)def.eDir, (int)OMX_DirOutput); 1881 1882 switch (def.eDomain) { 1883 case OMX_PortDomainVideo: 1884 { 1885 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video; 1886 1887 notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW); 1888 notify->setInt32("width", videoDef->nFrameWidth); 1889 notify->setInt32("height", videoDef->nFrameHeight); 1890 notify->setInt32("stride", videoDef->nStride); 1891 notify->setInt32("slice-height", videoDef->nSliceHeight); 1892 notify->setInt32("color-format", videoDef->eColorFormat); 1893 1894 OMX_CONFIG_RECTTYPE rect; 1895 InitOMXParams(&rect); 1896 rect.nPortIndex = kPortIndexOutput; 1897 1898 if (mOMX->getConfig( 1899 mNode, OMX_IndexConfigCommonOutputCrop, 1900 &rect, sizeof(rect)) != OK) { 1901 rect.nLeft = 0; 1902 rect.nTop = 0; 1903 rect.nWidth = videoDef->nFrameWidth; 1904 rect.nHeight = videoDef->nFrameHeight; 1905 } 1906 1907 CHECK_GE(rect.nLeft, 0); 1908 CHECK_GE(rect.nTop, 0); 1909 CHECK_GE(rect.nWidth, 0u); 1910 CHECK_GE(rect.nHeight, 0u); 1911 CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth); 1912 CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight); 1913 1914 notify->setRect( 1915 "crop", 1916 rect.nLeft, 1917 rect.nTop, 1918 rect.nLeft + rect.nWidth - 1, 1919 rect.nTop + rect.nHeight - 1); 1920 1921 if (mNativeWindow != NULL) { 1922 android_native_rect_t crop; 1923 crop.left = rect.nLeft; 1924 crop.top = rect.nTop; 1925 crop.right = rect.nLeft + rect.nWidth; 1926 crop.bottom = rect.nTop + rect.nHeight; 1927 1928 CHECK_EQ(0, native_window_set_crop( 1929 mNativeWindow.get(), &crop)); 1930 } 1931 break; 1932 } 1933 1934 case OMX_PortDomainAudio: 1935 { 1936 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio; 1937 CHECK_EQ((int)audioDef->eEncoding, (int)OMX_AUDIO_CodingPCM); 1938 1939 OMX_AUDIO_PARAM_PCMMODETYPE params; 1940 InitOMXParams(¶ms); 1941 params.nPortIndex = kPortIndexOutput; 1942 1943 CHECK_EQ(mOMX->getParameter( 1944 mNode, OMX_IndexParamAudioPcm, 1945 ¶ms, sizeof(params)), 1946 (status_t)OK); 1947 1948 CHECK(params.nChannels == 1 || params.bInterleaved); 1949 CHECK_EQ(params.nBitPerSample, 16u); 1950 CHECK_EQ((int)params.eNumData, (int)OMX_NumericalDataSigned); 1951 CHECK_EQ((int)params.ePCMMode, (int)OMX_AUDIO_PCMModeLinear); 1952 1953 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW); 1954 notify->setInt32("channel-count", params.nChannels); 1955 notify->setInt32("sample-rate", params.nSamplingRate); 1956 break; 1957 } 1958 1959 default: 1960 TRESPASS(); 1961 } 1962 1963 notify->post(); 1964 1965 mSentFormat = true; 1966} 1967 1968void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) { 1969 sp<AMessage> notify = mNotify->dup(); 1970 notify->setInt32("what", ACodec::kWhatError); 1971 notify->setInt32("omx-error", error); 1972 notify->setInt32("err", internalError); 1973 notify->post(); 1974} 1975 1976//////////////////////////////////////////////////////////////////////////////// 1977 1978ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState) 1979 : AState(parentState), 1980 mCodec(codec) { 1981} 1982 1983ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(OMX_U32 portIndex) { 1984 return KEEP_BUFFERS; 1985} 1986 1987bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) { 1988 switch (msg->what()) { 1989 case kWhatInputBufferFilled: 1990 { 1991 onInputBufferFilled(msg); 1992 break; 1993 } 1994 1995 case kWhatOutputBufferDrained: 1996 { 1997 onOutputBufferDrained(msg); 1998 break; 1999 } 2000 2001 case ACodec::kWhatOMXMessage: 2002 { 2003 return onOMXMessage(msg); 2004 } 2005 2006 default: 2007 return false; 2008 } 2009 2010 return true; 2011} 2012 2013bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) { 2014 int32_t type; 2015 CHECK(msg->findInt32("type", &type)); 2016 2017 IOMX::node_id nodeID; 2018 CHECK(msg->findPointer("node", &nodeID)); 2019 CHECK_EQ(nodeID, mCodec->mNode); 2020 2021 switch (type) { 2022 case omx_message::EVENT: 2023 { 2024 int32_t event, data1, data2; 2025 CHECK(msg->findInt32("event", &event)); 2026 CHECK(msg->findInt32("data1", &data1)); 2027 CHECK(msg->findInt32("data2", &data2)); 2028 2029 if (event == OMX_EventCmdComplete 2030 && data1 == OMX_CommandFlush 2031 && data2 == (int32_t)OMX_ALL) { 2032 // Use of this notification is not consistent across 2033 // implementations. We'll drop this notification and rely 2034 // on flush-complete notifications on the individual port 2035 // indices instead. 2036 2037 return true; 2038 } 2039 2040 return onOMXEvent( 2041 static_cast<OMX_EVENTTYPE>(event), 2042 static_cast<OMX_U32>(data1), 2043 static_cast<OMX_U32>(data2)); 2044 } 2045 2046 case omx_message::EMPTY_BUFFER_DONE: 2047 { 2048 IOMX::buffer_id bufferID; 2049 CHECK(msg->findPointer("buffer", &bufferID)); 2050 2051 return onOMXEmptyBufferDone(bufferID); 2052 } 2053 2054 case omx_message::FILL_BUFFER_DONE: 2055 { 2056 IOMX::buffer_id bufferID; 2057 CHECK(msg->findPointer("buffer", &bufferID)); 2058 2059 int32_t rangeOffset, rangeLength, flags; 2060 int64_t timeUs; 2061 void *platformPrivate; 2062 void *dataPtr; 2063 2064 CHECK(msg->findInt32("range_offset", &rangeOffset)); 2065 CHECK(msg->findInt32("range_length", &rangeLength)); 2066 CHECK(msg->findInt32("flags", &flags)); 2067 CHECK(msg->findInt64("timestamp", &timeUs)); 2068 CHECK(msg->findPointer("platform_private", &platformPrivate)); 2069 CHECK(msg->findPointer("data_ptr", &dataPtr)); 2070 2071 return onOMXFillBufferDone( 2072 bufferID, 2073 (size_t)rangeOffset, (size_t)rangeLength, 2074 (OMX_U32)flags, 2075 timeUs, 2076 platformPrivate, 2077 dataPtr); 2078 } 2079 2080 default: 2081 TRESPASS(); 2082 break; 2083 } 2084} 2085 2086bool ACodec::BaseState::onOMXEvent( 2087 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 2088 if (event != OMX_EventError) { 2089 ALOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)", 2090 mCodec->mComponentName.c_str(), event, data1, data2); 2091 2092 return false; 2093 } 2094 2095 ALOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1); 2096 2097 mCodec->signalError((OMX_ERRORTYPE)data1); 2098 2099 return true; 2100} 2101 2102bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) { 2103 ALOGV("[%s] onOMXEmptyBufferDone %p", 2104 mCodec->mComponentName.c_str(), bufferID); 2105 2106 BufferInfo *info = 2107 mCodec->findBufferByID(kPortIndexInput, bufferID); 2108 2109 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); 2110 info->mStatus = BufferInfo::OWNED_BY_US; 2111 2112 PortMode mode = getPortMode(kPortIndexInput); 2113 2114 switch (mode) { 2115 case KEEP_BUFFERS: 2116 break; 2117 2118 case RESUBMIT_BUFFERS: 2119 postFillThisBuffer(info); 2120 break; 2121 2122 default: 2123 { 2124 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 2125 TRESPASS(); // Not currently used 2126 break; 2127 } 2128 } 2129 2130 return true; 2131} 2132 2133void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) { 2134 if (mCodec->mPortEOS[kPortIndexInput]) { 2135 return; 2136 } 2137 2138 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 2139 2140 sp<AMessage> notify = mCodec->mNotify->dup(); 2141 notify->setInt32("what", ACodec::kWhatFillThisBuffer); 2142 notify->setPointer("buffer-id", info->mBufferID); 2143 2144 info->mData->meta()->clear(); 2145 notify->setBuffer("buffer", info->mData); 2146 2147 sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id()); 2148 reply->setPointer("buffer-id", info->mBufferID); 2149 2150 notify->setMessage("reply", reply); 2151 2152 notify->post(); 2153 2154 info->mStatus = BufferInfo::OWNED_BY_UPSTREAM; 2155} 2156 2157void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { 2158 IOMX::buffer_id bufferID; 2159 CHECK(msg->findPointer("buffer-id", &bufferID)); 2160 2161 sp<ABuffer> buffer; 2162 int32_t err = OK; 2163 bool eos = false; 2164 2165 if (!msg->findBuffer("buffer", &buffer)) { 2166 CHECK(msg->findInt32("err", &err)); 2167 2168 ALOGV("[%s] saw error %d instead of an input buffer", 2169 mCodec->mComponentName.c_str(), err); 2170 2171 buffer.clear(); 2172 2173 eos = true; 2174 } 2175 2176 int32_t tmp; 2177 if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) { 2178 eos = true; 2179 err = ERROR_END_OF_STREAM; 2180 } 2181 2182 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID); 2183 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM); 2184 2185 info->mStatus = BufferInfo::OWNED_BY_US; 2186 2187 PortMode mode = getPortMode(kPortIndexInput); 2188 2189 switch (mode) { 2190 case KEEP_BUFFERS: 2191 { 2192 if (eos) { 2193 if (!mCodec->mPortEOS[kPortIndexInput]) { 2194 mCodec->mPortEOS[kPortIndexInput] = true; 2195 mCodec->mInputEOSResult = err; 2196 } 2197 } 2198 break; 2199 } 2200 2201 case RESUBMIT_BUFFERS: 2202 { 2203 if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) { 2204 int64_t timeUs; 2205 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 2206 2207 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME; 2208 2209 int32_t isCSD; 2210 if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) { 2211 flags |= OMX_BUFFERFLAG_CODECCONFIG; 2212 } 2213 2214 if (eos) { 2215 flags |= OMX_BUFFERFLAG_EOS; 2216 } 2217 2218 if (buffer != info->mData) { 2219 if (0 && !(flags & OMX_BUFFERFLAG_CODECCONFIG)) { 2220 ALOGV("[%s] Needs to copy input data.", 2221 mCodec->mComponentName.c_str()); 2222 } 2223 2224 CHECK_LE(buffer->size(), info->mData->capacity()); 2225 memcpy(info->mData->data(), buffer->data(), buffer->size()); 2226 } 2227 2228 if (flags & OMX_BUFFERFLAG_CODECCONFIG) { 2229 ALOGV("[%s] calling emptyBuffer %p w/ codec specific data", 2230 mCodec->mComponentName.c_str(), bufferID); 2231 } else if (flags & OMX_BUFFERFLAG_EOS) { 2232 ALOGV("[%s] calling emptyBuffer %p w/ EOS", 2233 mCodec->mComponentName.c_str(), bufferID); 2234 } else { 2235 ALOGV("[%s] calling emptyBuffer %p w/ time %lld us", 2236 mCodec->mComponentName.c_str(), bufferID, timeUs); 2237 } 2238 2239 CHECK_EQ(mCodec->mOMX->emptyBuffer( 2240 mCodec->mNode, 2241 bufferID, 2242 0, 2243 buffer->size(), 2244 flags, 2245 timeUs), 2246 (status_t)OK); 2247 2248 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 2249 2250 if (!eos) { 2251 getMoreInputDataIfPossible(); 2252 } else { 2253 ALOGV("[%s] Signalled EOS on the input port", 2254 mCodec->mComponentName.c_str()); 2255 2256 mCodec->mPortEOS[kPortIndexInput] = true; 2257 mCodec->mInputEOSResult = err; 2258 } 2259 } else if (!mCodec->mPortEOS[kPortIndexInput]) { 2260 if (err != ERROR_END_OF_STREAM) { 2261 ALOGV("[%s] Signalling EOS on the input port " 2262 "due to error %d", 2263 mCodec->mComponentName.c_str(), err); 2264 } else { 2265 ALOGV("[%s] Signalling EOS on the input port", 2266 mCodec->mComponentName.c_str()); 2267 } 2268 2269 ALOGV("[%s] calling emptyBuffer %p signalling EOS", 2270 mCodec->mComponentName.c_str(), bufferID); 2271 2272 CHECK_EQ(mCodec->mOMX->emptyBuffer( 2273 mCodec->mNode, 2274 bufferID, 2275 0, 2276 0, 2277 OMX_BUFFERFLAG_EOS, 2278 0), 2279 (status_t)OK); 2280 2281 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 2282 2283 mCodec->mPortEOS[kPortIndexInput] = true; 2284 mCodec->mInputEOSResult = err; 2285 } 2286 break; 2287 2288 default: 2289 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 2290 break; 2291 } 2292 } 2293} 2294 2295void ACodec::BaseState::getMoreInputDataIfPossible() { 2296 if (mCodec->mPortEOS[kPortIndexInput]) { 2297 return; 2298 } 2299 2300 BufferInfo *eligible = NULL; 2301 2302 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 2303 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 2304 2305#if 0 2306 if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) { 2307 // There's already a "read" pending. 2308 return; 2309 } 2310#endif 2311 2312 if (info->mStatus == BufferInfo::OWNED_BY_US) { 2313 eligible = info; 2314 } 2315 } 2316 2317 if (eligible == NULL) { 2318 return; 2319 } 2320 2321 postFillThisBuffer(eligible); 2322} 2323 2324bool ACodec::BaseState::onOMXFillBufferDone( 2325 IOMX::buffer_id bufferID, 2326 size_t rangeOffset, size_t rangeLength, 2327 OMX_U32 flags, 2328 int64_t timeUs, 2329 void *platformPrivate, 2330 void *dataPtr) { 2331 ALOGV("[%s] onOMXFillBufferDone %p time %lld us, flags = 0x%08lx", 2332 mCodec->mComponentName.c_str(), bufferID, timeUs, flags); 2333 2334 ssize_t index; 2335 BufferInfo *info = 2336 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 2337 2338 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); 2339 2340 info->mStatus = BufferInfo::OWNED_BY_US; 2341 2342 PortMode mode = getPortMode(kPortIndexOutput); 2343 2344 switch (mode) { 2345 case KEEP_BUFFERS: 2346 break; 2347 2348 case RESUBMIT_BUFFERS: 2349 { 2350 if (rangeLength == 0 && !(flags & OMX_BUFFERFLAG_EOS)) { 2351 ALOGV("[%s] calling fillBuffer %p", 2352 mCodec->mComponentName.c_str(), info->mBufferID); 2353 2354 CHECK_EQ(mCodec->mOMX->fillBuffer( 2355 mCodec->mNode, info->mBufferID), 2356 (status_t)OK); 2357 2358 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 2359 break; 2360 } 2361 2362 if (!mCodec->mIsEncoder && !mCodec->mSentFormat) { 2363 mCodec->sendFormatChange(); 2364 } 2365 2366 if (mCodec->mNativeWindow == NULL) { 2367 info->mData->setRange(rangeOffset, rangeLength); 2368 } 2369 2370 info->mData->meta()->setInt64("timeUs", timeUs); 2371 2372 sp<AMessage> notify = mCodec->mNotify->dup(); 2373 notify->setInt32("what", ACodec::kWhatDrainThisBuffer); 2374 notify->setPointer("buffer-id", info->mBufferID); 2375 notify->setBuffer("buffer", info->mData); 2376 notify->setInt32("flags", flags); 2377 2378 sp<AMessage> reply = 2379 new AMessage(kWhatOutputBufferDrained, mCodec->id()); 2380 2381 reply->setPointer("buffer-id", info->mBufferID); 2382 2383 notify->setMessage("reply", reply); 2384 2385 notify->post(); 2386 2387 info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM; 2388 2389 if (flags & OMX_BUFFERFLAG_EOS) { 2390 ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str()); 2391 2392 sp<AMessage> notify = mCodec->mNotify->dup(); 2393 notify->setInt32("what", ACodec::kWhatEOS); 2394 notify->setInt32("err", mCodec->mInputEOSResult); 2395 notify->post(); 2396 2397 mCodec->mPortEOS[kPortIndexOutput] = true; 2398 } 2399 break; 2400 } 2401 2402 default: 2403 { 2404 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 2405 2406 CHECK_EQ((status_t)OK, 2407 mCodec->freeBuffer(kPortIndexOutput, index)); 2408 break; 2409 } 2410 } 2411 2412 return true; 2413} 2414 2415void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { 2416 IOMX::buffer_id bufferID; 2417 CHECK(msg->findPointer("buffer-id", &bufferID)); 2418 2419 ssize_t index; 2420 BufferInfo *info = 2421 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 2422 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM); 2423 2424 int32_t render; 2425 if (mCodec->mNativeWindow != NULL 2426 && msg->findInt32("render", &render) && render != 0) { 2427 // The client wants this buffer to be rendered. 2428 2429 status_t err; 2430 if ((err = mCodec->mNativeWindow->queueBuffer( 2431 mCodec->mNativeWindow.get(), 2432 info->mGraphicBuffer.get())) == OK) { 2433 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 2434 } else { 2435 mCodec->signalError(OMX_ErrorUndefined, err); 2436 info->mStatus = BufferInfo::OWNED_BY_US; 2437 } 2438 } else { 2439 info->mStatus = BufferInfo::OWNED_BY_US; 2440 } 2441 2442 PortMode mode = getPortMode(kPortIndexOutput); 2443 2444 switch (mode) { 2445 case KEEP_BUFFERS: 2446 { 2447 // XXX fishy, revisit!!! What about the FREE_BUFFERS case below? 2448 2449 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 2450 // We cannot resubmit the buffer we just rendered, dequeue 2451 // the spare instead. 2452 2453 info = mCodec->dequeueBufferFromNativeWindow(); 2454 } 2455 break; 2456 } 2457 2458 case RESUBMIT_BUFFERS: 2459 { 2460 if (!mCodec->mPortEOS[kPortIndexOutput]) { 2461 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 2462 // We cannot resubmit the buffer we just rendered, dequeue 2463 // the spare instead. 2464 2465 info = mCodec->dequeueBufferFromNativeWindow(); 2466 } 2467 2468 if (info != NULL) { 2469 ALOGV("[%s] calling fillBuffer %p", 2470 mCodec->mComponentName.c_str(), info->mBufferID); 2471 2472 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), 2473 (status_t)OK); 2474 2475 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 2476 } 2477 } 2478 break; 2479 } 2480 2481 default: 2482 { 2483 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 2484 2485 CHECK_EQ((status_t)OK, 2486 mCodec->freeBuffer(kPortIndexOutput, index)); 2487 break; 2488 } 2489 } 2490} 2491 2492//////////////////////////////////////////////////////////////////////////////// 2493 2494ACodec::UninitializedState::UninitializedState(ACodec *codec) 2495 : BaseState(codec) { 2496} 2497 2498bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) { 2499 bool handled = false; 2500 2501 switch (msg->what()) { 2502 case ACodec::kWhatSetup: 2503 { 2504 onSetup(msg); 2505 2506 handled = true; 2507 break; 2508 } 2509 2510 case ACodec::kWhatAllocateComponent: 2511 { 2512 onAllocateComponent(msg); 2513 handled = true; 2514 break; 2515 } 2516 2517 case ACodec::kWhatConfigureComponent: 2518 { 2519 onConfigureComponent(msg); 2520 handled = true; 2521 break; 2522 } 2523 2524 case ACodec::kWhatStart: 2525 { 2526 onStart(); 2527 handled = true; 2528 break; 2529 } 2530 2531 case ACodec::kWhatShutdown: 2532 { 2533 sp<AMessage> notify = mCodec->mNotify->dup(); 2534 notify->setInt32("what", ACodec::kWhatShutdownCompleted); 2535 notify->post(); 2536 2537 handled = true; 2538 break; 2539 } 2540 2541 case ACodec::kWhatFlush: 2542 { 2543 sp<AMessage> notify = mCodec->mNotify->dup(); 2544 notify->setInt32("what", ACodec::kWhatFlushCompleted); 2545 notify->post(); 2546 2547 handled = true; 2548 break; 2549 } 2550 2551 default: 2552 return BaseState::onMessageReceived(msg); 2553 } 2554 2555 return handled; 2556} 2557 2558void ACodec::UninitializedState::onSetup( 2559 const sp<AMessage> &msg) { 2560 onAllocateComponent(msg); 2561 onConfigureComponent(msg); 2562 onStart(); 2563} 2564 2565void ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) { 2566 ALOGV("onAllocateComponent"); 2567 2568 if (mCodec->mNode != NULL) { 2569 CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK); 2570 2571 mCodec->mNativeWindow.clear(); 2572 mCodec->mNode = NULL; 2573 mCodec->mOMX.clear(); 2574 mCodec->mComponentName.clear(); 2575 } 2576 2577 OMXClient client; 2578 CHECK_EQ(client.connect(), (status_t)OK); 2579 2580 sp<IOMX> omx = client.interface(); 2581 2582 Vector<String8> matchingCodecs; 2583 2584 AString mime; 2585 2586 AString componentName; 2587 if (msg->findString("componentName", &componentName)) { 2588 matchingCodecs.push_back(String8(componentName.c_str())); 2589 } else { 2590 CHECK(msg->findString("mime", &mime)); 2591 2592 int32_t encoder; 2593 if (!msg->findInt32("encoder", &encoder)) { 2594 encoder = false; 2595 } 2596 2597 OMXCodec::findMatchingCodecs( 2598 mime.c_str(), 2599 encoder, // createEncoder 2600 NULL, // matchComponentName 2601 0, // flags 2602 &matchingCodecs); 2603 } 2604 2605 sp<CodecObserver> observer = new CodecObserver; 2606 IOMX::node_id node = NULL; 2607 2608 for (size_t matchIndex = 0; matchIndex < matchingCodecs.size(); 2609 ++matchIndex) { 2610 componentName = matchingCodecs.itemAt(matchIndex).string(); 2611 2612 pid_t tid = androidGetTid(); 2613 int prevPriority = androidGetThreadPriority(tid); 2614 androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND); 2615 status_t err = omx->allocateNode(componentName.c_str(), observer, &node); 2616 androidSetThreadPriority(tid, prevPriority); 2617 2618 if (err == OK) { 2619 break; 2620 } 2621 2622 node = NULL; 2623 } 2624 2625 if (node == NULL) { 2626 if (!mime.empty()) { 2627 ALOGE("Unable to instantiate a decoder for type '%s'.", 2628 mime.c_str()); 2629 } else { 2630 ALOGE("Unable to instantiate decoder '%s'.", componentName.c_str()); 2631 } 2632 2633 mCodec->signalError(OMX_ErrorComponentNotFound); 2634 return; 2635 } 2636 2637 sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id()); 2638 observer->setNotificationMessage(notify); 2639 2640 mCodec->mComponentName = componentName; 2641 mCodec->mOMX = omx; 2642 mCodec->mNode = node; 2643 2644 mCodec->mPortEOS[kPortIndexInput] = 2645 mCodec->mPortEOS[kPortIndexOutput] = false; 2646 2647 mCodec->mInputEOSResult = OK; 2648 2649 { 2650 sp<AMessage> notify = mCodec->mNotify->dup(); 2651 notify->setInt32("what", ACodec::kWhatComponentAllocated); 2652 notify->setString("componentName", mCodec->mComponentName.c_str()); 2653 notify->post(); 2654 } 2655} 2656 2657void ACodec::UninitializedState::onConfigureComponent( 2658 const sp<AMessage> &msg) { 2659 ALOGV("onConfigureComponent"); 2660 2661 CHECK(mCodec->mNode != NULL); 2662 2663 AString mime; 2664 CHECK(msg->findString("mime", &mime)); 2665 2666 status_t err = mCodec->configureCodec(mime.c_str(), msg); 2667 2668 if (err != OK) { 2669 mCodec->signalError(OMX_ErrorUndefined, err); 2670 return; 2671 } 2672 2673 sp<RefBase> obj; 2674 if (msg->findObject("native-window", &obj) 2675 && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) { 2676 sp<NativeWindowWrapper> nativeWindow( 2677 static_cast<NativeWindowWrapper *>(obj.get())); 2678 CHECK(nativeWindow != NULL); 2679 mCodec->mNativeWindow = nativeWindow->getNativeWindow(); 2680 } 2681 CHECK_EQ((status_t)OK, mCodec->initNativeWindow()); 2682 2683 { 2684 sp<AMessage> notify = mCodec->mNotify->dup(); 2685 notify->setInt32("what", ACodec::kWhatComponentConfigured); 2686 notify->post(); 2687 } 2688} 2689 2690void ACodec::UninitializedState::onStart() { 2691 ALOGV("onStart"); 2692 2693 CHECK_EQ(mCodec->mOMX->sendCommand( 2694 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle), 2695 (status_t)OK); 2696 2697 mCodec->changeState(mCodec->mLoadedToIdleState); 2698} 2699 2700//////////////////////////////////////////////////////////////////////////////// 2701 2702ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec) 2703 : BaseState(codec) { 2704} 2705 2706void ACodec::LoadedToIdleState::stateEntered() { 2707 ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str()); 2708 2709 status_t err; 2710 if ((err = allocateBuffers()) != OK) { 2711 ALOGE("Failed to allocate buffers after transitioning to IDLE state " 2712 "(error 0x%08x)", 2713 err); 2714 2715 mCodec->signalError(OMX_ErrorUndefined, err); 2716 } 2717} 2718 2719status_t ACodec::LoadedToIdleState::allocateBuffers() { 2720 status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput); 2721 2722 if (err != OK) { 2723 return err; 2724 } 2725 2726 return mCodec->allocateBuffersOnPort(kPortIndexOutput); 2727} 2728 2729bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) { 2730 switch (msg->what()) { 2731 case kWhatShutdown: 2732 { 2733 mCodec->deferMessage(msg); 2734 return true; 2735 } 2736 2737 default: 2738 return BaseState::onMessageReceived(msg); 2739 } 2740} 2741 2742bool ACodec::LoadedToIdleState::onOMXEvent( 2743 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 2744 switch (event) { 2745 case OMX_EventCmdComplete: 2746 { 2747 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 2748 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); 2749 2750 CHECK_EQ(mCodec->mOMX->sendCommand( 2751 mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting), 2752 (status_t)OK); 2753 2754 mCodec->changeState(mCodec->mIdleToExecutingState); 2755 2756 return true; 2757 } 2758 2759 default: 2760 return BaseState::onOMXEvent(event, data1, data2); 2761 } 2762} 2763 2764//////////////////////////////////////////////////////////////////////////////// 2765 2766ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec) 2767 : BaseState(codec) { 2768} 2769 2770void ACodec::IdleToExecutingState::stateEntered() { 2771 ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str()); 2772} 2773 2774bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) { 2775 switch (msg->what()) { 2776 case kWhatShutdown: 2777 { 2778 mCodec->deferMessage(msg); 2779 return true; 2780 } 2781 2782 default: 2783 return BaseState::onMessageReceived(msg); 2784 } 2785} 2786 2787bool ACodec::IdleToExecutingState::onOMXEvent( 2788 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 2789 switch (event) { 2790 case OMX_EventCmdComplete: 2791 { 2792 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 2793 CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting); 2794 2795 mCodec->mExecutingState->resume(); 2796 mCodec->changeState(mCodec->mExecutingState); 2797 2798 return true; 2799 } 2800 2801 default: 2802 return BaseState::onOMXEvent(event, data1, data2); 2803 } 2804} 2805 2806//////////////////////////////////////////////////////////////////////////////// 2807 2808ACodec::ExecutingState::ExecutingState(ACodec *codec) 2809 : BaseState(codec), 2810 mActive(false) { 2811} 2812 2813ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode( 2814 OMX_U32 portIndex) { 2815 return RESUBMIT_BUFFERS; 2816} 2817 2818void ACodec::ExecutingState::submitOutputBuffers() { 2819 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) { 2820 BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i); 2821 2822 if (mCodec->mNativeWindow != NULL) { 2823 CHECK(info->mStatus == BufferInfo::OWNED_BY_US 2824 || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW); 2825 2826 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 2827 continue; 2828 } 2829 2830 status_t err = mCodec->mNativeWindow->lockBuffer( 2831 mCodec->mNativeWindow.get(), 2832 info->mGraphicBuffer.get()); 2833 CHECK_EQ(err, (status_t)OK); 2834 } else { 2835 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 2836 } 2837 2838 ALOGV("[%s] calling fillBuffer %p", 2839 mCodec->mComponentName.c_str(), info->mBufferID); 2840 2841 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), 2842 (status_t)OK); 2843 2844 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 2845 } 2846} 2847 2848void ACodec::ExecutingState::resume() { 2849 if (mActive) { 2850 ALOGV("[%s] We're already active, no need to resume.", 2851 mCodec->mComponentName.c_str()); 2852 2853 return; 2854 } 2855 2856 submitOutputBuffers(); 2857 2858 // Post the first input buffer. 2859 CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u); 2860 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0); 2861 2862 postFillThisBuffer(info); 2863 2864 mActive = true; 2865} 2866 2867void ACodec::ExecutingState::stateEntered() { 2868 ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str()); 2869 2870 mCodec->processDeferredMessages(); 2871} 2872 2873bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) { 2874 bool handled = false; 2875 2876 switch (msg->what()) { 2877 case kWhatShutdown: 2878 { 2879 mActive = false; 2880 2881 CHECK_EQ(mCodec->mOMX->sendCommand( 2882 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle), 2883 (status_t)OK); 2884 2885 mCodec->changeState(mCodec->mExecutingToIdleState); 2886 2887 handled = true; 2888 break; 2889 } 2890 2891 case kWhatFlush: 2892 { 2893 ALOGV("[%s] ExecutingState flushing now " 2894 "(codec owns %d/%d input, %d/%d output).", 2895 mCodec->mComponentName.c_str(), 2896 mCodec->countBuffersOwnedByComponent(kPortIndexInput), 2897 mCodec->mBuffers[kPortIndexInput].size(), 2898 mCodec->countBuffersOwnedByComponent(kPortIndexOutput), 2899 mCodec->mBuffers[kPortIndexOutput].size()); 2900 2901 mActive = false; 2902 2903 CHECK_EQ(mCodec->mOMX->sendCommand( 2904 mCodec->mNode, OMX_CommandFlush, OMX_ALL), 2905 (status_t)OK); 2906 2907 mCodec->changeState(mCodec->mFlushingState); 2908 2909 handled = true; 2910 break; 2911 } 2912 2913 case kWhatResume: 2914 { 2915 resume(); 2916 2917 handled = true; 2918 break; 2919 } 2920 2921 default: 2922 handled = BaseState::onMessageReceived(msg); 2923 break; 2924 } 2925 2926 return handled; 2927} 2928 2929bool ACodec::ExecutingState::onOMXEvent( 2930 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 2931 switch (event) { 2932 case OMX_EventPortSettingsChanged: 2933 { 2934 CHECK_EQ(data1, (OMX_U32)kPortIndexOutput); 2935 2936 if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) { 2937 CHECK_EQ(mCodec->mOMX->sendCommand( 2938 mCodec->mNode, 2939 OMX_CommandPortDisable, kPortIndexOutput), 2940 (status_t)OK); 2941 2942 mCodec->freeOutputBuffersNotOwnedByComponent(); 2943 2944 mCodec->changeState(mCodec->mOutputPortSettingsChangedState); 2945 } else if (data2 == OMX_IndexConfigCommonOutputCrop) { 2946 mCodec->mSentFormat = false; 2947 } else { 2948 ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx", 2949 mCodec->mComponentName.c_str(), data2); 2950 } 2951 2952 return true; 2953 } 2954 2955 case OMX_EventBufferFlag: 2956 { 2957 return true; 2958 } 2959 2960 default: 2961 return BaseState::onOMXEvent(event, data1, data2); 2962 } 2963} 2964 2965//////////////////////////////////////////////////////////////////////////////// 2966 2967ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState( 2968 ACodec *codec) 2969 : BaseState(codec) { 2970} 2971 2972ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode( 2973 OMX_U32 portIndex) { 2974 if (portIndex == kPortIndexOutput) { 2975 return FREE_BUFFERS; 2976 } 2977 2978 CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput); 2979 2980 return RESUBMIT_BUFFERS; 2981} 2982 2983bool ACodec::OutputPortSettingsChangedState::onMessageReceived( 2984 const sp<AMessage> &msg) { 2985 bool handled = false; 2986 2987 switch (msg->what()) { 2988 case kWhatFlush: 2989 case kWhatShutdown: 2990 case kWhatResume: 2991 { 2992 if (msg->what() == kWhatResume) { 2993 ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str()); 2994 } 2995 2996 mCodec->deferMessage(msg); 2997 handled = true; 2998 break; 2999 } 3000 3001 default: 3002 handled = BaseState::onMessageReceived(msg); 3003 break; 3004 } 3005 3006 return handled; 3007} 3008 3009void ACodec::OutputPortSettingsChangedState::stateEntered() { 3010 ALOGV("[%s] Now handling output port settings change", 3011 mCodec->mComponentName.c_str()); 3012} 3013 3014bool ACodec::OutputPortSettingsChangedState::onOMXEvent( 3015 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3016 switch (event) { 3017 case OMX_EventCmdComplete: 3018 { 3019 if (data1 == (OMX_U32)OMX_CommandPortDisable) { 3020 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput); 3021 3022 ALOGV("[%s] Output port now disabled.", 3023 mCodec->mComponentName.c_str()); 3024 3025 CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty()); 3026 mCodec->mDealer[kPortIndexOutput].clear(); 3027 3028 CHECK_EQ(mCodec->mOMX->sendCommand( 3029 mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput), 3030 (status_t)OK); 3031 3032 status_t err; 3033 if ((err = mCodec->allocateBuffersOnPort( 3034 kPortIndexOutput)) != OK) { 3035 ALOGE("Failed to allocate output port buffers after " 3036 "port reconfiguration (error 0x%08x)", 3037 err); 3038 3039 mCodec->signalError(OMX_ErrorUndefined, err); 3040 3041 // This is technically not correct, since we were unable 3042 // to allocate output buffers and therefore the output port 3043 // remains disabled. It is necessary however to allow us 3044 // to shutdown the codec properly. 3045 mCodec->changeState(mCodec->mExecutingState); 3046 } 3047 3048 return true; 3049 } else if (data1 == (OMX_U32)OMX_CommandPortEnable) { 3050 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput); 3051 3052 mCodec->mSentFormat = false; 3053 3054 ALOGV("[%s] Output port now reenabled.", 3055 mCodec->mComponentName.c_str()); 3056 3057 if (mCodec->mExecutingState->active()) { 3058 mCodec->mExecutingState->submitOutputBuffers(); 3059 } 3060 3061 mCodec->changeState(mCodec->mExecutingState); 3062 3063 return true; 3064 } 3065 3066 return false; 3067 } 3068 3069 default: 3070 return false; 3071 } 3072} 3073 3074//////////////////////////////////////////////////////////////////////////////// 3075 3076ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec) 3077 : BaseState(codec), 3078 mComponentNowIdle(false) { 3079} 3080 3081bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) { 3082 bool handled = false; 3083 3084 switch (msg->what()) { 3085 case kWhatFlush: 3086 { 3087 // Don't send me a flush request if you previously wanted me 3088 // to shutdown. 3089 TRESPASS(); 3090 break; 3091 } 3092 3093 case kWhatShutdown: 3094 { 3095 // We're already doing that... 3096 3097 handled = true; 3098 break; 3099 } 3100 3101 default: 3102 handled = BaseState::onMessageReceived(msg); 3103 break; 3104 } 3105 3106 return handled; 3107} 3108 3109void ACodec::ExecutingToIdleState::stateEntered() { 3110 ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str()); 3111 3112 mComponentNowIdle = false; 3113 mCodec->mSentFormat = false; 3114} 3115 3116bool ACodec::ExecutingToIdleState::onOMXEvent( 3117 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3118 switch (event) { 3119 case OMX_EventCmdComplete: 3120 { 3121 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 3122 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); 3123 3124 mComponentNowIdle = true; 3125 3126 changeStateIfWeOwnAllBuffers(); 3127 3128 return true; 3129 } 3130 3131 case OMX_EventPortSettingsChanged: 3132 case OMX_EventBufferFlag: 3133 { 3134 // We're shutting down and don't care about this anymore. 3135 return true; 3136 } 3137 3138 default: 3139 return BaseState::onOMXEvent(event, data1, data2); 3140 } 3141} 3142 3143void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() { 3144 if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) { 3145 CHECK_EQ(mCodec->mOMX->sendCommand( 3146 mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded), 3147 (status_t)OK); 3148 3149 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK); 3150 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK); 3151 3152 mCodec->changeState(mCodec->mIdleToLoadedState); 3153 } 3154} 3155 3156void ACodec::ExecutingToIdleState::onInputBufferFilled( 3157 const sp<AMessage> &msg) { 3158 BaseState::onInputBufferFilled(msg); 3159 3160 changeStateIfWeOwnAllBuffers(); 3161} 3162 3163void ACodec::ExecutingToIdleState::onOutputBufferDrained( 3164 const sp<AMessage> &msg) { 3165 BaseState::onOutputBufferDrained(msg); 3166 3167 changeStateIfWeOwnAllBuffers(); 3168} 3169 3170//////////////////////////////////////////////////////////////////////////////// 3171 3172ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec) 3173 : BaseState(codec) { 3174} 3175 3176bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) { 3177 bool handled = false; 3178 3179 switch (msg->what()) { 3180 case kWhatShutdown: 3181 { 3182 // We're already doing that... 3183 3184 handled = true; 3185 break; 3186 } 3187 3188 case kWhatFlush: 3189 { 3190 // Don't send me a flush request if you previously wanted me 3191 // to shutdown. 3192 TRESPASS(); 3193 break; 3194 } 3195 3196 default: 3197 handled = BaseState::onMessageReceived(msg); 3198 break; 3199 } 3200 3201 return handled; 3202} 3203 3204void ACodec::IdleToLoadedState::stateEntered() { 3205 ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str()); 3206} 3207 3208bool ACodec::IdleToLoadedState::onOMXEvent( 3209 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3210 switch (event) { 3211 case OMX_EventCmdComplete: 3212 { 3213 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 3214 CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded); 3215 3216 ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str()); 3217 3218 CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK); 3219 3220 mCodec->mNativeWindow.clear(); 3221 mCodec->mNode = NULL; 3222 mCodec->mOMX.clear(); 3223 mCodec->mComponentName.clear(); 3224 3225 mCodec->changeState(mCodec->mUninitializedState); 3226 3227 sp<AMessage> notify = mCodec->mNotify->dup(); 3228 notify->setInt32("what", ACodec::kWhatShutdownCompleted); 3229 notify->post(); 3230 3231 return true; 3232 } 3233 3234 default: 3235 return BaseState::onOMXEvent(event, data1, data2); 3236 } 3237} 3238 3239//////////////////////////////////////////////////////////////////////////////// 3240 3241ACodec::FlushingState::FlushingState(ACodec *codec) 3242 : BaseState(codec) { 3243} 3244 3245void ACodec::FlushingState::stateEntered() { 3246 ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str()); 3247 3248 mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false; 3249} 3250 3251bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) { 3252 bool handled = false; 3253 3254 switch (msg->what()) { 3255 case kWhatShutdown: 3256 { 3257 mCodec->deferMessage(msg); 3258 break; 3259 } 3260 3261 case kWhatFlush: 3262 { 3263 // We're already doing this right now. 3264 handled = true; 3265 break; 3266 } 3267 3268 default: 3269 handled = BaseState::onMessageReceived(msg); 3270 break; 3271 } 3272 3273 return handled; 3274} 3275 3276bool ACodec::FlushingState::onOMXEvent( 3277 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3278 ALOGV("[%s] FlushingState onOMXEvent(%d,%ld)", 3279 mCodec->mComponentName.c_str(), event, data1); 3280 3281 switch (event) { 3282 case OMX_EventCmdComplete: 3283 { 3284 CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush); 3285 3286 if (data2 == kPortIndexInput || data2 == kPortIndexOutput) { 3287 CHECK(!mFlushComplete[data2]); 3288 mFlushComplete[data2] = true; 3289 3290 if (mFlushComplete[kPortIndexInput] 3291 && mFlushComplete[kPortIndexOutput]) { 3292 changeStateIfWeOwnAllBuffers(); 3293 } 3294 } else { 3295 CHECK_EQ(data2, OMX_ALL); 3296 CHECK(mFlushComplete[kPortIndexInput]); 3297 CHECK(mFlushComplete[kPortIndexOutput]); 3298 3299 changeStateIfWeOwnAllBuffers(); 3300 } 3301 3302 return true; 3303 } 3304 3305 case OMX_EventPortSettingsChanged: 3306 { 3307 sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id()); 3308 msg->setInt32("type", omx_message::EVENT); 3309 msg->setPointer("node", mCodec->mNode); 3310 msg->setInt32("event", event); 3311 msg->setInt32("data1", data1); 3312 msg->setInt32("data2", data2); 3313 3314 ALOGV("[%s] Deferring OMX_EventPortSettingsChanged", 3315 mCodec->mComponentName.c_str()); 3316 3317 mCodec->deferMessage(msg); 3318 3319 return true; 3320 } 3321 3322 default: 3323 return BaseState::onOMXEvent(event, data1, data2); 3324 } 3325 3326 return true; 3327} 3328 3329void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) { 3330 BaseState::onOutputBufferDrained(msg); 3331 3332 changeStateIfWeOwnAllBuffers(); 3333} 3334 3335void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) { 3336 BaseState::onInputBufferFilled(msg); 3337 3338 changeStateIfWeOwnAllBuffers(); 3339} 3340 3341void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() { 3342 if (mFlushComplete[kPortIndexInput] 3343 && mFlushComplete[kPortIndexOutput] 3344 && mCodec->allYourBuffersAreBelongToUs()) { 3345 sp<AMessage> notify = mCodec->mNotify->dup(); 3346 notify->setInt32("what", ACodec::kWhatFlushCompleted); 3347 notify->post(); 3348 3349 mCodec->mPortEOS[kPortIndexInput] = 3350 mCodec->mPortEOS[kPortIndexOutput] = false; 3351 3352 mCodec->mInputEOSResult = OK; 3353 3354 mCodec->changeState(mCodec->mExecutingState); 3355 } 3356} 3357 3358} // namespace android 3359