ACodec.cpp revision dc9bacd838442a524585887e6ea6696836be2eda
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17//#define LOG_NDEBUG 0 18#define LOG_TAG "ACodec" 19 20#include <media/stagefright/ACodec.h> 21 22#include <binder/MemoryDealer.h> 23 24#include <media/stagefright/foundation/hexdump.h> 25#include <media/stagefright/foundation/ABuffer.h> 26#include <media/stagefright/foundation/ADebug.h> 27#include <media/stagefright/foundation/AMessage.h> 28 29#include <media/stagefright/MediaDefs.h> 30#include <media/stagefright/NativeWindowWrapper.h> 31#include <media/stagefright/OMXClient.h> 32#include <media/stagefright/OMXCodec.h> 33 34#include <surfaceflinger/Surface.h> 35#include <gui/SurfaceTextureClient.h> 36 37#include <OMX_Component.h> 38 39namespace android { 40 41template<class T> 42static void InitOMXParams(T *params) { 43 params->nSize = sizeof(T); 44 params->nVersion.s.nVersionMajor = 1; 45 params->nVersion.s.nVersionMinor = 0; 46 params->nVersion.s.nRevision = 0; 47 params->nVersion.s.nStep = 0; 48} 49 50struct CodecObserver : public BnOMXObserver { 51 CodecObserver() {} 52 53 void setNotificationMessage(const sp<AMessage> &msg) { 54 mNotify = msg; 55 } 56 57 // from IOMXObserver 58 virtual void onMessage(const omx_message &omx_msg) { 59 sp<AMessage> msg = mNotify->dup(); 60 61 msg->setInt32("type", omx_msg.type); 62 msg->setPointer("node", omx_msg.node); 63 64 switch (omx_msg.type) { 65 case omx_message::EVENT: 66 { 67 msg->setInt32("event", omx_msg.u.event_data.event); 68 msg->setInt32("data1", omx_msg.u.event_data.data1); 69 msg->setInt32("data2", omx_msg.u.event_data.data2); 70 break; 71 } 72 73 case omx_message::EMPTY_BUFFER_DONE: 74 { 75 msg->setPointer("buffer", omx_msg.u.buffer_data.buffer); 76 break; 77 } 78 79 case omx_message::FILL_BUFFER_DONE: 80 { 81 msg->setPointer( 82 "buffer", omx_msg.u.extended_buffer_data.buffer); 83 msg->setInt32( 84 "range_offset", 85 omx_msg.u.extended_buffer_data.range_offset); 86 msg->setInt32( 87 "range_length", 88 omx_msg.u.extended_buffer_data.range_length); 89 msg->setInt32( 90 "flags", 91 omx_msg.u.extended_buffer_data.flags); 92 msg->setInt64( 93 "timestamp", 94 omx_msg.u.extended_buffer_data.timestamp); 95 msg->setPointer( 96 "platform_private", 97 omx_msg.u.extended_buffer_data.platform_private); 98 msg->setPointer( 99 "data_ptr", 100 omx_msg.u.extended_buffer_data.data_ptr); 101 break; 102 } 103 104 default: 105 TRESPASS(); 106 break; 107 } 108 109 msg->post(); 110 } 111 112protected: 113 virtual ~CodecObserver() {} 114 115private: 116 sp<AMessage> mNotify; 117 118 DISALLOW_EVIL_CONSTRUCTORS(CodecObserver); 119}; 120 121//////////////////////////////////////////////////////////////////////////////// 122 123struct ACodec::BaseState : public AState { 124 BaseState(ACodec *codec, const sp<AState> &parentState = NULL); 125 126protected: 127 enum PortMode { 128 KEEP_BUFFERS, 129 RESUBMIT_BUFFERS, 130 FREE_BUFFERS, 131 }; 132 133 ACodec *mCodec; 134 135 virtual PortMode getPortMode(OMX_U32 portIndex); 136 137 virtual bool onMessageReceived(const sp<AMessage> &msg); 138 139 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 140 141 virtual void onOutputBufferDrained(const sp<AMessage> &msg); 142 virtual void onInputBufferFilled(const sp<AMessage> &msg); 143 144 void postFillThisBuffer(BufferInfo *info); 145 146private: 147 bool onOMXMessage(const sp<AMessage> &msg); 148 149 bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID); 150 151 bool onOMXFillBufferDone( 152 IOMX::buffer_id bufferID, 153 size_t rangeOffset, size_t rangeLength, 154 OMX_U32 flags, 155 int64_t timeUs, 156 void *platformPrivate, 157 void *dataPtr); 158 159 void getMoreInputDataIfPossible(); 160 161 DISALLOW_EVIL_CONSTRUCTORS(BaseState); 162}; 163 164//////////////////////////////////////////////////////////////////////////////// 165 166struct ACodec::UninitializedState : public ACodec::BaseState { 167 UninitializedState(ACodec *codec); 168 169protected: 170 virtual bool onMessageReceived(const sp<AMessage> &msg); 171 172private: 173 void onSetup(const sp<AMessage> &msg); 174 175 DISALLOW_EVIL_CONSTRUCTORS(UninitializedState); 176}; 177 178//////////////////////////////////////////////////////////////////////////////// 179 180struct ACodec::LoadedToIdleState : public ACodec::BaseState { 181 LoadedToIdleState(ACodec *codec); 182 183protected: 184 virtual bool onMessageReceived(const sp<AMessage> &msg); 185 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 186 virtual void stateEntered(); 187 188private: 189 status_t allocateBuffers(); 190 191 DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState); 192}; 193 194//////////////////////////////////////////////////////////////////////////////// 195 196struct ACodec::IdleToExecutingState : public ACodec::BaseState { 197 IdleToExecutingState(ACodec *codec); 198 199protected: 200 virtual bool onMessageReceived(const sp<AMessage> &msg); 201 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 202 virtual void stateEntered(); 203 204private: 205 DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState); 206}; 207 208//////////////////////////////////////////////////////////////////////////////// 209 210struct ACodec::ExecutingState : public ACodec::BaseState { 211 ExecutingState(ACodec *codec); 212 213 void submitOutputBuffers(); 214 215 // Submit output buffers to the decoder, submit input buffers to client 216 // to fill with data. 217 void resume(); 218 219 // Returns true iff input and output buffers are in play. 220 bool active() const { return mActive; } 221 222protected: 223 virtual PortMode getPortMode(OMX_U32 portIndex); 224 virtual bool onMessageReceived(const sp<AMessage> &msg); 225 virtual void stateEntered(); 226 227 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 228 229private: 230 bool mActive; 231 232 DISALLOW_EVIL_CONSTRUCTORS(ExecutingState); 233}; 234 235//////////////////////////////////////////////////////////////////////////////// 236 237struct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState { 238 OutputPortSettingsChangedState(ACodec *codec); 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 DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState); 249}; 250 251//////////////////////////////////////////////////////////////////////////////// 252 253struct ACodec::ExecutingToIdleState : public ACodec::BaseState { 254 ExecutingToIdleState(ACodec *codec); 255 256protected: 257 virtual bool onMessageReceived(const sp<AMessage> &msg); 258 virtual void stateEntered(); 259 260 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 261 262 virtual void onOutputBufferDrained(const sp<AMessage> &msg); 263 virtual void onInputBufferFilled(const sp<AMessage> &msg); 264 265private: 266 void changeStateIfWeOwnAllBuffers(); 267 268 DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState); 269}; 270 271//////////////////////////////////////////////////////////////////////////////// 272 273struct ACodec::IdleToLoadedState : public ACodec::BaseState { 274 IdleToLoadedState(ACodec *codec); 275 276protected: 277 virtual bool onMessageReceived(const sp<AMessage> &msg); 278 virtual void stateEntered(); 279 280 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 281 282private: 283 DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState); 284}; 285 286//////////////////////////////////////////////////////////////////////////////// 287 288struct ACodec::FlushingState : public ACodec::BaseState { 289 FlushingState(ACodec *codec); 290 291protected: 292 virtual bool onMessageReceived(const sp<AMessage> &msg); 293 virtual void stateEntered(); 294 295 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 296 297 virtual void onOutputBufferDrained(const sp<AMessage> &msg); 298 virtual void onInputBufferFilled(const sp<AMessage> &msg); 299 300private: 301 bool mFlushComplete[2]; 302 303 void changeStateIfWeOwnAllBuffers(); 304 305 DISALLOW_EVIL_CONSTRUCTORS(FlushingState); 306}; 307 308//////////////////////////////////////////////////////////////////////////////// 309 310ACodec::ACodec() 311 : mNode(NULL), 312 mSentFormat(false) { 313 mUninitializedState = new UninitializedState(this); 314 mLoadedToIdleState = new LoadedToIdleState(this); 315 mIdleToExecutingState = new IdleToExecutingState(this); 316 mExecutingState = new ExecutingState(this); 317 318 mOutputPortSettingsChangedState = 319 new OutputPortSettingsChangedState(this); 320 321 mExecutingToIdleState = new ExecutingToIdleState(this); 322 mIdleToLoadedState = new IdleToLoadedState(this); 323 mFlushingState = new FlushingState(this); 324 325 mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false; 326 mInputEOSResult = OK; 327 328 changeState(mUninitializedState); 329} 330 331ACodec::~ACodec() { 332} 333 334void ACodec::setNotificationMessage(const sp<AMessage> &msg) { 335 mNotify = msg; 336} 337 338void ACodec::initiateSetup(const sp<AMessage> &msg) { 339 msg->setWhat(kWhatSetup); 340 msg->setTarget(id()); 341 msg->post(); 342} 343 344void ACodec::signalFlush() { 345 (new AMessage(kWhatFlush, id()))->post(); 346} 347 348void ACodec::signalResume() { 349 (new AMessage(kWhatResume, id()))->post(); 350} 351 352void ACodec::initiateShutdown() { 353 (new AMessage(kWhatShutdown, id()))->post(); 354} 355 356status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) { 357 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 358 359 CHECK(mDealer[portIndex] == NULL); 360 CHECK(mBuffers[portIndex].isEmpty()); 361 362 if (mNativeWindow != NULL && portIndex == kPortIndexOutput) { 363 return allocateOutputBuffersFromNativeWindow(); 364 } 365 366 OMX_PARAM_PORTDEFINITIONTYPE def; 367 InitOMXParams(&def); 368 def.nPortIndex = portIndex; 369 370 status_t err = mOMX->getParameter( 371 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 372 373 if (err != OK) { 374 return err; 375 } 376 377 LOGV("[%s] Allocating %lu buffers of size %lu on %s port", 378 mComponentName.c_str(), 379 def.nBufferCountActual, def.nBufferSize, 380 portIndex == kPortIndexInput ? "input" : "output"); 381 382 size_t totalSize = def.nBufferCountActual * def.nBufferSize; 383 mDealer[portIndex] = new MemoryDealer(totalSize, "OMXCodec"); 384 385 for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) { 386 sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize); 387 CHECK(mem.get() != NULL); 388 389 IOMX::buffer_id buffer; 390 391 if (!strcasecmp( 392 mComponentName.c_str(), "OMX.TI.DUCATI1.VIDEO.DECODER")) { 393 if (portIndex == kPortIndexInput && i == 0) { 394 // Only log this warning once per allocation round. 395 396 LOGW("OMX.TI.DUCATI1.VIDEO.DECODER requires the use of " 397 "OMX_AllocateBuffer instead of the preferred " 398 "OMX_UseBuffer. Vendor must fix this."); 399 } 400 401 err = mOMX->allocateBufferWithBackup( 402 mNode, portIndex, mem, &buffer); 403 } else { 404 err = mOMX->useBuffer(mNode, portIndex, mem, &buffer); 405 } 406 407 if (err != OK) { 408 return err; 409 } 410 411 BufferInfo info; 412 info.mBufferID = buffer; 413 info.mStatus = BufferInfo::OWNED_BY_US; 414 info.mData = new ABuffer(mem->pointer(), def.nBufferSize); 415 mBuffers[portIndex].push(info); 416 } 417 418 return OK; 419} 420 421status_t ACodec::allocateOutputBuffersFromNativeWindow() { 422 OMX_PARAM_PORTDEFINITIONTYPE def; 423 InitOMXParams(&def); 424 def.nPortIndex = kPortIndexOutput; 425 426 status_t err = mOMX->getParameter( 427 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 428 429 if (err != OK) { 430 return err; 431 } 432 433 err = native_window_set_scaling_mode(mNativeWindow.get(), 434 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); 435 436 if (err != OK) { 437 return err; 438 } 439 440 err = native_window_set_buffers_geometry( 441 mNativeWindow.get(), 442 def.format.video.nFrameWidth, 443 def.format.video.nFrameHeight, 444 def.format.video.eColorFormat); 445 446 if (err != 0) { 447 LOGE("native_window_set_buffers_geometry failed: %s (%d)", 448 strerror(-err), -err); 449 return err; 450 } 451 452 // Set up the native window. 453 OMX_U32 usage = 0; 454 err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage); 455 if (err != 0) { 456 LOGW("querying usage flags from OMX IL component failed: %d", err); 457 // XXX: Currently this error is logged, but not fatal. 458 usage = 0; 459 } 460 461 err = native_window_set_usage( 462 mNativeWindow.get(), 463 usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP); 464 465 if (err != 0) { 466 LOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err); 467 return err; 468 } 469 470 int minUndequeuedBufs = 0; 471 err = mNativeWindow->query( 472 mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, 473 &minUndequeuedBufs); 474 475 if (err != 0) { 476 LOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)", 477 strerror(-err), -err); 478 return err; 479 } 480 481 // XXX: Is this the right logic to use? It's not clear to me what the OMX 482 // buffer counts refer to - how do they account for the renderer holding on 483 // to buffers? 484 if (def.nBufferCountActual < def.nBufferCountMin + minUndequeuedBufs) { 485 OMX_U32 newBufferCount = def.nBufferCountMin + minUndequeuedBufs; 486 def.nBufferCountActual = newBufferCount; 487 err = mOMX->setParameter( 488 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 489 490 if (err != OK) { 491 LOGE("[%s] setting nBufferCountActual to %lu failed: %d", 492 mComponentName.c_str(), newBufferCount, err); 493 return err; 494 } 495 } 496 497 err = native_window_set_buffer_count( 498 mNativeWindow.get(), def.nBufferCountActual); 499 500 if (err != 0) { 501 LOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), 502 -err); 503 return err; 504 } 505 506 LOGV("[%s] Allocating %lu buffers from a native window of size %lu on " 507 "output port", 508 mComponentName.c_str(), def.nBufferCountActual, def.nBufferSize); 509 510 // Dequeue buffers and send them to OMX 511 for (OMX_U32 i = 0; i < def.nBufferCountActual; i++) { 512 ANativeWindowBuffer *buf; 513 err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf); 514 if (err != 0) { 515 LOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err); 516 break; 517 } 518 519 sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false)); 520 BufferInfo info; 521 info.mStatus = BufferInfo::OWNED_BY_US; 522 info.mData = new ABuffer(0); 523 info.mGraphicBuffer = graphicBuffer; 524 mBuffers[kPortIndexOutput].push(info); 525 526 IOMX::buffer_id bufferId; 527 err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer, 528 &bufferId); 529 if (err != 0) { 530 LOGE("registering GraphicBuffer %lu with OMX IL component failed: " 531 "%d", i, err); 532 break; 533 } 534 535 mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId; 536 537 LOGV("[%s] Registered graphic buffer with ID %p (pointer = %p)", 538 mComponentName.c_str(), 539 bufferId, graphicBuffer.get()); 540 } 541 542 OMX_U32 cancelStart; 543 OMX_U32 cancelEnd; 544 545 if (err != 0) { 546 // If an error occurred while dequeuing we need to cancel any buffers 547 // that were dequeued. 548 cancelStart = 0; 549 cancelEnd = mBuffers[kPortIndexOutput].size(); 550 } else { 551 // Return the last two buffers to the native window. 552 cancelStart = def.nBufferCountActual - minUndequeuedBufs; 553 cancelEnd = def.nBufferCountActual; 554 } 555 556 for (OMX_U32 i = cancelStart; i < cancelEnd; i++) { 557 BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i); 558 cancelBufferToNativeWindow(info); 559 } 560 561 return err; 562} 563 564status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) { 565 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 566 567 LOGV("[%s] Calling cancelBuffer on buffer %p", 568 mComponentName.c_str(), info->mBufferID); 569 570 int err = mNativeWindow->cancelBuffer( 571 mNativeWindow.get(), info->mGraphicBuffer.get()); 572 573 CHECK_EQ(err, 0); 574 575 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 576 577 return OK; 578} 579 580ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() { 581 ANativeWindowBuffer *buf; 582 if (mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf) != 0) { 583 LOGE("dequeueBuffer failed."); 584 return NULL; 585 } 586 587 for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) { 588 BufferInfo *info = 589 &mBuffers[kPortIndexOutput].editItemAt(i); 590 591 if (info->mGraphicBuffer->handle == buf->handle) { 592 CHECK_EQ((int)info->mStatus, 593 (int)BufferInfo::OWNED_BY_NATIVE_WINDOW); 594 595 info->mStatus = BufferInfo::OWNED_BY_US; 596 597 return info; 598 } 599 } 600 601 TRESPASS(); 602 603 return NULL; 604} 605 606status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) { 607 for (size_t i = mBuffers[portIndex].size(); i-- > 0;) { 608 CHECK_EQ((status_t)OK, freeBuffer(portIndex, i)); 609 } 610 611 mDealer[portIndex].clear(); 612 613 return OK; 614} 615 616status_t ACodec::freeOutputBuffersNotOwnedByComponent() { 617 for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) { 618 BufferInfo *info = 619 &mBuffers[kPortIndexOutput].editItemAt(i); 620 621 if (info->mStatus != 622 BufferInfo::OWNED_BY_COMPONENT) { 623 // We shouldn't have sent out any buffers to the client at this 624 // point. 625 CHECK_NE((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM); 626 627 CHECK_EQ((status_t)OK, freeBuffer(kPortIndexOutput, i)); 628 } 629 } 630 631 return OK; 632} 633 634status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) { 635 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 636 637 CHECK(info->mStatus == BufferInfo::OWNED_BY_US 638 || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW); 639 640 if (portIndex == kPortIndexOutput && mNativeWindow != NULL 641 && info->mStatus == BufferInfo::OWNED_BY_US) { 642 CHECK_EQ((status_t)OK, cancelBufferToNativeWindow(info)); 643 } 644 645 CHECK_EQ(mOMX->freeBuffer( 646 mNode, portIndex, info->mBufferID), 647 (status_t)OK); 648 649 mBuffers[portIndex].removeAt(i); 650 651 return OK; 652} 653 654ACodec::BufferInfo *ACodec::findBufferByID( 655 uint32_t portIndex, IOMX::buffer_id bufferID, 656 ssize_t *index) { 657 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 658 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 659 660 if (info->mBufferID == bufferID) { 661 if (index != NULL) { 662 *index = i; 663 } 664 return info; 665 } 666 } 667 668 TRESPASS(); 669 670 return NULL; 671} 672 673void ACodec::setComponentRole( 674 bool isEncoder, const char *mime) { 675 struct MimeToRole { 676 const char *mime; 677 const char *decoderRole; 678 const char *encoderRole; 679 }; 680 681 static const MimeToRole kMimeToRole[] = { 682 { MEDIA_MIMETYPE_AUDIO_MPEG, 683 "audio_decoder.mp3", "audio_encoder.mp3" }, 684 { MEDIA_MIMETYPE_AUDIO_AMR_NB, 685 "audio_decoder.amrnb", "audio_encoder.amrnb" }, 686 { MEDIA_MIMETYPE_AUDIO_AMR_WB, 687 "audio_decoder.amrwb", "audio_encoder.amrwb" }, 688 { MEDIA_MIMETYPE_AUDIO_AAC, 689 "audio_decoder.aac", "audio_encoder.aac" }, 690 { MEDIA_MIMETYPE_VIDEO_AVC, 691 "video_decoder.avc", "video_encoder.avc" }, 692 { MEDIA_MIMETYPE_VIDEO_MPEG4, 693 "video_decoder.mpeg4", "video_encoder.mpeg4" }, 694 { MEDIA_MIMETYPE_VIDEO_H263, 695 "video_decoder.h263", "video_encoder.h263" }, 696 }; 697 698 static const size_t kNumMimeToRole = 699 sizeof(kMimeToRole) / sizeof(kMimeToRole[0]); 700 701 size_t i; 702 for (i = 0; i < kNumMimeToRole; ++i) { 703 if (!strcasecmp(mime, kMimeToRole[i].mime)) { 704 break; 705 } 706 } 707 708 if (i == kNumMimeToRole) { 709 return; 710 } 711 712 const char *role = 713 isEncoder ? kMimeToRole[i].encoderRole 714 : kMimeToRole[i].decoderRole; 715 716 if (role != NULL) { 717 OMX_PARAM_COMPONENTROLETYPE roleParams; 718 InitOMXParams(&roleParams); 719 720 strncpy((char *)roleParams.cRole, 721 role, OMX_MAX_STRINGNAME_SIZE - 1); 722 723 roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0'; 724 725 status_t err = mOMX->setParameter( 726 mNode, OMX_IndexParamStandardComponentRole, 727 &roleParams, sizeof(roleParams)); 728 729 if (err != OK) { 730 LOGW("[%s] Failed to set standard component role '%s'.", 731 mComponentName.c_str(), role); 732 } 733 } 734} 735 736void ACodec::configureCodec( 737 const char *mime, const sp<AMessage> &msg) { 738 setComponentRole(false /* isEncoder */, mime); 739 740 if (!strncasecmp(mime, "video/", 6)) { 741 int32_t width, height; 742 CHECK(msg->findInt32("width", &width)); 743 CHECK(msg->findInt32("height", &height)); 744 745 CHECK_EQ(setupVideoDecoder(mime, width, height), 746 (status_t)OK); 747 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 748 int32_t numChannels, sampleRate; 749 CHECK(msg->findInt32("channel-count", &numChannels)); 750 CHECK(msg->findInt32("sample-rate", &sampleRate)); 751 752 CHECK_EQ(setupAACDecoder(numChannels, sampleRate), (status_t)OK); 753 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) { 754 } else { 755 TRESPASS(); 756 } 757 758 int32_t maxInputSize; 759 if (msg->findInt32("max-input-size", &maxInputSize)) { 760 CHECK_EQ(setMinBufferSize(kPortIndexInput, (size_t)maxInputSize), 761 (status_t)OK); 762 } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) { 763 CHECK_EQ(setMinBufferSize(kPortIndexInput, 8192), // XXX 764 (status_t)OK); 765 } 766} 767 768status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) { 769 OMX_PARAM_PORTDEFINITIONTYPE def; 770 InitOMXParams(&def); 771 def.nPortIndex = portIndex; 772 773 status_t err = mOMX->getParameter( 774 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 775 776 if (err != OK) { 777 return err; 778 } 779 780 if (def.nBufferSize >= size) { 781 return OK; 782 } 783 784 def.nBufferSize = size; 785 786 err = mOMX->setParameter( 787 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 788 789 if (err != OK) { 790 return err; 791 } 792 793 err = mOMX->getParameter( 794 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 795 796 if (err != OK) { 797 return err; 798 } 799 800 CHECK(def.nBufferSize >= size); 801 802 return OK; 803} 804 805status_t ACodec::setupAACDecoder(int32_t numChannels, int32_t sampleRate) { 806 OMX_AUDIO_PARAM_AACPROFILETYPE profile; 807 InitOMXParams(&profile); 808 profile.nPortIndex = kPortIndexInput; 809 810 status_t err = mOMX->getParameter( 811 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 812 813 if (err != OK) { 814 return err; 815 } 816 817 profile.nChannels = numChannels; 818 profile.nSampleRate = sampleRate; 819 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS; 820 821 err = mOMX->setParameter( 822 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 823 824 return err; 825} 826 827status_t ACodec::setVideoPortFormatType( 828 OMX_U32 portIndex, 829 OMX_VIDEO_CODINGTYPE compressionFormat, 830 OMX_COLOR_FORMATTYPE colorFormat) { 831 OMX_VIDEO_PARAM_PORTFORMATTYPE format; 832 InitOMXParams(&format); 833 format.nPortIndex = portIndex; 834 format.nIndex = 0; 835 bool found = false; 836 837 OMX_U32 index = 0; 838 for (;;) { 839 format.nIndex = index; 840 status_t err = mOMX->getParameter( 841 mNode, OMX_IndexParamVideoPortFormat, 842 &format, sizeof(format)); 843 844 if (err != OK) { 845 return err; 846 } 847 848 // The following assertion is violated by TI's video decoder. 849 // CHECK_EQ(format.nIndex, index); 850 851 if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) { 852 if (portIndex == kPortIndexInput 853 && colorFormat == format.eColorFormat) { 854 // eCompressionFormat does not seem right. 855 found = true; 856 break; 857 } 858 if (portIndex == kPortIndexOutput 859 && compressionFormat == format.eCompressionFormat) { 860 // eColorFormat does not seem right. 861 found = true; 862 break; 863 } 864 } 865 866 if (format.eCompressionFormat == compressionFormat 867 && format.eColorFormat == colorFormat) { 868 found = true; 869 break; 870 } 871 872 ++index; 873 } 874 875 if (!found) { 876 return UNKNOWN_ERROR; 877 } 878 879 status_t err = mOMX->setParameter( 880 mNode, OMX_IndexParamVideoPortFormat, 881 &format, sizeof(format)); 882 883 return err; 884} 885 886status_t ACodec::setSupportedOutputFormat() { 887 OMX_VIDEO_PARAM_PORTFORMATTYPE format; 888 InitOMXParams(&format); 889 format.nPortIndex = kPortIndexOutput; 890 format.nIndex = 0; 891 892 status_t err = mOMX->getParameter( 893 mNode, OMX_IndexParamVideoPortFormat, 894 &format, sizeof(format)); 895 CHECK_EQ(err, (status_t)OK); 896 CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused); 897 898 CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar 899 || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar 900 || format.eColorFormat == OMX_COLOR_FormatCbYCrY 901 || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar 902 || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar); 903 904 return mOMX->setParameter( 905 mNode, OMX_IndexParamVideoPortFormat, 906 &format, sizeof(format)); 907} 908 909status_t ACodec::setupVideoDecoder( 910 const char *mime, int32_t width, int32_t height) { 911 OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused; 912 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { 913 compressionFormat = OMX_VIDEO_CodingAVC; 914 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { 915 compressionFormat = OMX_VIDEO_CodingMPEG4; 916 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) { 917 compressionFormat = OMX_VIDEO_CodingH263; 918 } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG2, mime)) { 919 compressionFormat = OMX_VIDEO_CodingMPEG2; 920 } else { 921 TRESPASS(); 922 } 923 924 status_t err = setVideoPortFormatType( 925 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused); 926 927 if (err != OK) { 928 return err; 929 } 930 931 err = setSupportedOutputFormat(); 932 933 if (err != OK) { 934 return err; 935 } 936 937 err = setVideoFormatOnPort( 938 kPortIndexInput, width, height, compressionFormat); 939 940 if (err != OK) { 941 return err; 942 } 943 944 err = setVideoFormatOnPort( 945 kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused); 946 947 if (err != OK) { 948 return err; 949 } 950 951 return OK; 952} 953 954status_t ACodec::setVideoFormatOnPort( 955 OMX_U32 portIndex, 956 int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) { 957 OMX_PARAM_PORTDEFINITIONTYPE def; 958 InitOMXParams(&def); 959 def.nPortIndex = portIndex; 960 961 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 962 963 status_t err = mOMX->getParameter( 964 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 965 966 CHECK_EQ(err, (status_t)OK); 967 968 if (portIndex == kPortIndexInput) { 969 // XXX Need a (much) better heuristic to compute input buffer sizes. 970 const size_t X = 64 * 1024; 971 if (def.nBufferSize < X) { 972 def.nBufferSize = X; 973 } 974 } 975 976 CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo); 977 978 video_def->nFrameWidth = width; 979 video_def->nFrameHeight = height; 980 981 if (portIndex == kPortIndexInput) { 982 video_def->eCompressionFormat = compressionFormat; 983 video_def->eColorFormat = OMX_COLOR_FormatUnused; 984 } 985 986 err = mOMX->setParameter( 987 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 988 989 return err; 990} 991 992status_t ACodec::initNativeWindow() { 993 if (mNativeWindow != NULL) { 994 return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE); 995 } 996 997 mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE); 998 return OK; 999} 1000 1001bool ACodec::allYourBuffersAreBelongToUs( 1002 OMX_U32 portIndex) { 1003 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 1004 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 1005 1006 if (info->mStatus != BufferInfo::OWNED_BY_US 1007 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) { 1008 LOGV("[%s] Buffer %p on port %ld still has status %d", 1009 mComponentName.c_str(), 1010 info->mBufferID, portIndex, info->mStatus); 1011 return false; 1012 } 1013 } 1014 1015 return true; 1016} 1017 1018bool ACodec::allYourBuffersAreBelongToUs() { 1019 return allYourBuffersAreBelongToUs(kPortIndexInput) 1020 && allYourBuffersAreBelongToUs(kPortIndexOutput); 1021} 1022 1023void ACodec::deferMessage(const sp<AMessage> &msg) { 1024 bool wasEmptyBefore = mDeferredQueue.empty(); 1025 mDeferredQueue.push_back(msg); 1026} 1027 1028void ACodec::processDeferredMessages() { 1029 List<sp<AMessage> > queue = mDeferredQueue; 1030 mDeferredQueue.clear(); 1031 1032 List<sp<AMessage> >::iterator it = queue.begin(); 1033 while (it != queue.end()) { 1034 onMessageReceived(*it++); 1035 } 1036} 1037 1038void ACodec::sendFormatChange() { 1039 sp<AMessage> notify = mNotify->dup(); 1040 notify->setInt32("what", kWhatOutputFormatChanged); 1041 1042 OMX_PARAM_PORTDEFINITIONTYPE def; 1043 InitOMXParams(&def); 1044 def.nPortIndex = kPortIndexOutput; 1045 1046 CHECK_EQ(mOMX->getParameter( 1047 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)), 1048 (status_t)OK); 1049 1050 CHECK_EQ((int)def.eDir, (int)OMX_DirOutput); 1051 1052 switch (def.eDomain) { 1053 case OMX_PortDomainVideo: 1054 { 1055 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video; 1056 1057 notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW); 1058 notify->setInt32("width", videoDef->nFrameWidth); 1059 notify->setInt32("height", videoDef->nFrameHeight); 1060 1061 OMX_CONFIG_RECTTYPE rect; 1062 InitOMXParams(&rect); 1063 rect.nPortIndex = kPortIndexOutput; 1064 1065 if (mOMX->getConfig( 1066 mNode, OMX_IndexConfigCommonOutputCrop, 1067 &rect, sizeof(rect)) != OK) { 1068 rect.nLeft = 0; 1069 rect.nTop = 0; 1070 rect.nWidth = videoDef->nFrameWidth; 1071 rect.nHeight = videoDef->nFrameHeight; 1072 } 1073 1074 CHECK_GE(rect.nLeft, 0); 1075 CHECK_GE(rect.nTop, 0); 1076 CHECK_GE(rect.nWidth, 0u); 1077 CHECK_GE(rect.nHeight, 0u); 1078 CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth); 1079 CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight); 1080 1081 notify->setRect( 1082 "crop", 1083 rect.nLeft, 1084 rect.nTop, 1085 rect.nLeft + rect.nWidth - 1, 1086 rect.nTop + rect.nHeight - 1); 1087 1088 if (mNativeWindow != NULL) { 1089 android_native_rect_t crop; 1090 crop.left = rect.nLeft; 1091 crop.top = rect.nTop; 1092 crop.right = rect.nLeft + rect.nWidth; 1093 crop.bottom = rect.nTop + rect.nHeight; 1094 1095 CHECK_EQ(0, native_window_set_crop( 1096 mNativeWindow.get(), &crop)); 1097 } 1098 break; 1099 } 1100 1101 case OMX_PortDomainAudio: 1102 { 1103 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio; 1104 CHECK_EQ((int)audioDef->eEncoding, (int)OMX_AUDIO_CodingPCM); 1105 1106 OMX_AUDIO_PARAM_PCMMODETYPE params; 1107 InitOMXParams(¶ms); 1108 params.nPortIndex = kPortIndexOutput; 1109 1110 CHECK_EQ(mOMX->getParameter( 1111 mNode, OMX_IndexParamAudioPcm, 1112 ¶ms, sizeof(params)), 1113 (status_t)OK); 1114 1115 CHECK(params.nChannels == 1 || params.bInterleaved); 1116 CHECK_EQ(params.nBitPerSample, 16u); 1117 CHECK_EQ((int)params.eNumData, (int)OMX_NumericalDataSigned); 1118 CHECK_EQ((int)params.ePCMMode, (int)OMX_AUDIO_PCMModeLinear); 1119 1120 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW); 1121 notify->setInt32("channel-count", params.nChannels); 1122 notify->setInt32("sample-rate", params.nSamplingRate); 1123 break; 1124 } 1125 1126 default: 1127 TRESPASS(); 1128 } 1129 1130 notify->post(); 1131 1132 mSentFormat = true; 1133} 1134 1135void ACodec::signalError(OMX_ERRORTYPE error) { 1136 sp<AMessage> notify = mNotify->dup(); 1137 notify->setInt32("what", ACodec::kWhatError); 1138 notify->setInt32("omx-error", error); 1139 notify->post(); 1140} 1141 1142//////////////////////////////////////////////////////////////////////////////// 1143 1144ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState) 1145 : AState(parentState), 1146 mCodec(codec) { 1147} 1148 1149ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(OMX_U32 portIndex) { 1150 return KEEP_BUFFERS; 1151} 1152 1153bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) { 1154 switch (msg->what()) { 1155 case kWhatInputBufferFilled: 1156 { 1157 onInputBufferFilled(msg); 1158 break; 1159 } 1160 1161 case kWhatOutputBufferDrained: 1162 { 1163 onOutputBufferDrained(msg); 1164 break; 1165 } 1166 1167 case ACodec::kWhatOMXMessage: 1168 { 1169 return onOMXMessage(msg); 1170 } 1171 1172 default: 1173 return false; 1174 } 1175 1176 return true; 1177} 1178 1179bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) { 1180 int32_t type; 1181 CHECK(msg->findInt32("type", &type)); 1182 1183 IOMX::node_id nodeID; 1184 CHECK(msg->findPointer("node", &nodeID)); 1185 CHECK_EQ(nodeID, mCodec->mNode); 1186 1187 switch (type) { 1188 case omx_message::EVENT: 1189 { 1190 int32_t event, data1, data2; 1191 CHECK(msg->findInt32("event", &event)); 1192 CHECK(msg->findInt32("data1", &data1)); 1193 CHECK(msg->findInt32("data2", &data2)); 1194 1195 if (event == OMX_EventCmdComplete 1196 && data1 == OMX_CommandFlush 1197 && data2 == (int32_t)OMX_ALL) { 1198 // Use of this notification is not consistent across 1199 // implementations. We'll drop this notification and rely 1200 // on flush-complete notifications on the individual port 1201 // indices instead. 1202 1203 return true; 1204 } 1205 1206 return onOMXEvent( 1207 static_cast<OMX_EVENTTYPE>(event), 1208 static_cast<OMX_U32>(data1), 1209 static_cast<OMX_U32>(data2)); 1210 } 1211 1212 case omx_message::EMPTY_BUFFER_DONE: 1213 { 1214 IOMX::buffer_id bufferID; 1215 CHECK(msg->findPointer("buffer", &bufferID)); 1216 1217 return onOMXEmptyBufferDone(bufferID); 1218 } 1219 1220 case omx_message::FILL_BUFFER_DONE: 1221 { 1222 IOMX::buffer_id bufferID; 1223 CHECK(msg->findPointer("buffer", &bufferID)); 1224 1225 int32_t rangeOffset, rangeLength, flags; 1226 int64_t timeUs; 1227 void *platformPrivate; 1228 void *dataPtr; 1229 1230 CHECK(msg->findInt32("range_offset", &rangeOffset)); 1231 CHECK(msg->findInt32("range_length", &rangeLength)); 1232 CHECK(msg->findInt32("flags", &flags)); 1233 CHECK(msg->findInt64("timestamp", &timeUs)); 1234 CHECK(msg->findPointer("platform_private", &platformPrivate)); 1235 CHECK(msg->findPointer("data_ptr", &dataPtr)); 1236 1237 return onOMXFillBufferDone( 1238 bufferID, 1239 (size_t)rangeOffset, (size_t)rangeLength, 1240 (OMX_U32)flags, 1241 timeUs, 1242 platformPrivate, 1243 dataPtr); 1244 } 1245 1246 default: 1247 TRESPASS(); 1248 break; 1249 } 1250} 1251 1252bool ACodec::BaseState::onOMXEvent( 1253 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 1254 if (event != OMX_EventError) { 1255 LOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)", 1256 mCodec->mComponentName.c_str(), event, data1, data2); 1257 1258 return false; 1259 } 1260 1261 LOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1); 1262 1263 mCodec->signalError((OMX_ERRORTYPE)data1); 1264 1265 return true; 1266} 1267 1268bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) { 1269 LOGV("[%s] onOMXEmptyBufferDone %p", 1270 mCodec->mComponentName.c_str(), bufferID); 1271 1272 BufferInfo *info = 1273 mCodec->findBufferByID(kPortIndexInput, bufferID); 1274 1275 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); 1276 info->mStatus = BufferInfo::OWNED_BY_US; 1277 1278 PortMode mode = getPortMode(kPortIndexInput); 1279 1280 switch (mode) { 1281 case KEEP_BUFFERS: 1282 break; 1283 1284 case RESUBMIT_BUFFERS: 1285 postFillThisBuffer(info); 1286 break; 1287 1288 default: 1289 { 1290 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 1291 TRESPASS(); // Not currently used 1292 break; 1293 } 1294 } 1295 1296 return true; 1297} 1298 1299void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) { 1300 if (mCodec->mPortEOS[kPortIndexInput]) { 1301 return; 1302 } 1303 1304 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 1305 1306 sp<AMessage> notify = mCodec->mNotify->dup(); 1307 notify->setInt32("what", ACodec::kWhatFillThisBuffer); 1308 notify->setPointer("buffer-id", info->mBufferID); 1309 1310 info->mData->meta()->clear(); 1311 notify->setObject("buffer", info->mData); 1312 1313 sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id()); 1314 reply->setPointer("buffer-id", info->mBufferID); 1315 1316 notify->setMessage("reply", reply); 1317 1318 notify->post(); 1319 1320 info->mStatus = BufferInfo::OWNED_BY_UPSTREAM; 1321} 1322 1323void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { 1324 IOMX::buffer_id bufferID; 1325 CHECK(msg->findPointer("buffer-id", &bufferID)); 1326 1327 sp<RefBase> obj; 1328 int32_t err = OK; 1329 if (!msg->findObject("buffer", &obj)) { 1330 CHECK(msg->findInt32("err", &err)); 1331 1332 LOGV("[%s] saw error %d instead of an input buffer", 1333 mCodec->mComponentName.c_str(), err); 1334 1335 obj.clear(); 1336 } 1337 1338 sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get()); 1339 1340 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID); 1341 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM); 1342 1343 info->mStatus = BufferInfo::OWNED_BY_US; 1344 1345 PortMode mode = getPortMode(kPortIndexInput); 1346 1347 switch (mode) { 1348 case KEEP_BUFFERS: 1349 { 1350 if (buffer == NULL) { 1351 if (!mCodec->mPortEOS[kPortIndexInput]) { 1352 mCodec->mPortEOS[kPortIndexInput] = true; 1353 mCodec->mInputEOSResult = err; 1354 } 1355 } 1356 break; 1357 } 1358 1359 case RESUBMIT_BUFFERS: 1360 { 1361 if (buffer != NULL) { 1362 CHECK(!mCodec->mPortEOS[kPortIndexInput]); 1363 1364 int64_t timeUs; 1365 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 1366 1367 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME; 1368 1369 int32_t isCSD; 1370 if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) { 1371 flags |= OMX_BUFFERFLAG_CODECCONFIG; 1372 } 1373 1374 if (buffer != info->mData) { 1375 if (0 && !(flags & OMX_BUFFERFLAG_CODECCONFIG)) { 1376 LOGV("[%s] Needs to copy input data.", 1377 mCodec->mComponentName.c_str()); 1378 } 1379 1380 CHECK_LE(buffer->size(), info->mData->capacity()); 1381 memcpy(info->mData->data(), buffer->data(), buffer->size()); 1382 } 1383 1384 if (flags & OMX_BUFFERFLAG_CODECCONFIG) { 1385 LOGV("[%s] calling emptyBuffer %p w/ codec specific data", 1386 mCodec->mComponentName.c_str(), bufferID); 1387 } else { 1388 LOGV("[%s] calling emptyBuffer %p w/ time %lld us", 1389 mCodec->mComponentName.c_str(), bufferID, timeUs); 1390 } 1391 1392 CHECK_EQ(mCodec->mOMX->emptyBuffer( 1393 mCodec->mNode, 1394 bufferID, 1395 0, 1396 buffer->size(), 1397 flags, 1398 timeUs), 1399 (status_t)OK); 1400 1401 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 1402 1403 getMoreInputDataIfPossible(); 1404 } else if (!mCodec->mPortEOS[kPortIndexInput]) { 1405 if (err != ERROR_END_OF_STREAM) { 1406 LOGV("[%s] Signalling EOS on the input port " 1407 "due to error %d", 1408 mCodec->mComponentName.c_str(), err); 1409 } else { 1410 LOGV("[%s] Signalling EOS on the input port", 1411 mCodec->mComponentName.c_str()); 1412 } 1413 1414 LOGV("[%s] calling emptyBuffer %p signalling EOS", 1415 mCodec->mComponentName.c_str(), bufferID); 1416 1417 CHECK_EQ(mCodec->mOMX->emptyBuffer( 1418 mCodec->mNode, 1419 bufferID, 1420 0, 1421 0, 1422 OMX_BUFFERFLAG_EOS, 1423 0), 1424 (status_t)OK); 1425 1426 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 1427 1428 mCodec->mPortEOS[kPortIndexInput] = true; 1429 mCodec->mInputEOSResult = err; 1430 } 1431 break; 1432 1433 default: 1434 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 1435 break; 1436 } 1437 } 1438} 1439 1440void ACodec::BaseState::getMoreInputDataIfPossible() { 1441 if (mCodec->mPortEOS[kPortIndexInput]) { 1442 return; 1443 } 1444 1445 BufferInfo *eligible = NULL; 1446 1447 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 1448 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 1449 1450#if 0 1451 if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) { 1452 // There's already a "read" pending. 1453 return; 1454 } 1455#endif 1456 1457 if (info->mStatus == BufferInfo::OWNED_BY_US) { 1458 eligible = info; 1459 } 1460 } 1461 1462 if (eligible == NULL) { 1463 return; 1464 } 1465 1466 postFillThisBuffer(eligible); 1467} 1468 1469bool ACodec::BaseState::onOMXFillBufferDone( 1470 IOMX::buffer_id bufferID, 1471 size_t rangeOffset, size_t rangeLength, 1472 OMX_U32 flags, 1473 int64_t timeUs, 1474 void *platformPrivate, 1475 void *dataPtr) { 1476 LOGV("[%s] onOMXFillBufferDone %p time %lld us", 1477 mCodec->mComponentName.c_str(), bufferID, timeUs); 1478 1479 ssize_t index; 1480 BufferInfo *info = 1481 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 1482 1483 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT); 1484 1485 info->mStatus = BufferInfo::OWNED_BY_US; 1486 1487 PortMode mode = getPortMode(kPortIndexOutput); 1488 1489 switch (mode) { 1490 case KEEP_BUFFERS: 1491 break; 1492 1493 case RESUBMIT_BUFFERS: 1494 { 1495 if (rangeLength == 0) { 1496 if (!(flags & OMX_BUFFERFLAG_EOS)) { 1497 LOGV("[%s] calling fillBuffer %p", 1498 mCodec->mComponentName.c_str(), info->mBufferID); 1499 1500 CHECK_EQ(mCodec->mOMX->fillBuffer( 1501 mCodec->mNode, info->mBufferID), 1502 (status_t)OK); 1503 1504 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 1505 } 1506 } else { 1507 if (!mCodec->mSentFormat) { 1508 mCodec->sendFormatChange(); 1509 } 1510 1511 if (mCodec->mNativeWindow == NULL) { 1512 info->mData->setRange(rangeOffset, rangeLength); 1513 } 1514 1515 info->mData->meta()->setInt64("timeUs", timeUs); 1516 1517 sp<AMessage> notify = mCodec->mNotify->dup(); 1518 notify->setInt32("what", ACodec::kWhatDrainThisBuffer); 1519 notify->setPointer("buffer-id", info->mBufferID); 1520 notify->setObject("buffer", info->mData); 1521 1522 sp<AMessage> reply = 1523 new AMessage(kWhatOutputBufferDrained, mCodec->id()); 1524 1525 reply->setPointer("buffer-id", info->mBufferID); 1526 1527 notify->setMessage("reply", reply); 1528 1529 notify->post(); 1530 1531 info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM; 1532 } 1533 1534 if (flags & OMX_BUFFERFLAG_EOS) { 1535 sp<AMessage> notify = mCodec->mNotify->dup(); 1536 notify->setInt32("what", ACodec::kWhatEOS); 1537 notify->setInt32("err", mCodec->mInputEOSResult); 1538 notify->post(); 1539 1540 mCodec->mPortEOS[kPortIndexOutput] = true; 1541 } 1542 break; 1543 } 1544 1545 default: 1546 { 1547 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 1548 1549 CHECK_EQ((status_t)OK, 1550 mCodec->freeBuffer(kPortIndexOutput, index)); 1551 break; 1552 } 1553 } 1554 1555 return true; 1556} 1557 1558void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { 1559 IOMX::buffer_id bufferID; 1560 CHECK(msg->findPointer("buffer-id", &bufferID)); 1561 1562 ssize_t index; 1563 BufferInfo *info = 1564 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 1565 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM); 1566 1567 int32_t render; 1568 if (mCodec->mNativeWindow != NULL 1569 && msg->findInt32("render", &render) && render != 0) { 1570 // The client wants this buffer to be rendered. 1571 1572 if (mCodec->mNativeWindow->queueBuffer( 1573 mCodec->mNativeWindow.get(), 1574 info->mGraphicBuffer.get()) == OK) { 1575 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 1576 } else { 1577 mCodec->signalError(); 1578 info->mStatus = BufferInfo::OWNED_BY_US; 1579 } 1580 } else { 1581 info->mStatus = BufferInfo::OWNED_BY_US; 1582 } 1583 1584 PortMode mode = getPortMode(kPortIndexOutput); 1585 1586 switch (mode) { 1587 case KEEP_BUFFERS: 1588 { 1589 // XXX fishy, revisit!!! What about the FREE_BUFFERS case below? 1590 1591 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 1592 // We cannot resubmit the buffer we just rendered, dequeue 1593 // the spare instead. 1594 1595 info = mCodec->dequeueBufferFromNativeWindow(); 1596 } 1597 break; 1598 } 1599 1600 case RESUBMIT_BUFFERS: 1601 { 1602 if (!mCodec->mPortEOS[kPortIndexOutput]) { 1603 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 1604 // We cannot resubmit the buffer we just rendered, dequeue 1605 // the spare instead. 1606 1607 info = mCodec->dequeueBufferFromNativeWindow(); 1608 } 1609 1610 if (info != NULL) { 1611 LOGV("[%s] calling fillBuffer %p", 1612 mCodec->mComponentName.c_str(), info->mBufferID); 1613 1614 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), 1615 (status_t)OK); 1616 1617 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 1618 } 1619 } 1620 break; 1621 } 1622 1623 default: 1624 { 1625 CHECK_EQ((int)mode, (int)FREE_BUFFERS); 1626 1627 CHECK_EQ((status_t)OK, 1628 mCodec->freeBuffer(kPortIndexOutput, index)); 1629 break; 1630 } 1631 } 1632} 1633 1634//////////////////////////////////////////////////////////////////////////////// 1635 1636ACodec::UninitializedState::UninitializedState(ACodec *codec) 1637 : BaseState(codec) { 1638} 1639 1640bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) { 1641 bool handled = false; 1642 1643 switch (msg->what()) { 1644 case ACodec::kWhatSetup: 1645 { 1646 onSetup(msg); 1647 1648 handled = true; 1649 break; 1650 } 1651 1652 case ACodec::kWhatShutdown: 1653 { 1654 sp<AMessage> notify = mCodec->mNotify->dup(); 1655 notify->setInt32("what", ACodec::kWhatShutdownCompleted); 1656 notify->post(); 1657 1658 handled = true; 1659 break; 1660 } 1661 1662 case ACodec::kWhatFlush: 1663 { 1664 sp<AMessage> notify = mCodec->mNotify->dup(); 1665 notify->setInt32("what", ACodec::kWhatFlushCompleted); 1666 notify->post(); 1667 1668 handled = true; 1669 break; 1670 } 1671 1672 default: 1673 return BaseState::onMessageReceived(msg); 1674 } 1675 1676 return handled; 1677} 1678 1679void ACodec::UninitializedState::onSetup( 1680 const sp<AMessage> &msg) { 1681 OMXClient client; 1682 CHECK_EQ(client.connect(), (status_t)OK); 1683 1684 sp<IOMX> omx = client.interface(); 1685 1686 AString mime; 1687 CHECK(msg->findString("mime", &mime)); 1688 1689 Vector<String8> matchingCodecs; 1690 OMXCodec::findMatchingCodecs( 1691 mime.c_str(), 1692 false, // createEncoder 1693 NULL, // matchComponentName 1694 0, // flags 1695 &matchingCodecs); 1696 1697 sp<CodecObserver> observer = new CodecObserver; 1698 IOMX::node_id node = NULL; 1699 1700 AString componentName; 1701 1702 for (size_t matchIndex = 0; matchIndex < matchingCodecs.size(); 1703 ++matchIndex) { 1704 componentName = matchingCodecs.itemAt(matchIndex).string(); 1705 1706 pid_t tid = androidGetTid(); 1707 int prevPriority = androidGetThreadPriority(tid); 1708 androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND); 1709 status_t err = omx->allocateNode(componentName.c_str(), observer, &node); 1710 androidSetThreadPriority(tid, prevPriority); 1711 1712 if (err == OK) { 1713 break; 1714 } 1715 1716 node = NULL; 1717 } 1718 1719 if (node == NULL) { 1720 LOGE("Unable to instantiate a decoder for type '%s'.", mime.c_str()); 1721 1722 mCodec->signalError(OMX_ErrorComponentNotFound); 1723 return; 1724 } 1725 1726 sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id()); 1727 observer->setNotificationMessage(notify); 1728 1729 mCodec->mComponentName = componentName; 1730 mCodec->mOMX = omx; 1731 mCodec->mNode = node; 1732 1733 mCodec->mPortEOS[kPortIndexInput] = 1734 mCodec->mPortEOS[kPortIndexOutput] = false; 1735 1736 mCodec->mInputEOSResult = OK; 1737 1738 mCodec->configureCodec(mime.c_str(), msg); 1739 1740 sp<RefBase> obj; 1741 if (msg->findObject("native-window", &obj) 1742 && strncmp("OMX.google.", componentName.c_str(), 11)) { 1743 sp<NativeWindowWrapper> nativeWindow( 1744 static_cast<NativeWindowWrapper *>(obj.get())); 1745 CHECK(nativeWindow != NULL); 1746 mCodec->mNativeWindow = nativeWindow->getNativeWindow(); 1747 } 1748 1749 CHECK_EQ((status_t)OK, mCodec->initNativeWindow()); 1750 1751 CHECK_EQ(omx->sendCommand(node, OMX_CommandStateSet, OMX_StateIdle), 1752 (status_t)OK); 1753 1754 mCodec->changeState(mCodec->mLoadedToIdleState); 1755} 1756 1757//////////////////////////////////////////////////////////////////////////////// 1758 1759ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec) 1760 : BaseState(codec) { 1761} 1762 1763void ACodec::LoadedToIdleState::stateEntered() { 1764 LOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str()); 1765 1766 status_t err; 1767 if ((err = allocateBuffers()) != OK) { 1768 LOGE("Failed to allocate buffers after transitioning to IDLE state " 1769 "(error 0x%08x)", 1770 err); 1771 1772 mCodec->signalError(); 1773 } 1774} 1775 1776status_t ACodec::LoadedToIdleState::allocateBuffers() { 1777 status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput); 1778 1779 if (err != OK) { 1780 return err; 1781 } 1782 1783 return mCodec->allocateBuffersOnPort(kPortIndexOutput); 1784} 1785 1786bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) { 1787 switch (msg->what()) { 1788 case kWhatShutdown: 1789 { 1790 mCodec->deferMessage(msg); 1791 return true; 1792 } 1793 1794 default: 1795 return BaseState::onMessageReceived(msg); 1796 } 1797} 1798 1799bool ACodec::LoadedToIdleState::onOMXEvent( 1800 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 1801 switch (event) { 1802 case OMX_EventCmdComplete: 1803 { 1804 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 1805 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); 1806 1807 CHECK_EQ(mCodec->mOMX->sendCommand( 1808 mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting), 1809 (status_t)OK); 1810 1811 mCodec->changeState(mCodec->mIdleToExecutingState); 1812 1813 return true; 1814 } 1815 1816 default: 1817 return BaseState::onOMXEvent(event, data1, data2); 1818 } 1819} 1820 1821//////////////////////////////////////////////////////////////////////////////// 1822 1823ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec) 1824 : BaseState(codec) { 1825} 1826 1827void ACodec::IdleToExecutingState::stateEntered() { 1828 LOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str()); 1829} 1830 1831bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) { 1832 switch (msg->what()) { 1833 case kWhatShutdown: 1834 { 1835 mCodec->deferMessage(msg); 1836 return true; 1837 } 1838 1839 default: 1840 return BaseState::onMessageReceived(msg); 1841 } 1842} 1843 1844bool ACodec::IdleToExecutingState::onOMXEvent( 1845 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 1846 switch (event) { 1847 case OMX_EventCmdComplete: 1848 { 1849 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 1850 CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting); 1851 1852 mCodec->mExecutingState->resume(); 1853 mCodec->changeState(mCodec->mExecutingState); 1854 1855 return true; 1856 } 1857 1858 default: 1859 return BaseState::onOMXEvent(event, data1, data2); 1860 } 1861} 1862 1863//////////////////////////////////////////////////////////////////////////////// 1864 1865ACodec::ExecutingState::ExecutingState(ACodec *codec) 1866 : BaseState(codec), 1867 mActive(false) { 1868} 1869 1870ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode( 1871 OMX_U32 portIndex) { 1872 return RESUBMIT_BUFFERS; 1873} 1874 1875void ACodec::ExecutingState::submitOutputBuffers() { 1876 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) { 1877 BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i); 1878 1879 if (mCodec->mNativeWindow != NULL) { 1880 CHECK(info->mStatus == BufferInfo::OWNED_BY_US 1881 || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW); 1882 1883 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 1884 continue; 1885 } 1886 1887 status_t err = mCodec->mNativeWindow->lockBuffer( 1888 mCodec->mNativeWindow.get(), 1889 info->mGraphicBuffer.get()); 1890 CHECK_EQ(err, (status_t)OK); 1891 } else { 1892 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 1893 } 1894 1895 LOGV("[%s] calling fillBuffer %p", 1896 mCodec->mComponentName.c_str(), info->mBufferID); 1897 1898 CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID), 1899 (status_t)OK); 1900 1901 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 1902 } 1903} 1904 1905void ACodec::ExecutingState::resume() { 1906 if (mActive) { 1907 LOGV("[%s] We're already active, no need to resume.", 1908 mCodec->mComponentName.c_str()); 1909 1910 return; 1911 } 1912 1913 submitOutputBuffers(); 1914 1915 // Post the first input buffer. 1916 CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u); 1917 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0); 1918 1919 postFillThisBuffer(info); 1920 1921 mActive = true; 1922} 1923 1924void ACodec::ExecutingState::stateEntered() { 1925 LOGV("[%s] Now Executing", mCodec->mComponentName.c_str()); 1926 1927 mCodec->processDeferredMessages(); 1928} 1929 1930bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) { 1931 bool handled = false; 1932 1933 switch (msg->what()) { 1934 case kWhatShutdown: 1935 { 1936 mActive = false; 1937 1938 CHECK_EQ(mCodec->mOMX->sendCommand( 1939 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle), 1940 (status_t)OK); 1941 1942 mCodec->changeState(mCodec->mExecutingToIdleState); 1943 1944 handled = true; 1945 break; 1946 } 1947 1948 case kWhatFlush: 1949 { 1950 mActive = false; 1951 1952 CHECK_EQ(mCodec->mOMX->sendCommand( 1953 mCodec->mNode, OMX_CommandFlush, OMX_ALL), 1954 (status_t)OK); 1955 1956 mCodec->changeState(mCodec->mFlushingState); 1957 1958 handled = true; 1959 break; 1960 } 1961 1962 case kWhatResume: 1963 { 1964 resume(); 1965 1966 handled = true; 1967 break; 1968 } 1969 1970 default: 1971 handled = BaseState::onMessageReceived(msg); 1972 break; 1973 } 1974 1975 return handled; 1976} 1977 1978bool ACodec::ExecutingState::onOMXEvent( 1979 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 1980 switch (event) { 1981 case OMX_EventPortSettingsChanged: 1982 { 1983 CHECK_EQ(data1, (OMX_U32)kPortIndexOutput); 1984 1985 if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) { 1986 CHECK_EQ(mCodec->mOMX->sendCommand( 1987 mCodec->mNode, 1988 OMX_CommandPortDisable, kPortIndexOutput), 1989 (status_t)OK); 1990 1991 mCodec->freeOutputBuffersNotOwnedByComponent(); 1992 1993 mCodec->changeState(mCodec->mOutputPortSettingsChangedState); 1994 } else if (data2 == OMX_IndexConfigCommonOutputCrop) { 1995 mCodec->mSentFormat = false; 1996 } else { 1997 LOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx", 1998 mCodec->mComponentName.c_str(), data2); 1999 } 2000 2001 return true; 2002 } 2003 2004 case OMX_EventBufferFlag: 2005 { 2006 return true; 2007 } 2008 2009 default: 2010 return BaseState::onOMXEvent(event, data1, data2); 2011 } 2012} 2013 2014//////////////////////////////////////////////////////////////////////////////// 2015 2016ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState( 2017 ACodec *codec) 2018 : BaseState(codec) { 2019} 2020 2021ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode( 2022 OMX_U32 portIndex) { 2023 if (portIndex == kPortIndexOutput) { 2024 return FREE_BUFFERS; 2025 } 2026 2027 CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput); 2028 2029 return RESUBMIT_BUFFERS; 2030} 2031 2032bool ACodec::OutputPortSettingsChangedState::onMessageReceived( 2033 const sp<AMessage> &msg) { 2034 bool handled = false; 2035 2036 switch (msg->what()) { 2037 case kWhatFlush: 2038 case kWhatShutdown: 2039 case kWhatResume: 2040 { 2041 if (msg->what() == kWhatResume) { 2042 LOGV("[%s] Deferring resume", mCodec->mComponentName.c_str()); 2043 } 2044 2045 mCodec->deferMessage(msg); 2046 handled = true; 2047 break; 2048 } 2049 2050 default: 2051 handled = BaseState::onMessageReceived(msg); 2052 break; 2053 } 2054 2055 return handled; 2056} 2057 2058void ACodec::OutputPortSettingsChangedState::stateEntered() { 2059 LOGV("[%s] Now handling output port settings change", 2060 mCodec->mComponentName.c_str()); 2061} 2062 2063bool ACodec::OutputPortSettingsChangedState::onOMXEvent( 2064 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 2065 switch (event) { 2066 case OMX_EventCmdComplete: 2067 { 2068 if (data1 == (OMX_U32)OMX_CommandPortDisable) { 2069 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput); 2070 2071 LOGV("[%s] Output port now disabled.", 2072 mCodec->mComponentName.c_str()); 2073 2074 CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty()); 2075 mCodec->mDealer[kPortIndexOutput].clear(); 2076 2077 CHECK_EQ(mCodec->mOMX->sendCommand( 2078 mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput), 2079 (status_t)OK); 2080 2081 status_t err; 2082 if ((err = mCodec->allocateBuffersOnPort( 2083 kPortIndexOutput)) != OK) { 2084 LOGE("Failed to allocate output port buffers after " 2085 "port reconfiguration (error 0x%08x)", 2086 err); 2087 2088 mCodec->signalError(); 2089 } 2090 2091 return true; 2092 } else if (data1 == (OMX_U32)OMX_CommandPortEnable) { 2093 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput); 2094 2095 mCodec->mSentFormat = false; 2096 2097 LOGV("[%s] Output port now reenabled.", 2098 mCodec->mComponentName.c_str()); 2099 2100 if (mCodec->mExecutingState->active()) { 2101 mCodec->mExecutingState->submitOutputBuffers(); 2102 } 2103 2104 mCodec->changeState(mCodec->mExecutingState); 2105 2106 return true; 2107 } 2108 2109 return false; 2110 } 2111 2112 default: 2113 return false; 2114 } 2115} 2116 2117//////////////////////////////////////////////////////////////////////////////// 2118 2119ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec) 2120 : BaseState(codec) { 2121} 2122 2123bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) { 2124 bool handled = false; 2125 2126 switch (msg->what()) { 2127 case kWhatFlush: 2128 { 2129 // Don't send me a flush request if you previously wanted me 2130 // to shutdown. 2131 TRESPASS(); 2132 break; 2133 } 2134 2135 case kWhatShutdown: 2136 { 2137 // We're already doing that... 2138 2139 handled = true; 2140 break; 2141 } 2142 2143 default: 2144 handled = BaseState::onMessageReceived(msg); 2145 break; 2146 } 2147 2148 return handled; 2149} 2150 2151void ACodec::ExecutingToIdleState::stateEntered() { 2152 LOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str()); 2153 2154 mCodec->mSentFormat = false; 2155} 2156 2157bool ACodec::ExecutingToIdleState::onOMXEvent( 2158 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 2159 switch (event) { 2160 case OMX_EventCmdComplete: 2161 { 2162 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 2163 CHECK_EQ(data2, (OMX_U32)OMX_StateIdle); 2164 2165 changeStateIfWeOwnAllBuffers(); 2166 2167 return true; 2168 } 2169 2170 case OMX_EventPortSettingsChanged: 2171 case OMX_EventBufferFlag: 2172 { 2173 // We're shutting down and don't care about this anymore. 2174 return true; 2175 } 2176 2177 default: 2178 return BaseState::onOMXEvent(event, data1, data2); 2179 } 2180} 2181 2182void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() { 2183 if (mCodec->allYourBuffersAreBelongToUs()) { 2184 CHECK_EQ(mCodec->mOMX->sendCommand( 2185 mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded), 2186 (status_t)OK); 2187 2188 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK); 2189 CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK); 2190 2191 mCodec->changeState(mCodec->mIdleToLoadedState); 2192 } 2193} 2194 2195void ACodec::ExecutingToIdleState::onInputBufferFilled( 2196 const sp<AMessage> &msg) { 2197 BaseState::onInputBufferFilled(msg); 2198 2199 changeStateIfWeOwnAllBuffers(); 2200} 2201 2202void ACodec::ExecutingToIdleState::onOutputBufferDrained( 2203 const sp<AMessage> &msg) { 2204 BaseState::onOutputBufferDrained(msg); 2205 2206 changeStateIfWeOwnAllBuffers(); 2207} 2208 2209//////////////////////////////////////////////////////////////////////////////// 2210 2211ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec) 2212 : BaseState(codec) { 2213} 2214 2215bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) { 2216 bool handled = false; 2217 2218 switch (msg->what()) { 2219 case kWhatShutdown: 2220 { 2221 // We're already doing that... 2222 2223 handled = true; 2224 break; 2225 } 2226 2227 case kWhatFlush: 2228 { 2229 // Don't send me a flush request if you previously wanted me 2230 // to shutdown. 2231 TRESPASS(); 2232 break; 2233 } 2234 2235 default: 2236 handled = BaseState::onMessageReceived(msg); 2237 break; 2238 } 2239 2240 return handled; 2241} 2242 2243void ACodec::IdleToLoadedState::stateEntered() { 2244 LOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str()); 2245} 2246 2247bool ACodec::IdleToLoadedState::onOMXEvent( 2248 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 2249 switch (event) { 2250 case OMX_EventCmdComplete: 2251 { 2252 CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet); 2253 CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded); 2254 2255 LOGV("[%s] Now Loaded", mCodec->mComponentName.c_str()); 2256 2257 CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK); 2258 2259 mCodec->mNativeWindow.clear(); 2260 mCodec->mNode = NULL; 2261 mCodec->mOMX.clear(); 2262 mCodec->mComponentName.clear(); 2263 2264 mCodec->changeState(mCodec->mUninitializedState); 2265 2266 sp<AMessage> notify = mCodec->mNotify->dup(); 2267 notify->setInt32("what", ACodec::kWhatShutdownCompleted); 2268 notify->post(); 2269 2270 return true; 2271 } 2272 2273 default: 2274 return BaseState::onOMXEvent(event, data1, data2); 2275 } 2276} 2277 2278//////////////////////////////////////////////////////////////////////////////// 2279 2280ACodec::FlushingState::FlushingState(ACodec *codec) 2281 : BaseState(codec) { 2282} 2283 2284void ACodec::FlushingState::stateEntered() { 2285 LOGV("[%s] Now Flushing", mCodec->mComponentName.c_str()); 2286 2287 mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false; 2288} 2289 2290bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) { 2291 bool handled = false; 2292 2293 switch (msg->what()) { 2294 case kWhatShutdown: 2295 { 2296 mCodec->deferMessage(msg); 2297 break; 2298 } 2299 2300 case kWhatFlush: 2301 { 2302 // We're already doing this right now. 2303 handled = true; 2304 break; 2305 } 2306 2307 default: 2308 handled = BaseState::onMessageReceived(msg); 2309 break; 2310 } 2311 2312 return handled; 2313} 2314 2315bool ACodec::FlushingState::onOMXEvent( 2316 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 2317 switch (event) { 2318 case OMX_EventCmdComplete: 2319 { 2320 CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush); 2321 2322 if (data2 == kPortIndexInput || data2 == kPortIndexOutput) { 2323 CHECK(!mFlushComplete[data2]); 2324 mFlushComplete[data2] = true; 2325 2326 if (mFlushComplete[kPortIndexInput] 2327 && mFlushComplete[kPortIndexOutput]) { 2328 changeStateIfWeOwnAllBuffers(); 2329 } 2330 } else { 2331 CHECK_EQ(data2, OMX_ALL); 2332 CHECK(mFlushComplete[kPortIndexInput]); 2333 CHECK(mFlushComplete[kPortIndexOutput]); 2334 2335 changeStateIfWeOwnAllBuffers(); 2336 } 2337 2338 return true; 2339 } 2340 2341 case OMX_EventPortSettingsChanged: 2342 { 2343 sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id()); 2344 msg->setInt32("type", omx_message::EVENT); 2345 msg->setPointer("node", mCodec->mNode); 2346 msg->setInt32("event", event); 2347 msg->setInt32("data1", data1); 2348 msg->setInt32("data2", data2); 2349 2350 LOGV("[%s] Deferring OMX_EventPortSettingsChanged", 2351 mCodec->mComponentName.c_str()); 2352 2353 mCodec->deferMessage(msg); 2354 2355 return true; 2356 } 2357 2358 default: 2359 return BaseState::onOMXEvent(event, data1, data2); 2360 } 2361 2362 return true; 2363} 2364 2365void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) { 2366 BaseState::onOutputBufferDrained(msg); 2367 2368 changeStateIfWeOwnAllBuffers(); 2369} 2370 2371void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) { 2372 BaseState::onInputBufferFilled(msg); 2373 2374 changeStateIfWeOwnAllBuffers(); 2375} 2376 2377void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() { 2378 if (mFlushComplete[kPortIndexInput] 2379 && mFlushComplete[kPortIndexOutput] 2380 && mCodec->allYourBuffersAreBelongToUs()) { 2381 sp<AMessage> notify = mCodec->mNotify->dup(); 2382 notify->setInt32("what", ACodec::kWhatFlushCompleted); 2383 notify->post(); 2384 2385 mCodec->mPortEOS[kPortIndexInput] = 2386 mCodec->mPortEOS[kPortIndexOutput] = false; 2387 2388 mCodec->mInputEOSResult = OK; 2389 2390 mCodec->changeState(mCodec->mExecutingState); 2391 } 2392} 2393 2394} // namespace android 2395