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