ACodec.cpp revision 5778822d86b0337407514b9372562b86edfa91cd
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->setObject(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->setObject("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<RefBase> obj; 2162 int32_t err = OK; 2163 bool eos = false; 2164 2165 if (!msg->findObject("buffer", &obj)) { 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 obj.clear(); 2172 2173 eos = true; 2174 } 2175 2176 sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get()); 2177 2178 int32_t tmp; 2179 if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) { 2180 eos = true; 2181 err = ERROR_END_OF_STREAM; 2182 } 2183 2184 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID); 2185 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM); 2186 2187 info->mStatus = BufferInfo::OWNED_BY_US; 2188 2189 PortMode mode = getPortMode(kPortIndexInput); 2190 2191 switch (mode) { 2192 case KEEP_BUFFERS: 2193 { 2194 if (eos) { 2195 if (!mCodec->mPortEOS[kPortIndexInput]) { 2196 mCodec->mPortEOS[kPortIndexInput] = true; 2197 mCodec->mInputEOSResult = err; 2198 } 2199 } 2200 break; 2201 } 2202 2203 case RESUBMIT_BUFFERS: 2204 { 2205 if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) { 2206 int64_t timeUs; 2207 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 2208 2209 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME; 2210 2211 int32_t isCSD; 2212 if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) { 2213 flags |= OMX_BUFFERFLAG_CODECCONFIG; 2214 } 2215 2216 if (eos) { 2217 flags |= OMX_BUFFERFLAG_EOS; 2218 } 2219 2220 if (buffer != info->mData) { 2221 if (0 && !(flags & OMX_BUFFERFLAG_CODECCONFIG)) { 2222 ALOGV("[%s] Needs to copy input data.", 2223 mCodec->mComponentName.c_str()); 2224 } 2225 2226 CHECK_LE(buffer->size(), info->mData->capacity()); 2227 memcpy(info->mData->data(), buffer->data(), buffer->size()); 2228 } 2229 2230 if (flags & OMX_BUFFERFLAG_CODECCONFIG) { 2231 ALOGV("[%s] calling emptyBuffer %p w/ codec specific data", 2232 mCodec->mComponentName.c_str(), bufferID); 2233 } else if (flags & OMX_BUFFERFLAG_EOS) { 2234 ALOGV("[%s] calling emptyBuffer %p w/ EOS", 2235 mCodec->mComponentName.c_str(), bufferID); 2236 } else { 2237 ALOGV("[%s] calling emptyBuffer %p w/ time %lld us", 2238 mCodec->mComponentName.c_str(), bufferID, timeUs); 2239 } 2240 2241 CHECK_EQ(mCodec->mOMX->emptyBuffer( 2242 mCodec->mNode, 2243 bufferID, 2244 0, 2245 buffer->size(), 2246 flags, 2247 timeUs), 2248 (status_t)OK); 2249 2250 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 2251 2252 if (!eos) { 2253 getMoreInputDataIfPossible(); 2254 } else { 2255 ALOGV("[%s] Signalled EOS on the input port", 2256 mCodec->mComponentName.c_str()); 2257 2258 mCodec->mPortEOS[kPortIndexInput] = true; 2259 mCodec->mInputEOSResult = err; 2260 } 2261 } else if (!mCodec->mPortEOS[kPortIndexInput]) { 2262 if (err != ERROR_END_OF_STREAM) { 2263 ALOGV("[%s] Signalling EOS on the input port " 2264 "due to error %d", 2265 mCodec->mComponentName.c_str(), err); 2266 } else { 2267 ALOGV("[%s] Signalling EOS on the input port", 2268 mCodec->mComponentName.c_str()); 2269 } 2270 2271 ALOGV("[%s] calling emptyBuffer %p signalling EOS", 2272 mCodec->mComponentName.c_str(), bufferID); 2273 2274 CHECK_EQ(mCodec->mOMX->emptyBuffer( 2275 mCodec->mNode, 2276 bufferID, 2277 0, 2278 0, 2279 OMX_BUFFERFLAG_EOS, 2280 0), 2281 (status_t)OK); 2282 2283 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 2284 2285 mCodec->mPortEOS[kPortIndexInput] = true; 2286 mCodec->mInputEOSResult = err; 2287 } 2288 break; 2289 2290 default: 2291 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 2292 break; 2293 } 2294 } 2295} 2296 2297void ACodec::BaseState::getMoreInputDataIfPossible() { 2298 if (mCodec->mPortEOS[kPortIndexInput]) { 2299 return; 2300 } 2301 2302 BufferInfo *eligible = NULL; 2303 2304 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 2305 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 2306 2307#if 0 2308 if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) { 2309 // There's already a "read" pending. 2310 return; 2311 } 2312#endif 2313 2314 if (info->mStatus == BufferInfo::OWNED_BY_US) { 2315 eligible = info; 2316 } 2317 } 2318 2319 if (eligible == NULL) { 2320 return; 2321 } 2322 2323 postFillThisBuffer(eligible); 2324} 2325 2326bool ACodec::BaseState::onOMXFillBufferDone( 2327 IOMX::buffer_id bufferID, 2328 size_t rangeOffset, size_t rangeLength, 2329 OMX_U32 flags, 2330 int64_t timeUs, 2331 void *platformPrivate, 2332 void *dataPtr) { 2333 ALOGV("[%s] onOMXFillBufferDone %p time %lld us, flags = 0x%08lx", 2334 mCodec->mComponentName.c_str(), bufferID, timeUs, flags); 2335 2336 ssize_t index; 2337 BufferInfo *info = 2338 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 2339 2340 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); 2341 2342 info->mStatus = BufferInfo::OWNED_BY_US; 2343 2344 PortMode mode = getPortMode(kPortIndexOutput); 2345 2346 switch (mode) { 2347 case KEEP_BUFFERS: 2348 break; 2349 2350 case RESUBMIT_BUFFERS: 2351 { 2352 if (rangeLength == 0 && !(flags & OMX_BUFFERFLAG_EOS)) { 2353 ALOGV("[%s] calling fillBuffer %p", 2354 mCodec->mComponentName.c_str(), info->mBufferID); 2355 2356 CHECK_EQ(mCodec->mOMX->fillBuffer( 2357 mCodec->mNode, info->mBufferID), 2358 (status_t)OK); 2359 2360 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 2361 break; 2362 } 2363 2364 if (!mCodec->mIsEncoder && !mCodec->mSentFormat) { 2365 mCodec->sendFormatChange(); 2366 } 2367 2368 if (mCodec->mNativeWindow == NULL) { 2369 info->mData->setRange(rangeOffset, rangeLength); 2370 } 2371 2372 info->mData->meta()->setInt64("timeUs", timeUs); 2373 2374 sp<AMessage> notify = mCodec->mNotify->dup(); 2375 notify->setInt32("what", ACodec::kWhatDrainThisBuffer); 2376 notify->setPointer("buffer-id", info->mBufferID); 2377 notify->setObject("buffer", info->mData); 2378 notify->setInt32("flags", flags); 2379 2380 sp<AMessage> reply = 2381 new AMessage(kWhatOutputBufferDrained, mCodec->id()); 2382 2383 reply->setPointer("buffer-id", info->mBufferID); 2384 2385 notify->setMessage("reply", reply); 2386 2387 notify->post(); 2388 2389 info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM; 2390 2391 if (flags & OMX_BUFFERFLAG_EOS) { 2392 ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str()); 2393 2394 sp<AMessage> notify = mCodec->mNotify->dup(); 2395 notify->setInt32("what", ACodec::kWhatEOS); 2396 notify->setInt32("err", mCodec->mInputEOSResult); 2397 notify->post(); 2398 2399 mCodec->mPortEOS[kPortIndexOutput] = true; 2400 } 2401 break; 2402 } 2403 2404 default: 2405 { 2406 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 2407 2408 CHECK_EQ((status_t)OK, 2409 mCodec->freeBuffer(kPortIndexOutput, index)); 2410 break; 2411 } 2412 } 2413 2414 return true; 2415} 2416 2417void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { 2418 IOMX::buffer_id bufferID; 2419 CHECK(msg->findPointer("buffer-id", &bufferID)); 2420 2421 ssize_t index; 2422 BufferInfo *info = 2423 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 2424 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM); 2425 2426 int32_t render; 2427 if (mCodec->mNativeWindow != NULL 2428 && msg->findInt32("render", &render) && render != 0) { 2429 // The client wants this buffer to be rendered. 2430 2431 status_t err; 2432 if ((err = mCodec->mNativeWindow->queueBuffer( 2433 mCodec->mNativeWindow.get(), 2434 info->mGraphicBuffer.get())) == OK) { 2435 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 2436 } else { 2437 mCodec->signalError(OMX_ErrorUndefined, err); 2438 info->mStatus = BufferInfo::OWNED_BY_US; 2439 } 2440 } else { 2441 info->mStatus = BufferInfo::OWNED_BY_US; 2442 } 2443 2444 PortMode mode = getPortMode(kPortIndexOutput); 2445 2446 switch (mode) { 2447 case KEEP_BUFFERS: 2448 { 2449 // XXX fishy, revisit!!! What about the FREE_BUFFERS case below? 2450 2451 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 2452 // We cannot resubmit the buffer we just rendered, dequeue 2453 // the spare instead. 2454 2455 info = mCodec->dequeueBufferFromNativeWindow(); 2456 } 2457 break; 2458 } 2459 2460 case RESUBMIT_BUFFERS: 2461 { 2462 if (!mCodec->mPortEOS[kPortIndexOutput]) { 2463 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 2464 // We cannot resubmit the buffer we just rendered, dequeue 2465 // the spare instead. 2466 2467 info = mCodec->dequeueBufferFromNativeWindow(); 2468 } 2469 2470 if (info != NULL) { 2471 ALOGV("[%s] calling fillBuffer %p", 2472 mCodec->mComponentName.c_str(), info->mBufferID); 2473 2474 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), 2475 (status_t)OK); 2476 2477 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 2478 } 2479 } 2480 break; 2481 } 2482 2483 default: 2484 { 2485 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 2486 2487 CHECK_EQ((status_t)OK, 2488 mCodec->freeBuffer(kPortIndexOutput, index)); 2489 break; 2490 } 2491 } 2492} 2493 2494//////////////////////////////////////////////////////////////////////////////// 2495 2496ACodec::UninitializedState::UninitializedState(ACodec *codec) 2497 : BaseState(codec) { 2498} 2499 2500bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) { 2501 bool handled = false; 2502 2503 switch (msg->what()) { 2504 case ACodec::kWhatSetup: 2505 { 2506 onSetup(msg); 2507 2508 handled = true; 2509 break; 2510 } 2511 2512 case ACodec::kWhatAllocateComponent: 2513 { 2514 onAllocateComponent(msg); 2515 handled = true; 2516 break; 2517 } 2518 2519 case ACodec::kWhatConfigureComponent: 2520 { 2521 onConfigureComponent(msg); 2522 handled = true; 2523 break; 2524 } 2525 2526 case ACodec::kWhatStart: 2527 { 2528 onStart(); 2529 handled = true; 2530 break; 2531 } 2532 2533 case ACodec::kWhatShutdown: 2534 { 2535 sp<AMessage> notify = mCodec->mNotify->dup(); 2536 notify->setInt32("what", ACodec::kWhatShutdownCompleted); 2537 notify->post(); 2538 2539 handled = true; 2540 break; 2541 } 2542 2543 case ACodec::kWhatFlush: 2544 { 2545 sp<AMessage> notify = mCodec->mNotify->dup(); 2546 notify->setInt32("what", ACodec::kWhatFlushCompleted); 2547 notify->post(); 2548 2549 handled = true; 2550 break; 2551 } 2552 2553 default: 2554 return BaseState::onMessageReceived(msg); 2555 } 2556 2557 return handled; 2558} 2559 2560void ACodec::UninitializedState::onSetup( 2561 const sp<AMessage> &msg) { 2562 onAllocateComponent(msg); 2563 onConfigureComponent(msg); 2564 onStart(); 2565} 2566 2567void ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) { 2568 ALOGV("onAllocateComponent"); 2569 2570 if (mCodec->mNode != NULL) { 2571 CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK); 2572 2573 mCodec->mNativeWindow.clear(); 2574 mCodec->mNode = NULL; 2575 mCodec->mOMX.clear(); 2576 mCodec->mComponentName.clear(); 2577 } 2578 2579 OMXClient client; 2580 CHECK_EQ(client.connect(), (status_t)OK); 2581 2582 sp<IOMX> omx = client.interface(); 2583 2584 Vector<String8> matchingCodecs; 2585 2586 AString mime; 2587 2588 AString componentName; 2589 if (msg->findString("componentName", &componentName)) { 2590 matchingCodecs.push_back(String8(componentName.c_str())); 2591 } else { 2592 CHECK(msg->findString("mime", &mime)); 2593 2594 int32_t encoder; 2595 if (!msg->findInt32("encoder", &encoder)) { 2596 encoder = false; 2597 } 2598 2599 OMXCodec::findMatchingCodecs( 2600 mime.c_str(), 2601 encoder, // createEncoder 2602 NULL, // matchComponentName 2603 0, // flags 2604 &matchingCodecs); 2605 } 2606 2607 sp<CodecObserver> observer = new CodecObserver; 2608 IOMX::node_id node = NULL; 2609 2610 for (size_t matchIndex = 0; matchIndex < matchingCodecs.size(); 2611 ++matchIndex) { 2612 componentName = matchingCodecs.itemAt(matchIndex).string(); 2613 2614 pid_t tid = androidGetTid(); 2615 int prevPriority = androidGetThreadPriority(tid); 2616 androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND); 2617 status_t err = omx->allocateNode(componentName.c_str(), observer, &node); 2618 androidSetThreadPriority(tid, prevPriority); 2619 2620 if (err == OK) { 2621 break; 2622 } 2623 2624 node = NULL; 2625 } 2626 2627 if (node == NULL) { 2628 if (!mime.empty()) { 2629 ALOGE("Unable to instantiate a decoder for type '%s'.", 2630 mime.c_str()); 2631 } else { 2632 ALOGE("Unable to instantiate decoder '%s'.", componentName.c_str()); 2633 } 2634 2635 mCodec->signalError(OMX_ErrorComponentNotFound); 2636 return; 2637 } 2638 2639 sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id()); 2640 observer->setNotificationMessage(notify); 2641 2642 mCodec->mComponentName = componentName; 2643 mCodec->mOMX = omx; 2644 mCodec->mNode = node; 2645 2646 mCodec->mPortEOS[kPortIndexInput] = 2647 mCodec->mPortEOS[kPortIndexOutput] = false; 2648 2649 mCodec->mInputEOSResult = OK; 2650 2651 { 2652 sp<AMessage> notify = mCodec->mNotify->dup(); 2653 notify->setInt32("what", ACodec::kWhatComponentAllocated); 2654 notify->setString("componentName", mCodec->mComponentName.c_str()); 2655 notify->post(); 2656 } 2657} 2658 2659void ACodec::UninitializedState::onConfigureComponent( 2660 const sp<AMessage> &msg) { 2661 ALOGV("onConfigureComponent"); 2662 2663 CHECK(mCodec->mNode != NULL); 2664 2665 AString mime; 2666 CHECK(msg->findString("mime", &mime)); 2667 2668 status_t err = mCodec->configureCodec(mime.c_str(), msg); 2669 2670 if (err != OK) { 2671 mCodec->signalError(OMX_ErrorUndefined, err); 2672 return; 2673 } 2674 2675 sp<RefBase> obj; 2676 if (msg->findObject("native-window", &obj) 2677 && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) { 2678 sp<NativeWindowWrapper> nativeWindow( 2679 static_cast<NativeWindowWrapper *>(obj.get())); 2680 CHECK(nativeWindow != NULL); 2681 mCodec->mNativeWindow = nativeWindow->getNativeWindow(); 2682 } 2683 CHECK_EQ((status_t)OK, mCodec->initNativeWindow()); 2684 2685 { 2686 sp<AMessage> notify = mCodec->mNotify->dup(); 2687 notify->setInt32("what", ACodec::kWhatComponentConfigured); 2688 notify->post(); 2689 } 2690} 2691 2692void ACodec::UninitializedState::onStart() { 2693 ALOGV("onStart"); 2694 2695 CHECK_EQ(mCodec->mOMX->sendCommand( 2696 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle), 2697 (status_t)OK); 2698 2699 mCodec->changeState(mCodec->mLoadedToIdleState); 2700} 2701 2702//////////////////////////////////////////////////////////////////////////////// 2703 2704ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec) 2705 : BaseState(codec) { 2706} 2707 2708void ACodec::LoadedToIdleState::stateEntered() { 2709 ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str()); 2710 2711 status_t err; 2712 if ((err = allocateBuffers()) != OK) { 2713 ALOGE("Failed to allocate buffers after transitioning to IDLE state " 2714 "(error 0x%08x)", 2715 err); 2716 2717 mCodec->signalError(OMX_ErrorUndefined, err); 2718 } 2719} 2720 2721status_t ACodec::LoadedToIdleState::allocateBuffers() { 2722 status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput); 2723 2724 if (err != OK) { 2725 return err; 2726 } 2727 2728 return mCodec->allocateBuffersOnPort(kPortIndexOutput); 2729} 2730 2731bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) { 2732 switch (msg->what()) { 2733 case kWhatShutdown: 2734 { 2735 mCodec->deferMessage(msg); 2736 return true; 2737 } 2738 2739 default: 2740 return BaseState::onMessageReceived(msg); 2741 } 2742} 2743 2744bool ACodec::LoadedToIdleState::onOMXEvent( 2745 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 2746 switch (event) { 2747 case OMX_EventCmdComplete: 2748 { 2749 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 2750 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); 2751 2752 CHECK_EQ(mCodec->mOMX->sendCommand( 2753 mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting), 2754 (status_t)OK); 2755 2756 mCodec->changeState(mCodec->mIdleToExecutingState); 2757 2758 return true; 2759 } 2760 2761 default: 2762 return BaseState::onOMXEvent(event, data1, data2); 2763 } 2764} 2765 2766//////////////////////////////////////////////////////////////////////////////// 2767 2768ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec) 2769 : BaseState(codec) { 2770} 2771 2772void ACodec::IdleToExecutingState::stateEntered() { 2773 ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str()); 2774} 2775 2776bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) { 2777 switch (msg->what()) { 2778 case kWhatShutdown: 2779 { 2780 mCodec->deferMessage(msg); 2781 return true; 2782 } 2783 2784 default: 2785 return BaseState::onMessageReceived(msg); 2786 } 2787} 2788 2789bool ACodec::IdleToExecutingState::onOMXEvent( 2790 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 2791 switch (event) { 2792 case OMX_EventCmdComplete: 2793 { 2794 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 2795 CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting); 2796 2797 mCodec->mExecutingState->resume(); 2798 mCodec->changeState(mCodec->mExecutingState); 2799 2800 return true; 2801 } 2802 2803 default: 2804 return BaseState::onOMXEvent(event, data1, data2); 2805 } 2806} 2807 2808//////////////////////////////////////////////////////////////////////////////// 2809 2810ACodec::ExecutingState::ExecutingState(ACodec *codec) 2811 : BaseState(codec), 2812 mActive(false) { 2813} 2814 2815ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode( 2816 OMX_U32 portIndex) { 2817 return RESUBMIT_BUFFERS; 2818} 2819 2820void ACodec::ExecutingState::submitOutputBuffers() { 2821 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) { 2822 BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i); 2823 2824 if (mCodec->mNativeWindow != NULL) { 2825 CHECK(info->mStatus == BufferInfo::OWNED_BY_US 2826 || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW); 2827 2828 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 2829 continue; 2830 } 2831 2832 status_t err = mCodec->mNativeWindow->lockBuffer( 2833 mCodec->mNativeWindow.get(), 2834 info->mGraphicBuffer.get()); 2835 CHECK_EQ(err, (status_t)OK); 2836 } else { 2837 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 2838 } 2839 2840 ALOGV("[%s] calling fillBuffer %p", 2841 mCodec->mComponentName.c_str(), info->mBufferID); 2842 2843 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), 2844 (status_t)OK); 2845 2846 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 2847 } 2848} 2849 2850void ACodec::ExecutingState::resume() { 2851 if (mActive) { 2852 ALOGV("[%s] We're already active, no need to resume.", 2853 mCodec->mComponentName.c_str()); 2854 2855 return; 2856 } 2857 2858 submitOutputBuffers(); 2859 2860 // Post the first input buffer. 2861 CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u); 2862 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0); 2863 2864 postFillThisBuffer(info); 2865 2866 mActive = true; 2867} 2868 2869void ACodec::ExecutingState::stateEntered() { 2870 ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str()); 2871 2872 mCodec->processDeferredMessages(); 2873} 2874 2875bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) { 2876 bool handled = false; 2877 2878 switch (msg->what()) { 2879 case kWhatShutdown: 2880 { 2881 mActive = false; 2882 2883 CHECK_EQ(mCodec->mOMX->sendCommand( 2884 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle), 2885 (status_t)OK); 2886 2887 mCodec->changeState(mCodec->mExecutingToIdleState); 2888 2889 handled = true; 2890 break; 2891 } 2892 2893 case kWhatFlush: 2894 { 2895 ALOGV("[%s] ExecutingState flushing now " 2896 "(codec owns %d/%d input, %d/%d output).", 2897 mCodec->mComponentName.c_str(), 2898 mCodec->countBuffersOwnedByComponent(kPortIndexInput), 2899 mCodec->mBuffers[kPortIndexInput].size(), 2900 mCodec->countBuffersOwnedByComponent(kPortIndexOutput), 2901 mCodec->mBuffers[kPortIndexOutput].size()); 2902 2903 mActive = false; 2904 2905 CHECK_EQ(mCodec->mOMX->sendCommand( 2906 mCodec->mNode, OMX_CommandFlush, OMX_ALL), 2907 (status_t)OK); 2908 2909 mCodec->changeState(mCodec->mFlushingState); 2910 2911 handled = true; 2912 break; 2913 } 2914 2915 case kWhatResume: 2916 { 2917 resume(); 2918 2919 handled = true; 2920 break; 2921 } 2922 2923 default: 2924 handled = BaseState::onMessageReceived(msg); 2925 break; 2926 } 2927 2928 return handled; 2929} 2930 2931bool ACodec::ExecutingState::onOMXEvent( 2932 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 2933 switch (event) { 2934 case OMX_EventPortSettingsChanged: 2935 { 2936 CHECK_EQ(data1, (OMX_U32)kPortIndexOutput); 2937 2938 if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) { 2939 CHECK_EQ(mCodec->mOMX->sendCommand( 2940 mCodec->mNode, 2941 OMX_CommandPortDisable, kPortIndexOutput), 2942 (status_t)OK); 2943 2944 mCodec->freeOutputBuffersNotOwnedByComponent(); 2945 2946 mCodec->changeState(mCodec->mOutputPortSettingsChangedState); 2947 } else if (data2 == OMX_IndexConfigCommonOutputCrop) { 2948 mCodec->mSentFormat = false; 2949 } else { 2950 ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx", 2951 mCodec->mComponentName.c_str(), data2); 2952 } 2953 2954 return true; 2955 } 2956 2957 case OMX_EventBufferFlag: 2958 { 2959 return true; 2960 } 2961 2962 default: 2963 return BaseState::onOMXEvent(event, data1, data2); 2964 } 2965} 2966 2967//////////////////////////////////////////////////////////////////////////////// 2968 2969ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState( 2970 ACodec *codec) 2971 : BaseState(codec) { 2972} 2973 2974ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode( 2975 OMX_U32 portIndex) { 2976 if (portIndex == kPortIndexOutput) { 2977 return FREE_BUFFERS; 2978 } 2979 2980 CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput); 2981 2982 return RESUBMIT_BUFFERS; 2983} 2984 2985bool ACodec::OutputPortSettingsChangedState::onMessageReceived( 2986 const sp<AMessage> &msg) { 2987 bool handled = false; 2988 2989 switch (msg->what()) { 2990 case kWhatFlush: 2991 case kWhatShutdown: 2992 case kWhatResume: 2993 { 2994 if (msg->what() == kWhatResume) { 2995 ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str()); 2996 } 2997 2998 mCodec->deferMessage(msg); 2999 handled = true; 3000 break; 3001 } 3002 3003 default: 3004 handled = BaseState::onMessageReceived(msg); 3005 break; 3006 } 3007 3008 return handled; 3009} 3010 3011void ACodec::OutputPortSettingsChangedState::stateEntered() { 3012 ALOGV("[%s] Now handling output port settings change", 3013 mCodec->mComponentName.c_str()); 3014} 3015 3016bool ACodec::OutputPortSettingsChangedState::onOMXEvent( 3017 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3018 switch (event) { 3019 case OMX_EventCmdComplete: 3020 { 3021 if (data1 == (OMX_U32)OMX_CommandPortDisable) { 3022 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput); 3023 3024 ALOGV("[%s] Output port now disabled.", 3025 mCodec->mComponentName.c_str()); 3026 3027 CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty()); 3028 mCodec->mDealer[kPortIndexOutput].clear(); 3029 3030 CHECK_EQ(mCodec->mOMX->sendCommand( 3031 mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput), 3032 (status_t)OK); 3033 3034 status_t err; 3035 if ((err = mCodec->allocateBuffersOnPort( 3036 kPortIndexOutput)) != OK) { 3037 ALOGE("Failed to allocate output port buffers after " 3038 "port reconfiguration (error 0x%08x)", 3039 err); 3040 3041 mCodec->signalError(OMX_ErrorUndefined, err); 3042 3043 // This is technically not correct, since we were unable 3044 // to allocate output buffers and therefore the output port 3045 // remains disabled. It is necessary however to allow us 3046 // to shutdown the codec properly. 3047 mCodec->changeState(mCodec->mExecutingState); 3048 } 3049 3050 return true; 3051 } else if (data1 == (OMX_U32)OMX_CommandPortEnable) { 3052 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput); 3053 3054 mCodec->mSentFormat = false; 3055 3056 ALOGV("[%s] Output port now reenabled.", 3057 mCodec->mComponentName.c_str()); 3058 3059 if (mCodec->mExecutingState->active()) { 3060 mCodec->mExecutingState->submitOutputBuffers(); 3061 } 3062 3063 mCodec->changeState(mCodec->mExecutingState); 3064 3065 return true; 3066 } 3067 3068 return false; 3069 } 3070 3071 default: 3072 return false; 3073 } 3074} 3075 3076//////////////////////////////////////////////////////////////////////////////// 3077 3078ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec) 3079 : BaseState(codec), 3080 mComponentNowIdle(false) { 3081} 3082 3083bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) { 3084 bool handled = false; 3085 3086 switch (msg->what()) { 3087 case kWhatFlush: 3088 { 3089 // Don't send me a flush request if you previously wanted me 3090 // to shutdown. 3091 TRESPASS(); 3092 break; 3093 } 3094 3095 case kWhatShutdown: 3096 { 3097 // We're already doing that... 3098 3099 handled = true; 3100 break; 3101 } 3102 3103 default: 3104 handled = BaseState::onMessageReceived(msg); 3105 break; 3106 } 3107 3108 return handled; 3109} 3110 3111void ACodec::ExecutingToIdleState::stateEntered() { 3112 ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str()); 3113 3114 mComponentNowIdle = false; 3115 mCodec->mSentFormat = false; 3116} 3117 3118bool ACodec::ExecutingToIdleState::onOMXEvent( 3119 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3120 switch (event) { 3121 case OMX_EventCmdComplete: 3122 { 3123 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 3124 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); 3125 3126 mComponentNowIdle = true; 3127 3128 changeStateIfWeOwnAllBuffers(); 3129 3130 return true; 3131 } 3132 3133 case OMX_EventPortSettingsChanged: 3134 case OMX_EventBufferFlag: 3135 { 3136 // We're shutting down and don't care about this anymore. 3137 return true; 3138 } 3139 3140 default: 3141 return BaseState::onOMXEvent(event, data1, data2); 3142 } 3143} 3144 3145void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() { 3146 if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) { 3147 CHECK_EQ(mCodec->mOMX->sendCommand( 3148 mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded), 3149 (status_t)OK); 3150 3151 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK); 3152 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK); 3153 3154 mCodec->changeState(mCodec->mIdleToLoadedState); 3155 } 3156} 3157 3158void ACodec::ExecutingToIdleState::onInputBufferFilled( 3159 const sp<AMessage> &msg) { 3160 BaseState::onInputBufferFilled(msg); 3161 3162 changeStateIfWeOwnAllBuffers(); 3163} 3164 3165void ACodec::ExecutingToIdleState::onOutputBufferDrained( 3166 const sp<AMessage> &msg) { 3167 BaseState::onOutputBufferDrained(msg); 3168 3169 changeStateIfWeOwnAllBuffers(); 3170} 3171 3172//////////////////////////////////////////////////////////////////////////////// 3173 3174ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec) 3175 : BaseState(codec) { 3176} 3177 3178bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) { 3179 bool handled = false; 3180 3181 switch (msg->what()) { 3182 case kWhatShutdown: 3183 { 3184 // We're already doing that... 3185 3186 handled = true; 3187 break; 3188 } 3189 3190 case kWhatFlush: 3191 { 3192 // Don't send me a flush request if you previously wanted me 3193 // to shutdown. 3194 TRESPASS(); 3195 break; 3196 } 3197 3198 default: 3199 handled = BaseState::onMessageReceived(msg); 3200 break; 3201 } 3202 3203 return handled; 3204} 3205 3206void ACodec::IdleToLoadedState::stateEntered() { 3207 ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str()); 3208} 3209 3210bool ACodec::IdleToLoadedState::onOMXEvent( 3211 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3212 switch (event) { 3213 case OMX_EventCmdComplete: 3214 { 3215 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 3216 CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded); 3217 3218 ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str()); 3219 3220 CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK); 3221 3222 mCodec->mNativeWindow.clear(); 3223 mCodec->mNode = NULL; 3224 mCodec->mOMX.clear(); 3225 mCodec->mComponentName.clear(); 3226 3227 mCodec->changeState(mCodec->mUninitializedState); 3228 3229 sp<AMessage> notify = mCodec->mNotify->dup(); 3230 notify->setInt32("what", ACodec::kWhatShutdownCompleted); 3231 notify->post(); 3232 3233 return true; 3234 } 3235 3236 default: 3237 return BaseState::onOMXEvent(event, data1, data2); 3238 } 3239} 3240 3241//////////////////////////////////////////////////////////////////////////////// 3242 3243ACodec::FlushingState::FlushingState(ACodec *codec) 3244 : BaseState(codec) { 3245} 3246 3247void ACodec::FlushingState::stateEntered() { 3248 ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str()); 3249 3250 mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false; 3251} 3252 3253bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) { 3254 bool handled = false; 3255 3256 switch (msg->what()) { 3257 case kWhatShutdown: 3258 { 3259 mCodec->deferMessage(msg); 3260 break; 3261 } 3262 3263 case kWhatFlush: 3264 { 3265 // We're already doing this right now. 3266 handled = true; 3267 break; 3268 } 3269 3270 default: 3271 handled = BaseState::onMessageReceived(msg); 3272 break; 3273 } 3274 3275 return handled; 3276} 3277 3278bool ACodec::FlushingState::onOMXEvent( 3279 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3280 ALOGV("[%s] FlushingState onOMXEvent(%d,%ld)", 3281 mCodec->mComponentName.c_str(), event, data1); 3282 3283 switch (event) { 3284 case OMX_EventCmdComplete: 3285 { 3286 CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush); 3287 3288 if (data2 == kPortIndexInput || data2 == kPortIndexOutput) { 3289 CHECK(!mFlushComplete[data2]); 3290 mFlushComplete[data2] = true; 3291 3292 if (mFlushComplete[kPortIndexInput] 3293 && mFlushComplete[kPortIndexOutput]) { 3294 changeStateIfWeOwnAllBuffers(); 3295 } 3296 } else { 3297 CHECK_EQ(data2, OMX_ALL); 3298 CHECK(mFlushComplete[kPortIndexInput]); 3299 CHECK(mFlushComplete[kPortIndexOutput]); 3300 3301 changeStateIfWeOwnAllBuffers(); 3302 } 3303 3304 return true; 3305 } 3306 3307 case OMX_EventPortSettingsChanged: 3308 { 3309 sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id()); 3310 msg->setInt32("type", omx_message::EVENT); 3311 msg->setPointer("node", mCodec->mNode); 3312 msg->setInt32("event", event); 3313 msg->setInt32("data1", data1); 3314 msg->setInt32("data2", data2); 3315 3316 ALOGV("[%s] Deferring OMX_EventPortSettingsChanged", 3317 mCodec->mComponentName.c_str()); 3318 3319 mCodec->deferMessage(msg); 3320 3321 return true; 3322 } 3323 3324 default: 3325 return BaseState::onOMXEvent(event, data1, data2); 3326 } 3327 3328 return true; 3329} 3330 3331void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) { 3332 BaseState::onOutputBufferDrained(msg); 3333 3334 changeStateIfWeOwnAllBuffers(); 3335} 3336 3337void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) { 3338 BaseState::onInputBufferFilled(msg); 3339 3340 changeStateIfWeOwnAllBuffers(); 3341} 3342 3343void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() { 3344 if (mFlushComplete[kPortIndexInput] 3345 && mFlushComplete[kPortIndexOutput] 3346 && mCodec->allYourBuffersAreBelongToUs()) { 3347 sp<AMessage> notify = mCodec->mNotify->dup(); 3348 notify->setInt32("what", ACodec::kWhatFlushCompleted); 3349 notify->post(); 3350 3351 mCodec->mPortEOS[kPortIndexInput] = 3352 mCodec->mPortEOS[kPortIndexOutput] = false; 3353 3354 mCodec->mInputEOSResult = OK; 3355 3356 mCodec->changeState(mCodec->mExecutingState); 3357 } 3358} 3359 3360} // namespace android 3361