ACodec.cpp revision dabb051cf03b5ccc994c769a1cd23f9e6c378dee
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#ifdef __LP64__ 21#define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS 22#endif 23 24#include <inttypes.h> 25#include <utils/Trace.h> 26 27#include <gui/Surface.h> 28 29#include <media/stagefright/ACodec.h> 30 31#include <binder/MemoryDealer.h> 32 33#include <media/stagefright/foundation/hexdump.h> 34#include <media/stagefright/foundation/ABuffer.h> 35#include <media/stagefright/foundation/ADebug.h> 36#include <media/stagefright/foundation/AMessage.h> 37#include <media/stagefright/foundation/AUtils.h> 38 39#include <media/stagefright/BufferProducerWrapper.h> 40#include <media/stagefright/MediaCodec.h> 41#include <media/stagefright/MediaCodecList.h> 42#include <media/stagefright/MediaDefs.h> 43#include <media/stagefright/OMXClient.h> 44#include <media/stagefright/PersistentSurface.h> 45#include <media/stagefright/SurfaceUtils.h> 46#include <media/hardware/HardwareAPI.h> 47 48#include <OMX_AudioExt.h> 49#include <OMX_VideoExt.h> 50#include <OMX_Component.h> 51#include <OMX_IndexExt.h> 52#include <OMX_AsString.h> 53 54#include "include/avc_utils.h" 55#include "omx/OMXUtils.h" 56 57namespace android { 58 59enum { 60 kMaxIndicesToCheck = 32, // used when enumerating supported formats and profiles 61}; 62 63// OMX errors are directly mapped into status_t range if 64// there is no corresponding MediaError status code. 65// Use the statusFromOMXError(int32_t omxError) function. 66// 67// Currently this is a direct map. 68// See frameworks/native/include/media/openmax/OMX_Core.h 69// 70// Vendor OMX errors from 0x90000000 - 0x9000FFFF 71// Extension OMX errors from 0x8F000000 - 0x90000000 72// Standard OMX errors from 0x80001000 - 0x80001024 (0x80001024 current) 73// 74 75// returns true if err is a recognized OMX error code. 76// as OMX error is OMX_S32, this is an int32_t type 77static inline bool isOMXError(int32_t err) { 78 return (ERROR_CODEC_MIN <= err && err <= ERROR_CODEC_MAX); 79} 80 81// converts an OMX error to a status_t 82static inline status_t statusFromOMXError(int32_t omxError) { 83 switch (omxError) { 84 case OMX_ErrorInvalidComponentName: 85 case OMX_ErrorComponentNotFound: 86 return NAME_NOT_FOUND; // can trigger illegal argument error for provided names. 87 default: 88 return isOMXError(omxError) ? omxError : 0; // no translation required 89 } 90} 91 92// checks and converts status_t to a non-side-effect status_t 93static inline status_t makeNoSideEffectStatus(status_t err) { 94 switch (err) { 95 // the following errors have side effects and may come 96 // from other code modules. Remap for safety reasons. 97 case INVALID_OPERATION: 98 case DEAD_OBJECT: 99 return UNKNOWN_ERROR; 100 default: 101 return err; 102 } 103} 104 105struct MessageList : public RefBase { 106 MessageList() { 107 } 108 virtual ~MessageList() { 109 } 110 std::list<sp<AMessage> > &getList() { return mList; } 111private: 112 std::list<sp<AMessage> > mList; 113 114 DISALLOW_EVIL_CONSTRUCTORS(MessageList); 115}; 116 117struct CodecObserver : public BnOMXObserver { 118 CodecObserver() {} 119 120 void setNotificationMessage(const sp<AMessage> &msg) { 121 mNotify = msg; 122 } 123 124 // from IOMXObserver 125 virtual void onMessages(const std::list<omx_message> &messages) { 126 if (messages.empty()) { 127 return; 128 } 129 130 sp<AMessage> notify = mNotify->dup(); 131 bool first = true; 132 sp<MessageList> msgList = new MessageList(); 133 for (std::list<omx_message>::const_iterator it = messages.cbegin(); 134 it != messages.cend(); ++it) { 135 const omx_message &omx_msg = *it; 136 if (first) { 137 notify->setInt32("node", omx_msg.node); 138 first = false; 139 } 140 141 sp<AMessage> msg = new AMessage; 142 msg->setInt32("type", omx_msg.type); 143 switch (omx_msg.type) { 144 case omx_message::EVENT: 145 { 146 msg->setInt32("event", omx_msg.u.event_data.event); 147 msg->setInt32("data1", omx_msg.u.event_data.data1); 148 msg->setInt32("data2", omx_msg.u.event_data.data2); 149 break; 150 } 151 152 case omx_message::EMPTY_BUFFER_DONE: 153 { 154 msg->setInt32("buffer", omx_msg.u.buffer_data.buffer); 155 msg->setInt32("fence_fd", omx_msg.fenceFd); 156 break; 157 } 158 159 case omx_message::FILL_BUFFER_DONE: 160 { 161 msg->setInt32( 162 "buffer", omx_msg.u.extended_buffer_data.buffer); 163 msg->setInt32( 164 "range_offset", 165 omx_msg.u.extended_buffer_data.range_offset); 166 msg->setInt32( 167 "range_length", 168 omx_msg.u.extended_buffer_data.range_length); 169 msg->setInt32( 170 "flags", 171 omx_msg.u.extended_buffer_data.flags); 172 msg->setInt64( 173 "timestamp", 174 omx_msg.u.extended_buffer_data.timestamp); 175 msg->setInt32( 176 "fence_fd", omx_msg.fenceFd); 177 break; 178 } 179 180 case omx_message::FRAME_RENDERED: 181 { 182 msg->setInt64( 183 "media_time_us", omx_msg.u.render_data.timestamp); 184 msg->setInt64( 185 "system_nano", omx_msg.u.render_data.nanoTime); 186 break; 187 } 188 189 default: 190 ALOGE("Unrecognized message type: %d", omx_msg.type); 191 break; 192 } 193 msgList->getList().push_back(msg); 194 } 195 notify->setObject("messages", msgList); 196 notify->post(); 197 } 198 199protected: 200 virtual ~CodecObserver() {} 201 202private: 203 sp<AMessage> mNotify; 204 205 DISALLOW_EVIL_CONSTRUCTORS(CodecObserver); 206}; 207 208//////////////////////////////////////////////////////////////////////////////// 209 210struct ACodec::BaseState : public AState { 211 BaseState(ACodec *codec, const sp<AState> &parentState = NULL); 212 213protected: 214 enum PortMode { 215 KEEP_BUFFERS, 216 RESUBMIT_BUFFERS, 217 FREE_BUFFERS, 218 }; 219 220 ACodec *mCodec; 221 222 virtual PortMode getPortMode(OMX_U32 portIndex); 223 224 virtual bool onMessageReceived(const sp<AMessage> &msg); 225 226 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 227 228 virtual void onOutputBufferDrained(const sp<AMessage> &msg); 229 virtual void onInputBufferFilled(const sp<AMessage> &msg); 230 231 void postFillThisBuffer(BufferInfo *info); 232 233private: 234 // Handles an OMX message. Returns true iff message was handled. 235 bool onOMXMessage(const sp<AMessage> &msg); 236 237 // Handles a list of messages. Returns true iff messages were handled. 238 bool onOMXMessageList(const sp<AMessage> &msg); 239 240 // returns true iff this message is for this component and the component is alive 241 bool checkOMXMessage(const sp<AMessage> &msg); 242 243 bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID, int fenceFd); 244 245 bool onOMXFillBufferDone( 246 IOMX::buffer_id bufferID, 247 size_t rangeOffset, size_t rangeLength, 248 OMX_U32 flags, 249 int64_t timeUs, 250 int fenceFd); 251 252 virtual bool onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano); 253 254 void getMoreInputDataIfPossible(); 255 256 DISALLOW_EVIL_CONSTRUCTORS(BaseState); 257}; 258 259//////////////////////////////////////////////////////////////////////////////// 260 261struct ACodec::DeathNotifier : public IBinder::DeathRecipient { 262 DeathNotifier(const sp<AMessage> ¬ify) 263 : mNotify(notify) { 264 } 265 266 virtual void binderDied(const wp<IBinder> &) { 267 mNotify->post(); 268 } 269 270protected: 271 virtual ~DeathNotifier() {} 272 273private: 274 sp<AMessage> mNotify; 275 276 DISALLOW_EVIL_CONSTRUCTORS(DeathNotifier); 277}; 278 279struct ACodec::UninitializedState : public ACodec::BaseState { 280 UninitializedState(ACodec *codec); 281 282protected: 283 virtual bool onMessageReceived(const sp<AMessage> &msg); 284 virtual void stateEntered(); 285 286private: 287 void onSetup(const sp<AMessage> &msg); 288 bool onAllocateComponent(const sp<AMessage> &msg); 289 290 sp<DeathNotifier> mDeathNotifier; 291 292 DISALLOW_EVIL_CONSTRUCTORS(UninitializedState); 293}; 294 295//////////////////////////////////////////////////////////////////////////////// 296 297struct ACodec::LoadedState : public ACodec::BaseState { 298 LoadedState(ACodec *codec); 299 300protected: 301 virtual bool onMessageReceived(const sp<AMessage> &msg); 302 virtual void stateEntered(); 303 304private: 305 friend struct ACodec::UninitializedState; 306 307 bool onConfigureComponent(const sp<AMessage> &msg); 308 void onCreateInputSurface(const sp<AMessage> &msg); 309 void onSetInputSurface(const sp<AMessage> &msg); 310 void onStart(); 311 void onShutdown(bool keepComponentAllocated); 312 313 status_t setupInputSurface(); 314 315 DISALLOW_EVIL_CONSTRUCTORS(LoadedState); 316}; 317 318//////////////////////////////////////////////////////////////////////////////// 319 320struct ACodec::LoadedToIdleState : public ACodec::BaseState { 321 LoadedToIdleState(ACodec *codec); 322 323protected: 324 virtual bool onMessageReceived(const sp<AMessage> &msg); 325 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 326 virtual void stateEntered(); 327 328private: 329 status_t allocateBuffers(); 330 331 DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState); 332}; 333 334//////////////////////////////////////////////////////////////////////////////// 335 336struct ACodec::IdleToExecutingState : public ACodec::BaseState { 337 IdleToExecutingState(ACodec *codec); 338 339protected: 340 virtual bool onMessageReceived(const sp<AMessage> &msg); 341 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 342 virtual void stateEntered(); 343 344private: 345 DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState); 346}; 347 348//////////////////////////////////////////////////////////////////////////////// 349 350struct ACodec::ExecutingState : public ACodec::BaseState { 351 ExecutingState(ACodec *codec); 352 353 void submitRegularOutputBuffers(); 354 void submitOutputMetaBuffers(); 355 void submitOutputBuffers(); 356 357 // Submit output buffers to the decoder, submit input buffers to client 358 // to fill with data. 359 void resume(); 360 361 // Returns true iff input and output buffers are in play. 362 bool active() const { return mActive; } 363 364protected: 365 virtual PortMode getPortMode(OMX_U32 portIndex); 366 virtual bool onMessageReceived(const sp<AMessage> &msg); 367 virtual void stateEntered(); 368 369 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 370 virtual bool onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano); 371 372private: 373 bool mActive; 374 375 DISALLOW_EVIL_CONSTRUCTORS(ExecutingState); 376}; 377 378//////////////////////////////////////////////////////////////////////////////// 379 380struct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState { 381 OutputPortSettingsChangedState(ACodec *codec); 382 383protected: 384 virtual PortMode getPortMode(OMX_U32 portIndex); 385 virtual bool onMessageReceived(const sp<AMessage> &msg); 386 virtual void stateEntered(); 387 388 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 389 virtual bool onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano); 390 391private: 392 DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState); 393}; 394 395//////////////////////////////////////////////////////////////////////////////// 396 397struct ACodec::ExecutingToIdleState : public ACodec::BaseState { 398 ExecutingToIdleState(ACodec *codec); 399 400protected: 401 virtual bool onMessageReceived(const sp<AMessage> &msg); 402 virtual void stateEntered(); 403 404 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 405 406 virtual void onOutputBufferDrained(const sp<AMessage> &msg); 407 virtual void onInputBufferFilled(const sp<AMessage> &msg); 408 409private: 410 void changeStateIfWeOwnAllBuffers(); 411 412 bool mComponentNowIdle; 413 414 DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState); 415}; 416 417//////////////////////////////////////////////////////////////////////////////// 418 419struct ACodec::IdleToLoadedState : public ACodec::BaseState { 420 IdleToLoadedState(ACodec *codec); 421 422protected: 423 virtual bool onMessageReceived(const sp<AMessage> &msg); 424 virtual void stateEntered(); 425 426 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 427 428private: 429 DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState); 430}; 431 432//////////////////////////////////////////////////////////////////////////////// 433 434struct ACodec::FlushingState : public ACodec::BaseState { 435 FlushingState(ACodec *codec); 436 437protected: 438 virtual bool onMessageReceived(const sp<AMessage> &msg); 439 virtual void stateEntered(); 440 441 virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2); 442 443 virtual void onOutputBufferDrained(const sp<AMessage> &msg); 444 virtual void onInputBufferFilled(const sp<AMessage> &msg); 445 446private: 447 bool mFlushComplete[2]; 448 449 void changeStateIfWeOwnAllBuffers(); 450 451 DISALLOW_EVIL_CONSTRUCTORS(FlushingState); 452}; 453 454//////////////////////////////////////////////////////////////////////////////// 455 456void ACodec::BufferInfo::setWriteFence(int fenceFd, const char *dbg) { 457 if (mFenceFd >= 0) { 458 ALOGW("OVERWRITE OF %s fence %d by write fence %d in %s", 459 mIsReadFence ? "read" : "write", mFenceFd, fenceFd, dbg); 460 } 461 mFenceFd = fenceFd; 462 mIsReadFence = false; 463} 464 465void ACodec::BufferInfo::setReadFence(int fenceFd, const char *dbg) { 466 if (mFenceFd >= 0) { 467 ALOGW("OVERWRITE OF %s fence %d by read fence %d in %s", 468 mIsReadFence ? "read" : "write", mFenceFd, fenceFd, dbg); 469 } 470 mFenceFd = fenceFd; 471 mIsReadFence = true; 472} 473 474void ACodec::BufferInfo::checkWriteFence(const char *dbg) { 475 if (mFenceFd >= 0 && mIsReadFence) { 476 ALOGD("REUSING read fence %d as write fence in %s", mFenceFd, dbg); 477 } 478} 479 480void ACodec::BufferInfo::checkReadFence(const char *dbg) { 481 if (mFenceFd >= 0 && !mIsReadFence) { 482 ALOGD("REUSING write fence %d as read fence in %s", mFenceFd, dbg); 483 } 484} 485 486//////////////////////////////////////////////////////////////////////////////// 487 488ACodec::ACodec() 489 : mQuirks(0), 490 mNode(0), 491 mUsingNativeWindow(false), 492 mNativeWindowUsageBits(0), 493 mIsVideo(false), 494 mIsEncoder(false), 495 mFatalError(false), 496 mShutdownInProgress(false), 497 mExplicitShutdown(false), 498 mEncoderDelay(0), 499 mEncoderPadding(0), 500 mRotationDegrees(0), 501 mChannelMaskPresent(false), 502 mChannelMask(0), 503 mDequeueCounter(0), 504 mInputMetadataType(kMetadataBufferTypeInvalid), 505 mOutputMetadataType(kMetadataBufferTypeInvalid), 506 mLegacyAdaptiveExperiment(false), 507 mMetadataBuffersToSubmit(0), 508 mRepeatFrameDelayUs(-1ll), 509 mMaxPtsGapUs(-1ll), 510 mMaxFps(-1), 511 mTimePerFrameUs(-1ll), 512 mTimePerCaptureUs(-1ll), 513 mCreateInputBuffersSuspended(false), 514 mTunneled(false), 515 mDescribeColorAspectsIndex((OMX_INDEXTYPE)0) { 516 mUninitializedState = new UninitializedState(this); 517 mLoadedState = new LoadedState(this); 518 mLoadedToIdleState = new LoadedToIdleState(this); 519 mIdleToExecutingState = new IdleToExecutingState(this); 520 mExecutingState = new ExecutingState(this); 521 522 mOutputPortSettingsChangedState = 523 new OutputPortSettingsChangedState(this); 524 525 mExecutingToIdleState = new ExecutingToIdleState(this); 526 mIdleToLoadedState = new IdleToLoadedState(this); 527 mFlushingState = new FlushingState(this); 528 529 mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false; 530 mInputEOSResult = OK; 531 532 changeState(mUninitializedState); 533} 534 535ACodec::~ACodec() { 536} 537 538void ACodec::setNotificationMessage(const sp<AMessage> &msg) { 539 mNotify = msg; 540} 541 542void ACodec::initiateSetup(const sp<AMessage> &msg) { 543 msg->setWhat(kWhatSetup); 544 msg->setTarget(this); 545 msg->post(); 546} 547 548void ACodec::signalSetParameters(const sp<AMessage> ¶ms) { 549 sp<AMessage> msg = new AMessage(kWhatSetParameters, this); 550 msg->setMessage("params", params); 551 msg->post(); 552} 553 554void ACodec::initiateAllocateComponent(const sp<AMessage> &msg) { 555 msg->setWhat(kWhatAllocateComponent); 556 msg->setTarget(this); 557 msg->post(); 558} 559 560void ACodec::initiateConfigureComponent(const sp<AMessage> &msg) { 561 msg->setWhat(kWhatConfigureComponent); 562 msg->setTarget(this); 563 msg->post(); 564} 565 566status_t ACodec::setSurface(const sp<Surface> &surface) { 567 sp<AMessage> msg = new AMessage(kWhatSetSurface, this); 568 msg->setObject("surface", surface); 569 570 sp<AMessage> response; 571 status_t err = msg->postAndAwaitResponse(&response); 572 573 if (err == OK) { 574 (void)response->findInt32("err", &err); 575 } 576 return err; 577} 578 579void ACodec::initiateCreateInputSurface() { 580 (new AMessage(kWhatCreateInputSurface, this))->post(); 581} 582 583void ACodec::initiateSetInputSurface( 584 const sp<PersistentSurface> &surface) { 585 sp<AMessage> msg = new AMessage(kWhatSetInputSurface, this); 586 msg->setObject("input-surface", surface); 587 msg->post(); 588} 589 590void ACodec::signalEndOfInputStream() { 591 (new AMessage(kWhatSignalEndOfInputStream, this))->post(); 592} 593 594void ACodec::initiateStart() { 595 (new AMessage(kWhatStart, this))->post(); 596} 597 598void ACodec::signalFlush() { 599 ALOGV("[%s] signalFlush", mComponentName.c_str()); 600 (new AMessage(kWhatFlush, this))->post(); 601} 602 603void ACodec::signalResume() { 604 (new AMessage(kWhatResume, this))->post(); 605} 606 607void ACodec::initiateShutdown(bool keepComponentAllocated) { 608 sp<AMessage> msg = new AMessage(kWhatShutdown, this); 609 msg->setInt32("keepComponentAllocated", keepComponentAllocated); 610 msg->post(); 611 if (!keepComponentAllocated) { 612 // ensure shutdown completes in 3 seconds 613 (new AMessage(kWhatReleaseCodecInstance, this))->post(3000000); 614 } 615} 616 617void ACodec::signalRequestIDRFrame() { 618 (new AMessage(kWhatRequestIDRFrame, this))->post(); 619} 620 621// *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** 622// Some codecs may return input buffers before having them processed. 623// This causes a halt if we already signaled an EOS on the input 624// port. For now keep submitting an output buffer if there was an 625// EOS on the input port, but not yet on the output port. 626void ACodec::signalSubmitOutputMetadataBufferIfEOS_workaround() { 627 if (mPortEOS[kPortIndexInput] && !mPortEOS[kPortIndexOutput] && 628 mMetadataBuffersToSubmit > 0) { 629 (new AMessage(kWhatSubmitOutputMetadataBufferIfEOS, this))->post(); 630 } 631} 632 633status_t ACodec::handleSetSurface(const sp<Surface> &surface) { 634 // allow keeping unset surface 635 if (surface == NULL) { 636 if (mNativeWindow != NULL) { 637 ALOGW("cannot unset a surface"); 638 return INVALID_OPERATION; 639 } 640 return OK; 641 } 642 643 // cannot switch from bytebuffers to surface 644 if (mNativeWindow == NULL) { 645 ALOGW("component was not configured with a surface"); 646 return INVALID_OPERATION; 647 } 648 649 ANativeWindow *nativeWindow = surface.get(); 650 // if we have not yet started the codec, we can simply set the native window 651 if (mBuffers[kPortIndexInput].size() == 0) { 652 mNativeWindow = surface; 653 return OK; 654 } 655 656 // we do not support changing a tunneled surface after start 657 if (mTunneled) { 658 ALOGW("cannot change tunneled surface"); 659 return INVALID_OPERATION; 660 } 661 662 int usageBits = 0; 663 status_t err = setupNativeWindowSizeFormatAndUsage(nativeWindow, &usageBits); 664 if (err != OK) { 665 return err; 666 } 667 668 int ignoredFlags = kVideoGrallocUsage; 669 // New output surface is not allowed to add new usage flag except ignored ones. 670 if ((usageBits & ~(mNativeWindowUsageBits | ignoredFlags)) != 0) { 671 ALOGW("cannot change usage from %#x to %#x", mNativeWindowUsageBits, usageBits); 672 return BAD_VALUE; 673 } 674 675 // get min undequeued count. We cannot switch to a surface that has a higher 676 // undequeued count than we allocated. 677 int minUndequeuedBuffers = 0; 678 err = nativeWindow->query( 679 nativeWindow, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, 680 &minUndequeuedBuffers); 681 if (err != 0) { 682 ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)", 683 strerror(-err), -err); 684 return err; 685 } 686 if (minUndequeuedBuffers > (int)mNumUndequeuedBuffers) { 687 ALOGE("new surface holds onto more buffers (%d) than planned for (%zu)", 688 minUndequeuedBuffers, mNumUndequeuedBuffers); 689 return BAD_VALUE; 690 } 691 692 // we cannot change the number of output buffers while OMX is running 693 // set up surface to the same count 694 Vector<BufferInfo> &buffers = mBuffers[kPortIndexOutput]; 695 ALOGV("setting up surface for %zu buffers", buffers.size()); 696 697 err = native_window_set_buffer_count(nativeWindow, buffers.size()); 698 if (err != 0) { 699 ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), 700 -err); 701 return err; 702 } 703 704 // need to enable allocation when attaching 705 surface->getIGraphicBufferProducer()->allowAllocation(true); 706 707 // for meta data mode, we move dequeud buffers to the new surface. 708 // for non-meta mode, we must move all registered buffers 709 for (size_t i = 0; i < buffers.size(); ++i) { 710 const BufferInfo &info = buffers[i]; 711 // skip undequeued buffers for meta data mode 712 if (storingMetadataInDecodedBuffers() 713 && !mLegacyAdaptiveExperiment 714 && info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 715 ALOGV("skipping buffer %p", info.mGraphicBuffer->getNativeBuffer()); 716 continue; 717 } 718 ALOGV("attaching buffer %p", info.mGraphicBuffer->getNativeBuffer()); 719 720 err = surface->attachBuffer(info.mGraphicBuffer->getNativeBuffer()); 721 if (err != OK) { 722 ALOGE("failed to attach buffer %p to the new surface: %s (%d)", 723 info.mGraphicBuffer->getNativeBuffer(), 724 strerror(-err), -err); 725 return err; 726 } 727 } 728 729 // cancel undequeued buffers to new surface 730 if (!storingMetadataInDecodedBuffers() || mLegacyAdaptiveExperiment) { 731 for (size_t i = 0; i < buffers.size(); ++i) { 732 BufferInfo &info = buffers.editItemAt(i); 733 if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 734 ALOGV("canceling buffer %p", info.mGraphicBuffer->getNativeBuffer()); 735 err = nativeWindow->cancelBuffer( 736 nativeWindow, info.mGraphicBuffer->getNativeBuffer(), info.mFenceFd); 737 info.mFenceFd = -1; 738 if (err != OK) { 739 ALOGE("failed to cancel buffer %p to the new surface: %s (%d)", 740 info.mGraphicBuffer->getNativeBuffer(), 741 strerror(-err), -err); 742 return err; 743 } 744 } 745 } 746 // disallow further allocation 747 (void)surface->getIGraphicBufferProducer()->allowAllocation(false); 748 } 749 750 // push blank buffers to previous window if requested 751 if (mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown) { 752 pushBlankBuffersToNativeWindow(mNativeWindow.get()); 753 } 754 755 mNativeWindow = nativeWindow; 756 mNativeWindowUsageBits = usageBits; 757 return OK; 758} 759 760status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) { 761 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 762 763 CHECK(mDealer[portIndex] == NULL); 764 CHECK(mBuffers[portIndex].isEmpty()); 765 766 status_t err; 767 if (mNativeWindow != NULL && portIndex == kPortIndexOutput) { 768 if (storingMetadataInDecodedBuffers()) { 769 err = allocateOutputMetadataBuffers(); 770 } else { 771 err = allocateOutputBuffersFromNativeWindow(); 772 } 773 } else { 774 OMX_PARAM_PORTDEFINITIONTYPE def; 775 InitOMXParams(&def); 776 def.nPortIndex = portIndex; 777 778 err = mOMX->getParameter( 779 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 780 781 if (err == OK) { 782 MetadataBufferType type = 783 portIndex == kPortIndexOutput ? mOutputMetadataType : mInputMetadataType; 784 int32_t bufSize = def.nBufferSize; 785 if (type == kMetadataBufferTypeGrallocSource) { 786 bufSize = sizeof(VideoGrallocMetadata); 787 } else if (type == kMetadataBufferTypeANWBuffer) { 788 bufSize = sizeof(VideoNativeMetadata); 789 } 790 791 // If using gralloc or native source input metadata buffers, allocate largest 792 // metadata size as we prefer to generate native source metadata, but component 793 // may require gralloc source. For camera source, allocate at least enough 794 // size for native metadata buffers. 795 int32_t allottedSize = bufSize; 796 if (portIndex == kPortIndexInput && type >= kMetadataBufferTypeGrallocSource) { 797 bufSize = max(sizeof(VideoGrallocMetadata), sizeof(VideoNativeMetadata)); 798 } else if (portIndex == kPortIndexInput && type == kMetadataBufferTypeCameraSource) { 799 bufSize = max(bufSize, (int32_t)sizeof(VideoNativeMetadata)); 800 } 801 802 ALOGV("[%s] Allocating %u buffers of size %d/%d (from %u using %s) on %s port", 803 mComponentName.c_str(), 804 def.nBufferCountActual, bufSize, allottedSize, def.nBufferSize, asString(type), 805 portIndex == kPortIndexInput ? "input" : "output"); 806 807 if (bufSize == 0 || def.nBufferCountActual > SIZE_MAX / bufSize) { 808 ALOGE("b/22885421"); 809 return NO_MEMORY; 810 } 811 size_t totalSize = def.nBufferCountActual * bufSize; 812 mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec"); 813 814 for (OMX_U32 i = 0; i < def.nBufferCountActual && err == OK; ++i) { 815 sp<IMemory> mem = mDealer[portIndex]->allocate(bufSize); 816 if (mem == NULL || mem->pointer() == NULL) { 817 return NO_MEMORY; 818 } 819 820 BufferInfo info; 821 info.mStatus = BufferInfo::OWNED_BY_US; 822 info.mFenceFd = -1; 823 info.mRenderInfo = NULL; 824 info.mNativeHandle = NULL; 825 826 uint32_t requiresAllocateBufferBit = 827 (portIndex == kPortIndexInput) 828 ? kRequiresAllocateBufferOnInputPorts 829 : kRequiresAllocateBufferOnOutputPorts; 830 831 if (portIndex == kPortIndexInput && (mFlags & kFlagIsSecure)) { 832 mem.clear(); 833 834 void *ptr = NULL; 835 native_handle_t *native_handle = NULL; 836 err = mOMX->allocateSecureBuffer( 837 mNode, portIndex, bufSize, &info.mBufferID, 838 &ptr, &native_handle); 839 840 // TRICKY: this representation is unorthodox, but ACodec requires 841 // an ABuffer with a proper size to validate range offsets and lengths. 842 // Since mData is never referenced for secure input, it is used to store 843 // either the pointer to the secure buffer, or the opaque handle as on 844 // some devices ptr is actually an opaque handle, not a pointer. 845 846 // TRICKY2: use native handle as the base of the ABuffer if received one, 847 // because Widevine source only receives these base addresses. 848 info.mData = new ABuffer(ptr != NULL ? ptr : (void *)native_handle, bufSize); 849 info.mNativeHandle = NativeHandle::create(native_handle, true /* ownsHandle */); 850 } else if (mQuirks & requiresAllocateBufferBit) { 851 err = mOMX->allocateBufferWithBackup( 852 mNode, portIndex, mem, &info.mBufferID, allottedSize); 853 } else { 854 err = mOMX->useBuffer(mNode, portIndex, mem, &info.mBufferID, allottedSize); 855 } 856 857 if (mem != NULL) { 858 info.mData = new ABuffer(mem->pointer(), bufSize); 859 if (type == kMetadataBufferTypeANWBuffer) { 860 ((VideoNativeMetadata *)mem->pointer())->nFenceFd = -1; 861 } 862 info.mMemRef = mem; 863 } 864 865 mBuffers[portIndex].push(info); 866 } 867 } 868 } 869 870 if (err != OK) { 871 return err; 872 } 873 874 sp<AMessage> notify = mNotify->dup(); 875 notify->setInt32("what", CodecBase::kWhatBuffersAllocated); 876 877 notify->setInt32("portIndex", portIndex); 878 879 sp<PortDescription> desc = new PortDescription; 880 881 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 882 const BufferInfo &info = mBuffers[portIndex][i]; 883 desc->addBuffer(info.mBufferID, info.mData, info.mNativeHandle, info.mMemRef); 884 } 885 886 notify->setObject("portDesc", desc); 887 notify->post(); 888 889 return OK; 890} 891 892status_t ACodec::setupNativeWindowSizeFormatAndUsage( 893 ANativeWindow *nativeWindow /* nonnull */, int *finalUsage /* nonnull */) { 894 OMX_PARAM_PORTDEFINITIONTYPE def; 895 InitOMXParams(&def); 896 def.nPortIndex = kPortIndexOutput; 897 898 status_t err = mOMX->getParameter( 899 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 900 901 if (err != OK) { 902 return err; 903 } 904 905 OMX_U32 usage = 0; 906 err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage); 907 if (err != 0) { 908 ALOGW("querying usage flags from OMX IL component failed: %d", err); 909 // XXX: Currently this error is logged, but not fatal. 910 usage = 0; 911 } 912 int omxUsage = usage; 913 914 if (mFlags & kFlagIsGrallocUsageProtected) { 915 usage |= GRALLOC_USAGE_PROTECTED; 916 } 917 918 usage |= kVideoGrallocUsage; 919 *finalUsage = usage; 920 921 ALOGV("gralloc usage: %#x(OMX) => %#x(ACodec)", omxUsage, usage); 922 return setNativeWindowSizeFormatAndUsage( 923 nativeWindow, 924 def.format.video.nFrameWidth, 925 def.format.video.nFrameHeight, 926 def.format.video.eColorFormat, 927 mRotationDegrees, 928 usage); 929} 930 931status_t ACodec::configureOutputBuffersFromNativeWindow( 932 OMX_U32 *bufferCount, OMX_U32 *bufferSize, 933 OMX_U32 *minUndequeuedBuffers) { 934 OMX_PARAM_PORTDEFINITIONTYPE def; 935 InitOMXParams(&def); 936 def.nPortIndex = kPortIndexOutput; 937 938 status_t err = mOMX->getParameter( 939 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 940 941 if (err == OK) { 942 err = setupNativeWindowSizeFormatAndUsage(mNativeWindow.get(), &mNativeWindowUsageBits); 943 } 944 if (err != OK) { 945 mNativeWindowUsageBits = 0; 946 return err; 947 } 948 949 // Exits here for tunneled video playback codecs -- i.e. skips native window 950 // buffer allocation step as this is managed by the tunneled OMX omponent 951 // itself and explicitly sets def.nBufferCountActual to 0. 952 if (mTunneled) { 953 ALOGV("Tunneled Playback: skipping native window buffer allocation."); 954 def.nBufferCountActual = 0; 955 err = mOMX->setParameter( 956 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 957 958 *minUndequeuedBuffers = 0; 959 *bufferCount = 0; 960 *bufferSize = 0; 961 return err; 962 } 963 964 *minUndequeuedBuffers = 0; 965 err = mNativeWindow->query( 966 mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, 967 (int *)minUndequeuedBuffers); 968 969 if (err != 0) { 970 ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)", 971 strerror(-err), -err); 972 return err; 973 } 974 975 // FIXME: assume that surface is controlled by app (native window 976 // returns the number for the case when surface is not controlled by app) 977 // FIXME2: This means that minUndeqeueudBufs can be 1 larger than reported 978 // For now, try to allocate 1 more buffer, but don't fail if unsuccessful 979 980 // Use conservative allocation while also trying to reduce starvation 981 // 982 // 1. allocate at least nBufferCountMin + minUndequeuedBuffers - that is the 983 // minimum needed for the consumer to be able to work 984 // 2. try to allocate two (2) additional buffers to reduce starvation from 985 // the consumer 986 // plus an extra buffer to account for incorrect minUndequeuedBufs 987 for (OMX_U32 extraBuffers = 2 + 1; /* condition inside loop */; extraBuffers--) { 988 OMX_U32 newBufferCount = 989 def.nBufferCountMin + *minUndequeuedBuffers + extraBuffers; 990 def.nBufferCountActual = newBufferCount; 991 err = mOMX->setParameter( 992 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 993 994 if (err == OK) { 995 *minUndequeuedBuffers += extraBuffers; 996 break; 997 } 998 999 ALOGW("[%s] setting nBufferCountActual to %u failed: %d", 1000 mComponentName.c_str(), newBufferCount, err); 1001 /* exit condition */ 1002 if (extraBuffers == 0) { 1003 return err; 1004 } 1005 } 1006 1007 err = native_window_set_buffer_count( 1008 mNativeWindow.get(), def.nBufferCountActual); 1009 1010 if (err != 0) { 1011 ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), 1012 -err); 1013 return err; 1014 } 1015 1016 *bufferCount = def.nBufferCountActual; 1017 *bufferSize = def.nBufferSize; 1018 return err; 1019} 1020 1021status_t ACodec::allocateOutputBuffersFromNativeWindow() { 1022 OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers; 1023 status_t err = configureOutputBuffersFromNativeWindow( 1024 &bufferCount, &bufferSize, &minUndequeuedBuffers); 1025 if (err != 0) 1026 return err; 1027 mNumUndequeuedBuffers = minUndequeuedBuffers; 1028 1029 if (!storingMetadataInDecodedBuffers()) { 1030 static_cast<Surface*>(mNativeWindow.get()) 1031 ->getIGraphicBufferProducer()->allowAllocation(true); 1032 } 1033 1034 ALOGV("[%s] Allocating %u buffers from a native window of size %u on " 1035 "output port", 1036 mComponentName.c_str(), bufferCount, bufferSize); 1037 1038 // Dequeue buffers and send them to OMX 1039 for (OMX_U32 i = 0; i < bufferCount; i++) { 1040 ANativeWindowBuffer *buf; 1041 int fenceFd; 1042 err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf, &fenceFd); 1043 if (err != 0) { 1044 ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err); 1045 break; 1046 } 1047 1048 sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false)); 1049 BufferInfo info; 1050 info.mStatus = BufferInfo::OWNED_BY_US; 1051 info.mFenceFd = fenceFd; 1052 info.mIsReadFence = false; 1053 info.mRenderInfo = NULL; 1054 info.mData = new ABuffer(NULL /* data */, bufferSize /* capacity */); 1055 info.mGraphicBuffer = graphicBuffer; 1056 mBuffers[kPortIndexOutput].push(info); 1057 1058 IOMX::buffer_id bufferId; 1059 err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer, 1060 &bufferId); 1061 if (err != 0) { 1062 ALOGE("registering GraphicBuffer %u with OMX IL component failed: " 1063 "%d", i, err); 1064 break; 1065 } 1066 1067 mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId; 1068 1069 ALOGV("[%s] Registered graphic buffer with ID %u (pointer = %p)", 1070 mComponentName.c_str(), 1071 bufferId, graphicBuffer.get()); 1072 } 1073 1074 OMX_U32 cancelStart; 1075 OMX_U32 cancelEnd; 1076 1077 if (err != 0) { 1078 // If an error occurred while dequeuing we need to cancel any buffers 1079 // that were dequeued. 1080 cancelStart = 0; 1081 cancelEnd = mBuffers[kPortIndexOutput].size(); 1082 } else { 1083 // Return the required minimum undequeued buffers to the native window. 1084 cancelStart = bufferCount - minUndequeuedBuffers; 1085 cancelEnd = bufferCount; 1086 } 1087 1088 for (OMX_U32 i = cancelStart; i < cancelEnd; i++) { 1089 BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i); 1090 if (info->mStatus == BufferInfo::OWNED_BY_US) { 1091 status_t error = cancelBufferToNativeWindow(info); 1092 if (err == 0) { 1093 err = error; 1094 } 1095 } 1096 } 1097 1098 if (!storingMetadataInDecodedBuffers()) { 1099 static_cast<Surface*>(mNativeWindow.get()) 1100 ->getIGraphicBufferProducer()->allowAllocation(false); 1101 } 1102 1103 return err; 1104} 1105 1106status_t ACodec::allocateOutputMetadataBuffers() { 1107 OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers; 1108 status_t err = configureOutputBuffersFromNativeWindow( 1109 &bufferCount, &bufferSize, &minUndequeuedBuffers); 1110 if (err != 0) 1111 return err; 1112 mNumUndequeuedBuffers = minUndequeuedBuffers; 1113 1114 ALOGV("[%s] Allocating %u meta buffers on output port", 1115 mComponentName.c_str(), bufferCount); 1116 1117 size_t bufSize = mOutputMetadataType == kMetadataBufferTypeANWBuffer ? 1118 sizeof(struct VideoNativeMetadata) : sizeof(struct VideoGrallocMetadata); 1119 size_t totalSize = bufferCount * bufSize; 1120 mDealer[kPortIndexOutput] = new MemoryDealer(totalSize, "ACodec"); 1121 1122 // Dequeue buffers and send them to OMX 1123 for (OMX_U32 i = 0; i < bufferCount; i++) { 1124 BufferInfo info; 1125 info.mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 1126 info.mFenceFd = -1; 1127 info.mRenderInfo = NULL; 1128 info.mGraphicBuffer = NULL; 1129 info.mDequeuedAt = mDequeueCounter; 1130 1131 sp<IMemory> mem = mDealer[kPortIndexOutput]->allocate(bufSize); 1132 if (mem == NULL || mem->pointer() == NULL) { 1133 return NO_MEMORY; 1134 } 1135 if (mOutputMetadataType == kMetadataBufferTypeANWBuffer) { 1136 ((VideoNativeMetadata *)mem->pointer())->nFenceFd = -1; 1137 } 1138 info.mData = new ABuffer(mem->pointer(), mem->size()); 1139 1140 // we use useBuffer for metadata regardless of quirks 1141 err = mOMX->useBuffer( 1142 mNode, kPortIndexOutput, mem, &info.mBufferID, mem->size()); 1143 info.mMemRef = mem; 1144 mBuffers[kPortIndexOutput].push(info); 1145 1146 ALOGV("[%s] allocated meta buffer with ID %u (pointer = %p)", 1147 mComponentName.c_str(), info.mBufferID, mem->pointer()); 1148 } 1149 1150 if (mLegacyAdaptiveExperiment) { 1151 // preallocate and preregister buffers 1152 static_cast<Surface *>(mNativeWindow.get()) 1153 ->getIGraphicBufferProducer()->allowAllocation(true); 1154 1155 ALOGV("[%s] Allocating %u buffers from a native window of size %u on " 1156 "output port", 1157 mComponentName.c_str(), bufferCount, bufferSize); 1158 1159 // Dequeue buffers then cancel them all 1160 for (OMX_U32 i = 0; i < bufferCount; i++) { 1161 BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i); 1162 1163 ANativeWindowBuffer *buf; 1164 int fenceFd; 1165 err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf, &fenceFd); 1166 if (err != 0) { 1167 ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err); 1168 break; 1169 } 1170 1171 sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false)); 1172 mOMX->updateGraphicBufferInMeta( 1173 mNode, kPortIndexOutput, graphicBuffer, info->mBufferID); 1174 info->mStatus = BufferInfo::OWNED_BY_US; 1175 info->setWriteFence(fenceFd, "allocateOutputMetadataBuffers for legacy"); 1176 info->mGraphicBuffer = graphicBuffer; 1177 } 1178 1179 for (OMX_U32 i = 0; i < mBuffers[kPortIndexOutput].size(); i++) { 1180 BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i); 1181 if (info->mStatus == BufferInfo::OWNED_BY_US) { 1182 status_t error = cancelBufferToNativeWindow(info); 1183 if (err == OK) { 1184 err = error; 1185 } 1186 } 1187 } 1188 1189 static_cast<Surface*>(mNativeWindow.get()) 1190 ->getIGraphicBufferProducer()->allowAllocation(false); 1191 } 1192 1193 mMetadataBuffersToSubmit = bufferCount - minUndequeuedBuffers; 1194 return err; 1195} 1196 1197status_t ACodec::submitOutputMetadataBuffer() { 1198 CHECK(storingMetadataInDecodedBuffers()); 1199 if (mMetadataBuffersToSubmit == 0) 1200 return OK; 1201 1202 BufferInfo *info = dequeueBufferFromNativeWindow(); 1203 if (info == NULL) { 1204 return ERROR_IO; 1205 } 1206 1207 ALOGV("[%s] submitting output meta buffer ID %u for graphic buffer %p", 1208 mComponentName.c_str(), info->mBufferID, info->mGraphicBuffer.get()); 1209 1210 --mMetadataBuffersToSubmit; 1211 info->checkWriteFence("submitOutputMetadataBuffer"); 1212 status_t err = mOMX->fillBuffer(mNode, info->mBufferID, info->mFenceFd); 1213 info->mFenceFd = -1; 1214 if (err == OK) { 1215 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 1216 } 1217 1218 return err; 1219} 1220 1221status_t ACodec::waitForFence(int fd, const char *dbg ) { 1222 status_t res = OK; 1223 if (fd >= 0) { 1224 sp<Fence> fence = new Fence(fd); 1225 res = fence->wait(IOMX::kFenceTimeoutMs); 1226 ALOGW_IF(res != OK, "FENCE TIMEOUT for %d in %s", fd, dbg); 1227 } 1228 return res; 1229} 1230 1231// static 1232const char *ACodec::_asString(BufferInfo::Status s) { 1233 switch (s) { 1234 case BufferInfo::OWNED_BY_US: return "OUR"; 1235 case BufferInfo::OWNED_BY_COMPONENT: return "COMPONENT"; 1236 case BufferInfo::OWNED_BY_UPSTREAM: return "UPSTREAM"; 1237 case BufferInfo::OWNED_BY_DOWNSTREAM: return "DOWNSTREAM"; 1238 case BufferInfo::OWNED_BY_NATIVE_WINDOW: return "SURFACE"; 1239 case BufferInfo::UNRECOGNIZED: return "UNRECOGNIZED"; 1240 default: return "?"; 1241 } 1242} 1243 1244void ACodec::dumpBuffers(OMX_U32 portIndex) { 1245 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 1246 ALOGI("[%s] %s port has %zu buffers:", mComponentName.c_str(), 1247 portIndex == kPortIndexInput ? "input" : "output", mBuffers[portIndex].size()); 1248 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 1249 const BufferInfo &info = mBuffers[portIndex][i]; 1250 ALOGI(" slot %2zu: #%8u %p/%p %s(%d) dequeued:%u", 1251 i, info.mBufferID, info.mGraphicBuffer.get(), 1252 info.mGraphicBuffer == NULL ? NULL : info.mGraphicBuffer->getNativeBuffer(), 1253 _asString(info.mStatus), info.mStatus, info.mDequeuedAt); 1254 } 1255} 1256 1257status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) { 1258 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 1259 1260 ALOGV("[%s] Calling cancelBuffer on buffer %u", 1261 mComponentName.c_str(), info->mBufferID); 1262 1263 info->checkWriteFence("cancelBufferToNativeWindow"); 1264 int err = mNativeWindow->cancelBuffer( 1265 mNativeWindow.get(), info->mGraphicBuffer.get(), info->mFenceFd); 1266 info->mFenceFd = -1; 1267 1268 ALOGW_IF(err != 0, "[%s] can not return buffer %u to native window", 1269 mComponentName.c_str(), info->mBufferID); 1270 // change ownership even if cancelBuffer fails 1271 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 1272 1273 return err; 1274} 1275 1276void ACodec::updateRenderInfoForDequeuedBuffer( 1277 ANativeWindowBuffer *buf, int fenceFd, BufferInfo *info) { 1278 1279 info->mRenderInfo = 1280 mRenderTracker.updateInfoForDequeuedBuffer( 1281 buf, fenceFd, info - &mBuffers[kPortIndexOutput][0]); 1282 1283 // check for any fences already signaled 1284 notifyOfRenderedFrames(false /* dropIncomplete */, info->mRenderInfo); 1285} 1286 1287void ACodec::onFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) { 1288 if (mRenderTracker.onFrameRendered(mediaTimeUs, systemNano) != OK) { 1289 mRenderTracker.dumpRenderQueue(); 1290 } 1291} 1292 1293void ACodec::notifyOfRenderedFrames(bool dropIncomplete, FrameRenderTracker::Info *until) { 1294 sp<AMessage> msg = mNotify->dup(); 1295 msg->setInt32("what", CodecBase::kWhatOutputFramesRendered); 1296 std::list<FrameRenderTracker::Info> done = 1297 mRenderTracker.checkFencesAndGetRenderedFrames(until, dropIncomplete); 1298 1299 // unlink untracked frames 1300 for (std::list<FrameRenderTracker::Info>::const_iterator it = done.cbegin(); 1301 it != done.cend(); ++it) { 1302 ssize_t index = it->getIndex(); 1303 if (index >= 0 && (size_t)index < mBuffers[kPortIndexOutput].size()) { 1304 mBuffers[kPortIndexOutput].editItemAt(index).mRenderInfo = NULL; 1305 } else if (index >= 0) { 1306 // THIS SHOULD NEVER HAPPEN 1307 ALOGE("invalid index %zd in %zu", index, mBuffers[kPortIndexOutput].size()); 1308 } 1309 } 1310 1311 if (MediaCodec::CreateFramesRenderedMessage(done, msg)) { 1312 msg->post(); 1313 } 1314} 1315 1316ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() { 1317 ANativeWindowBuffer *buf; 1318 CHECK(mNativeWindow.get() != NULL); 1319 1320 if (mTunneled) { 1321 ALOGW("dequeueBufferFromNativeWindow() should not be called in tunnel" 1322 " video playback mode mode!"); 1323 return NULL; 1324 } 1325 1326 if (mFatalError) { 1327 ALOGW("not dequeuing from native window due to fatal error"); 1328 return NULL; 1329 } 1330 1331 int fenceFd = -1; 1332 do { 1333 status_t err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf, &fenceFd); 1334 if (err != 0) { 1335 ALOGE("dequeueBuffer failed: %s(%d).", asString(err), err); 1336 return NULL; 1337 } 1338 1339 bool stale = false; 1340 for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) { 1341 i--; 1342 BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i); 1343 1344 if (info->mGraphicBuffer != NULL && 1345 info->mGraphicBuffer->handle == buf->handle) { 1346 // Since consumers can attach buffers to BufferQueues, it is possible 1347 // that a known yet stale buffer can return from a surface that we 1348 // once used. We can simply ignore this as we have already dequeued 1349 // this buffer properly. NOTE: this does not eliminate all cases, 1350 // e.g. it is possible that we have queued the valid buffer to the 1351 // NW, and a stale copy of the same buffer gets dequeued - which will 1352 // be treated as the valid buffer by ACodec. 1353 if (info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) { 1354 ALOGI("dequeued stale buffer %p. discarding", buf); 1355 stale = true; 1356 break; 1357 } 1358 1359 ALOGV("dequeued buffer %p", info->mGraphicBuffer->getNativeBuffer()); 1360 info->mStatus = BufferInfo::OWNED_BY_US; 1361 info->setWriteFence(fenceFd, "dequeueBufferFromNativeWindow"); 1362 updateRenderInfoForDequeuedBuffer(buf, fenceFd, info); 1363 return info; 1364 } 1365 } 1366 1367 // It is also possible to receive a previously unregistered buffer 1368 // in non-meta mode. These should be treated as stale buffers. The 1369 // same is possible in meta mode, in which case, it will be treated 1370 // as a normal buffer, which is not desirable. 1371 // TODO: fix this. 1372 if (!stale && (!storingMetadataInDecodedBuffers() || mLegacyAdaptiveExperiment)) { 1373 ALOGI("dequeued unrecognized (stale) buffer %p. discarding", buf); 1374 stale = true; 1375 } 1376 if (stale) { 1377 // TODO: detach stale buffer, but there is no API yet to do it. 1378 buf = NULL; 1379 } 1380 } while (buf == NULL); 1381 1382 // get oldest undequeued buffer 1383 BufferInfo *oldest = NULL; 1384 for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) { 1385 i--; 1386 BufferInfo *info = 1387 &mBuffers[kPortIndexOutput].editItemAt(i); 1388 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW && 1389 (oldest == NULL || 1390 // avoid potential issues from counter rolling over 1391 mDequeueCounter - info->mDequeuedAt > 1392 mDequeueCounter - oldest->mDequeuedAt)) { 1393 oldest = info; 1394 } 1395 } 1396 1397 // it is impossible dequeue a buffer when there are no buffers with ANW 1398 CHECK(oldest != NULL); 1399 // it is impossible to dequeue an unknown buffer in non-meta mode, as the 1400 // while loop above does not complete 1401 CHECK(storingMetadataInDecodedBuffers()); 1402 1403 // discard buffer in LRU info and replace with new buffer 1404 oldest->mGraphicBuffer = new GraphicBuffer(buf, false); 1405 oldest->mStatus = BufferInfo::OWNED_BY_US; 1406 oldest->setWriteFence(fenceFd, "dequeueBufferFromNativeWindow for oldest"); 1407 mRenderTracker.untrackFrame(oldest->mRenderInfo); 1408 oldest->mRenderInfo = NULL; 1409 1410 mOMX->updateGraphicBufferInMeta( 1411 mNode, kPortIndexOutput, oldest->mGraphicBuffer, 1412 oldest->mBufferID); 1413 1414 if (mOutputMetadataType == kMetadataBufferTypeGrallocSource) { 1415 VideoGrallocMetadata *grallocMeta = 1416 reinterpret_cast<VideoGrallocMetadata *>(oldest->mData->base()); 1417 ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)", 1418 (unsigned)(oldest - &mBuffers[kPortIndexOutput][0]), 1419 mDequeueCounter - oldest->mDequeuedAt, 1420 (void *)(uintptr_t)grallocMeta->pHandle, 1421 oldest->mGraphicBuffer->handle, oldest->mData->base()); 1422 } else if (mOutputMetadataType == kMetadataBufferTypeANWBuffer) { 1423 VideoNativeMetadata *nativeMeta = 1424 reinterpret_cast<VideoNativeMetadata *>(oldest->mData->base()); 1425 ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)", 1426 (unsigned)(oldest - &mBuffers[kPortIndexOutput][0]), 1427 mDequeueCounter - oldest->mDequeuedAt, 1428 (void *)(uintptr_t)nativeMeta->pBuffer, 1429 oldest->mGraphicBuffer->getNativeBuffer(), oldest->mData->base()); 1430 } 1431 1432 updateRenderInfoForDequeuedBuffer(buf, fenceFd, oldest); 1433 return oldest; 1434} 1435 1436status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) { 1437 status_t err = OK; 1438 for (size_t i = mBuffers[portIndex].size(); i > 0;) { 1439 i--; 1440 status_t err2 = freeBuffer(portIndex, i); 1441 if (err == OK) { 1442 err = err2; 1443 } 1444 } 1445 1446 // clear mDealer even on an error 1447 mDealer[portIndex].clear(); 1448 return err; 1449} 1450 1451status_t ACodec::freeOutputBuffersNotOwnedByComponent() { 1452 status_t err = OK; 1453 for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) { 1454 i--; 1455 BufferInfo *info = 1456 &mBuffers[kPortIndexOutput].editItemAt(i); 1457 1458 // At this time some buffers may still be with the component 1459 // or being drained. 1460 if (info->mStatus != BufferInfo::OWNED_BY_COMPONENT && 1461 info->mStatus != BufferInfo::OWNED_BY_DOWNSTREAM) { 1462 status_t err2 = freeBuffer(kPortIndexOutput, i); 1463 if (err == OK) { 1464 err = err2; 1465 } 1466 } 1467 } 1468 1469 return err; 1470} 1471 1472status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) { 1473 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 1474 status_t err = OK; 1475 1476 // there should not be any fences in the metadata 1477 MetadataBufferType type = 1478 portIndex == kPortIndexOutput ? mOutputMetadataType : mInputMetadataType; 1479 if (type == kMetadataBufferTypeANWBuffer && info->mData != NULL 1480 && info->mData->size() >= sizeof(VideoNativeMetadata)) { 1481 int fenceFd = ((VideoNativeMetadata *)info->mData->data())->nFenceFd; 1482 if (fenceFd >= 0) { 1483 ALOGW("unreleased fence (%d) in %s metadata buffer %zu", 1484 fenceFd, portIndex == kPortIndexInput ? "input" : "output", i); 1485 } 1486 } 1487 1488 switch (info->mStatus) { 1489 case BufferInfo::OWNED_BY_US: 1490 if (portIndex == kPortIndexOutput && mNativeWindow != NULL) { 1491 (void)cancelBufferToNativeWindow(info); 1492 } 1493 // fall through 1494 1495 case BufferInfo::OWNED_BY_NATIVE_WINDOW: 1496 err = mOMX->freeBuffer(mNode, portIndex, info->mBufferID); 1497 break; 1498 1499 default: 1500 ALOGE("trying to free buffer not owned by us or ANW (%d)", info->mStatus); 1501 err = FAILED_TRANSACTION; 1502 break; 1503 } 1504 1505 if (info->mFenceFd >= 0) { 1506 ::close(info->mFenceFd); 1507 } 1508 1509 if (portIndex == kPortIndexOutput) { 1510 mRenderTracker.untrackFrame(info->mRenderInfo, i); 1511 info->mRenderInfo = NULL; 1512 } 1513 1514 // remove buffer even if mOMX->freeBuffer fails 1515 mBuffers[portIndex].removeAt(i); 1516 return err; 1517} 1518 1519ACodec::BufferInfo *ACodec::findBufferByID( 1520 uint32_t portIndex, IOMX::buffer_id bufferID, ssize_t *index) { 1521 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 1522 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 1523 1524 if (info->mBufferID == bufferID) { 1525 if (index != NULL) { 1526 *index = i; 1527 } 1528 return info; 1529 } 1530 } 1531 1532 ALOGE("Could not find buffer with ID %u", bufferID); 1533 return NULL; 1534} 1535 1536status_t ACodec::setComponentRole( 1537 bool isEncoder, const char *mime) { 1538 const char *role = getComponentRole(isEncoder, mime); 1539 if (role == NULL) { 1540 return BAD_VALUE; 1541 } 1542 status_t err = setComponentRole(mOMX, mNode, role); 1543 if (err != OK) { 1544 ALOGW("[%s] Failed to set standard component role '%s'.", 1545 mComponentName.c_str(), role); 1546 } 1547 return err; 1548} 1549 1550//static 1551const char *ACodec::getComponentRole( 1552 bool isEncoder, const char *mime) { 1553 struct MimeToRole { 1554 const char *mime; 1555 const char *decoderRole; 1556 const char *encoderRole; 1557 }; 1558 1559 static const MimeToRole kMimeToRole[] = { 1560 { MEDIA_MIMETYPE_AUDIO_MPEG, 1561 "audio_decoder.mp3", "audio_encoder.mp3" }, 1562 { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I, 1563 "audio_decoder.mp1", "audio_encoder.mp1" }, 1564 { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II, 1565 "audio_decoder.mp2", "audio_encoder.mp2" }, 1566 { MEDIA_MIMETYPE_AUDIO_AMR_NB, 1567 "audio_decoder.amrnb", "audio_encoder.amrnb" }, 1568 { MEDIA_MIMETYPE_AUDIO_AMR_WB, 1569 "audio_decoder.amrwb", "audio_encoder.amrwb" }, 1570 { MEDIA_MIMETYPE_AUDIO_AAC, 1571 "audio_decoder.aac", "audio_encoder.aac" }, 1572 { MEDIA_MIMETYPE_AUDIO_VORBIS, 1573 "audio_decoder.vorbis", "audio_encoder.vorbis" }, 1574 { MEDIA_MIMETYPE_AUDIO_OPUS, 1575 "audio_decoder.opus", "audio_encoder.opus" }, 1576 { MEDIA_MIMETYPE_AUDIO_G711_MLAW, 1577 "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" }, 1578 { MEDIA_MIMETYPE_AUDIO_G711_ALAW, 1579 "audio_decoder.g711alaw", "audio_encoder.g711alaw" }, 1580 { MEDIA_MIMETYPE_VIDEO_AVC, 1581 "video_decoder.avc", "video_encoder.avc" }, 1582 { MEDIA_MIMETYPE_VIDEO_HEVC, 1583 "video_decoder.hevc", "video_encoder.hevc" }, 1584 { MEDIA_MIMETYPE_VIDEO_MPEG4, 1585 "video_decoder.mpeg4", "video_encoder.mpeg4" }, 1586 { MEDIA_MIMETYPE_VIDEO_H263, 1587 "video_decoder.h263", "video_encoder.h263" }, 1588 { MEDIA_MIMETYPE_VIDEO_VP8, 1589 "video_decoder.vp8", "video_encoder.vp8" }, 1590 { MEDIA_MIMETYPE_VIDEO_VP9, 1591 "video_decoder.vp9", "video_encoder.vp9" }, 1592 { MEDIA_MIMETYPE_AUDIO_RAW, 1593 "audio_decoder.raw", "audio_encoder.raw" }, 1594 { MEDIA_MIMETYPE_VIDEO_DOLBY_VISION, 1595 "video_decoder.dolby-vision", "video_encoder.dolby-vision" }, 1596 { MEDIA_MIMETYPE_AUDIO_FLAC, 1597 "audio_decoder.flac", "audio_encoder.flac" }, 1598 { MEDIA_MIMETYPE_AUDIO_MSGSM, 1599 "audio_decoder.gsm", "audio_encoder.gsm" }, 1600 { MEDIA_MIMETYPE_VIDEO_MPEG2, 1601 "video_decoder.mpeg2", "video_encoder.mpeg2" }, 1602 { MEDIA_MIMETYPE_AUDIO_AC3, 1603 "audio_decoder.ac3", "audio_encoder.ac3" }, 1604 { MEDIA_MIMETYPE_AUDIO_EAC3, 1605 "audio_decoder.eac3", "audio_encoder.eac3" }, 1606 }; 1607 1608 static const size_t kNumMimeToRole = 1609 sizeof(kMimeToRole) / sizeof(kMimeToRole[0]); 1610 1611 size_t i; 1612 for (i = 0; i < kNumMimeToRole; ++i) { 1613 if (!strcasecmp(mime, kMimeToRole[i].mime)) { 1614 break; 1615 } 1616 } 1617 1618 if (i == kNumMimeToRole) { 1619 return NULL; 1620 } 1621 1622 return isEncoder ? kMimeToRole[i].encoderRole 1623 : kMimeToRole[i].decoderRole; 1624} 1625 1626//static 1627status_t ACodec::setComponentRole( 1628 const sp<IOMX> &omx, IOMX::node_id node, const char *role) { 1629 OMX_PARAM_COMPONENTROLETYPE roleParams; 1630 InitOMXParams(&roleParams); 1631 1632 strncpy((char *)roleParams.cRole, 1633 role, OMX_MAX_STRINGNAME_SIZE - 1); 1634 1635 roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0'; 1636 1637 return omx->setParameter( 1638 node, OMX_IndexParamStandardComponentRole, 1639 &roleParams, sizeof(roleParams)); 1640} 1641 1642status_t ACodec::configureCodec( 1643 const char *mime, const sp<AMessage> &msg) { 1644 int32_t encoder; 1645 if (!msg->findInt32("encoder", &encoder)) { 1646 encoder = false; 1647 } 1648 1649 sp<AMessage> inputFormat = new AMessage; 1650 sp<AMessage> outputFormat = new AMessage; 1651 mConfigFormat = msg; 1652 1653 mIsEncoder = encoder; 1654 1655 mInputMetadataType = kMetadataBufferTypeInvalid; 1656 mOutputMetadataType = kMetadataBufferTypeInvalid; 1657 1658 status_t err = setComponentRole(encoder /* isEncoder */, mime); 1659 1660 if (err != OK) { 1661 return err; 1662 } 1663 1664 int32_t bitRate = 0; 1665 // FLAC encoder doesn't need a bitrate, other encoders do 1666 if (encoder && strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC) 1667 && !msg->findInt32("bitrate", &bitRate)) { 1668 return INVALID_OPERATION; 1669 } 1670 1671 int32_t storeMeta; 1672 if (encoder 1673 && msg->findInt32("store-metadata-in-buffers", &storeMeta) 1674 && storeMeta != 0) { 1675 err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexInput, OMX_TRUE, &mInputMetadataType); 1676 if (err != OK) { 1677 ALOGE("[%s] storeMetaDataInBuffers (input) failed w/ err %d", 1678 mComponentName.c_str(), err); 1679 1680 return err; 1681 } 1682 // For this specific case we could be using camera source even if storeMetaDataInBuffers 1683 // returns Gralloc source. Pretend that we are; this will force us to use nBufferSize. 1684 if (mInputMetadataType == kMetadataBufferTypeGrallocSource) { 1685 mInputMetadataType = kMetadataBufferTypeCameraSource; 1686 } 1687 1688 uint32_t usageBits; 1689 if (mOMX->getParameter( 1690 mNode, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits, 1691 &usageBits, sizeof(usageBits)) == OK) { 1692 inputFormat->setInt32( 1693 "using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN)); 1694 } 1695 } 1696 1697 int32_t prependSPSPPS = 0; 1698 if (encoder 1699 && msg->findInt32("prepend-sps-pps-to-idr-frames", &prependSPSPPS) 1700 && prependSPSPPS != 0) { 1701 OMX_INDEXTYPE index; 1702 err = mOMX->getExtensionIndex( 1703 mNode, 1704 "OMX.google.android.index.prependSPSPPSToIDRFrames", 1705 &index); 1706 1707 if (err == OK) { 1708 PrependSPSPPSToIDRFramesParams params; 1709 InitOMXParams(¶ms); 1710 params.bEnable = OMX_TRUE; 1711 1712 err = mOMX->setParameter( 1713 mNode, index, ¶ms, sizeof(params)); 1714 } 1715 1716 if (err != OK) { 1717 ALOGE("Encoder could not be configured to emit SPS/PPS before " 1718 "IDR frames. (err %d)", err); 1719 1720 return err; 1721 } 1722 } 1723 1724 // Only enable metadata mode on encoder output if encoder can prepend 1725 // sps/pps to idr frames, since in metadata mode the bitstream is in an 1726 // opaque handle, to which we don't have access. 1727 int32_t video = !strncasecmp(mime, "video/", 6); 1728 mIsVideo = video; 1729 if (encoder && video) { 1730 OMX_BOOL enable = (OMX_BOOL) (prependSPSPPS 1731 && msg->findInt32("store-metadata-in-buffers-output", &storeMeta) 1732 && storeMeta != 0); 1733 1734 err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, enable, &mOutputMetadataType); 1735 if (err != OK) { 1736 ALOGE("[%s] storeMetaDataInBuffers (output) failed w/ err %d", 1737 mComponentName.c_str(), err); 1738 } 1739 1740 if (!msg->findInt64( 1741 "repeat-previous-frame-after", 1742 &mRepeatFrameDelayUs)) { 1743 mRepeatFrameDelayUs = -1ll; 1744 } 1745 1746 if (!msg->findInt64("max-pts-gap-to-encoder", &mMaxPtsGapUs)) { 1747 mMaxPtsGapUs = -1ll; 1748 } 1749 1750 if (!msg->findFloat("max-fps-to-encoder", &mMaxFps)) { 1751 mMaxFps = -1; 1752 } 1753 1754 if (!msg->findInt64("time-lapse", &mTimePerCaptureUs)) { 1755 mTimePerCaptureUs = -1ll; 1756 } 1757 1758 if (!msg->findInt32( 1759 "create-input-buffers-suspended", 1760 (int32_t*)&mCreateInputBuffersSuspended)) { 1761 mCreateInputBuffersSuspended = false; 1762 } 1763 } 1764 1765 // NOTE: we only use native window for video decoders 1766 sp<RefBase> obj; 1767 bool haveNativeWindow = msg->findObject("native-window", &obj) 1768 && obj != NULL && video && !encoder; 1769 mUsingNativeWindow = haveNativeWindow; 1770 mLegacyAdaptiveExperiment = false; 1771 if (video && !encoder) { 1772 inputFormat->setInt32("adaptive-playback", false); 1773 1774 int32_t usageProtected; 1775 if (msg->findInt32("protected", &usageProtected) && usageProtected) { 1776 if (!haveNativeWindow) { 1777 ALOGE("protected output buffers must be sent to an ANativeWindow"); 1778 return PERMISSION_DENIED; 1779 } 1780 mFlags |= kFlagIsGrallocUsageProtected; 1781 mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown; 1782 } 1783 1784 if (mFlags & kFlagIsSecure) { 1785 // use native_handles for secure input buffers 1786 err = mOMX->enableNativeBuffers( 1787 mNode, kPortIndexInput, OMX_FALSE /* graphic */, OMX_TRUE); 1788 ALOGI_IF(err != OK, "falling back to non-native_handles"); 1789 err = OK; // ignore error for now 1790 } 1791 } 1792 if (haveNativeWindow) { 1793 sp<ANativeWindow> nativeWindow = 1794 static_cast<ANativeWindow *>(static_cast<Surface *>(obj.get())); 1795 1796 // START of temporary support for automatic FRC - THIS WILL BE REMOVED 1797 int32_t autoFrc; 1798 if (msg->findInt32("auto-frc", &autoFrc)) { 1799 bool enabled = autoFrc; 1800 OMX_CONFIG_BOOLEANTYPE config; 1801 InitOMXParams(&config); 1802 config.bEnabled = (OMX_BOOL)enabled; 1803 status_t temp = mOMX->setConfig( 1804 mNode, (OMX_INDEXTYPE)OMX_IndexConfigAutoFramerateConversion, 1805 &config, sizeof(config)); 1806 if (temp == OK) { 1807 outputFormat->setInt32("auto-frc", enabled); 1808 } else if (enabled) { 1809 ALOGI("codec does not support requested auto-frc (err %d)", temp); 1810 } 1811 } 1812 // END of temporary support for automatic FRC 1813 1814 int32_t tunneled; 1815 if (msg->findInt32("feature-tunneled-playback", &tunneled) && 1816 tunneled != 0) { 1817 ALOGI("Configuring TUNNELED video playback."); 1818 mTunneled = true; 1819 1820 int32_t audioHwSync = 0; 1821 if (!msg->findInt32("audio-hw-sync", &audioHwSync)) { 1822 ALOGW("No Audio HW Sync provided for video tunnel"); 1823 } 1824 err = configureTunneledVideoPlayback(audioHwSync, nativeWindow); 1825 if (err != OK) { 1826 ALOGE("configureTunneledVideoPlayback(%d,%p) failed!", 1827 audioHwSync, nativeWindow.get()); 1828 return err; 1829 } 1830 1831 int32_t maxWidth = 0, maxHeight = 0; 1832 if (msg->findInt32("max-width", &maxWidth) && 1833 msg->findInt32("max-height", &maxHeight)) { 1834 1835 err = mOMX->prepareForAdaptivePlayback( 1836 mNode, kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight); 1837 if (err != OK) { 1838 ALOGW("[%s] prepareForAdaptivePlayback failed w/ err %d", 1839 mComponentName.c_str(), err); 1840 // allow failure 1841 err = OK; 1842 } else { 1843 inputFormat->setInt32("max-width", maxWidth); 1844 inputFormat->setInt32("max-height", maxHeight); 1845 inputFormat->setInt32("adaptive-playback", true); 1846 } 1847 } 1848 } else { 1849 ALOGV("Configuring CPU controlled video playback."); 1850 mTunneled = false; 1851 1852 // Explicity reset the sideband handle of the window for 1853 // non-tunneled video in case the window was previously used 1854 // for a tunneled video playback. 1855 err = native_window_set_sideband_stream(nativeWindow.get(), NULL); 1856 if (err != OK) { 1857 ALOGE("set_sideband_stream(NULL) failed! (err %d).", err); 1858 return err; 1859 } 1860 1861 // Always try to enable dynamic output buffers on native surface 1862 err = mOMX->storeMetaDataInBuffers( 1863 mNode, kPortIndexOutput, OMX_TRUE, &mOutputMetadataType); 1864 if (err != OK) { 1865 ALOGE("[%s] storeMetaDataInBuffers failed w/ err %d", 1866 mComponentName.c_str(), err); 1867 1868 // if adaptive playback has been requested, try JB fallback 1869 // NOTE: THIS FALLBACK MECHANISM WILL BE REMOVED DUE TO ITS 1870 // LARGE MEMORY REQUIREMENT 1871 1872 // we will not do adaptive playback on software accessed 1873 // surfaces as they never had to respond to changes in the 1874 // crop window, and we don't trust that they will be able to. 1875 int usageBits = 0; 1876 bool canDoAdaptivePlayback; 1877 1878 if (nativeWindow->query( 1879 nativeWindow.get(), 1880 NATIVE_WINDOW_CONSUMER_USAGE_BITS, 1881 &usageBits) != OK) { 1882 canDoAdaptivePlayback = false; 1883 } else { 1884 canDoAdaptivePlayback = 1885 (usageBits & 1886 (GRALLOC_USAGE_SW_READ_MASK | 1887 GRALLOC_USAGE_SW_WRITE_MASK)) == 0; 1888 } 1889 1890 int32_t maxWidth = 0, maxHeight = 0; 1891 if (canDoAdaptivePlayback && 1892 msg->findInt32("max-width", &maxWidth) && 1893 msg->findInt32("max-height", &maxHeight)) { 1894 ALOGV("[%s] prepareForAdaptivePlayback(%dx%d)", 1895 mComponentName.c_str(), maxWidth, maxHeight); 1896 1897 err = mOMX->prepareForAdaptivePlayback( 1898 mNode, kPortIndexOutput, OMX_TRUE, maxWidth, 1899 maxHeight); 1900 ALOGW_IF(err != OK, 1901 "[%s] prepareForAdaptivePlayback failed w/ err %d", 1902 mComponentName.c_str(), err); 1903 1904 if (err == OK) { 1905 inputFormat->setInt32("max-width", maxWidth); 1906 inputFormat->setInt32("max-height", maxHeight); 1907 inputFormat->setInt32("adaptive-playback", true); 1908 } 1909 } 1910 // allow failure 1911 err = OK; 1912 } else { 1913 ALOGV("[%s] storeMetaDataInBuffers succeeded", 1914 mComponentName.c_str()); 1915 CHECK(storingMetadataInDecodedBuffers()); 1916 mLegacyAdaptiveExperiment = ADebug::isExperimentEnabled( 1917 "legacy-adaptive", !msg->contains("no-experiments")); 1918 1919 inputFormat->setInt32("adaptive-playback", true); 1920 } 1921 1922 int32_t push; 1923 if (msg->findInt32("push-blank-buffers-on-shutdown", &push) 1924 && push != 0) { 1925 mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown; 1926 } 1927 } 1928 1929 int32_t rotationDegrees; 1930 if (msg->findInt32("rotation-degrees", &rotationDegrees)) { 1931 mRotationDegrees = rotationDegrees; 1932 } else { 1933 mRotationDegrees = 0; 1934 } 1935 } 1936 1937 if (video) { 1938 // determine need for software renderer 1939 bool usingSwRenderer = false; 1940 if (haveNativeWindow && mComponentName.startsWith("OMX.google.")) { 1941 usingSwRenderer = true; 1942 haveNativeWindow = false; 1943 } 1944 1945 if (encoder) { 1946 err = setupVideoEncoder(mime, msg, outputFormat, inputFormat); 1947 } else { 1948 err = setupVideoDecoder(mime, msg, haveNativeWindow, usingSwRenderer, outputFormat); 1949 } 1950 1951 if (err != OK) { 1952 return err; 1953 } 1954 1955 if (haveNativeWindow) { 1956 mNativeWindow = static_cast<Surface *>(obj.get()); 1957 } 1958 1959 // initialize native window now to get actual output format 1960 // TODO: this is needed for some encoders even though they don't use native window 1961 err = initNativeWindow(); 1962 if (err != OK) { 1963 return err; 1964 } 1965 1966 // fallback for devices that do not handle flex-YUV for native buffers 1967 if (haveNativeWindow) { 1968 int32_t requestedColorFormat = OMX_COLOR_FormatUnused; 1969 if (msg->findInt32("color-format", &requestedColorFormat) && 1970 requestedColorFormat == OMX_COLOR_FormatYUV420Flexible) { 1971 status_t err = getPortFormat(kPortIndexOutput, outputFormat); 1972 if (err != OK) { 1973 return err; 1974 } 1975 int32_t colorFormat = OMX_COLOR_FormatUnused; 1976 OMX_U32 flexibleEquivalent = OMX_COLOR_FormatUnused; 1977 if (!outputFormat->findInt32("color-format", &colorFormat)) { 1978 ALOGE("ouptut port did not have a color format (wrong domain?)"); 1979 return BAD_VALUE; 1980 } 1981 ALOGD("[%s] Requested output format %#x and got %#x.", 1982 mComponentName.c_str(), requestedColorFormat, colorFormat); 1983 if (!isFlexibleColorFormat( 1984 mOMX, mNode, colorFormat, haveNativeWindow, &flexibleEquivalent) 1985 || flexibleEquivalent != (OMX_U32)requestedColorFormat) { 1986 // device did not handle flex-YUV request for native window, fall back 1987 // to SW renderer 1988 ALOGI("[%s] Falling back to software renderer", mComponentName.c_str()); 1989 mNativeWindow.clear(); 1990 mNativeWindowUsageBits = 0; 1991 haveNativeWindow = false; 1992 usingSwRenderer = true; 1993 if (storingMetadataInDecodedBuffers()) { 1994 err = mOMX->storeMetaDataInBuffers( 1995 mNode, kPortIndexOutput, OMX_FALSE, &mOutputMetadataType); 1996 mOutputMetadataType = kMetadataBufferTypeInvalid; // just in case 1997 // TODO: implement adaptive-playback support for bytebuffer mode. 1998 // This is done by SW codecs, but most HW codecs don't support it. 1999 inputFormat->setInt32("adaptive-playback", false); 2000 } 2001 if (err == OK) { 2002 err = mOMX->enableNativeBuffers( 2003 mNode, kPortIndexOutput, OMX_TRUE /* graphic */, OMX_FALSE); 2004 } 2005 if (mFlags & kFlagIsGrallocUsageProtected) { 2006 // fallback is not supported for protected playback 2007 err = PERMISSION_DENIED; 2008 } else if (err == OK) { 2009 err = setupVideoDecoder( 2010 mime, msg, haveNativeWindow, usingSwRenderer, outputFormat); 2011 } 2012 } 2013 } 2014 } 2015 2016 if (usingSwRenderer) { 2017 outputFormat->setInt32("using-sw-renderer", 1); 2018 } 2019 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) { 2020 int32_t numChannels, sampleRate; 2021 if (!msg->findInt32("channel-count", &numChannels) 2022 || !msg->findInt32("sample-rate", &sampleRate)) { 2023 // Since we did not always check for these, leave them optional 2024 // and have the decoder figure it all out. 2025 err = OK; 2026 } else { 2027 err = setupRawAudioFormat( 2028 encoder ? kPortIndexInput : kPortIndexOutput, 2029 sampleRate, 2030 numChannels); 2031 } 2032 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 2033 int32_t numChannels, sampleRate; 2034 if (!msg->findInt32("channel-count", &numChannels) 2035 || !msg->findInt32("sample-rate", &sampleRate)) { 2036 err = INVALID_OPERATION; 2037 } else { 2038 int32_t isADTS, aacProfile; 2039 int32_t sbrMode; 2040 int32_t maxOutputChannelCount; 2041 int32_t pcmLimiterEnable; 2042 drcParams_t drc; 2043 if (!msg->findInt32("is-adts", &isADTS)) { 2044 isADTS = 0; 2045 } 2046 if (!msg->findInt32("aac-profile", &aacProfile)) { 2047 aacProfile = OMX_AUDIO_AACObjectNull; 2048 } 2049 if (!msg->findInt32("aac-sbr-mode", &sbrMode)) { 2050 sbrMode = -1; 2051 } 2052 2053 if (!msg->findInt32("aac-max-output-channel_count", &maxOutputChannelCount)) { 2054 maxOutputChannelCount = -1; 2055 } 2056 if (!msg->findInt32("aac-pcm-limiter-enable", &pcmLimiterEnable)) { 2057 // value is unknown 2058 pcmLimiterEnable = -1; 2059 } 2060 if (!msg->findInt32("aac-encoded-target-level", &drc.encodedTargetLevel)) { 2061 // value is unknown 2062 drc.encodedTargetLevel = -1; 2063 } 2064 if (!msg->findInt32("aac-drc-cut-level", &drc.drcCut)) { 2065 // value is unknown 2066 drc.drcCut = -1; 2067 } 2068 if (!msg->findInt32("aac-drc-boost-level", &drc.drcBoost)) { 2069 // value is unknown 2070 drc.drcBoost = -1; 2071 } 2072 if (!msg->findInt32("aac-drc-heavy-compression", &drc.heavyCompression)) { 2073 // value is unknown 2074 drc.heavyCompression = -1; 2075 } 2076 if (!msg->findInt32("aac-target-ref-level", &drc.targetRefLevel)) { 2077 // value is unknown 2078 drc.targetRefLevel = -1; 2079 } 2080 2081 err = setupAACCodec( 2082 encoder, numChannels, sampleRate, bitRate, aacProfile, 2083 isADTS != 0, sbrMode, maxOutputChannelCount, drc, 2084 pcmLimiterEnable); 2085 } 2086 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) { 2087 err = setupAMRCodec(encoder, false /* isWAMR */, bitRate); 2088 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) { 2089 err = setupAMRCodec(encoder, true /* isWAMR */, bitRate); 2090 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW) 2091 || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) { 2092 // These are PCM-like formats with a fixed sample rate but 2093 // a variable number of channels. 2094 2095 int32_t numChannels; 2096 if (!msg->findInt32("channel-count", &numChannels)) { 2097 err = INVALID_OPERATION; 2098 } else { 2099 int32_t sampleRate; 2100 if (!msg->findInt32("sample-rate", &sampleRate)) { 2101 sampleRate = 8000; 2102 } 2103 err = setupG711Codec(encoder, sampleRate, numChannels); 2104 } 2105 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) { 2106 int32_t numChannels = 0, sampleRate = 0, compressionLevel = -1; 2107 if (encoder && 2108 (!msg->findInt32("channel-count", &numChannels) 2109 || !msg->findInt32("sample-rate", &sampleRate))) { 2110 ALOGE("missing channel count or sample rate for FLAC encoder"); 2111 err = INVALID_OPERATION; 2112 } else { 2113 if (encoder) { 2114 if (!msg->findInt32( 2115 "complexity", &compressionLevel) && 2116 !msg->findInt32( 2117 "flac-compression-level", &compressionLevel)) { 2118 compressionLevel = 5; // default FLAC compression level 2119 } else if (compressionLevel < 0) { 2120 ALOGW("compression level %d outside [0..8] range, " 2121 "using 0", 2122 compressionLevel); 2123 compressionLevel = 0; 2124 } else if (compressionLevel > 8) { 2125 ALOGW("compression level %d outside [0..8] range, " 2126 "using 8", 2127 compressionLevel); 2128 compressionLevel = 8; 2129 } 2130 } 2131 err = setupFlacCodec( 2132 encoder, numChannels, sampleRate, compressionLevel); 2133 } 2134 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) { 2135 int32_t numChannels, sampleRate; 2136 if (encoder 2137 || !msg->findInt32("channel-count", &numChannels) 2138 || !msg->findInt32("sample-rate", &sampleRate)) { 2139 err = INVALID_OPERATION; 2140 } else { 2141 err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels); 2142 } 2143 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AC3)) { 2144 int32_t numChannels; 2145 int32_t sampleRate; 2146 if (!msg->findInt32("channel-count", &numChannels) 2147 || !msg->findInt32("sample-rate", &sampleRate)) { 2148 err = INVALID_OPERATION; 2149 } else { 2150 err = setupAC3Codec(encoder, numChannels, sampleRate); 2151 } 2152 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_EAC3)) { 2153 int32_t numChannels; 2154 int32_t sampleRate; 2155 if (!msg->findInt32("channel-count", &numChannels) 2156 || !msg->findInt32("sample-rate", &sampleRate)) { 2157 err = INVALID_OPERATION; 2158 } else { 2159 err = setupEAC3Codec(encoder, numChannels, sampleRate); 2160 } 2161 } 2162 2163 if (err != OK) { 2164 return err; 2165 } 2166 2167 if (!msg->findInt32("encoder-delay", &mEncoderDelay)) { 2168 mEncoderDelay = 0; 2169 } 2170 2171 if (!msg->findInt32("encoder-padding", &mEncoderPadding)) { 2172 mEncoderPadding = 0; 2173 } 2174 2175 if (msg->findInt32("channel-mask", &mChannelMask)) { 2176 mChannelMaskPresent = true; 2177 } else { 2178 mChannelMaskPresent = false; 2179 } 2180 2181 int32_t maxInputSize; 2182 if (msg->findInt32("max-input-size", &maxInputSize)) { 2183 err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize); 2184 } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) { 2185 err = setMinBufferSize(kPortIndexInput, 8192); // XXX 2186 } 2187 2188 int32_t priority; 2189 if (msg->findInt32("priority", &priority)) { 2190 err = setPriority(priority); 2191 } 2192 2193 int32_t rateInt = -1; 2194 float rateFloat = -1; 2195 if (!msg->findFloat("operating-rate", &rateFloat)) { 2196 msg->findInt32("operating-rate", &rateInt); 2197 rateFloat = (float)rateInt; // 16MHz (FLINTMAX) is OK for upper bound. 2198 } 2199 if (rateFloat > 0) { 2200 err = setOperatingRate(rateFloat, video); 2201 } 2202 2203 mBaseOutputFormat = outputFormat; 2204 // trigger a kWhatOutputFormatChanged msg on first buffer 2205 mLastOutputFormat.clear(); 2206 2207 err = getPortFormat(kPortIndexInput, inputFormat); 2208 if (err == OK) { 2209 err = getPortFormat(kPortIndexOutput, outputFormat); 2210 if (err == OK) { 2211 mInputFormat = inputFormat; 2212 mOutputFormat = outputFormat; 2213 } 2214 } 2215 return err; 2216} 2217 2218status_t ACodec::setPriority(int32_t priority) { 2219 if (priority < 0) { 2220 return BAD_VALUE; 2221 } 2222 OMX_PARAM_U32TYPE config; 2223 InitOMXParams(&config); 2224 config.nU32 = (OMX_U32)priority; 2225 status_t temp = mOMX->setConfig( 2226 mNode, (OMX_INDEXTYPE)OMX_IndexConfigPriority, 2227 &config, sizeof(config)); 2228 if (temp != OK) { 2229 ALOGI("codec does not support config priority (err %d)", temp); 2230 } 2231 return OK; 2232} 2233 2234status_t ACodec::setOperatingRate(float rateFloat, bool isVideo) { 2235 if (rateFloat < 0) { 2236 return BAD_VALUE; 2237 } 2238 OMX_U32 rate; 2239 if (isVideo) { 2240 if (rateFloat > 65535) { 2241 return BAD_VALUE; 2242 } 2243 rate = (OMX_U32)(rateFloat * 65536.0f + 0.5f); 2244 } else { 2245 if (rateFloat > UINT_MAX) { 2246 return BAD_VALUE; 2247 } 2248 rate = (OMX_U32)(rateFloat); 2249 } 2250 OMX_PARAM_U32TYPE config; 2251 InitOMXParams(&config); 2252 config.nU32 = rate; 2253 status_t err = mOMX->setConfig( 2254 mNode, (OMX_INDEXTYPE)OMX_IndexConfigOperatingRate, 2255 &config, sizeof(config)); 2256 if (err != OK) { 2257 ALOGI("codec does not support config operating rate (err %d)", err); 2258 } 2259 return OK; 2260} 2261 2262status_t ACodec::getIntraRefreshPeriod(uint32_t *intraRefreshPeriod) { 2263 OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params; 2264 InitOMXParams(¶ms); 2265 params.nPortIndex = kPortIndexOutput; 2266 status_t err = mOMX->getConfig( 2267 mNode, (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, ¶ms, sizeof(params)); 2268 if (err == OK) { 2269 *intraRefreshPeriod = params.nRefreshPeriod; 2270 return OK; 2271 } 2272 2273 // Fallback to query through standard OMX index. 2274 OMX_VIDEO_PARAM_INTRAREFRESHTYPE refreshParams; 2275 InitOMXParams(&refreshParams); 2276 refreshParams.nPortIndex = kPortIndexOutput; 2277 refreshParams.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic; 2278 err = mOMX->getParameter( 2279 mNode, OMX_IndexParamVideoIntraRefresh, &refreshParams, sizeof(refreshParams)); 2280 if (err != OK || refreshParams.nCirMBs == 0) { 2281 *intraRefreshPeriod = 0; 2282 return OK; 2283 } 2284 2285 // Calculate period based on width and height 2286 uint32_t width, height; 2287 OMX_PARAM_PORTDEFINITIONTYPE def; 2288 InitOMXParams(&def); 2289 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 2290 def.nPortIndex = kPortIndexOutput; 2291 err = mOMX->getParameter( 2292 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2293 if (err != OK) { 2294 *intraRefreshPeriod = 0; 2295 return err; 2296 } 2297 width = video_def->nFrameWidth; 2298 height = video_def->nFrameHeight; 2299 // Use H.264/AVC MacroBlock size 16x16 2300 *intraRefreshPeriod = divUp((divUp(width, 16u) * divUp(height, 16u)), refreshParams.nCirMBs); 2301 2302 return OK; 2303} 2304 2305status_t ACodec::setIntraRefreshPeriod(uint32_t intraRefreshPeriod, bool inConfigure) { 2306 OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params; 2307 InitOMXParams(¶ms); 2308 params.nPortIndex = kPortIndexOutput; 2309 params.nRefreshPeriod = intraRefreshPeriod; 2310 status_t err = mOMX->setConfig( 2311 mNode, (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, ¶ms, sizeof(params)); 2312 if (err == OK) { 2313 return OK; 2314 } 2315 2316 // Only in configure state, a component could invoke setParameter. 2317 if (!inConfigure) { 2318 return INVALID_OPERATION; 2319 } else { 2320 ALOGI("[%s] try falling back to Cyclic", mComponentName.c_str()); 2321 } 2322 2323 OMX_VIDEO_PARAM_INTRAREFRESHTYPE refreshParams; 2324 InitOMXParams(&refreshParams); 2325 refreshParams.nPortIndex = kPortIndexOutput; 2326 refreshParams.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic; 2327 2328 if (intraRefreshPeriod == 0) { 2329 // 0 means disable intra refresh. 2330 refreshParams.nCirMBs = 0; 2331 } else { 2332 // Calculate macroblocks that need to be intra coded base on width and height 2333 uint32_t width, height; 2334 OMX_PARAM_PORTDEFINITIONTYPE def; 2335 InitOMXParams(&def); 2336 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 2337 def.nPortIndex = kPortIndexOutput; 2338 err = mOMX->getParameter( 2339 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2340 if (err != OK) { 2341 return err; 2342 } 2343 width = video_def->nFrameWidth; 2344 height = video_def->nFrameHeight; 2345 // Use H.264/AVC MacroBlock size 16x16 2346 refreshParams.nCirMBs = divUp((divUp(width, 16u) * divUp(height, 16u)), intraRefreshPeriod); 2347 } 2348 2349 err = mOMX->setParameter(mNode, OMX_IndexParamVideoIntraRefresh, 2350 &refreshParams, sizeof(refreshParams)); 2351 if (err != OK) { 2352 return err; 2353 } 2354 2355 return OK; 2356} 2357 2358status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) { 2359 OMX_PARAM_PORTDEFINITIONTYPE def; 2360 InitOMXParams(&def); 2361 def.nPortIndex = portIndex; 2362 2363 status_t err = mOMX->getParameter( 2364 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2365 2366 if (err != OK) { 2367 return err; 2368 } 2369 2370 if (def.nBufferSize >= size) { 2371 return OK; 2372 } 2373 2374 def.nBufferSize = size; 2375 2376 err = mOMX->setParameter( 2377 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2378 2379 if (err != OK) { 2380 return err; 2381 } 2382 2383 err = mOMX->getParameter( 2384 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2385 2386 if (err != OK) { 2387 return err; 2388 } 2389 2390 if (def.nBufferSize < size) { 2391 ALOGE("failed to set min buffer size to %zu (is still %u)", size, def.nBufferSize); 2392 return FAILED_TRANSACTION; 2393 } 2394 2395 return OK; 2396} 2397 2398status_t ACodec::selectAudioPortFormat( 2399 OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) { 2400 OMX_AUDIO_PARAM_PORTFORMATTYPE format; 2401 InitOMXParams(&format); 2402 2403 format.nPortIndex = portIndex; 2404 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { 2405 format.nIndex = index; 2406 status_t err = mOMX->getParameter( 2407 mNode, OMX_IndexParamAudioPortFormat, 2408 &format, sizeof(format)); 2409 2410 if (err != OK) { 2411 return err; 2412 } 2413 2414 if (format.eEncoding == desiredFormat) { 2415 break; 2416 } 2417 2418 if (index == kMaxIndicesToCheck) { 2419 ALOGW("[%s] stopping checking formats after %u: %s(%x)", 2420 mComponentName.c_str(), index, 2421 asString(format.eEncoding), format.eEncoding); 2422 return ERROR_UNSUPPORTED; 2423 } 2424 } 2425 2426 return mOMX->setParameter( 2427 mNode, OMX_IndexParamAudioPortFormat, &format, sizeof(format)); 2428} 2429 2430status_t ACodec::setupAACCodec( 2431 bool encoder, int32_t numChannels, int32_t sampleRate, 2432 int32_t bitRate, int32_t aacProfile, bool isADTS, int32_t sbrMode, 2433 int32_t maxOutputChannelCount, const drcParams_t& drc, 2434 int32_t pcmLimiterEnable) { 2435 if (encoder && isADTS) { 2436 return -EINVAL; 2437 } 2438 2439 status_t err = setupRawAudioFormat( 2440 encoder ? kPortIndexInput : kPortIndexOutput, 2441 sampleRate, 2442 numChannels); 2443 2444 if (err != OK) { 2445 return err; 2446 } 2447 2448 if (encoder) { 2449 err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC); 2450 2451 if (err != OK) { 2452 return err; 2453 } 2454 2455 OMX_PARAM_PORTDEFINITIONTYPE def; 2456 InitOMXParams(&def); 2457 def.nPortIndex = kPortIndexOutput; 2458 2459 err = mOMX->getParameter( 2460 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2461 2462 if (err != OK) { 2463 return err; 2464 } 2465 2466 def.format.audio.bFlagErrorConcealment = OMX_TRUE; 2467 def.format.audio.eEncoding = OMX_AUDIO_CodingAAC; 2468 2469 err = mOMX->setParameter( 2470 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2471 2472 if (err != OK) { 2473 return err; 2474 } 2475 2476 OMX_AUDIO_PARAM_AACPROFILETYPE profile; 2477 InitOMXParams(&profile); 2478 profile.nPortIndex = kPortIndexOutput; 2479 2480 err = mOMX->getParameter( 2481 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 2482 2483 if (err != OK) { 2484 return err; 2485 } 2486 2487 profile.nChannels = numChannels; 2488 2489 profile.eChannelMode = 2490 (numChannels == 1) 2491 ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo; 2492 2493 profile.nSampleRate = sampleRate; 2494 profile.nBitRate = bitRate; 2495 profile.nAudioBandWidth = 0; 2496 profile.nFrameLength = 0; 2497 profile.nAACtools = OMX_AUDIO_AACToolAll; 2498 profile.nAACERtools = OMX_AUDIO_AACERNone; 2499 profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile; 2500 profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF; 2501 switch (sbrMode) { 2502 case 0: 2503 // disable sbr 2504 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR; 2505 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR; 2506 break; 2507 case 1: 2508 // enable single-rate sbr 2509 profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR; 2510 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR; 2511 break; 2512 case 2: 2513 // enable dual-rate sbr 2514 profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR; 2515 profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR; 2516 break; 2517 case -1: 2518 // enable both modes -> the codec will decide which mode should be used 2519 profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR; 2520 profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR; 2521 break; 2522 default: 2523 // unsupported sbr mode 2524 return BAD_VALUE; 2525 } 2526 2527 2528 err = mOMX->setParameter( 2529 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 2530 2531 if (err != OK) { 2532 return err; 2533 } 2534 2535 return err; 2536 } 2537 2538 OMX_AUDIO_PARAM_AACPROFILETYPE profile; 2539 InitOMXParams(&profile); 2540 profile.nPortIndex = kPortIndexInput; 2541 2542 err = mOMX->getParameter( 2543 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 2544 2545 if (err != OK) { 2546 return err; 2547 } 2548 2549 profile.nChannels = numChannels; 2550 profile.nSampleRate = sampleRate; 2551 2552 profile.eAACStreamFormat = 2553 isADTS 2554 ? OMX_AUDIO_AACStreamFormatMP4ADTS 2555 : OMX_AUDIO_AACStreamFormatMP4FF; 2556 2557 OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE presentation; 2558 InitOMXParams(&presentation); 2559 presentation.nMaxOutputChannels = maxOutputChannelCount; 2560 presentation.nDrcCut = drc.drcCut; 2561 presentation.nDrcBoost = drc.drcBoost; 2562 presentation.nHeavyCompression = drc.heavyCompression; 2563 presentation.nTargetReferenceLevel = drc.targetRefLevel; 2564 presentation.nEncodedTargetLevel = drc.encodedTargetLevel; 2565 presentation.nPCMLimiterEnable = pcmLimiterEnable; 2566 2567 status_t res = mOMX->setParameter(mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 2568 if (res == OK) { 2569 // optional parameters, will not cause configuration failure 2570 mOMX->setParameter(mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacPresentation, 2571 &presentation, sizeof(presentation)); 2572 } else { 2573 ALOGW("did not set AudioAndroidAacPresentation due to error %d when setting AudioAac", res); 2574 } 2575 return res; 2576} 2577 2578status_t ACodec::setupAC3Codec( 2579 bool encoder, int32_t numChannels, int32_t sampleRate) { 2580 status_t err = setupRawAudioFormat( 2581 encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels); 2582 2583 if (err != OK) { 2584 return err; 2585 } 2586 2587 if (encoder) { 2588 ALOGW("AC3 encoding is not supported."); 2589 return INVALID_OPERATION; 2590 } 2591 2592 OMX_AUDIO_PARAM_ANDROID_AC3TYPE def; 2593 InitOMXParams(&def); 2594 def.nPortIndex = kPortIndexInput; 2595 2596 err = mOMX->getParameter( 2597 mNode, 2598 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, 2599 &def, 2600 sizeof(def)); 2601 2602 if (err != OK) { 2603 return err; 2604 } 2605 2606 def.nChannels = numChannels; 2607 def.nSampleRate = sampleRate; 2608 2609 return mOMX->setParameter( 2610 mNode, 2611 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, 2612 &def, 2613 sizeof(def)); 2614} 2615 2616status_t ACodec::setupEAC3Codec( 2617 bool encoder, int32_t numChannels, int32_t sampleRate) { 2618 status_t err = setupRawAudioFormat( 2619 encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels); 2620 2621 if (err != OK) { 2622 return err; 2623 } 2624 2625 if (encoder) { 2626 ALOGW("EAC3 encoding is not supported."); 2627 return INVALID_OPERATION; 2628 } 2629 2630 OMX_AUDIO_PARAM_ANDROID_EAC3TYPE def; 2631 InitOMXParams(&def); 2632 def.nPortIndex = kPortIndexInput; 2633 2634 err = mOMX->getParameter( 2635 mNode, 2636 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, 2637 &def, 2638 sizeof(def)); 2639 2640 if (err != OK) { 2641 return err; 2642 } 2643 2644 def.nChannels = numChannels; 2645 def.nSampleRate = sampleRate; 2646 2647 return mOMX->setParameter( 2648 mNode, 2649 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, 2650 &def, 2651 sizeof(def)); 2652} 2653 2654static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate( 2655 bool isAMRWB, int32_t bps) { 2656 if (isAMRWB) { 2657 if (bps <= 6600) { 2658 return OMX_AUDIO_AMRBandModeWB0; 2659 } else if (bps <= 8850) { 2660 return OMX_AUDIO_AMRBandModeWB1; 2661 } else if (bps <= 12650) { 2662 return OMX_AUDIO_AMRBandModeWB2; 2663 } else if (bps <= 14250) { 2664 return OMX_AUDIO_AMRBandModeWB3; 2665 } else if (bps <= 15850) { 2666 return OMX_AUDIO_AMRBandModeWB4; 2667 } else if (bps <= 18250) { 2668 return OMX_AUDIO_AMRBandModeWB5; 2669 } else if (bps <= 19850) { 2670 return OMX_AUDIO_AMRBandModeWB6; 2671 } else if (bps <= 23050) { 2672 return OMX_AUDIO_AMRBandModeWB7; 2673 } 2674 2675 // 23850 bps 2676 return OMX_AUDIO_AMRBandModeWB8; 2677 } else { // AMRNB 2678 if (bps <= 4750) { 2679 return OMX_AUDIO_AMRBandModeNB0; 2680 } else if (bps <= 5150) { 2681 return OMX_AUDIO_AMRBandModeNB1; 2682 } else if (bps <= 5900) { 2683 return OMX_AUDIO_AMRBandModeNB2; 2684 } else if (bps <= 6700) { 2685 return OMX_AUDIO_AMRBandModeNB3; 2686 } else if (bps <= 7400) { 2687 return OMX_AUDIO_AMRBandModeNB4; 2688 } else if (bps <= 7950) { 2689 return OMX_AUDIO_AMRBandModeNB5; 2690 } else if (bps <= 10200) { 2691 return OMX_AUDIO_AMRBandModeNB6; 2692 } 2693 2694 // 12200 bps 2695 return OMX_AUDIO_AMRBandModeNB7; 2696 } 2697} 2698 2699status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) { 2700 OMX_AUDIO_PARAM_AMRTYPE def; 2701 InitOMXParams(&def); 2702 def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput; 2703 2704 status_t err = 2705 mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); 2706 2707 if (err != OK) { 2708 return err; 2709 } 2710 2711 def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF; 2712 def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate); 2713 2714 err = mOMX->setParameter( 2715 mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); 2716 2717 if (err != OK) { 2718 return err; 2719 } 2720 2721 return setupRawAudioFormat( 2722 encoder ? kPortIndexInput : kPortIndexOutput, 2723 isWAMR ? 16000 : 8000 /* sampleRate */, 2724 1 /* numChannels */); 2725} 2726 2727status_t ACodec::setupG711Codec(bool encoder, int32_t sampleRate, int32_t numChannels) { 2728 if (encoder) { 2729 return INVALID_OPERATION; 2730 } 2731 2732 return setupRawAudioFormat( 2733 kPortIndexInput, sampleRate, numChannels); 2734} 2735 2736status_t ACodec::setupFlacCodec( 2737 bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel) { 2738 2739 if (encoder) { 2740 OMX_AUDIO_PARAM_FLACTYPE def; 2741 InitOMXParams(&def); 2742 def.nPortIndex = kPortIndexOutput; 2743 2744 // configure compression level 2745 status_t err = mOMX->getParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def)); 2746 if (err != OK) { 2747 ALOGE("setupFlacCodec(): Error %d getting OMX_IndexParamAudioFlac parameter", err); 2748 return err; 2749 } 2750 def.nCompressionLevel = compressionLevel; 2751 err = mOMX->setParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def)); 2752 if (err != OK) { 2753 ALOGE("setupFlacCodec(): Error %d setting OMX_IndexParamAudioFlac parameter", err); 2754 return err; 2755 } 2756 } 2757 2758 return setupRawAudioFormat( 2759 encoder ? kPortIndexInput : kPortIndexOutput, 2760 sampleRate, 2761 numChannels); 2762} 2763 2764status_t ACodec::setupRawAudioFormat( 2765 OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) { 2766 OMX_PARAM_PORTDEFINITIONTYPE def; 2767 InitOMXParams(&def); 2768 def.nPortIndex = portIndex; 2769 2770 status_t err = mOMX->getParameter( 2771 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2772 2773 if (err != OK) { 2774 return err; 2775 } 2776 2777 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; 2778 2779 err = mOMX->setParameter( 2780 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2781 2782 if (err != OK) { 2783 return err; 2784 } 2785 2786 OMX_AUDIO_PARAM_PCMMODETYPE pcmParams; 2787 InitOMXParams(&pcmParams); 2788 pcmParams.nPortIndex = portIndex; 2789 2790 err = mOMX->getParameter( 2791 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); 2792 2793 if (err != OK) { 2794 return err; 2795 } 2796 2797 pcmParams.nChannels = numChannels; 2798 pcmParams.eNumData = OMX_NumericalDataSigned; 2799 pcmParams.bInterleaved = OMX_TRUE; 2800 pcmParams.nBitPerSample = 16; 2801 pcmParams.nSamplingRate = sampleRate; 2802 pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear; 2803 2804 if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) { 2805 return OMX_ErrorNone; 2806 } 2807 2808 return mOMX->setParameter( 2809 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); 2810} 2811 2812status_t ACodec::configureTunneledVideoPlayback( 2813 int32_t audioHwSync, const sp<ANativeWindow> &nativeWindow) { 2814 native_handle_t* sidebandHandle; 2815 2816 status_t err = mOMX->configureVideoTunnelMode( 2817 mNode, kPortIndexOutput, OMX_TRUE, audioHwSync, &sidebandHandle); 2818 if (err != OK) { 2819 ALOGE("configureVideoTunnelMode failed! (err %d).", err); 2820 return err; 2821 } 2822 2823 err = native_window_set_sideband_stream(nativeWindow.get(), sidebandHandle); 2824 if (err != OK) { 2825 ALOGE("native_window_set_sideband_stream(%p) failed! (err %d).", 2826 sidebandHandle, err); 2827 return err; 2828 } 2829 2830 return OK; 2831} 2832 2833status_t ACodec::setVideoPortFormatType( 2834 OMX_U32 portIndex, 2835 OMX_VIDEO_CODINGTYPE compressionFormat, 2836 OMX_COLOR_FORMATTYPE colorFormat, 2837 bool usingNativeBuffers) { 2838 OMX_VIDEO_PARAM_PORTFORMATTYPE format; 2839 InitOMXParams(&format); 2840 format.nPortIndex = portIndex; 2841 format.nIndex = 0; 2842 bool found = false; 2843 2844 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { 2845 format.nIndex = index; 2846 status_t err = mOMX->getParameter( 2847 mNode, OMX_IndexParamVideoPortFormat, 2848 &format, sizeof(format)); 2849 2850 if (err != OK) { 2851 return err; 2852 } 2853 2854 // substitute back flexible color format to codec supported format 2855 OMX_U32 flexibleEquivalent; 2856 if (compressionFormat == OMX_VIDEO_CodingUnused 2857 && isFlexibleColorFormat( 2858 mOMX, mNode, format.eColorFormat, usingNativeBuffers, &flexibleEquivalent) 2859 && colorFormat == flexibleEquivalent) { 2860 ALOGI("[%s] using color format %#x in place of %#x", 2861 mComponentName.c_str(), format.eColorFormat, colorFormat); 2862 colorFormat = format.eColorFormat; 2863 } 2864 2865 // The following assertion is violated by TI's video decoder. 2866 // CHECK_EQ(format.nIndex, index); 2867 2868 if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) { 2869 if (portIndex == kPortIndexInput 2870 && colorFormat == format.eColorFormat) { 2871 // eCompressionFormat does not seem right. 2872 found = true; 2873 break; 2874 } 2875 if (portIndex == kPortIndexOutput 2876 && compressionFormat == format.eCompressionFormat) { 2877 // eColorFormat does not seem right. 2878 found = true; 2879 break; 2880 } 2881 } 2882 2883 if (format.eCompressionFormat == compressionFormat 2884 && format.eColorFormat == colorFormat) { 2885 found = true; 2886 break; 2887 } 2888 2889 if (index == kMaxIndicesToCheck) { 2890 ALOGW("[%s] stopping checking formats after %u: %s(%x)/%s(%x)", 2891 mComponentName.c_str(), index, 2892 asString(format.eCompressionFormat), format.eCompressionFormat, 2893 asString(format.eColorFormat), format.eColorFormat); 2894 } 2895 } 2896 2897 if (!found) { 2898 return UNKNOWN_ERROR; 2899 } 2900 2901 status_t err = mOMX->setParameter( 2902 mNode, OMX_IndexParamVideoPortFormat, 2903 &format, sizeof(format)); 2904 2905 return err; 2906} 2907 2908// Set optimal output format. OMX component lists output formats in the order 2909// of preference, but this got more complicated since the introduction of flexible 2910// YUV formats. We support a legacy behavior for applications that do not use 2911// surface output, do not specify an output format, but expect a "usable" standard 2912// OMX format. SW readable and standard formats must be flex-YUV. 2913// 2914// Suggested preference order: 2915// - optimal format for texture rendering (mediaplayer behavior) 2916// - optimal SW readable & texture renderable format (flex-YUV support) 2917// - optimal SW readable non-renderable format (flex-YUV bytebuffer support) 2918// - legacy "usable" standard formats 2919// 2920// For legacy support, we prefer a standard format, but will settle for a SW readable 2921// flex-YUV format. 2922status_t ACodec::setSupportedOutputFormat(bool getLegacyFlexibleFormat) { 2923 OMX_VIDEO_PARAM_PORTFORMATTYPE format, legacyFormat; 2924 InitOMXParams(&format); 2925 format.nPortIndex = kPortIndexOutput; 2926 2927 InitOMXParams(&legacyFormat); 2928 // this field will change when we find a suitable legacy format 2929 legacyFormat.eColorFormat = OMX_COLOR_FormatUnused; 2930 2931 for (OMX_U32 index = 0; ; ++index) { 2932 format.nIndex = index; 2933 status_t err = mOMX->getParameter( 2934 mNode, OMX_IndexParamVideoPortFormat, 2935 &format, sizeof(format)); 2936 if (err != OK) { 2937 // no more formats, pick legacy format if found 2938 if (legacyFormat.eColorFormat != OMX_COLOR_FormatUnused) { 2939 memcpy(&format, &legacyFormat, sizeof(format)); 2940 break; 2941 } 2942 return err; 2943 } 2944 if (format.eCompressionFormat != OMX_VIDEO_CodingUnused) { 2945 return OMX_ErrorBadParameter; 2946 } 2947 if (!getLegacyFlexibleFormat) { 2948 break; 2949 } 2950 // standard formats that were exposed to users before 2951 if (format.eColorFormat == OMX_COLOR_FormatYUV420Planar 2952 || format.eColorFormat == OMX_COLOR_FormatYUV420PackedPlanar 2953 || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar 2954 || format.eColorFormat == OMX_COLOR_FormatYUV420PackedSemiPlanar 2955 || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar) { 2956 break; 2957 } 2958 // find best legacy non-standard format 2959 OMX_U32 flexibleEquivalent; 2960 if (legacyFormat.eColorFormat == OMX_COLOR_FormatUnused 2961 && isFlexibleColorFormat( 2962 mOMX, mNode, format.eColorFormat, false /* usingNativeBuffers */, 2963 &flexibleEquivalent) 2964 && flexibleEquivalent == OMX_COLOR_FormatYUV420Flexible) { 2965 memcpy(&legacyFormat, &format, sizeof(format)); 2966 } 2967 } 2968 return mOMX->setParameter( 2969 mNode, OMX_IndexParamVideoPortFormat, 2970 &format, sizeof(format)); 2971} 2972 2973static const struct VideoCodingMapEntry { 2974 const char *mMime; 2975 OMX_VIDEO_CODINGTYPE mVideoCodingType; 2976} kVideoCodingMapEntry[] = { 2977 { MEDIA_MIMETYPE_VIDEO_AVC, OMX_VIDEO_CodingAVC }, 2978 { MEDIA_MIMETYPE_VIDEO_HEVC, OMX_VIDEO_CodingHEVC }, 2979 { MEDIA_MIMETYPE_VIDEO_MPEG4, OMX_VIDEO_CodingMPEG4 }, 2980 { MEDIA_MIMETYPE_VIDEO_H263, OMX_VIDEO_CodingH263 }, 2981 { MEDIA_MIMETYPE_VIDEO_MPEG2, OMX_VIDEO_CodingMPEG2 }, 2982 { MEDIA_MIMETYPE_VIDEO_VP8, OMX_VIDEO_CodingVP8 }, 2983 { MEDIA_MIMETYPE_VIDEO_VP9, OMX_VIDEO_CodingVP9 }, 2984 { MEDIA_MIMETYPE_VIDEO_DOLBY_VISION, OMX_VIDEO_CodingDolbyVision }, 2985}; 2986 2987static status_t GetVideoCodingTypeFromMime( 2988 const char *mime, OMX_VIDEO_CODINGTYPE *codingType) { 2989 for (size_t i = 0; 2990 i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]); 2991 ++i) { 2992 if (!strcasecmp(mime, kVideoCodingMapEntry[i].mMime)) { 2993 *codingType = kVideoCodingMapEntry[i].mVideoCodingType; 2994 return OK; 2995 } 2996 } 2997 2998 *codingType = OMX_VIDEO_CodingUnused; 2999 3000 return ERROR_UNSUPPORTED; 3001} 3002 3003static status_t GetMimeTypeForVideoCoding( 3004 OMX_VIDEO_CODINGTYPE codingType, AString *mime) { 3005 for (size_t i = 0; 3006 i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]); 3007 ++i) { 3008 if (codingType == kVideoCodingMapEntry[i].mVideoCodingType) { 3009 *mime = kVideoCodingMapEntry[i].mMime; 3010 return OK; 3011 } 3012 } 3013 3014 mime->clear(); 3015 3016 return ERROR_UNSUPPORTED; 3017} 3018 3019status_t ACodec::setupVideoDecoder( 3020 const char *mime, const sp<AMessage> &msg, bool haveNativeWindow, 3021 bool usingSwRenderer, sp<AMessage> &outputFormat) { 3022 int32_t width, height; 3023 if (!msg->findInt32("width", &width) 3024 || !msg->findInt32("height", &height)) { 3025 return INVALID_OPERATION; 3026 } 3027 3028 OMX_VIDEO_CODINGTYPE compressionFormat; 3029 status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat); 3030 3031 if (err != OK) { 3032 return err; 3033 } 3034 3035 err = setVideoPortFormatType( 3036 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused); 3037 3038 if (err != OK) { 3039 return err; 3040 } 3041 3042 int32_t tmp; 3043 if (msg->findInt32("color-format", &tmp)) { 3044 OMX_COLOR_FORMATTYPE colorFormat = 3045 static_cast<OMX_COLOR_FORMATTYPE>(tmp); 3046 err = setVideoPortFormatType( 3047 kPortIndexOutput, OMX_VIDEO_CodingUnused, colorFormat, haveNativeWindow); 3048 if (err != OK) { 3049 ALOGW("[%s] does not support color format %d", 3050 mComponentName.c_str(), colorFormat); 3051 err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */); 3052 } 3053 } else { 3054 err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */); 3055 } 3056 3057 if (err != OK) { 3058 return err; 3059 } 3060 3061 int32_t frameRateInt; 3062 float frameRateFloat; 3063 if (!msg->findFloat("frame-rate", &frameRateFloat)) { 3064 if (!msg->findInt32("frame-rate", &frameRateInt)) { 3065 frameRateInt = -1; 3066 } 3067 frameRateFloat = (float)frameRateInt; 3068 } 3069 3070 err = setVideoFormatOnPort( 3071 kPortIndexInput, width, height, compressionFormat, frameRateFloat); 3072 3073 if (err != OK) { 3074 return err; 3075 } 3076 3077 err = setVideoFormatOnPort( 3078 kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused); 3079 3080 if (err != OK) { 3081 return err; 3082 } 3083 3084 err = setColorAspectsForVideoDecoder( 3085 width, height, haveNativeWindow | usingSwRenderer, msg, outputFormat); 3086 if (err == ERROR_UNSUPPORTED) { // support is optional 3087 err = OK; 3088 } 3089 return err; 3090} 3091 3092status_t ACodec::initDescribeColorAspectsIndex() { 3093 status_t err = mOMX->getExtensionIndex( 3094 mNode, "OMX.google.android.index.describeColorAspects", &mDescribeColorAspectsIndex); 3095 if (err != OK) { 3096 mDescribeColorAspectsIndex = (OMX_INDEXTYPE)0; 3097 } 3098 return err; 3099} 3100 3101status_t ACodec::setCodecColorAspects(DescribeColorAspectsParams ¶ms, bool verify) { 3102 status_t err = ERROR_UNSUPPORTED; 3103 if (mDescribeColorAspectsIndex) { 3104 err = mOMX->setConfig(mNode, mDescribeColorAspectsIndex, ¶ms, sizeof(params)); 3105 } 3106 ALOGV("[%s] setting color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)", 3107 mComponentName.c_str(), 3108 params.sAspects.mRange, asString(params.sAspects.mRange), 3109 params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries), 3110 params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs), 3111 params.sAspects.mTransfer, asString(params.sAspects.mTransfer), 3112 err, asString(err)); 3113 3114 if (verify && err == OK) { 3115 err = getCodecColorAspects(params); 3116 } 3117 3118 ALOGW_IF(err == ERROR_UNSUPPORTED && mDescribeColorAspectsIndex, 3119 "[%s] getting color aspects failed even though codec advertises support", 3120 mComponentName.c_str()); 3121 return err; 3122} 3123 3124status_t ACodec::setColorAspectsForVideoDecoder( 3125 int32_t width, int32_t height, bool usingNativeWindow, 3126 const sp<AMessage> &configFormat, sp<AMessage> &outputFormat) { 3127 DescribeColorAspectsParams params; 3128 InitOMXParams(¶ms); 3129 params.nPortIndex = kPortIndexOutput; 3130 3131 getColorAspectsFromFormat(configFormat, params.sAspects); 3132 if (usingNativeWindow) { 3133 setDefaultCodecColorAspectsIfNeeded(params.sAspects, width, height); 3134 // The default aspects will be set back to the output format during the 3135 // getFormat phase of configure(). Set non-Unspecified values back into the 3136 // format, in case component does not support this enumeration. 3137 setColorAspectsIntoFormat(params.sAspects, outputFormat); 3138 } 3139 3140 (void)initDescribeColorAspectsIndex(); 3141 3142 // communicate color aspects to codec 3143 return setCodecColorAspects(params); 3144} 3145 3146status_t ACodec::getCodecColorAspects(DescribeColorAspectsParams ¶ms) { 3147 status_t err = ERROR_UNSUPPORTED; 3148 if (mDescribeColorAspectsIndex) { 3149 err = mOMX->getConfig(mNode, mDescribeColorAspectsIndex, ¶ms, sizeof(params)); 3150 } 3151 ALOGV("[%s] got color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)", 3152 mComponentName.c_str(), 3153 params.sAspects.mRange, asString(params.sAspects.mRange), 3154 params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries), 3155 params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs), 3156 params.sAspects.mTransfer, asString(params.sAspects.mTransfer), 3157 err, asString(err)); 3158 if (params.bRequestingDataSpace) { 3159 ALOGV("for dataspace %#x", params.nDataSpace); 3160 } 3161 if (err == ERROR_UNSUPPORTED && mDescribeColorAspectsIndex 3162 && !params.bRequestingDataSpace && !params.bDataSpaceChanged) { 3163 ALOGW("[%s] getting color aspects failed even though codec advertises support", 3164 mComponentName.c_str()); 3165 } 3166 return err; 3167} 3168 3169status_t ACodec::getInputColorAspectsForVideoEncoder(sp<AMessage> &format) { 3170 DescribeColorAspectsParams params; 3171 InitOMXParams(¶ms); 3172 params.nPortIndex = kPortIndexInput; 3173 status_t err = getCodecColorAspects(params); 3174 if (err == OK) { 3175 // we only set encoder input aspects if codec supports them 3176 setColorAspectsIntoFormat(params.sAspects, format, true /* force */); 3177 } 3178 return err; 3179} 3180 3181status_t ACodec::getDataSpace( 3182 DescribeColorAspectsParams ¶ms, android_dataspace *dataSpace /* nonnull */, 3183 bool tryCodec) { 3184 status_t err = OK; 3185 if (tryCodec) { 3186 // request dataspace guidance from codec. 3187 params.bRequestingDataSpace = OMX_TRUE; 3188 err = getCodecColorAspects(params); 3189 params.bRequestingDataSpace = OMX_FALSE; 3190 if (err == OK && params.nDataSpace != HAL_DATASPACE_UNKNOWN) { 3191 *dataSpace = (android_dataspace)params.nDataSpace; 3192 return err; 3193 } else if (err == ERROR_UNSUPPORTED) { 3194 // ignore not-implemented error for dataspace requests 3195 err = OK; 3196 } 3197 } 3198 3199 // this returns legacy versions if available 3200 *dataSpace = getDataSpaceForColorAspects(params.sAspects, true /* mayexpand */); 3201 ALOGV("[%s] using color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) " 3202 "and dataspace %#x", 3203 mComponentName.c_str(), 3204 params.sAspects.mRange, asString(params.sAspects.mRange), 3205 params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries), 3206 params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs), 3207 params.sAspects.mTransfer, asString(params.sAspects.mTransfer), 3208 *dataSpace); 3209 return err; 3210} 3211 3212 3213status_t ACodec::getColorAspectsAndDataSpaceForVideoDecoder( 3214 int32_t width, int32_t height, const sp<AMessage> &configFormat, sp<AMessage> &outputFormat, 3215 android_dataspace *dataSpace) { 3216 DescribeColorAspectsParams params; 3217 InitOMXParams(¶ms); 3218 params.nPortIndex = kPortIndexOutput; 3219 3220 // reset default format and get resulting format 3221 getColorAspectsFromFormat(configFormat, params.sAspects); 3222 if (dataSpace != NULL) { 3223 setDefaultCodecColorAspectsIfNeeded(params.sAspects, width, height); 3224 } 3225 status_t err = setCodecColorAspects(params, true /* readBack */); 3226 3227 // we always set specified aspects for decoders 3228 setColorAspectsIntoFormat(params.sAspects, outputFormat); 3229 3230 if (dataSpace != NULL) { 3231 status_t res = getDataSpace(params, dataSpace, err == OK /* tryCodec */); 3232 if (err == OK) { 3233 err = res; 3234 } 3235 } 3236 3237 return err; 3238} 3239 3240// initial video encoder setup for bytebuffer mode 3241status_t ACodec::setColorAspectsForVideoEncoder( 3242 const sp<AMessage> &configFormat, sp<AMessage> &outputFormat, sp<AMessage> &inputFormat) { 3243 // copy config to output format as this is not exposed via getFormat 3244 copyColorConfig(configFormat, outputFormat); 3245 3246 DescribeColorAspectsParams params; 3247 InitOMXParams(¶ms); 3248 params.nPortIndex = kPortIndexInput; 3249 getColorAspectsFromFormat(configFormat, params.sAspects); 3250 3251 (void)initDescribeColorAspectsIndex(); 3252 3253 int32_t usingRecorder; 3254 if (configFormat->findInt32("android._using-recorder", &usingRecorder) && usingRecorder) { 3255 android_dataspace dataSpace = HAL_DATASPACE_BT709; 3256 int32_t width, height; 3257 if (configFormat->findInt32("width", &width) 3258 && configFormat->findInt32("height", &height)) { 3259 setDefaultCodecColorAspectsIfNeeded(params.sAspects, width, height); 3260 status_t err = getDataSpace( 3261 params, &dataSpace, mDescribeColorAspectsIndex /* tryCodec */); 3262 if (err != OK) { 3263 return err; 3264 } 3265 setColorAspectsIntoFormat(params.sAspects, outputFormat); 3266 } 3267 inputFormat->setInt32("android._dataspace", (int32_t)dataSpace); 3268 } 3269 3270 // communicate color aspects to codec, but do not allow change of the platform aspects 3271 ColorAspects origAspects = params.sAspects; 3272 for (int triesLeft = 2; --triesLeft >= 0; ) { 3273 status_t err = setCodecColorAspects(params, true /* readBack */); 3274 if (err != OK 3275 || !ColorUtils::checkIfAspectsChangedAndUnspecifyThem( 3276 params.sAspects, origAspects, true /* usePlatformAspects */)) { 3277 return err; 3278 } 3279 ALOGW_IF(triesLeft == 0, "[%s] Codec repeatedly changed requested ColorAspects.", 3280 mComponentName.c_str()); 3281 } 3282 return OK; 3283} 3284 3285// subsequent initial video encoder setup for surface mode 3286status_t ACodec::setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace( 3287 android_dataspace *dataSpace /* nonnull */) { 3288 DescribeColorAspectsParams params; 3289 InitOMXParams(¶ms); 3290 params.nPortIndex = kPortIndexInput; 3291 ColorAspects &aspects = params.sAspects; 3292 3293 // reset default format and store resulting format into both input and output formats 3294 getColorAspectsFromFormat(mConfigFormat, aspects); 3295 int32_t width, height; 3296 if (mInputFormat->findInt32("width", &width) && mInputFormat->findInt32("height", &height)) { 3297 setDefaultCodecColorAspectsIfNeeded(aspects, width, height); 3298 } 3299 setColorAspectsIntoFormat(aspects, mInputFormat); 3300 setColorAspectsIntoFormat(aspects, mOutputFormat); 3301 3302 // communicate color aspects to codec, but do not allow any change 3303 ColorAspects origAspects = aspects; 3304 status_t err = OK; 3305 for (int triesLeft = 2; mDescribeColorAspectsIndex && --triesLeft >= 0; ) { 3306 status_t err = setCodecColorAspects(params, true /* readBack */); 3307 if (err != OK || !ColorUtils::checkIfAspectsChangedAndUnspecifyThem(aspects, origAspects)) { 3308 break; 3309 } 3310 ALOGW_IF(triesLeft == 0, "[%s] Codec repeatedly changed requested ColorAspects.", 3311 mComponentName.c_str()); 3312 } 3313 3314 *dataSpace = HAL_DATASPACE_BT709; 3315 aspects = origAspects; // restore desired color aspects 3316 status_t res = getDataSpace( 3317 params, dataSpace, err == OK && mDescribeColorAspectsIndex /* tryCodec */); 3318 if (err == OK) { 3319 err = res; 3320 } 3321 mInputFormat->setInt32("android._dataspace", (int32_t)*dataSpace); 3322 mInputFormat->setBuffer( 3323 "android._color-aspects", ABuffer::CreateAsCopy(&aspects, sizeof(aspects))); 3324 3325 // update input format with codec supported color aspects (basically set unsupported 3326 // aspects to Unspecified) 3327 if (err == OK) { 3328 (void)getInputColorAspectsForVideoEncoder(mInputFormat); 3329 } 3330 3331 ALOGV("set default color aspects, updated input format to %s, output format to %s", 3332 mInputFormat->debugString(4).c_str(), mOutputFormat->debugString(4).c_str()); 3333 3334 return err; 3335} 3336 3337status_t ACodec::setupVideoEncoder( 3338 const char *mime, const sp<AMessage> &msg, 3339 sp<AMessage> &outputFormat, sp<AMessage> &inputFormat) { 3340 int32_t tmp; 3341 if (!msg->findInt32("color-format", &tmp)) { 3342 return INVALID_OPERATION; 3343 } 3344 3345 OMX_COLOR_FORMATTYPE colorFormat = 3346 static_cast<OMX_COLOR_FORMATTYPE>(tmp); 3347 3348 status_t err = setVideoPortFormatType( 3349 kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat); 3350 3351 if (err != OK) { 3352 ALOGE("[%s] does not support color format %d", 3353 mComponentName.c_str(), colorFormat); 3354 3355 return err; 3356 } 3357 3358 /* Input port configuration */ 3359 3360 OMX_PARAM_PORTDEFINITIONTYPE def; 3361 InitOMXParams(&def); 3362 3363 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 3364 3365 def.nPortIndex = kPortIndexInput; 3366 3367 err = mOMX->getParameter( 3368 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 3369 3370 if (err != OK) { 3371 return err; 3372 } 3373 3374 int32_t width, height, bitrate; 3375 if (!msg->findInt32("width", &width) 3376 || !msg->findInt32("height", &height) 3377 || !msg->findInt32("bitrate", &bitrate)) { 3378 return INVALID_OPERATION; 3379 } 3380 3381 video_def->nFrameWidth = width; 3382 video_def->nFrameHeight = height; 3383 3384 int32_t stride; 3385 if (!msg->findInt32("stride", &stride)) { 3386 stride = width; 3387 } 3388 3389 video_def->nStride = stride; 3390 3391 int32_t sliceHeight; 3392 if (!msg->findInt32("slice-height", &sliceHeight)) { 3393 sliceHeight = height; 3394 } 3395 3396 video_def->nSliceHeight = sliceHeight; 3397 3398 def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2; 3399 3400 float frameRate; 3401 if (!msg->findFloat("frame-rate", &frameRate)) { 3402 int32_t tmp; 3403 if (!msg->findInt32("frame-rate", &tmp)) { 3404 return INVALID_OPERATION; 3405 } 3406 frameRate = (float)tmp; 3407 mTimePerFrameUs = (int64_t) (1000000.0f / frameRate); 3408 } 3409 3410 video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f); 3411 video_def->eCompressionFormat = OMX_VIDEO_CodingUnused; 3412 // this is redundant as it was already set up in setVideoPortFormatType 3413 // FIXME for now skip this only for flexible YUV formats 3414 if (colorFormat != OMX_COLOR_FormatYUV420Flexible) { 3415 video_def->eColorFormat = colorFormat; 3416 } 3417 3418 err = mOMX->setParameter( 3419 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 3420 3421 if (err != OK) { 3422 ALOGE("[%s] failed to set input port definition parameters.", 3423 mComponentName.c_str()); 3424 3425 return err; 3426 } 3427 3428 /* Output port configuration */ 3429 3430 OMX_VIDEO_CODINGTYPE compressionFormat; 3431 err = GetVideoCodingTypeFromMime(mime, &compressionFormat); 3432 3433 if (err != OK) { 3434 return err; 3435 } 3436 3437 err = setVideoPortFormatType( 3438 kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused); 3439 3440 if (err != OK) { 3441 ALOGE("[%s] does not support compression format %d", 3442 mComponentName.c_str(), compressionFormat); 3443 3444 return err; 3445 } 3446 3447 def.nPortIndex = kPortIndexOutput; 3448 3449 err = mOMX->getParameter( 3450 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 3451 3452 if (err != OK) { 3453 return err; 3454 } 3455 3456 video_def->nFrameWidth = width; 3457 video_def->nFrameHeight = height; 3458 video_def->xFramerate = 0; 3459 video_def->nBitrate = bitrate; 3460 video_def->eCompressionFormat = compressionFormat; 3461 video_def->eColorFormat = OMX_COLOR_FormatUnused; 3462 3463 err = mOMX->setParameter( 3464 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 3465 3466 if (err != OK) { 3467 ALOGE("[%s] failed to set output port definition parameters.", 3468 mComponentName.c_str()); 3469 3470 return err; 3471 } 3472 3473 int32_t intraRefreshPeriod = 0; 3474 if (msg->findInt32("intra-refresh-period", &intraRefreshPeriod) 3475 && intraRefreshPeriod >= 0) { 3476 err = setIntraRefreshPeriod((uint32_t)intraRefreshPeriod, true); 3477 if (err != OK) { 3478 ALOGI("[%s] failed setIntraRefreshPeriod. Failure is fine since this key is optional", 3479 mComponentName.c_str()); 3480 err = OK; 3481 } 3482 } 3483 3484 switch (compressionFormat) { 3485 case OMX_VIDEO_CodingMPEG4: 3486 err = setupMPEG4EncoderParameters(msg); 3487 break; 3488 3489 case OMX_VIDEO_CodingH263: 3490 err = setupH263EncoderParameters(msg); 3491 break; 3492 3493 case OMX_VIDEO_CodingAVC: 3494 err = setupAVCEncoderParameters(msg); 3495 break; 3496 3497 case OMX_VIDEO_CodingHEVC: 3498 err = setupHEVCEncoderParameters(msg); 3499 break; 3500 3501 case OMX_VIDEO_CodingVP8: 3502 case OMX_VIDEO_CodingVP9: 3503 err = setupVPXEncoderParameters(msg); 3504 break; 3505 3506 default: 3507 break; 3508 } 3509 3510 // Set up color aspects on input, but propagate them to the output format, as they will 3511 // not be read back from encoder. 3512 err = setColorAspectsForVideoEncoder(msg, outputFormat, inputFormat); 3513 if (err == ERROR_UNSUPPORTED) { 3514 ALOGI("[%s] cannot encode color aspects. Ignoring.", mComponentName.c_str()); 3515 err = OK; 3516 } 3517 3518 if (err == OK) { 3519 ALOGI("setupVideoEncoder succeeded"); 3520 } 3521 3522 return err; 3523} 3524 3525status_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) { 3526 OMX_VIDEO_PARAM_INTRAREFRESHTYPE params; 3527 InitOMXParams(¶ms); 3528 params.nPortIndex = kPortIndexOutput; 3529 3530 params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode); 3531 3532 if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic || 3533 params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) { 3534 int32_t mbs; 3535 if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) { 3536 return INVALID_OPERATION; 3537 } 3538 params.nCirMBs = mbs; 3539 } 3540 3541 if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive || 3542 params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) { 3543 int32_t mbs; 3544 if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) { 3545 return INVALID_OPERATION; 3546 } 3547 params.nAirMBs = mbs; 3548 3549 int32_t ref; 3550 if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) { 3551 return INVALID_OPERATION; 3552 } 3553 params.nAirRef = ref; 3554 } 3555 3556 status_t err = mOMX->setParameter( 3557 mNode, OMX_IndexParamVideoIntraRefresh, 3558 ¶ms, sizeof(params)); 3559 return err; 3560} 3561 3562static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) { 3563 if (iFramesInterval < 0) { 3564 return 0xFFFFFFFF; 3565 } else if (iFramesInterval == 0) { 3566 return 0; 3567 } 3568 OMX_U32 ret = frameRate * iFramesInterval; 3569 return ret; 3570} 3571 3572static OMX_VIDEO_CONTROLRATETYPE getBitrateMode(const sp<AMessage> &msg) { 3573 int32_t tmp; 3574 if (!msg->findInt32("bitrate-mode", &tmp)) { 3575 return OMX_Video_ControlRateVariable; 3576 } 3577 3578 return static_cast<OMX_VIDEO_CONTROLRATETYPE>(tmp); 3579} 3580 3581status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) { 3582 int32_t bitrate, iFrameInterval; 3583 if (!msg->findInt32("bitrate", &bitrate) 3584 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 3585 return INVALID_OPERATION; 3586 } 3587 3588 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 3589 3590 float frameRate; 3591 if (!msg->findFloat("frame-rate", &frameRate)) { 3592 int32_t tmp; 3593 if (!msg->findInt32("frame-rate", &tmp)) { 3594 return INVALID_OPERATION; 3595 } 3596 frameRate = (float)tmp; 3597 } 3598 3599 OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type; 3600 InitOMXParams(&mpeg4type); 3601 mpeg4type.nPortIndex = kPortIndexOutput; 3602 3603 status_t err = mOMX->getParameter( 3604 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); 3605 3606 if (err != OK) { 3607 return err; 3608 } 3609 3610 mpeg4type.nSliceHeaderSpacing = 0; 3611 mpeg4type.bSVH = OMX_FALSE; 3612 mpeg4type.bGov = OMX_FALSE; 3613 3614 mpeg4type.nAllowedPictureTypes = 3615 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 3616 3617 mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 3618 if (mpeg4type.nPFrames == 0) { 3619 mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 3620 } 3621 mpeg4type.nBFrames = 0; 3622 mpeg4type.nIDCVLCThreshold = 0; 3623 mpeg4type.bACPred = OMX_TRUE; 3624 mpeg4type.nMaxPacketSize = 256; 3625 mpeg4type.nTimeIncRes = 1000; 3626 mpeg4type.nHeaderExtension = 0; 3627 mpeg4type.bReversibleVLC = OMX_FALSE; 3628 3629 int32_t profile; 3630 if (msg->findInt32("profile", &profile)) { 3631 int32_t level; 3632 if (!msg->findInt32("level", &level)) { 3633 return INVALID_OPERATION; 3634 } 3635 3636 err = verifySupportForProfileAndLevel(profile, level); 3637 3638 if (err != OK) { 3639 return err; 3640 } 3641 3642 mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile); 3643 mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level); 3644 } 3645 3646 err = mOMX->setParameter( 3647 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); 3648 3649 if (err != OK) { 3650 return err; 3651 } 3652 3653 err = configureBitrate(bitrate, bitrateMode); 3654 3655 if (err != OK) { 3656 return err; 3657 } 3658 3659 return setupErrorCorrectionParameters(); 3660} 3661 3662status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) { 3663 int32_t bitrate, iFrameInterval; 3664 if (!msg->findInt32("bitrate", &bitrate) 3665 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 3666 return INVALID_OPERATION; 3667 } 3668 3669 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 3670 3671 float frameRate; 3672 if (!msg->findFloat("frame-rate", &frameRate)) { 3673 int32_t tmp; 3674 if (!msg->findInt32("frame-rate", &tmp)) { 3675 return INVALID_OPERATION; 3676 } 3677 frameRate = (float)tmp; 3678 } 3679 3680 OMX_VIDEO_PARAM_H263TYPE h263type; 3681 InitOMXParams(&h263type); 3682 h263type.nPortIndex = kPortIndexOutput; 3683 3684 status_t err = mOMX->getParameter( 3685 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); 3686 3687 if (err != OK) { 3688 return err; 3689 } 3690 3691 h263type.nAllowedPictureTypes = 3692 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 3693 3694 h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 3695 if (h263type.nPFrames == 0) { 3696 h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 3697 } 3698 h263type.nBFrames = 0; 3699 3700 int32_t profile; 3701 if (msg->findInt32("profile", &profile)) { 3702 int32_t level; 3703 if (!msg->findInt32("level", &level)) { 3704 return INVALID_OPERATION; 3705 } 3706 3707 err = verifySupportForProfileAndLevel(profile, level); 3708 3709 if (err != OK) { 3710 return err; 3711 } 3712 3713 h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile); 3714 h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level); 3715 } 3716 3717 h263type.bPLUSPTYPEAllowed = OMX_FALSE; 3718 h263type.bForceRoundingTypeToZero = OMX_FALSE; 3719 h263type.nPictureHeaderRepetition = 0; 3720 h263type.nGOBHeaderInterval = 0; 3721 3722 err = mOMX->setParameter( 3723 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); 3724 3725 if (err != OK) { 3726 return err; 3727 } 3728 3729 err = configureBitrate(bitrate, bitrateMode); 3730 3731 if (err != OK) { 3732 return err; 3733 } 3734 3735 return setupErrorCorrectionParameters(); 3736} 3737 3738// static 3739int /* OMX_VIDEO_AVCLEVELTYPE */ ACodec::getAVCLevelFor( 3740 int width, int height, int rate, int bitrate, 3741 OMX_VIDEO_AVCPROFILETYPE profile) { 3742 // convert bitrate to main/baseline profile kbps equivalent 3743 switch (profile) { 3744 case OMX_VIDEO_AVCProfileHigh10: 3745 bitrate = divUp(bitrate, 3000); break; 3746 case OMX_VIDEO_AVCProfileHigh: 3747 bitrate = divUp(bitrate, 1250); break; 3748 default: 3749 bitrate = divUp(bitrate, 1000); break; 3750 } 3751 3752 // convert size and rate to MBs 3753 width = divUp(width, 16); 3754 height = divUp(height, 16); 3755 int mbs = width * height; 3756 rate *= mbs; 3757 int maxDimension = max(width, height); 3758 3759 static const int limits[][5] = { 3760 /* MBps MB dim bitrate level */ 3761 { 1485, 99, 28, 64, OMX_VIDEO_AVCLevel1 }, 3762 { 1485, 99, 28, 128, OMX_VIDEO_AVCLevel1b }, 3763 { 3000, 396, 56, 192, OMX_VIDEO_AVCLevel11 }, 3764 { 6000, 396, 56, 384, OMX_VIDEO_AVCLevel12 }, 3765 { 11880, 396, 56, 768, OMX_VIDEO_AVCLevel13 }, 3766 { 11880, 396, 56, 2000, OMX_VIDEO_AVCLevel2 }, 3767 { 19800, 792, 79, 4000, OMX_VIDEO_AVCLevel21 }, 3768 { 20250, 1620, 113, 4000, OMX_VIDEO_AVCLevel22 }, 3769 { 40500, 1620, 113, 10000, OMX_VIDEO_AVCLevel3 }, 3770 { 108000, 3600, 169, 14000, OMX_VIDEO_AVCLevel31 }, 3771 { 216000, 5120, 202, 20000, OMX_VIDEO_AVCLevel32 }, 3772 { 245760, 8192, 256, 20000, OMX_VIDEO_AVCLevel4 }, 3773 { 245760, 8192, 256, 50000, OMX_VIDEO_AVCLevel41 }, 3774 { 522240, 8704, 263, 50000, OMX_VIDEO_AVCLevel42 }, 3775 { 589824, 22080, 420, 135000, OMX_VIDEO_AVCLevel5 }, 3776 { 983040, 36864, 543, 240000, OMX_VIDEO_AVCLevel51 }, 3777 { 2073600, 36864, 543, 240000, OMX_VIDEO_AVCLevel52 }, 3778 }; 3779 3780 for (size_t i = 0; i < ARRAY_SIZE(limits); i++) { 3781 const int (&limit)[5] = limits[i]; 3782 if (rate <= limit[0] && mbs <= limit[1] && maxDimension <= limit[2] 3783 && bitrate <= limit[3]) { 3784 return limit[4]; 3785 } 3786 } 3787 return 0; 3788} 3789 3790status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) { 3791 int32_t bitrate, iFrameInterval; 3792 if (!msg->findInt32("bitrate", &bitrate) 3793 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 3794 return INVALID_OPERATION; 3795 } 3796 3797 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 3798 3799 float frameRate; 3800 if (!msg->findFloat("frame-rate", &frameRate)) { 3801 int32_t tmp; 3802 if (!msg->findInt32("frame-rate", &tmp)) { 3803 return INVALID_OPERATION; 3804 } 3805 frameRate = (float)tmp; 3806 } 3807 3808 status_t err = OK; 3809 int32_t intraRefreshMode = 0; 3810 if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) { 3811 err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode); 3812 if (err != OK) { 3813 ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x", 3814 err, intraRefreshMode); 3815 return err; 3816 } 3817 } 3818 3819 OMX_VIDEO_PARAM_AVCTYPE h264type; 3820 InitOMXParams(&h264type); 3821 h264type.nPortIndex = kPortIndexOutput; 3822 3823 err = mOMX->getParameter( 3824 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 3825 3826 if (err != OK) { 3827 return err; 3828 } 3829 3830 h264type.nAllowedPictureTypes = 3831 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 3832 3833 int32_t profile; 3834 if (msg->findInt32("profile", &profile)) { 3835 int32_t level; 3836 if (!msg->findInt32("level", &level)) { 3837 return INVALID_OPERATION; 3838 } 3839 3840 err = verifySupportForProfileAndLevel(profile, level); 3841 3842 if (err != OK) { 3843 return err; 3844 } 3845 3846 h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile); 3847 h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level); 3848 } 3849 3850 if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) { 3851 h264type.nSliceHeaderSpacing = 0; 3852 h264type.bUseHadamard = OMX_TRUE; 3853 h264type.nRefFrames = 1; 3854 h264type.nBFrames = 0; 3855 h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 3856 if (h264type.nPFrames == 0) { 3857 h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 3858 } 3859 h264type.nRefIdx10ActiveMinus1 = 0; 3860 h264type.nRefIdx11ActiveMinus1 = 0; 3861 h264type.bEntropyCodingCABAC = OMX_FALSE; 3862 h264type.bWeightedPPrediction = OMX_FALSE; 3863 h264type.bconstIpred = OMX_FALSE; 3864 h264type.bDirect8x8Inference = OMX_FALSE; 3865 h264type.bDirectSpatialTemporal = OMX_FALSE; 3866 h264type.nCabacInitIdc = 0; 3867 } else if (h264type.eProfile == OMX_VIDEO_AVCProfileMain || 3868 h264type.eProfile == OMX_VIDEO_AVCProfileHigh) { 3869 h264type.nSliceHeaderSpacing = 0; 3870 h264type.bUseHadamard = OMX_TRUE; 3871 h264type.nRefFrames = 2; 3872 h264type.nBFrames = 1; 3873 h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 3874 h264type.nAllowedPictureTypes = 3875 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP | OMX_VIDEO_PictureTypeB; 3876 h264type.nRefIdx10ActiveMinus1 = 0; 3877 h264type.nRefIdx11ActiveMinus1 = 0; 3878 h264type.bEntropyCodingCABAC = OMX_TRUE; 3879 h264type.bWeightedPPrediction = OMX_TRUE; 3880 h264type.bconstIpred = OMX_TRUE; 3881 h264type.bDirect8x8Inference = OMX_TRUE; 3882 h264type.bDirectSpatialTemporal = OMX_TRUE; 3883 h264type.nCabacInitIdc = 1; 3884 } 3885 3886 if (h264type.nBFrames != 0) { 3887 h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB; 3888 } 3889 3890 h264type.bEnableUEP = OMX_FALSE; 3891 h264type.bEnableFMO = OMX_FALSE; 3892 h264type.bEnableASO = OMX_FALSE; 3893 h264type.bEnableRS = OMX_FALSE; 3894 h264type.bFrameMBsOnly = OMX_TRUE; 3895 h264type.bMBAFF = OMX_FALSE; 3896 h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; 3897 3898 err = mOMX->setParameter( 3899 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 3900 3901 if (err != OK) { 3902 return err; 3903 } 3904 3905 return configureBitrate(bitrate, bitrateMode); 3906} 3907 3908status_t ACodec::setupHEVCEncoderParameters(const sp<AMessage> &msg) { 3909 int32_t bitrate, iFrameInterval; 3910 if (!msg->findInt32("bitrate", &bitrate) 3911 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 3912 return INVALID_OPERATION; 3913 } 3914 3915 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 3916 3917 float frameRate; 3918 if (!msg->findFloat("frame-rate", &frameRate)) { 3919 int32_t tmp; 3920 if (!msg->findInt32("frame-rate", &tmp)) { 3921 return INVALID_OPERATION; 3922 } 3923 frameRate = (float)tmp; 3924 } 3925 3926 OMX_VIDEO_PARAM_HEVCTYPE hevcType; 3927 InitOMXParams(&hevcType); 3928 hevcType.nPortIndex = kPortIndexOutput; 3929 3930 status_t err = OK; 3931 err = mOMX->getParameter( 3932 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType)); 3933 if (err != OK) { 3934 return err; 3935 } 3936 3937 int32_t profile; 3938 if (msg->findInt32("profile", &profile)) { 3939 int32_t level; 3940 if (!msg->findInt32("level", &level)) { 3941 return INVALID_OPERATION; 3942 } 3943 3944 err = verifySupportForProfileAndLevel(profile, level); 3945 if (err != OK) { 3946 return err; 3947 } 3948 3949 hevcType.eProfile = static_cast<OMX_VIDEO_HEVCPROFILETYPE>(profile); 3950 hevcType.eLevel = static_cast<OMX_VIDEO_HEVCLEVELTYPE>(level); 3951 } 3952 // TODO: finer control? 3953 hevcType.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate); 3954 3955 err = mOMX->setParameter( 3956 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType)); 3957 if (err != OK) { 3958 return err; 3959 } 3960 3961 return configureBitrate(bitrate, bitrateMode); 3962} 3963 3964status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg) { 3965 int32_t bitrate; 3966 int32_t iFrameInterval = 0; 3967 size_t tsLayers = 0; 3968 OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE pattern = 3969 OMX_VIDEO_VPXTemporalLayerPatternNone; 3970 static const uint32_t kVp8LayerRateAlloction 3971 [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] 3972 [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] = { 3973 {100, 100, 100}, // 1 layer 3974 { 60, 100, 100}, // 2 layers {60%, 40%} 3975 { 40, 60, 100}, // 3 layers {40%, 20%, 40%} 3976 }; 3977 if (!msg->findInt32("bitrate", &bitrate)) { 3978 return INVALID_OPERATION; 3979 } 3980 msg->findInt32("i-frame-interval", &iFrameInterval); 3981 3982 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 3983 3984 float frameRate; 3985 if (!msg->findFloat("frame-rate", &frameRate)) { 3986 int32_t tmp; 3987 if (!msg->findInt32("frame-rate", &tmp)) { 3988 return INVALID_OPERATION; 3989 } 3990 frameRate = (float)tmp; 3991 } 3992 3993 AString tsSchema; 3994 if (msg->findString("ts-schema", &tsSchema)) { 3995 if (tsSchema == "webrtc.vp8.1-layer") { 3996 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC; 3997 tsLayers = 1; 3998 } else if (tsSchema == "webrtc.vp8.2-layer") { 3999 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC; 4000 tsLayers = 2; 4001 } else if (tsSchema == "webrtc.vp8.3-layer") { 4002 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC; 4003 tsLayers = 3; 4004 } else { 4005 ALOGW("Unsupported ts-schema [%s]", tsSchema.c_str()); 4006 } 4007 } 4008 4009 OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type; 4010 InitOMXParams(&vp8type); 4011 vp8type.nPortIndex = kPortIndexOutput; 4012 status_t err = mOMX->getParameter( 4013 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder, 4014 &vp8type, sizeof(vp8type)); 4015 4016 if (err == OK) { 4017 if (iFrameInterval > 0) { 4018 vp8type.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate); 4019 } 4020 vp8type.eTemporalPattern = pattern; 4021 vp8type.nTemporalLayerCount = tsLayers; 4022 if (tsLayers > 0) { 4023 for (size_t i = 0; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) { 4024 vp8type.nTemporalLayerBitrateRatio[i] = 4025 kVp8LayerRateAlloction[tsLayers - 1][i]; 4026 } 4027 } 4028 if (bitrateMode == OMX_Video_ControlRateConstant) { 4029 vp8type.nMinQuantizer = 2; 4030 vp8type.nMaxQuantizer = 63; 4031 } 4032 4033 err = mOMX->setParameter( 4034 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder, 4035 &vp8type, sizeof(vp8type)); 4036 if (err != OK) { 4037 ALOGW("Extended VP8 parameters set failed: %d", err); 4038 } 4039 } 4040 4041 return configureBitrate(bitrate, bitrateMode); 4042} 4043 4044status_t ACodec::verifySupportForProfileAndLevel( 4045 int32_t profile, int32_t level) { 4046 OMX_VIDEO_PARAM_PROFILELEVELTYPE params; 4047 InitOMXParams(¶ms); 4048 params.nPortIndex = kPortIndexOutput; 4049 4050 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { 4051 params.nProfileIndex = index; 4052 status_t err = mOMX->getParameter( 4053 mNode, 4054 OMX_IndexParamVideoProfileLevelQuerySupported, 4055 ¶ms, 4056 sizeof(params)); 4057 4058 if (err != OK) { 4059 return err; 4060 } 4061 4062 int32_t supportedProfile = static_cast<int32_t>(params.eProfile); 4063 int32_t supportedLevel = static_cast<int32_t>(params.eLevel); 4064 4065 if (profile == supportedProfile && level <= supportedLevel) { 4066 return OK; 4067 } 4068 4069 if (index == kMaxIndicesToCheck) { 4070 ALOGW("[%s] stopping checking profiles after %u: %x/%x", 4071 mComponentName.c_str(), index, 4072 params.eProfile, params.eLevel); 4073 } 4074 } 4075 return ERROR_UNSUPPORTED; 4076} 4077 4078status_t ACodec::configureBitrate( 4079 int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode) { 4080 OMX_VIDEO_PARAM_BITRATETYPE bitrateType; 4081 InitOMXParams(&bitrateType); 4082 bitrateType.nPortIndex = kPortIndexOutput; 4083 4084 status_t err = mOMX->getParameter( 4085 mNode, OMX_IndexParamVideoBitrate, 4086 &bitrateType, sizeof(bitrateType)); 4087 4088 if (err != OK) { 4089 return err; 4090 } 4091 4092 bitrateType.eControlRate = bitrateMode; 4093 bitrateType.nTargetBitrate = bitrate; 4094 4095 return mOMX->setParameter( 4096 mNode, OMX_IndexParamVideoBitrate, 4097 &bitrateType, sizeof(bitrateType)); 4098} 4099 4100status_t ACodec::setupErrorCorrectionParameters() { 4101 OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType; 4102 InitOMXParams(&errorCorrectionType); 4103 errorCorrectionType.nPortIndex = kPortIndexOutput; 4104 4105 status_t err = mOMX->getParameter( 4106 mNode, OMX_IndexParamVideoErrorCorrection, 4107 &errorCorrectionType, sizeof(errorCorrectionType)); 4108 4109 if (err != OK) { 4110 return OK; // Optional feature. Ignore this failure 4111 } 4112 4113 errorCorrectionType.bEnableHEC = OMX_FALSE; 4114 errorCorrectionType.bEnableResync = OMX_TRUE; 4115 errorCorrectionType.nResynchMarkerSpacing = 256; 4116 errorCorrectionType.bEnableDataPartitioning = OMX_FALSE; 4117 errorCorrectionType.bEnableRVLC = OMX_FALSE; 4118 4119 return mOMX->setParameter( 4120 mNode, OMX_IndexParamVideoErrorCorrection, 4121 &errorCorrectionType, sizeof(errorCorrectionType)); 4122} 4123 4124status_t ACodec::setVideoFormatOnPort( 4125 OMX_U32 portIndex, 4126 int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat, 4127 float frameRate) { 4128 OMX_PARAM_PORTDEFINITIONTYPE def; 4129 InitOMXParams(&def); 4130 def.nPortIndex = portIndex; 4131 4132 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 4133 4134 status_t err = mOMX->getParameter( 4135 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 4136 if (err != OK) { 4137 return err; 4138 } 4139 4140 if (portIndex == kPortIndexInput) { 4141 // XXX Need a (much) better heuristic to compute input buffer sizes. 4142 const size_t X = 64 * 1024; 4143 if (def.nBufferSize < X) { 4144 def.nBufferSize = X; 4145 } 4146 } 4147 4148 if (def.eDomain != OMX_PortDomainVideo) { 4149 ALOGE("expected video port, got %s(%d)", asString(def.eDomain), def.eDomain); 4150 return FAILED_TRANSACTION; 4151 } 4152 4153 video_def->nFrameWidth = width; 4154 video_def->nFrameHeight = height; 4155 4156 if (portIndex == kPortIndexInput) { 4157 video_def->eCompressionFormat = compressionFormat; 4158 video_def->eColorFormat = OMX_COLOR_FormatUnused; 4159 if (frameRate >= 0) { 4160 video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f); 4161 } 4162 } 4163 4164 err = mOMX->setParameter( 4165 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 4166 4167 return err; 4168} 4169 4170status_t ACodec::initNativeWindow() { 4171 if (mNativeWindow != NULL) { 4172 return mOMX->enableNativeBuffers(mNode, kPortIndexOutput, OMX_TRUE /* graphic */, OMX_TRUE); 4173 } 4174 4175 mOMX->enableNativeBuffers(mNode, kPortIndexOutput, OMX_TRUE /* graphic */, OMX_FALSE); 4176 return OK; 4177} 4178 4179size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const { 4180 size_t n = 0; 4181 4182 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 4183 const BufferInfo &info = mBuffers[portIndex].itemAt(i); 4184 4185 if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) { 4186 ++n; 4187 } 4188 } 4189 4190 return n; 4191} 4192 4193size_t ACodec::countBuffersOwnedByNativeWindow() const { 4194 size_t n = 0; 4195 4196 for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) { 4197 const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i); 4198 4199 if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 4200 ++n; 4201 } 4202 } 4203 4204 return n; 4205} 4206 4207void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() { 4208 if (mNativeWindow == NULL) { 4209 return; 4210 } 4211 4212 while (countBuffersOwnedByNativeWindow() > mNumUndequeuedBuffers 4213 && dequeueBufferFromNativeWindow() != NULL) { 4214 // these buffers will be submitted as regular buffers; account for this 4215 if (storingMetadataInDecodedBuffers() && mMetadataBuffersToSubmit > 0) { 4216 --mMetadataBuffersToSubmit; 4217 } 4218 } 4219} 4220 4221bool ACodec::allYourBuffersAreBelongToUs( 4222 OMX_U32 portIndex) { 4223 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 4224 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 4225 4226 if (info->mStatus != BufferInfo::OWNED_BY_US 4227 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) { 4228 ALOGV("[%s] Buffer %u on port %u still has status %d", 4229 mComponentName.c_str(), 4230 info->mBufferID, portIndex, info->mStatus); 4231 return false; 4232 } 4233 } 4234 4235 return true; 4236} 4237 4238bool ACodec::allYourBuffersAreBelongToUs() { 4239 return allYourBuffersAreBelongToUs(kPortIndexInput) 4240 && allYourBuffersAreBelongToUs(kPortIndexOutput); 4241} 4242 4243void ACodec::deferMessage(const sp<AMessage> &msg) { 4244 mDeferredQueue.push_back(msg); 4245} 4246 4247void ACodec::processDeferredMessages() { 4248 List<sp<AMessage> > queue = mDeferredQueue; 4249 mDeferredQueue.clear(); 4250 4251 List<sp<AMessage> >::iterator it = queue.begin(); 4252 while (it != queue.end()) { 4253 onMessageReceived(*it++); 4254 } 4255} 4256 4257// static 4258bool ACodec::describeDefaultColorFormat(DescribeColorFormat2Params ¶ms) { 4259 MediaImage2 &image = params.sMediaImage; 4260 memset(&image, 0, sizeof(image)); 4261 4262 image.mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN; 4263 image.mNumPlanes = 0; 4264 4265 const OMX_COLOR_FORMATTYPE fmt = params.eColorFormat; 4266 image.mWidth = params.nFrameWidth; 4267 image.mHeight = params.nFrameHeight; 4268 4269 // only supporting YUV420 4270 if (fmt != OMX_COLOR_FormatYUV420Planar && 4271 fmt != OMX_COLOR_FormatYUV420PackedPlanar && 4272 fmt != OMX_COLOR_FormatYUV420SemiPlanar && 4273 fmt != OMX_COLOR_FormatYUV420PackedSemiPlanar && 4274 fmt != (OMX_COLOR_FORMATTYPE)HAL_PIXEL_FORMAT_YV12) { 4275 ALOGW("do not know color format 0x%x = %d", fmt, fmt); 4276 return false; 4277 } 4278 4279 // TEMPORARY FIX for some vendors that advertise sliceHeight as 0 4280 if (params.nStride != 0 && params.nSliceHeight == 0) { 4281 ALOGW("using sliceHeight=%u instead of what codec advertised (=0)", 4282 params.nFrameHeight); 4283 params.nSliceHeight = params.nFrameHeight; 4284 } 4285 4286 // we need stride and slice-height to be non-zero and sensible. These values were chosen to 4287 // prevent integer overflows further down the line, and do not indicate support for 4288 // 32kx32k video. 4289 if (params.nStride == 0 || params.nSliceHeight == 0 4290 || params.nStride > 32768 || params.nSliceHeight > 32768) { 4291 ALOGW("cannot describe color format 0x%x = %d with stride=%u and sliceHeight=%u", 4292 fmt, fmt, params.nStride, params.nSliceHeight); 4293 return false; 4294 } 4295 4296 // set-up YUV format 4297 image.mType = MediaImage2::MEDIA_IMAGE_TYPE_YUV; 4298 image.mNumPlanes = 3; 4299 image.mBitDepth = 8; 4300 image.mBitDepthAllocated = 8; 4301 image.mPlane[image.Y].mOffset = 0; 4302 image.mPlane[image.Y].mColInc = 1; 4303 image.mPlane[image.Y].mRowInc = params.nStride; 4304 image.mPlane[image.Y].mHorizSubsampling = 1; 4305 image.mPlane[image.Y].mVertSubsampling = 1; 4306 4307 switch ((int)fmt) { 4308 case HAL_PIXEL_FORMAT_YV12: 4309 if (params.bUsingNativeBuffers) { 4310 size_t ystride = align(params.nStride, 16); 4311 size_t cstride = align(params.nStride / 2, 16); 4312 image.mPlane[image.Y].mRowInc = ystride; 4313 4314 image.mPlane[image.V].mOffset = ystride * params.nSliceHeight; 4315 image.mPlane[image.V].mColInc = 1; 4316 image.mPlane[image.V].mRowInc = cstride; 4317 image.mPlane[image.V].mHorizSubsampling = 2; 4318 image.mPlane[image.V].mVertSubsampling = 2; 4319 4320 image.mPlane[image.U].mOffset = image.mPlane[image.V].mOffset 4321 + (cstride * params.nSliceHeight / 2); 4322 image.mPlane[image.U].mColInc = 1; 4323 image.mPlane[image.U].mRowInc = cstride; 4324 image.mPlane[image.U].mHorizSubsampling = 2; 4325 image.mPlane[image.U].mVertSubsampling = 2; 4326 break; 4327 } else { 4328 // fall through as YV12 is used for YUV420Planar by some codecs 4329 } 4330 4331 case OMX_COLOR_FormatYUV420Planar: 4332 case OMX_COLOR_FormatYUV420PackedPlanar: 4333 image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight; 4334 image.mPlane[image.U].mColInc = 1; 4335 image.mPlane[image.U].mRowInc = params.nStride / 2; 4336 image.mPlane[image.U].mHorizSubsampling = 2; 4337 image.mPlane[image.U].mVertSubsampling = 2; 4338 4339 image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset 4340 + (params.nStride * params.nSliceHeight / 4); 4341 image.mPlane[image.V].mColInc = 1; 4342 image.mPlane[image.V].mRowInc = params.nStride / 2; 4343 image.mPlane[image.V].mHorizSubsampling = 2; 4344 image.mPlane[image.V].mVertSubsampling = 2; 4345 break; 4346 4347 case OMX_COLOR_FormatYUV420SemiPlanar: 4348 // FIXME: NV21 for sw-encoder, NV12 for decoder and hw-encoder 4349 case OMX_COLOR_FormatYUV420PackedSemiPlanar: 4350 // NV12 4351 image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight; 4352 image.mPlane[image.U].mColInc = 2; 4353 image.mPlane[image.U].mRowInc = params.nStride; 4354 image.mPlane[image.U].mHorizSubsampling = 2; 4355 image.mPlane[image.U].mVertSubsampling = 2; 4356 4357 image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset + 1; 4358 image.mPlane[image.V].mColInc = 2; 4359 image.mPlane[image.V].mRowInc = params.nStride; 4360 image.mPlane[image.V].mHorizSubsampling = 2; 4361 image.mPlane[image.V].mVertSubsampling = 2; 4362 break; 4363 4364 default: 4365 TRESPASS(); 4366 } 4367 return true; 4368} 4369 4370// static 4371bool ACodec::describeColorFormat( 4372 const sp<IOMX> &omx, IOMX::node_id node, 4373 DescribeColorFormat2Params &describeParams) 4374{ 4375 OMX_INDEXTYPE describeColorFormatIndex; 4376 if (omx->getExtensionIndex( 4377 node, "OMX.google.android.index.describeColorFormat", 4378 &describeColorFormatIndex) == OK) { 4379 DescribeColorFormatParams describeParamsV1(describeParams); 4380 if (omx->getParameter( 4381 node, describeColorFormatIndex, 4382 &describeParamsV1, sizeof(describeParamsV1)) == OK) { 4383 describeParams.initFromV1(describeParamsV1); 4384 return describeParams.sMediaImage.mType != MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN; 4385 } 4386 } else if (omx->getExtensionIndex( 4387 node, "OMX.google.android.index.describeColorFormat2", &describeColorFormatIndex) == OK 4388 && omx->getParameter( 4389 node, describeColorFormatIndex, &describeParams, sizeof(describeParams)) == OK) { 4390 return describeParams.sMediaImage.mType != MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN; 4391 } 4392 4393 return describeDefaultColorFormat(describeParams); 4394} 4395 4396// static 4397bool ACodec::isFlexibleColorFormat( 4398 const sp<IOMX> &omx, IOMX::node_id node, 4399 uint32_t colorFormat, bool usingNativeBuffers, OMX_U32 *flexibleEquivalent) { 4400 DescribeColorFormat2Params describeParams; 4401 InitOMXParams(&describeParams); 4402 describeParams.eColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat; 4403 // reasonable dummy values 4404 describeParams.nFrameWidth = 128; 4405 describeParams.nFrameHeight = 128; 4406 describeParams.nStride = 128; 4407 describeParams.nSliceHeight = 128; 4408 describeParams.bUsingNativeBuffers = (OMX_BOOL)usingNativeBuffers; 4409 4410 CHECK(flexibleEquivalent != NULL); 4411 4412 if (!describeColorFormat(omx, node, describeParams)) { 4413 return false; 4414 } 4415 4416 const MediaImage2 &img = describeParams.sMediaImage; 4417 if (img.mType == MediaImage2::MEDIA_IMAGE_TYPE_YUV) { 4418 if (img.mNumPlanes != 3 4419 || img.mPlane[img.Y].mHorizSubsampling != 1 4420 || img.mPlane[img.Y].mVertSubsampling != 1) { 4421 return false; 4422 } 4423 4424 // YUV 420 4425 if (img.mPlane[img.U].mHorizSubsampling == 2 4426 && img.mPlane[img.U].mVertSubsampling == 2 4427 && img.mPlane[img.V].mHorizSubsampling == 2 4428 && img.mPlane[img.V].mVertSubsampling == 2) { 4429 // possible flexible YUV420 format 4430 if (img.mBitDepth <= 8) { 4431 *flexibleEquivalent = OMX_COLOR_FormatYUV420Flexible; 4432 return true; 4433 } 4434 } 4435 } 4436 return false; 4437} 4438 4439status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> ¬ify) { 4440 const char *niceIndex = portIndex == kPortIndexInput ? "input" : "output"; 4441 OMX_PARAM_PORTDEFINITIONTYPE def; 4442 InitOMXParams(&def); 4443 def.nPortIndex = portIndex; 4444 4445 status_t err = mOMX->getParameter(mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 4446 if (err != OK) { 4447 return err; 4448 } 4449 4450 if (def.eDir != (portIndex == kPortIndexOutput ? OMX_DirOutput : OMX_DirInput)) { 4451 ALOGE("unexpected dir: %s(%d) on %s port", asString(def.eDir), def.eDir, niceIndex); 4452 return BAD_VALUE; 4453 } 4454 4455 switch (def.eDomain) { 4456 case OMX_PortDomainVideo: 4457 { 4458 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video; 4459 switch ((int)videoDef->eCompressionFormat) { 4460 case OMX_VIDEO_CodingUnused: 4461 { 4462 CHECK(mIsEncoder ^ (portIndex == kPortIndexOutput)); 4463 notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW); 4464 4465 notify->setInt32("stride", videoDef->nStride); 4466 notify->setInt32("slice-height", videoDef->nSliceHeight); 4467 notify->setInt32("color-format", videoDef->eColorFormat); 4468 4469 if (mNativeWindow == NULL) { 4470 DescribeColorFormat2Params describeParams; 4471 InitOMXParams(&describeParams); 4472 describeParams.eColorFormat = videoDef->eColorFormat; 4473 describeParams.nFrameWidth = videoDef->nFrameWidth; 4474 describeParams.nFrameHeight = videoDef->nFrameHeight; 4475 describeParams.nStride = videoDef->nStride; 4476 describeParams.nSliceHeight = videoDef->nSliceHeight; 4477 describeParams.bUsingNativeBuffers = OMX_FALSE; 4478 4479 if (describeColorFormat(mOMX, mNode, describeParams)) { 4480 notify->setBuffer( 4481 "image-data", 4482 ABuffer::CreateAsCopy( 4483 &describeParams.sMediaImage, 4484 sizeof(describeParams.sMediaImage))); 4485 4486 MediaImage2 &img = describeParams.sMediaImage; 4487 MediaImage2::PlaneInfo *plane = img.mPlane; 4488 ALOGV("[%s] MediaImage { F(%ux%u) @%u+%d+%d @%u+%d+%d @%u+%d+%d }", 4489 mComponentName.c_str(), img.mWidth, img.mHeight, 4490 plane[0].mOffset, plane[0].mColInc, plane[0].mRowInc, 4491 plane[1].mOffset, plane[1].mColInc, plane[1].mRowInc, 4492 plane[2].mOffset, plane[2].mColInc, plane[2].mRowInc); 4493 } 4494 } 4495 4496 int32_t width = (int32_t)videoDef->nFrameWidth; 4497 int32_t height = (int32_t)videoDef->nFrameHeight; 4498 4499 if (portIndex == kPortIndexOutput) { 4500 OMX_CONFIG_RECTTYPE rect; 4501 InitOMXParams(&rect); 4502 rect.nPortIndex = portIndex; 4503 4504 if (mOMX->getConfig( 4505 mNode, 4506 (portIndex == kPortIndexOutput ? 4507 OMX_IndexConfigCommonOutputCrop : 4508 OMX_IndexConfigCommonInputCrop), 4509 &rect, sizeof(rect)) != OK) { 4510 rect.nLeft = 0; 4511 rect.nTop = 0; 4512 rect.nWidth = videoDef->nFrameWidth; 4513 rect.nHeight = videoDef->nFrameHeight; 4514 } 4515 4516 if (rect.nLeft < 0 || 4517 rect.nTop < 0 || 4518 rect.nLeft + rect.nWidth > videoDef->nFrameWidth || 4519 rect.nTop + rect.nHeight > videoDef->nFrameHeight) { 4520 ALOGE("Wrong cropped rect (%d, %d) - (%u, %u) vs. frame (%u, %u)", 4521 rect.nLeft, rect.nTop, 4522 rect.nLeft + rect.nWidth, rect.nTop + rect.nHeight, 4523 videoDef->nFrameWidth, videoDef->nFrameHeight); 4524 return BAD_VALUE; 4525 } 4526 4527 notify->setRect( 4528 "crop", 4529 rect.nLeft, 4530 rect.nTop, 4531 rect.nLeft + rect.nWidth - 1, 4532 rect.nTop + rect.nHeight - 1); 4533 4534 width = rect.nWidth; 4535 height = rect.nHeight; 4536 4537 android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN; 4538 (void)getColorAspectsAndDataSpaceForVideoDecoder( 4539 width, height, mConfigFormat, notify, 4540 mUsingNativeWindow ? &dataSpace : NULL); 4541 if (mUsingNativeWindow) { 4542 notify->setInt32("android._dataspace", dataSpace); 4543 } 4544 } else { 4545 (void)getInputColorAspectsForVideoEncoder(notify); 4546 } 4547 4548 break; 4549 } 4550 4551 case OMX_VIDEO_CodingVP8: 4552 case OMX_VIDEO_CodingVP9: 4553 { 4554 OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type; 4555 InitOMXParams(&vp8type); 4556 vp8type.nPortIndex = kPortIndexOutput; 4557 status_t err = mOMX->getParameter( 4558 mNode, 4559 (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder, 4560 &vp8type, 4561 sizeof(vp8type)); 4562 4563 if (err == OK) { 4564 AString tsSchema = "none"; 4565 if (vp8type.eTemporalPattern 4566 == OMX_VIDEO_VPXTemporalLayerPatternWebRTC) { 4567 switch (vp8type.nTemporalLayerCount) { 4568 case 1: 4569 { 4570 tsSchema = "webrtc.vp8.1-layer"; 4571 break; 4572 } 4573 case 2: 4574 { 4575 tsSchema = "webrtc.vp8.2-layer"; 4576 break; 4577 } 4578 case 3: 4579 { 4580 tsSchema = "webrtc.vp8.3-layer"; 4581 break; 4582 } 4583 default: 4584 { 4585 break; 4586 } 4587 } 4588 } 4589 notify->setString("ts-schema", tsSchema); 4590 } 4591 // Fall through to set up mime. 4592 } 4593 4594 default: 4595 { 4596 if (mIsEncoder ^ (portIndex == kPortIndexOutput)) { 4597 // should be CodingUnused 4598 ALOGE("Raw port video compression format is %s(%d)", 4599 asString(videoDef->eCompressionFormat), 4600 videoDef->eCompressionFormat); 4601 return BAD_VALUE; 4602 } 4603 AString mime; 4604 if (GetMimeTypeForVideoCoding( 4605 videoDef->eCompressionFormat, &mime) != OK) { 4606 notify->setString("mime", "application/octet-stream"); 4607 } else { 4608 notify->setString("mime", mime.c_str()); 4609 } 4610 uint32_t intraRefreshPeriod = 0; 4611 if (mIsEncoder && getIntraRefreshPeriod(&intraRefreshPeriod) == OK 4612 && intraRefreshPeriod > 0) { 4613 notify->setInt32("intra-refresh-period", intraRefreshPeriod); 4614 } 4615 break; 4616 } 4617 } 4618 notify->setInt32("width", videoDef->nFrameWidth); 4619 notify->setInt32("height", videoDef->nFrameHeight); 4620 ALOGV("[%s] %s format is %s", mComponentName.c_str(), 4621 portIndex == kPortIndexInput ? "input" : "output", 4622 notify->debugString().c_str()); 4623 4624 break; 4625 } 4626 4627 case OMX_PortDomainAudio: 4628 { 4629 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio; 4630 4631 switch ((int)audioDef->eEncoding) { 4632 case OMX_AUDIO_CodingPCM: 4633 { 4634 OMX_AUDIO_PARAM_PCMMODETYPE params; 4635 InitOMXParams(¶ms); 4636 params.nPortIndex = portIndex; 4637 4638 err = mOMX->getParameter( 4639 mNode, OMX_IndexParamAudioPcm, ¶ms, sizeof(params)); 4640 if (err != OK) { 4641 return err; 4642 } 4643 4644 if (params.nChannels <= 0 4645 || (params.nChannels != 1 && !params.bInterleaved) 4646 || params.nBitPerSample != 16u 4647 || params.eNumData != OMX_NumericalDataSigned 4648 || params.ePCMMode != OMX_AUDIO_PCMModeLinear) { 4649 ALOGE("unsupported PCM port: %u channels%s, %u-bit, %s(%d), %s(%d) mode ", 4650 params.nChannels, 4651 params.bInterleaved ? " interleaved" : "", 4652 params.nBitPerSample, 4653 asString(params.eNumData), params.eNumData, 4654 asString(params.ePCMMode), params.ePCMMode); 4655 return FAILED_TRANSACTION; 4656 } 4657 4658 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW); 4659 notify->setInt32("channel-count", params.nChannels); 4660 notify->setInt32("sample-rate", params.nSamplingRate); 4661 4662 if (mChannelMaskPresent) { 4663 notify->setInt32("channel-mask", mChannelMask); 4664 } 4665 break; 4666 } 4667 4668 case OMX_AUDIO_CodingAAC: 4669 { 4670 OMX_AUDIO_PARAM_AACPROFILETYPE params; 4671 InitOMXParams(¶ms); 4672 params.nPortIndex = portIndex; 4673 4674 err = mOMX->getParameter( 4675 mNode, OMX_IndexParamAudioAac, ¶ms, sizeof(params)); 4676 if (err != OK) { 4677 return err; 4678 } 4679 4680 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC); 4681 notify->setInt32("channel-count", params.nChannels); 4682 notify->setInt32("sample-rate", params.nSampleRate); 4683 break; 4684 } 4685 4686 case OMX_AUDIO_CodingAMR: 4687 { 4688 OMX_AUDIO_PARAM_AMRTYPE params; 4689 InitOMXParams(¶ms); 4690 params.nPortIndex = portIndex; 4691 4692 err = mOMX->getParameter( 4693 mNode, OMX_IndexParamAudioAmr, ¶ms, sizeof(params)); 4694 if (err != OK) { 4695 return err; 4696 } 4697 4698 notify->setInt32("channel-count", 1); 4699 if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) { 4700 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_WB); 4701 notify->setInt32("sample-rate", 16000); 4702 } else { 4703 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB); 4704 notify->setInt32("sample-rate", 8000); 4705 } 4706 break; 4707 } 4708 4709 case OMX_AUDIO_CodingFLAC: 4710 { 4711 OMX_AUDIO_PARAM_FLACTYPE params; 4712 InitOMXParams(¶ms); 4713 params.nPortIndex = portIndex; 4714 4715 err = mOMX->getParameter( 4716 mNode, OMX_IndexParamAudioFlac, ¶ms, sizeof(params)); 4717 if (err != OK) { 4718 return err; 4719 } 4720 4721 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC); 4722 notify->setInt32("channel-count", params.nChannels); 4723 notify->setInt32("sample-rate", params.nSampleRate); 4724 break; 4725 } 4726 4727 case OMX_AUDIO_CodingMP3: 4728 { 4729 OMX_AUDIO_PARAM_MP3TYPE params; 4730 InitOMXParams(¶ms); 4731 params.nPortIndex = portIndex; 4732 4733 err = mOMX->getParameter( 4734 mNode, OMX_IndexParamAudioMp3, ¶ms, sizeof(params)); 4735 if (err != OK) { 4736 return err; 4737 } 4738 4739 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MPEG); 4740 notify->setInt32("channel-count", params.nChannels); 4741 notify->setInt32("sample-rate", params.nSampleRate); 4742 break; 4743 } 4744 4745 case OMX_AUDIO_CodingVORBIS: 4746 { 4747 OMX_AUDIO_PARAM_VORBISTYPE params; 4748 InitOMXParams(¶ms); 4749 params.nPortIndex = portIndex; 4750 4751 err = mOMX->getParameter( 4752 mNode, OMX_IndexParamAudioVorbis, ¶ms, sizeof(params)); 4753 if (err != OK) { 4754 return err; 4755 } 4756 4757 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_VORBIS); 4758 notify->setInt32("channel-count", params.nChannels); 4759 notify->setInt32("sample-rate", params.nSampleRate); 4760 break; 4761 } 4762 4763 case OMX_AUDIO_CodingAndroidAC3: 4764 { 4765 OMX_AUDIO_PARAM_ANDROID_AC3TYPE params; 4766 InitOMXParams(¶ms); 4767 params.nPortIndex = portIndex; 4768 4769 err = mOMX->getParameter( 4770 mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, 4771 ¶ms, sizeof(params)); 4772 if (err != OK) { 4773 return err; 4774 } 4775 4776 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3); 4777 notify->setInt32("channel-count", params.nChannels); 4778 notify->setInt32("sample-rate", params.nSampleRate); 4779 break; 4780 } 4781 4782 case OMX_AUDIO_CodingAndroidEAC3: 4783 { 4784 OMX_AUDIO_PARAM_ANDROID_EAC3TYPE params; 4785 InitOMXParams(¶ms); 4786 params.nPortIndex = portIndex; 4787 4788 err = mOMX->getParameter( 4789 mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, 4790 ¶ms, sizeof(params)); 4791 if (err != OK) { 4792 return err; 4793 } 4794 4795 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_EAC3); 4796 notify->setInt32("channel-count", params.nChannels); 4797 notify->setInt32("sample-rate", params.nSampleRate); 4798 break; 4799 } 4800 4801 case OMX_AUDIO_CodingAndroidOPUS: 4802 { 4803 OMX_AUDIO_PARAM_ANDROID_OPUSTYPE params; 4804 InitOMXParams(¶ms); 4805 params.nPortIndex = portIndex; 4806 4807 err = mOMX->getParameter( 4808 mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus, 4809 ¶ms, sizeof(params)); 4810 if (err != OK) { 4811 return err; 4812 } 4813 4814 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_OPUS); 4815 notify->setInt32("channel-count", params.nChannels); 4816 notify->setInt32("sample-rate", params.nSampleRate); 4817 break; 4818 } 4819 4820 case OMX_AUDIO_CodingG711: 4821 { 4822 OMX_AUDIO_PARAM_PCMMODETYPE params; 4823 InitOMXParams(¶ms); 4824 params.nPortIndex = portIndex; 4825 4826 err = mOMX->getParameter( 4827 mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioPcm, ¶ms, sizeof(params)); 4828 if (err != OK) { 4829 return err; 4830 } 4831 4832 const char *mime = NULL; 4833 if (params.ePCMMode == OMX_AUDIO_PCMModeMULaw) { 4834 mime = MEDIA_MIMETYPE_AUDIO_G711_MLAW; 4835 } else if (params.ePCMMode == OMX_AUDIO_PCMModeALaw) { 4836 mime = MEDIA_MIMETYPE_AUDIO_G711_ALAW; 4837 } else { // params.ePCMMode == OMX_AUDIO_PCMModeLinear 4838 mime = MEDIA_MIMETYPE_AUDIO_RAW; 4839 } 4840 notify->setString("mime", mime); 4841 notify->setInt32("channel-count", params.nChannels); 4842 notify->setInt32("sample-rate", params.nSamplingRate); 4843 break; 4844 } 4845 4846 case OMX_AUDIO_CodingGSMFR: 4847 { 4848 OMX_AUDIO_PARAM_PCMMODETYPE params; 4849 InitOMXParams(¶ms); 4850 params.nPortIndex = portIndex; 4851 4852 err = mOMX->getParameter( 4853 mNode, OMX_IndexParamAudioPcm, ¶ms, sizeof(params)); 4854 if (err != OK) { 4855 return err; 4856 } 4857 4858 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MSGSM); 4859 notify->setInt32("channel-count", params.nChannels); 4860 notify->setInt32("sample-rate", params.nSamplingRate); 4861 break; 4862 } 4863 4864 default: 4865 ALOGE("Unsupported audio coding: %s(%d)\n", 4866 asString(audioDef->eEncoding), audioDef->eEncoding); 4867 return BAD_TYPE; 4868 } 4869 break; 4870 } 4871 4872 default: 4873 ALOGE("Unsupported domain: %s(%d)", asString(def.eDomain), def.eDomain); 4874 return BAD_TYPE; 4875 } 4876 4877 return OK; 4878} 4879 4880void ACodec::onDataSpaceChanged(android_dataspace dataSpace, const ColorAspects &aspects) { 4881 // aspects are normally communicated in ColorAspects 4882 int32_t range, standard, transfer; 4883 convertCodecColorAspectsToPlatformAspects(aspects, &range, &standard, &transfer); 4884 4885 // if some aspects are unspecified, use dataspace fields 4886 if (range != 0) { 4887 range = (dataSpace & HAL_DATASPACE_RANGE_MASK) >> HAL_DATASPACE_RANGE_SHIFT; 4888 } 4889 if (standard != 0) { 4890 standard = (dataSpace & HAL_DATASPACE_STANDARD_MASK) >> HAL_DATASPACE_STANDARD_SHIFT; 4891 } 4892 if (transfer != 0) { 4893 transfer = (dataSpace & HAL_DATASPACE_TRANSFER_MASK) >> HAL_DATASPACE_TRANSFER_SHIFT; 4894 } 4895 4896 mOutputFormat = mOutputFormat->dup(); // trigger an output format changed event 4897 if (range != 0) { 4898 mOutputFormat->setInt32("color-range", range); 4899 } 4900 if (standard != 0) { 4901 mOutputFormat->setInt32("color-standard", standard); 4902 } 4903 if (transfer != 0) { 4904 mOutputFormat->setInt32("color-transfer", transfer); 4905 } 4906 4907 ALOGD("dataspace changed to %#x (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) " 4908 "(R:%d(%s), S:%d(%s), T:%d(%s))", 4909 dataSpace, 4910 aspects.mRange, asString(aspects.mRange), 4911 aspects.mPrimaries, asString(aspects.mPrimaries), 4912 aspects.mMatrixCoeffs, asString(aspects.mMatrixCoeffs), 4913 aspects.mTransfer, asString(aspects.mTransfer), 4914 range, asString((ColorRange)range), 4915 standard, asString((ColorStandard)standard), 4916 transfer, asString((ColorTransfer)transfer)); 4917} 4918 4919void ACodec::onOutputFormatChanged() { 4920 // store new output format 4921 mOutputFormat = mBaseOutputFormat->dup(); 4922 4923 if (getPortFormat(kPortIndexOutput, mOutputFormat) != OK) { 4924 ALOGE("[%s] Failed to get port format to send format change", mComponentName.c_str()); 4925 return; 4926 } 4927 4928 if (mTunneled) { 4929 sendFormatChange(); 4930 } 4931} 4932 4933void ACodec::addKeyFormatChangesToRenderBufferNotification(sp<AMessage> ¬ify) { 4934 AString mime; 4935 CHECK(mOutputFormat->findString("mime", &mime)); 4936 4937 if (mime == MEDIA_MIMETYPE_VIDEO_RAW && mNativeWindow != NULL) { 4938 // notify renderer of the crop change and dataspace change 4939 // NOTE: native window uses extended right-bottom coordinate 4940 int32_t left, top, right, bottom; 4941 if (mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) { 4942 notify->setRect("crop", left, top, right + 1, bottom + 1); 4943 } 4944 4945 int32_t dataSpace; 4946 if (mOutputFormat->findInt32("android._dataspace", &dataSpace)) { 4947 notify->setInt32("dataspace", dataSpace); 4948 } 4949 } 4950} 4951 4952void ACodec::sendFormatChange() { 4953 AString mime; 4954 CHECK(mOutputFormat->findString("mime", &mime)); 4955 4956 if (mime == MEDIA_MIMETYPE_AUDIO_RAW && (mEncoderDelay || mEncoderPadding)) { 4957 int32_t channelCount; 4958 CHECK(mOutputFormat->findInt32("channel-count", &channelCount)); 4959 if (mSkipCutBuffer != NULL) { 4960 size_t prevbufsize = mSkipCutBuffer->size(); 4961 if (prevbufsize != 0) { 4962 ALOGW("Replacing SkipCutBuffer holding %zu bytes", prevbufsize); 4963 } 4964 } 4965 mSkipCutBuffer = new SkipCutBuffer(mEncoderDelay, mEncoderPadding, channelCount); 4966 } 4967 4968 sp<AMessage> notify = mNotify->dup(); 4969 notify->setInt32("what", kWhatOutputFormatChanged); 4970 notify->setMessage("format", mOutputFormat); 4971 notify->post(); 4972 4973 // mLastOutputFormat is not used when tunneled; doing this just to stay consistent 4974 mLastOutputFormat = mOutputFormat; 4975} 4976 4977void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) { 4978 sp<AMessage> notify = mNotify->dup(); 4979 notify->setInt32("what", CodecBase::kWhatError); 4980 ALOGE("signalError(omxError %#x, internalError %d)", error, internalError); 4981 4982 if (internalError == UNKNOWN_ERROR) { // find better error code 4983 const status_t omxStatus = statusFromOMXError(error); 4984 if (omxStatus != 0) { 4985 internalError = omxStatus; 4986 } else { 4987 ALOGW("Invalid OMX error %#x", error); 4988 } 4989 } 4990 4991 mFatalError = true; 4992 4993 notify->setInt32("err", internalError); 4994 notify->setInt32("actionCode", ACTION_CODE_FATAL); // could translate from OMX error. 4995 notify->post(); 4996} 4997 4998//////////////////////////////////////////////////////////////////////////////// 4999 5000ACodec::PortDescription::PortDescription() { 5001} 5002 5003status_t ACodec::requestIDRFrame() { 5004 if (!mIsEncoder) { 5005 return ERROR_UNSUPPORTED; 5006 } 5007 5008 OMX_CONFIG_INTRAREFRESHVOPTYPE params; 5009 InitOMXParams(¶ms); 5010 5011 params.nPortIndex = kPortIndexOutput; 5012 params.IntraRefreshVOP = OMX_TRUE; 5013 5014 return mOMX->setConfig( 5015 mNode, 5016 OMX_IndexConfigVideoIntraVOPRefresh, 5017 ¶ms, 5018 sizeof(params)); 5019} 5020 5021void ACodec::PortDescription::addBuffer( 5022 IOMX::buffer_id id, const sp<ABuffer> &buffer, 5023 const sp<NativeHandle> &handle, const sp<RefBase> &memRef) { 5024 mBufferIDs.push_back(id); 5025 mBuffers.push_back(buffer); 5026 mHandles.push_back(handle); 5027 mMemRefs.push_back(memRef); 5028} 5029 5030size_t ACodec::PortDescription::countBuffers() { 5031 return mBufferIDs.size(); 5032} 5033 5034IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const { 5035 return mBufferIDs.itemAt(index); 5036} 5037 5038sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const { 5039 return mBuffers.itemAt(index); 5040} 5041 5042sp<NativeHandle> ACodec::PortDescription::handleAt(size_t index) const { 5043 return mHandles.itemAt(index); 5044} 5045 5046sp<RefBase> ACodec::PortDescription::memRefAt(size_t index) const { 5047 return mMemRefs.itemAt(index); 5048} 5049 5050//////////////////////////////////////////////////////////////////////////////// 5051 5052ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState) 5053 : AState(parentState), 5054 mCodec(codec) { 5055} 5056 5057ACodec::BaseState::PortMode ACodec::BaseState::getPortMode( 5058 OMX_U32 /* portIndex */) { 5059 return KEEP_BUFFERS; 5060} 5061 5062bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) { 5063 switch (msg->what()) { 5064 case kWhatInputBufferFilled: 5065 { 5066 onInputBufferFilled(msg); 5067 break; 5068 } 5069 5070 case kWhatOutputBufferDrained: 5071 { 5072 onOutputBufferDrained(msg); 5073 break; 5074 } 5075 5076 case ACodec::kWhatOMXMessageList: 5077 { 5078 return checkOMXMessage(msg) ? onOMXMessageList(msg) : true; 5079 } 5080 5081 case ACodec::kWhatOMXMessageItem: 5082 { 5083 // no need to check as we already did it for kWhatOMXMessageList 5084 return onOMXMessage(msg); 5085 } 5086 5087 case ACodec::kWhatOMXMessage: 5088 { 5089 return checkOMXMessage(msg) ? onOMXMessage(msg) : true; 5090 } 5091 5092 case ACodec::kWhatSetSurface: 5093 { 5094 sp<AReplyToken> replyID; 5095 CHECK(msg->senderAwaitsResponse(&replyID)); 5096 5097 sp<RefBase> obj; 5098 CHECK(msg->findObject("surface", &obj)); 5099 5100 status_t err = mCodec->handleSetSurface(static_cast<Surface *>(obj.get())); 5101 5102 sp<AMessage> response = new AMessage; 5103 response->setInt32("err", err); 5104 response->postReply(replyID); 5105 break; 5106 } 5107 5108 case ACodec::kWhatCreateInputSurface: 5109 case ACodec::kWhatSetInputSurface: 5110 case ACodec::kWhatSignalEndOfInputStream: 5111 { 5112 // This may result in an app illegal state exception. 5113 ALOGE("Message 0x%x was not handled", msg->what()); 5114 mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION); 5115 return true; 5116 } 5117 5118 case ACodec::kWhatOMXDied: 5119 { 5120 // This will result in kFlagSawMediaServerDie handling in MediaCodec. 5121 ALOGE("OMX/mediaserver died, signalling error!"); 5122 mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT); 5123 break; 5124 } 5125 5126 case ACodec::kWhatReleaseCodecInstance: 5127 { 5128 ALOGI("[%s] forcing the release of codec", 5129 mCodec->mComponentName.c_str()); 5130 status_t err = mCodec->mOMX->freeNode(mCodec->mNode); 5131 ALOGE_IF("[%s] failed to release codec instance: err=%d", 5132 mCodec->mComponentName.c_str(), err); 5133 sp<AMessage> notify = mCodec->mNotify->dup(); 5134 notify->setInt32("what", CodecBase::kWhatShutdownCompleted); 5135 notify->post(); 5136 break; 5137 } 5138 5139 default: 5140 return false; 5141 } 5142 5143 return true; 5144} 5145 5146bool ACodec::BaseState::checkOMXMessage(const sp<AMessage> &msg) { 5147 // there is a possibility that this is an outstanding message for a 5148 // codec that we have already destroyed 5149 if (mCodec->mNode == 0) { 5150 ALOGI("ignoring message as already freed component: %s", 5151 msg->debugString().c_str()); 5152 return false; 5153 } 5154 5155 IOMX::node_id nodeID; 5156 CHECK(msg->findInt32("node", (int32_t*)&nodeID)); 5157 if (nodeID != mCodec->mNode) { 5158 ALOGE("Unexpected message for nodeID: %u, should have been %u", nodeID, mCodec->mNode); 5159 return false; 5160 } 5161 return true; 5162} 5163 5164bool ACodec::BaseState::onOMXMessageList(const sp<AMessage> &msg) { 5165 sp<RefBase> obj; 5166 CHECK(msg->findObject("messages", &obj)); 5167 sp<MessageList> msgList = static_cast<MessageList *>(obj.get()); 5168 5169 bool receivedRenderedEvents = false; 5170 for (std::list<sp<AMessage>>::const_iterator it = msgList->getList().cbegin(); 5171 it != msgList->getList().cend(); ++it) { 5172 (*it)->setWhat(ACodec::kWhatOMXMessageItem); 5173 mCodec->handleMessage(*it); 5174 int32_t type; 5175 CHECK((*it)->findInt32("type", &type)); 5176 if (type == omx_message::FRAME_RENDERED) { 5177 receivedRenderedEvents = true; 5178 } 5179 } 5180 5181 if (receivedRenderedEvents) { 5182 // NOTE: all buffers are rendered in this case 5183 mCodec->notifyOfRenderedFrames(); 5184 } 5185 return true; 5186} 5187 5188bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) { 5189 int32_t type; 5190 CHECK(msg->findInt32("type", &type)); 5191 5192 switch (type) { 5193 case omx_message::EVENT: 5194 { 5195 int32_t event, data1, data2; 5196 CHECK(msg->findInt32("event", &event)); 5197 CHECK(msg->findInt32("data1", &data1)); 5198 CHECK(msg->findInt32("data2", &data2)); 5199 5200 if (event == OMX_EventCmdComplete 5201 && data1 == OMX_CommandFlush 5202 && data2 == (int32_t)OMX_ALL) { 5203 // Use of this notification is not consistent across 5204 // implementations. We'll drop this notification and rely 5205 // on flush-complete notifications on the individual port 5206 // indices instead. 5207 5208 return true; 5209 } 5210 5211 return onOMXEvent( 5212 static_cast<OMX_EVENTTYPE>(event), 5213 static_cast<OMX_U32>(data1), 5214 static_cast<OMX_U32>(data2)); 5215 } 5216 5217 case omx_message::EMPTY_BUFFER_DONE: 5218 { 5219 IOMX::buffer_id bufferID; 5220 int32_t fenceFd; 5221 5222 CHECK(msg->findInt32("buffer", (int32_t*)&bufferID)); 5223 CHECK(msg->findInt32("fence_fd", &fenceFd)); 5224 5225 return onOMXEmptyBufferDone(bufferID, fenceFd); 5226 } 5227 5228 case omx_message::FILL_BUFFER_DONE: 5229 { 5230 IOMX::buffer_id bufferID; 5231 CHECK(msg->findInt32("buffer", (int32_t*)&bufferID)); 5232 5233 int32_t rangeOffset, rangeLength, flags, fenceFd; 5234 int64_t timeUs; 5235 5236 CHECK(msg->findInt32("range_offset", &rangeOffset)); 5237 CHECK(msg->findInt32("range_length", &rangeLength)); 5238 CHECK(msg->findInt32("flags", &flags)); 5239 CHECK(msg->findInt64("timestamp", &timeUs)); 5240 CHECK(msg->findInt32("fence_fd", &fenceFd)); 5241 5242 return onOMXFillBufferDone( 5243 bufferID, 5244 (size_t)rangeOffset, (size_t)rangeLength, 5245 (OMX_U32)flags, 5246 timeUs, 5247 fenceFd); 5248 } 5249 5250 case omx_message::FRAME_RENDERED: 5251 { 5252 int64_t mediaTimeUs, systemNano; 5253 5254 CHECK(msg->findInt64("media_time_us", &mediaTimeUs)); 5255 CHECK(msg->findInt64("system_nano", &systemNano)); 5256 5257 return onOMXFrameRendered( 5258 mediaTimeUs, systemNano); 5259 } 5260 5261 default: 5262 ALOGE("Unexpected message type: %d", type); 5263 return false; 5264 } 5265} 5266 5267bool ACodec::BaseState::onOMXFrameRendered( 5268 int64_t mediaTimeUs __unused, nsecs_t systemNano __unused) { 5269 // ignore outside of Executing and PortSettingsChanged states 5270 return true; 5271} 5272 5273bool ACodec::BaseState::onOMXEvent( 5274 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 5275 if (event == OMX_EventDataSpaceChanged) { 5276 ColorAspects aspects; 5277 aspects.mRange = (ColorAspects::Range)((data2 >> 24) & 0xFF); 5278 aspects.mPrimaries = (ColorAspects::Primaries)((data2 >> 16) & 0xFF); 5279 aspects.mMatrixCoeffs = (ColorAspects::MatrixCoeffs)((data2 >> 8) & 0xFF); 5280 aspects.mTransfer = (ColorAspects::Transfer)(data2 & 0xFF); 5281 5282 mCodec->onDataSpaceChanged((android_dataspace)data1, aspects); 5283 return true; 5284 } 5285 5286 if (event != OMX_EventError) { 5287 ALOGV("[%s] EVENT(%d, 0x%08x, 0x%08x)", 5288 mCodec->mComponentName.c_str(), event, data1, data2); 5289 5290 return false; 5291 } 5292 5293 ALOGE("[%s] ERROR(0x%08x)", mCodec->mComponentName.c_str(), data1); 5294 5295 // verify OMX component sends back an error we expect. 5296 OMX_ERRORTYPE omxError = (OMX_ERRORTYPE)data1; 5297 if (!isOMXError(omxError)) { 5298 ALOGW("Invalid OMX error %#x", omxError); 5299 omxError = OMX_ErrorUndefined; 5300 } 5301 mCodec->signalError(omxError); 5302 5303 return true; 5304} 5305 5306bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID, int fenceFd) { 5307 ALOGV("[%s] onOMXEmptyBufferDone %u", 5308 mCodec->mComponentName.c_str(), bufferID); 5309 5310 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID); 5311 BufferInfo::Status status = BufferInfo::getSafeStatus(info); 5312 if (status != BufferInfo::OWNED_BY_COMPONENT) { 5313 ALOGE("Wrong ownership in EBD: %s(%d) buffer #%u", _asString(status), status, bufferID); 5314 mCodec->dumpBuffers(kPortIndexInput); 5315 if (fenceFd >= 0) { 5316 ::close(fenceFd); 5317 } 5318 return false; 5319 } 5320 info->mStatus = BufferInfo::OWNED_BY_US; 5321 5322 // input buffers cannot take fences, so wait for any fence now 5323 (void)mCodec->waitForFence(fenceFd, "onOMXEmptyBufferDone"); 5324 fenceFd = -1; 5325 5326 // still save fence for completeness 5327 info->setWriteFence(fenceFd, "onOMXEmptyBufferDone"); 5328 5329 // We're in "store-metadata-in-buffers" mode, the underlying 5330 // OMX component had access to data that's implicitly refcounted 5331 // by this "MediaBuffer" object. Now that the OMX component has 5332 // told us that it's done with the input buffer, we can decrement 5333 // the mediaBuffer's reference count. 5334 info->mData->setMediaBufferBase(NULL); 5335 5336 PortMode mode = getPortMode(kPortIndexInput); 5337 5338 switch (mode) { 5339 case KEEP_BUFFERS: 5340 break; 5341 5342 case RESUBMIT_BUFFERS: 5343 postFillThisBuffer(info); 5344 break; 5345 5346 case FREE_BUFFERS: 5347 default: 5348 ALOGE("SHOULD NOT REACH HERE: cannot free empty output buffers"); 5349 return false; 5350 } 5351 5352 return true; 5353} 5354 5355void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) { 5356 if (mCodec->mPortEOS[kPortIndexInput]) { 5357 return; 5358 } 5359 5360 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 5361 5362 sp<AMessage> notify = mCodec->mNotify->dup(); 5363 notify->setInt32("what", CodecBase::kWhatFillThisBuffer); 5364 notify->setInt32("buffer-id", info->mBufferID); 5365 5366 info->mData->meta()->clear(); 5367 notify->setBuffer("buffer", info->mData); 5368 5369 sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec); 5370 reply->setInt32("buffer-id", info->mBufferID); 5371 5372 notify->setMessage("reply", reply); 5373 5374 notify->post(); 5375 5376 info->mStatus = BufferInfo::OWNED_BY_UPSTREAM; 5377} 5378 5379void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { 5380 IOMX::buffer_id bufferID; 5381 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID)); 5382 sp<ABuffer> buffer; 5383 int32_t err = OK; 5384 bool eos = false; 5385 PortMode mode = getPortMode(kPortIndexInput); 5386 5387 if (!msg->findBuffer("buffer", &buffer)) { 5388 /* these are unfilled buffers returned by client */ 5389 CHECK(msg->findInt32("err", &err)); 5390 5391 if (err == OK) { 5392 /* buffers with no errors are returned on MediaCodec.flush */ 5393 mode = KEEP_BUFFERS; 5394 } else { 5395 ALOGV("[%s] saw error %d instead of an input buffer", 5396 mCodec->mComponentName.c_str(), err); 5397 eos = true; 5398 } 5399 5400 buffer.clear(); 5401 } 5402 5403 int32_t tmp; 5404 if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) { 5405 eos = true; 5406 err = ERROR_END_OF_STREAM; 5407 } 5408 5409 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID); 5410 BufferInfo::Status status = BufferInfo::getSafeStatus(info); 5411 if (status != BufferInfo::OWNED_BY_UPSTREAM) { 5412 ALOGE("Wrong ownership in IBF: %s(%d) buffer #%u", _asString(status), status, bufferID); 5413 mCodec->dumpBuffers(kPortIndexInput); 5414 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 5415 return; 5416 } 5417 5418 info->mStatus = BufferInfo::OWNED_BY_US; 5419 5420 switch (mode) { 5421 case KEEP_BUFFERS: 5422 { 5423 if (eos) { 5424 if (!mCodec->mPortEOS[kPortIndexInput]) { 5425 mCodec->mPortEOS[kPortIndexInput] = true; 5426 mCodec->mInputEOSResult = err; 5427 } 5428 } 5429 break; 5430 } 5431 5432 case RESUBMIT_BUFFERS: 5433 { 5434 if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) { 5435 // Do not send empty input buffer w/o EOS to the component. 5436 if (buffer->size() == 0 && !eos) { 5437 postFillThisBuffer(info); 5438 break; 5439 } 5440 5441 int64_t timeUs; 5442 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 5443 5444 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME; 5445 5446 int32_t isCSD; 5447 if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) { 5448 flags |= OMX_BUFFERFLAG_CODECCONFIG; 5449 } 5450 5451 if (eos) { 5452 flags |= OMX_BUFFERFLAG_EOS; 5453 } 5454 5455 if (buffer != info->mData) { 5456 ALOGV("[%s] Needs to copy input data for buffer %u. (%p != %p)", 5457 mCodec->mComponentName.c_str(), 5458 bufferID, 5459 buffer.get(), info->mData.get()); 5460 5461 if (buffer->size() > info->mData->capacity()) { 5462 ALOGE("data size (%zu) is greated than buffer capacity (%zu)", 5463 buffer->size(), // this is the data received 5464 info->mData->capacity()); // this is out buffer size 5465 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 5466 return; 5467 } 5468 memcpy(info->mData->data(), buffer->data(), buffer->size()); 5469 } 5470 5471 if (flags & OMX_BUFFERFLAG_CODECCONFIG) { 5472 ALOGV("[%s] calling emptyBuffer %u w/ codec specific data", 5473 mCodec->mComponentName.c_str(), bufferID); 5474 } else if (flags & OMX_BUFFERFLAG_EOS) { 5475 ALOGV("[%s] calling emptyBuffer %u w/ EOS", 5476 mCodec->mComponentName.c_str(), bufferID); 5477 } else { 5478#if TRACK_BUFFER_TIMING 5479 ALOGI("[%s] calling emptyBuffer %u w/ time %lld us", 5480 mCodec->mComponentName.c_str(), bufferID, (long long)timeUs); 5481#else 5482 ALOGV("[%s] calling emptyBuffer %u w/ time %lld us", 5483 mCodec->mComponentName.c_str(), bufferID, (long long)timeUs); 5484#endif 5485 } 5486 5487#if TRACK_BUFFER_TIMING 5488 ACodec::BufferStats stats; 5489 stats.mEmptyBufferTimeUs = ALooper::GetNowUs(); 5490 stats.mFillBufferDoneTimeUs = -1ll; 5491 mCodec->mBufferStats.add(timeUs, stats); 5492#endif 5493 5494 if (mCodec->storingMetadataInDecodedBuffers()) { 5495 // try to submit an output buffer for each input buffer 5496 PortMode outputMode = getPortMode(kPortIndexOutput); 5497 5498 ALOGV("MetadataBuffersToSubmit=%u portMode=%s", 5499 mCodec->mMetadataBuffersToSubmit, 5500 (outputMode == FREE_BUFFERS ? "FREE" : 5501 outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT")); 5502 if (outputMode == RESUBMIT_BUFFERS) { 5503 mCodec->submitOutputMetadataBuffer(); 5504 } 5505 } 5506 info->checkReadFence("onInputBufferFilled"); 5507 status_t err2 = mCodec->mOMX->emptyBuffer( 5508 mCodec->mNode, 5509 bufferID, 5510 0, 5511 buffer->size(), 5512 flags, 5513 timeUs, 5514 info->mFenceFd); 5515 info->mFenceFd = -1; 5516 if (err2 != OK) { 5517 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2)); 5518 return; 5519 } 5520 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 5521 5522 if (!eos && err == OK) { 5523 getMoreInputDataIfPossible(); 5524 } else { 5525 ALOGV("[%s] Signalled EOS (%d) on the input port", 5526 mCodec->mComponentName.c_str(), err); 5527 5528 mCodec->mPortEOS[kPortIndexInput] = true; 5529 mCodec->mInputEOSResult = err; 5530 } 5531 } else if (!mCodec->mPortEOS[kPortIndexInput]) { 5532 if (err != OK && err != ERROR_END_OF_STREAM) { 5533 ALOGV("[%s] Signalling EOS on the input port due to error %d", 5534 mCodec->mComponentName.c_str(), err); 5535 } else { 5536 ALOGV("[%s] Signalling EOS on the input port", 5537 mCodec->mComponentName.c_str()); 5538 } 5539 5540 ALOGV("[%s] calling emptyBuffer %u signalling EOS", 5541 mCodec->mComponentName.c_str(), bufferID); 5542 5543 info->checkReadFence("onInputBufferFilled"); 5544 status_t err2 = mCodec->mOMX->emptyBuffer( 5545 mCodec->mNode, 5546 bufferID, 5547 0, 5548 0, 5549 OMX_BUFFERFLAG_EOS, 5550 0, 5551 info->mFenceFd); 5552 info->mFenceFd = -1; 5553 if (err2 != OK) { 5554 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2)); 5555 return; 5556 } 5557 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 5558 5559 mCodec->mPortEOS[kPortIndexInput] = true; 5560 mCodec->mInputEOSResult = err; 5561 } 5562 break; 5563 } 5564 5565 case FREE_BUFFERS: 5566 break; 5567 5568 default: 5569 ALOGE("invalid port mode: %d", mode); 5570 break; 5571 } 5572} 5573 5574void ACodec::BaseState::getMoreInputDataIfPossible() { 5575 if (mCodec->mPortEOS[kPortIndexInput]) { 5576 return; 5577 } 5578 5579 BufferInfo *eligible = NULL; 5580 5581 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 5582 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 5583 5584#if 0 5585 if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) { 5586 // There's already a "read" pending. 5587 return; 5588 } 5589#endif 5590 5591 if (info->mStatus == BufferInfo::OWNED_BY_US) { 5592 eligible = info; 5593 } 5594 } 5595 5596 if (eligible == NULL) { 5597 return; 5598 } 5599 5600 postFillThisBuffer(eligible); 5601} 5602 5603bool ACodec::BaseState::onOMXFillBufferDone( 5604 IOMX::buffer_id bufferID, 5605 size_t rangeOffset, size_t rangeLength, 5606 OMX_U32 flags, 5607 int64_t timeUs, 5608 int fenceFd) { 5609 ALOGV("[%s] onOMXFillBufferDone %u time %" PRId64 " us, flags = 0x%08x", 5610 mCodec->mComponentName.c_str(), bufferID, timeUs, flags); 5611 5612 ssize_t index; 5613 status_t err= OK; 5614 5615#if TRACK_BUFFER_TIMING 5616 index = mCodec->mBufferStats.indexOfKey(timeUs); 5617 if (index >= 0) { 5618 ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index); 5619 stats->mFillBufferDoneTimeUs = ALooper::GetNowUs(); 5620 5621 ALOGI("frame PTS %lld: %lld", 5622 timeUs, 5623 stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs); 5624 5625 mCodec->mBufferStats.removeItemsAt(index); 5626 stats = NULL; 5627 } 5628#endif 5629 5630 BufferInfo *info = 5631 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 5632 BufferInfo::Status status = BufferInfo::getSafeStatus(info); 5633 if (status != BufferInfo::OWNED_BY_COMPONENT) { 5634 ALOGE("Wrong ownership in FBD: %s(%d) buffer #%u", _asString(status), status, bufferID); 5635 mCodec->dumpBuffers(kPortIndexOutput); 5636 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 5637 if (fenceFd >= 0) { 5638 ::close(fenceFd); 5639 } 5640 return true; 5641 } 5642 5643 info->mDequeuedAt = ++mCodec->mDequeueCounter; 5644 info->mStatus = BufferInfo::OWNED_BY_US; 5645 5646 if (info->mRenderInfo != NULL) { 5647 // The fence for an emptied buffer must have signaled, but there still could be queued 5648 // or out-of-order dequeued buffers in the render queue prior to this buffer. Drop these, 5649 // as we will soon requeue this buffer to the surface. While in theory we could still keep 5650 // track of buffers that are requeued to the surface, it is better to add support to the 5651 // buffer-queue to notify us of released buffers and their fences (in the future). 5652 mCodec->notifyOfRenderedFrames(true /* dropIncomplete */); 5653 } 5654 5655 // byte buffers cannot take fences, so wait for any fence now 5656 if (mCodec->mNativeWindow == NULL) { 5657 (void)mCodec->waitForFence(fenceFd, "onOMXFillBufferDone"); 5658 fenceFd = -1; 5659 } 5660 info->setReadFence(fenceFd, "onOMXFillBufferDone"); 5661 5662 PortMode mode = getPortMode(kPortIndexOutput); 5663 5664 switch (mode) { 5665 case KEEP_BUFFERS: 5666 break; 5667 5668 case RESUBMIT_BUFFERS: 5669 { 5670 if (rangeLength == 0 && (!(flags & OMX_BUFFERFLAG_EOS) 5671 || mCodec->mPortEOS[kPortIndexOutput])) { 5672 ALOGV("[%s] calling fillBuffer %u", 5673 mCodec->mComponentName.c_str(), info->mBufferID); 5674 5675 err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID, info->mFenceFd); 5676 info->mFenceFd = -1; 5677 if (err != OK) { 5678 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 5679 return true; 5680 } 5681 5682 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 5683 break; 5684 } 5685 5686 sp<AMessage> reply = 5687 new AMessage(kWhatOutputBufferDrained, mCodec); 5688 5689 if (mCodec->mOutputFormat != mCodec->mLastOutputFormat && rangeLength > 0) { 5690 mCodec->addKeyFormatChangesToRenderBufferNotification(reply); 5691 mCodec->sendFormatChange(); 5692 } 5693 5694 if (mCodec->usingMetadataOnEncoderOutput()) { 5695 native_handle_t *handle = NULL; 5696 VideoGrallocMetadata &grallocMeta = *(VideoGrallocMetadata *)info->mData->data(); 5697 VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)info->mData->data(); 5698 if (info->mData->size() >= sizeof(grallocMeta) 5699 && grallocMeta.eType == kMetadataBufferTypeGrallocSource) { 5700 handle = (native_handle_t *)(uintptr_t)grallocMeta.pHandle; 5701 } else if (info->mData->size() >= sizeof(nativeMeta) 5702 && nativeMeta.eType == kMetadataBufferTypeANWBuffer) { 5703#ifdef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS 5704 // ANativeWindowBuffer is only valid on 32-bit/mediaserver process 5705 handle = NULL; 5706#else 5707 handle = (native_handle_t *)nativeMeta.pBuffer->handle; 5708#endif 5709 } 5710 info->mData->meta()->setPointer("handle", handle); 5711 info->mData->meta()->setInt32("rangeOffset", rangeOffset); 5712 info->mData->meta()->setInt32("rangeLength", rangeLength); 5713 } else { 5714 info->mData->setRange(rangeOffset, rangeLength); 5715 } 5716#if 0 5717 if (mCodec->mNativeWindow == NULL) { 5718 if (IsIDR(info->mData)) { 5719 ALOGI("IDR frame"); 5720 } 5721 } 5722#endif 5723 5724 if (mCodec->mSkipCutBuffer != NULL) { 5725 mCodec->mSkipCutBuffer->submit(info->mData); 5726 } 5727 info->mData->meta()->setInt64("timeUs", timeUs); 5728 5729 sp<AMessage> notify = mCodec->mNotify->dup(); 5730 notify->setInt32("what", CodecBase::kWhatDrainThisBuffer); 5731 notify->setInt32("buffer-id", info->mBufferID); 5732 notify->setBuffer("buffer", info->mData); 5733 notify->setInt32("flags", flags); 5734 5735 reply->setInt32("buffer-id", info->mBufferID); 5736 5737 notify->setMessage("reply", reply); 5738 5739 notify->post(); 5740 5741 info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM; 5742 5743 if (flags & OMX_BUFFERFLAG_EOS) { 5744 ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str()); 5745 5746 sp<AMessage> notify = mCodec->mNotify->dup(); 5747 notify->setInt32("what", CodecBase::kWhatEOS); 5748 notify->setInt32("err", mCodec->mInputEOSResult); 5749 notify->post(); 5750 5751 mCodec->mPortEOS[kPortIndexOutput] = true; 5752 } 5753 break; 5754 } 5755 5756 case FREE_BUFFERS: 5757 err = mCodec->freeBuffer(kPortIndexOutput, index); 5758 if (err != OK) { 5759 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 5760 return true; 5761 } 5762 break; 5763 5764 default: 5765 ALOGE("Invalid port mode: %d", mode); 5766 return false; 5767 } 5768 5769 return true; 5770} 5771 5772void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { 5773 IOMX::buffer_id bufferID; 5774 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID)); 5775 ssize_t index; 5776 BufferInfo *info = mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 5777 BufferInfo::Status status = BufferInfo::getSafeStatus(info); 5778 if (status != BufferInfo::OWNED_BY_DOWNSTREAM) { 5779 ALOGE("Wrong ownership in OBD: %s(%d) buffer #%u", _asString(status), status, bufferID); 5780 mCodec->dumpBuffers(kPortIndexOutput); 5781 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 5782 return; 5783 } 5784 5785 android_native_rect_t crop; 5786 if (msg->findRect("crop", &crop.left, &crop.top, &crop.right, &crop.bottom)) { 5787 status_t err = native_window_set_crop(mCodec->mNativeWindow.get(), &crop); 5788 ALOGW_IF(err != NO_ERROR, "failed to set crop: %d", err); 5789 } 5790 5791 int32_t dataSpace; 5792 if (msg->findInt32("dataspace", &dataSpace)) { 5793 status_t err = native_window_set_buffers_data_space( 5794 mCodec->mNativeWindow.get(), (android_dataspace)dataSpace); 5795 ALOGW_IF(err != NO_ERROR, "failed to set dataspace: %d", err); 5796 } 5797 5798 int32_t render; 5799 if (mCodec->mNativeWindow != NULL 5800 && msg->findInt32("render", &render) && render != 0 5801 && info->mData != NULL && info->mData->size() != 0) { 5802 ATRACE_NAME("render"); 5803 // The client wants this buffer to be rendered. 5804 5805 // save buffers sent to the surface so we can get render time when they return 5806 int64_t mediaTimeUs = -1; 5807 info->mData->meta()->findInt64("timeUs", &mediaTimeUs); 5808 if (mediaTimeUs >= 0) { 5809 mCodec->mRenderTracker.onFrameQueued( 5810 mediaTimeUs, info->mGraphicBuffer, new Fence(::dup(info->mFenceFd))); 5811 } 5812 5813 int64_t timestampNs = 0; 5814 if (!msg->findInt64("timestampNs", ×tampNs)) { 5815 // use media timestamp if client did not request a specific render timestamp 5816 if (info->mData->meta()->findInt64("timeUs", ×tampNs)) { 5817 ALOGV("using buffer PTS of %lld", (long long)timestampNs); 5818 timestampNs *= 1000; 5819 } 5820 } 5821 5822 status_t err; 5823 err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs); 5824 ALOGW_IF(err != NO_ERROR, "failed to set buffer timestamp: %d", err); 5825 5826 info->checkReadFence("onOutputBufferDrained before queueBuffer"); 5827 err = mCodec->mNativeWindow->queueBuffer( 5828 mCodec->mNativeWindow.get(), info->mGraphicBuffer.get(), info->mFenceFd); 5829 info->mFenceFd = -1; 5830 if (err == OK) { 5831 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 5832 } else { 5833 ALOGE("queueBuffer failed in onOutputBufferDrained: %d", err); 5834 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 5835 info->mStatus = BufferInfo::OWNED_BY_US; 5836 // keeping read fence as write fence to avoid clobbering 5837 info->mIsReadFence = false; 5838 } 5839 } else { 5840 if (mCodec->mNativeWindow != NULL && 5841 (info->mData == NULL || info->mData->size() != 0)) { 5842 // move read fence into write fence to avoid clobbering 5843 info->mIsReadFence = false; 5844 ATRACE_NAME("frame-drop"); 5845 } 5846 info->mStatus = BufferInfo::OWNED_BY_US; 5847 } 5848 5849 PortMode mode = getPortMode(kPortIndexOutput); 5850 5851 switch (mode) { 5852 case KEEP_BUFFERS: 5853 { 5854 // XXX fishy, revisit!!! What about the FREE_BUFFERS case below? 5855 5856 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 5857 // We cannot resubmit the buffer we just rendered, dequeue 5858 // the spare instead. 5859 5860 info = mCodec->dequeueBufferFromNativeWindow(); 5861 } 5862 break; 5863 } 5864 5865 case RESUBMIT_BUFFERS: 5866 { 5867 if (!mCodec->mPortEOS[kPortIndexOutput]) { 5868 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 5869 // We cannot resubmit the buffer we just rendered, dequeue 5870 // the spare instead. 5871 5872 info = mCodec->dequeueBufferFromNativeWindow(); 5873 } 5874 5875 if (info != NULL) { 5876 ALOGV("[%s] calling fillBuffer %u", 5877 mCodec->mComponentName.c_str(), info->mBufferID); 5878 info->checkWriteFence("onOutputBufferDrained::RESUBMIT_BUFFERS"); 5879 status_t err = mCodec->mOMX->fillBuffer( 5880 mCodec->mNode, info->mBufferID, info->mFenceFd); 5881 info->mFenceFd = -1; 5882 if (err == OK) { 5883 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 5884 } else { 5885 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 5886 } 5887 } 5888 } 5889 break; 5890 } 5891 5892 case FREE_BUFFERS: 5893 { 5894 status_t err = mCodec->freeBuffer(kPortIndexOutput, index); 5895 if (err != OK) { 5896 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 5897 } 5898 break; 5899 } 5900 5901 default: 5902 ALOGE("Invalid port mode: %d", mode); 5903 return; 5904 } 5905} 5906 5907//////////////////////////////////////////////////////////////////////////////// 5908 5909ACodec::UninitializedState::UninitializedState(ACodec *codec) 5910 : BaseState(codec) { 5911} 5912 5913void ACodec::UninitializedState::stateEntered() { 5914 ALOGV("Now uninitialized"); 5915 5916 if (mDeathNotifier != NULL) { 5917 mCodec->mNodeBinder->unlinkToDeath(mDeathNotifier); 5918 mDeathNotifier.clear(); 5919 } 5920 5921 mCodec->mUsingNativeWindow = false; 5922 mCodec->mNativeWindow.clear(); 5923 mCodec->mNativeWindowUsageBits = 0; 5924 mCodec->mNode = 0; 5925 mCodec->mOMX.clear(); 5926 mCodec->mQuirks = 0; 5927 mCodec->mFlags = 0; 5928 mCodec->mInputMetadataType = kMetadataBufferTypeInvalid; 5929 mCodec->mOutputMetadataType = kMetadataBufferTypeInvalid; 5930 mCodec->mComponentName.clear(); 5931} 5932 5933bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) { 5934 bool handled = false; 5935 5936 switch (msg->what()) { 5937 case ACodec::kWhatSetup: 5938 { 5939 onSetup(msg); 5940 5941 handled = true; 5942 break; 5943 } 5944 5945 case ACodec::kWhatAllocateComponent: 5946 { 5947 onAllocateComponent(msg); 5948 handled = true; 5949 break; 5950 } 5951 5952 case ACodec::kWhatShutdown: 5953 { 5954 int32_t keepComponentAllocated; 5955 CHECK(msg->findInt32( 5956 "keepComponentAllocated", &keepComponentAllocated)); 5957 ALOGW_IF(keepComponentAllocated, 5958 "cannot keep component allocated on shutdown in Uninitialized state"); 5959 5960 sp<AMessage> notify = mCodec->mNotify->dup(); 5961 notify->setInt32("what", CodecBase::kWhatShutdownCompleted); 5962 notify->post(); 5963 5964 handled = true; 5965 break; 5966 } 5967 5968 case ACodec::kWhatFlush: 5969 { 5970 sp<AMessage> notify = mCodec->mNotify->dup(); 5971 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 5972 notify->post(); 5973 5974 handled = true; 5975 break; 5976 } 5977 5978 case ACodec::kWhatReleaseCodecInstance: 5979 { 5980 // nothing to do, as we have already signaled shutdown 5981 handled = true; 5982 break; 5983 } 5984 5985 default: 5986 return BaseState::onMessageReceived(msg); 5987 } 5988 5989 return handled; 5990} 5991 5992void ACodec::UninitializedState::onSetup( 5993 const sp<AMessage> &msg) { 5994 if (onAllocateComponent(msg) 5995 && mCodec->mLoadedState->onConfigureComponent(msg)) { 5996 mCodec->mLoadedState->onStart(); 5997 } 5998} 5999 6000bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) { 6001 ALOGV("onAllocateComponent"); 6002 6003 CHECK(mCodec->mNode == 0); 6004 6005 OMXClient client; 6006 if (client.connect() != OK) { 6007 mCodec->signalError(OMX_ErrorUndefined, NO_INIT); 6008 return false; 6009 } 6010 6011 sp<IOMX> omx = client.interface(); 6012 6013 sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec); 6014 6015 Vector<AString> matchingCodecs; 6016 6017 AString mime; 6018 6019 AString componentName; 6020 uint32_t quirks = 0; 6021 int32_t encoder = false; 6022 if (msg->findString("componentName", &componentName)) { 6023 sp<IMediaCodecList> list = MediaCodecList::getInstance(); 6024 if (list != NULL && list->findCodecByName(componentName.c_str()) >= 0) { 6025 matchingCodecs.add(componentName); 6026 } 6027 } else { 6028 CHECK(msg->findString("mime", &mime)); 6029 6030 if (!msg->findInt32("encoder", &encoder)) { 6031 encoder = false; 6032 } 6033 6034 MediaCodecList::findMatchingCodecs( 6035 mime.c_str(), 6036 encoder, // createEncoder 6037 0, // flags 6038 &matchingCodecs); 6039 } 6040 6041 sp<CodecObserver> observer = new CodecObserver; 6042 IOMX::node_id node = 0; 6043 6044 status_t err = NAME_NOT_FOUND; 6045 for (size_t matchIndex = 0; matchIndex < matchingCodecs.size(); 6046 ++matchIndex) { 6047 componentName = matchingCodecs[matchIndex]; 6048 quirks = MediaCodecList::getQuirksFor(componentName.c_str()); 6049 6050 pid_t tid = gettid(); 6051 int prevPriority = androidGetThreadPriority(tid); 6052 androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND); 6053 err = omx->allocateNode(componentName.c_str(), observer, &mCodec->mNodeBinder, &node); 6054 androidSetThreadPriority(tid, prevPriority); 6055 6056 if (err == OK) { 6057 break; 6058 } else { 6059 ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str()); 6060 } 6061 6062 node = 0; 6063 } 6064 6065 if (node == 0) { 6066 if (!mime.empty()) { 6067 ALOGE("Unable to instantiate a %scoder for type '%s' with err %#x.", 6068 encoder ? "en" : "de", mime.c_str(), err); 6069 } else { 6070 ALOGE("Unable to instantiate codec '%s' with err %#x.", componentName.c_str(), err); 6071 } 6072 6073 mCodec->signalError((OMX_ERRORTYPE)err, makeNoSideEffectStatus(err)); 6074 return false; 6075 } 6076 6077 mDeathNotifier = new DeathNotifier(notify); 6078 if (mCodec->mNodeBinder == NULL || 6079 mCodec->mNodeBinder->linkToDeath(mDeathNotifier) != OK) { 6080 // This was a local binder, if it dies so do we, we won't care 6081 // about any notifications in the afterlife. 6082 mDeathNotifier.clear(); 6083 } 6084 6085 notify = new AMessage(kWhatOMXMessageList, mCodec); 6086 observer->setNotificationMessage(notify); 6087 6088 mCodec->mComponentName = componentName; 6089 mCodec->mRenderTracker.setComponentName(componentName); 6090 mCodec->mFlags = 0; 6091 6092 if (componentName.endsWith(".secure")) { 6093 mCodec->mFlags |= kFlagIsSecure; 6094 mCodec->mFlags |= kFlagIsGrallocUsageProtected; 6095 mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown; 6096 } 6097 6098 mCodec->mQuirks = quirks; 6099 mCodec->mOMX = omx; 6100 mCodec->mNode = node; 6101 6102 { 6103 sp<AMessage> notify = mCodec->mNotify->dup(); 6104 notify->setInt32("what", CodecBase::kWhatComponentAllocated); 6105 notify->setString("componentName", mCodec->mComponentName.c_str()); 6106 notify->post(); 6107 } 6108 6109 mCodec->changeState(mCodec->mLoadedState); 6110 6111 return true; 6112} 6113 6114//////////////////////////////////////////////////////////////////////////////// 6115 6116ACodec::LoadedState::LoadedState(ACodec *codec) 6117 : BaseState(codec) { 6118} 6119 6120void ACodec::LoadedState::stateEntered() { 6121 ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str()); 6122 6123 mCodec->mPortEOS[kPortIndexInput] = 6124 mCodec->mPortEOS[kPortIndexOutput] = false; 6125 6126 mCodec->mInputEOSResult = OK; 6127 6128 mCodec->mDequeueCounter = 0; 6129 mCodec->mMetadataBuffersToSubmit = 0; 6130 mCodec->mRepeatFrameDelayUs = -1ll; 6131 mCodec->mInputFormat.clear(); 6132 mCodec->mOutputFormat.clear(); 6133 mCodec->mBaseOutputFormat.clear(); 6134 6135 if (mCodec->mShutdownInProgress) { 6136 bool keepComponentAllocated = mCodec->mKeepComponentAllocated; 6137 6138 mCodec->mShutdownInProgress = false; 6139 mCodec->mKeepComponentAllocated = false; 6140 6141 onShutdown(keepComponentAllocated); 6142 } 6143 mCodec->mExplicitShutdown = false; 6144 6145 mCodec->processDeferredMessages(); 6146} 6147 6148void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) { 6149 if (!keepComponentAllocated) { 6150 (void)mCodec->mOMX->freeNode(mCodec->mNode); 6151 6152 mCodec->changeState(mCodec->mUninitializedState); 6153 } 6154 6155 if (mCodec->mExplicitShutdown) { 6156 sp<AMessage> notify = mCodec->mNotify->dup(); 6157 notify->setInt32("what", CodecBase::kWhatShutdownCompleted); 6158 notify->post(); 6159 mCodec->mExplicitShutdown = false; 6160 } 6161} 6162 6163bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) { 6164 bool handled = false; 6165 6166 switch (msg->what()) { 6167 case ACodec::kWhatConfigureComponent: 6168 { 6169 onConfigureComponent(msg); 6170 handled = true; 6171 break; 6172 } 6173 6174 case ACodec::kWhatCreateInputSurface: 6175 { 6176 onCreateInputSurface(msg); 6177 handled = true; 6178 break; 6179 } 6180 6181 case ACodec::kWhatSetInputSurface: 6182 { 6183 onSetInputSurface(msg); 6184 handled = true; 6185 break; 6186 } 6187 6188 case ACodec::kWhatStart: 6189 { 6190 onStart(); 6191 handled = true; 6192 break; 6193 } 6194 6195 case ACodec::kWhatShutdown: 6196 { 6197 int32_t keepComponentAllocated; 6198 CHECK(msg->findInt32( 6199 "keepComponentAllocated", &keepComponentAllocated)); 6200 6201 mCodec->mExplicitShutdown = true; 6202 onShutdown(keepComponentAllocated); 6203 6204 handled = true; 6205 break; 6206 } 6207 6208 case ACodec::kWhatFlush: 6209 { 6210 sp<AMessage> notify = mCodec->mNotify->dup(); 6211 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 6212 notify->post(); 6213 6214 handled = true; 6215 break; 6216 } 6217 6218 default: 6219 return BaseState::onMessageReceived(msg); 6220 } 6221 6222 return handled; 6223} 6224 6225bool ACodec::LoadedState::onConfigureComponent( 6226 const sp<AMessage> &msg) { 6227 ALOGV("onConfigureComponent"); 6228 6229 CHECK(mCodec->mNode != 0); 6230 6231 status_t err = OK; 6232 AString mime; 6233 if (!msg->findString("mime", &mime)) { 6234 err = BAD_VALUE; 6235 } else { 6236 err = mCodec->configureCodec(mime.c_str(), msg); 6237 } 6238 if (err != OK) { 6239 ALOGE("[%s] configureCodec returning error %d", 6240 mCodec->mComponentName.c_str(), err); 6241 6242 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6243 return false; 6244 } 6245 6246 { 6247 sp<AMessage> notify = mCodec->mNotify->dup(); 6248 notify->setInt32("what", CodecBase::kWhatComponentConfigured); 6249 notify->setMessage("input-format", mCodec->mInputFormat); 6250 notify->setMessage("output-format", mCodec->mOutputFormat); 6251 notify->post(); 6252 } 6253 6254 return true; 6255} 6256 6257status_t ACodec::LoadedState::setupInputSurface() { 6258 status_t err = OK; 6259 6260 if (mCodec->mRepeatFrameDelayUs > 0ll) { 6261 err = mCodec->mOMX->setInternalOption( 6262 mCodec->mNode, 6263 kPortIndexInput, 6264 IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY, 6265 &mCodec->mRepeatFrameDelayUs, 6266 sizeof(mCodec->mRepeatFrameDelayUs)); 6267 6268 if (err != OK) { 6269 ALOGE("[%s] Unable to configure option to repeat previous " 6270 "frames (err %d)", 6271 mCodec->mComponentName.c_str(), 6272 err); 6273 return err; 6274 } 6275 } 6276 6277 if (mCodec->mMaxPtsGapUs > 0ll) { 6278 err = mCodec->mOMX->setInternalOption( 6279 mCodec->mNode, 6280 kPortIndexInput, 6281 IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP, 6282 &mCodec->mMaxPtsGapUs, 6283 sizeof(mCodec->mMaxPtsGapUs)); 6284 6285 if (err != OK) { 6286 ALOGE("[%s] Unable to configure max timestamp gap (err %d)", 6287 mCodec->mComponentName.c_str(), 6288 err); 6289 return err; 6290 } 6291 } 6292 6293 if (mCodec->mMaxFps > 0) { 6294 err = mCodec->mOMX->setInternalOption( 6295 mCodec->mNode, 6296 kPortIndexInput, 6297 IOMX::INTERNAL_OPTION_MAX_FPS, 6298 &mCodec->mMaxFps, 6299 sizeof(mCodec->mMaxFps)); 6300 6301 if (err != OK) { 6302 ALOGE("[%s] Unable to configure max fps (err %d)", 6303 mCodec->mComponentName.c_str(), 6304 err); 6305 return err; 6306 } 6307 } 6308 6309 if (mCodec->mTimePerCaptureUs > 0ll 6310 && mCodec->mTimePerFrameUs > 0ll) { 6311 int64_t timeLapse[2]; 6312 timeLapse[0] = mCodec->mTimePerFrameUs; 6313 timeLapse[1] = mCodec->mTimePerCaptureUs; 6314 err = mCodec->mOMX->setInternalOption( 6315 mCodec->mNode, 6316 kPortIndexInput, 6317 IOMX::INTERNAL_OPTION_TIME_LAPSE, 6318 &timeLapse[0], 6319 sizeof(timeLapse)); 6320 6321 if (err != OK) { 6322 ALOGE("[%s] Unable to configure time lapse (err %d)", 6323 mCodec->mComponentName.c_str(), 6324 err); 6325 return err; 6326 } 6327 } 6328 6329 if (mCodec->mCreateInputBuffersSuspended) { 6330 bool suspend = true; 6331 err = mCodec->mOMX->setInternalOption( 6332 mCodec->mNode, 6333 kPortIndexInput, 6334 IOMX::INTERNAL_OPTION_SUSPEND, 6335 &suspend, 6336 sizeof(suspend)); 6337 6338 if (err != OK) { 6339 ALOGE("[%s] Unable to configure option to suspend (err %d)", 6340 mCodec->mComponentName.c_str(), 6341 err); 6342 return err; 6343 } 6344 } 6345 6346 uint32_t usageBits; 6347 if (mCodec->mOMX->getParameter( 6348 mCodec->mNode, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits, 6349 &usageBits, sizeof(usageBits)) == OK) { 6350 mCodec->mInputFormat->setInt32( 6351 "using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN)); 6352 } 6353 6354 sp<ABuffer> colorAspectsBuffer; 6355 if (mCodec->mInputFormat->findBuffer("android._color-aspects", &colorAspectsBuffer)) { 6356 err = mCodec->mOMX->setInternalOption( 6357 mCodec->mNode, kPortIndexInput, IOMX::INTERNAL_OPTION_COLOR_ASPECTS, 6358 colorAspectsBuffer->base(), colorAspectsBuffer->capacity()); 6359 if (err != OK) { 6360 ALOGE("[%s] Unable to configure color aspects (err %d)", 6361 mCodec->mComponentName.c_str(), err); 6362 return err; 6363 } 6364 } 6365 return OK; 6366} 6367 6368void ACodec::LoadedState::onCreateInputSurface( 6369 const sp<AMessage> & /* msg */) { 6370 ALOGV("onCreateInputSurface"); 6371 6372 sp<AMessage> notify = mCodec->mNotify->dup(); 6373 notify->setInt32("what", CodecBase::kWhatInputSurfaceCreated); 6374 6375 android_dataspace dataSpace; 6376 status_t err = 6377 mCodec->setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace(&dataSpace); 6378 notify->setMessage("input-format", mCodec->mInputFormat); 6379 notify->setMessage("output-format", mCodec->mOutputFormat); 6380 6381 sp<IGraphicBufferProducer> bufferProducer; 6382 if (err == OK) { 6383 err = mCodec->mOMX->createInputSurface( 6384 mCodec->mNode, kPortIndexInput, dataSpace, &bufferProducer, &mCodec->mInputMetadataType); 6385 } 6386 6387 if (err == OK) { 6388 err = setupInputSurface(); 6389 } 6390 6391 if (err == OK) { 6392 notify->setObject("input-surface", 6393 new BufferProducerWrapper(bufferProducer)); 6394 } else { 6395 // Can't use mCodec->signalError() here -- MediaCodec won't forward 6396 // the error through because it's in the "configured" state. We 6397 // send a kWhatInputSurfaceCreated with an error value instead. 6398 ALOGE("[%s] onCreateInputSurface returning error %d", 6399 mCodec->mComponentName.c_str(), err); 6400 notify->setInt32("err", err); 6401 } 6402 notify->post(); 6403} 6404 6405void ACodec::LoadedState::onSetInputSurface( 6406 const sp<AMessage> &msg) { 6407 ALOGV("onSetInputSurface"); 6408 6409 sp<AMessage> notify = mCodec->mNotify->dup(); 6410 notify->setInt32("what", CodecBase::kWhatInputSurfaceAccepted); 6411 6412 sp<RefBase> obj; 6413 CHECK(msg->findObject("input-surface", &obj)); 6414 sp<PersistentSurface> surface = static_cast<PersistentSurface *>(obj.get()); 6415 6416 android_dataspace dataSpace; 6417 status_t err = 6418 mCodec->setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace(&dataSpace); 6419 notify->setMessage("input-format", mCodec->mInputFormat); 6420 notify->setMessage("output-format", mCodec->mOutputFormat); 6421 6422 if (err == OK) { 6423 err = mCodec->mOMX->setInputSurface( 6424 mCodec->mNode, kPortIndexInput, surface->getBufferConsumer(), 6425 &mCodec->mInputMetadataType); 6426 } 6427 6428 if (err == OK) { 6429 surface->getBufferConsumer()->setDefaultBufferDataSpace(dataSpace); 6430 err = setupInputSurface(); 6431 } 6432 6433 if (err != OK) { 6434 // Can't use mCodec->signalError() here -- MediaCodec won't forward 6435 // the error through because it's in the "configured" state. We 6436 // send a kWhatInputSurfaceAccepted with an error value instead. 6437 ALOGE("[%s] onSetInputSurface returning error %d", 6438 mCodec->mComponentName.c_str(), err); 6439 notify->setInt32("err", err); 6440 } 6441 notify->post(); 6442} 6443 6444void ACodec::LoadedState::onStart() { 6445 ALOGV("onStart"); 6446 6447 status_t err = mCodec->mOMX->sendCommand(mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle); 6448 if (err != OK) { 6449 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6450 } else { 6451 mCodec->changeState(mCodec->mLoadedToIdleState); 6452 } 6453} 6454 6455//////////////////////////////////////////////////////////////////////////////// 6456 6457ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec) 6458 : BaseState(codec) { 6459} 6460 6461void ACodec::LoadedToIdleState::stateEntered() { 6462 ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str()); 6463 6464 status_t err; 6465 if ((err = allocateBuffers()) != OK) { 6466 ALOGE("Failed to allocate buffers after transitioning to IDLE state " 6467 "(error 0x%08x)", 6468 err); 6469 6470 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6471 6472 mCodec->mOMX->sendCommand( 6473 mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded); 6474 if (mCodec->allYourBuffersAreBelongToUs(kPortIndexInput)) { 6475 mCodec->freeBuffersOnPort(kPortIndexInput); 6476 } 6477 if (mCodec->allYourBuffersAreBelongToUs(kPortIndexOutput)) { 6478 mCodec->freeBuffersOnPort(kPortIndexOutput); 6479 } 6480 6481 mCodec->changeState(mCodec->mLoadedState); 6482 } 6483} 6484 6485status_t ACodec::LoadedToIdleState::allocateBuffers() { 6486 status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput); 6487 6488 if (err != OK) { 6489 return err; 6490 } 6491 6492 return mCodec->allocateBuffersOnPort(kPortIndexOutput); 6493} 6494 6495bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) { 6496 switch (msg->what()) { 6497 case kWhatSetParameters: 6498 case kWhatShutdown: 6499 { 6500 mCodec->deferMessage(msg); 6501 return true; 6502 } 6503 6504 case kWhatSignalEndOfInputStream: 6505 { 6506 mCodec->onSignalEndOfInputStream(); 6507 return true; 6508 } 6509 6510 case kWhatResume: 6511 { 6512 // We'll be active soon enough. 6513 return true; 6514 } 6515 6516 case kWhatFlush: 6517 { 6518 // We haven't even started yet, so we're flushed alright... 6519 sp<AMessage> notify = mCodec->mNotify->dup(); 6520 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 6521 notify->post(); 6522 return true; 6523 } 6524 6525 default: 6526 return BaseState::onMessageReceived(msg); 6527 } 6528} 6529 6530bool ACodec::LoadedToIdleState::onOMXEvent( 6531 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 6532 switch (event) { 6533 case OMX_EventCmdComplete: 6534 { 6535 status_t err = OK; 6536 if (data1 != (OMX_U32)OMX_CommandStateSet 6537 || data2 != (OMX_U32)OMX_StateIdle) { 6538 ALOGE("Unexpected command completion in LoadedToIdleState: %s(%u) %s(%u)", 6539 asString((OMX_COMMANDTYPE)data1), data1, 6540 asString((OMX_STATETYPE)data2), data2); 6541 err = FAILED_TRANSACTION; 6542 } 6543 6544 if (err == OK) { 6545 err = mCodec->mOMX->sendCommand( 6546 mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting); 6547 } 6548 6549 if (err != OK) { 6550 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6551 } else { 6552 mCodec->changeState(mCodec->mIdleToExecutingState); 6553 } 6554 6555 return true; 6556 } 6557 6558 default: 6559 return BaseState::onOMXEvent(event, data1, data2); 6560 } 6561} 6562 6563//////////////////////////////////////////////////////////////////////////////// 6564 6565ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec) 6566 : BaseState(codec) { 6567} 6568 6569void ACodec::IdleToExecutingState::stateEntered() { 6570 ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str()); 6571} 6572 6573bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) { 6574 switch (msg->what()) { 6575 case kWhatSetParameters: 6576 case kWhatShutdown: 6577 { 6578 mCodec->deferMessage(msg); 6579 return true; 6580 } 6581 6582 case kWhatResume: 6583 { 6584 // We'll be active soon enough. 6585 return true; 6586 } 6587 6588 case kWhatFlush: 6589 { 6590 // We haven't even started yet, so we're flushed alright... 6591 sp<AMessage> notify = mCodec->mNotify->dup(); 6592 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 6593 notify->post(); 6594 6595 return true; 6596 } 6597 6598 case kWhatSignalEndOfInputStream: 6599 { 6600 mCodec->onSignalEndOfInputStream(); 6601 return true; 6602 } 6603 6604 default: 6605 return BaseState::onMessageReceived(msg); 6606 } 6607} 6608 6609bool ACodec::IdleToExecutingState::onOMXEvent( 6610 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 6611 switch (event) { 6612 case OMX_EventCmdComplete: 6613 { 6614 if (data1 != (OMX_U32)OMX_CommandStateSet 6615 || data2 != (OMX_U32)OMX_StateExecuting) { 6616 ALOGE("Unexpected command completion in IdleToExecutingState: %s(%u) %s(%u)", 6617 asString((OMX_COMMANDTYPE)data1), data1, 6618 asString((OMX_STATETYPE)data2), data2); 6619 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6620 return true; 6621 } 6622 6623 mCodec->mExecutingState->resume(); 6624 mCodec->changeState(mCodec->mExecutingState); 6625 6626 return true; 6627 } 6628 6629 default: 6630 return BaseState::onOMXEvent(event, data1, data2); 6631 } 6632} 6633 6634//////////////////////////////////////////////////////////////////////////////// 6635 6636ACodec::ExecutingState::ExecutingState(ACodec *codec) 6637 : BaseState(codec), 6638 mActive(false) { 6639} 6640 6641ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode( 6642 OMX_U32 /* portIndex */) { 6643 return RESUBMIT_BUFFERS; 6644} 6645 6646void ACodec::ExecutingState::submitOutputMetaBuffers() { 6647 // submit as many buffers as there are input buffers with the codec 6648 // in case we are in port reconfiguring 6649 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 6650 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 6651 6652 if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) { 6653 if (mCodec->submitOutputMetadataBuffer() != OK) 6654 break; 6655 } 6656 } 6657 6658 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** 6659 mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround(); 6660} 6661 6662void ACodec::ExecutingState::submitRegularOutputBuffers() { 6663 bool failed = false; 6664 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) { 6665 BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i); 6666 6667 if (mCodec->mNativeWindow != NULL) { 6668 if (info->mStatus != BufferInfo::OWNED_BY_US 6669 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) { 6670 ALOGE("buffers should be owned by us or the surface"); 6671 failed = true; 6672 break; 6673 } 6674 6675 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 6676 continue; 6677 } 6678 } else { 6679 if (info->mStatus != BufferInfo::OWNED_BY_US) { 6680 ALOGE("buffers should be owned by us"); 6681 failed = true; 6682 break; 6683 } 6684 } 6685 6686 ALOGV("[%s] calling fillBuffer %u", mCodec->mComponentName.c_str(), info->mBufferID); 6687 6688 info->checkWriteFence("submitRegularOutputBuffers"); 6689 status_t err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID, info->mFenceFd); 6690 info->mFenceFd = -1; 6691 if (err != OK) { 6692 failed = true; 6693 break; 6694 } 6695 6696 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 6697 } 6698 6699 if (failed) { 6700 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6701 } 6702} 6703 6704void ACodec::ExecutingState::submitOutputBuffers() { 6705 submitRegularOutputBuffers(); 6706 if (mCodec->storingMetadataInDecodedBuffers()) { 6707 submitOutputMetaBuffers(); 6708 } 6709} 6710 6711void ACodec::ExecutingState::resume() { 6712 if (mActive) { 6713 ALOGV("[%s] We're already active, no need to resume.", mCodec->mComponentName.c_str()); 6714 return; 6715 } 6716 6717 submitOutputBuffers(); 6718 6719 // Post all available input buffers 6720 if (mCodec->mBuffers[kPortIndexInput].size() == 0u) { 6721 ALOGW("[%s] we don't have any input buffers to resume", mCodec->mComponentName.c_str()); 6722 } 6723 6724 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) { 6725 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 6726 if (info->mStatus == BufferInfo::OWNED_BY_US) { 6727 postFillThisBuffer(info); 6728 } 6729 } 6730 6731 mActive = true; 6732} 6733 6734void ACodec::ExecutingState::stateEntered() { 6735 ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str()); 6736 6737 mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC)); 6738 mCodec->processDeferredMessages(); 6739} 6740 6741bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) { 6742 bool handled = false; 6743 6744 switch (msg->what()) { 6745 case kWhatShutdown: 6746 { 6747 int32_t keepComponentAllocated; 6748 CHECK(msg->findInt32( 6749 "keepComponentAllocated", &keepComponentAllocated)); 6750 6751 mCodec->mShutdownInProgress = true; 6752 mCodec->mExplicitShutdown = true; 6753 mCodec->mKeepComponentAllocated = keepComponentAllocated; 6754 6755 mActive = false; 6756 6757 status_t err = mCodec->mOMX->sendCommand( 6758 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle); 6759 if (err != OK) { 6760 if (keepComponentAllocated) { 6761 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6762 } 6763 // TODO: do some recovery here. 6764 } else { 6765 mCodec->changeState(mCodec->mExecutingToIdleState); 6766 } 6767 6768 handled = true; 6769 break; 6770 } 6771 6772 case kWhatFlush: 6773 { 6774 ALOGV("[%s] ExecutingState flushing now " 6775 "(codec owns %zu/%zu input, %zu/%zu output).", 6776 mCodec->mComponentName.c_str(), 6777 mCodec->countBuffersOwnedByComponent(kPortIndexInput), 6778 mCodec->mBuffers[kPortIndexInput].size(), 6779 mCodec->countBuffersOwnedByComponent(kPortIndexOutput), 6780 mCodec->mBuffers[kPortIndexOutput].size()); 6781 6782 mActive = false; 6783 6784 status_t err = mCodec->mOMX->sendCommand(mCodec->mNode, OMX_CommandFlush, OMX_ALL); 6785 if (err != OK) { 6786 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6787 } else { 6788 mCodec->changeState(mCodec->mFlushingState); 6789 } 6790 6791 handled = true; 6792 break; 6793 } 6794 6795 case kWhatResume: 6796 { 6797 resume(); 6798 6799 handled = true; 6800 break; 6801 } 6802 6803 case kWhatRequestIDRFrame: 6804 { 6805 status_t err = mCodec->requestIDRFrame(); 6806 if (err != OK) { 6807 ALOGW("Requesting an IDR frame failed."); 6808 } 6809 6810 handled = true; 6811 break; 6812 } 6813 6814 case kWhatSetParameters: 6815 { 6816 sp<AMessage> params; 6817 CHECK(msg->findMessage("params", ¶ms)); 6818 6819 status_t err = mCodec->setParameters(params); 6820 6821 sp<AMessage> reply; 6822 if (msg->findMessage("reply", &reply)) { 6823 reply->setInt32("err", err); 6824 reply->post(); 6825 } 6826 6827 handled = true; 6828 break; 6829 } 6830 6831 case ACodec::kWhatSignalEndOfInputStream: 6832 { 6833 mCodec->onSignalEndOfInputStream(); 6834 handled = true; 6835 break; 6836 } 6837 6838 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** 6839 case kWhatSubmitOutputMetadataBufferIfEOS: 6840 { 6841 if (mCodec->mPortEOS[kPortIndexInput] && 6842 !mCodec->mPortEOS[kPortIndexOutput]) { 6843 status_t err = mCodec->submitOutputMetadataBuffer(); 6844 if (err == OK) { 6845 mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround(); 6846 } 6847 } 6848 return true; 6849 } 6850 6851 default: 6852 handled = BaseState::onMessageReceived(msg); 6853 break; 6854 } 6855 6856 return handled; 6857} 6858 6859status_t ACodec::setParameters(const sp<AMessage> ¶ms) { 6860 int32_t videoBitrate; 6861 if (params->findInt32("video-bitrate", &videoBitrate)) { 6862 OMX_VIDEO_CONFIG_BITRATETYPE configParams; 6863 InitOMXParams(&configParams); 6864 configParams.nPortIndex = kPortIndexOutput; 6865 configParams.nEncodeBitrate = videoBitrate; 6866 6867 status_t err = mOMX->setConfig( 6868 mNode, 6869 OMX_IndexConfigVideoBitrate, 6870 &configParams, 6871 sizeof(configParams)); 6872 6873 if (err != OK) { 6874 ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d", 6875 videoBitrate, err); 6876 6877 return err; 6878 } 6879 } 6880 6881 int64_t skipFramesBeforeUs; 6882 if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) { 6883 status_t err = 6884 mOMX->setInternalOption( 6885 mNode, 6886 kPortIndexInput, 6887 IOMX::INTERNAL_OPTION_START_TIME, 6888 &skipFramesBeforeUs, 6889 sizeof(skipFramesBeforeUs)); 6890 6891 if (err != OK) { 6892 ALOGE("Failed to set parameter 'skip-frames-before' (err %d)", err); 6893 return err; 6894 } 6895 } 6896 6897 int32_t dropInputFrames; 6898 if (params->findInt32("drop-input-frames", &dropInputFrames)) { 6899 bool suspend = dropInputFrames != 0; 6900 6901 status_t err = 6902 mOMX->setInternalOption( 6903 mNode, 6904 kPortIndexInput, 6905 IOMX::INTERNAL_OPTION_SUSPEND, 6906 &suspend, 6907 sizeof(suspend)); 6908 6909 if (err != OK) { 6910 ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err); 6911 return err; 6912 } 6913 } 6914 6915 int32_t dummy; 6916 if (params->findInt32("request-sync", &dummy)) { 6917 status_t err = requestIDRFrame(); 6918 6919 if (err != OK) { 6920 ALOGE("Requesting a sync frame failed w/ err %d", err); 6921 return err; 6922 } 6923 } 6924 6925 float rate; 6926 if (params->findFloat("operating-rate", &rate) && rate > 0) { 6927 status_t err = setOperatingRate(rate, mIsVideo); 6928 if (err != OK) { 6929 ALOGE("Failed to set parameter 'operating-rate' (err %d)", err); 6930 return err; 6931 } 6932 } 6933 6934 int32_t intraRefreshPeriod = 0; 6935 if (params->findInt32("intra-refresh-period", &intraRefreshPeriod) 6936 && intraRefreshPeriod > 0) { 6937 status_t err = setIntraRefreshPeriod(intraRefreshPeriod, false); 6938 if (err != OK) { 6939 ALOGI("[%s] failed setIntraRefreshPeriod. Failure is fine since this key is optional", 6940 mComponentName.c_str()); 6941 err = OK; 6942 } 6943 } 6944 6945 return OK; 6946} 6947 6948void ACodec::onSignalEndOfInputStream() { 6949 sp<AMessage> notify = mNotify->dup(); 6950 notify->setInt32("what", CodecBase::kWhatSignaledInputEOS); 6951 6952 status_t err = mOMX->signalEndOfInputStream(mNode); 6953 if (err != OK) { 6954 notify->setInt32("err", err); 6955 } 6956 notify->post(); 6957} 6958 6959bool ACodec::ExecutingState::onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) { 6960 mCodec->onFrameRendered(mediaTimeUs, systemNano); 6961 return true; 6962} 6963 6964bool ACodec::ExecutingState::onOMXEvent( 6965 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 6966 switch (event) { 6967 case OMX_EventPortSettingsChanged: 6968 { 6969 CHECK_EQ(data1, (OMX_U32)kPortIndexOutput); 6970 6971 mCodec->onOutputFormatChanged(); 6972 6973 if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) { 6974 mCodec->mMetadataBuffersToSubmit = 0; 6975 CHECK_EQ(mCodec->mOMX->sendCommand( 6976 mCodec->mNode, 6977 OMX_CommandPortDisable, kPortIndexOutput), 6978 (status_t)OK); 6979 6980 mCodec->freeOutputBuffersNotOwnedByComponent(); 6981 6982 mCodec->changeState(mCodec->mOutputPortSettingsChangedState); 6983 } else if (data2 != OMX_IndexConfigCommonOutputCrop 6984 && data2 != OMX_IndexConfigAndroidIntraRefresh) { 6985 ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08x", 6986 mCodec->mComponentName.c_str(), data2); 6987 } 6988 6989 return true; 6990 } 6991 6992 case OMX_EventBufferFlag: 6993 { 6994 return true; 6995 } 6996 6997 default: 6998 return BaseState::onOMXEvent(event, data1, data2); 6999 } 7000} 7001 7002//////////////////////////////////////////////////////////////////////////////// 7003 7004ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState( 7005 ACodec *codec) 7006 : BaseState(codec) { 7007} 7008 7009ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode( 7010 OMX_U32 portIndex) { 7011 if (portIndex == kPortIndexOutput) { 7012 return FREE_BUFFERS; 7013 } 7014 7015 CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput); 7016 7017 return RESUBMIT_BUFFERS; 7018} 7019 7020bool ACodec::OutputPortSettingsChangedState::onMessageReceived( 7021 const sp<AMessage> &msg) { 7022 bool handled = false; 7023 7024 switch (msg->what()) { 7025 case kWhatFlush: 7026 case kWhatShutdown: 7027 case kWhatResume: 7028 case kWhatSetParameters: 7029 { 7030 if (msg->what() == kWhatResume) { 7031 ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str()); 7032 } 7033 7034 mCodec->deferMessage(msg); 7035 handled = true; 7036 break; 7037 } 7038 7039 default: 7040 handled = BaseState::onMessageReceived(msg); 7041 break; 7042 } 7043 7044 return handled; 7045} 7046 7047void ACodec::OutputPortSettingsChangedState::stateEntered() { 7048 ALOGV("[%s] Now handling output port settings change", 7049 mCodec->mComponentName.c_str()); 7050} 7051 7052bool ACodec::OutputPortSettingsChangedState::onOMXFrameRendered( 7053 int64_t mediaTimeUs, nsecs_t systemNano) { 7054 mCodec->onFrameRendered(mediaTimeUs, systemNano); 7055 return true; 7056} 7057 7058bool ACodec::OutputPortSettingsChangedState::onOMXEvent( 7059 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 7060 switch (event) { 7061 case OMX_EventCmdComplete: 7062 { 7063 if (data1 == (OMX_U32)OMX_CommandPortDisable) { 7064 if (data2 != (OMX_U32)kPortIndexOutput) { 7065 ALOGW("ignoring EventCmdComplete CommandPortDisable for port %u", data2); 7066 return false; 7067 } 7068 7069 ALOGV("[%s] Output port now disabled.", mCodec->mComponentName.c_str()); 7070 7071 status_t err = OK; 7072 if (!mCodec->mBuffers[kPortIndexOutput].isEmpty()) { 7073 ALOGE("disabled port should be empty, but has %zu buffers", 7074 mCodec->mBuffers[kPortIndexOutput].size()); 7075 err = FAILED_TRANSACTION; 7076 } else { 7077 mCodec->mDealer[kPortIndexOutput].clear(); 7078 } 7079 7080 if (err == OK) { 7081 err = mCodec->mOMX->sendCommand( 7082 mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput); 7083 } 7084 7085 if (err == OK) { 7086 err = mCodec->allocateBuffersOnPort(kPortIndexOutput); 7087 ALOGE_IF(err != OK, "Failed to allocate output port buffers after port " 7088 "reconfiguration: (%d)", err); 7089 } 7090 7091 if (err != OK) { 7092 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 7093 7094 // This is technically not correct, but appears to be 7095 // the only way to free the component instance. 7096 // Controlled transitioning from excecuting->idle 7097 // and idle->loaded seem impossible probably because 7098 // the output port never finishes re-enabling. 7099 mCodec->mShutdownInProgress = true; 7100 mCodec->mKeepComponentAllocated = false; 7101 mCodec->changeState(mCodec->mLoadedState); 7102 } 7103 7104 return true; 7105 } else if (data1 == (OMX_U32)OMX_CommandPortEnable) { 7106 if (data2 != (OMX_U32)kPortIndexOutput) { 7107 ALOGW("ignoring EventCmdComplete OMX_CommandPortEnable for port %u", data2); 7108 return false; 7109 } 7110 7111 ALOGV("[%s] Output port now reenabled.", mCodec->mComponentName.c_str()); 7112 7113 if (mCodec->mExecutingState->active()) { 7114 mCodec->mExecutingState->submitOutputBuffers(); 7115 } 7116 7117 mCodec->changeState(mCodec->mExecutingState); 7118 7119 return true; 7120 } 7121 7122 return false; 7123 } 7124 7125 default: 7126 return false; 7127 } 7128} 7129 7130//////////////////////////////////////////////////////////////////////////////// 7131 7132ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec) 7133 : BaseState(codec), 7134 mComponentNowIdle(false) { 7135} 7136 7137bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) { 7138 bool handled = false; 7139 7140 switch (msg->what()) { 7141 case kWhatFlush: 7142 { 7143 // Don't send me a flush request if you previously wanted me 7144 // to shutdown. 7145 ALOGW("Ignoring flush request in ExecutingToIdleState"); 7146 break; 7147 } 7148 7149 case kWhatShutdown: 7150 { 7151 // We're already doing that... 7152 7153 handled = true; 7154 break; 7155 } 7156 7157 default: 7158 handled = BaseState::onMessageReceived(msg); 7159 break; 7160 } 7161 7162 return handled; 7163} 7164 7165void ACodec::ExecutingToIdleState::stateEntered() { 7166 ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str()); 7167 7168 mComponentNowIdle = false; 7169 mCodec->mLastOutputFormat.clear(); 7170} 7171 7172bool ACodec::ExecutingToIdleState::onOMXEvent( 7173 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 7174 switch (event) { 7175 case OMX_EventCmdComplete: 7176 { 7177 if (data1 != (OMX_U32)OMX_CommandStateSet 7178 || data2 != (OMX_U32)OMX_StateIdle) { 7179 ALOGE("Unexpected command completion in ExecutingToIdleState: %s(%u) %s(%u)", 7180 asString((OMX_COMMANDTYPE)data1), data1, 7181 asString((OMX_STATETYPE)data2), data2); 7182 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 7183 return true; 7184 } 7185 7186 mComponentNowIdle = true; 7187 7188 changeStateIfWeOwnAllBuffers(); 7189 7190 return true; 7191 } 7192 7193 case OMX_EventPortSettingsChanged: 7194 case OMX_EventBufferFlag: 7195 { 7196 // We're shutting down and don't care about this anymore. 7197 return true; 7198 } 7199 7200 default: 7201 return BaseState::onOMXEvent(event, data1, data2); 7202 } 7203} 7204 7205void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() { 7206 if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) { 7207 status_t err = mCodec->mOMX->sendCommand( 7208 mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded); 7209 if (err == OK) { 7210 err = mCodec->freeBuffersOnPort(kPortIndexInput); 7211 status_t err2 = mCodec->freeBuffersOnPort(kPortIndexOutput); 7212 if (err == OK) { 7213 err = err2; 7214 } 7215 } 7216 7217 if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown) 7218 && mCodec->mNativeWindow != NULL) { 7219 // We push enough 1x1 blank buffers to ensure that one of 7220 // them has made it to the display. This allows the OMX 7221 // component teardown to zero out any protected buffers 7222 // without the risk of scanning out one of those buffers. 7223 pushBlankBuffersToNativeWindow(mCodec->mNativeWindow.get()); 7224 } 7225 7226 if (err != OK) { 7227 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 7228 return; 7229 } 7230 7231 mCodec->changeState(mCodec->mIdleToLoadedState); 7232 } 7233} 7234 7235void ACodec::ExecutingToIdleState::onInputBufferFilled( 7236 const sp<AMessage> &msg) { 7237 BaseState::onInputBufferFilled(msg); 7238 7239 changeStateIfWeOwnAllBuffers(); 7240} 7241 7242void ACodec::ExecutingToIdleState::onOutputBufferDrained( 7243 const sp<AMessage> &msg) { 7244 BaseState::onOutputBufferDrained(msg); 7245 7246 changeStateIfWeOwnAllBuffers(); 7247} 7248 7249//////////////////////////////////////////////////////////////////////////////// 7250 7251ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec) 7252 : BaseState(codec) { 7253} 7254 7255bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) { 7256 bool handled = false; 7257 7258 switch (msg->what()) { 7259 case kWhatShutdown: 7260 { 7261 // We're already doing that... 7262 7263 handled = true; 7264 break; 7265 } 7266 7267 case kWhatFlush: 7268 { 7269 // Don't send me a flush request if you previously wanted me 7270 // to shutdown. 7271 ALOGE("Got flush request in IdleToLoadedState"); 7272 break; 7273 } 7274 7275 default: 7276 handled = BaseState::onMessageReceived(msg); 7277 break; 7278 } 7279 7280 return handled; 7281} 7282 7283void ACodec::IdleToLoadedState::stateEntered() { 7284 ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str()); 7285} 7286 7287bool ACodec::IdleToLoadedState::onOMXEvent( 7288 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 7289 switch (event) { 7290 case OMX_EventCmdComplete: 7291 { 7292 if (data1 != (OMX_U32)OMX_CommandStateSet 7293 || data2 != (OMX_U32)OMX_StateLoaded) { 7294 ALOGE("Unexpected command completion in IdleToLoadedState: %s(%u) %s(%u)", 7295 asString((OMX_COMMANDTYPE)data1), data1, 7296 asString((OMX_STATETYPE)data2), data2); 7297 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 7298 return true; 7299 } 7300 7301 mCodec->changeState(mCodec->mLoadedState); 7302 7303 return true; 7304 } 7305 7306 default: 7307 return BaseState::onOMXEvent(event, data1, data2); 7308 } 7309} 7310 7311//////////////////////////////////////////////////////////////////////////////// 7312 7313ACodec::FlushingState::FlushingState(ACodec *codec) 7314 : BaseState(codec) { 7315} 7316 7317void ACodec::FlushingState::stateEntered() { 7318 ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str()); 7319 7320 mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false; 7321} 7322 7323bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) { 7324 bool handled = false; 7325 7326 switch (msg->what()) { 7327 case kWhatShutdown: 7328 { 7329 mCodec->deferMessage(msg); 7330 break; 7331 } 7332 7333 case kWhatFlush: 7334 { 7335 // We're already doing this right now. 7336 handled = true; 7337 break; 7338 } 7339 7340 default: 7341 handled = BaseState::onMessageReceived(msg); 7342 break; 7343 } 7344 7345 return handled; 7346} 7347 7348bool ACodec::FlushingState::onOMXEvent( 7349 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 7350 ALOGV("[%s] FlushingState onOMXEvent(%u,%d)", 7351 mCodec->mComponentName.c_str(), event, (OMX_S32)data1); 7352 7353 switch (event) { 7354 case OMX_EventCmdComplete: 7355 { 7356 if (data1 != (OMX_U32)OMX_CommandFlush) { 7357 ALOGE("unexpected EventCmdComplete %s(%d) data2:%d in FlushingState", 7358 asString((OMX_COMMANDTYPE)data1), data1, data2); 7359 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 7360 return true; 7361 } 7362 7363 if (data2 == kPortIndexInput || data2 == kPortIndexOutput) { 7364 if (mFlushComplete[data2]) { 7365 ALOGW("Flush already completed for %s port", 7366 data2 == kPortIndexInput ? "input" : "output"); 7367 return true; 7368 } 7369 mFlushComplete[data2] = true; 7370 7371 if (mFlushComplete[kPortIndexInput] && mFlushComplete[kPortIndexOutput]) { 7372 changeStateIfWeOwnAllBuffers(); 7373 } 7374 } else if (data2 == OMX_ALL) { 7375 if (!mFlushComplete[kPortIndexInput] || !mFlushComplete[kPortIndexOutput]) { 7376 ALOGW("received flush complete event for OMX_ALL before ports have been" 7377 "flushed (%d/%d)", 7378 mFlushComplete[kPortIndexInput], mFlushComplete[kPortIndexOutput]); 7379 return false; 7380 } 7381 7382 changeStateIfWeOwnAllBuffers(); 7383 } else { 7384 ALOGW("data2 not OMX_ALL but %u in EventCmdComplete CommandFlush", data2); 7385 } 7386 7387 return true; 7388 } 7389 7390 case OMX_EventPortSettingsChanged: 7391 { 7392 sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec); 7393 msg->setInt32("type", omx_message::EVENT); 7394 msg->setInt32("node", mCodec->mNode); 7395 msg->setInt32("event", event); 7396 msg->setInt32("data1", data1); 7397 msg->setInt32("data2", data2); 7398 7399 ALOGV("[%s] Deferring OMX_EventPortSettingsChanged", 7400 mCodec->mComponentName.c_str()); 7401 7402 mCodec->deferMessage(msg); 7403 7404 return true; 7405 } 7406 7407 default: 7408 return BaseState::onOMXEvent(event, data1, data2); 7409 } 7410 7411 return true; 7412} 7413 7414void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) { 7415 BaseState::onOutputBufferDrained(msg); 7416 7417 changeStateIfWeOwnAllBuffers(); 7418} 7419 7420void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) { 7421 BaseState::onInputBufferFilled(msg); 7422 7423 changeStateIfWeOwnAllBuffers(); 7424} 7425 7426void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() { 7427 if (mFlushComplete[kPortIndexInput] 7428 && mFlushComplete[kPortIndexOutput] 7429 && mCodec->allYourBuffersAreBelongToUs()) { 7430 // We now own all buffers except possibly those still queued with 7431 // the native window for rendering. Let's get those back as well. 7432 mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs(); 7433 7434 mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC)); 7435 7436 sp<AMessage> notify = mCodec->mNotify->dup(); 7437 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 7438 notify->post(); 7439 7440 mCodec->mPortEOS[kPortIndexInput] = 7441 mCodec->mPortEOS[kPortIndexOutput] = false; 7442 7443 mCodec->mInputEOSResult = OK; 7444 7445 if (mCodec->mSkipCutBuffer != NULL) { 7446 mCodec->mSkipCutBuffer->clear(); 7447 } 7448 7449 mCodec->changeState(mCodec->mExecutingState); 7450 } 7451} 7452 7453status_t ACodec::queryCapabilities( 7454 const AString &name, const AString &mime, bool isEncoder, 7455 sp<MediaCodecInfo::Capabilities> *caps) { 7456 (*caps).clear(); 7457 const char *role = getComponentRole(isEncoder, mime.c_str()); 7458 if (role == NULL) { 7459 return BAD_VALUE; 7460 } 7461 7462 OMXClient client; 7463 status_t err = client.connect(); 7464 if (err != OK) { 7465 return err; 7466 } 7467 7468 sp<IOMX> omx = client.interface(); 7469 sp<CodecObserver> observer = new CodecObserver; 7470 IOMX::node_id node = 0; 7471 7472 err = omx->allocateNode(name.c_str(), observer, NULL, &node); 7473 if (err != OK) { 7474 client.disconnect(); 7475 return err; 7476 } 7477 7478 err = setComponentRole(omx, node, role); 7479 if (err != OK) { 7480 omx->freeNode(node); 7481 client.disconnect(); 7482 return err; 7483 } 7484 7485 sp<MediaCodecInfo::CapabilitiesBuilder> builder = new MediaCodecInfo::CapabilitiesBuilder(); 7486 bool isVideo = mime.startsWithIgnoreCase("video/"); 7487 7488 if (isVideo) { 7489 OMX_VIDEO_PARAM_PROFILELEVELTYPE param; 7490 InitOMXParams(¶m); 7491 param.nPortIndex = isEncoder ? kPortIndexOutput : kPortIndexInput; 7492 7493 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { 7494 param.nProfileIndex = index; 7495 status_t err = omx->getParameter( 7496 node, OMX_IndexParamVideoProfileLevelQuerySupported, 7497 ¶m, sizeof(param)); 7498 if (err != OK) { 7499 break; 7500 } 7501 builder->addProfileLevel(param.eProfile, param.eLevel); 7502 7503 if (index == kMaxIndicesToCheck) { 7504 ALOGW("[%s] stopping checking profiles after %u: %x/%x", 7505 name.c_str(), index, 7506 param.eProfile, param.eLevel); 7507 } 7508 } 7509 7510 // Color format query 7511 // return colors in the order reported by the OMX component 7512 // prefix "flexible" standard ones with the flexible equivalent 7513 OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat; 7514 InitOMXParams(&portFormat); 7515 portFormat.nPortIndex = isEncoder ? kPortIndexInput : kPortIndexOutput; 7516 Vector<uint32_t> supportedColors; // shadow copy to check for duplicates 7517 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { 7518 portFormat.nIndex = index; 7519 status_t err = omx->getParameter( 7520 node, OMX_IndexParamVideoPortFormat, 7521 &portFormat, sizeof(portFormat)); 7522 if (err != OK) { 7523 break; 7524 } 7525 7526 OMX_U32 flexibleEquivalent; 7527 if (isFlexibleColorFormat( 7528 omx, node, portFormat.eColorFormat, false /* usingNativeWindow */, 7529 &flexibleEquivalent)) { 7530 bool marked = false; 7531 for (size_t i = 0; i < supportedColors.size(); ++i) { 7532 if (supportedColors[i] == flexibleEquivalent) { 7533 marked = true; 7534 break; 7535 } 7536 } 7537 if (!marked) { 7538 supportedColors.push(flexibleEquivalent); 7539 builder->addColorFormat(flexibleEquivalent); 7540 } 7541 } 7542 supportedColors.push(portFormat.eColorFormat); 7543 builder->addColorFormat(portFormat.eColorFormat); 7544 7545 if (index == kMaxIndicesToCheck) { 7546 ALOGW("[%s] stopping checking formats after %u: %s(%x)", 7547 name.c_str(), index, 7548 asString(portFormat.eColorFormat), portFormat.eColorFormat); 7549 } 7550 } 7551 } else if (mime.equalsIgnoreCase(MEDIA_MIMETYPE_AUDIO_AAC)) { 7552 // More audio codecs if they have profiles. 7553 OMX_AUDIO_PARAM_ANDROID_PROFILETYPE param; 7554 InitOMXParams(¶m); 7555 param.nPortIndex = isEncoder ? kPortIndexOutput : kPortIndexInput; 7556 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { 7557 param.nProfileIndex = index; 7558 status_t err = omx->getParameter( 7559 node, (OMX_INDEXTYPE)OMX_IndexParamAudioProfileQuerySupported, 7560 ¶m, sizeof(param)); 7561 if (err != OK) { 7562 break; 7563 } 7564 // For audio, level is ignored. 7565 builder->addProfileLevel(param.eProfile, 0 /* level */); 7566 7567 if (index == kMaxIndicesToCheck) { 7568 ALOGW("[%s] stopping checking profiles after %u: %x", 7569 name.c_str(), index, 7570 param.eProfile); 7571 } 7572 } 7573 7574 // NOTE: Without Android extensions, OMX does not provide a way to query 7575 // AAC profile support 7576 if (param.nProfileIndex == 0) { 7577 ALOGW("component %s doesn't support profile query.", name.c_str()); 7578 } 7579 } 7580 7581 if (isVideo && !isEncoder) { 7582 native_handle_t *sidebandHandle = NULL; 7583 if (omx->configureVideoTunnelMode( 7584 node, kPortIndexOutput, OMX_TRUE, 0, &sidebandHandle) == OK) { 7585 // tunneled playback includes adaptive playback 7586 builder->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback 7587 | MediaCodecInfo::Capabilities::kFlagSupportsTunneledPlayback); 7588 } else if (omx->storeMetaDataInBuffers( 7589 node, kPortIndexOutput, OMX_TRUE) == OK || 7590 omx->prepareForAdaptivePlayback( 7591 node, kPortIndexOutput, OMX_TRUE, 7592 1280 /* width */, 720 /* height */) == OK) { 7593 builder->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback); 7594 } 7595 } 7596 7597 if (isVideo && isEncoder) { 7598 OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params; 7599 InitOMXParams(¶ms); 7600 params.nPortIndex = kPortIndexOutput; 7601 // TODO: should we verify if fallback is supported? 7602 if (omx->getConfig( 7603 node, (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, 7604 ¶ms, sizeof(params)) == OK) { 7605 builder->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsIntraRefresh); 7606 } 7607 } 7608 7609 *caps = builder; 7610 omx->freeNode(node); 7611 client.disconnect(); 7612 return OK; 7613} 7614 7615// These are supposed be equivalent to the logic in 7616// "audio_channel_out_mask_from_count". 7617//static 7618status_t ACodec::getOMXChannelMapping(size_t numChannels, OMX_AUDIO_CHANNELTYPE map[]) { 7619 switch (numChannels) { 7620 case 1: 7621 map[0] = OMX_AUDIO_ChannelCF; 7622 break; 7623 case 2: 7624 map[0] = OMX_AUDIO_ChannelLF; 7625 map[1] = OMX_AUDIO_ChannelRF; 7626 break; 7627 case 3: 7628 map[0] = OMX_AUDIO_ChannelLF; 7629 map[1] = OMX_AUDIO_ChannelRF; 7630 map[2] = OMX_AUDIO_ChannelCF; 7631 break; 7632 case 4: 7633 map[0] = OMX_AUDIO_ChannelLF; 7634 map[1] = OMX_AUDIO_ChannelRF; 7635 map[2] = OMX_AUDIO_ChannelLR; 7636 map[3] = OMX_AUDIO_ChannelRR; 7637 break; 7638 case 5: 7639 map[0] = OMX_AUDIO_ChannelLF; 7640 map[1] = OMX_AUDIO_ChannelRF; 7641 map[2] = OMX_AUDIO_ChannelCF; 7642 map[3] = OMX_AUDIO_ChannelLR; 7643 map[4] = OMX_AUDIO_ChannelRR; 7644 break; 7645 case 6: 7646 map[0] = OMX_AUDIO_ChannelLF; 7647 map[1] = OMX_AUDIO_ChannelRF; 7648 map[2] = OMX_AUDIO_ChannelCF; 7649 map[3] = OMX_AUDIO_ChannelLFE; 7650 map[4] = OMX_AUDIO_ChannelLR; 7651 map[5] = OMX_AUDIO_ChannelRR; 7652 break; 7653 case 7: 7654 map[0] = OMX_AUDIO_ChannelLF; 7655 map[1] = OMX_AUDIO_ChannelRF; 7656 map[2] = OMX_AUDIO_ChannelCF; 7657 map[3] = OMX_AUDIO_ChannelLFE; 7658 map[4] = OMX_AUDIO_ChannelLR; 7659 map[5] = OMX_AUDIO_ChannelRR; 7660 map[6] = OMX_AUDIO_ChannelCS; 7661 break; 7662 case 8: 7663 map[0] = OMX_AUDIO_ChannelLF; 7664 map[1] = OMX_AUDIO_ChannelRF; 7665 map[2] = OMX_AUDIO_ChannelCF; 7666 map[3] = OMX_AUDIO_ChannelLFE; 7667 map[4] = OMX_AUDIO_ChannelLR; 7668 map[5] = OMX_AUDIO_ChannelRR; 7669 map[6] = OMX_AUDIO_ChannelLS; 7670 map[7] = OMX_AUDIO_ChannelRS; 7671 break; 7672 default: 7673 return -EINVAL; 7674 } 7675 7676 return OK; 7677} 7678 7679} // namespace android 7680