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