ACodec.cpp revision 3c09d025b60dedc605e893d630177bd54552f061
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/BufferProducerWrapper.h> 30#include <media/stagefright/MediaCodecList.h> 31#include <media/stagefright/MediaDefs.h> 32#include <media/stagefright/NativeWindowWrapper.h> 33#include <media/stagefright/OMXClient.h> 34#include <media/stagefright/OMXCodec.h> 35 36#include <media/hardware/HardwareAPI.h> 37 38#include <OMX_Component.h> 39 40#include "include/avc_utils.h" 41 42namespace android { 43 44template<class T> 45static void InitOMXParams(T *params) { 46 params->nSize = sizeof(T); 47 params->nVersion.s.nVersionMajor = 1; 48 params->nVersion.s.nVersionMinor = 0; 49 params->nVersion.s.nRevision = 0; 50 params->nVersion.s.nStep = 0; 51} 52 53struct CodecObserver : public BnOMXObserver { 54 CodecObserver() {} 55 56 void setNotificationMessage(const sp<AMessage> &msg) { 57 mNotify = msg; 58 } 59 60 // from IOMXObserver 61 virtual void onMessage(const omx_message &omx_msg) { 62 sp<AMessage> msg = mNotify->dup(); 63 64 msg->setInt32("type", omx_msg.type); 65 msg->setPointer("node", omx_msg.node); 66 67 switch (omx_msg.type) { 68 case omx_message::EVENT: 69 { 70 msg->setInt32("event", omx_msg.u.event_data.event); 71 msg->setInt32("data1", omx_msg.u.event_data.data1); 72 msg->setInt32("data2", omx_msg.u.event_data.data2); 73 break; 74 } 75 76 case omx_message::EMPTY_BUFFER_DONE: 77 { 78 msg->setPointer("buffer", omx_msg.u.buffer_data.buffer); 79 break; 80 } 81 82 case omx_message::FILL_BUFFER_DONE: 83 { 84 msg->setPointer( 85 "buffer", omx_msg.u.extended_buffer_data.buffer); 86 msg->setInt32( 87 "range_offset", 88 omx_msg.u.extended_buffer_data.range_offset); 89 msg->setInt32( 90 "range_length", 91 omx_msg.u.extended_buffer_data.range_length); 92 msg->setInt32( 93 "flags", 94 omx_msg.u.extended_buffer_data.flags); 95 msg->setInt64( 96 "timestamp", 97 omx_msg.u.extended_buffer_data.timestamp); 98 msg->setPointer( 99 "platform_private", 100 omx_msg.u.extended_buffer_data.platform_private); 101 msg->setPointer( 102 "data_ptr", 103 omx_msg.u.extended_buffer_data.data_ptr); 104 break; 105 } 106 107 default: 108 TRESPASS(); 109 break; 110 } 111 112 msg->post(); 113 } 114 115protected: 116 virtual ~CodecObserver() {} 117 118private: 119 sp<AMessage> mNotify; 120 121 DISALLOW_EVIL_CONSTRUCTORS(CodecObserver); 122}; 123 124//////////////////////////////////////////////////////////////////////////////// 125 126struct ACodec::BaseState : public AState { 127 BaseState(ACodec *codec, const sp<AState> &parentState = NULL); 128 129protected: 130 enum PortMode { 131 KEEP_BUFFERS, 132 RESUBMIT_BUFFERS, 133 FREE_BUFFERS, 134 }; 135 136 ACodec *mCodec; 137 138 virtual PortMode getPortMode(OMX_U32 portIndex); 139 140 virtual bool onMessageReceived(const sp<AMessage> &msg); 141 142 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 143 144 virtual void onOutputBufferDrained(const sp<AMessage> &msg); 145 virtual void onInputBufferFilled(const sp<AMessage> &msg); 146 147 void postFillThisBuffer(BufferInfo *info); 148 149private: 150 bool onOMXMessage(const sp<AMessage> &msg); 151 152 bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID); 153 154 bool onOMXFillBufferDone( 155 IOMX::buffer_id bufferID, 156 size_t rangeOffset, size_t rangeLength, 157 OMX_U32 flags, 158 int64_t timeUs, 159 void *platformPrivate, 160 void *dataPtr); 161 162 void getMoreInputDataIfPossible(); 163 164 DISALLOW_EVIL_CONSTRUCTORS(BaseState); 165}; 166 167//////////////////////////////////////////////////////////////////////////////// 168 169struct ACodec::UninitializedState : public ACodec::BaseState { 170 UninitializedState(ACodec *codec); 171 172protected: 173 virtual bool onMessageReceived(const sp<AMessage> &msg); 174 virtual void stateEntered(); 175 176private: 177 void onSetup(const sp<AMessage> &msg); 178 bool onAllocateComponent(const sp<AMessage> &msg); 179 180 DISALLOW_EVIL_CONSTRUCTORS(UninitializedState); 181}; 182 183//////////////////////////////////////////////////////////////////////////////// 184 185struct ACodec::LoadedState : public ACodec::BaseState { 186 LoadedState(ACodec *codec); 187 188protected: 189 virtual bool onMessageReceived(const sp<AMessage> &msg); 190 virtual void stateEntered(); 191 192private: 193 friend struct ACodec::UninitializedState; 194 195 bool onConfigureComponent(const sp<AMessage> &msg); 196 void onCreateInputSurface(const sp<AMessage> &msg); 197 void onStart(); 198 void onShutdown(bool keepComponentAllocated); 199 200 DISALLOW_EVIL_CONSTRUCTORS(LoadedState); 201}; 202 203//////////////////////////////////////////////////////////////////////////////// 204 205struct ACodec::LoadedToIdleState : public ACodec::BaseState { 206 LoadedToIdleState(ACodec *codec); 207 208protected: 209 virtual bool onMessageReceived(const sp<AMessage> &msg); 210 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 211 virtual void stateEntered(); 212 213private: 214 status_t allocateBuffers(); 215 216 DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState); 217}; 218 219//////////////////////////////////////////////////////////////////////////////// 220 221struct ACodec::IdleToExecutingState : public ACodec::BaseState { 222 IdleToExecutingState(ACodec *codec); 223 224protected: 225 virtual bool onMessageReceived(const sp<AMessage> &msg); 226 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 227 virtual void stateEntered(); 228 229private: 230 DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState); 231}; 232 233//////////////////////////////////////////////////////////////////////////////// 234 235struct ACodec::ExecutingState : public ACodec::BaseState { 236 ExecutingState(ACodec *codec); 237 238 void submitOutputBuffers(); 239 240 // Submit output buffers to the decoder, submit input buffers to client 241 // to fill with data. 242 void resume(); 243 244 // Returns true iff input and output buffers are in play. 245 bool active() const { return mActive; } 246 247protected: 248 virtual PortMode getPortMode(OMX_U32 portIndex); 249 virtual bool onMessageReceived(const sp<AMessage> &msg); 250 virtual void stateEntered(); 251 252 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 253 254private: 255 bool mActive; 256 257 DISALLOW_EVIL_CONSTRUCTORS(ExecutingState); 258}; 259 260//////////////////////////////////////////////////////////////////////////////// 261 262struct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState { 263 OutputPortSettingsChangedState(ACodec *codec); 264 265protected: 266 virtual PortMode getPortMode(OMX_U32 portIndex); 267 virtual bool onMessageReceived(const sp<AMessage> &msg); 268 virtual void stateEntered(); 269 270 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 271 272private: 273 DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState); 274}; 275 276//////////////////////////////////////////////////////////////////////////////// 277 278struct ACodec::ExecutingToIdleState : public ACodec::BaseState { 279 ExecutingToIdleState(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 287 virtual void onOutputBufferDrained(const sp<AMessage> &msg); 288 virtual void onInputBufferFilled(const sp<AMessage> &msg); 289 290private: 291 void changeStateIfWeOwnAllBuffers(); 292 293 bool mComponentNowIdle; 294 295 DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState); 296}; 297 298//////////////////////////////////////////////////////////////////////////////// 299 300struct ACodec::IdleToLoadedState : public ACodec::BaseState { 301 IdleToLoadedState(ACodec *codec); 302 303protected: 304 virtual bool onMessageReceived(const sp<AMessage> &msg); 305 virtual void stateEntered(); 306 307 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 308 309private: 310 DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState); 311}; 312 313//////////////////////////////////////////////////////////////////////////////// 314 315struct ACodec::FlushingState : public ACodec::BaseState { 316 FlushingState(ACodec *codec); 317 318protected: 319 virtual bool onMessageReceived(const sp<AMessage> &msg); 320 virtual void stateEntered(); 321 322 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 323 324 virtual void onOutputBufferDrained(const sp<AMessage> &msg); 325 virtual void onInputBufferFilled(const sp<AMessage> &msg); 326 327private: 328 bool mFlushComplete[2]; 329 330 void changeStateIfWeOwnAllBuffers(); 331 332 DISALLOW_EVIL_CONSTRUCTORS(FlushingState); 333}; 334 335//////////////////////////////////////////////////////////////////////////////// 336 337ACodec::ACodec() 338 : mQuirks(0), 339 mNode(NULL), 340 mSentFormat(false), 341 mIsEncoder(false), 342 mShutdownInProgress(false), 343 mEncoderDelay(0), 344 mEncoderPadding(0), 345 mChannelMaskPresent(false), 346 mChannelMask(0) { 347 mUninitializedState = new UninitializedState(this); 348 mLoadedState = new LoadedState(this); 349 mLoadedToIdleState = new LoadedToIdleState(this); 350 mIdleToExecutingState = new IdleToExecutingState(this); 351 mExecutingState = new ExecutingState(this); 352 353 mOutputPortSettingsChangedState = 354 new OutputPortSettingsChangedState(this); 355 356 mExecutingToIdleState = new ExecutingToIdleState(this); 357 mIdleToLoadedState = new IdleToLoadedState(this); 358 mFlushingState = new FlushingState(this); 359 360 mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false; 361 mInputEOSResult = OK; 362 363 changeState(mUninitializedState); 364} 365 366ACodec::~ACodec() { 367} 368 369void ACodec::setNotificationMessage(const sp<AMessage> &msg) { 370 mNotify = msg; 371} 372 373void ACodec::initiateSetup(const sp<AMessage> &msg) { 374 msg->setWhat(kWhatSetup); 375 msg->setTarget(id()); 376 msg->post(); 377} 378 379void ACodec::signalSetParameters(const sp<AMessage> ¶ms) { 380 sp<AMessage> msg = new AMessage(kWhatSetParameters, id()); 381 msg->setMessage("params", params); 382 msg->post(); 383} 384 385void ACodec::initiateAllocateComponent(const sp<AMessage> &msg) { 386 msg->setWhat(kWhatAllocateComponent); 387 msg->setTarget(id()); 388 msg->post(); 389} 390 391void ACodec::initiateConfigureComponent(const sp<AMessage> &msg) { 392 msg->setWhat(kWhatConfigureComponent); 393 msg->setTarget(id()); 394 msg->post(); 395} 396 397void ACodec::initiateCreateInputSurface() { 398 (new AMessage(kWhatCreateInputSurface, id()))->post(); 399} 400 401void ACodec::signalEndOfInputStream() { 402 (new AMessage(kWhatSignalEndOfInputStream, id()))->post(); 403} 404 405void ACodec::initiateStart() { 406 (new AMessage(kWhatStart, id()))->post(); 407} 408 409void ACodec::signalFlush() { 410 ALOGV("[%s] signalFlush", mComponentName.c_str()); 411 (new AMessage(kWhatFlush, id()))->post(); 412} 413 414void ACodec::signalResume() { 415 (new AMessage(kWhatResume, id()))->post(); 416} 417 418void ACodec::initiateShutdown(bool keepComponentAllocated) { 419 sp<AMessage> msg = new AMessage(kWhatShutdown, id()); 420 msg->setInt32("keepComponentAllocated", keepComponentAllocated); 421 msg->post(); 422} 423 424void ACodec::signalRequestIDRFrame() { 425 (new AMessage(kWhatRequestIDRFrame, id()))->post(); 426} 427 428status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) { 429 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 430 431 CHECK(mDealer[portIndex] == NULL); 432 CHECK(mBuffers[portIndex].isEmpty()); 433 434 status_t err; 435 if (mNativeWindow != NULL && portIndex == kPortIndexOutput) { 436 err = allocateOutputBuffersFromNativeWindow(); 437 } else { 438 OMX_PARAM_PORTDEFINITIONTYPE def; 439 InitOMXParams(&def); 440 def.nPortIndex = portIndex; 441 442 err = mOMX->getParameter( 443 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 444 445 if (err == OK) { 446 ALOGV("[%s] Allocating %lu buffers of size %lu on %s port", 447 mComponentName.c_str(), 448 def.nBufferCountActual, def.nBufferSize, 449 portIndex == kPortIndexInput ? "input" : "output"); 450 451 size_t totalSize = def.nBufferCountActual * def.nBufferSize; 452 mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec"); 453 454 for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) { 455 sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize); 456 CHECK(mem.get() != NULL); 457 458 BufferInfo info; 459 info.mStatus = BufferInfo::OWNED_BY_US; 460 461 uint32_t requiresAllocateBufferBit = 462 (portIndex == kPortIndexInput) 463 ? OMXCodec::kRequiresAllocateBufferOnInputPorts 464 : OMXCodec::kRequiresAllocateBufferOnOutputPorts; 465 466 if (portIndex == kPortIndexInput && (mFlags & kFlagIsSecure)) { 467 mem.clear(); 468 469 void *ptr; 470 err = mOMX->allocateBuffer( 471 mNode, portIndex, def.nBufferSize, &info.mBufferID, 472 &ptr); 473 474 info.mData = new ABuffer(ptr, def.nBufferSize); 475 } else if (mQuirks & requiresAllocateBufferBit) { 476 err = mOMX->allocateBufferWithBackup( 477 mNode, portIndex, mem, &info.mBufferID); 478 } else { 479 err = mOMX->useBuffer(mNode, portIndex, mem, &info.mBufferID); 480 } 481 482 if (mem != NULL) { 483 info.mData = new ABuffer(mem->pointer(), def.nBufferSize); 484 } 485 486 mBuffers[portIndex].push(info); 487 } 488 } 489 } 490 491 if (err != OK) { 492 return err; 493 } 494 495 sp<AMessage> notify = mNotify->dup(); 496 notify->setInt32("what", ACodec::kWhatBuffersAllocated); 497 498 notify->setInt32("portIndex", portIndex); 499 500 sp<PortDescription> desc = new PortDescription; 501 502 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 503 const BufferInfo &info = mBuffers[portIndex][i]; 504 505 desc->addBuffer(info.mBufferID, info.mData); 506 } 507 508 notify->setObject("portDesc", desc); 509 notify->post(); 510 511 return OK; 512} 513 514status_t ACodec::allocateOutputBuffersFromNativeWindow() { 515 OMX_PARAM_PORTDEFINITIONTYPE def; 516 InitOMXParams(&def); 517 def.nPortIndex = kPortIndexOutput; 518 519 status_t err = mOMX->getParameter( 520 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 521 522 if (err != OK) { 523 return err; 524 } 525 526 err = native_window_set_buffers_geometry( 527 mNativeWindow.get(), 528 def.format.video.nFrameWidth, 529 def.format.video.nFrameHeight, 530 def.format.video.eColorFormat); 531 532 if (err != 0) { 533 ALOGE("native_window_set_buffers_geometry failed: %s (%d)", 534 strerror(-err), -err); 535 return err; 536 } 537 538 // Set up the native window. 539 OMX_U32 usage = 0; 540 err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage); 541 if (err != 0) { 542 ALOGW("querying usage flags from OMX IL component failed: %d", err); 543 // XXX: Currently this error is logged, but not fatal. 544 usage = 0; 545 } 546 547 if (mFlags & kFlagIsSecure) { 548 usage |= GRALLOC_USAGE_PROTECTED; 549 } 550 551 // Make sure to check whether either Stagefright or the video decoder 552 // requested protected buffers. 553 if (usage & GRALLOC_USAGE_PROTECTED) { 554 // Verify that the ANativeWindow sends images directly to 555 // SurfaceFlinger. 556 int queuesToNativeWindow = 0; 557 err = mNativeWindow->query( 558 mNativeWindow.get(), NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, 559 &queuesToNativeWindow); 560 if (err != 0) { 561 ALOGE("error authenticating native window: %d", err); 562 return err; 563 } 564 if (queuesToNativeWindow != 1) { 565 ALOGE("native window could not be authenticated"); 566 return PERMISSION_DENIED; 567 } 568 } 569 570 err = native_window_set_usage( 571 mNativeWindow.get(), 572 usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP); 573 574 if (err != 0) { 575 ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err); 576 return err; 577 } 578 579 int minUndequeuedBufs = 0; 580 err = mNativeWindow->query( 581 mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, 582 &minUndequeuedBufs); 583 584 if (err != 0) { 585 ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)", 586 strerror(-err), -err); 587 return err; 588 } 589 590 // XXX: Is this the right logic to use? It's not clear to me what the OMX 591 // buffer counts refer to - how do they account for the renderer holding on 592 // to buffers? 593 if (def.nBufferCountActual < def.nBufferCountMin + minUndequeuedBufs) { 594 OMX_U32 newBufferCount = def.nBufferCountMin + minUndequeuedBufs; 595 def.nBufferCountActual = newBufferCount; 596 err = mOMX->setParameter( 597 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 598 599 if (err != OK) { 600 ALOGE("[%s] setting nBufferCountActual to %lu failed: %d", 601 mComponentName.c_str(), newBufferCount, err); 602 return err; 603 } 604 } 605 606 err = native_window_set_buffer_count( 607 mNativeWindow.get(), def.nBufferCountActual); 608 609 if (err != 0) { 610 ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), 611 -err); 612 return err; 613 } 614 615 ALOGV("[%s] Allocating %lu buffers from a native window of size %lu on " 616 "output port", 617 mComponentName.c_str(), def.nBufferCountActual, def.nBufferSize); 618 619 // Dequeue buffers and send them to OMX 620 for (OMX_U32 i = 0; i < def.nBufferCountActual; i++) { 621 ANativeWindowBuffer *buf; 622 err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf); 623 if (err != 0) { 624 ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err); 625 break; 626 } 627 628 sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false)); 629 BufferInfo info; 630 info.mStatus = BufferInfo::OWNED_BY_US; 631 info.mData = new ABuffer(NULL /* data */, def.nBufferSize /* capacity */); 632 info.mGraphicBuffer = graphicBuffer; 633 mBuffers[kPortIndexOutput].push(info); 634 635 IOMX::buffer_id bufferId; 636 err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer, 637 &bufferId); 638 if (err != 0) { 639 ALOGE("registering GraphicBuffer %lu with OMX IL component failed: " 640 "%d", i, err); 641 break; 642 } 643 644 mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId; 645 646 ALOGV("[%s] Registered graphic buffer with ID %p (pointer = %p)", 647 mComponentName.c_str(), 648 bufferId, graphicBuffer.get()); 649 } 650 651 OMX_U32 cancelStart; 652 OMX_U32 cancelEnd; 653 654 if (err != 0) { 655 // If an error occurred while dequeuing we need to cancel any buffers 656 // that were dequeued. 657 cancelStart = 0; 658 cancelEnd = mBuffers[kPortIndexOutput].size(); 659 } else { 660 // Return the last two buffers to the native window. 661 cancelStart = def.nBufferCountActual - minUndequeuedBufs; 662 cancelEnd = def.nBufferCountActual; 663 } 664 665 for (OMX_U32 i = cancelStart; i < cancelEnd; i++) { 666 BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i); 667 cancelBufferToNativeWindow(info); 668 } 669 670 return err; 671} 672 673status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) { 674 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 675 676 ALOGV("[%s] Calling cancelBuffer on buffer %p", 677 mComponentName.c_str(), info->mBufferID); 678 679 int err = mNativeWindow->cancelBuffer( 680 mNativeWindow.get(), info->mGraphicBuffer.get(), -1); 681 682 CHECK_EQ(err, 0); 683 684 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 685 686 return OK; 687} 688 689ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() { 690 ANativeWindowBuffer *buf; 691 int fenceFd = -1; 692 if (native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf) != 0) { 693 ALOGE("dequeueBuffer failed."); 694 return NULL; 695 } 696 697 for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) { 698 BufferInfo *info = 699 &mBuffers[kPortIndexOutput].editItemAt(i); 700 701 if (info->mGraphicBuffer->handle == buf->handle) { 702 CHECK_EQ((int)info->mStatus, 703 (int)BufferInfo::OWNED_BY_NATIVE_WINDOW); 704 705 info->mStatus = BufferInfo::OWNED_BY_US; 706 707 return info; 708 } 709 } 710 711 TRESPASS(); 712 713 return NULL; 714} 715 716status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) { 717 for (size_t i = mBuffers[portIndex].size(); i-- > 0;) { 718 CHECK_EQ((status_t)OK, freeBuffer(portIndex, i)); 719 } 720 721 mDealer[portIndex].clear(); 722 723 return OK; 724} 725 726status_t ACodec::freeOutputBuffersNotOwnedByComponent() { 727 for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) { 728 BufferInfo *info = 729 &mBuffers[kPortIndexOutput].editItemAt(i); 730 731 if (info->mStatus != 732 BufferInfo::OWNED_BY_COMPONENT) { 733 // We shouldn't have sent out any buffers to the client at this 734 // point. 735 CHECK_NE((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM); 736 737 CHECK_EQ((status_t)OK, freeBuffer(kPortIndexOutput, i)); 738 } 739 } 740 741 return OK; 742} 743 744status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) { 745 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 746 747 CHECK(info->mStatus == BufferInfo::OWNED_BY_US 748 || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW); 749 750 if (portIndex == kPortIndexOutput && mNativeWindow != NULL 751 && info->mStatus == BufferInfo::OWNED_BY_US) { 752 CHECK_EQ((status_t)OK, cancelBufferToNativeWindow(info)); 753 } 754 755 CHECK_EQ(mOMX->freeBuffer( 756 mNode, portIndex, info->mBufferID), 757 (status_t)OK); 758 759 mBuffers[portIndex].removeAt(i); 760 761 return OK; 762} 763 764ACodec::BufferInfo *ACodec::findBufferByID( 765 uint32_t portIndex, IOMX::buffer_id bufferID, 766 ssize_t *index) { 767 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 768 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 769 770 if (info->mBufferID == bufferID) { 771 if (index != NULL) { 772 *index = i; 773 } 774 return info; 775 } 776 } 777 778 TRESPASS(); 779 780 return NULL; 781} 782 783status_t ACodec::setComponentRole( 784 bool isEncoder, const char *mime) { 785 struct MimeToRole { 786 const char *mime; 787 const char *decoderRole; 788 const char *encoderRole; 789 }; 790 791 static const MimeToRole kMimeToRole[] = { 792 { MEDIA_MIMETYPE_AUDIO_MPEG, 793 "audio_decoder.mp3", "audio_encoder.mp3" }, 794 { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I, 795 "audio_decoder.mp1", "audio_encoder.mp1" }, 796 { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II, 797 "audio_decoder.mp2", "audio_encoder.mp2" }, 798 { MEDIA_MIMETYPE_AUDIO_AMR_NB, 799 "audio_decoder.amrnb", "audio_encoder.amrnb" }, 800 { MEDIA_MIMETYPE_AUDIO_AMR_WB, 801 "audio_decoder.amrwb", "audio_encoder.amrwb" }, 802 { MEDIA_MIMETYPE_AUDIO_AAC, 803 "audio_decoder.aac", "audio_encoder.aac" }, 804 { MEDIA_MIMETYPE_AUDIO_VORBIS, 805 "audio_decoder.vorbis", "audio_encoder.vorbis" }, 806 { MEDIA_MIMETYPE_AUDIO_G711_MLAW, 807 "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" }, 808 { MEDIA_MIMETYPE_AUDIO_G711_ALAW, 809 "audio_decoder.g711alaw", "audio_encoder.g711alaw" }, 810 { MEDIA_MIMETYPE_VIDEO_AVC, 811 "video_decoder.avc", "video_encoder.avc" }, 812 { MEDIA_MIMETYPE_VIDEO_MPEG4, 813 "video_decoder.mpeg4", "video_encoder.mpeg4" }, 814 { MEDIA_MIMETYPE_VIDEO_H263, 815 "video_decoder.h263", "video_encoder.h263" }, 816 { MEDIA_MIMETYPE_VIDEO_VPX, 817 "video_decoder.vpx", "video_encoder.vpx" }, 818 { MEDIA_MIMETYPE_AUDIO_RAW, 819 "audio_decoder.raw", "audio_encoder.raw" }, 820 { MEDIA_MIMETYPE_AUDIO_FLAC, 821 "audio_decoder.flac", "audio_encoder.flac" }, 822 { MEDIA_MIMETYPE_AUDIO_MSGSM, 823 "audio_decoder.gsm", "audio_encoder.gsm" }, 824 }; 825 826 static const size_t kNumMimeToRole = 827 sizeof(kMimeToRole) / sizeof(kMimeToRole[0]); 828 829 size_t i; 830 for (i = 0; i < kNumMimeToRole; ++i) { 831 if (!strcasecmp(mime, kMimeToRole[i].mime)) { 832 break; 833 } 834 } 835 836 if (i == kNumMimeToRole) { 837 return ERROR_UNSUPPORTED; 838 } 839 840 const char *role = 841 isEncoder ? kMimeToRole[i].encoderRole 842 : kMimeToRole[i].decoderRole; 843 844 if (role != NULL) { 845 OMX_PARAM_COMPONENTROLETYPE roleParams; 846 InitOMXParams(&roleParams); 847 848 strncpy((char *)roleParams.cRole, 849 role, OMX_MAX_STRINGNAME_SIZE - 1); 850 851 roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0'; 852 853 status_t err = mOMX->setParameter( 854 mNode, OMX_IndexParamStandardComponentRole, 855 &roleParams, sizeof(roleParams)); 856 857 if (err != OK) { 858 ALOGW("[%s] Failed to set standard component role '%s'.", 859 mComponentName.c_str(), role); 860 861 return err; 862 } 863 } 864 865 return OK; 866} 867 868status_t ACodec::configureCodec( 869 const char *mime, const sp<AMessage> &msg) { 870 int32_t encoder; 871 if (!msg->findInt32("encoder", &encoder)) { 872 encoder = false; 873 } 874 875 mIsEncoder = encoder; 876 877 status_t err = setComponentRole(encoder /* isEncoder */, mime); 878 879 if (err != OK) { 880 return err; 881 } 882 883 int32_t bitRate = 0; 884 // FLAC encoder doesn't need a bitrate, other encoders do 885 if (encoder && strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC) 886 && !msg->findInt32("bitrate", &bitRate)) { 887 return INVALID_OPERATION; 888 } 889 890 int32_t storeMeta; 891 if (encoder 892 && msg->findInt32("store-metadata-in-buffers", &storeMeta) 893 && storeMeta != 0) { 894 err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexInput, OMX_TRUE); 895 896 if (err != OK) { 897 ALOGE("[%s] storeMetaDataInBuffers failed w/ err %d", 898 mComponentName.c_str(), err); 899 900 return err; 901 } 902 } 903 904 int32_t prependSPSPPS; 905 if (encoder 906 && msg->findInt32("prepend-sps-pps-to-idr-frames", &prependSPSPPS) 907 && prependSPSPPS != 0) { 908 OMX_INDEXTYPE index; 909 err = mOMX->getExtensionIndex( 910 mNode, 911 "OMX.google.android.index.prependSPSPPSToIDRFrames", 912 &index); 913 914 if (err == OK) { 915 PrependSPSPPSToIDRFramesParams params; 916 InitOMXParams(¶ms); 917 params.bEnable = OMX_TRUE; 918 919 err = mOMX->setParameter( 920 mNode, index, ¶ms, sizeof(params)); 921 } 922 923 if (err != OK) { 924 ALOGE("Encoder could not be configured to emit SPS/PPS before " 925 "IDR frames. (err %d)", err); 926 927 return err; 928 } 929 } 930 931 if (!strncasecmp(mime, "video/", 6)) { 932 if (encoder) { 933 err = setupVideoEncoder(mime, msg); 934 } else { 935 int32_t width, height; 936 if (!msg->findInt32("width", &width) 937 || !msg->findInt32("height", &height)) { 938 err = INVALID_OPERATION; 939 } else { 940 err = setupVideoDecoder(mime, width, height); 941 } 942 } 943 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 944 int32_t numChannels, sampleRate; 945 if (!msg->findInt32("channel-count", &numChannels) 946 || !msg->findInt32("sample-rate", &sampleRate)) { 947 err = INVALID_OPERATION; 948 } else { 949 int32_t isADTS, aacProfile; 950 if (!msg->findInt32("is-adts", &isADTS)) { 951 isADTS = 0; 952 } 953 if (!msg->findInt32("aac-profile", &aacProfile)) { 954 aacProfile = OMX_AUDIO_AACObjectNull; 955 } 956 957 err = setupAACCodec( 958 encoder, numChannels, sampleRate, bitRate, aacProfile, 959 isADTS != 0); 960 } 961 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) { 962 err = setupAMRCodec(encoder, false /* isWAMR */, bitRate); 963 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) { 964 err = setupAMRCodec(encoder, true /* isWAMR */, bitRate); 965 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW) 966 || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) { 967 // These are PCM-like formats with a fixed sample rate but 968 // a variable number of channels. 969 970 int32_t numChannels; 971 if (!msg->findInt32("channel-count", &numChannels)) { 972 err = INVALID_OPERATION; 973 } else { 974 err = setupG711Codec(encoder, numChannels); 975 } 976 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) { 977 int32_t numChannels, sampleRate, compressionLevel = -1; 978 if (encoder && 979 (!msg->findInt32("channel-count", &numChannels) 980 || !msg->findInt32("sample-rate", &sampleRate))) { 981 ALOGE("missing channel count or sample rate for FLAC encoder"); 982 err = INVALID_OPERATION; 983 } else { 984 if (encoder) { 985 if (!msg->findInt32( 986 "flac-compression-level", &compressionLevel)) { 987 compressionLevel = 5;// default FLAC compression level 988 } else if (compressionLevel < 0) { 989 ALOGW("compression level %d outside [0..8] range, " 990 "using 0", 991 compressionLevel); 992 compressionLevel = 0; 993 } else if (compressionLevel > 8) { 994 ALOGW("compression level %d outside [0..8] range, " 995 "using 8", 996 compressionLevel); 997 compressionLevel = 8; 998 } 999 } 1000 err = setupFlacCodec( 1001 encoder, numChannels, sampleRate, compressionLevel); 1002 } 1003 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) { 1004 int32_t numChannels, sampleRate; 1005 if (encoder 1006 || !msg->findInt32("channel-count", &numChannels) 1007 || !msg->findInt32("sample-rate", &sampleRate)) { 1008 err = INVALID_OPERATION; 1009 } else { 1010 err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels); 1011 } 1012 } 1013 1014 if (err != OK) { 1015 return err; 1016 } 1017 1018 if (!msg->findInt32("encoder-delay", &mEncoderDelay)) { 1019 mEncoderDelay = 0; 1020 } 1021 1022 if (!msg->findInt32("encoder-padding", &mEncoderPadding)) { 1023 mEncoderPadding = 0; 1024 } 1025 1026 if (msg->findInt32("channel-mask", &mChannelMask)) { 1027 mChannelMaskPresent = true; 1028 } else { 1029 mChannelMaskPresent = false; 1030 } 1031 1032 int32_t maxInputSize; 1033 if (msg->findInt32("max-input-size", &maxInputSize)) { 1034 err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize); 1035 } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) { 1036 err = setMinBufferSize(kPortIndexInput, 8192); // XXX 1037 } 1038 1039 return err; 1040} 1041 1042status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) { 1043 OMX_PARAM_PORTDEFINITIONTYPE def; 1044 InitOMXParams(&def); 1045 def.nPortIndex = portIndex; 1046 1047 status_t err = mOMX->getParameter( 1048 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1049 1050 if (err != OK) { 1051 return err; 1052 } 1053 1054 if (def.nBufferSize >= size) { 1055 return OK; 1056 } 1057 1058 def.nBufferSize = size; 1059 1060 err = mOMX->setParameter( 1061 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1062 1063 if (err != OK) { 1064 return err; 1065 } 1066 1067 err = mOMX->getParameter( 1068 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1069 1070 if (err != OK) { 1071 return err; 1072 } 1073 1074 CHECK(def.nBufferSize >= size); 1075 1076 return OK; 1077} 1078 1079status_t ACodec::selectAudioPortFormat( 1080 OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) { 1081 OMX_AUDIO_PARAM_PORTFORMATTYPE format; 1082 InitOMXParams(&format); 1083 1084 format.nPortIndex = portIndex; 1085 for (OMX_U32 index = 0;; ++index) { 1086 format.nIndex = index; 1087 1088 status_t err = mOMX->getParameter( 1089 mNode, OMX_IndexParamAudioPortFormat, 1090 &format, sizeof(format)); 1091 1092 if (err != OK) { 1093 return err; 1094 } 1095 1096 if (format.eEncoding == desiredFormat) { 1097 break; 1098 } 1099 } 1100 1101 return mOMX->setParameter( 1102 mNode, OMX_IndexParamAudioPortFormat, &format, sizeof(format)); 1103} 1104 1105status_t ACodec::setupAACCodec( 1106 bool encoder, int32_t numChannels, int32_t sampleRate, 1107 int32_t bitRate, int32_t aacProfile, bool isADTS) { 1108 if (encoder && isADTS) { 1109 return -EINVAL; 1110 } 1111 1112 status_t err = setupRawAudioFormat( 1113 encoder ? kPortIndexInput : kPortIndexOutput, 1114 sampleRate, 1115 numChannels); 1116 1117 if (err != OK) { 1118 return err; 1119 } 1120 1121 if (encoder) { 1122 err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC); 1123 1124 if (err != OK) { 1125 return err; 1126 } 1127 1128 OMX_PARAM_PORTDEFINITIONTYPE def; 1129 InitOMXParams(&def); 1130 def.nPortIndex = kPortIndexOutput; 1131 1132 err = mOMX->getParameter( 1133 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1134 1135 if (err != OK) { 1136 return err; 1137 } 1138 1139 def.format.audio.bFlagErrorConcealment = OMX_TRUE; 1140 def.format.audio.eEncoding = OMX_AUDIO_CodingAAC; 1141 1142 err = mOMX->setParameter( 1143 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1144 1145 if (err != OK) { 1146 return err; 1147 } 1148 1149 OMX_AUDIO_PARAM_AACPROFILETYPE profile; 1150 InitOMXParams(&profile); 1151 profile.nPortIndex = kPortIndexOutput; 1152 1153 err = mOMX->getParameter( 1154 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 1155 1156 if (err != OK) { 1157 return err; 1158 } 1159 1160 profile.nChannels = numChannels; 1161 1162 profile.eChannelMode = 1163 (numChannels == 1) 1164 ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo; 1165 1166 profile.nSampleRate = sampleRate; 1167 profile.nBitRate = bitRate; 1168 profile.nAudioBandWidth = 0; 1169 profile.nFrameLength = 0; 1170 profile.nAACtools = OMX_AUDIO_AACToolAll; 1171 profile.nAACERtools = OMX_AUDIO_AACERNone; 1172 profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile; 1173 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF; 1174 1175 err = mOMX->setParameter( 1176 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 1177 1178 if (err != OK) { 1179 return err; 1180 } 1181 1182 return err; 1183 } 1184 1185 OMX_AUDIO_PARAM_AACPROFILETYPE profile; 1186 InitOMXParams(&profile); 1187 profile.nPortIndex = kPortIndexInput; 1188 1189 err = mOMX->getParameter( 1190 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 1191 1192 if (err != OK) { 1193 return err; 1194 } 1195 1196 profile.nChannels = numChannels; 1197 profile.nSampleRate = sampleRate; 1198 1199 profile.eAACStreamFormat = 1200 isADTS 1201 ? OMX_AUDIO_AACStreamFormatMP4ADTS 1202 : OMX_AUDIO_AACStreamFormatMP4FF; 1203 1204 return mOMX->setParameter( 1205 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 1206} 1207 1208static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate( 1209 bool isAMRWB, int32_t bps) { 1210 if (isAMRWB) { 1211 if (bps <= 6600) { 1212 return OMX_AUDIO_AMRBandModeWB0; 1213 } else if (bps <= 8850) { 1214 return OMX_AUDIO_AMRBandModeWB1; 1215 } else if (bps <= 12650) { 1216 return OMX_AUDIO_AMRBandModeWB2; 1217 } else if (bps <= 14250) { 1218 return OMX_AUDIO_AMRBandModeWB3; 1219 } else if (bps <= 15850) { 1220 return OMX_AUDIO_AMRBandModeWB4; 1221 } else if (bps <= 18250) { 1222 return OMX_AUDIO_AMRBandModeWB5; 1223 } else if (bps <= 19850) { 1224 return OMX_AUDIO_AMRBandModeWB6; 1225 } else if (bps <= 23050) { 1226 return OMX_AUDIO_AMRBandModeWB7; 1227 } 1228 1229 // 23850 bps 1230 return OMX_AUDIO_AMRBandModeWB8; 1231 } else { // AMRNB 1232 if (bps <= 4750) { 1233 return OMX_AUDIO_AMRBandModeNB0; 1234 } else if (bps <= 5150) { 1235 return OMX_AUDIO_AMRBandModeNB1; 1236 } else if (bps <= 5900) { 1237 return OMX_AUDIO_AMRBandModeNB2; 1238 } else if (bps <= 6700) { 1239 return OMX_AUDIO_AMRBandModeNB3; 1240 } else if (bps <= 7400) { 1241 return OMX_AUDIO_AMRBandModeNB4; 1242 } else if (bps <= 7950) { 1243 return OMX_AUDIO_AMRBandModeNB5; 1244 } else if (bps <= 10200) { 1245 return OMX_AUDIO_AMRBandModeNB6; 1246 } 1247 1248 // 12200 bps 1249 return OMX_AUDIO_AMRBandModeNB7; 1250 } 1251} 1252 1253status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) { 1254 OMX_AUDIO_PARAM_AMRTYPE def; 1255 InitOMXParams(&def); 1256 def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput; 1257 1258 status_t err = 1259 mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); 1260 1261 if (err != OK) { 1262 return err; 1263 } 1264 1265 def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF; 1266 def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate); 1267 1268 err = mOMX->setParameter( 1269 mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); 1270 1271 if (err != OK) { 1272 return err; 1273 } 1274 1275 return setupRawAudioFormat( 1276 encoder ? kPortIndexInput : kPortIndexOutput, 1277 isWAMR ? 16000 : 8000 /* sampleRate */, 1278 1 /* numChannels */); 1279} 1280 1281status_t ACodec::setupG711Codec(bool encoder, int32_t numChannels) { 1282 CHECK(!encoder); // XXX TODO 1283 1284 return setupRawAudioFormat( 1285 kPortIndexInput, 8000 /* sampleRate */, numChannels); 1286} 1287 1288status_t ACodec::setupFlacCodec( 1289 bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel) { 1290 1291 if (encoder) { 1292 OMX_AUDIO_PARAM_FLACTYPE def; 1293 InitOMXParams(&def); 1294 def.nPortIndex = kPortIndexOutput; 1295 1296 // configure compression level 1297 status_t err = mOMX->getParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def)); 1298 if (err != OK) { 1299 ALOGE("setupFlacCodec(): Error %d getting OMX_IndexParamAudioFlac parameter", err); 1300 return err; 1301 } 1302 def.nCompressionLevel = compressionLevel; 1303 err = mOMX->setParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def)); 1304 if (err != OK) { 1305 ALOGE("setupFlacCodec(): Error %d setting OMX_IndexParamAudioFlac parameter", err); 1306 return err; 1307 } 1308 } 1309 1310 return setupRawAudioFormat( 1311 encoder ? kPortIndexInput : kPortIndexOutput, 1312 sampleRate, 1313 numChannels); 1314} 1315 1316status_t ACodec::setupRawAudioFormat( 1317 OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) { 1318 OMX_PARAM_PORTDEFINITIONTYPE def; 1319 InitOMXParams(&def); 1320 def.nPortIndex = portIndex; 1321 1322 status_t err = mOMX->getParameter( 1323 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1324 1325 if (err != OK) { 1326 return err; 1327 } 1328 1329 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; 1330 1331 err = mOMX->setParameter( 1332 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1333 1334 if (err != OK) { 1335 return err; 1336 } 1337 1338 OMX_AUDIO_PARAM_PCMMODETYPE pcmParams; 1339 InitOMXParams(&pcmParams); 1340 pcmParams.nPortIndex = portIndex; 1341 1342 err = mOMX->getParameter( 1343 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); 1344 1345 if (err != OK) { 1346 return err; 1347 } 1348 1349 pcmParams.nChannels = numChannels; 1350 pcmParams.eNumData = OMX_NumericalDataSigned; 1351 pcmParams.bInterleaved = OMX_TRUE; 1352 pcmParams.nBitPerSample = 16; 1353 pcmParams.nSamplingRate = sampleRate; 1354 pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear; 1355 1356 if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) { 1357 return OMX_ErrorNone; 1358 } 1359 1360 return mOMX->setParameter( 1361 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); 1362} 1363 1364status_t ACodec::setVideoPortFormatType( 1365 OMX_U32 portIndex, 1366 OMX_VIDEO_CODINGTYPE compressionFormat, 1367 OMX_COLOR_FORMATTYPE colorFormat) { 1368 OMX_VIDEO_PARAM_PORTFORMATTYPE format; 1369 InitOMXParams(&format); 1370 format.nPortIndex = portIndex; 1371 format.nIndex = 0; 1372 bool found = false; 1373 1374 OMX_U32 index = 0; 1375 for (;;) { 1376 format.nIndex = index; 1377 status_t err = mOMX->getParameter( 1378 mNode, OMX_IndexParamVideoPortFormat, 1379 &format, sizeof(format)); 1380 1381 if (err != OK) { 1382 return err; 1383 } 1384 1385 // The following assertion is violated by TI's video decoder. 1386 // CHECK_EQ(format.nIndex, index); 1387 1388 if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) { 1389 if (portIndex == kPortIndexInput 1390 && colorFormat == format.eColorFormat) { 1391 // eCompressionFormat does not seem right. 1392 found = true; 1393 break; 1394 } 1395 if (portIndex == kPortIndexOutput 1396 && compressionFormat == format.eCompressionFormat) { 1397 // eColorFormat does not seem right. 1398 found = true; 1399 break; 1400 } 1401 } 1402 1403 if (format.eCompressionFormat == compressionFormat 1404 && format.eColorFormat == colorFormat) { 1405 found = true; 1406 break; 1407 } 1408 1409 ++index; 1410 } 1411 1412 if (!found) { 1413 return UNKNOWN_ERROR; 1414 } 1415 1416 status_t err = mOMX->setParameter( 1417 mNode, OMX_IndexParamVideoPortFormat, 1418 &format, sizeof(format)); 1419 1420 return err; 1421} 1422 1423status_t ACodec::setSupportedOutputFormat() { 1424 OMX_VIDEO_PARAM_PORTFORMATTYPE format; 1425 InitOMXParams(&format); 1426 format.nPortIndex = kPortIndexOutput; 1427 format.nIndex = 0; 1428 1429 status_t err = mOMX->getParameter( 1430 mNode, OMX_IndexParamVideoPortFormat, 1431 &format, sizeof(format)); 1432 CHECK_EQ(err, (status_t)OK); 1433 CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused); 1434 1435 return mOMX->setParameter( 1436 mNode, OMX_IndexParamVideoPortFormat, 1437 &format, sizeof(format)); 1438} 1439 1440static status_t GetVideoCodingTypeFromMime( 1441 const char *mime, OMX_VIDEO_CODINGTYPE *codingType) { 1442 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 1443 *codingType = OMX_VIDEO_CodingAVC; 1444 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 1445 *codingType = OMX_VIDEO_CodingMPEG4; 1446 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 1447 *codingType = OMX_VIDEO_CodingH263; 1448 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG2, mime)) { 1449 *codingType = OMX_VIDEO_CodingMPEG2; 1450 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_VPX, mime)) { 1451 *codingType = OMX_VIDEO_CodingVPX; 1452 } else { 1453 *codingType = OMX_VIDEO_CodingUnused; 1454 return ERROR_UNSUPPORTED; 1455 } 1456 1457 return OK; 1458} 1459 1460status_t ACodec::setupVideoDecoder( 1461 const char *mime, int32_t width, int32_t height) { 1462 OMX_VIDEO_CODINGTYPE compressionFormat; 1463 status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat); 1464 1465 if (err != OK) { 1466 return err; 1467 } 1468 1469 err = setVideoPortFormatType( 1470 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused); 1471 1472 if (err != OK) { 1473 return err; 1474 } 1475 1476 err = setSupportedOutputFormat(); 1477 1478 if (err != OK) { 1479 return err; 1480 } 1481 1482 err = setVideoFormatOnPort( 1483 kPortIndexInput, width, height, compressionFormat); 1484 1485 if (err != OK) { 1486 return err; 1487 } 1488 1489 err = setVideoFormatOnPort( 1490 kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused); 1491 1492 if (err != OK) { 1493 return err; 1494 } 1495 1496 return OK; 1497} 1498 1499status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) { 1500 int32_t tmp; 1501 if (!msg->findInt32("color-format", &tmp)) { 1502 return INVALID_OPERATION; 1503 } 1504 1505 OMX_COLOR_FORMATTYPE colorFormat = 1506 static_cast<OMX_COLOR_FORMATTYPE>(tmp); 1507 1508 status_t err = setVideoPortFormatType( 1509 kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat); 1510 1511 if (err != OK) { 1512 ALOGE("[%s] does not support color format %d", 1513 mComponentName.c_str(), colorFormat); 1514 1515 return err; 1516 } 1517 1518 /* Input port configuration */ 1519 1520 OMX_PARAM_PORTDEFINITIONTYPE def; 1521 InitOMXParams(&def); 1522 1523 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 1524 1525 def.nPortIndex = kPortIndexInput; 1526 1527 err = mOMX->getParameter( 1528 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1529 1530 if (err != OK) { 1531 return err; 1532 } 1533 1534 int32_t width, height, bitrate; 1535 if (!msg->findInt32("width", &width) 1536 || !msg->findInt32("height", &height) 1537 || !msg->findInt32("bitrate", &bitrate)) { 1538 return INVALID_OPERATION; 1539 } 1540 1541 video_def->nFrameWidth = width; 1542 video_def->nFrameHeight = height; 1543 1544 int32_t stride; 1545 if (!msg->findInt32("stride", &stride)) { 1546 stride = width; 1547 } 1548 1549 video_def->nStride = stride; 1550 1551 int32_t sliceHeight; 1552 if (!msg->findInt32("slice-height", &sliceHeight)) { 1553 sliceHeight = height; 1554 } 1555 1556 video_def->nSliceHeight = sliceHeight; 1557 1558 def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2; 1559 1560 float frameRate; 1561 if (!msg->findFloat("frame-rate", &frameRate)) { 1562 int32_t tmp; 1563 if (!msg->findInt32("frame-rate", &tmp)) { 1564 return INVALID_OPERATION; 1565 } 1566 frameRate = (float)tmp; 1567 } 1568 1569 video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f); 1570 video_def->eCompressionFormat = OMX_VIDEO_CodingUnused; 1571 video_def->eColorFormat = colorFormat; 1572 1573 err = mOMX->setParameter( 1574 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1575 1576 if (err != OK) { 1577 ALOGE("[%s] failed to set input port definition parameters.", 1578 mComponentName.c_str()); 1579 1580 return err; 1581 } 1582 1583 /* Output port configuration */ 1584 1585 OMX_VIDEO_CODINGTYPE compressionFormat; 1586 err = GetVideoCodingTypeFromMime(mime, &compressionFormat); 1587 1588 if (err != OK) { 1589 return err; 1590 } 1591 1592 err = setVideoPortFormatType( 1593 kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused); 1594 1595 if (err != OK) { 1596 ALOGE("[%s] does not support compression format %d", 1597 mComponentName.c_str(), compressionFormat); 1598 1599 return err; 1600 } 1601 1602 def.nPortIndex = kPortIndexOutput; 1603 1604 err = mOMX->getParameter( 1605 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1606 1607 if (err != OK) { 1608 return err; 1609 } 1610 1611 video_def->nFrameWidth = width; 1612 video_def->nFrameHeight = height; 1613 video_def->xFramerate = 0; 1614 video_def->nBitrate = bitrate; 1615 video_def->eCompressionFormat = compressionFormat; 1616 video_def->eColorFormat = OMX_COLOR_FormatUnused; 1617 1618 err = mOMX->setParameter( 1619 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1620 1621 if (err != OK) { 1622 ALOGE("[%s] failed to set output port definition parameters.", 1623 mComponentName.c_str()); 1624 1625 return err; 1626 } 1627 1628 switch (compressionFormat) { 1629 case OMX_VIDEO_CodingMPEG4: 1630 err = setupMPEG4EncoderParameters(msg); 1631 break; 1632 1633 case OMX_VIDEO_CodingH263: 1634 err = setupH263EncoderParameters(msg); 1635 break; 1636 1637 case OMX_VIDEO_CodingAVC: 1638 err = setupAVCEncoderParameters(msg); 1639 break; 1640 1641 default: 1642 break; 1643 } 1644 1645 ALOGI("setupVideoEncoder succeeded"); 1646 1647 return err; 1648} 1649 1650status_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) { 1651 OMX_VIDEO_PARAM_INTRAREFRESHTYPE params; 1652 InitOMXParams(¶ms); 1653 params.nPortIndex = kPortIndexOutput; 1654 1655 params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode); 1656 1657 if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic || 1658 params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) { 1659 int32_t mbs; 1660 if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) { 1661 return INVALID_OPERATION; 1662 } 1663 params.nCirMBs = mbs; 1664 } 1665 1666 if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive || 1667 params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) { 1668 int32_t mbs; 1669 if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) { 1670 return INVALID_OPERATION; 1671 } 1672 params.nAirMBs = mbs; 1673 1674 int32_t ref; 1675 if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) { 1676 return INVALID_OPERATION; 1677 } 1678 params.nAirRef = ref; 1679 } 1680 1681 status_t err = mOMX->setParameter( 1682 mNode, OMX_IndexParamVideoIntraRefresh, 1683 ¶ms, sizeof(params)); 1684 return err; 1685} 1686 1687static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) { 1688 if (iFramesInterval < 0) { 1689 return 0xFFFFFFFF; 1690 } else if (iFramesInterval == 0) { 1691 return 0; 1692 } 1693 OMX_U32 ret = frameRate * iFramesInterval; 1694 CHECK(ret > 1); 1695 return ret; 1696} 1697 1698static OMX_VIDEO_CONTROLRATETYPE getBitrateMode(const sp<AMessage> &msg) { 1699 int32_t tmp; 1700 if (!msg->findInt32("bitrate-mode", &tmp)) { 1701 return OMX_Video_ControlRateVariable; 1702 } 1703 1704 return static_cast<OMX_VIDEO_CONTROLRATETYPE>(tmp); 1705} 1706 1707status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) { 1708 int32_t bitrate, iFrameInterval; 1709 if (!msg->findInt32("bitrate", &bitrate) 1710 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 1711 return INVALID_OPERATION; 1712 } 1713 1714 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 1715 1716 float frameRate; 1717 if (!msg->findFloat("frame-rate", &frameRate)) { 1718 int32_t tmp; 1719 if (!msg->findInt32("frame-rate", &tmp)) { 1720 return INVALID_OPERATION; 1721 } 1722 frameRate = (float)tmp; 1723 } 1724 1725 OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type; 1726 InitOMXParams(&mpeg4type); 1727 mpeg4type.nPortIndex = kPortIndexOutput; 1728 1729 status_t err = mOMX->getParameter( 1730 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); 1731 1732 if (err != OK) { 1733 return err; 1734 } 1735 1736 mpeg4type.nSliceHeaderSpacing = 0; 1737 mpeg4type.bSVH = OMX_FALSE; 1738 mpeg4type.bGov = OMX_FALSE; 1739 1740 mpeg4type.nAllowedPictureTypes = 1741 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 1742 1743 mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 1744 if (mpeg4type.nPFrames == 0) { 1745 mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 1746 } 1747 mpeg4type.nBFrames = 0; 1748 mpeg4type.nIDCVLCThreshold = 0; 1749 mpeg4type.bACPred = OMX_TRUE; 1750 mpeg4type.nMaxPacketSize = 256; 1751 mpeg4type.nTimeIncRes = 1000; 1752 mpeg4type.nHeaderExtension = 0; 1753 mpeg4type.bReversibleVLC = OMX_FALSE; 1754 1755 int32_t profile; 1756 if (msg->findInt32("profile", &profile)) { 1757 int32_t level; 1758 if (!msg->findInt32("level", &level)) { 1759 return INVALID_OPERATION; 1760 } 1761 1762 err = verifySupportForProfileAndLevel(profile, level); 1763 1764 if (err != OK) { 1765 return err; 1766 } 1767 1768 mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile); 1769 mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level); 1770 } 1771 1772 err = mOMX->setParameter( 1773 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); 1774 1775 if (err != OK) { 1776 return err; 1777 } 1778 1779 err = configureBitrate(bitrate, bitrateMode); 1780 1781 if (err != OK) { 1782 return err; 1783 } 1784 1785 return setupErrorCorrectionParameters(); 1786} 1787 1788status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) { 1789 int32_t bitrate, iFrameInterval; 1790 if (!msg->findInt32("bitrate", &bitrate) 1791 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 1792 return INVALID_OPERATION; 1793 } 1794 1795 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 1796 1797 float frameRate; 1798 if (!msg->findFloat("frame-rate", &frameRate)) { 1799 int32_t tmp; 1800 if (!msg->findInt32("frame-rate", &tmp)) { 1801 return INVALID_OPERATION; 1802 } 1803 frameRate = (float)tmp; 1804 } 1805 1806 OMX_VIDEO_PARAM_H263TYPE h263type; 1807 InitOMXParams(&h263type); 1808 h263type.nPortIndex = kPortIndexOutput; 1809 1810 status_t err = mOMX->getParameter( 1811 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); 1812 1813 if (err != OK) { 1814 return err; 1815 } 1816 1817 h263type.nAllowedPictureTypes = 1818 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 1819 1820 h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 1821 if (h263type.nPFrames == 0) { 1822 h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 1823 } 1824 h263type.nBFrames = 0; 1825 1826 int32_t profile; 1827 if (msg->findInt32("profile", &profile)) { 1828 int32_t level; 1829 if (!msg->findInt32("level", &level)) { 1830 return INVALID_OPERATION; 1831 } 1832 1833 err = verifySupportForProfileAndLevel(profile, level); 1834 1835 if (err != OK) { 1836 return err; 1837 } 1838 1839 h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile); 1840 h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level); 1841 } 1842 1843 h263type.bPLUSPTYPEAllowed = OMX_FALSE; 1844 h263type.bForceRoundingTypeToZero = OMX_FALSE; 1845 h263type.nPictureHeaderRepetition = 0; 1846 h263type.nGOBHeaderInterval = 0; 1847 1848 err = mOMX->setParameter( 1849 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); 1850 1851 if (err != OK) { 1852 return err; 1853 } 1854 1855 err = configureBitrate(bitrate, bitrateMode); 1856 1857 if (err != OK) { 1858 return err; 1859 } 1860 1861 return setupErrorCorrectionParameters(); 1862} 1863 1864status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) { 1865 int32_t bitrate, iFrameInterval; 1866 if (!msg->findInt32("bitrate", &bitrate) 1867 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 1868 return INVALID_OPERATION; 1869 } 1870 1871 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 1872 1873 float frameRate; 1874 if (!msg->findFloat("frame-rate", &frameRate)) { 1875 int32_t tmp; 1876 if (!msg->findInt32("frame-rate", &tmp)) { 1877 return INVALID_OPERATION; 1878 } 1879 frameRate = (float)tmp; 1880 } 1881 1882 status_t err = OK; 1883 int32_t intraRefreshMode = 0; 1884 if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) { 1885 err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode); 1886 if (err != OK) { 1887 ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x", 1888 err, intraRefreshMode); 1889 return err; 1890 } 1891 } 1892 1893 OMX_VIDEO_PARAM_AVCTYPE h264type; 1894 InitOMXParams(&h264type); 1895 h264type.nPortIndex = kPortIndexOutput; 1896 1897 err = mOMX->getParameter( 1898 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 1899 1900 if (err != OK) { 1901 return err; 1902 } 1903 1904 h264type.nAllowedPictureTypes = 1905 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 1906 1907 int32_t profile; 1908 if (msg->findInt32("profile", &profile)) { 1909 int32_t level; 1910 if (!msg->findInt32("level", &level)) { 1911 return INVALID_OPERATION; 1912 } 1913 1914 err = verifySupportForProfileAndLevel(profile, level); 1915 1916 if (err != OK) { 1917 return err; 1918 } 1919 1920 h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile); 1921 h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level); 1922 } 1923 1924 // XXX 1925 if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) { 1926 ALOGW("Use baseline profile instead of %d for AVC recording", 1927 h264type.eProfile); 1928 h264type.eProfile = OMX_VIDEO_AVCProfileBaseline; 1929 } 1930 1931 if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) { 1932 h264type.nSliceHeaderSpacing = 0; 1933 h264type.bUseHadamard = OMX_TRUE; 1934 h264type.nRefFrames = 1; 1935 h264type.nBFrames = 0; 1936 h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 1937 if (h264type.nPFrames == 0) { 1938 h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 1939 } 1940 h264type.nRefIdx10ActiveMinus1 = 0; 1941 h264type.nRefIdx11ActiveMinus1 = 0; 1942 h264type.bEntropyCodingCABAC = OMX_FALSE; 1943 h264type.bWeightedPPrediction = OMX_FALSE; 1944 h264type.bconstIpred = OMX_FALSE; 1945 h264type.bDirect8x8Inference = OMX_FALSE; 1946 h264type.bDirectSpatialTemporal = OMX_FALSE; 1947 h264type.nCabacInitIdc = 0; 1948 } 1949 1950 if (h264type.nBFrames != 0) { 1951 h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB; 1952 } 1953 1954 h264type.bEnableUEP = OMX_FALSE; 1955 h264type.bEnableFMO = OMX_FALSE; 1956 h264type.bEnableASO = OMX_FALSE; 1957 h264type.bEnableRS = OMX_FALSE; 1958 h264type.bFrameMBsOnly = OMX_TRUE; 1959 h264type.bMBAFF = OMX_FALSE; 1960 h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; 1961 1962 err = mOMX->setParameter( 1963 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 1964 1965 if (err != OK) { 1966 return err; 1967 } 1968 1969 return configureBitrate(bitrate, bitrateMode); 1970} 1971 1972status_t ACodec::verifySupportForProfileAndLevel( 1973 int32_t profile, int32_t level) { 1974 OMX_VIDEO_PARAM_PROFILELEVELTYPE params; 1975 InitOMXParams(¶ms); 1976 params.nPortIndex = kPortIndexOutput; 1977 1978 for (params.nProfileIndex = 0;; ++params.nProfileIndex) { 1979 status_t err = mOMX->getParameter( 1980 mNode, 1981 OMX_IndexParamVideoProfileLevelQuerySupported, 1982 ¶ms, 1983 sizeof(params)); 1984 1985 if (err != OK) { 1986 return err; 1987 } 1988 1989 int32_t supportedProfile = static_cast<int32_t>(params.eProfile); 1990 int32_t supportedLevel = static_cast<int32_t>(params.eLevel); 1991 1992 if (profile == supportedProfile && level <= supportedLevel) { 1993 return OK; 1994 } 1995 } 1996} 1997 1998status_t ACodec::configureBitrate( 1999 int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode) { 2000 OMX_VIDEO_PARAM_BITRATETYPE bitrateType; 2001 InitOMXParams(&bitrateType); 2002 bitrateType.nPortIndex = kPortIndexOutput; 2003 2004 status_t err = mOMX->getParameter( 2005 mNode, OMX_IndexParamVideoBitrate, 2006 &bitrateType, sizeof(bitrateType)); 2007 2008 if (err != OK) { 2009 return err; 2010 } 2011 2012 bitrateType.eControlRate = bitrateMode; 2013 bitrateType.nTargetBitrate = bitrate; 2014 2015 return mOMX->setParameter( 2016 mNode, OMX_IndexParamVideoBitrate, 2017 &bitrateType, sizeof(bitrateType)); 2018} 2019 2020status_t ACodec::setupErrorCorrectionParameters() { 2021 OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType; 2022 InitOMXParams(&errorCorrectionType); 2023 errorCorrectionType.nPortIndex = kPortIndexOutput; 2024 2025 status_t err = mOMX->getParameter( 2026 mNode, OMX_IndexParamVideoErrorCorrection, 2027 &errorCorrectionType, sizeof(errorCorrectionType)); 2028 2029 if (err != OK) { 2030 return OK; // Optional feature. Ignore this failure 2031 } 2032 2033 errorCorrectionType.bEnableHEC = OMX_FALSE; 2034 errorCorrectionType.bEnableResync = OMX_TRUE; 2035 errorCorrectionType.nResynchMarkerSpacing = 256; 2036 errorCorrectionType.bEnableDataPartitioning = OMX_FALSE; 2037 errorCorrectionType.bEnableRVLC = OMX_FALSE; 2038 2039 return mOMX->setParameter( 2040 mNode, OMX_IndexParamVideoErrorCorrection, 2041 &errorCorrectionType, sizeof(errorCorrectionType)); 2042} 2043 2044status_t ACodec::setVideoFormatOnPort( 2045 OMX_U32 portIndex, 2046 int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) { 2047 OMX_PARAM_PORTDEFINITIONTYPE def; 2048 InitOMXParams(&def); 2049 def.nPortIndex = portIndex; 2050 2051 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 2052 2053 status_t err = mOMX->getParameter( 2054 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2055 2056 CHECK_EQ(err, (status_t)OK); 2057 2058 if (portIndex == kPortIndexInput) { 2059 // XXX Need a (much) better heuristic to compute input buffer sizes. 2060 const size_t X = 64 * 1024; 2061 if (def.nBufferSize < X) { 2062 def.nBufferSize = X; 2063 } 2064 } 2065 2066 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo); 2067 2068 video_def->nFrameWidth = width; 2069 video_def->nFrameHeight = height; 2070 2071 if (portIndex == kPortIndexInput) { 2072 video_def->eCompressionFormat = compressionFormat; 2073 video_def->eColorFormat = OMX_COLOR_FormatUnused; 2074 } 2075 2076 err = mOMX->setParameter( 2077 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2078 2079 return err; 2080} 2081 2082status_t ACodec::initNativeWindow() { 2083 if (mNativeWindow != NULL) { 2084 return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE); 2085 } 2086 2087 mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE); 2088 return OK; 2089} 2090 2091size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const { 2092 size_t n = 0; 2093 2094 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 2095 const BufferInfo &info = mBuffers[portIndex].itemAt(i); 2096 2097 if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) { 2098 ++n; 2099 } 2100 } 2101 2102 return n; 2103} 2104 2105bool ACodec::allYourBuffersAreBelongToUs( 2106 OMX_U32 portIndex) { 2107 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 2108 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 2109 2110 if (info->mStatus != BufferInfo::OWNED_BY_US 2111 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) { 2112 ALOGV("[%s] Buffer %p on port %ld still has status %d", 2113 mComponentName.c_str(), 2114 info->mBufferID, portIndex, info->mStatus); 2115 return false; 2116 } 2117 } 2118 2119 return true; 2120} 2121 2122bool ACodec::allYourBuffersAreBelongToUs() { 2123 return allYourBuffersAreBelongToUs(kPortIndexInput) 2124 && allYourBuffersAreBelongToUs(kPortIndexOutput); 2125} 2126 2127void ACodec::deferMessage(const sp<AMessage> &msg) { 2128 bool wasEmptyBefore = mDeferredQueue.empty(); 2129 mDeferredQueue.push_back(msg); 2130} 2131 2132void ACodec::processDeferredMessages() { 2133 List<sp<AMessage> > queue = mDeferredQueue; 2134 mDeferredQueue.clear(); 2135 2136 List<sp<AMessage> >::iterator it = queue.begin(); 2137 while (it != queue.end()) { 2138 onMessageReceived(*it++); 2139 } 2140} 2141 2142void ACodec::sendFormatChange() { 2143 sp<AMessage> notify = mNotify->dup(); 2144 notify->setInt32("what", kWhatOutputFormatChanged); 2145 2146 OMX_PARAM_PORTDEFINITIONTYPE def; 2147 InitOMXParams(&def); 2148 def.nPortIndex = kPortIndexOutput; 2149 2150 CHECK_EQ(mOMX->getParameter( 2151 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)), 2152 (status_t)OK); 2153 2154 CHECK_EQ((int)def.eDir, (int)OMX_DirOutput); 2155 2156 switch (def.eDomain) { 2157 case OMX_PortDomainVideo: 2158 { 2159 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video; 2160 2161 notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW); 2162 notify->setInt32("width", videoDef->nFrameWidth); 2163 notify->setInt32("height", videoDef->nFrameHeight); 2164 notify->setInt32("stride", videoDef->nStride); 2165 notify->setInt32("slice-height", videoDef->nSliceHeight); 2166 notify->setInt32("color-format", videoDef->eColorFormat); 2167 2168 OMX_CONFIG_RECTTYPE rect; 2169 InitOMXParams(&rect); 2170 rect.nPortIndex = kPortIndexOutput; 2171 2172 if (mOMX->getConfig( 2173 mNode, OMX_IndexConfigCommonOutputCrop, 2174 &rect, sizeof(rect)) != OK) { 2175 rect.nLeft = 0; 2176 rect.nTop = 0; 2177 rect.nWidth = videoDef->nFrameWidth; 2178 rect.nHeight = videoDef->nFrameHeight; 2179 } 2180 2181 CHECK_GE(rect.nLeft, 0); 2182 CHECK_GE(rect.nTop, 0); 2183 CHECK_GE(rect.nWidth, 0u); 2184 CHECK_GE(rect.nHeight, 0u); 2185 CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth); 2186 CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight); 2187 2188 notify->setRect( 2189 "crop", 2190 rect.nLeft, 2191 rect.nTop, 2192 rect.nLeft + rect.nWidth - 1, 2193 rect.nTop + rect.nHeight - 1); 2194 2195 if (mNativeWindow != NULL) { 2196 android_native_rect_t crop; 2197 crop.left = rect.nLeft; 2198 crop.top = rect.nTop; 2199 crop.right = rect.nLeft + rect.nWidth; 2200 crop.bottom = rect.nTop + rect.nHeight; 2201 2202 CHECK_EQ(0, native_window_set_crop( 2203 mNativeWindow.get(), &crop)); 2204 } 2205 break; 2206 } 2207 2208 case OMX_PortDomainAudio: 2209 { 2210 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio; 2211 CHECK_EQ((int)audioDef->eEncoding, (int)OMX_AUDIO_CodingPCM); 2212 2213 OMX_AUDIO_PARAM_PCMMODETYPE params; 2214 InitOMXParams(¶ms); 2215 params.nPortIndex = kPortIndexOutput; 2216 2217 CHECK_EQ(mOMX->getParameter( 2218 mNode, OMX_IndexParamAudioPcm, 2219 ¶ms, sizeof(params)), 2220 (status_t)OK); 2221 2222 CHECK(params.nChannels == 1 || params.bInterleaved); 2223 CHECK_EQ(params.nBitPerSample, 16u); 2224 CHECK_EQ((int)params.eNumData, (int)OMX_NumericalDataSigned); 2225 CHECK_EQ((int)params.ePCMMode, (int)OMX_AUDIO_PCMModeLinear); 2226 2227 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW); 2228 notify->setInt32("channel-count", params.nChannels); 2229 notify->setInt32("sample-rate", params.nSamplingRate); 2230 if (mEncoderDelay + mEncoderPadding) { 2231 size_t frameSize = params.nChannels * sizeof(int16_t); 2232 if (mSkipCutBuffer != NULL) { 2233 size_t prevbufsize = mSkipCutBuffer->size(); 2234 if (prevbufsize != 0) { 2235 ALOGW("Replacing SkipCutBuffer holding %d bytes", prevbufsize); 2236 } 2237 } 2238 mSkipCutBuffer = new SkipCutBuffer(mEncoderDelay * frameSize, 2239 mEncoderPadding * frameSize); 2240 } 2241 2242 if (mChannelMaskPresent) { 2243 notify->setInt32("channel-mask", mChannelMask); 2244 } 2245 2246 break; 2247 } 2248 2249 default: 2250 TRESPASS(); 2251 } 2252 2253 notify->post(); 2254 2255 mSentFormat = true; 2256} 2257 2258void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) { 2259 sp<AMessage> notify = mNotify->dup(); 2260 notify->setInt32("what", ACodec::kWhatError); 2261 notify->setInt32("omx-error", error); 2262 notify->setInt32("err", internalError); 2263 notify->post(); 2264} 2265 2266status_t ACodec::pushBlankBuffersToNativeWindow() { 2267 status_t err = NO_ERROR; 2268 ANativeWindowBuffer* anb = NULL; 2269 int numBufs = 0; 2270 int minUndequeuedBufs = 0; 2271 2272 // We need to reconnect to the ANativeWindow as a CPU client to ensure that 2273 // no frames get dropped by SurfaceFlinger assuming that these are video 2274 // frames. 2275 err = native_window_api_disconnect(mNativeWindow.get(), 2276 NATIVE_WINDOW_API_MEDIA); 2277 if (err != NO_ERROR) { 2278 ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)", 2279 strerror(-err), -err); 2280 return err; 2281 } 2282 2283 err = native_window_api_connect(mNativeWindow.get(), 2284 NATIVE_WINDOW_API_CPU); 2285 if (err != NO_ERROR) { 2286 ALOGE("error pushing blank frames: api_connect failed: %s (%d)", 2287 strerror(-err), -err); 2288 return err; 2289 } 2290 2291 err = native_window_set_buffers_geometry(mNativeWindow.get(), 1, 1, 2292 HAL_PIXEL_FORMAT_RGBX_8888); 2293 if (err != NO_ERROR) { 2294 ALOGE("error pushing blank frames: set_buffers_geometry failed: %s (%d)", 2295 strerror(-err), -err); 2296 goto error; 2297 } 2298 2299 err = native_window_set_usage(mNativeWindow.get(), 2300 GRALLOC_USAGE_SW_WRITE_OFTEN); 2301 if (err != NO_ERROR) { 2302 ALOGE("error pushing blank frames: set_usage failed: %s (%d)", 2303 strerror(-err), -err); 2304 goto error; 2305 } 2306 2307 err = mNativeWindow->query(mNativeWindow.get(), 2308 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs); 2309 if (err != NO_ERROR) { 2310 ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query " 2311 "failed: %s (%d)", strerror(-err), -err); 2312 goto error; 2313 } 2314 2315 numBufs = minUndequeuedBufs + 1; 2316 err = native_window_set_buffer_count(mNativeWindow.get(), numBufs); 2317 if (err != NO_ERROR) { 2318 ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)", 2319 strerror(-err), -err); 2320 goto error; 2321 } 2322 2323 // We push numBufs + 1 buffers to ensure that we've drawn into the same 2324 // buffer twice. This should guarantee that the buffer has been displayed 2325 // on the screen and then been replaced, so an previous video frames are 2326 // guaranteed NOT to be currently displayed. 2327 for (int i = 0; i < numBufs + 1; i++) { 2328 int fenceFd = -1; 2329 err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &anb); 2330 if (err != NO_ERROR) { 2331 ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)", 2332 strerror(-err), -err); 2333 goto error; 2334 } 2335 2336 sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); 2337 2338 // Fill the buffer with the a 1x1 checkerboard pattern ;) 2339 uint32_t* img = NULL; 2340 err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); 2341 if (err != NO_ERROR) { 2342 ALOGE("error pushing blank frames: lock failed: %s (%d)", 2343 strerror(-err), -err); 2344 goto error; 2345 } 2346 2347 *img = 0; 2348 2349 err = buf->unlock(); 2350 if (err != NO_ERROR) { 2351 ALOGE("error pushing blank frames: unlock failed: %s (%d)", 2352 strerror(-err), -err); 2353 goto error; 2354 } 2355 2356 err = mNativeWindow->queueBuffer(mNativeWindow.get(), 2357 buf->getNativeBuffer(), -1); 2358 if (err != NO_ERROR) { 2359 ALOGE("error pushing blank frames: queueBuffer failed: %s (%d)", 2360 strerror(-err), -err); 2361 goto error; 2362 } 2363 2364 anb = NULL; 2365 } 2366 2367error: 2368 2369 if (err != NO_ERROR) { 2370 // Clean up after an error. 2371 if (anb != NULL) { 2372 mNativeWindow->cancelBuffer(mNativeWindow.get(), anb, -1); 2373 } 2374 2375 native_window_api_disconnect(mNativeWindow.get(), 2376 NATIVE_WINDOW_API_CPU); 2377 native_window_api_connect(mNativeWindow.get(), 2378 NATIVE_WINDOW_API_MEDIA); 2379 2380 return err; 2381 } else { 2382 // Clean up after success. 2383 err = native_window_api_disconnect(mNativeWindow.get(), 2384 NATIVE_WINDOW_API_CPU); 2385 if (err != NO_ERROR) { 2386 ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)", 2387 strerror(-err), -err); 2388 return err; 2389 } 2390 2391 err = native_window_api_connect(mNativeWindow.get(), 2392 NATIVE_WINDOW_API_MEDIA); 2393 if (err != NO_ERROR) { 2394 ALOGE("error pushing blank frames: api_connect failed: %s (%d)", 2395 strerror(-err), -err); 2396 return err; 2397 } 2398 2399 return NO_ERROR; 2400 } 2401} 2402 2403//////////////////////////////////////////////////////////////////////////////// 2404 2405ACodec::PortDescription::PortDescription() { 2406} 2407 2408status_t ACodec::requestIDRFrame() { 2409 if (!mIsEncoder) { 2410 return ERROR_UNSUPPORTED; 2411 } 2412 2413 OMX_CONFIG_INTRAREFRESHVOPTYPE params; 2414 InitOMXParams(¶ms); 2415 2416 params.nPortIndex = kPortIndexOutput; 2417 params.IntraRefreshVOP = OMX_TRUE; 2418 2419 return mOMX->setConfig( 2420 mNode, 2421 OMX_IndexConfigVideoIntraVOPRefresh, 2422 ¶ms, 2423 sizeof(params)); 2424} 2425 2426void ACodec::PortDescription::addBuffer( 2427 IOMX::buffer_id id, const sp<ABuffer> &buffer) { 2428 mBufferIDs.push_back(id); 2429 mBuffers.push_back(buffer); 2430} 2431 2432size_t ACodec::PortDescription::countBuffers() { 2433 return mBufferIDs.size(); 2434} 2435 2436IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const { 2437 return mBufferIDs.itemAt(index); 2438} 2439 2440sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const { 2441 return mBuffers.itemAt(index); 2442} 2443 2444//////////////////////////////////////////////////////////////////////////////// 2445 2446ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState) 2447 : AState(parentState), 2448 mCodec(codec) { 2449} 2450 2451ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(OMX_U32 portIndex) { 2452 return KEEP_BUFFERS; 2453} 2454 2455bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) { 2456 switch (msg->what()) { 2457 case kWhatInputBufferFilled: 2458 { 2459 onInputBufferFilled(msg); 2460 break; 2461 } 2462 2463 case kWhatOutputBufferDrained: 2464 { 2465 onOutputBufferDrained(msg); 2466 break; 2467 } 2468 2469 case ACodec::kWhatOMXMessage: 2470 { 2471 return onOMXMessage(msg); 2472 } 2473 2474 case ACodec::kWhatCreateInputSurface: 2475 case ACodec::kWhatSignalEndOfInputStream: 2476 { 2477 ALOGE("Message 0x%x was not handled", msg->what()); 2478 mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION); 2479 return true; 2480 } 2481 2482 default: 2483 return false; 2484 } 2485 2486 return true; 2487} 2488 2489bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) { 2490 int32_t type; 2491 CHECK(msg->findInt32("type", &type)); 2492 2493 IOMX::node_id nodeID; 2494 CHECK(msg->findPointer("node", &nodeID)); 2495 CHECK_EQ(nodeID, mCodec->mNode); 2496 2497 switch (type) { 2498 case omx_message::EVENT: 2499 { 2500 int32_t event, data1, data2; 2501 CHECK(msg->findInt32("event", &event)); 2502 CHECK(msg->findInt32("data1", &data1)); 2503 CHECK(msg->findInt32("data2", &data2)); 2504 2505 if (event == OMX_EventCmdComplete 2506 && data1 == OMX_CommandFlush 2507 && data2 == (int32_t)OMX_ALL) { 2508 // Use of this notification is not consistent across 2509 // implementations. We'll drop this notification and rely 2510 // on flush-complete notifications on the individual port 2511 // indices instead. 2512 2513 return true; 2514 } 2515 2516 return onOMXEvent( 2517 static_cast<OMX_EVENTTYPE>(event), 2518 static_cast<OMX_U32>(data1), 2519 static_cast<OMX_U32>(data2)); 2520 } 2521 2522 case omx_message::EMPTY_BUFFER_DONE: 2523 { 2524 IOMX::buffer_id bufferID; 2525 CHECK(msg->findPointer("buffer", &bufferID)); 2526 2527 return onOMXEmptyBufferDone(bufferID); 2528 } 2529 2530 case omx_message::FILL_BUFFER_DONE: 2531 { 2532 IOMX::buffer_id bufferID; 2533 CHECK(msg->findPointer("buffer", &bufferID)); 2534 2535 int32_t rangeOffset, rangeLength, flags; 2536 int64_t timeUs; 2537 void *platformPrivate; 2538 void *dataPtr; 2539 2540 CHECK(msg->findInt32("range_offset", &rangeOffset)); 2541 CHECK(msg->findInt32("range_length", &rangeLength)); 2542 CHECK(msg->findInt32("flags", &flags)); 2543 CHECK(msg->findInt64("timestamp", &timeUs)); 2544 CHECK(msg->findPointer("platform_private", &platformPrivate)); 2545 CHECK(msg->findPointer("data_ptr", &dataPtr)); 2546 2547 return onOMXFillBufferDone( 2548 bufferID, 2549 (size_t)rangeOffset, (size_t)rangeLength, 2550 (OMX_U32)flags, 2551 timeUs, 2552 platformPrivate, 2553 dataPtr); 2554 } 2555 2556 default: 2557 TRESPASS(); 2558 break; 2559 } 2560} 2561 2562bool ACodec::BaseState::onOMXEvent( 2563 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 2564 if (event != OMX_EventError) { 2565 ALOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)", 2566 mCodec->mComponentName.c_str(), event, data1, data2); 2567 2568 return false; 2569 } 2570 2571 ALOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1); 2572 2573 mCodec->signalError((OMX_ERRORTYPE)data1); 2574 2575 return true; 2576} 2577 2578bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) { 2579 ALOGV("[%s] onOMXEmptyBufferDone %p", 2580 mCodec->mComponentName.c_str(), bufferID); 2581 2582 BufferInfo *info = 2583 mCodec->findBufferByID(kPortIndexInput, bufferID); 2584 2585 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); 2586 info->mStatus = BufferInfo::OWNED_BY_US; 2587 2588 const sp<AMessage> &bufferMeta = info->mData->meta(); 2589 void *mediaBuffer; 2590 if (bufferMeta->findPointer("mediaBuffer", &mediaBuffer) 2591 && mediaBuffer != NULL) { 2592 // We're in "store-metadata-in-buffers" mode, the underlying 2593 // OMX component had access to data that's implicitly refcounted 2594 // by this "mediaBuffer" object. Now that the OMX component has 2595 // told us that it's done with the input buffer, we can decrement 2596 // the mediaBuffer's reference count. 2597 2598 ALOGV("releasing mbuf %p", mediaBuffer); 2599 2600 ((MediaBuffer *)mediaBuffer)->release(); 2601 mediaBuffer = NULL; 2602 2603 bufferMeta->setPointer("mediaBuffer", NULL); 2604 } 2605 2606 PortMode mode = getPortMode(kPortIndexInput); 2607 2608 switch (mode) { 2609 case KEEP_BUFFERS: 2610 break; 2611 2612 case RESUBMIT_BUFFERS: 2613 postFillThisBuffer(info); 2614 break; 2615 2616 default: 2617 { 2618 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 2619 TRESPASS(); // Not currently used 2620 break; 2621 } 2622 } 2623 2624 return true; 2625} 2626 2627void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) { 2628 if (mCodec->mPortEOS[kPortIndexInput]) { 2629 return; 2630 } 2631 2632 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 2633 2634 sp<AMessage> notify = mCodec->mNotify->dup(); 2635 notify->setInt32("what", ACodec::kWhatFillThisBuffer); 2636 notify->setPointer("buffer-id", info->mBufferID); 2637 2638 info->mData->meta()->clear(); 2639 notify->setBuffer("buffer", info->mData); 2640 2641 sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id()); 2642 reply->setPointer("buffer-id", info->mBufferID); 2643 2644 notify->setMessage("reply", reply); 2645 2646 notify->post(); 2647 2648 info->mStatus = BufferInfo::OWNED_BY_UPSTREAM; 2649} 2650 2651void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { 2652 IOMX::buffer_id bufferID; 2653 CHECK(msg->findPointer("buffer-id", &bufferID)); 2654 2655 sp<ABuffer> buffer; 2656 int32_t err = OK; 2657 bool eos = false; 2658 2659 if (!msg->findBuffer("buffer", &buffer)) { 2660 CHECK(msg->findInt32("err", &err)); 2661 2662 ALOGV("[%s] saw error %d instead of an input buffer", 2663 mCodec->mComponentName.c_str(), err); 2664 2665 buffer.clear(); 2666 2667 eos = true; 2668 } 2669 2670 int32_t tmp; 2671 if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) { 2672 eos = true; 2673 err = ERROR_END_OF_STREAM; 2674 } 2675 2676 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID); 2677 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM); 2678 2679 info->mStatus = BufferInfo::OWNED_BY_US; 2680 2681 PortMode mode = getPortMode(kPortIndexInput); 2682 2683 switch (mode) { 2684 case KEEP_BUFFERS: 2685 { 2686 if (eos) { 2687 if (!mCodec->mPortEOS[kPortIndexInput]) { 2688 mCodec->mPortEOS[kPortIndexInput] = true; 2689 mCodec->mInputEOSResult = err; 2690 } 2691 } 2692 break; 2693 } 2694 2695 case RESUBMIT_BUFFERS: 2696 { 2697 if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) { 2698 int64_t timeUs; 2699 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 2700 2701 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME; 2702 2703 int32_t isCSD; 2704 if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) { 2705 flags |= OMX_BUFFERFLAG_CODECCONFIG; 2706 } 2707 2708 if (eos) { 2709 flags |= OMX_BUFFERFLAG_EOS; 2710 } 2711 2712 if (buffer != info->mData) { 2713 ALOGV("[%s] Needs to copy input data for buffer %p. (%p != %p)", 2714 mCodec->mComponentName.c_str(), 2715 bufferID, 2716 buffer.get(), info->mData.get()); 2717 2718 CHECK_LE(buffer->size(), info->mData->capacity()); 2719 memcpy(info->mData->data(), buffer->data(), buffer->size()); 2720 } 2721 2722 if (flags & OMX_BUFFERFLAG_CODECCONFIG) { 2723 ALOGV("[%s] calling emptyBuffer %p w/ codec specific data", 2724 mCodec->mComponentName.c_str(), bufferID); 2725 } else if (flags & OMX_BUFFERFLAG_EOS) { 2726 ALOGV("[%s] calling emptyBuffer %p w/ EOS", 2727 mCodec->mComponentName.c_str(), bufferID); 2728 } else { 2729#if TRACK_BUFFER_TIMING 2730 ALOGI("[%s] calling emptyBuffer %p w/ time %lld us", 2731 mCodec->mComponentName.c_str(), bufferID, timeUs); 2732#else 2733 ALOGV("[%s] calling emptyBuffer %p w/ time %lld us", 2734 mCodec->mComponentName.c_str(), bufferID, timeUs); 2735#endif 2736 } 2737 2738#if TRACK_BUFFER_TIMING 2739 ACodec::BufferStats stats; 2740 stats.mEmptyBufferTimeUs = ALooper::GetNowUs(); 2741 stats.mFillBufferDoneTimeUs = -1ll; 2742 mCodec->mBufferStats.add(timeUs, stats); 2743#endif 2744 2745 CHECK_EQ(mCodec->mOMX->emptyBuffer( 2746 mCodec->mNode, 2747 bufferID, 2748 0, 2749 buffer->size(), 2750 flags, 2751 timeUs), 2752 (status_t)OK); 2753 2754 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 2755 2756 if (!eos) { 2757 getMoreInputDataIfPossible(); 2758 } else { 2759 ALOGV("[%s] Signalled EOS on the input port", 2760 mCodec->mComponentName.c_str()); 2761 2762 mCodec->mPortEOS[kPortIndexInput] = true; 2763 mCodec->mInputEOSResult = err; 2764 } 2765 } else if (!mCodec->mPortEOS[kPortIndexInput]) { 2766 if (err != ERROR_END_OF_STREAM) { 2767 ALOGV("[%s] Signalling EOS on the input port " 2768 "due to error %d", 2769 mCodec->mComponentName.c_str(), err); 2770 } else { 2771 ALOGV("[%s] Signalling EOS on the input port", 2772 mCodec->mComponentName.c_str()); 2773 } 2774 2775 ALOGV("[%s] calling emptyBuffer %p signalling EOS", 2776 mCodec->mComponentName.c_str(), bufferID); 2777 2778 CHECK_EQ(mCodec->mOMX->emptyBuffer( 2779 mCodec->mNode, 2780 bufferID, 2781 0, 2782 0, 2783 OMX_BUFFERFLAG_EOS, 2784 0), 2785 (status_t)OK); 2786 2787 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 2788 2789 mCodec->mPortEOS[kPortIndexInput] = true; 2790 mCodec->mInputEOSResult = err; 2791 } 2792 break; 2793 2794 default: 2795 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 2796 break; 2797 } 2798 } 2799} 2800 2801void ACodec::BaseState::getMoreInputDataIfPossible() { 2802 if (mCodec->mPortEOS[kPortIndexInput]) { 2803 return; 2804 } 2805 2806 BufferInfo *eligible = NULL; 2807 2808 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 2809 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 2810 2811#if 0 2812 if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) { 2813 // There's already a "read" pending. 2814 return; 2815 } 2816#endif 2817 2818 if (info->mStatus == BufferInfo::OWNED_BY_US) { 2819 eligible = info; 2820 } 2821 } 2822 2823 if (eligible == NULL) { 2824 return; 2825 } 2826 2827 postFillThisBuffer(eligible); 2828} 2829 2830bool ACodec::BaseState::onOMXFillBufferDone( 2831 IOMX::buffer_id bufferID, 2832 size_t rangeOffset, size_t rangeLength, 2833 OMX_U32 flags, 2834 int64_t timeUs, 2835 void *platformPrivate, 2836 void *dataPtr) { 2837 ALOGV("[%s] onOMXFillBufferDone %p time %lld us, flags = 0x%08lx", 2838 mCodec->mComponentName.c_str(), bufferID, timeUs, flags); 2839 2840 ssize_t index; 2841 2842#if TRACK_BUFFER_TIMING 2843 index = mCodec->mBufferStats.indexOfKey(timeUs); 2844 if (index >= 0) { 2845 ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index); 2846 stats->mFillBufferDoneTimeUs = ALooper::GetNowUs(); 2847 2848 ALOGI("frame PTS %lld: %lld", 2849 timeUs, 2850 stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs); 2851 2852 mCodec->mBufferStats.removeItemsAt(index); 2853 stats = NULL; 2854 } 2855#endif 2856 2857 BufferInfo *info = 2858 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 2859 2860 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); 2861 2862 info->mStatus = BufferInfo::OWNED_BY_US; 2863 2864 PortMode mode = getPortMode(kPortIndexOutput); 2865 2866 switch (mode) { 2867 case KEEP_BUFFERS: 2868 break; 2869 2870 case RESUBMIT_BUFFERS: 2871 { 2872 if (rangeLength == 0 && !(flags & OMX_BUFFERFLAG_EOS)) { 2873 ALOGV("[%s] calling fillBuffer %p", 2874 mCodec->mComponentName.c_str(), info->mBufferID); 2875 2876 CHECK_EQ(mCodec->mOMX->fillBuffer( 2877 mCodec->mNode, info->mBufferID), 2878 (status_t)OK); 2879 2880 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 2881 break; 2882 } 2883 2884 if (!mCodec->mIsEncoder && !mCodec->mSentFormat) { 2885 mCodec->sendFormatChange(); 2886 } 2887 2888 info->mData->setRange(rangeOffset, rangeLength); 2889#if 0 2890 if (mCodec->mNativeWindow == NULL) { 2891 if (IsIDR(info->mData)) { 2892 ALOGI("IDR frame"); 2893 } 2894 } 2895#endif 2896 2897 if (mCodec->mSkipCutBuffer != NULL) { 2898 mCodec->mSkipCutBuffer->submit(info->mData); 2899 } 2900 info->mData->meta()->setInt64("timeUs", timeUs); 2901 2902 sp<AMessage> notify = mCodec->mNotify->dup(); 2903 notify->setInt32("what", ACodec::kWhatDrainThisBuffer); 2904 notify->setPointer("buffer-id", info->mBufferID); 2905 notify->setBuffer("buffer", info->mData); 2906 notify->setInt32("flags", flags); 2907 2908 sp<AMessage> reply = 2909 new AMessage(kWhatOutputBufferDrained, mCodec->id()); 2910 2911 reply->setPointer("buffer-id", info->mBufferID); 2912 2913 notify->setMessage("reply", reply); 2914 2915 notify->post(); 2916 2917 info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM; 2918 2919 if (flags & OMX_BUFFERFLAG_EOS) { 2920 ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str()); 2921 2922 sp<AMessage> notify = mCodec->mNotify->dup(); 2923 notify->setInt32("what", ACodec::kWhatEOS); 2924 notify->setInt32("err", mCodec->mInputEOSResult); 2925 notify->post(); 2926 2927 mCodec->mPortEOS[kPortIndexOutput] = true; 2928 } 2929 break; 2930 } 2931 2932 default: 2933 { 2934 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 2935 2936 CHECK_EQ((status_t)OK, 2937 mCodec->freeBuffer(kPortIndexOutput, index)); 2938 break; 2939 } 2940 } 2941 2942 return true; 2943} 2944 2945void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { 2946 IOMX::buffer_id bufferID; 2947 CHECK(msg->findPointer("buffer-id", &bufferID)); 2948 2949 ssize_t index; 2950 BufferInfo *info = 2951 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 2952 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM); 2953 2954 int32_t render; 2955 if (mCodec->mNativeWindow != NULL 2956 && msg->findInt32("render", &render) && render != 0) { 2957 // The client wants this buffer to be rendered. 2958 2959 status_t err; 2960 if ((err = mCodec->mNativeWindow->queueBuffer( 2961 mCodec->mNativeWindow.get(), 2962 info->mGraphicBuffer.get(), -1)) == OK) { 2963 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 2964 } else { 2965 mCodec->signalError(OMX_ErrorUndefined, err); 2966 info->mStatus = BufferInfo::OWNED_BY_US; 2967 } 2968 } else { 2969 info->mStatus = BufferInfo::OWNED_BY_US; 2970 } 2971 2972 PortMode mode = getPortMode(kPortIndexOutput); 2973 2974 switch (mode) { 2975 case KEEP_BUFFERS: 2976 { 2977 // XXX fishy, revisit!!! What about the FREE_BUFFERS case below? 2978 2979 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 2980 // We cannot resubmit the buffer we just rendered, dequeue 2981 // the spare instead. 2982 2983 info = mCodec->dequeueBufferFromNativeWindow(); 2984 } 2985 break; 2986 } 2987 2988 case RESUBMIT_BUFFERS: 2989 { 2990 if (!mCodec->mPortEOS[kPortIndexOutput]) { 2991 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 2992 // We cannot resubmit the buffer we just rendered, dequeue 2993 // the spare instead. 2994 2995 info = mCodec->dequeueBufferFromNativeWindow(); 2996 } 2997 2998 if (info != NULL) { 2999 ALOGV("[%s] calling fillBuffer %p", 3000 mCodec->mComponentName.c_str(), info->mBufferID); 3001 3002 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), 3003 (status_t)OK); 3004 3005 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 3006 } 3007 } 3008 break; 3009 } 3010 3011 default: 3012 { 3013 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 3014 3015 CHECK_EQ((status_t)OK, 3016 mCodec->freeBuffer(kPortIndexOutput, index)); 3017 break; 3018 } 3019 } 3020} 3021 3022//////////////////////////////////////////////////////////////////////////////// 3023 3024ACodec::UninitializedState::UninitializedState(ACodec *codec) 3025 : BaseState(codec) { 3026} 3027 3028void ACodec::UninitializedState::stateEntered() { 3029 ALOGV("Now uninitialized"); 3030} 3031 3032bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) { 3033 bool handled = false; 3034 3035 switch (msg->what()) { 3036 case ACodec::kWhatSetup: 3037 { 3038 onSetup(msg); 3039 3040 handled = true; 3041 break; 3042 } 3043 3044 case ACodec::kWhatAllocateComponent: 3045 { 3046 onAllocateComponent(msg); 3047 handled = true; 3048 break; 3049 } 3050 3051 case ACodec::kWhatShutdown: 3052 { 3053 int32_t keepComponentAllocated; 3054 CHECK(msg->findInt32( 3055 "keepComponentAllocated", &keepComponentAllocated)); 3056 CHECK(!keepComponentAllocated); 3057 3058 sp<AMessage> notify = mCodec->mNotify->dup(); 3059 notify->setInt32("what", ACodec::kWhatShutdownCompleted); 3060 notify->post(); 3061 3062 handled = true; 3063 break; 3064 } 3065 3066 case ACodec::kWhatFlush: 3067 { 3068 sp<AMessage> notify = mCodec->mNotify->dup(); 3069 notify->setInt32("what", ACodec::kWhatFlushCompleted); 3070 notify->post(); 3071 3072 handled = true; 3073 break; 3074 } 3075 3076 default: 3077 return BaseState::onMessageReceived(msg); 3078 } 3079 3080 return handled; 3081} 3082 3083void ACodec::UninitializedState::onSetup( 3084 const sp<AMessage> &msg) { 3085 if (onAllocateComponent(msg) 3086 && mCodec->mLoadedState->onConfigureComponent(msg)) { 3087 mCodec->mLoadedState->onStart(); 3088 } 3089} 3090 3091bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) { 3092 ALOGV("onAllocateComponent"); 3093 3094 CHECK(mCodec->mNode == NULL); 3095 3096 OMXClient client; 3097 CHECK_EQ(client.connect(), (status_t)OK); 3098 3099 sp<IOMX> omx = client.interface(); 3100 3101 Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs; 3102 3103 AString mime; 3104 3105 AString componentName; 3106 uint32_t quirks = 0; 3107 if (msg->findString("componentName", &componentName)) { 3108 ssize_t index = matchingCodecs.add(); 3109 OMXCodec::CodecNameAndQuirks *entry = &matchingCodecs.editItemAt(index); 3110 entry->mName = String8(componentName.c_str()); 3111 3112 if (!OMXCodec::findCodecQuirks( 3113 componentName.c_str(), &entry->mQuirks)) { 3114 entry->mQuirks = 0; 3115 } 3116 } else { 3117 CHECK(msg->findString("mime", &mime)); 3118 3119 int32_t encoder; 3120 if (!msg->findInt32("encoder", &encoder)) { 3121 encoder = false; 3122 } 3123 3124 OMXCodec::findMatchingCodecs( 3125 mime.c_str(), 3126 encoder, // createEncoder 3127 NULL, // matchComponentName 3128 0, // flags 3129 &matchingCodecs); 3130 } 3131 3132 sp<CodecObserver> observer = new CodecObserver; 3133 IOMX::node_id node = NULL; 3134 3135 for (size_t matchIndex = 0; matchIndex < matchingCodecs.size(); 3136 ++matchIndex) { 3137 componentName = matchingCodecs.itemAt(matchIndex).mName.string(); 3138 quirks = matchingCodecs.itemAt(matchIndex).mQuirks; 3139 3140 pid_t tid = androidGetTid(); 3141 int prevPriority = androidGetThreadPriority(tid); 3142 androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND); 3143 status_t err = omx->allocateNode(componentName.c_str(), observer, &node); 3144 androidSetThreadPriority(tid, prevPriority); 3145 3146 if (err == OK) { 3147 break; 3148 } 3149 3150 node = NULL; 3151 } 3152 3153 if (node == NULL) { 3154 if (!mime.empty()) { 3155 ALOGE("Unable to instantiate a decoder for type '%s'.", 3156 mime.c_str()); 3157 } else { 3158 ALOGE("Unable to instantiate decoder '%s'.", componentName.c_str()); 3159 } 3160 3161 mCodec->signalError(OMX_ErrorComponentNotFound); 3162 return false; 3163 } 3164 3165 sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id()); 3166 observer->setNotificationMessage(notify); 3167 3168 mCodec->mComponentName = componentName; 3169 mCodec->mFlags = 0; 3170 3171 if (componentName.endsWith(".secure")) { 3172 mCodec->mFlags |= kFlagIsSecure; 3173 } 3174 3175 mCodec->mQuirks = quirks; 3176 mCodec->mOMX = omx; 3177 mCodec->mNode = node; 3178 3179 { 3180 sp<AMessage> notify = mCodec->mNotify->dup(); 3181 notify->setInt32("what", ACodec::kWhatComponentAllocated); 3182 notify->setString("componentName", mCodec->mComponentName.c_str()); 3183 notify->post(); 3184 } 3185 3186 mCodec->changeState(mCodec->mLoadedState); 3187 3188 return true; 3189} 3190 3191//////////////////////////////////////////////////////////////////////////////// 3192 3193ACodec::LoadedState::LoadedState(ACodec *codec) 3194 : BaseState(codec) { 3195} 3196 3197void ACodec::LoadedState::stateEntered() { 3198 ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str()); 3199 3200 mCodec->mPortEOS[kPortIndexInput] = 3201 mCodec->mPortEOS[kPortIndexOutput] = false; 3202 3203 mCodec->mInputEOSResult = OK; 3204 3205 if (mCodec->mShutdownInProgress) { 3206 bool keepComponentAllocated = mCodec->mKeepComponentAllocated; 3207 3208 mCodec->mShutdownInProgress = false; 3209 mCodec->mKeepComponentAllocated = false; 3210 3211 onShutdown(keepComponentAllocated); 3212 } 3213} 3214 3215void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) { 3216 if (!keepComponentAllocated) { 3217 CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK); 3218 3219 mCodec->mNativeWindow.clear(); 3220 mCodec->mNode = NULL; 3221 mCodec->mOMX.clear(); 3222 mCodec->mQuirks = 0; 3223 mCodec->mFlags = 0; 3224 mCodec->mComponentName.clear(); 3225 3226 mCodec->changeState(mCodec->mUninitializedState); 3227 } 3228 3229 sp<AMessage> notify = mCodec->mNotify->dup(); 3230 notify->setInt32("what", ACodec::kWhatShutdownCompleted); 3231 notify->post(); 3232} 3233 3234bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) { 3235 bool handled = false; 3236 3237 switch (msg->what()) { 3238 case ACodec::kWhatConfigureComponent: 3239 { 3240 onConfigureComponent(msg); 3241 handled = true; 3242 break; 3243 } 3244 3245 case ACodec::kWhatCreateInputSurface: 3246 { 3247 onCreateInputSurface(msg); 3248 handled = true; 3249 break; 3250 } 3251 3252 case ACodec::kWhatStart: 3253 { 3254 onStart(); 3255 handled = true; 3256 break; 3257 } 3258 3259 case ACodec::kWhatShutdown: 3260 { 3261 int32_t keepComponentAllocated; 3262 CHECK(msg->findInt32( 3263 "keepComponentAllocated", &keepComponentAllocated)); 3264 3265 onShutdown(keepComponentAllocated); 3266 3267 handled = true; 3268 break; 3269 } 3270 3271 case ACodec::kWhatFlush: 3272 { 3273 sp<AMessage> notify = mCodec->mNotify->dup(); 3274 notify->setInt32("what", ACodec::kWhatFlushCompleted); 3275 notify->post(); 3276 3277 handled = true; 3278 break; 3279 } 3280 3281 default: 3282 return BaseState::onMessageReceived(msg); 3283 } 3284 3285 return handled; 3286} 3287 3288bool ACodec::LoadedState::onConfigureComponent( 3289 const sp<AMessage> &msg) { 3290 ALOGV("onConfigureComponent"); 3291 3292 CHECK(mCodec->mNode != NULL); 3293 3294 AString mime; 3295 CHECK(msg->findString("mime", &mime)); 3296 3297 status_t err = mCodec->configureCodec(mime.c_str(), msg); 3298 3299 if (err != OK) { 3300 ALOGE("[%s] configureCodec returning error %d", 3301 mCodec->mComponentName.c_str(), err); 3302 3303 mCodec->signalError(OMX_ErrorUndefined, err); 3304 return false; 3305 } 3306 3307 sp<RefBase> obj; 3308 if (msg->findObject("native-window", &obj) 3309 && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) { 3310 sp<NativeWindowWrapper> nativeWindow( 3311 static_cast<NativeWindowWrapper *>(obj.get())); 3312 CHECK(nativeWindow != NULL); 3313 mCodec->mNativeWindow = nativeWindow->getNativeWindow(); 3314 3315 native_window_set_scaling_mode( 3316 mCodec->mNativeWindow.get(), 3317 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); 3318 } 3319 CHECK_EQ((status_t)OK, mCodec->initNativeWindow()); 3320 3321 { 3322 sp<AMessage> notify = mCodec->mNotify->dup(); 3323 notify->setInt32("what", ACodec::kWhatComponentConfigured); 3324 notify->post(); 3325 } 3326 3327 return true; 3328} 3329 3330void ACodec::LoadedState::onCreateInputSurface( 3331 const sp<AMessage> &msg) { 3332 ALOGV("onCreateInputSurface"); 3333 3334 sp<AMessage> notify = mCodec->mNotify->dup(); 3335 notify->setInt32("what", ACodec::kWhatInputSurfaceCreated); 3336 3337 sp<IGraphicBufferProducer> bufferProducer; 3338 status_t err; 3339 3340 err = mCodec->mOMX->createInputSurface(mCodec->mNode, kPortIndexInput, 3341 &bufferProducer); 3342 if (err == OK) { 3343 notify->setObject("input-surface", 3344 new BufferProducerWrapper(bufferProducer)); 3345 } else { 3346 // Can't use mCodec->signalError() here -- MediaCodec won't forward 3347 // the error through because it's in the "configured" state. We 3348 // send a kWhatInputSurfaceCreated with an error value instead. 3349 ALOGE("[%s] onCreateInputSurface returning error %d", 3350 mCodec->mComponentName.c_str(), err); 3351 notify->setInt32("err", err); 3352 } 3353 notify->post(); 3354} 3355 3356void ACodec::LoadedState::onStart() { 3357 ALOGV("onStart"); 3358 3359 CHECK_EQ(mCodec->mOMX->sendCommand( 3360 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle), 3361 (status_t)OK); 3362 3363 mCodec->changeState(mCodec->mLoadedToIdleState); 3364} 3365 3366//////////////////////////////////////////////////////////////////////////////// 3367 3368ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec) 3369 : BaseState(codec) { 3370} 3371 3372void ACodec::LoadedToIdleState::stateEntered() { 3373 ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str()); 3374 3375 status_t err; 3376 if ((err = allocateBuffers()) != OK) { 3377 ALOGE("Failed to allocate buffers after transitioning to IDLE state " 3378 "(error 0x%08x)", 3379 err); 3380 3381 mCodec->signalError(OMX_ErrorUndefined, err); 3382 3383 mCodec->changeState(mCodec->mLoadedState); 3384 } 3385} 3386 3387status_t ACodec::LoadedToIdleState::allocateBuffers() { 3388 status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput); 3389 3390 if (err != OK) { 3391 return err; 3392 } 3393 3394 return mCodec->allocateBuffersOnPort(kPortIndexOutput); 3395} 3396 3397bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) { 3398 switch (msg->what()) { 3399 case kWhatShutdown: 3400 { 3401 mCodec->deferMessage(msg); 3402 return true; 3403 } 3404 3405 case kWhatSignalEndOfInputStream: 3406 { 3407 mCodec->onSignalEndOfInputStream(); 3408 return true; 3409 } 3410 3411 case kWhatResume: 3412 { 3413 // We'll be active soon enough. 3414 return true; 3415 } 3416 3417 case kWhatFlush: 3418 { 3419 // We haven't even started yet, so we're flushed alright... 3420 sp<AMessage> notify = mCodec->mNotify->dup(); 3421 notify->setInt32("what", ACodec::kWhatFlushCompleted); 3422 notify->post(); 3423 return true; 3424 } 3425 3426 default: 3427 return BaseState::onMessageReceived(msg); 3428 } 3429} 3430 3431bool ACodec::LoadedToIdleState::onOMXEvent( 3432 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3433 switch (event) { 3434 case OMX_EventCmdComplete: 3435 { 3436 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 3437 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); 3438 3439 CHECK_EQ(mCodec->mOMX->sendCommand( 3440 mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting), 3441 (status_t)OK); 3442 3443 mCodec->changeState(mCodec->mIdleToExecutingState); 3444 3445 return true; 3446 } 3447 3448 default: 3449 return BaseState::onOMXEvent(event, data1, data2); 3450 } 3451} 3452 3453//////////////////////////////////////////////////////////////////////////////// 3454 3455ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec) 3456 : BaseState(codec) { 3457} 3458 3459void ACodec::IdleToExecutingState::stateEntered() { 3460 ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str()); 3461} 3462 3463bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) { 3464 switch (msg->what()) { 3465 case kWhatShutdown: 3466 { 3467 mCodec->deferMessage(msg); 3468 return true; 3469 } 3470 3471 case kWhatResume: 3472 { 3473 // We'll be active soon enough. 3474 return true; 3475 } 3476 3477 case kWhatFlush: 3478 { 3479 // We haven't even started yet, so we're flushed alright... 3480 sp<AMessage> notify = mCodec->mNotify->dup(); 3481 notify->setInt32("what", ACodec::kWhatFlushCompleted); 3482 notify->post(); 3483 3484 return true; 3485 } 3486 3487 case kWhatSignalEndOfInputStream: 3488 { 3489 mCodec->onSignalEndOfInputStream(); 3490 return true; 3491 } 3492 3493 default: 3494 return BaseState::onMessageReceived(msg); 3495 } 3496} 3497 3498bool ACodec::IdleToExecutingState::onOMXEvent( 3499 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3500 switch (event) { 3501 case OMX_EventCmdComplete: 3502 { 3503 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 3504 CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting); 3505 3506 mCodec->mExecutingState->resume(); 3507 mCodec->changeState(mCodec->mExecutingState); 3508 3509 return true; 3510 } 3511 3512 default: 3513 return BaseState::onOMXEvent(event, data1, data2); 3514 } 3515} 3516 3517//////////////////////////////////////////////////////////////////////////////// 3518 3519ACodec::ExecutingState::ExecutingState(ACodec *codec) 3520 : BaseState(codec), 3521 mActive(false) { 3522} 3523 3524ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode( 3525 OMX_U32 portIndex) { 3526 return RESUBMIT_BUFFERS; 3527} 3528 3529void ACodec::ExecutingState::submitOutputBuffers() { 3530 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) { 3531 BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i); 3532 3533 if (mCodec->mNativeWindow != NULL) { 3534 CHECK(info->mStatus == BufferInfo::OWNED_BY_US 3535 || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW); 3536 3537 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 3538 continue; 3539 } 3540 } else { 3541 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 3542 } 3543 3544 ALOGV("[%s] calling fillBuffer %p", 3545 mCodec->mComponentName.c_str(), info->mBufferID); 3546 3547 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), 3548 (status_t)OK); 3549 3550 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 3551 } 3552} 3553 3554void ACodec::ExecutingState::resume() { 3555 if (mActive) { 3556 ALOGV("[%s] We're already active, no need to resume.", 3557 mCodec->mComponentName.c_str()); 3558 3559 return; 3560 } 3561 3562 submitOutputBuffers(); 3563 3564 // Post the first input buffer. 3565 CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u); 3566 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0); 3567 3568 postFillThisBuffer(info); 3569 3570 mActive = true; 3571} 3572 3573void ACodec::ExecutingState::stateEntered() { 3574 ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str()); 3575 3576 mCodec->processDeferredMessages(); 3577} 3578 3579bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) { 3580 bool handled = false; 3581 3582 switch (msg->what()) { 3583 case kWhatShutdown: 3584 { 3585 int32_t keepComponentAllocated; 3586 CHECK(msg->findInt32( 3587 "keepComponentAllocated", &keepComponentAllocated)); 3588 3589 mCodec->mShutdownInProgress = true; 3590 mCodec->mKeepComponentAllocated = keepComponentAllocated; 3591 3592 mActive = false; 3593 3594 CHECK_EQ(mCodec->mOMX->sendCommand( 3595 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle), 3596 (status_t)OK); 3597 3598 mCodec->changeState(mCodec->mExecutingToIdleState); 3599 3600 handled = true; 3601 break; 3602 } 3603 3604 case kWhatFlush: 3605 { 3606 ALOGV("[%s] ExecutingState flushing now " 3607 "(codec owns %d/%d input, %d/%d output).", 3608 mCodec->mComponentName.c_str(), 3609 mCodec->countBuffersOwnedByComponent(kPortIndexInput), 3610 mCodec->mBuffers[kPortIndexInput].size(), 3611 mCodec->countBuffersOwnedByComponent(kPortIndexOutput), 3612 mCodec->mBuffers[kPortIndexOutput].size()); 3613 3614 mActive = false; 3615 3616 CHECK_EQ(mCodec->mOMX->sendCommand( 3617 mCodec->mNode, OMX_CommandFlush, OMX_ALL), 3618 (status_t)OK); 3619 3620 mCodec->changeState(mCodec->mFlushingState); 3621 3622 handled = true; 3623 break; 3624 } 3625 3626 case kWhatResume: 3627 { 3628 resume(); 3629 3630 handled = true; 3631 break; 3632 } 3633 3634 case kWhatRequestIDRFrame: 3635 { 3636 status_t err = mCodec->requestIDRFrame(); 3637 if (err != OK) { 3638 ALOGW("Requesting an IDR frame failed."); 3639 } 3640 3641 handled = true; 3642 break; 3643 } 3644 3645 case kWhatSetParameters: 3646 { 3647 sp<AMessage> params; 3648 CHECK(msg->findMessage("params", ¶ms)); 3649 3650 status_t err = mCodec->setParameters(params); 3651 3652 sp<AMessage> reply; 3653 if (msg->findMessage("reply", &reply)) { 3654 reply->setInt32("err", err); 3655 reply->post(); 3656 } 3657 3658 handled = true; 3659 break; 3660 } 3661 3662 case ACodec::kWhatSignalEndOfInputStream: 3663 { 3664 mCodec->onSignalEndOfInputStream(); 3665 handled = true; 3666 break; 3667 } 3668 3669 default: 3670 handled = BaseState::onMessageReceived(msg); 3671 break; 3672 } 3673 3674 return handled; 3675} 3676 3677status_t ACodec::setParameters(const sp<AMessage> ¶ms) { 3678 int32_t videoBitrate; 3679 if (params->findInt32("videoBitrate", &videoBitrate)) { 3680 OMX_VIDEO_CONFIG_BITRATETYPE configParams; 3681 InitOMXParams(&configParams); 3682 configParams.nPortIndex = kPortIndexOutput; 3683 configParams.nEncodeBitrate = videoBitrate; 3684 3685 status_t err = mOMX->setConfig( 3686 mNode, 3687 OMX_IndexConfigVideoBitrate, 3688 &configParams, 3689 sizeof(configParams)); 3690 3691 if (err != OK) { 3692 ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d", 3693 videoBitrate, err); 3694 3695 return err; 3696 } 3697 } 3698 3699 return OK; 3700} 3701 3702void ACodec::onSignalEndOfInputStream() { 3703 sp<AMessage> notify = mNotify->dup(); 3704 notify->setInt32("what", ACodec::kWhatSignaledInputEOS); 3705 3706 status_t err = mOMX->signalEndOfInputStream(mNode); 3707 if (err != OK) { 3708 notify->setInt32("err", err); 3709 } 3710 notify->post(); 3711} 3712 3713bool ACodec::ExecutingState::onOMXEvent( 3714 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3715 switch (event) { 3716 case OMX_EventPortSettingsChanged: 3717 { 3718 CHECK_EQ(data1, (OMX_U32)kPortIndexOutput); 3719 3720 if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) { 3721 CHECK_EQ(mCodec->mOMX->sendCommand( 3722 mCodec->mNode, 3723 OMX_CommandPortDisable, kPortIndexOutput), 3724 (status_t)OK); 3725 3726 mCodec->freeOutputBuffersNotOwnedByComponent(); 3727 3728 mCodec->changeState(mCodec->mOutputPortSettingsChangedState); 3729 } else if (data2 == OMX_IndexConfigCommonOutputCrop) { 3730 mCodec->mSentFormat = false; 3731 } else { 3732 ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx", 3733 mCodec->mComponentName.c_str(), data2); 3734 } 3735 3736 return true; 3737 } 3738 3739 case OMX_EventBufferFlag: 3740 { 3741 return true; 3742 } 3743 3744 default: 3745 return BaseState::onOMXEvent(event, data1, data2); 3746 } 3747} 3748 3749//////////////////////////////////////////////////////////////////////////////// 3750 3751ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState( 3752 ACodec *codec) 3753 : BaseState(codec) { 3754} 3755 3756ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode( 3757 OMX_U32 portIndex) { 3758 if (portIndex == kPortIndexOutput) { 3759 return FREE_BUFFERS; 3760 } 3761 3762 CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput); 3763 3764 return RESUBMIT_BUFFERS; 3765} 3766 3767bool ACodec::OutputPortSettingsChangedState::onMessageReceived( 3768 const sp<AMessage> &msg) { 3769 bool handled = false; 3770 3771 switch (msg->what()) { 3772 case kWhatFlush: 3773 case kWhatShutdown: 3774 case kWhatResume: 3775 { 3776 if (msg->what() == kWhatResume) { 3777 ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str()); 3778 } 3779 3780 mCodec->deferMessage(msg); 3781 handled = true; 3782 break; 3783 } 3784 3785 default: 3786 handled = BaseState::onMessageReceived(msg); 3787 break; 3788 } 3789 3790 return handled; 3791} 3792 3793void ACodec::OutputPortSettingsChangedState::stateEntered() { 3794 ALOGV("[%s] Now handling output port settings change", 3795 mCodec->mComponentName.c_str()); 3796} 3797 3798bool ACodec::OutputPortSettingsChangedState::onOMXEvent( 3799 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3800 switch (event) { 3801 case OMX_EventCmdComplete: 3802 { 3803 if (data1 == (OMX_U32)OMX_CommandPortDisable) { 3804 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput); 3805 3806 ALOGV("[%s] Output port now disabled.", 3807 mCodec->mComponentName.c_str()); 3808 3809 CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty()); 3810 mCodec->mDealer[kPortIndexOutput].clear(); 3811 3812 CHECK_EQ(mCodec->mOMX->sendCommand( 3813 mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput), 3814 (status_t)OK); 3815 3816 status_t err; 3817 if ((err = mCodec->allocateBuffersOnPort( 3818 kPortIndexOutput)) != OK) { 3819 ALOGE("Failed to allocate output port buffers after " 3820 "port reconfiguration (error 0x%08x)", 3821 err); 3822 3823 mCodec->signalError(OMX_ErrorUndefined, err); 3824 3825 // This is technically not correct, but appears to be 3826 // the only way to free the component instance. 3827 // Controlled transitioning from excecuting->idle 3828 // and idle->loaded seem impossible probably because 3829 // the output port never finishes re-enabling. 3830 mCodec->mShutdownInProgress = true; 3831 mCodec->mKeepComponentAllocated = false; 3832 mCodec->changeState(mCodec->mLoadedState); 3833 } 3834 3835 return true; 3836 } else if (data1 == (OMX_U32)OMX_CommandPortEnable) { 3837 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput); 3838 3839 mCodec->mSentFormat = false; 3840 3841 ALOGV("[%s] Output port now reenabled.", 3842 mCodec->mComponentName.c_str()); 3843 3844 if (mCodec->mExecutingState->active()) { 3845 mCodec->mExecutingState->submitOutputBuffers(); 3846 } 3847 3848 mCodec->changeState(mCodec->mExecutingState); 3849 3850 return true; 3851 } 3852 3853 return false; 3854 } 3855 3856 default: 3857 return false; 3858 } 3859} 3860 3861//////////////////////////////////////////////////////////////////////////////// 3862 3863ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec) 3864 : BaseState(codec), 3865 mComponentNowIdle(false) { 3866} 3867 3868bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) { 3869 bool handled = false; 3870 3871 switch (msg->what()) { 3872 case kWhatFlush: 3873 { 3874 // Don't send me a flush request if you previously wanted me 3875 // to shutdown. 3876 TRESPASS(); 3877 break; 3878 } 3879 3880 case kWhatShutdown: 3881 { 3882 // We're already doing that... 3883 3884 handled = true; 3885 break; 3886 } 3887 3888 default: 3889 handled = BaseState::onMessageReceived(msg); 3890 break; 3891 } 3892 3893 return handled; 3894} 3895 3896void ACodec::ExecutingToIdleState::stateEntered() { 3897 ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str()); 3898 3899 mComponentNowIdle = false; 3900 mCodec->mSentFormat = false; 3901} 3902 3903bool ACodec::ExecutingToIdleState::onOMXEvent( 3904 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3905 switch (event) { 3906 case OMX_EventCmdComplete: 3907 { 3908 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 3909 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); 3910 3911 mComponentNowIdle = true; 3912 3913 changeStateIfWeOwnAllBuffers(); 3914 3915 return true; 3916 } 3917 3918 case OMX_EventPortSettingsChanged: 3919 case OMX_EventBufferFlag: 3920 { 3921 // We're shutting down and don't care about this anymore. 3922 return true; 3923 } 3924 3925 default: 3926 return BaseState::onOMXEvent(event, data1, data2); 3927 } 3928} 3929 3930void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() { 3931 if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) { 3932 CHECK_EQ(mCodec->mOMX->sendCommand( 3933 mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded), 3934 (status_t)OK); 3935 3936 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK); 3937 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK); 3938 3939 if (mCodec->mFlags & kFlagIsSecure && mCodec->mNativeWindow != NULL) { 3940 // We push enough 1x1 blank buffers to ensure that one of 3941 // them has made it to the display. This allows the OMX 3942 // component teardown to zero out any protected buffers 3943 // without the risk of scanning out one of those buffers. 3944 mCodec->pushBlankBuffersToNativeWindow(); 3945 } 3946 3947 mCodec->changeState(mCodec->mIdleToLoadedState); 3948 } 3949} 3950 3951void ACodec::ExecutingToIdleState::onInputBufferFilled( 3952 const sp<AMessage> &msg) { 3953 BaseState::onInputBufferFilled(msg); 3954 3955 changeStateIfWeOwnAllBuffers(); 3956} 3957 3958void ACodec::ExecutingToIdleState::onOutputBufferDrained( 3959 const sp<AMessage> &msg) { 3960 BaseState::onOutputBufferDrained(msg); 3961 3962 changeStateIfWeOwnAllBuffers(); 3963} 3964 3965//////////////////////////////////////////////////////////////////////////////// 3966 3967ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec) 3968 : BaseState(codec) { 3969} 3970 3971bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) { 3972 bool handled = false; 3973 3974 switch (msg->what()) { 3975 case kWhatShutdown: 3976 { 3977 // We're already doing that... 3978 3979 handled = true; 3980 break; 3981 } 3982 3983 case kWhatFlush: 3984 { 3985 // Don't send me a flush request if you previously wanted me 3986 // to shutdown. 3987 TRESPASS(); 3988 break; 3989 } 3990 3991 default: 3992 handled = BaseState::onMessageReceived(msg); 3993 break; 3994 } 3995 3996 return handled; 3997} 3998 3999void ACodec::IdleToLoadedState::stateEntered() { 4000 ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str()); 4001} 4002 4003bool ACodec::IdleToLoadedState::onOMXEvent( 4004 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 4005 switch (event) { 4006 case OMX_EventCmdComplete: 4007 { 4008 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 4009 CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded); 4010 4011 mCodec->changeState(mCodec->mLoadedState); 4012 4013 return true; 4014 } 4015 4016 default: 4017 return BaseState::onOMXEvent(event, data1, data2); 4018 } 4019} 4020 4021//////////////////////////////////////////////////////////////////////////////// 4022 4023ACodec::FlushingState::FlushingState(ACodec *codec) 4024 : BaseState(codec) { 4025} 4026 4027void ACodec::FlushingState::stateEntered() { 4028 ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str()); 4029 4030 mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false; 4031} 4032 4033bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) { 4034 bool handled = false; 4035 4036 switch (msg->what()) { 4037 case kWhatShutdown: 4038 { 4039 mCodec->deferMessage(msg); 4040 break; 4041 } 4042 4043 case kWhatFlush: 4044 { 4045 // We're already doing this right now. 4046 handled = true; 4047 break; 4048 } 4049 4050 default: 4051 handled = BaseState::onMessageReceived(msg); 4052 break; 4053 } 4054 4055 return handled; 4056} 4057 4058bool ACodec::FlushingState::onOMXEvent( 4059 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 4060 ALOGV("[%s] FlushingState onOMXEvent(%d,%ld)", 4061 mCodec->mComponentName.c_str(), event, data1); 4062 4063 switch (event) { 4064 case OMX_EventCmdComplete: 4065 { 4066 CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush); 4067 4068 if (data2 == kPortIndexInput || data2 == kPortIndexOutput) { 4069 CHECK(!mFlushComplete[data2]); 4070 mFlushComplete[data2] = true; 4071 4072 if (mFlushComplete[kPortIndexInput] 4073 && mFlushComplete[kPortIndexOutput]) { 4074 changeStateIfWeOwnAllBuffers(); 4075 } 4076 } else { 4077 CHECK_EQ(data2, OMX_ALL); 4078 CHECK(mFlushComplete[kPortIndexInput]); 4079 CHECK(mFlushComplete[kPortIndexOutput]); 4080 4081 changeStateIfWeOwnAllBuffers(); 4082 } 4083 4084 return true; 4085 } 4086 4087 case OMX_EventPortSettingsChanged: 4088 { 4089 sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id()); 4090 msg->setInt32("type", omx_message::EVENT); 4091 msg->setPointer("node", mCodec->mNode); 4092 msg->setInt32("event", event); 4093 msg->setInt32("data1", data1); 4094 msg->setInt32("data2", data2); 4095 4096 ALOGV("[%s] Deferring OMX_EventPortSettingsChanged", 4097 mCodec->mComponentName.c_str()); 4098 4099 mCodec->deferMessage(msg); 4100 4101 return true; 4102 } 4103 4104 default: 4105 return BaseState::onOMXEvent(event, data1, data2); 4106 } 4107 4108 return true; 4109} 4110 4111void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) { 4112 BaseState::onOutputBufferDrained(msg); 4113 4114 changeStateIfWeOwnAllBuffers(); 4115} 4116 4117void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) { 4118 BaseState::onInputBufferFilled(msg); 4119 4120 changeStateIfWeOwnAllBuffers(); 4121} 4122 4123void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() { 4124 if (mFlushComplete[kPortIndexInput] 4125 && mFlushComplete[kPortIndexOutput] 4126 && mCodec->allYourBuffersAreBelongToUs()) { 4127 sp<AMessage> notify = mCodec->mNotify->dup(); 4128 notify->setInt32("what", ACodec::kWhatFlushCompleted); 4129 notify->post(); 4130 4131 mCodec->mPortEOS[kPortIndexInput] = 4132 mCodec->mPortEOS[kPortIndexOutput] = false; 4133 4134 mCodec->mInputEOSResult = OK; 4135 4136 mCodec->changeState(mCodec->mExecutingState); 4137 } 4138} 4139 4140} // namespace android 4141