ACodec.cpp revision 6463e76d41430f9b03a79b221de84255f2475658
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 CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar 1436 || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar 1437 || format.eColorFormat == OMX_COLOR_FormatCbYCrY 1438 || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar 1439 || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar 1440 || format.eColorFormat == OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka 1441 || format.eColorFormat == OMX_SEC_COLOR_FormatNV12Tiled); 1442 1443 return mOMX->setParameter( 1444 mNode, OMX_IndexParamVideoPortFormat, 1445 &format, sizeof(format)); 1446} 1447 1448static status_t GetVideoCodingTypeFromMime( 1449 const char *mime, OMX_VIDEO_CODINGTYPE *codingType) { 1450 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 1451 *codingType = OMX_VIDEO_CodingAVC; 1452 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 1453 *codingType = OMX_VIDEO_CodingMPEG4; 1454 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 1455 *codingType = OMX_VIDEO_CodingH263; 1456 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG2, mime)) { 1457 *codingType = OMX_VIDEO_CodingMPEG2; 1458 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_VPX, mime)) { 1459 *codingType = OMX_VIDEO_CodingVPX; 1460 } else { 1461 *codingType = OMX_VIDEO_CodingUnused; 1462 return ERROR_UNSUPPORTED; 1463 } 1464 1465 return OK; 1466} 1467 1468status_t ACodec::setupVideoDecoder( 1469 const char *mime, int32_t width, int32_t height) { 1470 OMX_VIDEO_CODINGTYPE compressionFormat; 1471 status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat); 1472 1473 if (err != OK) { 1474 return err; 1475 } 1476 1477 err = setVideoPortFormatType( 1478 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused); 1479 1480 if (err != OK) { 1481 return err; 1482 } 1483 1484 err = setSupportedOutputFormat(); 1485 1486 if (err != OK) { 1487 return err; 1488 } 1489 1490 err = setVideoFormatOnPort( 1491 kPortIndexInput, width, height, compressionFormat); 1492 1493 if (err != OK) { 1494 return err; 1495 } 1496 1497 err = setVideoFormatOnPort( 1498 kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused); 1499 1500 if (err != OK) { 1501 return err; 1502 } 1503 1504 return OK; 1505} 1506 1507status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) { 1508 int32_t tmp; 1509 if (!msg->findInt32("color-format", &tmp)) { 1510 return INVALID_OPERATION; 1511 } 1512 1513 OMX_COLOR_FORMATTYPE colorFormat = 1514 static_cast<OMX_COLOR_FORMATTYPE>(tmp); 1515 1516 status_t err = setVideoPortFormatType( 1517 kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat); 1518 1519 if (err != OK) { 1520 ALOGE("[%s] does not support color format %d", 1521 mComponentName.c_str(), colorFormat); 1522 1523 return err; 1524 } 1525 1526 /* Input port configuration */ 1527 1528 OMX_PARAM_PORTDEFINITIONTYPE def; 1529 InitOMXParams(&def); 1530 1531 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 1532 1533 def.nPortIndex = kPortIndexInput; 1534 1535 err = mOMX->getParameter( 1536 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1537 1538 if (err != OK) { 1539 return err; 1540 } 1541 1542 int32_t width, height, bitrate; 1543 if (!msg->findInt32("width", &width) 1544 || !msg->findInt32("height", &height) 1545 || !msg->findInt32("bitrate", &bitrate)) { 1546 return INVALID_OPERATION; 1547 } 1548 1549 video_def->nFrameWidth = width; 1550 video_def->nFrameHeight = height; 1551 1552 int32_t stride; 1553 if (!msg->findInt32("stride", &stride)) { 1554 stride = width; 1555 } 1556 1557 video_def->nStride = stride; 1558 1559 int32_t sliceHeight; 1560 if (!msg->findInt32("slice-height", &sliceHeight)) { 1561 sliceHeight = height; 1562 } 1563 1564 video_def->nSliceHeight = sliceHeight; 1565 1566 def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2; 1567 1568 float frameRate; 1569 if (!msg->findFloat("frame-rate", &frameRate)) { 1570 int32_t tmp; 1571 if (!msg->findInt32("frame-rate", &tmp)) { 1572 return INVALID_OPERATION; 1573 } 1574 frameRate = (float)tmp; 1575 } 1576 1577 video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f); 1578 video_def->eCompressionFormat = OMX_VIDEO_CodingUnused; 1579 video_def->eColorFormat = colorFormat; 1580 1581 err = mOMX->setParameter( 1582 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1583 1584 if (err != OK) { 1585 ALOGE("[%s] failed to set input port definition parameters.", 1586 mComponentName.c_str()); 1587 1588 return err; 1589 } 1590 1591 /* Output port configuration */ 1592 1593 OMX_VIDEO_CODINGTYPE compressionFormat; 1594 err = GetVideoCodingTypeFromMime(mime, &compressionFormat); 1595 1596 if (err != OK) { 1597 return err; 1598 } 1599 1600 err = setVideoPortFormatType( 1601 kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused); 1602 1603 if (err != OK) { 1604 ALOGE("[%s] does not support compression format %d", 1605 mComponentName.c_str(), compressionFormat); 1606 1607 return err; 1608 } 1609 1610 def.nPortIndex = kPortIndexOutput; 1611 1612 err = mOMX->getParameter( 1613 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1614 1615 if (err != OK) { 1616 return err; 1617 } 1618 1619 video_def->nFrameWidth = width; 1620 video_def->nFrameHeight = height; 1621 video_def->xFramerate = 0; 1622 video_def->nBitrate = bitrate; 1623 video_def->eCompressionFormat = compressionFormat; 1624 video_def->eColorFormat = OMX_COLOR_FormatUnused; 1625 1626 err = mOMX->setParameter( 1627 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 1628 1629 if (err != OK) { 1630 ALOGE("[%s] failed to set output port definition parameters.", 1631 mComponentName.c_str()); 1632 1633 return err; 1634 } 1635 1636 switch (compressionFormat) { 1637 case OMX_VIDEO_CodingMPEG4: 1638 err = setupMPEG4EncoderParameters(msg); 1639 break; 1640 1641 case OMX_VIDEO_CodingH263: 1642 err = setupH263EncoderParameters(msg); 1643 break; 1644 1645 case OMX_VIDEO_CodingAVC: 1646 err = setupAVCEncoderParameters(msg); 1647 break; 1648 1649 default: 1650 break; 1651 } 1652 1653 ALOGI("setupVideoEncoder succeeded"); 1654 1655 return err; 1656} 1657 1658status_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) { 1659 OMX_VIDEO_PARAM_INTRAREFRESHTYPE params; 1660 InitOMXParams(¶ms); 1661 params.nPortIndex = kPortIndexOutput; 1662 1663 params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode); 1664 1665 if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic || 1666 params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) { 1667 int32_t mbs; 1668 if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) { 1669 return INVALID_OPERATION; 1670 } 1671 params.nCirMBs = mbs; 1672 } 1673 1674 if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive || 1675 params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) { 1676 int32_t mbs; 1677 if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) { 1678 return INVALID_OPERATION; 1679 } 1680 params.nAirMBs = mbs; 1681 1682 int32_t ref; 1683 if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) { 1684 return INVALID_OPERATION; 1685 } 1686 params.nAirRef = ref; 1687 } 1688 1689 status_t err = mOMX->setParameter( 1690 mNode, OMX_IndexParamVideoIntraRefresh, 1691 ¶ms, sizeof(params)); 1692 return err; 1693} 1694 1695static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) { 1696 if (iFramesInterval < 0) { 1697 return 0xFFFFFFFF; 1698 } else if (iFramesInterval == 0) { 1699 return 0; 1700 } 1701 OMX_U32 ret = frameRate * iFramesInterval; 1702 CHECK(ret > 1); 1703 return ret; 1704} 1705 1706static OMX_VIDEO_CONTROLRATETYPE getBitrateMode(const sp<AMessage> &msg) { 1707 int32_t tmp; 1708 if (!msg->findInt32("bitrate-mode", &tmp)) { 1709 return OMX_Video_ControlRateVariable; 1710 } 1711 1712 return static_cast<OMX_VIDEO_CONTROLRATETYPE>(tmp); 1713} 1714 1715status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) { 1716 int32_t bitrate, iFrameInterval; 1717 if (!msg->findInt32("bitrate", &bitrate) 1718 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 1719 return INVALID_OPERATION; 1720 } 1721 1722 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 1723 1724 float frameRate; 1725 if (!msg->findFloat("frame-rate", &frameRate)) { 1726 int32_t tmp; 1727 if (!msg->findInt32("frame-rate", &tmp)) { 1728 return INVALID_OPERATION; 1729 } 1730 frameRate = (float)tmp; 1731 } 1732 1733 OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type; 1734 InitOMXParams(&mpeg4type); 1735 mpeg4type.nPortIndex = kPortIndexOutput; 1736 1737 status_t err = mOMX->getParameter( 1738 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); 1739 1740 if (err != OK) { 1741 return err; 1742 } 1743 1744 mpeg4type.nSliceHeaderSpacing = 0; 1745 mpeg4type.bSVH = OMX_FALSE; 1746 mpeg4type.bGov = OMX_FALSE; 1747 1748 mpeg4type.nAllowedPictureTypes = 1749 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 1750 1751 mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 1752 if (mpeg4type.nPFrames == 0) { 1753 mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 1754 } 1755 mpeg4type.nBFrames = 0; 1756 mpeg4type.nIDCVLCThreshold = 0; 1757 mpeg4type.bACPred = OMX_TRUE; 1758 mpeg4type.nMaxPacketSize = 256; 1759 mpeg4type.nTimeIncRes = 1000; 1760 mpeg4type.nHeaderExtension = 0; 1761 mpeg4type.bReversibleVLC = OMX_FALSE; 1762 1763 int32_t profile; 1764 if (msg->findInt32("profile", &profile)) { 1765 int32_t level; 1766 if (!msg->findInt32("level", &level)) { 1767 return INVALID_OPERATION; 1768 } 1769 1770 err = verifySupportForProfileAndLevel(profile, level); 1771 1772 if (err != OK) { 1773 return err; 1774 } 1775 1776 mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile); 1777 mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level); 1778 } 1779 1780 err = mOMX->setParameter( 1781 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); 1782 1783 if (err != OK) { 1784 return err; 1785 } 1786 1787 err = configureBitrate(bitrate, bitrateMode); 1788 1789 if (err != OK) { 1790 return err; 1791 } 1792 1793 return setupErrorCorrectionParameters(); 1794} 1795 1796status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) { 1797 int32_t bitrate, iFrameInterval; 1798 if (!msg->findInt32("bitrate", &bitrate) 1799 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 1800 return INVALID_OPERATION; 1801 } 1802 1803 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 1804 1805 float frameRate; 1806 if (!msg->findFloat("frame-rate", &frameRate)) { 1807 int32_t tmp; 1808 if (!msg->findInt32("frame-rate", &tmp)) { 1809 return INVALID_OPERATION; 1810 } 1811 frameRate = (float)tmp; 1812 } 1813 1814 OMX_VIDEO_PARAM_H263TYPE h263type; 1815 InitOMXParams(&h263type); 1816 h263type.nPortIndex = kPortIndexOutput; 1817 1818 status_t err = mOMX->getParameter( 1819 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); 1820 1821 if (err != OK) { 1822 return err; 1823 } 1824 1825 h263type.nAllowedPictureTypes = 1826 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 1827 1828 h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 1829 if (h263type.nPFrames == 0) { 1830 h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 1831 } 1832 h263type.nBFrames = 0; 1833 1834 int32_t profile; 1835 if (msg->findInt32("profile", &profile)) { 1836 int32_t level; 1837 if (!msg->findInt32("level", &level)) { 1838 return INVALID_OPERATION; 1839 } 1840 1841 err = verifySupportForProfileAndLevel(profile, level); 1842 1843 if (err != OK) { 1844 return err; 1845 } 1846 1847 h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile); 1848 h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level); 1849 } 1850 1851 h263type.bPLUSPTYPEAllowed = OMX_FALSE; 1852 h263type.bForceRoundingTypeToZero = OMX_FALSE; 1853 h263type.nPictureHeaderRepetition = 0; 1854 h263type.nGOBHeaderInterval = 0; 1855 1856 err = mOMX->setParameter( 1857 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); 1858 1859 if (err != OK) { 1860 return err; 1861 } 1862 1863 err = configureBitrate(bitrate, bitrateMode); 1864 1865 if (err != OK) { 1866 return err; 1867 } 1868 1869 return setupErrorCorrectionParameters(); 1870} 1871 1872status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) { 1873 int32_t bitrate, iFrameInterval; 1874 if (!msg->findInt32("bitrate", &bitrate) 1875 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 1876 return INVALID_OPERATION; 1877 } 1878 1879 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 1880 1881 float frameRate; 1882 if (!msg->findFloat("frame-rate", &frameRate)) { 1883 int32_t tmp; 1884 if (!msg->findInt32("frame-rate", &tmp)) { 1885 return INVALID_OPERATION; 1886 } 1887 frameRate = (float)tmp; 1888 } 1889 1890 status_t err = OK; 1891 int32_t intraRefreshMode = 0; 1892 if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) { 1893 err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode); 1894 if (err != OK) { 1895 ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x", 1896 err, intraRefreshMode); 1897 return err; 1898 } 1899 } 1900 1901 OMX_VIDEO_PARAM_AVCTYPE h264type; 1902 InitOMXParams(&h264type); 1903 h264type.nPortIndex = kPortIndexOutput; 1904 1905 err = mOMX->getParameter( 1906 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 1907 1908 if (err != OK) { 1909 return err; 1910 } 1911 1912 h264type.nAllowedPictureTypes = 1913 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 1914 1915 int32_t profile; 1916 if (msg->findInt32("profile", &profile)) { 1917 int32_t level; 1918 if (!msg->findInt32("level", &level)) { 1919 return INVALID_OPERATION; 1920 } 1921 1922 err = verifySupportForProfileAndLevel(profile, level); 1923 1924 if (err != OK) { 1925 return err; 1926 } 1927 1928 h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile); 1929 h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level); 1930 } 1931 1932 // XXX 1933 if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) { 1934 ALOGW("Use baseline profile instead of %d for AVC recording", 1935 h264type.eProfile); 1936 h264type.eProfile = OMX_VIDEO_AVCProfileBaseline; 1937 } 1938 1939 if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) { 1940 h264type.nSliceHeaderSpacing = 0; 1941 h264type.bUseHadamard = OMX_TRUE; 1942 h264type.nRefFrames = 1; 1943 h264type.nBFrames = 0; 1944 h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 1945 if (h264type.nPFrames == 0) { 1946 h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 1947 } 1948 h264type.nRefIdx10ActiveMinus1 = 0; 1949 h264type.nRefIdx11ActiveMinus1 = 0; 1950 h264type.bEntropyCodingCABAC = OMX_FALSE; 1951 h264type.bWeightedPPrediction = OMX_FALSE; 1952 h264type.bconstIpred = OMX_FALSE; 1953 h264type.bDirect8x8Inference = OMX_FALSE; 1954 h264type.bDirectSpatialTemporal = OMX_FALSE; 1955 h264type.nCabacInitIdc = 0; 1956 } 1957 1958 if (h264type.nBFrames != 0) { 1959 h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB; 1960 } 1961 1962 h264type.bEnableUEP = OMX_FALSE; 1963 h264type.bEnableFMO = OMX_FALSE; 1964 h264type.bEnableASO = OMX_FALSE; 1965 h264type.bEnableRS = OMX_FALSE; 1966 h264type.bFrameMBsOnly = OMX_TRUE; 1967 h264type.bMBAFF = OMX_FALSE; 1968 h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; 1969 1970 err = mOMX->setParameter( 1971 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 1972 1973 if (err != OK) { 1974 return err; 1975 } 1976 1977 return configureBitrate(bitrate, bitrateMode); 1978} 1979 1980status_t ACodec::verifySupportForProfileAndLevel( 1981 int32_t profile, int32_t level) { 1982 OMX_VIDEO_PARAM_PROFILELEVELTYPE params; 1983 InitOMXParams(¶ms); 1984 params.nPortIndex = kPortIndexOutput; 1985 1986 for (params.nProfileIndex = 0;; ++params.nProfileIndex) { 1987 status_t err = mOMX->getParameter( 1988 mNode, 1989 OMX_IndexParamVideoProfileLevelQuerySupported, 1990 ¶ms, 1991 sizeof(params)); 1992 1993 if (err != OK) { 1994 return err; 1995 } 1996 1997 int32_t supportedProfile = static_cast<int32_t>(params.eProfile); 1998 int32_t supportedLevel = static_cast<int32_t>(params.eLevel); 1999 2000 if (profile == supportedProfile && level <= supportedLevel) { 2001 return OK; 2002 } 2003 } 2004} 2005 2006status_t ACodec::configureBitrate( 2007 int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode) { 2008 OMX_VIDEO_PARAM_BITRATETYPE bitrateType; 2009 InitOMXParams(&bitrateType); 2010 bitrateType.nPortIndex = kPortIndexOutput; 2011 2012 status_t err = mOMX->getParameter( 2013 mNode, OMX_IndexParamVideoBitrate, 2014 &bitrateType, sizeof(bitrateType)); 2015 2016 if (err != OK) { 2017 return err; 2018 } 2019 2020 bitrateType.eControlRate = bitrateMode; 2021 bitrateType.nTargetBitrate = bitrate; 2022 2023 return mOMX->setParameter( 2024 mNode, OMX_IndexParamVideoBitrate, 2025 &bitrateType, sizeof(bitrateType)); 2026} 2027 2028status_t ACodec::setupErrorCorrectionParameters() { 2029 OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType; 2030 InitOMXParams(&errorCorrectionType); 2031 errorCorrectionType.nPortIndex = kPortIndexOutput; 2032 2033 status_t err = mOMX->getParameter( 2034 mNode, OMX_IndexParamVideoErrorCorrection, 2035 &errorCorrectionType, sizeof(errorCorrectionType)); 2036 2037 if (err != OK) { 2038 return OK; // Optional feature. Ignore this failure 2039 } 2040 2041 errorCorrectionType.bEnableHEC = OMX_FALSE; 2042 errorCorrectionType.bEnableResync = OMX_TRUE; 2043 errorCorrectionType.nResynchMarkerSpacing = 256; 2044 errorCorrectionType.bEnableDataPartitioning = OMX_FALSE; 2045 errorCorrectionType.bEnableRVLC = OMX_FALSE; 2046 2047 return mOMX->setParameter( 2048 mNode, OMX_IndexParamVideoErrorCorrection, 2049 &errorCorrectionType, sizeof(errorCorrectionType)); 2050} 2051 2052status_t ACodec::setVideoFormatOnPort( 2053 OMX_U32 portIndex, 2054 int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) { 2055 OMX_PARAM_PORTDEFINITIONTYPE def; 2056 InitOMXParams(&def); 2057 def.nPortIndex = portIndex; 2058 2059 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 2060 2061 status_t err = mOMX->getParameter( 2062 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2063 2064 CHECK_EQ(err, (status_t)OK); 2065 2066 if (portIndex == kPortIndexInput) { 2067 // XXX Need a (much) better heuristic to compute input buffer sizes. 2068 const size_t X = 64 * 1024; 2069 if (def.nBufferSize < X) { 2070 def.nBufferSize = X; 2071 } 2072 } 2073 2074 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo); 2075 2076 video_def->nFrameWidth = width; 2077 video_def->nFrameHeight = height; 2078 2079 if (portIndex == kPortIndexInput) { 2080 video_def->eCompressionFormat = compressionFormat; 2081 video_def->eColorFormat = OMX_COLOR_FormatUnused; 2082 } 2083 2084 err = mOMX->setParameter( 2085 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2086 2087 return err; 2088} 2089 2090status_t ACodec::initNativeWindow() { 2091 if (mNativeWindow != NULL) { 2092 return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE); 2093 } 2094 2095 mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE); 2096 return OK; 2097} 2098 2099size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const { 2100 size_t n = 0; 2101 2102 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 2103 const BufferInfo &info = mBuffers[portIndex].itemAt(i); 2104 2105 if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) { 2106 ++n; 2107 } 2108 } 2109 2110 return n; 2111} 2112 2113bool ACodec::allYourBuffersAreBelongToUs( 2114 OMX_U32 portIndex) { 2115 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 2116 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 2117 2118 if (info->mStatus != BufferInfo::OWNED_BY_US 2119 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) { 2120 ALOGV("[%s] Buffer %p on port %ld still has status %d", 2121 mComponentName.c_str(), 2122 info->mBufferID, portIndex, info->mStatus); 2123 return false; 2124 } 2125 } 2126 2127 return true; 2128} 2129 2130bool ACodec::allYourBuffersAreBelongToUs() { 2131 return allYourBuffersAreBelongToUs(kPortIndexInput) 2132 && allYourBuffersAreBelongToUs(kPortIndexOutput); 2133} 2134 2135void ACodec::deferMessage(const sp<AMessage> &msg) { 2136 bool wasEmptyBefore = mDeferredQueue.empty(); 2137 mDeferredQueue.push_back(msg); 2138} 2139 2140void ACodec::processDeferredMessages() { 2141 List<sp<AMessage> > queue = mDeferredQueue; 2142 mDeferredQueue.clear(); 2143 2144 List<sp<AMessage> >::iterator it = queue.begin(); 2145 while (it != queue.end()) { 2146 onMessageReceived(*it++); 2147 } 2148} 2149 2150void ACodec::sendFormatChange() { 2151 sp<AMessage> notify = mNotify->dup(); 2152 notify->setInt32("what", kWhatOutputFormatChanged); 2153 2154 OMX_PARAM_PORTDEFINITIONTYPE def; 2155 InitOMXParams(&def); 2156 def.nPortIndex = kPortIndexOutput; 2157 2158 CHECK_EQ(mOMX->getParameter( 2159 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)), 2160 (status_t)OK); 2161 2162 CHECK_EQ((int)def.eDir, (int)OMX_DirOutput); 2163 2164 switch (def.eDomain) { 2165 case OMX_PortDomainVideo: 2166 { 2167 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video; 2168 2169 notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW); 2170 notify->setInt32("width", videoDef->nFrameWidth); 2171 notify->setInt32("height", videoDef->nFrameHeight); 2172 notify->setInt32("stride", videoDef->nStride); 2173 notify->setInt32("slice-height", videoDef->nSliceHeight); 2174 notify->setInt32("color-format", videoDef->eColorFormat); 2175 2176 OMX_CONFIG_RECTTYPE rect; 2177 InitOMXParams(&rect); 2178 rect.nPortIndex = kPortIndexOutput; 2179 2180 if (mOMX->getConfig( 2181 mNode, OMX_IndexConfigCommonOutputCrop, 2182 &rect, sizeof(rect)) != OK) { 2183 rect.nLeft = 0; 2184 rect.nTop = 0; 2185 rect.nWidth = videoDef->nFrameWidth; 2186 rect.nHeight = videoDef->nFrameHeight; 2187 } 2188 2189 CHECK_GE(rect.nLeft, 0); 2190 CHECK_GE(rect.nTop, 0); 2191 CHECK_GE(rect.nWidth, 0u); 2192 CHECK_GE(rect.nHeight, 0u); 2193 CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth); 2194 CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight); 2195 2196 notify->setRect( 2197 "crop", 2198 rect.nLeft, 2199 rect.nTop, 2200 rect.nLeft + rect.nWidth - 1, 2201 rect.nTop + rect.nHeight - 1); 2202 2203 if (mNativeWindow != NULL) { 2204 android_native_rect_t crop; 2205 crop.left = rect.nLeft; 2206 crop.top = rect.nTop; 2207 crop.right = rect.nLeft + rect.nWidth; 2208 crop.bottom = rect.nTop + rect.nHeight; 2209 2210 CHECK_EQ(0, native_window_set_crop( 2211 mNativeWindow.get(), &crop)); 2212 } 2213 break; 2214 } 2215 2216 case OMX_PortDomainAudio: 2217 { 2218 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio; 2219 CHECK_EQ((int)audioDef->eEncoding, (int)OMX_AUDIO_CodingPCM); 2220 2221 OMX_AUDIO_PARAM_PCMMODETYPE params; 2222 InitOMXParams(¶ms); 2223 params.nPortIndex = kPortIndexOutput; 2224 2225 CHECK_EQ(mOMX->getParameter( 2226 mNode, OMX_IndexParamAudioPcm, 2227 ¶ms, sizeof(params)), 2228 (status_t)OK); 2229 2230 CHECK(params.nChannels == 1 || params.bInterleaved); 2231 CHECK_EQ(params.nBitPerSample, 16u); 2232 CHECK_EQ((int)params.eNumData, (int)OMX_NumericalDataSigned); 2233 CHECK_EQ((int)params.ePCMMode, (int)OMX_AUDIO_PCMModeLinear); 2234 2235 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW); 2236 notify->setInt32("channel-count", params.nChannels); 2237 notify->setInt32("sample-rate", params.nSamplingRate); 2238 if (mEncoderDelay + mEncoderPadding) { 2239 size_t frameSize = params.nChannels * sizeof(int16_t); 2240 if (mSkipCutBuffer != NULL) { 2241 size_t prevbufsize = mSkipCutBuffer->size(); 2242 if (prevbufsize != 0) { 2243 ALOGW("Replacing SkipCutBuffer holding %d bytes", prevbufsize); 2244 } 2245 } 2246 mSkipCutBuffer = new SkipCutBuffer(mEncoderDelay * frameSize, 2247 mEncoderPadding * frameSize); 2248 } 2249 2250 if (mChannelMaskPresent) { 2251 notify->setInt32("channel-mask", mChannelMask); 2252 } 2253 2254 break; 2255 } 2256 2257 default: 2258 TRESPASS(); 2259 } 2260 2261 notify->post(); 2262 2263 mSentFormat = true; 2264} 2265 2266void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) { 2267 sp<AMessage> notify = mNotify->dup(); 2268 notify->setInt32("what", ACodec::kWhatError); 2269 notify->setInt32("omx-error", error); 2270 notify->setInt32("err", internalError); 2271 notify->post(); 2272} 2273 2274status_t ACodec::pushBlankBuffersToNativeWindow() { 2275 status_t err = NO_ERROR; 2276 ANativeWindowBuffer* anb = NULL; 2277 int numBufs = 0; 2278 int minUndequeuedBufs = 0; 2279 2280 // We need to reconnect to the ANativeWindow as a CPU client to ensure that 2281 // no frames get dropped by SurfaceFlinger assuming that these are video 2282 // frames. 2283 err = native_window_api_disconnect(mNativeWindow.get(), 2284 NATIVE_WINDOW_API_MEDIA); 2285 if (err != NO_ERROR) { 2286 ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)", 2287 strerror(-err), -err); 2288 return err; 2289 } 2290 2291 err = native_window_api_connect(mNativeWindow.get(), 2292 NATIVE_WINDOW_API_CPU); 2293 if (err != NO_ERROR) { 2294 ALOGE("error pushing blank frames: api_connect failed: %s (%d)", 2295 strerror(-err), -err); 2296 return err; 2297 } 2298 2299 err = native_window_set_buffers_geometry(mNativeWindow.get(), 1, 1, 2300 HAL_PIXEL_FORMAT_RGBX_8888); 2301 if (err != NO_ERROR) { 2302 ALOGE("error pushing blank frames: set_buffers_geometry failed: %s (%d)", 2303 strerror(-err), -err); 2304 goto error; 2305 } 2306 2307 err = native_window_set_usage(mNativeWindow.get(), 2308 GRALLOC_USAGE_SW_WRITE_OFTEN); 2309 if (err != NO_ERROR) { 2310 ALOGE("error pushing blank frames: set_usage failed: %s (%d)", 2311 strerror(-err), -err); 2312 goto error; 2313 } 2314 2315 err = mNativeWindow->query(mNativeWindow.get(), 2316 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs); 2317 if (err != NO_ERROR) { 2318 ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query " 2319 "failed: %s (%d)", strerror(-err), -err); 2320 goto error; 2321 } 2322 2323 numBufs = minUndequeuedBufs + 1; 2324 err = native_window_set_buffer_count(mNativeWindow.get(), numBufs); 2325 if (err != NO_ERROR) { 2326 ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)", 2327 strerror(-err), -err); 2328 goto error; 2329 } 2330 2331 // We push numBufs + 1 buffers to ensure that we've drawn into the same 2332 // buffer twice. This should guarantee that the buffer has been displayed 2333 // on the screen and then been replaced, so an previous video frames are 2334 // guaranteed NOT to be currently displayed. 2335 for (int i = 0; i < numBufs + 1; i++) { 2336 int fenceFd = -1; 2337 err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &anb); 2338 if (err != NO_ERROR) { 2339 ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)", 2340 strerror(-err), -err); 2341 goto error; 2342 } 2343 2344 sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); 2345 2346 // Fill the buffer with the a 1x1 checkerboard pattern ;) 2347 uint32_t* img = NULL; 2348 err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); 2349 if (err != NO_ERROR) { 2350 ALOGE("error pushing blank frames: lock failed: %s (%d)", 2351 strerror(-err), -err); 2352 goto error; 2353 } 2354 2355 *img = 0; 2356 2357 err = buf->unlock(); 2358 if (err != NO_ERROR) { 2359 ALOGE("error pushing blank frames: unlock failed: %s (%d)", 2360 strerror(-err), -err); 2361 goto error; 2362 } 2363 2364 err = mNativeWindow->queueBuffer(mNativeWindow.get(), 2365 buf->getNativeBuffer(), -1); 2366 if (err != NO_ERROR) { 2367 ALOGE("error pushing blank frames: queueBuffer failed: %s (%d)", 2368 strerror(-err), -err); 2369 goto error; 2370 } 2371 2372 anb = NULL; 2373 } 2374 2375error: 2376 2377 if (err != NO_ERROR) { 2378 // Clean up after an error. 2379 if (anb != NULL) { 2380 mNativeWindow->cancelBuffer(mNativeWindow.get(), anb, -1); 2381 } 2382 2383 native_window_api_disconnect(mNativeWindow.get(), 2384 NATIVE_WINDOW_API_CPU); 2385 native_window_api_connect(mNativeWindow.get(), 2386 NATIVE_WINDOW_API_MEDIA); 2387 2388 return err; 2389 } else { 2390 // Clean up after success. 2391 err = native_window_api_disconnect(mNativeWindow.get(), 2392 NATIVE_WINDOW_API_CPU); 2393 if (err != NO_ERROR) { 2394 ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)", 2395 strerror(-err), -err); 2396 return err; 2397 } 2398 2399 err = native_window_api_connect(mNativeWindow.get(), 2400 NATIVE_WINDOW_API_MEDIA); 2401 if (err != NO_ERROR) { 2402 ALOGE("error pushing blank frames: api_connect failed: %s (%d)", 2403 strerror(-err), -err); 2404 return err; 2405 } 2406 2407 return NO_ERROR; 2408 } 2409} 2410 2411//////////////////////////////////////////////////////////////////////////////// 2412 2413ACodec::PortDescription::PortDescription() { 2414} 2415 2416status_t ACodec::requestIDRFrame() { 2417 if (!mIsEncoder) { 2418 return ERROR_UNSUPPORTED; 2419 } 2420 2421 OMX_CONFIG_INTRAREFRESHVOPTYPE params; 2422 InitOMXParams(¶ms); 2423 2424 params.nPortIndex = kPortIndexOutput; 2425 params.IntraRefreshVOP = OMX_TRUE; 2426 2427 return mOMX->setConfig( 2428 mNode, 2429 OMX_IndexConfigVideoIntraVOPRefresh, 2430 ¶ms, 2431 sizeof(params)); 2432} 2433 2434void ACodec::PortDescription::addBuffer( 2435 IOMX::buffer_id id, const sp<ABuffer> &buffer) { 2436 mBufferIDs.push_back(id); 2437 mBuffers.push_back(buffer); 2438} 2439 2440size_t ACodec::PortDescription::countBuffers() { 2441 return mBufferIDs.size(); 2442} 2443 2444IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const { 2445 return mBufferIDs.itemAt(index); 2446} 2447 2448sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const { 2449 return mBuffers.itemAt(index); 2450} 2451 2452//////////////////////////////////////////////////////////////////////////////// 2453 2454ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState) 2455 : AState(parentState), 2456 mCodec(codec) { 2457} 2458 2459ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(OMX_U32 portIndex) { 2460 return KEEP_BUFFERS; 2461} 2462 2463bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) { 2464 switch (msg->what()) { 2465 case kWhatInputBufferFilled: 2466 { 2467 onInputBufferFilled(msg); 2468 break; 2469 } 2470 2471 case kWhatOutputBufferDrained: 2472 { 2473 onOutputBufferDrained(msg); 2474 break; 2475 } 2476 2477 case ACodec::kWhatOMXMessage: 2478 { 2479 return onOMXMessage(msg); 2480 } 2481 2482 case ACodec::kWhatCreateInputSurface: 2483 case ACodec::kWhatSignalEndOfInputStream: 2484 { 2485 ALOGE("Message 0x%x was not handled", msg->what()); 2486 mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION); 2487 return true; 2488 } 2489 2490 default: 2491 return false; 2492 } 2493 2494 return true; 2495} 2496 2497bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) { 2498 int32_t type; 2499 CHECK(msg->findInt32("type", &type)); 2500 2501 IOMX::node_id nodeID; 2502 CHECK(msg->findPointer("node", &nodeID)); 2503 CHECK_EQ(nodeID, mCodec->mNode); 2504 2505 switch (type) { 2506 case omx_message::EVENT: 2507 { 2508 int32_t event, data1, data2; 2509 CHECK(msg->findInt32("event", &event)); 2510 CHECK(msg->findInt32("data1", &data1)); 2511 CHECK(msg->findInt32("data2", &data2)); 2512 2513 if (event == OMX_EventCmdComplete 2514 && data1 == OMX_CommandFlush 2515 && data2 == (int32_t)OMX_ALL) { 2516 // Use of this notification is not consistent across 2517 // implementations. We'll drop this notification and rely 2518 // on flush-complete notifications on the individual port 2519 // indices instead. 2520 2521 return true; 2522 } 2523 2524 return onOMXEvent( 2525 static_cast<OMX_EVENTTYPE>(event), 2526 static_cast<OMX_U32>(data1), 2527 static_cast<OMX_U32>(data2)); 2528 } 2529 2530 case omx_message::EMPTY_BUFFER_DONE: 2531 { 2532 IOMX::buffer_id bufferID; 2533 CHECK(msg->findPointer("buffer", &bufferID)); 2534 2535 return onOMXEmptyBufferDone(bufferID); 2536 } 2537 2538 case omx_message::FILL_BUFFER_DONE: 2539 { 2540 IOMX::buffer_id bufferID; 2541 CHECK(msg->findPointer("buffer", &bufferID)); 2542 2543 int32_t rangeOffset, rangeLength, flags; 2544 int64_t timeUs; 2545 void *platformPrivate; 2546 void *dataPtr; 2547 2548 CHECK(msg->findInt32("range_offset", &rangeOffset)); 2549 CHECK(msg->findInt32("range_length", &rangeLength)); 2550 CHECK(msg->findInt32("flags", &flags)); 2551 CHECK(msg->findInt64("timestamp", &timeUs)); 2552 CHECK(msg->findPointer("platform_private", &platformPrivate)); 2553 CHECK(msg->findPointer("data_ptr", &dataPtr)); 2554 2555 return onOMXFillBufferDone( 2556 bufferID, 2557 (size_t)rangeOffset, (size_t)rangeLength, 2558 (OMX_U32)flags, 2559 timeUs, 2560 platformPrivate, 2561 dataPtr); 2562 } 2563 2564 default: 2565 TRESPASS(); 2566 break; 2567 } 2568} 2569 2570bool ACodec::BaseState::onOMXEvent( 2571 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 2572 if (event != OMX_EventError) { 2573 ALOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)", 2574 mCodec->mComponentName.c_str(), event, data1, data2); 2575 2576 return false; 2577 } 2578 2579 ALOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1); 2580 2581 mCodec->signalError((OMX_ERRORTYPE)data1); 2582 2583 return true; 2584} 2585 2586bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) { 2587 ALOGV("[%s] onOMXEmptyBufferDone %p", 2588 mCodec->mComponentName.c_str(), bufferID); 2589 2590 BufferInfo *info = 2591 mCodec->findBufferByID(kPortIndexInput, bufferID); 2592 2593 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); 2594 info->mStatus = BufferInfo::OWNED_BY_US; 2595 2596 const sp<AMessage> &bufferMeta = info->mData->meta(); 2597 void *mediaBuffer; 2598 if (bufferMeta->findPointer("mediaBuffer", &mediaBuffer) 2599 && mediaBuffer != NULL) { 2600 // We're in "store-metadata-in-buffers" mode, the underlying 2601 // OMX component had access to data that's implicitly refcounted 2602 // by this "mediaBuffer" object. Now that the OMX component has 2603 // told us that it's done with the input buffer, we can decrement 2604 // the mediaBuffer's reference count. 2605 2606 ALOGV("releasing mbuf %p", mediaBuffer); 2607 2608 ((MediaBuffer *)mediaBuffer)->release(); 2609 mediaBuffer = NULL; 2610 2611 bufferMeta->setPointer("mediaBuffer", NULL); 2612 } 2613 2614 PortMode mode = getPortMode(kPortIndexInput); 2615 2616 switch (mode) { 2617 case KEEP_BUFFERS: 2618 break; 2619 2620 case RESUBMIT_BUFFERS: 2621 postFillThisBuffer(info); 2622 break; 2623 2624 default: 2625 { 2626 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 2627 TRESPASS(); // Not currently used 2628 break; 2629 } 2630 } 2631 2632 return true; 2633} 2634 2635void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) { 2636 if (mCodec->mPortEOS[kPortIndexInput]) { 2637 return; 2638 } 2639 2640 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 2641 2642 sp<AMessage> notify = mCodec->mNotify->dup(); 2643 notify->setInt32("what", ACodec::kWhatFillThisBuffer); 2644 notify->setPointer("buffer-id", info->mBufferID); 2645 2646 info->mData->meta()->clear(); 2647 notify->setBuffer("buffer", info->mData); 2648 2649 sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id()); 2650 reply->setPointer("buffer-id", info->mBufferID); 2651 2652 notify->setMessage("reply", reply); 2653 2654 notify->post(); 2655 2656 info->mStatus = BufferInfo::OWNED_BY_UPSTREAM; 2657} 2658 2659void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { 2660 IOMX::buffer_id bufferID; 2661 CHECK(msg->findPointer("buffer-id", &bufferID)); 2662 2663 sp<ABuffer> buffer; 2664 int32_t err = OK; 2665 bool eos = false; 2666 2667 if (!msg->findBuffer("buffer", &buffer)) { 2668 CHECK(msg->findInt32("err", &err)); 2669 2670 ALOGV("[%s] saw error %d instead of an input buffer", 2671 mCodec->mComponentName.c_str(), err); 2672 2673 buffer.clear(); 2674 2675 eos = true; 2676 } 2677 2678 int32_t tmp; 2679 if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) { 2680 eos = true; 2681 err = ERROR_END_OF_STREAM; 2682 } 2683 2684 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID); 2685 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM); 2686 2687 info->mStatus = BufferInfo::OWNED_BY_US; 2688 2689 PortMode mode = getPortMode(kPortIndexInput); 2690 2691 switch (mode) { 2692 case KEEP_BUFFERS: 2693 { 2694 if (eos) { 2695 if (!mCodec->mPortEOS[kPortIndexInput]) { 2696 mCodec->mPortEOS[kPortIndexInput] = true; 2697 mCodec->mInputEOSResult = err; 2698 } 2699 } 2700 break; 2701 } 2702 2703 case RESUBMIT_BUFFERS: 2704 { 2705 if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) { 2706 int64_t timeUs; 2707 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 2708 2709 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME; 2710 2711 int32_t isCSD; 2712 if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) { 2713 flags |= OMX_BUFFERFLAG_CODECCONFIG; 2714 } 2715 2716 if (eos) { 2717 flags |= OMX_BUFFERFLAG_EOS; 2718 } 2719 2720 if (buffer != info->mData) { 2721 ALOGV("[%s] Needs to copy input data for buffer %p. (%p != %p)", 2722 mCodec->mComponentName.c_str(), 2723 bufferID, 2724 buffer.get(), info->mData.get()); 2725 2726 CHECK_LE(buffer->size(), info->mData->capacity()); 2727 memcpy(info->mData->data(), buffer->data(), buffer->size()); 2728 } 2729 2730 if (flags & OMX_BUFFERFLAG_CODECCONFIG) { 2731 ALOGV("[%s] calling emptyBuffer %p w/ codec specific data", 2732 mCodec->mComponentName.c_str(), bufferID); 2733 } else if (flags & OMX_BUFFERFLAG_EOS) { 2734 ALOGV("[%s] calling emptyBuffer %p w/ EOS", 2735 mCodec->mComponentName.c_str(), bufferID); 2736 } else { 2737#if TRACK_BUFFER_TIMING 2738 ALOGI("[%s] calling emptyBuffer %p w/ time %lld us", 2739 mCodec->mComponentName.c_str(), bufferID, timeUs); 2740#else 2741 ALOGV("[%s] calling emptyBuffer %p w/ time %lld us", 2742 mCodec->mComponentName.c_str(), bufferID, timeUs); 2743#endif 2744 } 2745 2746#if TRACK_BUFFER_TIMING 2747 ACodec::BufferStats stats; 2748 stats.mEmptyBufferTimeUs = ALooper::GetNowUs(); 2749 stats.mFillBufferDoneTimeUs = -1ll; 2750 mCodec->mBufferStats.add(timeUs, stats); 2751#endif 2752 2753 CHECK_EQ(mCodec->mOMX->emptyBuffer( 2754 mCodec->mNode, 2755 bufferID, 2756 0, 2757 buffer->size(), 2758 flags, 2759 timeUs), 2760 (status_t)OK); 2761 2762 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 2763 2764 if (!eos) { 2765 getMoreInputDataIfPossible(); 2766 } else { 2767 ALOGV("[%s] Signalled EOS on the input port", 2768 mCodec->mComponentName.c_str()); 2769 2770 mCodec->mPortEOS[kPortIndexInput] = true; 2771 mCodec->mInputEOSResult = err; 2772 } 2773 } else if (!mCodec->mPortEOS[kPortIndexInput]) { 2774 if (err != ERROR_END_OF_STREAM) { 2775 ALOGV("[%s] Signalling EOS on the input port " 2776 "due to error %d", 2777 mCodec->mComponentName.c_str(), err); 2778 } else { 2779 ALOGV("[%s] Signalling EOS on the input port", 2780 mCodec->mComponentName.c_str()); 2781 } 2782 2783 ALOGV("[%s] calling emptyBuffer %p signalling EOS", 2784 mCodec->mComponentName.c_str(), bufferID); 2785 2786 CHECK_EQ(mCodec->mOMX->emptyBuffer( 2787 mCodec->mNode, 2788 bufferID, 2789 0, 2790 0, 2791 OMX_BUFFERFLAG_EOS, 2792 0), 2793 (status_t)OK); 2794 2795 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 2796 2797 mCodec->mPortEOS[kPortIndexInput] = true; 2798 mCodec->mInputEOSResult = err; 2799 } 2800 break; 2801 2802 default: 2803 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 2804 break; 2805 } 2806 } 2807} 2808 2809void ACodec::BaseState::getMoreInputDataIfPossible() { 2810 if (mCodec->mPortEOS[kPortIndexInput]) { 2811 return; 2812 } 2813 2814 BufferInfo *eligible = NULL; 2815 2816 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 2817 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 2818 2819#if 0 2820 if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) { 2821 // There's already a "read" pending. 2822 return; 2823 } 2824#endif 2825 2826 if (info->mStatus == BufferInfo::OWNED_BY_US) { 2827 eligible = info; 2828 } 2829 } 2830 2831 if (eligible == NULL) { 2832 return; 2833 } 2834 2835 postFillThisBuffer(eligible); 2836} 2837 2838bool ACodec::BaseState::onOMXFillBufferDone( 2839 IOMX::buffer_id bufferID, 2840 size_t rangeOffset, size_t rangeLength, 2841 OMX_U32 flags, 2842 int64_t timeUs, 2843 void *platformPrivate, 2844 void *dataPtr) { 2845 ALOGV("[%s] onOMXFillBufferDone %p time %lld us, flags = 0x%08lx", 2846 mCodec->mComponentName.c_str(), bufferID, timeUs, flags); 2847 2848 ssize_t index; 2849 2850#if TRACK_BUFFER_TIMING 2851 index = mCodec->mBufferStats.indexOfKey(timeUs); 2852 if (index >= 0) { 2853 ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index); 2854 stats->mFillBufferDoneTimeUs = ALooper::GetNowUs(); 2855 2856 ALOGI("frame PTS %lld: %lld", 2857 timeUs, 2858 stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs); 2859 2860 mCodec->mBufferStats.removeItemsAt(index); 2861 stats = NULL; 2862 } 2863#endif 2864 2865 BufferInfo *info = 2866 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 2867 2868 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); 2869 2870 info->mStatus = BufferInfo::OWNED_BY_US; 2871 2872 PortMode mode = getPortMode(kPortIndexOutput); 2873 2874 switch (mode) { 2875 case KEEP_BUFFERS: 2876 break; 2877 2878 case RESUBMIT_BUFFERS: 2879 { 2880 if (rangeLength == 0 && !(flags & OMX_BUFFERFLAG_EOS)) { 2881 ALOGV("[%s] calling fillBuffer %p", 2882 mCodec->mComponentName.c_str(), info->mBufferID); 2883 2884 CHECK_EQ(mCodec->mOMX->fillBuffer( 2885 mCodec->mNode, info->mBufferID), 2886 (status_t)OK); 2887 2888 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 2889 break; 2890 } 2891 2892 if (!mCodec->mIsEncoder && !mCodec->mSentFormat) { 2893 mCodec->sendFormatChange(); 2894 } 2895 2896 info->mData->setRange(rangeOffset, rangeLength); 2897#if 0 2898 if (mCodec->mNativeWindow == NULL) { 2899 if (IsIDR(info->mData)) { 2900 ALOGI("IDR frame"); 2901 } 2902 } 2903#endif 2904 2905 if (mCodec->mSkipCutBuffer != NULL) { 2906 mCodec->mSkipCutBuffer->submit(info->mData); 2907 } 2908 info->mData->meta()->setInt64("timeUs", timeUs); 2909 2910 sp<AMessage> notify = mCodec->mNotify->dup(); 2911 notify->setInt32("what", ACodec::kWhatDrainThisBuffer); 2912 notify->setPointer("buffer-id", info->mBufferID); 2913 notify->setBuffer("buffer", info->mData); 2914 notify->setInt32("flags", flags); 2915 2916 sp<AMessage> reply = 2917 new AMessage(kWhatOutputBufferDrained, mCodec->id()); 2918 2919 reply->setPointer("buffer-id", info->mBufferID); 2920 2921 notify->setMessage("reply", reply); 2922 2923 notify->post(); 2924 2925 info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM; 2926 2927 if (flags & OMX_BUFFERFLAG_EOS) { 2928 ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str()); 2929 2930 sp<AMessage> notify = mCodec->mNotify->dup(); 2931 notify->setInt32("what", ACodec::kWhatEOS); 2932 notify->setInt32("err", mCodec->mInputEOSResult); 2933 notify->post(); 2934 2935 mCodec->mPortEOS[kPortIndexOutput] = true; 2936 } 2937 break; 2938 } 2939 2940 default: 2941 { 2942 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 2943 2944 CHECK_EQ((status_t)OK, 2945 mCodec->freeBuffer(kPortIndexOutput, index)); 2946 break; 2947 } 2948 } 2949 2950 return true; 2951} 2952 2953void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { 2954 IOMX::buffer_id bufferID; 2955 CHECK(msg->findPointer("buffer-id", &bufferID)); 2956 2957 ssize_t index; 2958 BufferInfo *info = 2959 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 2960 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM); 2961 2962 int32_t render; 2963 if (mCodec->mNativeWindow != NULL 2964 && msg->findInt32("render", &render) && render != 0) { 2965 // The client wants this buffer to be rendered. 2966 2967 status_t err; 2968 if ((err = mCodec->mNativeWindow->queueBuffer( 2969 mCodec->mNativeWindow.get(), 2970 info->mGraphicBuffer.get(), -1)) == OK) { 2971 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 2972 } else { 2973 mCodec->signalError(OMX_ErrorUndefined, err); 2974 info->mStatus = BufferInfo::OWNED_BY_US; 2975 } 2976 } else { 2977 info->mStatus = BufferInfo::OWNED_BY_US; 2978 } 2979 2980 PortMode mode = getPortMode(kPortIndexOutput); 2981 2982 switch (mode) { 2983 case KEEP_BUFFERS: 2984 { 2985 // XXX fishy, revisit!!! What about the FREE_BUFFERS case below? 2986 2987 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 2988 // We cannot resubmit the buffer we just rendered, dequeue 2989 // the spare instead. 2990 2991 info = mCodec->dequeueBufferFromNativeWindow(); 2992 } 2993 break; 2994 } 2995 2996 case RESUBMIT_BUFFERS: 2997 { 2998 if (!mCodec->mPortEOS[kPortIndexOutput]) { 2999 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 3000 // We cannot resubmit the buffer we just rendered, dequeue 3001 // the spare instead. 3002 3003 info = mCodec->dequeueBufferFromNativeWindow(); 3004 } 3005 3006 if (info != NULL) { 3007 ALOGV("[%s] calling fillBuffer %p", 3008 mCodec->mComponentName.c_str(), info->mBufferID); 3009 3010 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), 3011 (status_t)OK); 3012 3013 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 3014 } 3015 } 3016 break; 3017 } 3018 3019 default: 3020 { 3021 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 3022 3023 CHECK_EQ((status_t)OK, 3024 mCodec->freeBuffer(kPortIndexOutput, index)); 3025 break; 3026 } 3027 } 3028} 3029 3030//////////////////////////////////////////////////////////////////////////////// 3031 3032ACodec::UninitializedState::UninitializedState(ACodec *codec) 3033 : BaseState(codec) { 3034} 3035 3036void ACodec::UninitializedState::stateEntered() { 3037 ALOGV("Now uninitialized"); 3038} 3039 3040bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) { 3041 bool handled = false; 3042 3043 switch (msg->what()) { 3044 case ACodec::kWhatSetup: 3045 { 3046 onSetup(msg); 3047 3048 handled = true; 3049 break; 3050 } 3051 3052 case ACodec::kWhatAllocateComponent: 3053 { 3054 onAllocateComponent(msg); 3055 handled = true; 3056 break; 3057 } 3058 3059 case ACodec::kWhatShutdown: 3060 { 3061 int32_t keepComponentAllocated; 3062 CHECK(msg->findInt32( 3063 "keepComponentAllocated", &keepComponentAllocated)); 3064 CHECK(!keepComponentAllocated); 3065 3066 sp<AMessage> notify = mCodec->mNotify->dup(); 3067 notify->setInt32("what", ACodec::kWhatShutdownCompleted); 3068 notify->post(); 3069 3070 handled = true; 3071 break; 3072 } 3073 3074 case ACodec::kWhatFlush: 3075 { 3076 sp<AMessage> notify = mCodec->mNotify->dup(); 3077 notify->setInt32("what", ACodec::kWhatFlushCompleted); 3078 notify->post(); 3079 3080 handled = true; 3081 break; 3082 } 3083 3084 default: 3085 return BaseState::onMessageReceived(msg); 3086 } 3087 3088 return handled; 3089} 3090 3091void ACodec::UninitializedState::onSetup( 3092 const sp<AMessage> &msg) { 3093 if (onAllocateComponent(msg) 3094 && mCodec->mLoadedState->onConfigureComponent(msg)) { 3095 mCodec->mLoadedState->onStart(); 3096 } 3097} 3098 3099bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) { 3100 ALOGV("onAllocateComponent"); 3101 3102 CHECK(mCodec->mNode == NULL); 3103 3104 OMXClient client; 3105 CHECK_EQ(client.connect(), (status_t)OK); 3106 3107 sp<IOMX> omx = client.interface(); 3108 3109 Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs; 3110 3111 AString mime; 3112 3113 AString componentName; 3114 uint32_t quirks = 0; 3115 if (msg->findString("componentName", &componentName)) { 3116 ssize_t index = matchingCodecs.add(); 3117 OMXCodec::CodecNameAndQuirks *entry = &matchingCodecs.editItemAt(index); 3118 entry->mName = String8(componentName.c_str()); 3119 3120 if (!OMXCodec::findCodecQuirks( 3121 componentName.c_str(), &entry->mQuirks)) { 3122 entry->mQuirks = 0; 3123 } 3124 } else { 3125 CHECK(msg->findString("mime", &mime)); 3126 3127 int32_t encoder; 3128 if (!msg->findInt32("encoder", &encoder)) { 3129 encoder = false; 3130 } 3131 3132 OMXCodec::findMatchingCodecs( 3133 mime.c_str(), 3134 encoder, // createEncoder 3135 NULL, // matchComponentName 3136 0, // flags 3137 &matchingCodecs); 3138 } 3139 3140 sp<CodecObserver> observer = new CodecObserver; 3141 IOMX::node_id node = NULL; 3142 3143 for (size_t matchIndex = 0; matchIndex < matchingCodecs.size(); 3144 ++matchIndex) { 3145 componentName = matchingCodecs.itemAt(matchIndex).mName.string(); 3146 quirks = matchingCodecs.itemAt(matchIndex).mQuirks; 3147 3148 pid_t tid = androidGetTid(); 3149 int prevPriority = androidGetThreadPriority(tid); 3150 androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND); 3151 status_t err = omx->allocateNode(componentName.c_str(), observer, &node); 3152 androidSetThreadPriority(tid, prevPriority); 3153 3154 if (err == OK) { 3155 break; 3156 } 3157 3158 node = NULL; 3159 } 3160 3161 if (node == NULL) { 3162 if (!mime.empty()) { 3163 ALOGE("Unable to instantiate a decoder for type '%s'.", 3164 mime.c_str()); 3165 } else { 3166 ALOGE("Unable to instantiate decoder '%s'.", componentName.c_str()); 3167 } 3168 3169 mCodec->signalError(OMX_ErrorComponentNotFound); 3170 return false; 3171 } 3172 3173 sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id()); 3174 observer->setNotificationMessage(notify); 3175 3176 mCodec->mComponentName = componentName; 3177 mCodec->mFlags = 0; 3178 3179 if (componentName.endsWith(".secure")) { 3180 mCodec->mFlags |= kFlagIsSecure; 3181 } 3182 3183 mCodec->mQuirks = quirks; 3184 mCodec->mOMX = omx; 3185 mCodec->mNode = node; 3186 3187 { 3188 sp<AMessage> notify = mCodec->mNotify->dup(); 3189 notify->setInt32("what", ACodec::kWhatComponentAllocated); 3190 notify->setString("componentName", mCodec->mComponentName.c_str()); 3191 notify->post(); 3192 } 3193 3194 mCodec->changeState(mCodec->mLoadedState); 3195 3196 return true; 3197} 3198 3199//////////////////////////////////////////////////////////////////////////////// 3200 3201ACodec::LoadedState::LoadedState(ACodec *codec) 3202 : BaseState(codec) { 3203} 3204 3205void ACodec::LoadedState::stateEntered() { 3206 ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str()); 3207 3208 mCodec->mPortEOS[kPortIndexInput] = 3209 mCodec->mPortEOS[kPortIndexOutput] = false; 3210 3211 mCodec->mInputEOSResult = OK; 3212 3213 if (mCodec->mShutdownInProgress) { 3214 bool keepComponentAllocated = mCodec->mKeepComponentAllocated; 3215 3216 mCodec->mShutdownInProgress = false; 3217 mCodec->mKeepComponentAllocated = false; 3218 3219 onShutdown(keepComponentAllocated); 3220 } 3221} 3222 3223void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) { 3224 if (!keepComponentAllocated) { 3225 CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK); 3226 3227 mCodec->mNativeWindow.clear(); 3228 mCodec->mNode = NULL; 3229 mCodec->mOMX.clear(); 3230 mCodec->mQuirks = 0; 3231 mCodec->mFlags = 0; 3232 mCodec->mComponentName.clear(); 3233 3234 mCodec->changeState(mCodec->mUninitializedState); 3235 } 3236 3237 sp<AMessage> notify = mCodec->mNotify->dup(); 3238 notify->setInt32("what", ACodec::kWhatShutdownCompleted); 3239 notify->post(); 3240} 3241 3242bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) { 3243 bool handled = false; 3244 3245 switch (msg->what()) { 3246 case ACodec::kWhatConfigureComponent: 3247 { 3248 onConfigureComponent(msg); 3249 handled = true; 3250 break; 3251 } 3252 3253 case ACodec::kWhatCreateInputSurface: 3254 { 3255 onCreateInputSurface(msg); 3256 handled = true; 3257 break; 3258 } 3259 3260 case ACodec::kWhatStart: 3261 { 3262 onStart(); 3263 handled = true; 3264 break; 3265 } 3266 3267 case ACodec::kWhatShutdown: 3268 { 3269 int32_t keepComponentAllocated; 3270 CHECK(msg->findInt32( 3271 "keepComponentAllocated", &keepComponentAllocated)); 3272 3273 onShutdown(keepComponentAllocated); 3274 3275 handled = true; 3276 break; 3277 } 3278 3279 case ACodec::kWhatFlush: 3280 { 3281 sp<AMessage> notify = mCodec->mNotify->dup(); 3282 notify->setInt32("what", ACodec::kWhatFlushCompleted); 3283 notify->post(); 3284 3285 handled = true; 3286 break; 3287 } 3288 3289 default: 3290 return BaseState::onMessageReceived(msg); 3291 } 3292 3293 return handled; 3294} 3295 3296bool ACodec::LoadedState::onConfigureComponent( 3297 const sp<AMessage> &msg) { 3298 ALOGV("onConfigureComponent"); 3299 3300 CHECK(mCodec->mNode != NULL); 3301 3302 AString mime; 3303 CHECK(msg->findString("mime", &mime)); 3304 3305 status_t err = mCodec->configureCodec(mime.c_str(), msg); 3306 3307 if (err != OK) { 3308 ALOGE("[%s] configureCodec returning error %d", 3309 mCodec->mComponentName.c_str(), err); 3310 3311 mCodec->signalError(OMX_ErrorUndefined, err); 3312 return false; 3313 } 3314 3315 sp<RefBase> obj; 3316 if (msg->findObject("native-window", &obj) 3317 && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) { 3318 sp<NativeWindowWrapper> nativeWindow( 3319 static_cast<NativeWindowWrapper *>(obj.get())); 3320 CHECK(nativeWindow != NULL); 3321 mCodec->mNativeWindow = nativeWindow->getNativeWindow(); 3322 3323 native_window_set_scaling_mode( 3324 mCodec->mNativeWindow.get(), 3325 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); 3326 } 3327 CHECK_EQ((status_t)OK, mCodec->initNativeWindow()); 3328 3329 { 3330 sp<AMessage> notify = mCodec->mNotify->dup(); 3331 notify->setInt32("what", ACodec::kWhatComponentConfigured); 3332 notify->post(); 3333 } 3334 3335 return true; 3336} 3337 3338void ACodec::LoadedState::onCreateInputSurface( 3339 const sp<AMessage> &msg) { 3340 ALOGV("onCreateInputSurface"); 3341 3342 sp<AMessage> notify = mCodec->mNotify->dup(); 3343 notify->setInt32("what", ACodec::kWhatInputSurfaceCreated); 3344 3345 sp<IGraphicBufferProducer> bufferProducer; 3346 status_t err; 3347 3348 err = mCodec->mOMX->createInputSurface(mCodec->mNode, kPortIndexInput, 3349 &bufferProducer); 3350 if (err == OK) { 3351 notify->setObject("input-surface", 3352 new BufferProducerWrapper(bufferProducer)); 3353 } else { 3354 // Can't use mCodec->signalError() here -- MediaCodec won't forward 3355 // the error through because it's in the "configured" state. We 3356 // send a kWhatInputSurfaceCreated with an error value instead. 3357 ALOGE("[%s] onCreateInputSurface returning error %d", 3358 mCodec->mComponentName.c_str(), err); 3359 notify->setInt32("err", err); 3360 } 3361 notify->post(); 3362} 3363 3364void ACodec::LoadedState::onStart() { 3365 ALOGV("onStart"); 3366 3367 CHECK_EQ(mCodec->mOMX->sendCommand( 3368 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle), 3369 (status_t)OK); 3370 3371 mCodec->changeState(mCodec->mLoadedToIdleState); 3372} 3373 3374//////////////////////////////////////////////////////////////////////////////// 3375 3376ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec) 3377 : BaseState(codec) { 3378} 3379 3380void ACodec::LoadedToIdleState::stateEntered() { 3381 ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str()); 3382 3383 status_t err; 3384 if ((err = allocateBuffers()) != OK) { 3385 ALOGE("Failed to allocate buffers after transitioning to IDLE state " 3386 "(error 0x%08x)", 3387 err); 3388 3389 mCodec->signalError(OMX_ErrorUndefined, err); 3390 3391 mCodec->changeState(mCodec->mLoadedState); 3392 } 3393} 3394 3395status_t ACodec::LoadedToIdleState::allocateBuffers() { 3396 status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput); 3397 3398 if (err != OK) { 3399 return err; 3400 } 3401 3402 return mCodec->allocateBuffersOnPort(kPortIndexOutput); 3403} 3404 3405bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) { 3406 switch (msg->what()) { 3407 case kWhatShutdown: 3408 { 3409 mCodec->deferMessage(msg); 3410 return true; 3411 } 3412 3413 case kWhatSignalEndOfInputStream: 3414 { 3415 mCodec->onSignalEndOfInputStream(); 3416 return true; 3417 } 3418 3419 case kWhatResume: 3420 { 3421 // We'll be active soon enough. 3422 return true; 3423 } 3424 3425 case kWhatFlush: 3426 { 3427 // We haven't even started yet, so we're flushed alright... 3428 sp<AMessage> notify = mCodec->mNotify->dup(); 3429 notify->setInt32("what", ACodec::kWhatFlushCompleted); 3430 notify->post(); 3431 return true; 3432 } 3433 3434 default: 3435 return BaseState::onMessageReceived(msg); 3436 } 3437} 3438 3439bool ACodec::LoadedToIdleState::onOMXEvent( 3440 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3441 switch (event) { 3442 case OMX_EventCmdComplete: 3443 { 3444 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 3445 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); 3446 3447 CHECK_EQ(mCodec->mOMX->sendCommand( 3448 mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting), 3449 (status_t)OK); 3450 3451 mCodec->changeState(mCodec->mIdleToExecutingState); 3452 3453 return true; 3454 } 3455 3456 default: 3457 return BaseState::onOMXEvent(event, data1, data2); 3458 } 3459} 3460 3461//////////////////////////////////////////////////////////////////////////////// 3462 3463ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec) 3464 : BaseState(codec) { 3465} 3466 3467void ACodec::IdleToExecutingState::stateEntered() { 3468 ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str()); 3469} 3470 3471bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) { 3472 switch (msg->what()) { 3473 case kWhatShutdown: 3474 { 3475 mCodec->deferMessage(msg); 3476 return true; 3477 } 3478 3479 case kWhatResume: 3480 { 3481 // We'll be active soon enough. 3482 return true; 3483 } 3484 3485 case kWhatFlush: 3486 { 3487 // We haven't even started yet, so we're flushed alright... 3488 sp<AMessage> notify = mCodec->mNotify->dup(); 3489 notify->setInt32("what", ACodec::kWhatFlushCompleted); 3490 notify->post(); 3491 3492 return true; 3493 } 3494 3495 case kWhatSignalEndOfInputStream: 3496 { 3497 mCodec->onSignalEndOfInputStream(); 3498 return true; 3499 } 3500 3501 default: 3502 return BaseState::onMessageReceived(msg); 3503 } 3504} 3505 3506bool ACodec::IdleToExecutingState::onOMXEvent( 3507 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3508 switch (event) { 3509 case OMX_EventCmdComplete: 3510 { 3511 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 3512 CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting); 3513 3514 mCodec->mExecutingState->resume(); 3515 mCodec->changeState(mCodec->mExecutingState); 3516 3517 return true; 3518 } 3519 3520 default: 3521 return BaseState::onOMXEvent(event, data1, data2); 3522 } 3523} 3524 3525//////////////////////////////////////////////////////////////////////////////// 3526 3527ACodec::ExecutingState::ExecutingState(ACodec *codec) 3528 : BaseState(codec), 3529 mActive(false) { 3530} 3531 3532ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode( 3533 OMX_U32 portIndex) { 3534 return RESUBMIT_BUFFERS; 3535} 3536 3537void ACodec::ExecutingState::submitOutputBuffers() { 3538 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) { 3539 BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i); 3540 3541 if (mCodec->mNativeWindow != NULL) { 3542 CHECK(info->mStatus == BufferInfo::OWNED_BY_US 3543 || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW); 3544 3545 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 3546 continue; 3547 } 3548 } else { 3549 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 3550 } 3551 3552 ALOGV("[%s] calling fillBuffer %p", 3553 mCodec->mComponentName.c_str(), info->mBufferID); 3554 3555 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), 3556 (status_t)OK); 3557 3558 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 3559 } 3560} 3561 3562void ACodec::ExecutingState::resume() { 3563 if (mActive) { 3564 ALOGV("[%s] We're already active, no need to resume.", 3565 mCodec->mComponentName.c_str()); 3566 3567 return; 3568 } 3569 3570 submitOutputBuffers(); 3571 3572 // Post the first input buffer. 3573 CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u); 3574 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0); 3575 3576 postFillThisBuffer(info); 3577 3578 mActive = true; 3579} 3580 3581void ACodec::ExecutingState::stateEntered() { 3582 ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str()); 3583 3584 mCodec->processDeferredMessages(); 3585} 3586 3587bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) { 3588 bool handled = false; 3589 3590 switch (msg->what()) { 3591 case kWhatShutdown: 3592 { 3593 int32_t keepComponentAllocated; 3594 CHECK(msg->findInt32( 3595 "keepComponentAllocated", &keepComponentAllocated)); 3596 3597 mCodec->mShutdownInProgress = true; 3598 mCodec->mKeepComponentAllocated = keepComponentAllocated; 3599 3600 mActive = false; 3601 3602 CHECK_EQ(mCodec->mOMX->sendCommand( 3603 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle), 3604 (status_t)OK); 3605 3606 mCodec->changeState(mCodec->mExecutingToIdleState); 3607 3608 handled = true; 3609 break; 3610 } 3611 3612 case kWhatFlush: 3613 { 3614 ALOGV("[%s] ExecutingState flushing now " 3615 "(codec owns %d/%d input, %d/%d output).", 3616 mCodec->mComponentName.c_str(), 3617 mCodec->countBuffersOwnedByComponent(kPortIndexInput), 3618 mCodec->mBuffers[kPortIndexInput].size(), 3619 mCodec->countBuffersOwnedByComponent(kPortIndexOutput), 3620 mCodec->mBuffers[kPortIndexOutput].size()); 3621 3622 mActive = false; 3623 3624 CHECK_EQ(mCodec->mOMX->sendCommand( 3625 mCodec->mNode, OMX_CommandFlush, OMX_ALL), 3626 (status_t)OK); 3627 3628 mCodec->changeState(mCodec->mFlushingState); 3629 3630 handled = true; 3631 break; 3632 } 3633 3634 case kWhatResume: 3635 { 3636 resume(); 3637 3638 handled = true; 3639 break; 3640 } 3641 3642 case kWhatRequestIDRFrame: 3643 { 3644 status_t err = mCodec->requestIDRFrame(); 3645 if (err != OK) { 3646 ALOGW("Requesting an IDR frame failed."); 3647 } 3648 3649 handled = true; 3650 break; 3651 } 3652 3653 case kWhatSetParameters: 3654 { 3655 sp<AMessage> params; 3656 CHECK(msg->findMessage("params", ¶ms)); 3657 3658 status_t err = mCodec->setParameters(params); 3659 3660 sp<AMessage> reply; 3661 if (msg->findMessage("reply", &reply)) { 3662 reply->setInt32("err", err); 3663 reply->post(); 3664 } 3665 3666 handled = true; 3667 break; 3668 } 3669 3670 case ACodec::kWhatSignalEndOfInputStream: 3671 { 3672 mCodec->onSignalEndOfInputStream(); 3673 handled = true; 3674 break; 3675 } 3676 3677 default: 3678 handled = BaseState::onMessageReceived(msg); 3679 break; 3680 } 3681 3682 return handled; 3683} 3684 3685status_t ACodec::setParameters(const sp<AMessage> ¶ms) { 3686 int32_t videoBitrate; 3687 if (params->findInt32("videoBitrate", &videoBitrate)) { 3688 OMX_VIDEO_CONFIG_BITRATETYPE configParams; 3689 InitOMXParams(&configParams); 3690 configParams.nPortIndex = kPortIndexOutput; 3691 configParams.nEncodeBitrate = videoBitrate; 3692 3693 status_t err = mOMX->setConfig( 3694 mNode, 3695 OMX_IndexConfigVideoBitrate, 3696 &configParams, 3697 sizeof(configParams)); 3698 3699 if (err != OK) { 3700 ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d", 3701 videoBitrate, err); 3702 3703 return err; 3704 } 3705 } 3706 3707 return OK; 3708} 3709 3710void ACodec::onSignalEndOfInputStream() { 3711 sp<AMessage> notify = mNotify->dup(); 3712 notify->setInt32("what", ACodec::kWhatSignaledInputEOS); 3713 3714 status_t err = mOMX->signalEndOfInputStream(mNode); 3715 if (err != OK) { 3716 notify->setInt32("err", err); 3717 } 3718 notify->post(); 3719} 3720 3721bool ACodec::ExecutingState::onOMXEvent( 3722 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3723 switch (event) { 3724 case OMX_EventPortSettingsChanged: 3725 { 3726 CHECK_EQ(data1, (OMX_U32)kPortIndexOutput); 3727 3728 if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) { 3729 CHECK_EQ(mCodec->mOMX->sendCommand( 3730 mCodec->mNode, 3731 OMX_CommandPortDisable, kPortIndexOutput), 3732 (status_t)OK); 3733 3734 mCodec->freeOutputBuffersNotOwnedByComponent(); 3735 3736 mCodec->changeState(mCodec->mOutputPortSettingsChangedState); 3737 } else if (data2 == OMX_IndexConfigCommonOutputCrop) { 3738 mCodec->mSentFormat = false; 3739 } else { 3740 ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx", 3741 mCodec->mComponentName.c_str(), data2); 3742 } 3743 3744 return true; 3745 } 3746 3747 case OMX_EventBufferFlag: 3748 { 3749 return true; 3750 } 3751 3752 default: 3753 return BaseState::onOMXEvent(event, data1, data2); 3754 } 3755} 3756 3757//////////////////////////////////////////////////////////////////////////////// 3758 3759ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState( 3760 ACodec *codec) 3761 : BaseState(codec) { 3762} 3763 3764ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode( 3765 OMX_U32 portIndex) { 3766 if (portIndex == kPortIndexOutput) { 3767 return FREE_BUFFERS; 3768 } 3769 3770 CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput); 3771 3772 return RESUBMIT_BUFFERS; 3773} 3774 3775bool ACodec::OutputPortSettingsChangedState::onMessageReceived( 3776 const sp<AMessage> &msg) { 3777 bool handled = false; 3778 3779 switch (msg->what()) { 3780 case kWhatFlush: 3781 case kWhatShutdown: 3782 case kWhatResume: 3783 { 3784 if (msg->what() == kWhatResume) { 3785 ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str()); 3786 } 3787 3788 mCodec->deferMessage(msg); 3789 handled = true; 3790 break; 3791 } 3792 3793 default: 3794 handled = BaseState::onMessageReceived(msg); 3795 break; 3796 } 3797 3798 return handled; 3799} 3800 3801void ACodec::OutputPortSettingsChangedState::stateEntered() { 3802 ALOGV("[%s] Now handling output port settings change", 3803 mCodec->mComponentName.c_str()); 3804} 3805 3806bool ACodec::OutputPortSettingsChangedState::onOMXEvent( 3807 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3808 switch (event) { 3809 case OMX_EventCmdComplete: 3810 { 3811 if (data1 == (OMX_U32)OMX_CommandPortDisable) { 3812 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput); 3813 3814 ALOGV("[%s] Output port now disabled.", 3815 mCodec->mComponentName.c_str()); 3816 3817 CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty()); 3818 mCodec->mDealer[kPortIndexOutput].clear(); 3819 3820 CHECK_EQ(mCodec->mOMX->sendCommand( 3821 mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput), 3822 (status_t)OK); 3823 3824 status_t err; 3825 if ((err = mCodec->allocateBuffersOnPort( 3826 kPortIndexOutput)) != OK) { 3827 ALOGE("Failed to allocate output port buffers after " 3828 "port reconfiguration (error 0x%08x)", 3829 err); 3830 3831 mCodec->signalError(OMX_ErrorUndefined, err); 3832 3833 // This is technically not correct, but appears to be 3834 // the only way to free the component instance. 3835 // Controlled transitioning from excecuting->idle 3836 // and idle->loaded seem impossible probably because 3837 // the output port never finishes re-enabling. 3838 mCodec->mShutdownInProgress = true; 3839 mCodec->mKeepComponentAllocated = false; 3840 mCodec->changeState(mCodec->mLoadedState); 3841 } 3842 3843 return true; 3844 } else if (data1 == (OMX_U32)OMX_CommandPortEnable) { 3845 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput); 3846 3847 mCodec->mSentFormat = false; 3848 3849 ALOGV("[%s] Output port now reenabled.", 3850 mCodec->mComponentName.c_str()); 3851 3852 if (mCodec->mExecutingState->active()) { 3853 mCodec->mExecutingState->submitOutputBuffers(); 3854 } 3855 3856 mCodec->changeState(mCodec->mExecutingState); 3857 3858 return true; 3859 } 3860 3861 return false; 3862 } 3863 3864 default: 3865 return false; 3866 } 3867} 3868 3869//////////////////////////////////////////////////////////////////////////////// 3870 3871ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec) 3872 : BaseState(codec), 3873 mComponentNowIdle(false) { 3874} 3875 3876bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) { 3877 bool handled = false; 3878 3879 switch (msg->what()) { 3880 case kWhatFlush: 3881 { 3882 // Don't send me a flush request if you previously wanted me 3883 // to shutdown. 3884 TRESPASS(); 3885 break; 3886 } 3887 3888 case kWhatShutdown: 3889 { 3890 // We're already doing that... 3891 3892 handled = true; 3893 break; 3894 } 3895 3896 default: 3897 handled = BaseState::onMessageReceived(msg); 3898 break; 3899 } 3900 3901 return handled; 3902} 3903 3904void ACodec::ExecutingToIdleState::stateEntered() { 3905 ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str()); 3906 3907 mComponentNowIdle = false; 3908 mCodec->mSentFormat = false; 3909} 3910 3911bool ACodec::ExecutingToIdleState::onOMXEvent( 3912 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 3913 switch (event) { 3914 case OMX_EventCmdComplete: 3915 { 3916 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 3917 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); 3918 3919 mComponentNowIdle = true; 3920 3921 changeStateIfWeOwnAllBuffers(); 3922 3923 return true; 3924 } 3925 3926 case OMX_EventPortSettingsChanged: 3927 case OMX_EventBufferFlag: 3928 { 3929 // We're shutting down and don't care about this anymore. 3930 return true; 3931 } 3932 3933 default: 3934 return BaseState::onOMXEvent(event, data1, data2); 3935 } 3936} 3937 3938void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() { 3939 if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) { 3940 CHECK_EQ(mCodec->mOMX->sendCommand( 3941 mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded), 3942 (status_t)OK); 3943 3944 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK); 3945 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK); 3946 3947 if (mCodec->mFlags & kFlagIsSecure && mCodec->mNativeWindow != NULL) { 3948 // We push enough 1x1 blank buffers to ensure that one of 3949 // them has made it to the display. This allows the OMX 3950 // component teardown to zero out any protected buffers 3951 // without the risk of scanning out one of those buffers. 3952 mCodec->pushBlankBuffersToNativeWindow(); 3953 } 3954 3955 mCodec->changeState(mCodec->mIdleToLoadedState); 3956 } 3957} 3958 3959void ACodec::ExecutingToIdleState::onInputBufferFilled( 3960 const sp<AMessage> &msg) { 3961 BaseState::onInputBufferFilled(msg); 3962 3963 changeStateIfWeOwnAllBuffers(); 3964} 3965 3966void ACodec::ExecutingToIdleState::onOutputBufferDrained( 3967 const sp<AMessage> &msg) { 3968 BaseState::onOutputBufferDrained(msg); 3969 3970 changeStateIfWeOwnAllBuffers(); 3971} 3972 3973//////////////////////////////////////////////////////////////////////////////// 3974 3975ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec) 3976 : BaseState(codec) { 3977} 3978 3979bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) { 3980 bool handled = false; 3981 3982 switch (msg->what()) { 3983 case kWhatShutdown: 3984 { 3985 // We're already doing that... 3986 3987 handled = true; 3988 break; 3989 } 3990 3991 case kWhatFlush: 3992 { 3993 // Don't send me a flush request if you previously wanted me 3994 // to shutdown. 3995 TRESPASS(); 3996 break; 3997 } 3998 3999 default: 4000 handled = BaseState::onMessageReceived(msg); 4001 break; 4002 } 4003 4004 return handled; 4005} 4006 4007void ACodec::IdleToLoadedState::stateEntered() { 4008 ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str()); 4009} 4010 4011bool ACodec::IdleToLoadedState::onOMXEvent( 4012 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 4013 switch (event) { 4014 case OMX_EventCmdComplete: 4015 { 4016 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 4017 CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded); 4018 4019 mCodec->changeState(mCodec->mLoadedState); 4020 4021 return true; 4022 } 4023 4024 default: 4025 return BaseState::onOMXEvent(event, data1, data2); 4026 } 4027} 4028 4029//////////////////////////////////////////////////////////////////////////////// 4030 4031ACodec::FlushingState::FlushingState(ACodec *codec) 4032 : BaseState(codec) { 4033} 4034 4035void ACodec::FlushingState::stateEntered() { 4036 ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str()); 4037 4038 mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false; 4039} 4040 4041bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) { 4042 bool handled = false; 4043 4044 switch (msg->what()) { 4045 case kWhatShutdown: 4046 { 4047 mCodec->deferMessage(msg); 4048 break; 4049 } 4050 4051 case kWhatFlush: 4052 { 4053 // We're already doing this right now. 4054 handled = true; 4055 break; 4056 } 4057 4058 default: 4059 handled = BaseState::onMessageReceived(msg); 4060 break; 4061 } 4062 4063 return handled; 4064} 4065 4066bool ACodec::FlushingState::onOMXEvent( 4067 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 4068 ALOGV("[%s] FlushingState onOMXEvent(%d,%ld)", 4069 mCodec->mComponentName.c_str(), event, data1); 4070 4071 switch (event) { 4072 case OMX_EventCmdComplete: 4073 { 4074 CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush); 4075 4076 if (data2 == kPortIndexInput || data2 == kPortIndexOutput) { 4077 CHECK(!mFlushComplete[data2]); 4078 mFlushComplete[data2] = true; 4079 4080 if (mFlushComplete[kPortIndexInput] 4081 && mFlushComplete[kPortIndexOutput]) { 4082 changeStateIfWeOwnAllBuffers(); 4083 } 4084 } else { 4085 CHECK_EQ(data2, OMX_ALL); 4086 CHECK(mFlushComplete[kPortIndexInput]); 4087 CHECK(mFlushComplete[kPortIndexOutput]); 4088 4089 changeStateIfWeOwnAllBuffers(); 4090 } 4091 4092 return true; 4093 } 4094 4095 case OMX_EventPortSettingsChanged: 4096 { 4097 sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id()); 4098 msg->setInt32("type", omx_message::EVENT); 4099 msg->setPointer("node", mCodec->mNode); 4100 msg->setInt32("event", event); 4101 msg->setInt32("data1", data1); 4102 msg->setInt32("data2", data2); 4103 4104 ALOGV("[%s] Deferring OMX_EventPortSettingsChanged", 4105 mCodec->mComponentName.c_str()); 4106 4107 mCodec->deferMessage(msg); 4108 4109 return true; 4110 } 4111 4112 default: 4113 return BaseState::onOMXEvent(event, data1, data2); 4114 } 4115 4116 return true; 4117} 4118 4119void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) { 4120 BaseState::onOutputBufferDrained(msg); 4121 4122 changeStateIfWeOwnAllBuffers(); 4123} 4124 4125void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) { 4126 BaseState::onInputBufferFilled(msg); 4127 4128 changeStateIfWeOwnAllBuffers(); 4129} 4130 4131void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() { 4132 if (mFlushComplete[kPortIndexInput] 4133 && mFlushComplete[kPortIndexOutput] 4134 && mCodec->allYourBuffersAreBelongToUs()) { 4135 sp<AMessage> notify = mCodec->mNotify->dup(); 4136 notify->setInt32("what", ACodec::kWhatFlushCompleted); 4137 notify->post(); 4138 4139 mCodec->mPortEOS[kPortIndexInput] = 4140 mCodec->mPortEOS[kPortIndexOutput] = false; 4141 4142 mCodec->mInputEOSResult = OK; 4143 4144 mCodec->changeState(mCodec->mExecutingState); 4145 } 4146} 4147 4148} // namespace android 4149