ACodec.cpp revision c63f91525c793e8bb06ce805d6161965e85571d2
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 presentation.nMaxOutputChannels = maxOutputChannelCount; 2559 presentation.nDrcCut = drc.drcCut; 2560 presentation.nDrcBoost = drc.drcBoost; 2561 presentation.nHeavyCompression = drc.heavyCompression; 2562 presentation.nTargetReferenceLevel = drc.targetRefLevel; 2563 presentation.nEncodedTargetLevel = drc.encodedTargetLevel; 2564 presentation.nPCMLimiterEnable = pcmLimiterEnable; 2565 2566 status_t res = mOMX->setParameter(mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile)); 2567 if (res == OK) { 2568 // optional parameters, will not cause configuration failure 2569 mOMX->setParameter(mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacPresentation, 2570 &presentation, sizeof(presentation)); 2571 } else { 2572 ALOGW("did not set AudioAndroidAacPresentation due to error %d when setting AudioAac", res); 2573 } 2574 return res; 2575} 2576 2577status_t ACodec::setupAC3Codec( 2578 bool encoder, int32_t numChannels, int32_t sampleRate) { 2579 status_t err = setupRawAudioFormat( 2580 encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels); 2581 2582 if (err != OK) { 2583 return err; 2584 } 2585 2586 if (encoder) { 2587 ALOGW("AC3 encoding is not supported."); 2588 return INVALID_OPERATION; 2589 } 2590 2591 OMX_AUDIO_PARAM_ANDROID_AC3TYPE def; 2592 InitOMXParams(&def); 2593 def.nPortIndex = kPortIndexInput; 2594 2595 err = mOMX->getParameter( 2596 mNode, 2597 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, 2598 &def, 2599 sizeof(def)); 2600 2601 if (err != OK) { 2602 return err; 2603 } 2604 2605 def.nChannels = numChannels; 2606 def.nSampleRate = sampleRate; 2607 2608 return mOMX->setParameter( 2609 mNode, 2610 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, 2611 &def, 2612 sizeof(def)); 2613} 2614 2615status_t ACodec::setupEAC3Codec( 2616 bool encoder, int32_t numChannels, int32_t sampleRate) { 2617 status_t err = setupRawAudioFormat( 2618 encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels); 2619 2620 if (err != OK) { 2621 return err; 2622 } 2623 2624 if (encoder) { 2625 ALOGW("EAC3 encoding is not supported."); 2626 return INVALID_OPERATION; 2627 } 2628 2629 OMX_AUDIO_PARAM_ANDROID_EAC3TYPE def; 2630 InitOMXParams(&def); 2631 def.nPortIndex = kPortIndexInput; 2632 2633 err = mOMX->getParameter( 2634 mNode, 2635 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, 2636 &def, 2637 sizeof(def)); 2638 2639 if (err != OK) { 2640 return err; 2641 } 2642 2643 def.nChannels = numChannels; 2644 def.nSampleRate = sampleRate; 2645 2646 return mOMX->setParameter( 2647 mNode, 2648 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, 2649 &def, 2650 sizeof(def)); 2651} 2652 2653static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate( 2654 bool isAMRWB, int32_t bps) { 2655 if (isAMRWB) { 2656 if (bps <= 6600) { 2657 return OMX_AUDIO_AMRBandModeWB0; 2658 } else if (bps <= 8850) { 2659 return OMX_AUDIO_AMRBandModeWB1; 2660 } else if (bps <= 12650) { 2661 return OMX_AUDIO_AMRBandModeWB2; 2662 } else if (bps <= 14250) { 2663 return OMX_AUDIO_AMRBandModeWB3; 2664 } else if (bps <= 15850) { 2665 return OMX_AUDIO_AMRBandModeWB4; 2666 } else if (bps <= 18250) { 2667 return OMX_AUDIO_AMRBandModeWB5; 2668 } else if (bps <= 19850) { 2669 return OMX_AUDIO_AMRBandModeWB6; 2670 } else if (bps <= 23050) { 2671 return OMX_AUDIO_AMRBandModeWB7; 2672 } 2673 2674 // 23850 bps 2675 return OMX_AUDIO_AMRBandModeWB8; 2676 } else { // AMRNB 2677 if (bps <= 4750) { 2678 return OMX_AUDIO_AMRBandModeNB0; 2679 } else if (bps <= 5150) { 2680 return OMX_AUDIO_AMRBandModeNB1; 2681 } else if (bps <= 5900) { 2682 return OMX_AUDIO_AMRBandModeNB2; 2683 } else if (bps <= 6700) { 2684 return OMX_AUDIO_AMRBandModeNB3; 2685 } else if (bps <= 7400) { 2686 return OMX_AUDIO_AMRBandModeNB4; 2687 } else if (bps <= 7950) { 2688 return OMX_AUDIO_AMRBandModeNB5; 2689 } else if (bps <= 10200) { 2690 return OMX_AUDIO_AMRBandModeNB6; 2691 } 2692 2693 // 12200 bps 2694 return OMX_AUDIO_AMRBandModeNB7; 2695 } 2696} 2697 2698status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) { 2699 OMX_AUDIO_PARAM_AMRTYPE def; 2700 InitOMXParams(&def); 2701 def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput; 2702 2703 status_t err = 2704 mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); 2705 2706 if (err != OK) { 2707 return err; 2708 } 2709 2710 def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF; 2711 def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate); 2712 2713 err = mOMX->setParameter( 2714 mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); 2715 2716 if (err != OK) { 2717 return err; 2718 } 2719 2720 return setupRawAudioFormat( 2721 encoder ? kPortIndexInput : kPortIndexOutput, 2722 isWAMR ? 16000 : 8000 /* sampleRate */, 2723 1 /* numChannels */); 2724} 2725 2726status_t ACodec::setupG711Codec(bool encoder, int32_t sampleRate, int32_t numChannels) { 2727 if (encoder) { 2728 return INVALID_OPERATION; 2729 } 2730 2731 return setupRawAudioFormat( 2732 kPortIndexInput, sampleRate, numChannels); 2733} 2734 2735status_t ACodec::setupFlacCodec( 2736 bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel) { 2737 2738 if (encoder) { 2739 OMX_AUDIO_PARAM_FLACTYPE def; 2740 InitOMXParams(&def); 2741 def.nPortIndex = kPortIndexOutput; 2742 2743 // configure compression level 2744 status_t err = mOMX->getParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def)); 2745 if (err != OK) { 2746 ALOGE("setupFlacCodec(): Error %d getting OMX_IndexParamAudioFlac parameter", err); 2747 return err; 2748 } 2749 def.nCompressionLevel = compressionLevel; 2750 err = mOMX->setParameter(mNode, OMX_IndexParamAudioFlac, &def, sizeof(def)); 2751 if (err != OK) { 2752 ALOGE("setupFlacCodec(): Error %d setting OMX_IndexParamAudioFlac parameter", err); 2753 return err; 2754 } 2755 } 2756 2757 return setupRawAudioFormat( 2758 encoder ? kPortIndexInput : kPortIndexOutput, 2759 sampleRate, 2760 numChannels); 2761} 2762 2763status_t ACodec::setupRawAudioFormat( 2764 OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) { 2765 OMX_PARAM_PORTDEFINITIONTYPE def; 2766 InitOMXParams(&def); 2767 def.nPortIndex = portIndex; 2768 2769 status_t err = mOMX->getParameter( 2770 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2771 2772 if (err != OK) { 2773 return err; 2774 } 2775 2776 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; 2777 2778 err = mOMX->setParameter( 2779 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 2780 2781 if (err != OK) { 2782 return err; 2783 } 2784 2785 OMX_AUDIO_PARAM_PCMMODETYPE pcmParams; 2786 InitOMXParams(&pcmParams); 2787 pcmParams.nPortIndex = portIndex; 2788 2789 err = mOMX->getParameter( 2790 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); 2791 2792 if (err != OK) { 2793 return err; 2794 } 2795 2796 pcmParams.nChannels = numChannels; 2797 pcmParams.eNumData = OMX_NumericalDataSigned; 2798 pcmParams.bInterleaved = OMX_TRUE; 2799 pcmParams.nBitPerSample = 16; 2800 pcmParams.nSamplingRate = sampleRate; 2801 pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear; 2802 2803 if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) { 2804 return OMX_ErrorNone; 2805 } 2806 2807 return mOMX->setParameter( 2808 mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); 2809} 2810 2811status_t ACodec::configureTunneledVideoPlayback( 2812 int32_t audioHwSync, const sp<ANativeWindow> &nativeWindow) { 2813 native_handle_t* sidebandHandle; 2814 2815 status_t err = mOMX->configureVideoTunnelMode( 2816 mNode, kPortIndexOutput, OMX_TRUE, audioHwSync, &sidebandHandle); 2817 if (err != OK) { 2818 ALOGE("configureVideoTunnelMode failed! (err %d).", err); 2819 return err; 2820 } 2821 2822 err = native_window_set_sideband_stream(nativeWindow.get(), sidebandHandle); 2823 if (err != OK) { 2824 ALOGE("native_window_set_sideband_stream(%p) failed! (err %d).", 2825 sidebandHandle, err); 2826 return err; 2827 } 2828 2829 return OK; 2830} 2831 2832status_t ACodec::setVideoPortFormatType( 2833 OMX_U32 portIndex, 2834 OMX_VIDEO_CODINGTYPE compressionFormat, 2835 OMX_COLOR_FORMATTYPE colorFormat, 2836 bool usingNativeBuffers) { 2837 OMX_VIDEO_PARAM_PORTFORMATTYPE format; 2838 InitOMXParams(&format); 2839 format.nPortIndex = portIndex; 2840 format.nIndex = 0; 2841 bool found = false; 2842 2843 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { 2844 format.nIndex = index; 2845 status_t err = mOMX->getParameter( 2846 mNode, OMX_IndexParamVideoPortFormat, 2847 &format, sizeof(format)); 2848 2849 if (err != OK) { 2850 return err; 2851 } 2852 2853 // substitute back flexible color format to codec supported format 2854 OMX_U32 flexibleEquivalent; 2855 if (compressionFormat == OMX_VIDEO_CodingUnused 2856 && isFlexibleColorFormat( 2857 mOMX, mNode, format.eColorFormat, usingNativeBuffers, &flexibleEquivalent) 2858 && colorFormat == flexibleEquivalent) { 2859 ALOGI("[%s] using color format %#x in place of %#x", 2860 mComponentName.c_str(), format.eColorFormat, colorFormat); 2861 colorFormat = format.eColorFormat; 2862 } 2863 2864 // The following assertion is violated by TI's video decoder. 2865 // CHECK_EQ(format.nIndex, index); 2866 2867 if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) { 2868 if (portIndex == kPortIndexInput 2869 && colorFormat == format.eColorFormat) { 2870 // eCompressionFormat does not seem right. 2871 found = true; 2872 break; 2873 } 2874 if (portIndex == kPortIndexOutput 2875 && compressionFormat == format.eCompressionFormat) { 2876 // eColorFormat does not seem right. 2877 found = true; 2878 break; 2879 } 2880 } 2881 2882 if (format.eCompressionFormat == compressionFormat 2883 && format.eColorFormat == colorFormat) { 2884 found = true; 2885 break; 2886 } 2887 2888 if (index == kMaxIndicesToCheck) { 2889 ALOGW("[%s] stopping checking formats after %u: %s(%x)/%s(%x)", 2890 mComponentName.c_str(), index, 2891 asString(format.eCompressionFormat), format.eCompressionFormat, 2892 asString(format.eColorFormat), format.eColorFormat); 2893 } 2894 } 2895 2896 if (!found) { 2897 return UNKNOWN_ERROR; 2898 } 2899 2900 status_t err = mOMX->setParameter( 2901 mNode, OMX_IndexParamVideoPortFormat, 2902 &format, sizeof(format)); 2903 2904 return err; 2905} 2906 2907// Set optimal output format. OMX component lists output formats in the order 2908// of preference, but this got more complicated since the introduction of flexible 2909// YUV formats. We support a legacy behavior for applications that do not use 2910// surface output, do not specify an output format, but expect a "usable" standard 2911// OMX format. SW readable and standard formats must be flex-YUV. 2912// 2913// Suggested preference order: 2914// - optimal format for texture rendering (mediaplayer behavior) 2915// - optimal SW readable & texture renderable format (flex-YUV support) 2916// - optimal SW readable non-renderable format (flex-YUV bytebuffer support) 2917// - legacy "usable" standard formats 2918// 2919// For legacy support, we prefer a standard format, but will settle for a SW readable 2920// flex-YUV format. 2921status_t ACodec::setSupportedOutputFormat(bool getLegacyFlexibleFormat) { 2922 OMX_VIDEO_PARAM_PORTFORMATTYPE format, legacyFormat; 2923 InitOMXParams(&format); 2924 format.nPortIndex = kPortIndexOutput; 2925 2926 InitOMXParams(&legacyFormat); 2927 // this field will change when we find a suitable legacy format 2928 legacyFormat.eColorFormat = OMX_COLOR_FormatUnused; 2929 2930 for (OMX_U32 index = 0; ; ++index) { 2931 format.nIndex = index; 2932 status_t err = mOMX->getParameter( 2933 mNode, OMX_IndexParamVideoPortFormat, 2934 &format, sizeof(format)); 2935 if (err != OK) { 2936 // no more formats, pick legacy format if found 2937 if (legacyFormat.eColorFormat != OMX_COLOR_FormatUnused) { 2938 memcpy(&format, &legacyFormat, sizeof(format)); 2939 break; 2940 } 2941 return err; 2942 } 2943 if (format.eCompressionFormat != OMX_VIDEO_CodingUnused) { 2944 return OMX_ErrorBadParameter; 2945 } 2946 if (!getLegacyFlexibleFormat) { 2947 break; 2948 } 2949 // standard formats that were exposed to users before 2950 if (format.eColorFormat == OMX_COLOR_FormatYUV420Planar 2951 || format.eColorFormat == OMX_COLOR_FormatYUV420PackedPlanar 2952 || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar 2953 || format.eColorFormat == OMX_COLOR_FormatYUV420PackedSemiPlanar 2954 || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar) { 2955 break; 2956 } 2957 // find best legacy non-standard format 2958 OMX_U32 flexibleEquivalent; 2959 if (legacyFormat.eColorFormat == OMX_COLOR_FormatUnused 2960 && isFlexibleColorFormat( 2961 mOMX, mNode, format.eColorFormat, false /* usingNativeBuffers */, 2962 &flexibleEquivalent) 2963 && flexibleEquivalent == OMX_COLOR_FormatYUV420Flexible) { 2964 memcpy(&legacyFormat, &format, sizeof(format)); 2965 } 2966 } 2967 return mOMX->setParameter( 2968 mNode, OMX_IndexParamVideoPortFormat, 2969 &format, sizeof(format)); 2970} 2971 2972static const struct VideoCodingMapEntry { 2973 const char *mMime; 2974 OMX_VIDEO_CODINGTYPE mVideoCodingType; 2975} kVideoCodingMapEntry[] = { 2976 { MEDIA_MIMETYPE_VIDEO_AVC, OMX_VIDEO_CodingAVC }, 2977 { MEDIA_MIMETYPE_VIDEO_HEVC, OMX_VIDEO_CodingHEVC }, 2978 { MEDIA_MIMETYPE_VIDEO_MPEG4, OMX_VIDEO_CodingMPEG4 }, 2979 { MEDIA_MIMETYPE_VIDEO_H263, OMX_VIDEO_CodingH263 }, 2980 { MEDIA_MIMETYPE_VIDEO_MPEG2, OMX_VIDEO_CodingMPEG2 }, 2981 { MEDIA_MIMETYPE_VIDEO_VP8, OMX_VIDEO_CodingVP8 }, 2982 { MEDIA_MIMETYPE_VIDEO_VP9, OMX_VIDEO_CodingVP9 }, 2983 { MEDIA_MIMETYPE_VIDEO_DOLBY_VISION, OMX_VIDEO_CodingDolbyVision }, 2984}; 2985 2986static status_t GetVideoCodingTypeFromMime( 2987 const char *mime, OMX_VIDEO_CODINGTYPE *codingType) { 2988 for (size_t i = 0; 2989 i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]); 2990 ++i) { 2991 if (!strcasecmp(mime, kVideoCodingMapEntry[i].mMime)) { 2992 *codingType = kVideoCodingMapEntry[i].mVideoCodingType; 2993 return OK; 2994 } 2995 } 2996 2997 *codingType = OMX_VIDEO_CodingUnused; 2998 2999 return ERROR_UNSUPPORTED; 3000} 3001 3002static status_t GetMimeTypeForVideoCoding( 3003 OMX_VIDEO_CODINGTYPE codingType, AString *mime) { 3004 for (size_t i = 0; 3005 i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]); 3006 ++i) { 3007 if (codingType == kVideoCodingMapEntry[i].mVideoCodingType) { 3008 *mime = kVideoCodingMapEntry[i].mMime; 3009 return OK; 3010 } 3011 } 3012 3013 mime->clear(); 3014 3015 return ERROR_UNSUPPORTED; 3016} 3017 3018status_t ACodec::setupVideoDecoder( 3019 const char *mime, const sp<AMessage> &msg, bool haveNativeWindow, 3020 bool usingSwRenderer, sp<AMessage> &outputFormat) { 3021 int32_t width, height; 3022 if (!msg->findInt32("width", &width) 3023 || !msg->findInt32("height", &height)) { 3024 return INVALID_OPERATION; 3025 } 3026 3027 OMX_VIDEO_CODINGTYPE compressionFormat; 3028 status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat); 3029 3030 if (err != OK) { 3031 return err; 3032 } 3033 3034 err = setVideoPortFormatType( 3035 kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused); 3036 3037 if (err != OK) { 3038 return err; 3039 } 3040 3041 int32_t tmp; 3042 if (msg->findInt32("color-format", &tmp)) { 3043 OMX_COLOR_FORMATTYPE colorFormat = 3044 static_cast<OMX_COLOR_FORMATTYPE>(tmp); 3045 err = setVideoPortFormatType( 3046 kPortIndexOutput, OMX_VIDEO_CodingUnused, colorFormat, haveNativeWindow); 3047 if (err != OK) { 3048 ALOGW("[%s] does not support color format %d", 3049 mComponentName.c_str(), colorFormat); 3050 err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */); 3051 } 3052 } else { 3053 err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */); 3054 } 3055 3056 if (err != OK) { 3057 return err; 3058 } 3059 3060 int32_t frameRateInt; 3061 float frameRateFloat; 3062 if (!msg->findFloat("frame-rate", &frameRateFloat)) { 3063 if (!msg->findInt32("frame-rate", &frameRateInt)) { 3064 frameRateInt = -1; 3065 } 3066 frameRateFloat = (float)frameRateInt; 3067 } 3068 3069 err = setVideoFormatOnPort( 3070 kPortIndexInput, width, height, compressionFormat, frameRateFloat); 3071 3072 if (err != OK) { 3073 return err; 3074 } 3075 3076 err = setVideoFormatOnPort( 3077 kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused); 3078 3079 if (err != OK) { 3080 return err; 3081 } 3082 3083 err = setColorAspectsForVideoDecoder( 3084 width, height, haveNativeWindow | usingSwRenderer, msg, outputFormat); 3085 if (err == ERROR_UNSUPPORTED) { // support is optional 3086 err = OK; 3087 } 3088 return err; 3089} 3090 3091status_t ACodec::initDescribeColorAspectsIndex() { 3092 status_t err = mOMX->getExtensionIndex( 3093 mNode, "OMX.google.android.index.describeColorAspects", &mDescribeColorAspectsIndex); 3094 if (err != OK) { 3095 mDescribeColorAspectsIndex = (OMX_INDEXTYPE)0; 3096 } 3097 return err; 3098} 3099 3100status_t ACodec::setCodecColorAspects(DescribeColorAspectsParams ¶ms, bool verify) { 3101 status_t err = ERROR_UNSUPPORTED; 3102 if (mDescribeColorAspectsIndex) { 3103 err = mOMX->setConfig(mNode, mDescribeColorAspectsIndex, ¶ms, sizeof(params)); 3104 } 3105 ALOGV("[%s] setting color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)", 3106 mComponentName.c_str(), 3107 params.sAspects.mRange, asString(params.sAspects.mRange), 3108 params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries), 3109 params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs), 3110 params.sAspects.mTransfer, asString(params.sAspects.mTransfer), 3111 err, asString(err)); 3112 3113 if (verify && err == OK) { 3114 err = getCodecColorAspects(params); 3115 } 3116 3117 ALOGW_IF(err == ERROR_UNSUPPORTED && mDescribeColorAspectsIndex, 3118 "[%s] getting color aspects failed even though codec advertises support", 3119 mComponentName.c_str()); 3120 return err; 3121} 3122 3123status_t ACodec::setColorAspectsForVideoDecoder( 3124 int32_t width, int32_t height, bool usingNativeWindow, 3125 const sp<AMessage> &configFormat, sp<AMessage> &outputFormat) { 3126 DescribeColorAspectsParams params; 3127 InitOMXParams(¶ms); 3128 params.nPortIndex = kPortIndexOutput; 3129 3130 getColorAspectsFromFormat(configFormat, params.sAspects); 3131 if (usingNativeWindow) { 3132 setDefaultCodecColorAspectsIfNeeded(params.sAspects, width, height); 3133 // The default aspects will be set back to the output format during the 3134 // getFormat phase of configure(). Set non-Unspecified values back into the 3135 // format, in case component does not support this enumeration. 3136 setColorAspectsIntoFormat(params.sAspects, outputFormat); 3137 } 3138 3139 (void)initDescribeColorAspectsIndex(); 3140 3141 // communicate color aspects to codec 3142 return setCodecColorAspects(params); 3143} 3144 3145status_t ACodec::getCodecColorAspects(DescribeColorAspectsParams ¶ms) { 3146 status_t err = ERROR_UNSUPPORTED; 3147 if (mDescribeColorAspectsIndex) { 3148 err = mOMX->getConfig(mNode, mDescribeColorAspectsIndex, ¶ms, sizeof(params)); 3149 } 3150 ALOGV("[%s] got color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)", 3151 mComponentName.c_str(), 3152 params.sAspects.mRange, asString(params.sAspects.mRange), 3153 params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries), 3154 params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs), 3155 params.sAspects.mTransfer, asString(params.sAspects.mTransfer), 3156 err, asString(err)); 3157 if (params.bRequestingDataSpace) { 3158 ALOGV("for dataspace %#x", params.nDataSpace); 3159 } 3160 if (err == ERROR_UNSUPPORTED && mDescribeColorAspectsIndex 3161 && !params.bRequestingDataSpace && !params.bDataSpaceChanged) { 3162 ALOGW("[%s] getting color aspects failed even though codec advertises support", 3163 mComponentName.c_str()); 3164 } 3165 return err; 3166} 3167 3168status_t ACodec::getInputColorAspectsForVideoEncoder(sp<AMessage> &format) { 3169 DescribeColorAspectsParams params; 3170 InitOMXParams(¶ms); 3171 params.nPortIndex = kPortIndexInput; 3172 status_t err = getCodecColorAspects(params); 3173 if (err == OK) { 3174 // we only set encoder input aspects if codec supports them 3175 setColorAspectsIntoFormat(params.sAspects, format, true /* force */); 3176 } 3177 return err; 3178} 3179 3180status_t ACodec::getDataSpace( 3181 DescribeColorAspectsParams ¶ms, android_dataspace *dataSpace /* nonnull */, 3182 bool tryCodec) { 3183 status_t err = OK; 3184 if (tryCodec) { 3185 // request dataspace guidance from codec. 3186 params.bRequestingDataSpace = OMX_TRUE; 3187 err = getCodecColorAspects(params); 3188 params.bRequestingDataSpace = OMX_FALSE; 3189 if (err == OK && params.nDataSpace != HAL_DATASPACE_UNKNOWN) { 3190 *dataSpace = (android_dataspace)params.nDataSpace; 3191 return err; 3192 } else if (err == ERROR_UNSUPPORTED) { 3193 // ignore not-implemented error for dataspace requests 3194 err = OK; 3195 } 3196 } 3197 3198 // this returns legacy versions if available 3199 *dataSpace = getDataSpaceForColorAspects(params.sAspects, true /* mayexpand */); 3200 ALOGV("[%s] using color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) " 3201 "and dataspace %#x", 3202 mComponentName.c_str(), 3203 params.sAspects.mRange, asString(params.sAspects.mRange), 3204 params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries), 3205 params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs), 3206 params.sAspects.mTransfer, asString(params.sAspects.mTransfer), 3207 *dataSpace); 3208 return err; 3209} 3210 3211 3212status_t ACodec::getColorAspectsAndDataSpaceForVideoDecoder( 3213 int32_t width, int32_t height, const sp<AMessage> &configFormat, sp<AMessage> &outputFormat, 3214 android_dataspace *dataSpace) { 3215 DescribeColorAspectsParams params; 3216 InitOMXParams(¶ms); 3217 params.nPortIndex = kPortIndexOutput; 3218 3219 // reset default format and get resulting format 3220 getColorAspectsFromFormat(configFormat, params.sAspects); 3221 if (dataSpace != NULL) { 3222 setDefaultCodecColorAspectsIfNeeded(params.sAspects, width, height); 3223 } 3224 status_t err = setCodecColorAspects(params, true /* readBack */); 3225 3226 // we always set specified aspects for decoders 3227 setColorAspectsIntoFormat(params.sAspects, outputFormat); 3228 3229 if (dataSpace != NULL) { 3230 status_t res = getDataSpace(params, dataSpace, err == OK /* tryCodec */); 3231 if (err == OK) { 3232 err = res; 3233 } 3234 } 3235 3236 return err; 3237} 3238 3239// initial video encoder setup for bytebuffer mode 3240status_t ACodec::setColorAspectsForVideoEncoder( 3241 const sp<AMessage> &configFormat, sp<AMessage> &outputFormat, sp<AMessage> &inputFormat) { 3242 // copy config to output format as this is not exposed via getFormat 3243 copyColorConfig(configFormat, outputFormat); 3244 3245 DescribeColorAspectsParams params; 3246 InitOMXParams(¶ms); 3247 params.nPortIndex = kPortIndexInput; 3248 getColorAspectsFromFormat(configFormat, params.sAspects); 3249 3250 (void)initDescribeColorAspectsIndex(); 3251 3252 int32_t usingRecorder; 3253 if (configFormat->findInt32("android._using-recorder", &usingRecorder) && usingRecorder) { 3254 android_dataspace dataSpace = HAL_DATASPACE_BT709; 3255 int32_t width, height; 3256 if (configFormat->findInt32("width", &width) 3257 && configFormat->findInt32("height", &height)) { 3258 setDefaultCodecColorAspectsIfNeeded(params.sAspects, width, height); 3259 status_t err = getDataSpace( 3260 params, &dataSpace, mDescribeColorAspectsIndex /* tryCodec */); 3261 if (err != OK) { 3262 return err; 3263 } 3264 setColorAspectsIntoFormat(params.sAspects, outputFormat); 3265 } 3266 inputFormat->setInt32("android._dataspace", (int32_t)dataSpace); 3267 } 3268 3269 // communicate color aspects to codec, but do not allow change of the platform aspects 3270 ColorAspects origAspects = params.sAspects; 3271 for (int triesLeft = 2; --triesLeft >= 0; ) { 3272 status_t err = setCodecColorAspects(params, true /* readBack */); 3273 if (err != OK 3274 || !ColorUtils::checkIfAspectsChangedAndUnspecifyThem( 3275 params.sAspects, origAspects, true /* usePlatformAspects */)) { 3276 return err; 3277 } 3278 ALOGW_IF(triesLeft == 0, "[%s] Codec repeatedly changed requested ColorAspects.", 3279 mComponentName.c_str()); 3280 } 3281 return OK; 3282} 3283 3284// subsequent initial video encoder setup for surface mode 3285status_t ACodec::setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace( 3286 android_dataspace *dataSpace /* nonnull */) { 3287 DescribeColorAspectsParams params; 3288 InitOMXParams(¶ms); 3289 params.nPortIndex = kPortIndexInput; 3290 ColorAspects &aspects = params.sAspects; 3291 3292 // reset default format and store resulting format into both input and output formats 3293 getColorAspectsFromFormat(mConfigFormat, aspects); 3294 int32_t width, height; 3295 if (mInputFormat->findInt32("width", &width) && mInputFormat->findInt32("height", &height)) { 3296 setDefaultCodecColorAspectsIfNeeded(aspects, width, height); 3297 } 3298 setColorAspectsIntoFormat(aspects, mInputFormat); 3299 setColorAspectsIntoFormat(aspects, mOutputFormat); 3300 3301 // communicate color aspects to codec, but do not allow any change 3302 ColorAspects origAspects = aspects; 3303 status_t err = OK; 3304 for (int triesLeft = 2; mDescribeColorAspectsIndex && --triesLeft >= 0; ) { 3305 status_t err = setCodecColorAspects(params, true /* readBack */); 3306 if (err != OK || !ColorUtils::checkIfAspectsChangedAndUnspecifyThem(aspects, origAspects)) { 3307 break; 3308 } 3309 ALOGW_IF(triesLeft == 0, "[%s] Codec repeatedly changed requested ColorAspects.", 3310 mComponentName.c_str()); 3311 } 3312 3313 *dataSpace = HAL_DATASPACE_BT709; 3314 aspects = origAspects; // restore desired color aspects 3315 status_t res = getDataSpace( 3316 params, dataSpace, err == OK && mDescribeColorAspectsIndex /* tryCodec */); 3317 if (err == OK) { 3318 err = res; 3319 } 3320 mInputFormat->setInt32("android._dataspace", (int32_t)*dataSpace); 3321 mInputFormat->setBuffer( 3322 "android._color-aspects", ABuffer::CreateAsCopy(&aspects, sizeof(aspects))); 3323 3324 // update input format with codec supported color aspects (basically set unsupported 3325 // aspects to Unspecified) 3326 if (err == OK) { 3327 (void)getInputColorAspectsForVideoEncoder(mInputFormat); 3328 } 3329 3330 ALOGV("set default color aspects, updated input format to %s, output format to %s", 3331 mInputFormat->debugString(4).c_str(), mOutputFormat->debugString(4).c_str()); 3332 3333 return err; 3334} 3335 3336status_t ACodec::setupVideoEncoder( 3337 const char *mime, const sp<AMessage> &msg, 3338 sp<AMessage> &outputFormat, sp<AMessage> &inputFormat) { 3339 int32_t tmp; 3340 if (!msg->findInt32("color-format", &tmp)) { 3341 return INVALID_OPERATION; 3342 } 3343 3344 OMX_COLOR_FORMATTYPE colorFormat = 3345 static_cast<OMX_COLOR_FORMATTYPE>(tmp); 3346 3347 status_t err = setVideoPortFormatType( 3348 kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat); 3349 3350 if (err != OK) { 3351 ALOGE("[%s] does not support color format %d", 3352 mComponentName.c_str(), colorFormat); 3353 3354 return err; 3355 } 3356 3357 /* Input port configuration */ 3358 3359 OMX_PARAM_PORTDEFINITIONTYPE def; 3360 InitOMXParams(&def); 3361 3362 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 3363 3364 def.nPortIndex = kPortIndexInput; 3365 3366 err = mOMX->getParameter( 3367 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 3368 3369 if (err != OK) { 3370 return err; 3371 } 3372 3373 int32_t width, height, bitrate; 3374 if (!msg->findInt32("width", &width) 3375 || !msg->findInt32("height", &height) 3376 || !msg->findInt32("bitrate", &bitrate)) { 3377 return INVALID_OPERATION; 3378 } 3379 3380 video_def->nFrameWidth = width; 3381 video_def->nFrameHeight = height; 3382 3383 int32_t stride; 3384 if (!msg->findInt32("stride", &stride)) { 3385 stride = width; 3386 } 3387 3388 video_def->nStride = stride; 3389 3390 int32_t sliceHeight; 3391 if (!msg->findInt32("slice-height", &sliceHeight)) { 3392 sliceHeight = height; 3393 } 3394 3395 video_def->nSliceHeight = sliceHeight; 3396 3397 def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2; 3398 3399 float frameRate; 3400 if (!msg->findFloat("frame-rate", &frameRate)) { 3401 int32_t tmp; 3402 if (!msg->findInt32("frame-rate", &tmp)) { 3403 return INVALID_OPERATION; 3404 } 3405 frameRate = (float)tmp; 3406 mTimePerFrameUs = (int64_t) (1000000.0f / frameRate); 3407 } 3408 3409 video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f); 3410 video_def->eCompressionFormat = OMX_VIDEO_CodingUnused; 3411 // this is redundant as it was already set up in setVideoPortFormatType 3412 // FIXME for now skip this only for flexible YUV formats 3413 if (colorFormat != OMX_COLOR_FormatYUV420Flexible) { 3414 video_def->eColorFormat = colorFormat; 3415 } 3416 3417 err = mOMX->setParameter( 3418 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 3419 3420 if (err != OK) { 3421 ALOGE("[%s] failed to set input port definition parameters.", 3422 mComponentName.c_str()); 3423 3424 return err; 3425 } 3426 3427 /* Output port configuration */ 3428 3429 OMX_VIDEO_CODINGTYPE compressionFormat; 3430 err = GetVideoCodingTypeFromMime(mime, &compressionFormat); 3431 3432 if (err != OK) { 3433 return err; 3434 } 3435 3436 err = setVideoPortFormatType( 3437 kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused); 3438 3439 if (err != OK) { 3440 ALOGE("[%s] does not support compression format %d", 3441 mComponentName.c_str(), compressionFormat); 3442 3443 return err; 3444 } 3445 3446 def.nPortIndex = kPortIndexOutput; 3447 3448 err = mOMX->getParameter( 3449 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 3450 3451 if (err != OK) { 3452 return err; 3453 } 3454 3455 video_def->nFrameWidth = width; 3456 video_def->nFrameHeight = height; 3457 video_def->xFramerate = 0; 3458 video_def->nBitrate = bitrate; 3459 video_def->eCompressionFormat = compressionFormat; 3460 video_def->eColorFormat = OMX_COLOR_FormatUnused; 3461 3462 err = mOMX->setParameter( 3463 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 3464 3465 if (err != OK) { 3466 ALOGE("[%s] failed to set output port definition parameters.", 3467 mComponentName.c_str()); 3468 3469 return err; 3470 } 3471 3472 int32_t intraRefreshPeriod = 0; 3473 if (msg->findInt32("intra-refresh-period", &intraRefreshPeriod) 3474 && intraRefreshPeriod >= 0) { 3475 err = setIntraRefreshPeriod((uint32_t)intraRefreshPeriod, true); 3476 if (err != OK) { 3477 ALOGI("[%s] failed setIntraRefreshPeriod. Failure is fine since this key is optional", 3478 mComponentName.c_str()); 3479 err = OK; 3480 } 3481 } 3482 3483 switch (compressionFormat) { 3484 case OMX_VIDEO_CodingMPEG4: 3485 err = setupMPEG4EncoderParameters(msg); 3486 break; 3487 3488 case OMX_VIDEO_CodingH263: 3489 err = setupH263EncoderParameters(msg); 3490 break; 3491 3492 case OMX_VIDEO_CodingAVC: 3493 err = setupAVCEncoderParameters(msg); 3494 break; 3495 3496 case OMX_VIDEO_CodingHEVC: 3497 err = setupHEVCEncoderParameters(msg); 3498 break; 3499 3500 case OMX_VIDEO_CodingVP8: 3501 case OMX_VIDEO_CodingVP9: 3502 err = setupVPXEncoderParameters(msg); 3503 break; 3504 3505 default: 3506 break; 3507 } 3508 3509 // Set up color aspects on input, but propagate them to the output format, as they will 3510 // not be read back from encoder. 3511 err = setColorAspectsForVideoEncoder(msg, outputFormat, inputFormat); 3512 if (err == ERROR_UNSUPPORTED) { 3513 ALOGI("[%s] cannot encode color aspects. Ignoring.", mComponentName.c_str()); 3514 err = OK; 3515 } 3516 3517 if (err == OK) { 3518 ALOGI("setupVideoEncoder succeeded"); 3519 } 3520 3521 return err; 3522} 3523 3524status_t ACodec::setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode) { 3525 OMX_VIDEO_PARAM_INTRAREFRESHTYPE params; 3526 InitOMXParams(¶ms); 3527 params.nPortIndex = kPortIndexOutput; 3528 3529 params.eRefreshMode = static_cast<OMX_VIDEO_INTRAREFRESHTYPE>(mode); 3530 3531 if (params.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic || 3532 params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) { 3533 int32_t mbs; 3534 if (!msg->findInt32("intra-refresh-CIR-mbs", &mbs)) { 3535 return INVALID_OPERATION; 3536 } 3537 params.nCirMBs = mbs; 3538 } 3539 3540 if (params.eRefreshMode == OMX_VIDEO_IntraRefreshAdaptive || 3541 params.eRefreshMode == OMX_VIDEO_IntraRefreshBoth) { 3542 int32_t mbs; 3543 if (!msg->findInt32("intra-refresh-AIR-mbs", &mbs)) { 3544 return INVALID_OPERATION; 3545 } 3546 params.nAirMBs = mbs; 3547 3548 int32_t ref; 3549 if (!msg->findInt32("intra-refresh-AIR-ref", &ref)) { 3550 return INVALID_OPERATION; 3551 } 3552 params.nAirRef = ref; 3553 } 3554 3555 status_t err = mOMX->setParameter( 3556 mNode, OMX_IndexParamVideoIntraRefresh, 3557 ¶ms, sizeof(params)); 3558 return err; 3559} 3560 3561static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) { 3562 if (iFramesInterval < 0) { 3563 return 0xFFFFFFFF; 3564 } else if (iFramesInterval == 0) { 3565 return 0; 3566 } 3567 OMX_U32 ret = frameRate * iFramesInterval; 3568 return ret; 3569} 3570 3571static OMX_VIDEO_CONTROLRATETYPE getBitrateMode(const sp<AMessage> &msg) { 3572 int32_t tmp; 3573 if (!msg->findInt32("bitrate-mode", &tmp)) { 3574 return OMX_Video_ControlRateVariable; 3575 } 3576 3577 return static_cast<OMX_VIDEO_CONTROLRATETYPE>(tmp); 3578} 3579 3580status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) { 3581 int32_t bitrate, iFrameInterval; 3582 if (!msg->findInt32("bitrate", &bitrate) 3583 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 3584 return INVALID_OPERATION; 3585 } 3586 3587 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 3588 3589 float frameRate; 3590 if (!msg->findFloat("frame-rate", &frameRate)) { 3591 int32_t tmp; 3592 if (!msg->findInt32("frame-rate", &tmp)) { 3593 return INVALID_OPERATION; 3594 } 3595 frameRate = (float)tmp; 3596 } 3597 3598 OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type; 3599 InitOMXParams(&mpeg4type); 3600 mpeg4type.nPortIndex = kPortIndexOutput; 3601 3602 status_t err = mOMX->getParameter( 3603 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); 3604 3605 if (err != OK) { 3606 return err; 3607 } 3608 3609 mpeg4type.nSliceHeaderSpacing = 0; 3610 mpeg4type.bSVH = OMX_FALSE; 3611 mpeg4type.bGov = OMX_FALSE; 3612 3613 mpeg4type.nAllowedPictureTypes = 3614 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 3615 3616 mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 3617 if (mpeg4type.nPFrames == 0) { 3618 mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 3619 } 3620 mpeg4type.nBFrames = 0; 3621 mpeg4type.nIDCVLCThreshold = 0; 3622 mpeg4type.bACPred = OMX_TRUE; 3623 mpeg4type.nMaxPacketSize = 256; 3624 mpeg4type.nTimeIncRes = 1000; 3625 mpeg4type.nHeaderExtension = 0; 3626 mpeg4type.bReversibleVLC = OMX_FALSE; 3627 3628 int32_t profile; 3629 if (msg->findInt32("profile", &profile)) { 3630 int32_t level; 3631 if (!msg->findInt32("level", &level)) { 3632 return INVALID_OPERATION; 3633 } 3634 3635 err = verifySupportForProfileAndLevel(profile, level); 3636 3637 if (err != OK) { 3638 return err; 3639 } 3640 3641 mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile); 3642 mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level); 3643 } 3644 3645 err = mOMX->setParameter( 3646 mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); 3647 3648 if (err != OK) { 3649 return err; 3650 } 3651 3652 err = configureBitrate(bitrate, bitrateMode); 3653 3654 if (err != OK) { 3655 return err; 3656 } 3657 3658 return setupErrorCorrectionParameters(); 3659} 3660 3661status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) { 3662 int32_t bitrate, iFrameInterval; 3663 if (!msg->findInt32("bitrate", &bitrate) 3664 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 3665 return INVALID_OPERATION; 3666 } 3667 3668 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 3669 3670 float frameRate; 3671 if (!msg->findFloat("frame-rate", &frameRate)) { 3672 int32_t tmp; 3673 if (!msg->findInt32("frame-rate", &tmp)) { 3674 return INVALID_OPERATION; 3675 } 3676 frameRate = (float)tmp; 3677 } 3678 3679 OMX_VIDEO_PARAM_H263TYPE h263type; 3680 InitOMXParams(&h263type); 3681 h263type.nPortIndex = kPortIndexOutput; 3682 3683 status_t err = mOMX->getParameter( 3684 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); 3685 3686 if (err != OK) { 3687 return err; 3688 } 3689 3690 h263type.nAllowedPictureTypes = 3691 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 3692 3693 h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 3694 if (h263type.nPFrames == 0) { 3695 h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 3696 } 3697 h263type.nBFrames = 0; 3698 3699 int32_t profile; 3700 if (msg->findInt32("profile", &profile)) { 3701 int32_t level; 3702 if (!msg->findInt32("level", &level)) { 3703 return INVALID_OPERATION; 3704 } 3705 3706 err = verifySupportForProfileAndLevel(profile, level); 3707 3708 if (err != OK) { 3709 return err; 3710 } 3711 3712 h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile); 3713 h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level); 3714 } 3715 3716 h263type.bPLUSPTYPEAllowed = OMX_FALSE; 3717 h263type.bForceRoundingTypeToZero = OMX_FALSE; 3718 h263type.nPictureHeaderRepetition = 0; 3719 h263type.nGOBHeaderInterval = 0; 3720 3721 err = mOMX->setParameter( 3722 mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type)); 3723 3724 if (err != OK) { 3725 return err; 3726 } 3727 3728 err = configureBitrate(bitrate, bitrateMode); 3729 3730 if (err != OK) { 3731 return err; 3732 } 3733 3734 return setupErrorCorrectionParameters(); 3735} 3736 3737// static 3738int /* OMX_VIDEO_AVCLEVELTYPE */ ACodec::getAVCLevelFor( 3739 int width, int height, int rate, int bitrate, 3740 OMX_VIDEO_AVCPROFILETYPE profile) { 3741 // convert bitrate to main/baseline profile kbps equivalent 3742 switch (profile) { 3743 case OMX_VIDEO_AVCProfileHigh10: 3744 bitrate = divUp(bitrate, 3000); break; 3745 case OMX_VIDEO_AVCProfileHigh: 3746 bitrate = divUp(bitrate, 1250); break; 3747 default: 3748 bitrate = divUp(bitrate, 1000); break; 3749 } 3750 3751 // convert size and rate to MBs 3752 width = divUp(width, 16); 3753 height = divUp(height, 16); 3754 int mbs = width * height; 3755 rate *= mbs; 3756 int maxDimension = max(width, height); 3757 3758 static const int limits[][5] = { 3759 /* MBps MB dim bitrate level */ 3760 { 1485, 99, 28, 64, OMX_VIDEO_AVCLevel1 }, 3761 { 1485, 99, 28, 128, OMX_VIDEO_AVCLevel1b }, 3762 { 3000, 396, 56, 192, OMX_VIDEO_AVCLevel11 }, 3763 { 6000, 396, 56, 384, OMX_VIDEO_AVCLevel12 }, 3764 { 11880, 396, 56, 768, OMX_VIDEO_AVCLevel13 }, 3765 { 11880, 396, 56, 2000, OMX_VIDEO_AVCLevel2 }, 3766 { 19800, 792, 79, 4000, OMX_VIDEO_AVCLevel21 }, 3767 { 20250, 1620, 113, 4000, OMX_VIDEO_AVCLevel22 }, 3768 { 40500, 1620, 113, 10000, OMX_VIDEO_AVCLevel3 }, 3769 { 108000, 3600, 169, 14000, OMX_VIDEO_AVCLevel31 }, 3770 { 216000, 5120, 202, 20000, OMX_VIDEO_AVCLevel32 }, 3771 { 245760, 8192, 256, 20000, OMX_VIDEO_AVCLevel4 }, 3772 { 245760, 8192, 256, 50000, OMX_VIDEO_AVCLevel41 }, 3773 { 522240, 8704, 263, 50000, OMX_VIDEO_AVCLevel42 }, 3774 { 589824, 22080, 420, 135000, OMX_VIDEO_AVCLevel5 }, 3775 { 983040, 36864, 543, 240000, OMX_VIDEO_AVCLevel51 }, 3776 { 2073600, 36864, 543, 240000, OMX_VIDEO_AVCLevel52 }, 3777 }; 3778 3779 for (size_t i = 0; i < ARRAY_SIZE(limits); i++) { 3780 const int (&limit)[5] = limits[i]; 3781 if (rate <= limit[0] && mbs <= limit[1] && maxDimension <= limit[2] 3782 && bitrate <= limit[3]) { 3783 return limit[4]; 3784 } 3785 } 3786 return 0; 3787} 3788 3789status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) { 3790 int32_t bitrate, iFrameInterval; 3791 if (!msg->findInt32("bitrate", &bitrate) 3792 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 3793 return INVALID_OPERATION; 3794 } 3795 3796 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 3797 3798 float frameRate; 3799 if (!msg->findFloat("frame-rate", &frameRate)) { 3800 int32_t tmp; 3801 if (!msg->findInt32("frame-rate", &tmp)) { 3802 return INVALID_OPERATION; 3803 } 3804 frameRate = (float)tmp; 3805 } 3806 3807 status_t err = OK; 3808 int32_t intraRefreshMode = 0; 3809 if (msg->findInt32("intra-refresh-mode", &intraRefreshMode)) { 3810 err = setCyclicIntraMacroblockRefresh(msg, intraRefreshMode); 3811 if (err != OK) { 3812 ALOGE("Setting intra macroblock refresh mode (%d) failed: 0x%x", 3813 err, intraRefreshMode); 3814 return err; 3815 } 3816 } 3817 3818 OMX_VIDEO_PARAM_AVCTYPE h264type; 3819 InitOMXParams(&h264type); 3820 h264type.nPortIndex = kPortIndexOutput; 3821 3822 err = mOMX->getParameter( 3823 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 3824 3825 if (err != OK) { 3826 return err; 3827 } 3828 3829 h264type.nAllowedPictureTypes = 3830 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 3831 3832 int32_t profile; 3833 if (msg->findInt32("profile", &profile)) { 3834 int32_t level; 3835 if (!msg->findInt32("level", &level)) { 3836 return INVALID_OPERATION; 3837 } 3838 3839 err = verifySupportForProfileAndLevel(profile, level); 3840 3841 if (err != OK) { 3842 return err; 3843 } 3844 3845 h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile); 3846 h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level); 3847 } 3848 3849 if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) { 3850 h264type.nSliceHeaderSpacing = 0; 3851 h264type.bUseHadamard = OMX_TRUE; 3852 h264type.nRefFrames = 1; 3853 h264type.nBFrames = 0; 3854 h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 3855 if (h264type.nPFrames == 0) { 3856 h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 3857 } 3858 h264type.nRefIdx10ActiveMinus1 = 0; 3859 h264type.nRefIdx11ActiveMinus1 = 0; 3860 h264type.bEntropyCodingCABAC = OMX_FALSE; 3861 h264type.bWeightedPPrediction = OMX_FALSE; 3862 h264type.bconstIpred = OMX_FALSE; 3863 h264type.bDirect8x8Inference = OMX_FALSE; 3864 h264type.bDirectSpatialTemporal = OMX_FALSE; 3865 h264type.nCabacInitIdc = 0; 3866 } else if (h264type.eProfile == OMX_VIDEO_AVCProfileMain || 3867 h264type.eProfile == OMX_VIDEO_AVCProfileHigh) { 3868 h264type.nSliceHeaderSpacing = 0; 3869 h264type.bUseHadamard = OMX_TRUE; 3870 h264type.nRefFrames = 2; 3871 h264type.nBFrames = 1; 3872 h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate); 3873 h264type.nAllowedPictureTypes = 3874 OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP | OMX_VIDEO_PictureTypeB; 3875 h264type.nRefIdx10ActiveMinus1 = 0; 3876 h264type.nRefIdx11ActiveMinus1 = 0; 3877 h264type.bEntropyCodingCABAC = OMX_TRUE; 3878 h264type.bWeightedPPrediction = OMX_TRUE; 3879 h264type.bconstIpred = OMX_TRUE; 3880 h264type.bDirect8x8Inference = OMX_TRUE; 3881 h264type.bDirectSpatialTemporal = OMX_TRUE; 3882 h264type.nCabacInitIdc = 1; 3883 } 3884 3885 if (h264type.nBFrames != 0) { 3886 h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB; 3887 } 3888 3889 h264type.bEnableUEP = OMX_FALSE; 3890 h264type.bEnableFMO = OMX_FALSE; 3891 h264type.bEnableASO = OMX_FALSE; 3892 h264type.bEnableRS = OMX_FALSE; 3893 h264type.bFrameMBsOnly = OMX_TRUE; 3894 h264type.bMBAFF = OMX_FALSE; 3895 h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; 3896 3897 err = mOMX->setParameter( 3898 mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type)); 3899 3900 if (err != OK) { 3901 return err; 3902 } 3903 3904 return configureBitrate(bitrate, bitrateMode); 3905} 3906 3907status_t ACodec::setupHEVCEncoderParameters(const sp<AMessage> &msg) { 3908 int32_t bitrate, iFrameInterval; 3909 if (!msg->findInt32("bitrate", &bitrate) 3910 || !msg->findInt32("i-frame-interval", &iFrameInterval)) { 3911 return INVALID_OPERATION; 3912 } 3913 3914 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 3915 3916 float frameRate; 3917 if (!msg->findFloat("frame-rate", &frameRate)) { 3918 int32_t tmp; 3919 if (!msg->findInt32("frame-rate", &tmp)) { 3920 return INVALID_OPERATION; 3921 } 3922 frameRate = (float)tmp; 3923 } 3924 3925 OMX_VIDEO_PARAM_HEVCTYPE hevcType; 3926 InitOMXParams(&hevcType); 3927 hevcType.nPortIndex = kPortIndexOutput; 3928 3929 status_t err = OK; 3930 err = mOMX->getParameter( 3931 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType)); 3932 if (err != OK) { 3933 return err; 3934 } 3935 3936 int32_t profile; 3937 if (msg->findInt32("profile", &profile)) { 3938 int32_t level; 3939 if (!msg->findInt32("level", &level)) { 3940 return INVALID_OPERATION; 3941 } 3942 3943 err = verifySupportForProfileAndLevel(profile, level); 3944 if (err != OK) { 3945 return err; 3946 } 3947 3948 hevcType.eProfile = static_cast<OMX_VIDEO_HEVCPROFILETYPE>(profile); 3949 hevcType.eLevel = static_cast<OMX_VIDEO_HEVCLEVELTYPE>(level); 3950 } 3951 // TODO: finer control? 3952 hevcType.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate); 3953 3954 err = mOMX->setParameter( 3955 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoHevc, &hevcType, sizeof(hevcType)); 3956 if (err != OK) { 3957 return err; 3958 } 3959 3960 return configureBitrate(bitrate, bitrateMode); 3961} 3962 3963status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg) { 3964 int32_t bitrate; 3965 int32_t iFrameInterval = 0; 3966 size_t tsLayers = 0; 3967 OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE pattern = 3968 OMX_VIDEO_VPXTemporalLayerPatternNone; 3969 static const uint32_t kVp8LayerRateAlloction 3970 [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] 3971 [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] = { 3972 {100, 100, 100}, // 1 layer 3973 { 60, 100, 100}, // 2 layers {60%, 40%} 3974 { 40, 60, 100}, // 3 layers {40%, 20%, 40%} 3975 }; 3976 if (!msg->findInt32("bitrate", &bitrate)) { 3977 return INVALID_OPERATION; 3978 } 3979 msg->findInt32("i-frame-interval", &iFrameInterval); 3980 3981 OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg); 3982 3983 float frameRate; 3984 if (!msg->findFloat("frame-rate", &frameRate)) { 3985 int32_t tmp; 3986 if (!msg->findInt32("frame-rate", &tmp)) { 3987 return INVALID_OPERATION; 3988 } 3989 frameRate = (float)tmp; 3990 } 3991 3992 AString tsSchema; 3993 if (msg->findString("ts-schema", &tsSchema)) { 3994 if (tsSchema == "webrtc.vp8.1-layer") { 3995 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC; 3996 tsLayers = 1; 3997 } else if (tsSchema == "webrtc.vp8.2-layer") { 3998 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC; 3999 tsLayers = 2; 4000 } else if (tsSchema == "webrtc.vp8.3-layer") { 4001 pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC; 4002 tsLayers = 3; 4003 } else { 4004 ALOGW("Unsupported ts-schema [%s]", tsSchema.c_str()); 4005 } 4006 } 4007 4008 OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type; 4009 InitOMXParams(&vp8type); 4010 vp8type.nPortIndex = kPortIndexOutput; 4011 status_t err = mOMX->getParameter( 4012 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder, 4013 &vp8type, sizeof(vp8type)); 4014 4015 if (err == OK) { 4016 if (iFrameInterval > 0) { 4017 vp8type.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate); 4018 } 4019 vp8type.eTemporalPattern = pattern; 4020 vp8type.nTemporalLayerCount = tsLayers; 4021 if (tsLayers > 0) { 4022 for (size_t i = 0; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) { 4023 vp8type.nTemporalLayerBitrateRatio[i] = 4024 kVp8LayerRateAlloction[tsLayers - 1][i]; 4025 } 4026 } 4027 if (bitrateMode == OMX_Video_ControlRateConstant) { 4028 vp8type.nMinQuantizer = 2; 4029 vp8type.nMaxQuantizer = 63; 4030 } 4031 4032 err = mOMX->setParameter( 4033 mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder, 4034 &vp8type, sizeof(vp8type)); 4035 if (err != OK) { 4036 ALOGW("Extended VP8 parameters set failed: %d", err); 4037 } 4038 } 4039 4040 return configureBitrate(bitrate, bitrateMode); 4041} 4042 4043status_t ACodec::verifySupportForProfileAndLevel( 4044 int32_t profile, int32_t level) { 4045 OMX_VIDEO_PARAM_PROFILELEVELTYPE params; 4046 InitOMXParams(¶ms); 4047 params.nPortIndex = kPortIndexOutput; 4048 4049 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { 4050 params.nProfileIndex = index; 4051 status_t err = mOMX->getParameter( 4052 mNode, 4053 OMX_IndexParamVideoProfileLevelQuerySupported, 4054 ¶ms, 4055 sizeof(params)); 4056 4057 if (err != OK) { 4058 return err; 4059 } 4060 4061 int32_t supportedProfile = static_cast<int32_t>(params.eProfile); 4062 int32_t supportedLevel = static_cast<int32_t>(params.eLevel); 4063 4064 if (profile == supportedProfile && level <= supportedLevel) { 4065 return OK; 4066 } 4067 4068 if (index == kMaxIndicesToCheck) { 4069 ALOGW("[%s] stopping checking profiles after %u: %x/%x", 4070 mComponentName.c_str(), index, 4071 params.eProfile, params.eLevel); 4072 } 4073 } 4074 return ERROR_UNSUPPORTED; 4075} 4076 4077status_t ACodec::configureBitrate( 4078 int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode) { 4079 OMX_VIDEO_PARAM_BITRATETYPE bitrateType; 4080 InitOMXParams(&bitrateType); 4081 bitrateType.nPortIndex = kPortIndexOutput; 4082 4083 status_t err = mOMX->getParameter( 4084 mNode, OMX_IndexParamVideoBitrate, 4085 &bitrateType, sizeof(bitrateType)); 4086 4087 if (err != OK) { 4088 return err; 4089 } 4090 4091 bitrateType.eControlRate = bitrateMode; 4092 bitrateType.nTargetBitrate = bitrate; 4093 4094 return mOMX->setParameter( 4095 mNode, OMX_IndexParamVideoBitrate, 4096 &bitrateType, sizeof(bitrateType)); 4097} 4098 4099status_t ACodec::setupErrorCorrectionParameters() { 4100 OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType; 4101 InitOMXParams(&errorCorrectionType); 4102 errorCorrectionType.nPortIndex = kPortIndexOutput; 4103 4104 status_t err = mOMX->getParameter( 4105 mNode, OMX_IndexParamVideoErrorCorrection, 4106 &errorCorrectionType, sizeof(errorCorrectionType)); 4107 4108 if (err != OK) { 4109 return OK; // Optional feature. Ignore this failure 4110 } 4111 4112 errorCorrectionType.bEnableHEC = OMX_FALSE; 4113 errorCorrectionType.bEnableResync = OMX_TRUE; 4114 errorCorrectionType.nResynchMarkerSpacing = 256; 4115 errorCorrectionType.bEnableDataPartitioning = OMX_FALSE; 4116 errorCorrectionType.bEnableRVLC = OMX_FALSE; 4117 4118 return mOMX->setParameter( 4119 mNode, OMX_IndexParamVideoErrorCorrection, 4120 &errorCorrectionType, sizeof(errorCorrectionType)); 4121} 4122 4123status_t ACodec::setVideoFormatOnPort( 4124 OMX_U32 portIndex, 4125 int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat, 4126 float frameRate) { 4127 OMX_PARAM_PORTDEFINITIONTYPE def; 4128 InitOMXParams(&def); 4129 def.nPortIndex = portIndex; 4130 4131 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video; 4132 4133 status_t err = mOMX->getParameter( 4134 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 4135 if (err != OK) { 4136 return err; 4137 } 4138 4139 if (portIndex == kPortIndexInput) { 4140 // XXX Need a (much) better heuristic to compute input buffer sizes. 4141 const size_t X = 64 * 1024; 4142 if (def.nBufferSize < X) { 4143 def.nBufferSize = X; 4144 } 4145 } 4146 4147 if (def.eDomain != OMX_PortDomainVideo) { 4148 ALOGE("expected video port, got %s(%d)", asString(def.eDomain), def.eDomain); 4149 return FAILED_TRANSACTION; 4150 } 4151 4152 video_def->nFrameWidth = width; 4153 video_def->nFrameHeight = height; 4154 4155 if (portIndex == kPortIndexInput) { 4156 video_def->eCompressionFormat = compressionFormat; 4157 video_def->eColorFormat = OMX_COLOR_FormatUnused; 4158 if (frameRate >= 0) { 4159 video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f); 4160 } 4161 } 4162 4163 err = mOMX->setParameter( 4164 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 4165 4166 return err; 4167} 4168 4169status_t ACodec::initNativeWindow() { 4170 if (mNativeWindow != NULL) { 4171 return mOMX->enableNativeBuffers(mNode, kPortIndexOutput, OMX_TRUE /* graphic */, OMX_TRUE); 4172 } 4173 4174 mOMX->enableNativeBuffers(mNode, kPortIndexOutput, OMX_TRUE /* graphic */, OMX_FALSE); 4175 return OK; 4176} 4177 4178size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const { 4179 size_t n = 0; 4180 4181 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 4182 const BufferInfo &info = mBuffers[portIndex].itemAt(i); 4183 4184 if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) { 4185 ++n; 4186 } 4187 } 4188 4189 return n; 4190} 4191 4192size_t ACodec::countBuffersOwnedByNativeWindow() const { 4193 size_t n = 0; 4194 4195 for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) { 4196 const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i); 4197 4198 if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 4199 ++n; 4200 } 4201 } 4202 4203 return n; 4204} 4205 4206void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() { 4207 if (mNativeWindow == NULL) { 4208 return; 4209 } 4210 4211 while (countBuffersOwnedByNativeWindow() > mNumUndequeuedBuffers 4212 && dequeueBufferFromNativeWindow() != NULL) { 4213 // these buffers will be submitted as regular buffers; account for this 4214 if (storingMetadataInDecodedBuffers() && mMetadataBuffersToSubmit > 0) { 4215 --mMetadataBuffersToSubmit; 4216 } 4217 } 4218} 4219 4220bool ACodec::allYourBuffersAreBelongToUs( 4221 OMX_U32 portIndex) { 4222 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 4223 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 4224 4225 if (info->mStatus != BufferInfo::OWNED_BY_US 4226 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) { 4227 ALOGV("[%s] Buffer %u on port %u still has status %d", 4228 mComponentName.c_str(), 4229 info->mBufferID, portIndex, info->mStatus); 4230 return false; 4231 } 4232 } 4233 4234 return true; 4235} 4236 4237bool ACodec::allYourBuffersAreBelongToUs() { 4238 return allYourBuffersAreBelongToUs(kPortIndexInput) 4239 && allYourBuffersAreBelongToUs(kPortIndexOutput); 4240} 4241 4242void ACodec::deferMessage(const sp<AMessage> &msg) { 4243 mDeferredQueue.push_back(msg); 4244} 4245 4246void ACodec::processDeferredMessages() { 4247 List<sp<AMessage> > queue = mDeferredQueue; 4248 mDeferredQueue.clear(); 4249 4250 List<sp<AMessage> >::iterator it = queue.begin(); 4251 while (it != queue.end()) { 4252 onMessageReceived(*it++); 4253 } 4254} 4255 4256// static 4257bool ACodec::describeDefaultColorFormat(DescribeColorFormat2Params ¶ms) { 4258 MediaImage2 &image = params.sMediaImage; 4259 memset(&image, 0, sizeof(image)); 4260 4261 image.mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN; 4262 image.mNumPlanes = 0; 4263 4264 const OMX_COLOR_FORMATTYPE fmt = params.eColorFormat; 4265 image.mWidth = params.nFrameWidth; 4266 image.mHeight = params.nFrameHeight; 4267 4268 // only supporting YUV420 4269 if (fmt != OMX_COLOR_FormatYUV420Planar && 4270 fmt != OMX_COLOR_FormatYUV420PackedPlanar && 4271 fmt != OMX_COLOR_FormatYUV420SemiPlanar && 4272 fmt != OMX_COLOR_FormatYUV420PackedSemiPlanar && 4273 fmt != (OMX_COLOR_FORMATTYPE)HAL_PIXEL_FORMAT_YV12) { 4274 ALOGW("do not know color format 0x%x = %d", fmt, fmt); 4275 return false; 4276 } 4277 4278 // TEMPORARY FIX for some vendors that advertise sliceHeight as 0 4279 if (params.nStride != 0 && params.nSliceHeight == 0) { 4280 ALOGW("using sliceHeight=%u instead of what codec advertised (=0)", 4281 params.nFrameHeight); 4282 params.nSliceHeight = params.nFrameHeight; 4283 } 4284 4285 // we need stride and slice-height to be non-zero and sensible. These values were chosen to 4286 // prevent integer overflows further down the line, and do not indicate support for 4287 // 32kx32k video. 4288 if (params.nStride == 0 || params.nSliceHeight == 0 4289 || params.nStride > 32768 || params.nSliceHeight > 32768) { 4290 ALOGW("cannot describe color format 0x%x = %d with stride=%u and sliceHeight=%u", 4291 fmt, fmt, params.nStride, params.nSliceHeight); 4292 return false; 4293 } 4294 4295 // set-up YUV format 4296 image.mType = MediaImage2::MEDIA_IMAGE_TYPE_YUV; 4297 image.mNumPlanes = 3; 4298 image.mBitDepth = 8; 4299 image.mBitDepthAllocated = 8; 4300 image.mPlane[image.Y].mOffset = 0; 4301 image.mPlane[image.Y].mColInc = 1; 4302 image.mPlane[image.Y].mRowInc = params.nStride; 4303 image.mPlane[image.Y].mHorizSubsampling = 1; 4304 image.mPlane[image.Y].mVertSubsampling = 1; 4305 4306 switch ((int)fmt) { 4307 case HAL_PIXEL_FORMAT_YV12: 4308 if (params.bUsingNativeBuffers) { 4309 size_t ystride = align(params.nStride, 16); 4310 size_t cstride = align(params.nStride / 2, 16); 4311 image.mPlane[image.Y].mRowInc = ystride; 4312 4313 image.mPlane[image.V].mOffset = ystride * params.nSliceHeight; 4314 image.mPlane[image.V].mColInc = 1; 4315 image.mPlane[image.V].mRowInc = cstride; 4316 image.mPlane[image.V].mHorizSubsampling = 2; 4317 image.mPlane[image.V].mVertSubsampling = 2; 4318 4319 image.mPlane[image.U].mOffset = image.mPlane[image.V].mOffset 4320 + (cstride * params.nSliceHeight / 2); 4321 image.mPlane[image.U].mColInc = 1; 4322 image.mPlane[image.U].mRowInc = cstride; 4323 image.mPlane[image.U].mHorizSubsampling = 2; 4324 image.mPlane[image.U].mVertSubsampling = 2; 4325 break; 4326 } else { 4327 // fall through as YV12 is used for YUV420Planar by some codecs 4328 } 4329 4330 case OMX_COLOR_FormatYUV420Planar: 4331 case OMX_COLOR_FormatYUV420PackedPlanar: 4332 image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight; 4333 image.mPlane[image.U].mColInc = 1; 4334 image.mPlane[image.U].mRowInc = params.nStride / 2; 4335 image.mPlane[image.U].mHorizSubsampling = 2; 4336 image.mPlane[image.U].mVertSubsampling = 2; 4337 4338 image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset 4339 + (params.nStride * params.nSliceHeight / 4); 4340 image.mPlane[image.V].mColInc = 1; 4341 image.mPlane[image.V].mRowInc = params.nStride / 2; 4342 image.mPlane[image.V].mHorizSubsampling = 2; 4343 image.mPlane[image.V].mVertSubsampling = 2; 4344 break; 4345 4346 case OMX_COLOR_FormatYUV420SemiPlanar: 4347 // FIXME: NV21 for sw-encoder, NV12 for decoder and hw-encoder 4348 case OMX_COLOR_FormatYUV420PackedSemiPlanar: 4349 // NV12 4350 image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight; 4351 image.mPlane[image.U].mColInc = 2; 4352 image.mPlane[image.U].mRowInc = params.nStride; 4353 image.mPlane[image.U].mHorizSubsampling = 2; 4354 image.mPlane[image.U].mVertSubsampling = 2; 4355 4356 image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset + 1; 4357 image.mPlane[image.V].mColInc = 2; 4358 image.mPlane[image.V].mRowInc = params.nStride; 4359 image.mPlane[image.V].mHorizSubsampling = 2; 4360 image.mPlane[image.V].mVertSubsampling = 2; 4361 break; 4362 4363 default: 4364 TRESPASS(); 4365 } 4366 return true; 4367} 4368 4369// static 4370bool ACodec::describeColorFormat( 4371 const sp<IOMX> &omx, IOMX::node_id node, 4372 DescribeColorFormat2Params &describeParams) 4373{ 4374 OMX_INDEXTYPE describeColorFormatIndex; 4375 if (omx->getExtensionIndex( 4376 node, "OMX.google.android.index.describeColorFormat", 4377 &describeColorFormatIndex) == OK) { 4378 DescribeColorFormatParams describeParamsV1(describeParams); 4379 if (omx->getParameter( 4380 node, describeColorFormatIndex, 4381 &describeParamsV1, sizeof(describeParamsV1)) == OK) { 4382 describeParams.initFromV1(describeParamsV1); 4383 return describeParams.sMediaImage.mType != MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN; 4384 } 4385 } else if (omx->getExtensionIndex( 4386 node, "OMX.google.android.index.describeColorFormat2", &describeColorFormatIndex) == OK 4387 && omx->getParameter( 4388 node, describeColorFormatIndex, &describeParams, sizeof(describeParams)) == OK) { 4389 return describeParams.sMediaImage.mType != MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN; 4390 } 4391 4392 return describeDefaultColorFormat(describeParams); 4393} 4394 4395// static 4396bool ACodec::isFlexibleColorFormat( 4397 const sp<IOMX> &omx, IOMX::node_id node, 4398 uint32_t colorFormat, bool usingNativeBuffers, OMX_U32 *flexibleEquivalent) { 4399 DescribeColorFormat2Params describeParams; 4400 InitOMXParams(&describeParams); 4401 describeParams.eColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat; 4402 // reasonable dummy values 4403 describeParams.nFrameWidth = 128; 4404 describeParams.nFrameHeight = 128; 4405 describeParams.nStride = 128; 4406 describeParams.nSliceHeight = 128; 4407 describeParams.bUsingNativeBuffers = (OMX_BOOL)usingNativeBuffers; 4408 4409 CHECK(flexibleEquivalent != NULL); 4410 4411 if (!describeColorFormat(omx, node, describeParams)) { 4412 return false; 4413 } 4414 4415 const MediaImage2 &img = describeParams.sMediaImage; 4416 if (img.mType == MediaImage2::MEDIA_IMAGE_TYPE_YUV) { 4417 if (img.mNumPlanes != 3 4418 || img.mPlane[img.Y].mHorizSubsampling != 1 4419 || img.mPlane[img.Y].mVertSubsampling != 1) { 4420 return false; 4421 } 4422 4423 // YUV 420 4424 if (img.mPlane[img.U].mHorizSubsampling == 2 4425 && img.mPlane[img.U].mVertSubsampling == 2 4426 && img.mPlane[img.V].mHorizSubsampling == 2 4427 && img.mPlane[img.V].mVertSubsampling == 2) { 4428 // possible flexible YUV420 format 4429 if (img.mBitDepth <= 8) { 4430 *flexibleEquivalent = OMX_COLOR_FormatYUV420Flexible; 4431 return true; 4432 } 4433 } 4434 } 4435 return false; 4436} 4437 4438status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> ¬ify) { 4439 const char *niceIndex = portIndex == kPortIndexInput ? "input" : "output"; 4440 OMX_PARAM_PORTDEFINITIONTYPE def; 4441 InitOMXParams(&def); 4442 def.nPortIndex = portIndex; 4443 4444 status_t err = mOMX->getParameter(mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); 4445 if (err != OK) { 4446 return err; 4447 } 4448 4449 if (def.eDir != (portIndex == kPortIndexOutput ? OMX_DirOutput : OMX_DirInput)) { 4450 ALOGE("unexpected dir: %s(%d) on %s port", asString(def.eDir), def.eDir, niceIndex); 4451 return BAD_VALUE; 4452 } 4453 4454 switch (def.eDomain) { 4455 case OMX_PortDomainVideo: 4456 { 4457 OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video; 4458 switch ((int)videoDef->eCompressionFormat) { 4459 case OMX_VIDEO_CodingUnused: 4460 { 4461 CHECK(mIsEncoder ^ (portIndex == kPortIndexOutput)); 4462 notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW); 4463 4464 notify->setInt32("stride", videoDef->nStride); 4465 notify->setInt32("slice-height", videoDef->nSliceHeight); 4466 notify->setInt32("color-format", videoDef->eColorFormat); 4467 4468 if (mNativeWindow == NULL) { 4469 DescribeColorFormat2Params describeParams; 4470 InitOMXParams(&describeParams); 4471 describeParams.eColorFormat = videoDef->eColorFormat; 4472 describeParams.nFrameWidth = videoDef->nFrameWidth; 4473 describeParams.nFrameHeight = videoDef->nFrameHeight; 4474 describeParams.nStride = videoDef->nStride; 4475 describeParams.nSliceHeight = videoDef->nSliceHeight; 4476 describeParams.bUsingNativeBuffers = OMX_FALSE; 4477 4478 if (describeColorFormat(mOMX, mNode, describeParams)) { 4479 notify->setBuffer( 4480 "image-data", 4481 ABuffer::CreateAsCopy( 4482 &describeParams.sMediaImage, 4483 sizeof(describeParams.sMediaImage))); 4484 4485 MediaImage2 &img = describeParams.sMediaImage; 4486 MediaImage2::PlaneInfo *plane = img.mPlane; 4487 ALOGV("[%s] MediaImage { F(%ux%u) @%u+%d+%d @%u+%d+%d @%u+%d+%d }", 4488 mComponentName.c_str(), img.mWidth, img.mHeight, 4489 plane[0].mOffset, plane[0].mColInc, plane[0].mRowInc, 4490 plane[1].mOffset, plane[1].mColInc, plane[1].mRowInc, 4491 plane[2].mOffset, plane[2].mColInc, plane[2].mRowInc); 4492 } 4493 } 4494 4495 int32_t width = (int32_t)videoDef->nFrameWidth; 4496 int32_t height = (int32_t)videoDef->nFrameHeight; 4497 4498 if (portIndex == kPortIndexOutput) { 4499 OMX_CONFIG_RECTTYPE rect; 4500 InitOMXParams(&rect); 4501 rect.nPortIndex = portIndex; 4502 4503 if (mOMX->getConfig( 4504 mNode, 4505 (portIndex == kPortIndexOutput ? 4506 OMX_IndexConfigCommonOutputCrop : 4507 OMX_IndexConfigCommonInputCrop), 4508 &rect, sizeof(rect)) != OK) { 4509 rect.nLeft = 0; 4510 rect.nTop = 0; 4511 rect.nWidth = videoDef->nFrameWidth; 4512 rect.nHeight = videoDef->nFrameHeight; 4513 } 4514 4515 if (rect.nLeft < 0 || 4516 rect.nTop < 0 || 4517 rect.nLeft + rect.nWidth > videoDef->nFrameWidth || 4518 rect.nTop + rect.nHeight > videoDef->nFrameHeight) { 4519 ALOGE("Wrong cropped rect (%d, %d) - (%u, %u) vs. frame (%u, %u)", 4520 rect.nLeft, rect.nTop, 4521 rect.nLeft + rect.nWidth, rect.nTop + rect.nHeight, 4522 videoDef->nFrameWidth, videoDef->nFrameHeight); 4523 return BAD_VALUE; 4524 } 4525 4526 notify->setRect( 4527 "crop", 4528 rect.nLeft, 4529 rect.nTop, 4530 rect.nLeft + rect.nWidth - 1, 4531 rect.nTop + rect.nHeight - 1); 4532 4533 width = rect.nWidth; 4534 height = rect.nHeight; 4535 4536 android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN; 4537 (void)getColorAspectsAndDataSpaceForVideoDecoder( 4538 width, height, mConfigFormat, notify, 4539 mUsingNativeWindow ? &dataSpace : NULL); 4540 if (mUsingNativeWindow) { 4541 notify->setInt32("android._dataspace", dataSpace); 4542 } 4543 } else { 4544 (void)getInputColorAspectsForVideoEncoder(notify); 4545 } 4546 4547 break; 4548 } 4549 4550 case OMX_VIDEO_CodingVP8: 4551 case OMX_VIDEO_CodingVP9: 4552 { 4553 OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type; 4554 InitOMXParams(&vp8type); 4555 vp8type.nPortIndex = kPortIndexOutput; 4556 status_t err = mOMX->getParameter( 4557 mNode, 4558 (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder, 4559 &vp8type, 4560 sizeof(vp8type)); 4561 4562 if (err == OK) { 4563 AString tsSchema = "none"; 4564 if (vp8type.eTemporalPattern 4565 == OMX_VIDEO_VPXTemporalLayerPatternWebRTC) { 4566 switch (vp8type.nTemporalLayerCount) { 4567 case 1: 4568 { 4569 tsSchema = "webrtc.vp8.1-layer"; 4570 break; 4571 } 4572 case 2: 4573 { 4574 tsSchema = "webrtc.vp8.2-layer"; 4575 break; 4576 } 4577 case 3: 4578 { 4579 tsSchema = "webrtc.vp8.3-layer"; 4580 break; 4581 } 4582 default: 4583 { 4584 break; 4585 } 4586 } 4587 } 4588 notify->setString("ts-schema", tsSchema); 4589 } 4590 // Fall through to set up mime. 4591 } 4592 4593 default: 4594 { 4595 if (mIsEncoder ^ (portIndex == kPortIndexOutput)) { 4596 // should be CodingUnused 4597 ALOGE("Raw port video compression format is %s(%d)", 4598 asString(videoDef->eCompressionFormat), 4599 videoDef->eCompressionFormat); 4600 return BAD_VALUE; 4601 } 4602 AString mime; 4603 if (GetMimeTypeForVideoCoding( 4604 videoDef->eCompressionFormat, &mime) != OK) { 4605 notify->setString("mime", "application/octet-stream"); 4606 } else { 4607 notify->setString("mime", mime.c_str()); 4608 } 4609 uint32_t intraRefreshPeriod = 0; 4610 if (mIsEncoder && getIntraRefreshPeriod(&intraRefreshPeriod) == OK 4611 && intraRefreshPeriod > 0) { 4612 notify->setInt32("intra-refresh-period", intraRefreshPeriod); 4613 } 4614 break; 4615 } 4616 } 4617 notify->setInt32("width", videoDef->nFrameWidth); 4618 notify->setInt32("height", videoDef->nFrameHeight); 4619 ALOGV("[%s] %s format is %s", mComponentName.c_str(), 4620 portIndex == kPortIndexInput ? "input" : "output", 4621 notify->debugString().c_str()); 4622 4623 break; 4624 } 4625 4626 case OMX_PortDomainAudio: 4627 { 4628 OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio; 4629 4630 switch ((int)audioDef->eEncoding) { 4631 case OMX_AUDIO_CodingPCM: 4632 { 4633 OMX_AUDIO_PARAM_PCMMODETYPE params; 4634 InitOMXParams(¶ms); 4635 params.nPortIndex = portIndex; 4636 4637 err = mOMX->getParameter( 4638 mNode, OMX_IndexParamAudioPcm, ¶ms, sizeof(params)); 4639 if (err != OK) { 4640 return err; 4641 } 4642 4643 if (params.nChannels <= 0 4644 || (params.nChannels != 1 && !params.bInterleaved) 4645 || params.nBitPerSample != 16u 4646 || params.eNumData != OMX_NumericalDataSigned 4647 || params.ePCMMode != OMX_AUDIO_PCMModeLinear) { 4648 ALOGE("unsupported PCM port: %u channels%s, %u-bit, %s(%d), %s(%d) mode ", 4649 params.nChannels, 4650 params.bInterleaved ? " interleaved" : "", 4651 params.nBitPerSample, 4652 asString(params.eNumData), params.eNumData, 4653 asString(params.ePCMMode), params.ePCMMode); 4654 return FAILED_TRANSACTION; 4655 } 4656 4657 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW); 4658 notify->setInt32("channel-count", params.nChannels); 4659 notify->setInt32("sample-rate", params.nSamplingRate); 4660 4661 if (mChannelMaskPresent) { 4662 notify->setInt32("channel-mask", mChannelMask); 4663 } 4664 break; 4665 } 4666 4667 case OMX_AUDIO_CodingAAC: 4668 { 4669 OMX_AUDIO_PARAM_AACPROFILETYPE params; 4670 InitOMXParams(¶ms); 4671 params.nPortIndex = portIndex; 4672 4673 err = mOMX->getParameter( 4674 mNode, OMX_IndexParamAudioAac, ¶ms, sizeof(params)); 4675 if (err != OK) { 4676 return err; 4677 } 4678 4679 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC); 4680 notify->setInt32("channel-count", params.nChannels); 4681 notify->setInt32("sample-rate", params.nSampleRate); 4682 break; 4683 } 4684 4685 case OMX_AUDIO_CodingAMR: 4686 { 4687 OMX_AUDIO_PARAM_AMRTYPE params; 4688 InitOMXParams(¶ms); 4689 params.nPortIndex = portIndex; 4690 4691 err = mOMX->getParameter( 4692 mNode, OMX_IndexParamAudioAmr, ¶ms, sizeof(params)); 4693 if (err != OK) { 4694 return err; 4695 } 4696 4697 notify->setInt32("channel-count", 1); 4698 if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) { 4699 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_WB); 4700 notify->setInt32("sample-rate", 16000); 4701 } else { 4702 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB); 4703 notify->setInt32("sample-rate", 8000); 4704 } 4705 break; 4706 } 4707 4708 case OMX_AUDIO_CodingFLAC: 4709 { 4710 OMX_AUDIO_PARAM_FLACTYPE params; 4711 InitOMXParams(¶ms); 4712 params.nPortIndex = portIndex; 4713 4714 err = mOMX->getParameter( 4715 mNode, OMX_IndexParamAudioFlac, ¶ms, sizeof(params)); 4716 if (err != OK) { 4717 return err; 4718 } 4719 4720 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC); 4721 notify->setInt32("channel-count", params.nChannels); 4722 notify->setInt32("sample-rate", params.nSampleRate); 4723 break; 4724 } 4725 4726 case OMX_AUDIO_CodingMP3: 4727 { 4728 OMX_AUDIO_PARAM_MP3TYPE params; 4729 InitOMXParams(¶ms); 4730 params.nPortIndex = portIndex; 4731 4732 err = mOMX->getParameter( 4733 mNode, OMX_IndexParamAudioMp3, ¶ms, sizeof(params)); 4734 if (err != OK) { 4735 return err; 4736 } 4737 4738 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MPEG); 4739 notify->setInt32("channel-count", params.nChannels); 4740 notify->setInt32("sample-rate", params.nSampleRate); 4741 break; 4742 } 4743 4744 case OMX_AUDIO_CodingVORBIS: 4745 { 4746 OMX_AUDIO_PARAM_VORBISTYPE params; 4747 InitOMXParams(¶ms); 4748 params.nPortIndex = portIndex; 4749 4750 err = mOMX->getParameter( 4751 mNode, OMX_IndexParamAudioVorbis, ¶ms, sizeof(params)); 4752 if (err != OK) { 4753 return err; 4754 } 4755 4756 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_VORBIS); 4757 notify->setInt32("channel-count", params.nChannels); 4758 notify->setInt32("sample-rate", params.nSampleRate); 4759 break; 4760 } 4761 4762 case OMX_AUDIO_CodingAndroidAC3: 4763 { 4764 OMX_AUDIO_PARAM_ANDROID_AC3TYPE params; 4765 InitOMXParams(¶ms); 4766 params.nPortIndex = portIndex; 4767 4768 err = mOMX->getParameter( 4769 mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, 4770 ¶ms, sizeof(params)); 4771 if (err != OK) { 4772 return err; 4773 } 4774 4775 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3); 4776 notify->setInt32("channel-count", params.nChannels); 4777 notify->setInt32("sample-rate", params.nSampleRate); 4778 break; 4779 } 4780 4781 case OMX_AUDIO_CodingAndroidEAC3: 4782 { 4783 OMX_AUDIO_PARAM_ANDROID_EAC3TYPE params; 4784 InitOMXParams(¶ms); 4785 params.nPortIndex = portIndex; 4786 4787 err = mOMX->getParameter( 4788 mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, 4789 ¶ms, sizeof(params)); 4790 if (err != OK) { 4791 return err; 4792 } 4793 4794 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_EAC3); 4795 notify->setInt32("channel-count", params.nChannels); 4796 notify->setInt32("sample-rate", params.nSampleRate); 4797 break; 4798 } 4799 4800 case OMX_AUDIO_CodingAndroidOPUS: 4801 { 4802 OMX_AUDIO_PARAM_ANDROID_OPUSTYPE params; 4803 InitOMXParams(¶ms); 4804 params.nPortIndex = portIndex; 4805 4806 err = mOMX->getParameter( 4807 mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus, 4808 ¶ms, sizeof(params)); 4809 if (err != OK) { 4810 return err; 4811 } 4812 4813 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_OPUS); 4814 notify->setInt32("channel-count", params.nChannels); 4815 notify->setInt32("sample-rate", params.nSampleRate); 4816 break; 4817 } 4818 4819 case OMX_AUDIO_CodingG711: 4820 { 4821 OMX_AUDIO_PARAM_PCMMODETYPE params; 4822 InitOMXParams(¶ms); 4823 params.nPortIndex = portIndex; 4824 4825 err = mOMX->getParameter( 4826 mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioPcm, ¶ms, sizeof(params)); 4827 if (err != OK) { 4828 return err; 4829 } 4830 4831 const char *mime = NULL; 4832 if (params.ePCMMode == OMX_AUDIO_PCMModeMULaw) { 4833 mime = MEDIA_MIMETYPE_AUDIO_G711_MLAW; 4834 } else if (params.ePCMMode == OMX_AUDIO_PCMModeALaw) { 4835 mime = MEDIA_MIMETYPE_AUDIO_G711_ALAW; 4836 } else { // params.ePCMMode == OMX_AUDIO_PCMModeLinear 4837 mime = MEDIA_MIMETYPE_AUDIO_RAW; 4838 } 4839 notify->setString("mime", mime); 4840 notify->setInt32("channel-count", params.nChannels); 4841 notify->setInt32("sample-rate", params.nSamplingRate); 4842 break; 4843 } 4844 4845 case OMX_AUDIO_CodingGSMFR: 4846 { 4847 OMX_AUDIO_PARAM_PCMMODETYPE params; 4848 InitOMXParams(¶ms); 4849 params.nPortIndex = portIndex; 4850 4851 err = mOMX->getParameter( 4852 mNode, OMX_IndexParamAudioPcm, ¶ms, sizeof(params)); 4853 if (err != OK) { 4854 return err; 4855 } 4856 4857 notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MSGSM); 4858 notify->setInt32("channel-count", params.nChannels); 4859 notify->setInt32("sample-rate", params.nSamplingRate); 4860 break; 4861 } 4862 4863 default: 4864 ALOGE("Unsupported audio coding: %s(%d)\n", 4865 asString(audioDef->eEncoding), audioDef->eEncoding); 4866 return BAD_TYPE; 4867 } 4868 break; 4869 } 4870 4871 default: 4872 ALOGE("Unsupported domain: %s(%d)", asString(def.eDomain), def.eDomain); 4873 return BAD_TYPE; 4874 } 4875 4876 return OK; 4877} 4878 4879void ACodec::onDataSpaceChanged(android_dataspace dataSpace, const ColorAspects &aspects) { 4880 // aspects are normally communicated in ColorAspects 4881 int32_t range, standard, transfer; 4882 convertCodecColorAspectsToPlatformAspects(aspects, &range, &standard, &transfer); 4883 4884 // if some aspects are unspecified, use dataspace fields 4885 if (range != 0) { 4886 range = (dataSpace & HAL_DATASPACE_RANGE_MASK) >> HAL_DATASPACE_RANGE_SHIFT; 4887 } 4888 if (standard != 0) { 4889 standard = (dataSpace & HAL_DATASPACE_STANDARD_MASK) >> HAL_DATASPACE_STANDARD_SHIFT; 4890 } 4891 if (transfer != 0) { 4892 transfer = (dataSpace & HAL_DATASPACE_TRANSFER_MASK) >> HAL_DATASPACE_TRANSFER_SHIFT; 4893 } 4894 4895 mOutputFormat = mOutputFormat->dup(); // trigger an output format changed event 4896 if (range != 0) { 4897 mOutputFormat->setInt32("color-range", range); 4898 } 4899 if (standard != 0) { 4900 mOutputFormat->setInt32("color-standard", standard); 4901 } 4902 if (transfer != 0) { 4903 mOutputFormat->setInt32("color-transfer", transfer); 4904 } 4905 4906 ALOGD("dataspace changed to %#x (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) " 4907 "(R:%d(%s), S:%d(%s), T:%d(%s))", 4908 dataSpace, 4909 aspects.mRange, asString(aspects.mRange), 4910 aspects.mPrimaries, asString(aspects.mPrimaries), 4911 aspects.mMatrixCoeffs, asString(aspects.mMatrixCoeffs), 4912 aspects.mTransfer, asString(aspects.mTransfer), 4913 range, asString((ColorRange)range), 4914 standard, asString((ColorStandard)standard), 4915 transfer, asString((ColorTransfer)transfer)); 4916} 4917 4918void ACodec::onOutputFormatChanged() { 4919 // store new output format 4920 mOutputFormat = mBaseOutputFormat->dup(); 4921 4922 if (getPortFormat(kPortIndexOutput, mOutputFormat) != OK) { 4923 ALOGE("[%s] Failed to get port format to send format change", mComponentName.c_str()); 4924 return; 4925 } 4926 4927 if (mTunneled) { 4928 sendFormatChange(); 4929 } 4930} 4931 4932void ACodec::addKeyFormatChangesToRenderBufferNotification(sp<AMessage> ¬ify) { 4933 AString mime; 4934 CHECK(mOutputFormat->findString("mime", &mime)); 4935 4936 if (mime == MEDIA_MIMETYPE_VIDEO_RAW && mNativeWindow != NULL) { 4937 // notify renderer of the crop change and dataspace change 4938 // NOTE: native window uses extended right-bottom coordinate 4939 int32_t left, top, right, bottom; 4940 if (mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) { 4941 notify->setRect("crop", left, top, right + 1, bottom + 1); 4942 } 4943 4944 int32_t dataSpace; 4945 if (mOutputFormat->findInt32("android._dataspace", &dataSpace)) { 4946 notify->setInt32("dataspace", dataSpace); 4947 } 4948 } 4949} 4950 4951void ACodec::sendFormatChange() { 4952 AString mime; 4953 CHECK(mOutputFormat->findString("mime", &mime)); 4954 4955 if (mime == MEDIA_MIMETYPE_AUDIO_RAW && (mEncoderDelay || mEncoderPadding)) { 4956 int32_t channelCount; 4957 CHECK(mOutputFormat->findInt32("channel-count", &channelCount)); 4958 if (mSkipCutBuffer != NULL) { 4959 size_t prevbufsize = mSkipCutBuffer->size(); 4960 if (prevbufsize != 0) { 4961 ALOGW("Replacing SkipCutBuffer holding %zu bytes", prevbufsize); 4962 } 4963 } 4964 mSkipCutBuffer = new SkipCutBuffer(mEncoderDelay, mEncoderPadding, channelCount); 4965 } 4966 4967 sp<AMessage> notify = mNotify->dup(); 4968 notify->setInt32("what", kWhatOutputFormatChanged); 4969 notify->setMessage("format", mOutputFormat); 4970 notify->post(); 4971 4972 // mLastOutputFormat is not used when tunneled; doing this just to stay consistent 4973 mLastOutputFormat = mOutputFormat; 4974} 4975 4976void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) { 4977 sp<AMessage> notify = mNotify->dup(); 4978 notify->setInt32("what", CodecBase::kWhatError); 4979 ALOGE("signalError(omxError %#x, internalError %d)", error, internalError); 4980 4981 if (internalError == UNKNOWN_ERROR) { // find better error code 4982 const status_t omxStatus = statusFromOMXError(error); 4983 if (omxStatus != 0) { 4984 internalError = omxStatus; 4985 } else { 4986 ALOGW("Invalid OMX error %#x", error); 4987 } 4988 } 4989 4990 mFatalError = true; 4991 4992 notify->setInt32("err", internalError); 4993 notify->setInt32("actionCode", ACTION_CODE_FATAL); // could translate from OMX error. 4994 notify->post(); 4995} 4996 4997//////////////////////////////////////////////////////////////////////////////// 4998 4999ACodec::PortDescription::PortDescription() { 5000} 5001 5002status_t ACodec::requestIDRFrame() { 5003 if (!mIsEncoder) { 5004 return ERROR_UNSUPPORTED; 5005 } 5006 5007 OMX_CONFIG_INTRAREFRESHVOPTYPE params; 5008 InitOMXParams(¶ms); 5009 5010 params.nPortIndex = kPortIndexOutput; 5011 params.IntraRefreshVOP = OMX_TRUE; 5012 5013 return mOMX->setConfig( 5014 mNode, 5015 OMX_IndexConfigVideoIntraVOPRefresh, 5016 ¶ms, 5017 sizeof(params)); 5018} 5019 5020void ACodec::PortDescription::addBuffer( 5021 IOMX::buffer_id id, const sp<ABuffer> &buffer, 5022 const sp<NativeHandle> &handle, const sp<RefBase> &memRef) { 5023 mBufferIDs.push_back(id); 5024 mBuffers.push_back(buffer); 5025 mHandles.push_back(handle); 5026 mMemRefs.push_back(memRef); 5027} 5028 5029size_t ACodec::PortDescription::countBuffers() { 5030 return mBufferIDs.size(); 5031} 5032 5033IOMX::buffer_id ACodec::PortDescription::bufferIDAt(size_t index) const { 5034 return mBufferIDs.itemAt(index); 5035} 5036 5037sp<ABuffer> ACodec::PortDescription::bufferAt(size_t index) const { 5038 return mBuffers.itemAt(index); 5039} 5040 5041sp<NativeHandle> ACodec::PortDescription::handleAt(size_t index) const { 5042 return mHandles.itemAt(index); 5043} 5044 5045sp<RefBase> ACodec::PortDescription::memRefAt(size_t index) const { 5046 return mMemRefs.itemAt(index); 5047} 5048 5049//////////////////////////////////////////////////////////////////////////////// 5050 5051ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState) 5052 : AState(parentState), 5053 mCodec(codec) { 5054} 5055 5056ACodec::BaseState::PortMode ACodec::BaseState::getPortMode( 5057 OMX_U32 /* portIndex */) { 5058 return KEEP_BUFFERS; 5059} 5060 5061bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) { 5062 switch (msg->what()) { 5063 case kWhatInputBufferFilled: 5064 { 5065 onInputBufferFilled(msg); 5066 break; 5067 } 5068 5069 case kWhatOutputBufferDrained: 5070 { 5071 onOutputBufferDrained(msg); 5072 break; 5073 } 5074 5075 case ACodec::kWhatOMXMessageList: 5076 { 5077 return checkOMXMessage(msg) ? onOMXMessageList(msg) : true; 5078 } 5079 5080 case ACodec::kWhatOMXMessageItem: 5081 { 5082 // no need to check as we already did it for kWhatOMXMessageList 5083 return onOMXMessage(msg); 5084 } 5085 5086 case ACodec::kWhatOMXMessage: 5087 { 5088 return checkOMXMessage(msg) ? onOMXMessage(msg) : true; 5089 } 5090 5091 case ACodec::kWhatSetSurface: 5092 { 5093 sp<AReplyToken> replyID; 5094 CHECK(msg->senderAwaitsResponse(&replyID)); 5095 5096 sp<RefBase> obj; 5097 CHECK(msg->findObject("surface", &obj)); 5098 5099 status_t err = mCodec->handleSetSurface(static_cast<Surface *>(obj.get())); 5100 5101 sp<AMessage> response = new AMessage; 5102 response->setInt32("err", err); 5103 response->postReply(replyID); 5104 break; 5105 } 5106 5107 case ACodec::kWhatCreateInputSurface: 5108 case ACodec::kWhatSetInputSurface: 5109 case ACodec::kWhatSignalEndOfInputStream: 5110 { 5111 // This may result in an app illegal state exception. 5112 ALOGE("Message 0x%x was not handled", msg->what()); 5113 mCodec->signalError(OMX_ErrorUndefined, INVALID_OPERATION); 5114 return true; 5115 } 5116 5117 case ACodec::kWhatOMXDied: 5118 { 5119 // This will result in kFlagSawMediaServerDie handling in MediaCodec. 5120 ALOGE("OMX/mediaserver died, signalling error!"); 5121 mCodec->signalError(OMX_ErrorResourcesLost, DEAD_OBJECT); 5122 break; 5123 } 5124 5125 case ACodec::kWhatReleaseCodecInstance: 5126 { 5127 ALOGI("[%s] forcing the release of codec", 5128 mCodec->mComponentName.c_str()); 5129 status_t err = mCodec->mOMX->freeNode(mCodec->mNode); 5130 ALOGE_IF("[%s] failed to release codec instance: err=%d", 5131 mCodec->mComponentName.c_str(), err); 5132 sp<AMessage> notify = mCodec->mNotify->dup(); 5133 notify->setInt32("what", CodecBase::kWhatShutdownCompleted); 5134 notify->post(); 5135 break; 5136 } 5137 5138 default: 5139 return false; 5140 } 5141 5142 return true; 5143} 5144 5145bool ACodec::BaseState::checkOMXMessage(const sp<AMessage> &msg) { 5146 // there is a possibility that this is an outstanding message for a 5147 // codec that we have already destroyed 5148 if (mCodec->mNode == 0) { 5149 ALOGI("ignoring message as already freed component: %s", 5150 msg->debugString().c_str()); 5151 return false; 5152 } 5153 5154 IOMX::node_id nodeID; 5155 CHECK(msg->findInt32("node", (int32_t*)&nodeID)); 5156 if (nodeID != mCodec->mNode) { 5157 ALOGE("Unexpected message for nodeID: %u, should have been %u", nodeID, mCodec->mNode); 5158 return false; 5159 } 5160 return true; 5161} 5162 5163bool ACodec::BaseState::onOMXMessageList(const sp<AMessage> &msg) { 5164 sp<RefBase> obj; 5165 CHECK(msg->findObject("messages", &obj)); 5166 sp<MessageList> msgList = static_cast<MessageList *>(obj.get()); 5167 5168 bool receivedRenderedEvents = false; 5169 for (std::list<sp<AMessage>>::const_iterator it = msgList->getList().cbegin(); 5170 it != msgList->getList().cend(); ++it) { 5171 (*it)->setWhat(ACodec::kWhatOMXMessageItem); 5172 mCodec->handleMessage(*it); 5173 int32_t type; 5174 CHECK((*it)->findInt32("type", &type)); 5175 if (type == omx_message::FRAME_RENDERED) { 5176 receivedRenderedEvents = true; 5177 } 5178 } 5179 5180 if (receivedRenderedEvents) { 5181 // NOTE: all buffers are rendered in this case 5182 mCodec->notifyOfRenderedFrames(); 5183 } 5184 return true; 5185} 5186 5187bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) { 5188 int32_t type; 5189 CHECK(msg->findInt32("type", &type)); 5190 5191 switch (type) { 5192 case omx_message::EVENT: 5193 { 5194 int32_t event, data1, data2; 5195 CHECK(msg->findInt32("event", &event)); 5196 CHECK(msg->findInt32("data1", &data1)); 5197 CHECK(msg->findInt32("data2", &data2)); 5198 5199 if (event == OMX_EventCmdComplete 5200 && data1 == OMX_CommandFlush 5201 && data2 == (int32_t)OMX_ALL) { 5202 // Use of this notification is not consistent across 5203 // implementations. We'll drop this notification and rely 5204 // on flush-complete notifications on the individual port 5205 // indices instead. 5206 5207 return true; 5208 } 5209 5210 return onOMXEvent( 5211 static_cast<OMX_EVENTTYPE>(event), 5212 static_cast<OMX_U32>(data1), 5213 static_cast<OMX_U32>(data2)); 5214 } 5215 5216 case omx_message::EMPTY_BUFFER_DONE: 5217 { 5218 IOMX::buffer_id bufferID; 5219 int32_t fenceFd; 5220 5221 CHECK(msg->findInt32("buffer", (int32_t*)&bufferID)); 5222 CHECK(msg->findInt32("fence_fd", &fenceFd)); 5223 5224 return onOMXEmptyBufferDone(bufferID, fenceFd); 5225 } 5226 5227 case omx_message::FILL_BUFFER_DONE: 5228 { 5229 IOMX::buffer_id bufferID; 5230 CHECK(msg->findInt32("buffer", (int32_t*)&bufferID)); 5231 5232 int32_t rangeOffset, rangeLength, flags, fenceFd; 5233 int64_t timeUs; 5234 5235 CHECK(msg->findInt32("range_offset", &rangeOffset)); 5236 CHECK(msg->findInt32("range_length", &rangeLength)); 5237 CHECK(msg->findInt32("flags", &flags)); 5238 CHECK(msg->findInt64("timestamp", &timeUs)); 5239 CHECK(msg->findInt32("fence_fd", &fenceFd)); 5240 5241 return onOMXFillBufferDone( 5242 bufferID, 5243 (size_t)rangeOffset, (size_t)rangeLength, 5244 (OMX_U32)flags, 5245 timeUs, 5246 fenceFd); 5247 } 5248 5249 case omx_message::FRAME_RENDERED: 5250 { 5251 int64_t mediaTimeUs, systemNano; 5252 5253 CHECK(msg->findInt64("media_time_us", &mediaTimeUs)); 5254 CHECK(msg->findInt64("system_nano", &systemNano)); 5255 5256 return onOMXFrameRendered( 5257 mediaTimeUs, systemNano); 5258 } 5259 5260 default: 5261 ALOGE("Unexpected message type: %d", type); 5262 return false; 5263 } 5264} 5265 5266bool ACodec::BaseState::onOMXFrameRendered( 5267 int64_t mediaTimeUs __unused, nsecs_t systemNano __unused) { 5268 // ignore outside of Executing and PortSettingsChanged states 5269 return true; 5270} 5271 5272bool ACodec::BaseState::onOMXEvent( 5273 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 5274 if (event == OMX_EventDataSpaceChanged) { 5275 ColorAspects aspects; 5276 aspects.mRange = (ColorAspects::Range)((data2 >> 24) & 0xFF); 5277 aspects.mPrimaries = (ColorAspects::Primaries)((data2 >> 16) & 0xFF); 5278 aspects.mMatrixCoeffs = (ColorAspects::MatrixCoeffs)((data2 >> 8) & 0xFF); 5279 aspects.mTransfer = (ColorAspects::Transfer)(data2 & 0xFF); 5280 5281 mCodec->onDataSpaceChanged((android_dataspace)data1, aspects); 5282 return true; 5283 } 5284 5285 if (event != OMX_EventError) { 5286 ALOGV("[%s] EVENT(%d, 0x%08x, 0x%08x)", 5287 mCodec->mComponentName.c_str(), event, data1, data2); 5288 5289 return false; 5290 } 5291 5292 ALOGE("[%s] ERROR(0x%08x)", mCodec->mComponentName.c_str(), data1); 5293 5294 // verify OMX component sends back an error we expect. 5295 OMX_ERRORTYPE omxError = (OMX_ERRORTYPE)data1; 5296 if (!isOMXError(omxError)) { 5297 ALOGW("Invalid OMX error %#x", omxError); 5298 omxError = OMX_ErrorUndefined; 5299 } 5300 mCodec->signalError(omxError); 5301 5302 return true; 5303} 5304 5305bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID, int fenceFd) { 5306 ALOGV("[%s] onOMXEmptyBufferDone %u", 5307 mCodec->mComponentName.c_str(), bufferID); 5308 5309 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID); 5310 BufferInfo::Status status = BufferInfo::getSafeStatus(info); 5311 if (status != BufferInfo::OWNED_BY_COMPONENT) { 5312 ALOGE("Wrong ownership in EBD: %s(%d) buffer #%u", _asString(status), status, bufferID); 5313 mCodec->dumpBuffers(kPortIndexInput); 5314 if (fenceFd >= 0) { 5315 ::close(fenceFd); 5316 } 5317 return false; 5318 } 5319 info->mStatus = BufferInfo::OWNED_BY_US; 5320 5321 // input buffers cannot take fences, so wait for any fence now 5322 (void)mCodec->waitForFence(fenceFd, "onOMXEmptyBufferDone"); 5323 fenceFd = -1; 5324 5325 // still save fence for completeness 5326 info->setWriteFence(fenceFd, "onOMXEmptyBufferDone"); 5327 5328 // We're in "store-metadata-in-buffers" mode, the underlying 5329 // OMX component had access to data that's implicitly refcounted 5330 // by this "MediaBuffer" object. Now that the OMX component has 5331 // told us that it's done with the input buffer, we can decrement 5332 // the mediaBuffer's reference count. 5333 info->mData->setMediaBufferBase(NULL); 5334 5335 PortMode mode = getPortMode(kPortIndexInput); 5336 5337 switch (mode) { 5338 case KEEP_BUFFERS: 5339 break; 5340 5341 case RESUBMIT_BUFFERS: 5342 postFillThisBuffer(info); 5343 break; 5344 5345 case FREE_BUFFERS: 5346 default: 5347 ALOGE("SHOULD NOT REACH HERE: cannot free empty output buffers"); 5348 return false; 5349 } 5350 5351 return true; 5352} 5353 5354void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) { 5355 if (mCodec->mPortEOS[kPortIndexInput]) { 5356 return; 5357 } 5358 5359 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 5360 5361 sp<AMessage> notify = mCodec->mNotify->dup(); 5362 notify->setInt32("what", CodecBase::kWhatFillThisBuffer); 5363 notify->setInt32("buffer-id", info->mBufferID); 5364 5365 info->mData->meta()->clear(); 5366 notify->setBuffer("buffer", info->mData); 5367 5368 sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec); 5369 reply->setInt32("buffer-id", info->mBufferID); 5370 5371 notify->setMessage("reply", reply); 5372 5373 notify->post(); 5374 5375 info->mStatus = BufferInfo::OWNED_BY_UPSTREAM; 5376} 5377 5378void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) { 5379 IOMX::buffer_id bufferID; 5380 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID)); 5381 sp<ABuffer> buffer; 5382 int32_t err = OK; 5383 bool eos = false; 5384 PortMode mode = getPortMode(kPortIndexInput); 5385 5386 if (!msg->findBuffer("buffer", &buffer)) { 5387 /* these are unfilled buffers returned by client */ 5388 CHECK(msg->findInt32("err", &err)); 5389 5390 if (err == OK) { 5391 /* buffers with no errors are returned on MediaCodec.flush */ 5392 mode = KEEP_BUFFERS; 5393 } else { 5394 ALOGV("[%s] saw error %d instead of an input buffer", 5395 mCodec->mComponentName.c_str(), err); 5396 eos = true; 5397 } 5398 5399 buffer.clear(); 5400 } 5401 5402 int32_t tmp; 5403 if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) { 5404 eos = true; 5405 err = ERROR_END_OF_STREAM; 5406 } 5407 5408 BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID); 5409 BufferInfo::Status status = BufferInfo::getSafeStatus(info); 5410 if (status != BufferInfo::OWNED_BY_UPSTREAM) { 5411 ALOGE("Wrong ownership in IBF: %s(%d) buffer #%u", _asString(status), status, bufferID); 5412 mCodec->dumpBuffers(kPortIndexInput); 5413 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 5414 return; 5415 } 5416 5417 info->mStatus = BufferInfo::OWNED_BY_US; 5418 5419 switch (mode) { 5420 case KEEP_BUFFERS: 5421 { 5422 if (eos) { 5423 if (!mCodec->mPortEOS[kPortIndexInput]) { 5424 mCodec->mPortEOS[kPortIndexInput] = true; 5425 mCodec->mInputEOSResult = err; 5426 } 5427 } 5428 break; 5429 } 5430 5431 case RESUBMIT_BUFFERS: 5432 { 5433 if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) { 5434 // Do not send empty input buffer w/o EOS to the component. 5435 if (buffer->size() == 0 && !eos) { 5436 postFillThisBuffer(info); 5437 break; 5438 } 5439 5440 int64_t timeUs; 5441 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 5442 5443 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME; 5444 5445 int32_t isCSD; 5446 if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) { 5447 flags |= OMX_BUFFERFLAG_CODECCONFIG; 5448 } 5449 5450 if (eos) { 5451 flags |= OMX_BUFFERFLAG_EOS; 5452 } 5453 5454 if (buffer != info->mData) { 5455 ALOGV("[%s] Needs to copy input data for buffer %u. (%p != %p)", 5456 mCodec->mComponentName.c_str(), 5457 bufferID, 5458 buffer.get(), info->mData.get()); 5459 5460 if (buffer->size() > info->mData->capacity()) { 5461 ALOGE("data size (%zu) is greated than buffer capacity (%zu)", 5462 buffer->size(), // this is the data received 5463 info->mData->capacity()); // this is out buffer size 5464 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 5465 return; 5466 } 5467 memcpy(info->mData->data(), buffer->data(), buffer->size()); 5468 } 5469 5470 if (flags & OMX_BUFFERFLAG_CODECCONFIG) { 5471 ALOGV("[%s] calling emptyBuffer %u w/ codec specific data", 5472 mCodec->mComponentName.c_str(), bufferID); 5473 } else if (flags & OMX_BUFFERFLAG_EOS) { 5474 ALOGV("[%s] calling emptyBuffer %u w/ EOS", 5475 mCodec->mComponentName.c_str(), bufferID); 5476 } else { 5477#if TRACK_BUFFER_TIMING 5478 ALOGI("[%s] calling emptyBuffer %u w/ time %lld us", 5479 mCodec->mComponentName.c_str(), bufferID, (long long)timeUs); 5480#else 5481 ALOGV("[%s] calling emptyBuffer %u w/ time %lld us", 5482 mCodec->mComponentName.c_str(), bufferID, (long long)timeUs); 5483#endif 5484 } 5485 5486#if TRACK_BUFFER_TIMING 5487 ACodec::BufferStats stats; 5488 stats.mEmptyBufferTimeUs = ALooper::GetNowUs(); 5489 stats.mFillBufferDoneTimeUs = -1ll; 5490 mCodec->mBufferStats.add(timeUs, stats); 5491#endif 5492 5493 if (mCodec->storingMetadataInDecodedBuffers()) { 5494 // try to submit an output buffer for each input buffer 5495 PortMode outputMode = getPortMode(kPortIndexOutput); 5496 5497 ALOGV("MetadataBuffersToSubmit=%u portMode=%s", 5498 mCodec->mMetadataBuffersToSubmit, 5499 (outputMode == FREE_BUFFERS ? "FREE" : 5500 outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT")); 5501 if (outputMode == RESUBMIT_BUFFERS) { 5502 mCodec->submitOutputMetadataBuffer(); 5503 } 5504 } 5505 info->checkReadFence("onInputBufferFilled"); 5506 status_t err2 = mCodec->mOMX->emptyBuffer( 5507 mCodec->mNode, 5508 bufferID, 5509 0, 5510 buffer->size(), 5511 flags, 5512 timeUs, 5513 info->mFenceFd); 5514 info->mFenceFd = -1; 5515 if (err2 != OK) { 5516 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2)); 5517 return; 5518 } 5519 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 5520 5521 if (!eos && err == OK) { 5522 getMoreInputDataIfPossible(); 5523 } else { 5524 ALOGV("[%s] Signalled EOS (%d) on the input port", 5525 mCodec->mComponentName.c_str(), err); 5526 5527 mCodec->mPortEOS[kPortIndexInput] = true; 5528 mCodec->mInputEOSResult = err; 5529 } 5530 } else if (!mCodec->mPortEOS[kPortIndexInput]) { 5531 if (err != OK && err != ERROR_END_OF_STREAM) { 5532 ALOGV("[%s] Signalling EOS on the input port due to error %d", 5533 mCodec->mComponentName.c_str(), err); 5534 } else { 5535 ALOGV("[%s] Signalling EOS on the input port", 5536 mCodec->mComponentName.c_str()); 5537 } 5538 5539 ALOGV("[%s] calling emptyBuffer %u signalling EOS", 5540 mCodec->mComponentName.c_str(), bufferID); 5541 5542 info->checkReadFence("onInputBufferFilled"); 5543 status_t err2 = mCodec->mOMX->emptyBuffer( 5544 mCodec->mNode, 5545 bufferID, 5546 0, 5547 0, 5548 OMX_BUFFERFLAG_EOS, 5549 0, 5550 info->mFenceFd); 5551 info->mFenceFd = -1; 5552 if (err2 != OK) { 5553 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2)); 5554 return; 5555 } 5556 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 5557 5558 mCodec->mPortEOS[kPortIndexInput] = true; 5559 mCodec->mInputEOSResult = err; 5560 } 5561 break; 5562 } 5563 5564 case FREE_BUFFERS: 5565 break; 5566 5567 default: 5568 ALOGE("invalid port mode: %d", mode); 5569 break; 5570 } 5571} 5572 5573void ACodec::BaseState::getMoreInputDataIfPossible() { 5574 if (mCodec->mPortEOS[kPortIndexInput]) { 5575 return; 5576 } 5577 5578 BufferInfo *eligible = NULL; 5579 5580 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 5581 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 5582 5583#if 0 5584 if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) { 5585 // There's already a "read" pending. 5586 return; 5587 } 5588#endif 5589 5590 if (info->mStatus == BufferInfo::OWNED_BY_US) { 5591 eligible = info; 5592 } 5593 } 5594 5595 if (eligible == NULL) { 5596 return; 5597 } 5598 5599 postFillThisBuffer(eligible); 5600} 5601 5602bool ACodec::BaseState::onOMXFillBufferDone( 5603 IOMX::buffer_id bufferID, 5604 size_t rangeOffset, size_t rangeLength, 5605 OMX_U32 flags, 5606 int64_t timeUs, 5607 int fenceFd) { 5608 ALOGV("[%s] onOMXFillBufferDone %u time %" PRId64 " us, flags = 0x%08x", 5609 mCodec->mComponentName.c_str(), bufferID, timeUs, flags); 5610 5611 ssize_t index; 5612 status_t err= OK; 5613 5614#if TRACK_BUFFER_TIMING 5615 index = mCodec->mBufferStats.indexOfKey(timeUs); 5616 if (index >= 0) { 5617 ACodec::BufferStats *stats = &mCodec->mBufferStats.editValueAt(index); 5618 stats->mFillBufferDoneTimeUs = ALooper::GetNowUs(); 5619 5620 ALOGI("frame PTS %lld: %lld", 5621 timeUs, 5622 stats->mFillBufferDoneTimeUs - stats->mEmptyBufferTimeUs); 5623 5624 mCodec->mBufferStats.removeItemsAt(index); 5625 stats = NULL; 5626 } 5627#endif 5628 5629 BufferInfo *info = 5630 mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 5631 BufferInfo::Status status = BufferInfo::getSafeStatus(info); 5632 if (status != BufferInfo::OWNED_BY_COMPONENT) { 5633 ALOGE("Wrong ownership in FBD: %s(%d) buffer #%u", _asString(status), status, bufferID); 5634 mCodec->dumpBuffers(kPortIndexOutput); 5635 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 5636 if (fenceFd >= 0) { 5637 ::close(fenceFd); 5638 } 5639 return true; 5640 } 5641 5642 info->mDequeuedAt = ++mCodec->mDequeueCounter; 5643 info->mStatus = BufferInfo::OWNED_BY_US; 5644 5645 if (info->mRenderInfo != NULL) { 5646 // The fence for an emptied buffer must have signaled, but there still could be queued 5647 // or out-of-order dequeued buffers in the render queue prior to this buffer. Drop these, 5648 // as we will soon requeue this buffer to the surface. While in theory we could still keep 5649 // track of buffers that are requeued to the surface, it is better to add support to the 5650 // buffer-queue to notify us of released buffers and their fences (in the future). 5651 mCodec->notifyOfRenderedFrames(true /* dropIncomplete */); 5652 } 5653 5654 // byte buffers cannot take fences, so wait for any fence now 5655 if (mCodec->mNativeWindow == NULL) { 5656 (void)mCodec->waitForFence(fenceFd, "onOMXFillBufferDone"); 5657 fenceFd = -1; 5658 } 5659 info->setReadFence(fenceFd, "onOMXFillBufferDone"); 5660 5661 PortMode mode = getPortMode(kPortIndexOutput); 5662 5663 switch (mode) { 5664 case KEEP_BUFFERS: 5665 break; 5666 5667 case RESUBMIT_BUFFERS: 5668 { 5669 if (rangeLength == 0 && (!(flags & OMX_BUFFERFLAG_EOS) 5670 || mCodec->mPortEOS[kPortIndexOutput])) { 5671 ALOGV("[%s] calling fillBuffer %u", 5672 mCodec->mComponentName.c_str(), info->mBufferID); 5673 5674 err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID, info->mFenceFd); 5675 info->mFenceFd = -1; 5676 if (err != OK) { 5677 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 5678 return true; 5679 } 5680 5681 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 5682 break; 5683 } 5684 5685 sp<AMessage> reply = 5686 new AMessage(kWhatOutputBufferDrained, mCodec); 5687 5688 if (mCodec->mOutputFormat != mCodec->mLastOutputFormat && rangeLength > 0) { 5689 mCodec->addKeyFormatChangesToRenderBufferNotification(reply); 5690 mCodec->sendFormatChange(); 5691 } 5692 5693 if (mCodec->usingMetadataOnEncoderOutput()) { 5694 native_handle_t *handle = NULL; 5695 VideoGrallocMetadata &grallocMeta = *(VideoGrallocMetadata *)info->mData->data(); 5696 VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)info->mData->data(); 5697 if (info->mData->size() >= sizeof(grallocMeta) 5698 && grallocMeta.eType == kMetadataBufferTypeGrallocSource) { 5699 handle = (native_handle_t *)(uintptr_t)grallocMeta.pHandle; 5700 } else if (info->mData->size() >= sizeof(nativeMeta) 5701 && nativeMeta.eType == kMetadataBufferTypeANWBuffer) { 5702#ifdef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS 5703 // ANativeWindowBuffer is only valid on 32-bit/mediaserver process 5704 handle = NULL; 5705#else 5706 handle = (native_handle_t *)nativeMeta.pBuffer->handle; 5707#endif 5708 } 5709 info->mData->meta()->setPointer("handle", handle); 5710 info->mData->meta()->setInt32("rangeOffset", rangeOffset); 5711 info->mData->meta()->setInt32("rangeLength", rangeLength); 5712 } else { 5713 info->mData->setRange(rangeOffset, rangeLength); 5714 } 5715#if 0 5716 if (mCodec->mNativeWindow == NULL) { 5717 if (IsIDR(info->mData)) { 5718 ALOGI("IDR frame"); 5719 } 5720 } 5721#endif 5722 5723 if (mCodec->mSkipCutBuffer != NULL) { 5724 mCodec->mSkipCutBuffer->submit(info->mData); 5725 } 5726 info->mData->meta()->setInt64("timeUs", timeUs); 5727 5728 sp<AMessage> notify = mCodec->mNotify->dup(); 5729 notify->setInt32("what", CodecBase::kWhatDrainThisBuffer); 5730 notify->setInt32("buffer-id", info->mBufferID); 5731 notify->setBuffer("buffer", info->mData); 5732 notify->setInt32("flags", flags); 5733 5734 reply->setInt32("buffer-id", info->mBufferID); 5735 5736 notify->setMessage("reply", reply); 5737 5738 notify->post(); 5739 5740 info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM; 5741 5742 if (flags & OMX_BUFFERFLAG_EOS) { 5743 ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str()); 5744 5745 sp<AMessage> notify = mCodec->mNotify->dup(); 5746 notify->setInt32("what", CodecBase::kWhatEOS); 5747 notify->setInt32("err", mCodec->mInputEOSResult); 5748 notify->post(); 5749 5750 mCodec->mPortEOS[kPortIndexOutput] = true; 5751 } 5752 break; 5753 } 5754 5755 case FREE_BUFFERS: 5756 err = mCodec->freeBuffer(kPortIndexOutput, index); 5757 if (err != OK) { 5758 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 5759 return true; 5760 } 5761 break; 5762 5763 default: 5764 ALOGE("Invalid port mode: %d", mode); 5765 return false; 5766 } 5767 5768 return true; 5769} 5770 5771void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { 5772 IOMX::buffer_id bufferID; 5773 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID)); 5774 ssize_t index; 5775 BufferInfo *info = mCodec->findBufferByID(kPortIndexOutput, bufferID, &index); 5776 BufferInfo::Status status = BufferInfo::getSafeStatus(info); 5777 if (status != BufferInfo::OWNED_BY_DOWNSTREAM) { 5778 ALOGE("Wrong ownership in OBD: %s(%d) buffer #%u", _asString(status), status, bufferID); 5779 mCodec->dumpBuffers(kPortIndexOutput); 5780 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 5781 return; 5782 } 5783 5784 android_native_rect_t crop; 5785 if (msg->findRect("crop", &crop.left, &crop.top, &crop.right, &crop.bottom)) { 5786 status_t err = native_window_set_crop(mCodec->mNativeWindow.get(), &crop); 5787 ALOGW_IF(err != NO_ERROR, "failed to set crop: %d", err); 5788 } 5789 5790 int32_t dataSpace; 5791 if (msg->findInt32("dataspace", &dataSpace)) { 5792 status_t err = native_window_set_buffers_data_space( 5793 mCodec->mNativeWindow.get(), (android_dataspace)dataSpace); 5794 ALOGW_IF(err != NO_ERROR, "failed to set dataspace: %d", err); 5795 } 5796 5797 int32_t render; 5798 if (mCodec->mNativeWindow != NULL 5799 && msg->findInt32("render", &render) && render != 0 5800 && info->mData != NULL && info->mData->size() != 0) { 5801 ATRACE_NAME("render"); 5802 // The client wants this buffer to be rendered. 5803 5804 // save buffers sent to the surface so we can get render time when they return 5805 int64_t mediaTimeUs = -1; 5806 info->mData->meta()->findInt64("timeUs", &mediaTimeUs); 5807 if (mediaTimeUs >= 0) { 5808 mCodec->mRenderTracker.onFrameQueued( 5809 mediaTimeUs, info->mGraphicBuffer, new Fence(::dup(info->mFenceFd))); 5810 } 5811 5812 int64_t timestampNs = 0; 5813 if (!msg->findInt64("timestampNs", ×tampNs)) { 5814 // use media timestamp if client did not request a specific render timestamp 5815 if (info->mData->meta()->findInt64("timeUs", ×tampNs)) { 5816 ALOGV("using buffer PTS of %lld", (long long)timestampNs); 5817 timestampNs *= 1000; 5818 } 5819 } 5820 5821 status_t err; 5822 err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs); 5823 ALOGW_IF(err != NO_ERROR, "failed to set buffer timestamp: %d", err); 5824 5825 info->checkReadFence("onOutputBufferDrained before queueBuffer"); 5826 err = mCodec->mNativeWindow->queueBuffer( 5827 mCodec->mNativeWindow.get(), info->mGraphicBuffer.get(), info->mFenceFd); 5828 info->mFenceFd = -1; 5829 if (err == OK) { 5830 info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; 5831 } else { 5832 ALOGE("queueBuffer failed in onOutputBufferDrained: %d", err); 5833 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 5834 info->mStatus = BufferInfo::OWNED_BY_US; 5835 // keeping read fence as write fence to avoid clobbering 5836 info->mIsReadFence = false; 5837 } 5838 } else { 5839 if (mCodec->mNativeWindow != NULL && 5840 (info->mData == NULL || info->mData->size() != 0)) { 5841 // move read fence into write fence to avoid clobbering 5842 info->mIsReadFence = false; 5843 ATRACE_NAME("frame-drop"); 5844 } 5845 info->mStatus = BufferInfo::OWNED_BY_US; 5846 } 5847 5848 PortMode mode = getPortMode(kPortIndexOutput); 5849 5850 switch (mode) { 5851 case KEEP_BUFFERS: 5852 { 5853 // XXX fishy, revisit!!! What about the FREE_BUFFERS case below? 5854 5855 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 5856 // We cannot resubmit the buffer we just rendered, dequeue 5857 // the spare instead. 5858 5859 info = mCodec->dequeueBufferFromNativeWindow(); 5860 } 5861 break; 5862 } 5863 5864 case RESUBMIT_BUFFERS: 5865 { 5866 if (!mCodec->mPortEOS[kPortIndexOutput]) { 5867 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 5868 // We cannot resubmit the buffer we just rendered, dequeue 5869 // the spare instead. 5870 5871 info = mCodec->dequeueBufferFromNativeWindow(); 5872 } 5873 5874 if (info != NULL) { 5875 ALOGV("[%s] calling fillBuffer %u", 5876 mCodec->mComponentName.c_str(), info->mBufferID); 5877 info->checkWriteFence("onOutputBufferDrained::RESUBMIT_BUFFERS"); 5878 status_t err = mCodec->mOMX->fillBuffer( 5879 mCodec->mNode, info->mBufferID, info->mFenceFd); 5880 info->mFenceFd = -1; 5881 if (err == OK) { 5882 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 5883 } else { 5884 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 5885 } 5886 } 5887 } 5888 break; 5889 } 5890 5891 case FREE_BUFFERS: 5892 { 5893 status_t err = mCodec->freeBuffer(kPortIndexOutput, index); 5894 if (err != OK) { 5895 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 5896 } 5897 break; 5898 } 5899 5900 default: 5901 ALOGE("Invalid port mode: %d", mode); 5902 return; 5903 } 5904} 5905 5906//////////////////////////////////////////////////////////////////////////////// 5907 5908ACodec::UninitializedState::UninitializedState(ACodec *codec) 5909 : BaseState(codec) { 5910} 5911 5912void ACodec::UninitializedState::stateEntered() { 5913 ALOGV("Now uninitialized"); 5914 5915 if (mDeathNotifier != NULL) { 5916 mCodec->mNodeBinder->unlinkToDeath(mDeathNotifier); 5917 mDeathNotifier.clear(); 5918 } 5919 5920 mCodec->mUsingNativeWindow = false; 5921 mCodec->mNativeWindow.clear(); 5922 mCodec->mNativeWindowUsageBits = 0; 5923 mCodec->mNode = 0; 5924 mCodec->mOMX.clear(); 5925 mCodec->mQuirks = 0; 5926 mCodec->mFlags = 0; 5927 mCodec->mInputMetadataType = kMetadataBufferTypeInvalid; 5928 mCodec->mOutputMetadataType = kMetadataBufferTypeInvalid; 5929 mCodec->mComponentName.clear(); 5930} 5931 5932bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) { 5933 bool handled = false; 5934 5935 switch (msg->what()) { 5936 case ACodec::kWhatSetup: 5937 { 5938 onSetup(msg); 5939 5940 handled = true; 5941 break; 5942 } 5943 5944 case ACodec::kWhatAllocateComponent: 5945 { 5946 onAllocateComponent(msg); 5947 handled = true; 5948 break; 5949 } 5950 5951 case ACodec::kWhatShutdown: 5952 { 5953 int32_t keepComponentAllocated; 5954 CHECK(msg->findInt32( 5955 "keepComponentAllocated", &keepComponentAllocated)); 5956 ALOGW_IF(keepComponentAllocated, 5957 "cannot keep component allocated on shutdown in Uninitialized state"); 5958 5959 sp<AMessage> notify = mCodec->mNotify->dup(); 5960 notify->setInt32("what", CodecBase::kWhatShutdownCompleted); 5961 notify->post(); 5962 5963 handled = true; 5964 break; 5965 } 5966 5967 case ACodec::kWhatFlush: 5968 { 5969 sp<AMessage> notify = mCodec->mNotify->dup(); 5970 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 5971 notify->post(); 5972 5973 handled = true; 5974 break; 5975 } 5976 5977 case ACodec::kWhatReleaseCodecInstance: 5978 { 5979 // nothing to do, as we have already signaled shutdown 5980 handled = true; 5981 break; 5982 } 5983 5984 default: 5985 return BaseState::onMessageReceived(msg); 5986 } 5987 5988 return handled; 5989} 5990 5991void ACodec::UninitializedState::onSetup( 5992 const sp<AMessage> &msg) { 5993 if (onAllocateComponent(msg) 5994 && mCodec->mLoadedState->onConfigureComponent(msg)) { 5995 mCodec->mLoadedState->onStart(); 5996 } 5997} 5998 5999bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) { 6000 ALOGV("onAllocateComponent"); 6001 6002 CHECK(mCodec->mNode == 0); 6003 6004 OMXClient client; 6005 if (client.connect() != OK) { 6006 mCodec->signalError(OMX_ErrorUndefined, NO_INIT); 6007 return false; 6008 } 6009 6010 sp<IOMX> omx = client.interface(); 6011 6012 sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec); 6013 6014 Vector<AString> matchingCodecs; 6015 6016 AString mime; 6017 6018 AString componentName; 6019 uint32_t quirks = 0; 6020 int32_t encoder = false; 6021 if (msg->findString("componentName", &componentName)) { 6022 sp<IMediaCodecList> list = MediaCodecList::getInstance(); 6023 if (list != NULL && list->findCodecByName(componentName.c_str()) >= 0) { 6024 matchingCodecs.add(componentName); 6025 } 6026 } else { 6027 CHECK(msg->findString("mime", &mime)); 6028 6029 if (!msg->findInt32("encoder", &encoder)) { 6030 encoder = false; 6031 } 6032 6033 MediaCodecList::findMatchingCodecs( 6034 mime.c_str(), 6035 encoder, // createEncoder 6036 0, // flags 6037 &matchingCodecs); 6038 } 6039 6040 sp<CodecObserver> observer = new CodecObserver; 6041 IOMX::node_id node = 0; 6042 6043 status_t err = NAME_NOT_FOUND; 6044 for (size_t matchIndex = 0; matchIndex < matchingCodecs.size(); 6045 ++matchIndex) { 6046 componentName = matchingCodecs[matchIndex]; 6047 quirks = MediaCodecList::getQuirksFor(componentName.c_str()); 6048 6049 pid_t tid = gettid(); 6050 int prevPriority = androidGetThreadPriority(tid); 6051 androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND); 6052 err = omx->allocateNode(componentName.c_str(), observer, &mCodec->mNodeBinder, &node); 6053 androidSetThreadPriority(tid, prevPriority); 6054 6055 if (err == OK) { 6056 break; 6057 } else { 6058 ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str()); 6059 } 6060 6061 node = 0; 6062 } 6063 6064 if (node == 0) { 6065 if (!mime.empty()) { 6066 ALOGE("Unable to instantiate a %scoder for type '%s' with err %#x.", 6067 encoder ? "en" : "de", mime.c_str(), err); 6068 } else { 6069 ALOGE("Unable to instantiate codec '%s' with err %#x.", componentName.c_str(), err); 6070 } 6071 6072 mCodec->signalError((OMX_ERRORTYPE)err, makeNoSideEffectStatus(err)); 6073 return false; 6074 } 6075 6076 mDeathNotifier = new DeathNotifier(notify); 6077 if (mCodec->mNodeBinder == NULL || 6078 mCodec->mNodeBinder->linkToDeath(mDeathNotifier) != OK) { 6079 // This was a local binder, if it dies so do we, we won't care 6080 // about any notifications in the afterlife. 6081 mDeathNotifier.clear(); 6082 } 6083 6084 notify = new AMessage(kWhatOMXMessageList, mCodec); 6085 observer->setNotificationMessage(notify); 6086 6087 mCodec->mComponentName = componentName; 6088 mCodec->mRenderTracker.setComponentName(componentName); 6089 mCodec->mFlags = 0; 6090 6091 if (componentName.endsWith(".secure")) { 6092 mCodec->mFlags |= kFlagIsSecure; 6093 mCodec->mFlags |= kFlagIsGrallocUsageProtected; 6094 mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown; 6095 } 6096 6097 mCodec->mQuirks = quirks; 6098 mCodec->mOMX = omx; 6099 mCodec->mNode = node; 6100 6101 { 6102 sp<AMessage> notify = mCodec->mNotify->dup(); 6103 notify->setInt32("what", CodecBase::kWhatComponentAllocated); 6104 notify->setString("componentName", mCodec->mComponentName.c_str()); 6105 notify->post(); 6106 } 6107 6108 mCodec->changeState(mCodec->mLoadedState); 6109 6110 return true; 6111} 6112 6113//////////////////////////////////////////////////////////////////////////////// 6114 6115ACodec::LoadedState::LoadedState(ACodec *codec) 6116 : BaseState(codec) { 6117} 6118 6119void ACodec::LoadedState::stateEntered() { 6120 ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str()); 6121 6122 mCodec->mPortEOS[kPortIndexInput] = 6123 mCodec->mPortEOS[kPortIndexOutput] = false; 6124 6125 mCodec->mInputEOSResult = OK; 6126 6127 mCodec->mDequeueCounter = 0; 6128 mCodec->mMetadataBuffersToSubmit = 0; 6129 mCodec->mRepeatFrameDelayUs = -1ll; 6130 mCodec->mInputFormat.clear(); 6131 mCodec->mOutputFormat.clear(); 6132 mCodec->mBaseOutputFormat.clear(); 6133 6134 if (mCodec->mShutdownInProgress) { 6135 bool keepComponentAllocated = mCodec->mKeepComponentAllocated; 6136 6137 mCodec->mShutdownInProgress = false; 6138 mCodec->mKeepComponentAllocated = false; 6139 6140 onShutdown(keepComponentAllocated); 6141 } 6142 mCodec->mExplicitShutdown = false; 6143 6144 mCodec->processDeferredMessages(); 6145} 6146 6147void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) { 6148 if (!keepComponentAllocated) { 6149 (void)mCodec->mOMX->freeNode(mCodec->mNode); 6150 6151 mCodec->changeState(mCodec->mUninitializedState); 6152 } 6153 6154 if (mCodec->mExplicitShutdown) { 6155 sp<AMessage> notify = mCodec->mNotify->dup(); 6156 notify->setInt32("what", CodecBase::kWhatShutdownCompleted); 6157 notify->post(); 6158 mCodec->mExplicitShutdown = false; 6159 } 6160} 6161 6162bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) { 6163 bool handled = false; 6164 6165 switch (msg->what()) { 6166 case ACodec::kWhatConfigureComponent: 6167 { 6168 onConfigureComponent(msg); 6169 handled = true; 6170 break; 6171 } 6172 6173 case ACodec::kWhatCreateInputSurface: 6174 { 6175 onCreateInputSurface(msg); 6176 handled = true; 6177 break; 6178 } 6179 6180 case ACodec::kWhatSetInputSurface: 6181 { 6182 onSetInputSurface(msg); 6183 handled = true; 6184 break; 6185 } 6186 6187 case ACodec::kWhatStart: 6188 { 6189 onStart(); 6190 handled = true; 6191 break; 6192 } 6193 6194 case ACodec::kWhatShutdown: 6195 { 6196 int32_t keepComponentAllocated; 6197 CHECK(msg->findInt32( 6198 "keepComponentAllocated", &keepComponentAllocated)); 6199 6200 mCodec->mExplicitShutdown = true; 6201 onShutdown(keepComponentAllocated); 6202 6203 handled = true; 6204 break; 6205 } 6206 6207 case ACodec::kWhatFlush: 6208 { 6209 sp<AMessage> notify = mCodec->mNotify->dup(); 6210 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 6211 notify->post(); 6212 6213 handled = true; 6214 break; 6215 } 6216 6217 default: 6218 return BaseState::onMessageReceived(msg); 6219 } 6220 6221 return handled; 6222} 6223 6224bool ACodec::LoadedState::onConfigureComponent( 6225 const sp<AMessage> &msg) { 6226 ALOGV("onConfigureComponent"); 6227 6228 CHECK(mCodec->mNode != 0); 6229 6230 status_t err = OK; 6231 AString mime; 6232 if (!msg->findString("mime", &mime)) { 6233 err = BAD_VALUE; 6234 } else { 6235 err = mCodec->configureCodec(mime.c_str(), msg); 6236 } 6237 if (err != OK) { 6238 ALOGE("[%s] configureCodec returning error %d", 6239 mCodec->mComponentName.c_str(), err); 6240 6241 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6242 return false; 6243 } 6244 6245 { 6246 sp<AMessage> notify = mCodec->mNotify->dup(); 6247 notify->setInt32("what", CodecBase::kWhatComponentConfigured); 6248 notify->setMessage("input-format", mCodec->mInputFormat); 6249 notify->setMessage("output-format", mCodec->mOutputFormat); 6250 notify->post(); 6251 } 6252 6253 return true; 6254} 6255 6256status_t ACodec::LoadedState::setupInputSurface() { 6257 status_t err = OK; 6258 6259 if (mCodec->mRepeatFrameDelayUs > 0ll) { 6260 err = mCodec->mOMX->setInternalOption( 6261 mCodec->mNode, 6262 kPortIndexInput, 6263 IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY, 6264 &mCodec->mRepeatFrameDelayUs, 6265 sizeof(mCodec->mRepeatFrameDelayUs)); 6266 6267 if (err != OK) { 6268 ALOGE("[%s] Unable to configure option to repeat previous " 6269 "frames (err %d)", 6270 mCodec->mComponentName.c_str(), 6271 err); 6272 return err; 6273 } 6274 } 6275 6276 if (mCodec->mMaxPtsGapUs > 0ll) { 6277 err = mCodec->mOMX->setInternalOption( 6278 mCodec->mNode, 6279 kPortIndexInput, 6280 IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP, 6281 &mCodec->mMaxPtsGapUs, 6282 sizeof(mCodec->mMaxPtsGapUs)); 6283 6284 if (err != OK) { 6285 ALOGE("[%s] Unable to configure max timestamp gap (err %d)", 6286 mCodec->mComponentName.c_str(), 6287 err); 6288 return err; 6289 } 6290 } 6291 6292 if (mCodec->mMaxFps > 0) { 6293 err = mCodec->mOMX->setInternalOption( 6294 mCodec->mNode, 6295 kPortIndexInput, 6296 IOMX::INTERNAL_OPTION_MAX_FPS, 6297 &mCodec->mMaxFps, 6298 sizeof(mCodec->mMaxFps)); 6299 6300 if (err != OK) { 6301 ALOGE("[%s] Unable to configure max fps (err %d)", 6302 mCodec->mComponentName.c_str(), 6303 err); 6304 return err; 6305 } 6306 } 6307 6308 if (mCodec->mTimePerCaptureUs > 0ll 6309 && mCodec->mTimePerFrameUs > 0ll) { 6310 int64_t timeLapse[2]; 6311 timeLapse[0] = mCodec->mTimePerFrameUs; 6312 timeLapse[1] = mCodec->mTimePerCaptureUs; 6313 err = mCodec->mOMX->setInternalOption( 6314 mCodec->mNode, 6315 kPortIndexInput, 6316 IOMX::INTERNAL_OPTION_TIME_LAPSE, 6317 &timeLapse[0], 6318 sizeof(timeLapse)); 6319 6320 if (err != OK) { 6321 ALOGE("[%s] Unable to configure time lapse (err %d)", 6322 mCodec->mComponentName.c_str(), 6323 err); 6324 return err; 6325 } 6326 } 6327 6328 if (mCodec->mCreateInputBuffersSuspended) { 6329 bool suspend = true; 6330 err = mCodec->mOMX->setInternalOption( 6331 mCodec->mNode, 6332 kPortIndexInput, 6333 IOMX::INTERNAL_OPTION_SUSPEND, 6334 &suspend, 6335 sizeof(suspend)); 6336 6337 if (err != OK) { 6338 ALOGE("[%s] Unable to configure option to suspend (err %d)", 6339 mCodec->mComponentName.c_str(), 6340 err); 6341 return err; 6342 } 6343 } 6344 6345 uint32_t usageBits; 6346 if (mCodec->mOMX->getParameter( 6347 mCodec->mNode, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits, 6348 &usageBits, sizeof(usageBits)) == OK) { 6349 mCodec->mInputFormat->setInt32( 6350 "using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN)); 6351 } 6352 6353 sp<ABuffer> colorAspectsBuffer; 6354 if (mCodec->mInputFormat->findBuffer("android._color-aspects", &colorAspectsBuffer)) { 6355 err = mCodec->mOMX->setInternalOption( 6356 mCodec->mNode, kPortIndexInput, IOMX::INTERNAL_OPTION_COLOR_ASPECTS, 6357 colorAspectsBuffer->base(), colorAspectsBuffer->capacity()); 6358 if (err != OK) { 6359 ALOGE("[%s] Unable to configure color aspects (err %d)", 6360 mCodec->mComponentName.c_str(), err); 6361 return err; 6362 } 6363 } 6364 return OK; 6365} 6366 6367void ACodec::LoadedState::onCreateInputSurface( 6368 const sp<AMessage> & /* msg */) { 6369 ALOGV("onCreateInputSurface"); 6370 6371 sp<AMessage> notify = mCodec->mNotify->dup(); 6372 notify->setInt32("what", CodecBase::kWhatInputSurfaceCreated); 6373 6374 android_dataspace dataSpace; 6375 status_t err = 6376 mCodec->setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace(&dataSpace); 6377 notify->setMessage("input-format", mCodec->mInputFormat); 6378 notify->setMessage("output-format", mCodec->mOutputFormat); 6379 6380 sp<IGraphicBufferProducer> bufferProducer; 6381 if (err == OK) { 6382 err = mCodec->mOMX->createInputSurface( 6383 mCodec->mNode, kPortIndexInput, dataSpace, &bufferProducer, &mCodec->mInputMetadataType); 6384 } 6385 6386 if (err == OK) { 6387 err = setupInputSurface(); 6388 } 6389 6390 if (err == OK) { 6391 notify->setObject("input-surface", 6392 new BufferProducerWrapper(bufferProducer)); 6393 } else { 6394 // Can't use mCodec->signalError() here -- MediaCodec won't forward 6395 // the error through because it's in the "configured" state. We 6396 // send a kWhatInputSurfaceCreated with an error value instead. 6397 ALOGE("[%s] onCreateInputSurface returning error %d", 6398 mCodec->mComponentName.c_str(), err); 6399 notify->setInt32("err", err); 6400 } 6401 notify->post(); 6402} 6403 6404void ACodec::LoadedState::onSetInputSurface( 6405 const sp<AMessage> &msg) { 6406 ALOGV("onSetInputSurface"); 6407 6408 sp<AMessage> notify = mCodec->mNotify->dup(); 6409 notify->setInt32("what", CodecBase::kWhatInputSurfaceAccepted); 6410 6411 sp<RefBase> obj; 6412 CHECK(msg->findObject("input-surface", &obj)); 6413 sp<PersistentSurface> surface = static_cast<PersistentSurface *>(obj.get()); 6414 6415 android_dataspace dataSpace; 6416 status_t err = 6417 mCodec->setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace(&dataSpace); 6418 notify->setMessage("input-format", mCodec->mInputFormat); 6419 notify->setMessage("output-format", mCodec->mOutputFormat); 6420 6421 if (err == OK) { 6422 err = mCodec->mOMX->setInputSurface( 6423 mCodec->mNode, kPortIndexInput, surface->getBufferConsumer(), 6424 &mCodec->mInputMetadataType); 6425 } 6426 6427 if (err == OK) { 6428 surface->getBufferConsumer()->setDefaultBufferDataSpace(dataSpace); 6429 err = setupInputSurface(); 6430 } 6431 6432 if (err != OK) { 6433 // Can't use mCodec->signalError() here -- MediaCodec won't forward 6434 // the error through because it's in the "configured" state. We 6435 // send a kWhatInputSurfaceAccepted with an error value instead. 6436 ALOGE("[%s] onSetInputSurface returning error %d", 6437 mCodec->mComponentName.c_str(), err); 6438 notify->setInt32("err", err); 6439 } 6440 notify->post(); 6441} 6442 6443void ACodec::LoadedState::onStart() { 6444 ALOGV("onStart"); 6445 6446 status_t err = mCodec->mOMX->sendCommand(mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle); 6447 if (err != OK) { 6448 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6449 } else { 6450 mCodec->changeState(mCodec->mLoadedToIdleState); 6451 } 6452} 6453 6454//////////////////////////////////////////////////////////////////////////////// 6455 6456ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec) 6457 : BaseState(codec) { 6458} 6459 6460void ACodec::LoadedToIdleState::stateEntered() { 6461 ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str()); 6462 6463 status_t err; 6464 if ((err = allocateBuffers()) != OK) { 6465 ALOGE("Failed to allocate buffers after transitioning to IDLE state " 6466 "(error 0x%08x)", 6467 err); 6468 6469 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6470 6471 mCodec->mOMX->sendCommand( 6472 mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded); 6473 if (mCodec->allYourBuffersAreBelongToUs(kPortIndexInput)) { 6474 mCodec->freeBuffersOnPort(kPortIndexInput); 6475 } 6476 if (mCodec->allYourBuffersAreBelongToUs(kPortIndexOutput)) { 6477 mCodec->freeBuffersOnPort(kPortIndexOutput); 6478 } 6479 6480 mCodec->changeState(mCodec->mLoadedState); 6481 } 6482} 6483 6484status_t ACodec::LoadedToIdleState::allocateBuffers() { 6485 status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput); 6486 6487 if (err != OK) { 6488 return err; 6489 } 6490 6491 return mCodec->allocateBuffersOnPort(kPortIndexOutput); 6492} 6493 6494bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) { 6495 switch (msg->what()) { 6496 case kWhatSetParameters: 6497 case kWhatShutdown: 6498 { 6499 mCodec->deferMessage(msg); 6500 return true; 6501 } 6502 6503 case kWhatSignalEndOfInputStream: 6504 { 6505 mCodec->onSignalEndOfInputStream(); 6506 return true; 6507 } 6508 6509 case kWhatResume: 6510 { 6511 // We'll be active soon enough. 6512 return true; 6513 } 6514 6515 case kWhatFlush: 6516 { 6517 // We haven't even started yet, so we're flushed alright... 6518 sp<AMessage> notify = mCodec->mNotify->dup(); 6519 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 6520 notify->post(); 6521 return true; 6522 } 6523 6524 default: 6525 return BaseState::onMessageReceived(msg); 6526 } 6527} 6528 6529bool ACodec::LoadedToIdleState::onOMXEvent( 6530 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 6531 switch (event) { 6532 case OMX_EventCmdComplete: 6533 { 6534 status_t err = OK; 6535 if (data1 != (OMX_U32)OMX_CommandStateSet 6536 || data2 != (OMX_U32)OMX_StateIdle) { 6537 ALOGE("Unexpected command completion in LoadedToIdleState: %s(%u) %s(%u)", 6538 asString((OMX_COMMANDTYPE)data1), data1, 6539 asString((OMX_STATETYPE)data2), data2); 6540 err = FAILED_TRANSACTION; 6541 } 6542 6543 if (err == OK) { 6544 err = mCodec->mOMX->sendCommand( 6545 mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting); 6546 } 6547 6548 if (err != OK) { 6549 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 6550 } else { 6551 mCodec->changeState(mCodec->mIdleToExecutingState); 6552 } 6553 6554 return true; 6555 } 6556 6557 default: 6558 return BaseState::onOMXEvent(event, data1, data2); 6559 } 6560} 6561 6562//////////////////////////////////////////////////////////////////////////////// 6563 6564ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec) 6565 : BaseState(codec) { 6566} 6567 6568void ACodec::IdleToExecutingState::stateEntered() { 6569 ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str()); 6570} 6571 6572bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) { 6573 switch (msg->what()) { 6574 case kWhatSetParameters: 6575 case kWhatShutdown: 6576 { 6577 mCodec->deferMessage(msg); 6578 return true; 6579 } 6580 6581 case kWhatResume: 6582 { 6583 // We'll be active soon enough. 6584 return true; 6585 } 6586 6587 case kWhatFlush: 6588 { 6589 // We haven't even started yet, so we're flushed alright... 6590 sp<AMessage> notify = mCodec->mNotify->dup(); 6591 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 6592 notify->post(); 6593 6594 return true; 6595 } 6596 6597 case kWhatSignalEndOfInputStream: 6598 { 6599 mCodec->onSignalEndOfInputStream(); 6600 return true; 6601 } 6602 6603 default: 6604 return BaseState::onMessageReceived(msg); 6605 } 6606} 6607 6608bool ACodec::IdleToExecutingState::onOMXEvent( 6609 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 6610 switch (event) { 6611 case OMX_EventCmdComplete: 6612 { 6613 if (data1 != (OMX_U32)OMX_CommandStateSet 6614 || data2 != (OMX_U32)OMX_StateExecuting) { 6615 ALOGE("Unexpected command completion in IdleToExecutingState: %s(%u) %s(%u)", 6616 asString((OMX_COMMANDTYPE)data1), data1, 6617 asString((OMX_STATETYPE)data2), data2); 6618 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6619 return true; 6620 } 6621 6622 mCodec->mExecutingState->resume(); 6623 mCodec->changeState(mCodec->mExecutingState); 6624 6625 return true; 6626 } 6627 6628 default: 6629 return BaseState::onOMXEvent(event, data1, data2); 6630 } 6631} 6632 6633//////////////////////////////////////////////////////////////////////////////// 6634 6635ACodec::ExecutingState::ExecutingState(ACodec *codec) 6636 : BaseState(codec), 6637 mActive(false) { 6638} 6639 6640ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode( 6641 OMX_U32 /* portIndex */) { 6642 return RESUBMIT_BUFFERS; 6643} 6644 6645void ACodec::ExecutingState::submitOutputMetaBuffers() { 6646 // submit as many buffers as there are input buffers with the codec 6647 // in case we are in port reconfiguring 6648 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) { 6649 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 6650 6651 if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) { 6652 if (mCodec->submitOutputMetadataBuffer() != OK) 6653 break; 6654 } 6655 } 6656 6657 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** 6658 mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround(); 6659} 6660 6661void ACodec::ExecutingState::submitRegularOutputBuffers() { 6662 bool failed = false; 6663 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) { 6664 BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i); 6665 6666 if (mCodec->mNativeWindow != NULL) { 6667 if (info->mStatus != BufferInfo::OWNED_BY_US 6668 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) { 6669 ALOGE("buffers should be owned by us or the surface"); 6670 failed = true; 6671 break; 6672 } 6673 6674 if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) { 6675 continue; 6676 } 6677 } else { 6678 if (info->mStatus != BufferInfo::OWNED_BY_US) { 6679 ALOGE("buffers should be owned by us"); 6680 failed = true; 6681 break; 6682 } 6683 } 6684 6685 ALOGV("[%s] calling fillBuffer %u", mCodec->mComponentName.c_str(), info->mBufferID); 6686 6687 info->checkWriteFence("submitRegularOutputBuffers"); 6688 status_t err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID, info->mFenceFd); 6689 info->mFenceFd = -1; 6690 if (err != OK) { 6691 failed = true; 6692 break; 6693 } 6694 6695 info->mStatus = BufferInfo::OWNED_BY_COMPONENT; 6696 } 6697 6698 if (failed) { 6699 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6700 } 6701} 6702 6703void ACodec::ExecutingState::submitOutputBuffers() { 6704 submitRegularOutputBuffers(); 6705 if (mCodec->storingMetadataInDecodedBuffers()) { 6706 submitOutputMetaBuffers(); 6707 } 6708} 6709 6710void ACodec::ExecutingState::resume() { 6711 if (mActive) { 6712 ALOGV("[%s] We're already active, no need to resume.", mCodec->mComponentName.c_str()); 6713 return; 6714 } 6715 6716 submitOutputBuffers(); 6717 6718 // Post all available input buffers 6719 if (mCodec->mBuffers[kPortIndexInput].size() == 0u) { 6720 ALOGW("[%s] we don't have any input buffers to resume", mCodec->mComponentName.c_str()); 6721 } 6722 6723 for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) { 6724 BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i); 6725 if (info->mStatus == BufferInfo::OWNED_BY_US) { 6726 postFillThisBuffer(info); 6727 } 6728 } 6729 6730 mActive = true; 6731} 6732 6733void ACodec::ExecutingState::stateEntered() { 6734 ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str()); 6735 6736 mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC)); 6737 mCodec->processDeferredMessages(); 6738} 6739 6740bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) { 6741 bool handled = false; 6742 6743 switch (msg->what()) { 6744 case kWhatShutdown: 6745 { 6746 int32_t keepComponentAllocated; 6747 CHECK(msg->findInt32( 6748 "keepComponentAllocated", &keepComponentAllocated)); 6749 6750 mCodec->mShutdownInProgress = true; 6751 mCodec->mExplicitShutdown = true; 6752 mCodec->mKeepComponentAllocated = keepComponentAllocated; 6753 6754 mActive = false; 6755 6756 status_t err = mCodec->mOMX->sendCommand( 6757 mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle); 6758 if (err != OK) { 6759 if (keepComponentAllocated) { 6760 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6761 } 6762 // TODO: do some recovery here. 6763 } else { 6764 mCodec->changeState(mCodec->mExecutingToIdleState); 6765 } 6766 6767 handled = true; 6768 break; 6769 } 6770 6771 case kWhatFlush: 6772 { 6773 ALOGV("[%s] ExecutingState flushing now " 6774 "(codec owns %zu/%zu input, %zu/%zu output).", 6775 mCodec->mComponentName.c_str(), 6776 mCodec->countBuffersOwnedByComponent(kPortIndexInput), 6777 mCodec->mBuffers[kPortIndexInput].size(), 6778 mCodec->countBuffersOwnedByComponent(kPortIndexOutput), 6779 mCodec->mBuffers[kPortIndexOutput].size()); 6780 6781 mActive = false; 6782 6783 status_t err = mCodec->mOMX->sendCommand(mCodec->mNode, OMX_CommandFlush, OMX_ALL); 6784 if (err != OK) { 6785 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 6786 } else { 6787 mCodec->changeState(mCodec->mFlushingState); 6788 } 6789 6790 handled = true; 6791 break; 6792 } 6793 6794 case kWhatResume: 6795 { 6796 resume(); 6797 6798 handled = true; 6799 break; 6800 } 6801 6802 case kWhatRequestIDRFrame: 6803 { 6804 status_t err = mCodec->requestIDRFrame(); 6805 if (err != OK) { 6806 ALOGW("Requesting an IDR frame failed."); 6807 } 6808 6809 handled = true; 6810 break; 6811 } 6812 6813 case kWhatSetParameters: 6814 { 6815 sp<AMessage> params; 6816 CHECK(msg->findMessage("params", ¶ms)); 6817 6818 status_t err = mCodec->setParameters(params); 6819 6820 sp<AMessage> reply; 6821 if (msg->findMessage("reply", &reply)) { 6822 reply->setInt32("err", err); 6823 reply->post(); 6824 } 6825 6826 handled = true; 6827 break; 6828 } 6829 6830 case ACodec::kWhatSignalEndOfInputStream: 6831 { 6832 mCodec->onSignalEndOfInputStream(); 6833 handled = true; 6834 break; 6835 } 6836 6837 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED *** 6838 case kWhatSubmitOutputMetadataBufferIfEOS: 6839 { 6840 if (mCodec->mPortEOS[kPortIndexInput] && 6841 !mCodec->mPortEOS[kPortIndexOutput]) { 6842 status_t err = mCodec->submitOutputMetadataBuffer(); 6843 if (err == OK) { 6844 mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround(); 6845 } 6846 } 6847 return true; 6848 } 6849 6850 default: 6851 handled = BaseState::onMessageReceived(msg); 6852 break; 6853 } 6854 6855 return handled; 6856} 6857 6858status_t ACodec::setParameters(const sp<AMessage> ¶ms) { 6859 int32_t videoBitrate; 6860 if (params->findInt32("video-bitrate", &videoBitrate)) { 6861 OMX_VIDEO_CONFIG_BITRATETYPE configParams; 6862 InitOMXParams(&configParams); 6863 configParams.nPortIndex = kPortIndexOutput; 6864 configParams.nEncodeBitrate = videoBitrate; 6865 6866 status_t err = mOMX->setConfig( 6867 mNode, 6868 OMX_IndexConfigVideoBitrate, 6869 &configParams, 6870 sizeof(configParams)); 6871 6872 if (err != OK) { 6873 ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d", 6874 videoBitrate, err); 6875 6876 return err; 6877 } 6878 } 6879 6880 int64_t skipFramesBeforeUs; 6881 if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) { 6882 status_t err = 6883 mOMX->setInternalOption( 6884 mNode, 6885 kPortIndexInput, 6886 IOMX::INTERNAL_OPTION_START_TIME, 6887 &skipFramesBeforeUs, 6888 sizeof(skipFramesBeforeUs)); 6889 6890 if (err != OK) { 6891 ALOGE("Failed to set parameter 'skip-frames-before' (err %d)", err); 6892 return err; 6893 } 6894 } 6895 6896 int32_t dropInputFrames; 6897 if (params->findInt32("drop-input-frames", &dropInputFrames)) { 6898 bool suspend = dropInputFrames != 0; 6899 6900 status_t err = 6901 mOMX->setInternalOption( 6902 mNode, 6903 kPortIndexInput, 6904 IOMX::INTERNAL_OPTION_SUSPEND, 6905 &suspend, 6906 sizeof(suspend)); 6907 6908 if (err != OK) { 6909 ALOGE("Failed to set parameter 'drop-input-frames' (err %d)", err); 6910 return err; 6911 } 6912 } 6913 6914 int32_t dummy; 6915 if (params->findInt32("request-sync", &dummy)) { 6916 status_t err = requestIDRFrame(); 6917 6918 if (err != OK) { 6919 ALOGE("Requesting a sync frame failed w/ err %d", err); 6920 return err; 6921 } 6922 } 6923 6924 float rate; 6925 if (params->findFloat("operating-rate", &rate) && rate > 0) { 6926 status_t err = setOperatingRate(rate, mIsVideo); 6927 if (err != OK) { 6928 ALOGE("Failed to set parameter 'operating-rate' (err %d)", err); 6929 return err; 6930 } 6931 } 6932 6933 int32_t intraRefreshPeriod = 0; 6934 if (params->findInt32("intra-refresh-period", &intraRefreshPeriod) 6935 && intraRefreshPeriod > 0) { 6936 status_t err = setIntraRefreshPeriod(intraRefreshPeriod, false); 6937 if (err != OK) { 6938 ALOGI("[%s] failed setIntraRefreshPeriod. Failure is fine since this key is optional", 6939 mComponentName.c_str()); 6940 err = OK; 6941 } 6942 } 6943 6944 return OK; 6945} 6946 6947void ACodec::onSignalEndOfInputStream() { 6948 sp<AMessage> notify = mNotify->dup(); 6949 notify->setInt32("what", CodecBase::kWhatSignaledInputEOS); 6950 6951 status_t err = mOMX->signalEndOfInputStream(mNode); 6952 if (err != OK) { 6953 notify->setInt32("err", err); 6954 } 6955 notify->post(); 6956} 6957 6958bool ACodec::ExecutingState::onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) { 6959 mCodec->onFrameRendered(mediaTimeUs, systemNano); 6960 return true; 6961} 6962 6963bool ACodec::ExecutingState::onOMXEvent( 6964 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 6965 switch (event) { 6966 case OMX_EventPortSettingsChanged: 6967 { 6968 CHECK_EQ(data1, (OMX_U32)kPortIndexOutput); 6969 6970 mCodec->onOutputFormatChanged(); 6971 6972 if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) { 6973 mCodec->mMetadataBuffersToSubmit = 0; 6974 CHECK_EQ(mCodec->mOMX->sendCommand( 6975 mCodec->mNode, 6976 OMX_CommandPortDisable, kPortIndexOutput), 6977 (status_t)OK); 6978 6979 mCodec->freeOutputBuffersNotOwnedByComponent(); 6980 6981 mCodec->changeState(mCodec->mOutputPortSettingsChangedState); 6982 } else if (data2 != OMX_IndexConfigCommonOutputCrop 6983 && data2 != OMX_IndexConfigAndroidIntraRefresh) { 6984 ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08x", 6985 mCodec->mComponentName.c_str(), data2); 6986 } 6987 6988 return true; 6989 } 6990 6991 case OMX_EventBufferFlag: 6992 { 6993 return true; 6994 } 6995 6996 default: 6997 return BaseState::onOMXEvent(event, data1, data2); 6998 } 6999} 7000 7001//////////////////////////////////////////////////////////////////////////////// 7002 7003ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState( 7004 ACodec *codec) 7005 : BaseState(codec) { 7006} 7007 7008ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode( 7009 OMX_U32 portIndex) { 7010 if (portIndex == kPortIndexOutput) { 7011 return FREE_BUFFERS; 7012 } 7013 7014 CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput); 7015 7016 return RESUBMIT_BUFFERS; 7017} 7018 7019bool ACodec::OutputPortSettingsChangedState::onMessageReceived( 7020 const sp<AMessage> &msg) { 7021 bool handled = false; 7022 7023 switch (msg->what()) { 7024 case kWhatFlush: 7025 case kWhatShutdown: 7026 case kWhatResume: 7027 case kWhatSetParameters: 7028 { 7029 if (msg->what() == kWhatResume) { 7030 ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str()); 7031 } 7032 7033 mCodec->deferMessage(msg); 7034 handled = true; 7035 break; 7036 } 7037 7038 default: 7039 handled = BaseState::onMessageReceived(msg); 7040 break; 7041 } 7042 7043 return handled; 7044} 7045 7046void ACodec::OutputPortSettingsChangedState::stateEntered() { 7047 ALOGV("[%s] Now handling output port settings change", 7048 mCodec->mComponentName.c_str()); 7049} 7050 7051bool ACodec::OutputPortSettingsChangedState::onOMXFrameRendered( 7052 int64_t mediaTimeUs, nsecs_t systemNano) { 7053 mCodec->onFrameRendered(mediaTimeUs, systemNano); 7054 return true; 7055} 7056 7057bool ACodec::OutputPortSettingsChangedState::onOMXEvent( 7058 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 7059 switch (event) { 7060 case OMX_EventCmdComplete: 7061 { 7062 if (data1 == (OMX_U32)OMX_CommandPortDisable) { 7063 if (data2 != (OMX_U32)kPortIndexOutput) { 7064 ALOGW("ignoring EventCmdComplete CommandPortDisable for port %u", data2); 7065 return false; 7066 } 7067 7068 ALOGV("[%s] Output port now disabled.", mCodec->mComponentName.c_str()); 7069 7070 status_t err = OK; 7071 if (!mCodec->mBuffers[kPortIndexOutput].isEmpty()) { 7072 ALOGE("disabled port should be empty, but has %zu buffers", 7073 mCodec->mBuffers[kPortIndexOutput].size()); 7074 err = FAILED_TRANSACTION; 7075 } else { 7076 mCodec->mDealer[kPortIndexOutput].clear(); 7077 } 7078 7079 if (err == OK) { 7080 err = mCodec->mOMX->sendCommand( 7081 mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput); 7082 } 7083 7084 if (err == OK) { 7085 err = mCodec->allocateBuffersOnPort(kPortIndexOutput); 7086 ALOGE_IF(err != OK, "Failed to allocate output port buffers after port " 7087 "reconfiguration: (%d)", err); 7088 } 7089 7090 if (err != OK) { 7091 mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); 7092 7093 // This is technically not correct, but appears to be 7094 // the only way to free the component instance. 7095 // Controlled transitioning from excecuting->idle 7096 // and idle->loaded seem impossible probably because 7097 // the output port never finishes re-enabling. 7098 mCodec->mShutdownInProgress = true; 7099 mCodec->mKeepComponentAllocated = false; 7100 mCodec->changeState(mCodec->mLoadedState); 7101 } 7102 7103 return true; 7104 } else if (data1 == (OMX_U32)OMX_CommandPortEnable) { 7105 if (data2 != (OMX_U32)kPortIndexOutput) { 7106 ALOGW("ignoring EventCmdComplete OMX_CommandPortEnable for port %u", data2); 7107 return false; 7108 } 7109 7110 ALOGV("[%s] Output port now reenabled.", mCodec->mComponentName.c_str()); 7111 7112 if (mCodec->mExecutingState->active()) { 7113 mCodec->mExecutingState->submitOutputBuffers(); 7114 } 7115 7116 mCodec->changeState(mCodec->mExecutingState); 7117 7118 return true; 7119 } 7120 7121 return false; 7122 } 7123 7124 default: 7125 return false; 7126 } 7127} 7128 7129//////////////////////////////////////////////////////////////////////////////// 7130 7131ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec) 7132 : BaseState(codec), 7133 mComponentNowIdle(false) { 7134} 7135 7136bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) { 7137 bool handled = false; 7138 7139 switch (msg->what()) { 7140 case kWhatFlush: 7141 { 7142 // Don't send me a flush request if you previously wanted me 7143 // to shutdown. 7144 ALOGW("Ignoring flush request in ExecutingToIdleState"); 7145 break; 7146 } 7147 7148 case kWhatShutdown: 7149 { 7150 // We're already doing that... 7151 7152 handled = true; 7153 break; 7154 } 7155 7156 default: 7157 handled = BaseState::onMessageReceived(msg); 7158 break; 7159 } 7160 7161 return handled; 7162} 7163 7164void ACodec::ExecutingToIdleState::stateEntered() { 7165 ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str()); 7166 7167 mComponentNowIdle = false; 7168 mCodec->mLastOutputFormat.clear(); 7169} 7170 7171bool ACodec::ExecutingToIdleState::onOMXEvent( 7172 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 7173 switch (event) { 7174 case OMX_EventCmdComplete: 7175 { 7176 if (data1 != (OMX_U32)OMX_CommandStateSet 7177 || data2 != (OMX_U32)OMX_StateIdle) { 7178 ALOGE("Unexpected command completion in ExecutingToIdleState: %s(%u) %s(%u)", 7179 asString((OMX_COMMANDTYPE)data1), data1, 7180 asString((OMX_STATETYPE)data2), data2); 7181 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 7182 return true; 7183 } 7184 7185 mComponentNowIdle = true; 7186 7187 changeStateIfWeOwnAllBuffers(); 7188 7189 return true; 7190 } 7191 7192 case OMX_EventPortSettingsChanged: 7193 case OMX_EventBufferFlag: 7194 { 7195 // We're shutting down and don't care about this anymore. 7196 return true; 7197 } 7198 7199 default: 7200 return BaseState::onOMXEvent(event, data1, data2); 7201 } 7202} 7203 7204void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() { 7205 if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) { 7206 status_t err = mCodec->mOMX->sendCommand( 7207 mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded); 7208 if (err == OK) { 7209 err = mCodec->freeBuffersOnPort(kPortIndexInput); 7210 status_t err2 = mCodec->freeBuffersOnPort(kPortIndexOutput); 7211 if (err == OK) { 7212 err = err2; 7213 } 7214 } 7215 7216 if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown) 7217 && mCodec->mNativeWindow != NULL) { 7218 // We push enough 1x1 blank buffers to ensure that one of 7219 // them has made it to the display. This allows the OMX 7220 // component teardown to zero out any protected buffers 7221 // without the risk of scanning out one of those buffers. 7222 pushBlankBuffersToNativeWindow(mCodec->mNativeWindow.get()); 7223 } 7224 7225 if (err != OK) { 7226 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 7227 return; 7228 } 7229 7230 mCodec->changeState(mCodec->mIdleToLoadedState); 7231 } 7232} 7233 7234void ACodec::ExecutingToIdleState::onInputBufferFilled( 7235 const sp<AMessage> &msg) { 7236 BaseState::onInputBufferFilled(msg); 7237 7238 changeStateIfWeOwnAllBuffers(); 7239} 7240 7241void ACodec::ExecutingToIdleState::onOutputBufferDrained( 7242 const sp<AMessage> &msg) { 7243 BaseState::onOutputBufferDrained(msg); 7244 7245 changeStateIfWeOwnAllBuffers(); 7246} 7247 7248//////////////////////////////////////////////////////////////////////////////// 7249 7250ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec) 7251 : BaseState(codec) { 7252} 7253 7254bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) { 7255 bool handled = false; 7256 7257 switch (msg->what()) { 7258 case kWhatShutdown: 7259 { 7260 // We're already doing that... 7261 7262 handled = true; 7263 break; 7264 } 7265 7266 case kWhatFlush: 7267 { 7268 // Don't send me a flush request if you previously wanted me 7269 // to shutdown. 7270 ALOGE("Got flush request in IdleToLoadedState"); 7271 break; 7272 } 7273 7274 default: 7275 handled = BaseState::onMessageReceived(msg); 7276 break; 7277 } 7278 7279 return handled; 7280} 7281 7282void ACodec::IdleToLoadedState::stateEntered() { 7283 ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str()); 7284} 7285 7286bool ACodec::IdleToLoadedState::onOMXEvent( 7287 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 7288 switch (event) { 7289 case OMX_EventCmdComplete: 7290 { 7291 if (data1 != (OMX_U32)OMX_CommandStateSet 7292 || data2 != (OMX_U32)OMX_StateLoaded) { 7293 ALOGE("Unexpected command completion in IdleToLoadedState: %s(%u) %s(%u)", 7294 asString((OMX_COMMANDTYPE)data1), data1, 7295 asString((OMX_STATETYPE)data2), data2); 7296 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 7297 return true; 7298 } 7299 7300 mCodec->changeState(mCodec->mLoadedState); 7301 7302 return true; 7303 } 7304 7305 default: 7306 return BaseState::onOMXEvent(event, data1, data2); 7307 } 7308} 7309 7310//////////////////////////////////////////////////////////////////////////////// 7311 7312ACodec::FlushingState::FlushingState(ACodec *codec) 7313 : BaseState(codec) { 7314} 7315 7316void ACodec::FlushingState::stateEntered() { 7317 ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str()); 7318 7319 mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false; 7320} 7321 7322bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) { 7323 bool handled = false; 7324 7325 switch (msg->what()) { 7326 case kWhatShutdown: 7327 { 7328 mCodec->deferMessage(msg); 7329 break; 7330 } 7331 7332 case kWhatFlush: 7333 { 7334 // We're already doing this right now. 7335 handled = true; 7336 break; 7337 } 7338 7339 default: 7340 handled = BaseState::onMessageReceived(msg); 7341 break; 7342 } 7343 7344 return handled; 7345} 7346 7347bool ACodec::FlushingState::onOMXEvent( 7348 OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) { 7349 ALOGV("[%s] FlushingState onOMXEvent(%u,%d)", 7350 mCodec->mComponentName.c_str(), event, (OMX_S32)data1); 7351 7352 switch (event) { 7353 case OMX_EventCmdComplete: 7354 { 7355 if (data1 != (OMX_U32)OMX_CommandFlush) { 7356 ALOGE("unexpected EventCmdComplete %s(%d) data2:%d in FlushingState", 7357 asString((OMX_COMMANDTYPE)data1), data1, data2); 7358 mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION); 7359 return true; 7360 } 7361 7362 if (data2 == kPortIndexInput || data2 == kPortIndexOutput) { 7363 if (mFlushComplete[data2]) { 7364 ALOGW("Flush already completed for %s port", 7365 data2 == kPortIndexInput ? "input" : "output"); 7366 return true; 7367 } 7368 mFlushComplete[data2] = true; 7369 7370 if (mFlushComplete[kPortIndexInput] && mFlushComplete[kPortIndexOutput]) { 7371 changeStateIfWeOwnAllBuffers(); 7372 } 7373 } else if (data2 == OMX_ALL) { 7374 if (!mFlushComplete[kPortIndexInput] || !mFlushComplete[kPortIndexOutput]) { 7375 ALOGW("received flush complete event for OMX_ALL before ports have been" 7376 "flushed (%d/%d)", 7377 mFlushComplete[kPortIndexInput], mFlushComplete[kPortIndexOutput]); 7378 return false; 7379 } 7380 7381 changeStateIfWeOwnAllBuffers(); 7382 } else { 7383 ALOGW("data2 not OMX_ALL but %u in EventCmdComplete CommandFlush", data2); 7384 } 7385 7386 return true; 7387 } 7388 7389 case OMX_EventPortSettingsChanged: 7390 { 7391 sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec); 7392 msg->setInt32("type", omx_message::EVENT); 7393 msg->setInt32("node", mCodec->mNode); 7394 msg->setInt32("event", event); 7395 msg->setInt32("data1", data1); 7396 msg->setInt32("data2", data2); 7397 7398 ALOGV("[%s] Deferring OMX_EventPortSettingsChanged", 7399 mCodec->mComponentName.c_str()); 7400 7401 mCodec->deferMessage(msg); 7402 7403 return true; 7404 } 7405 7406 default: 7407 return BaseState::onOMXEvent(event, data1, data2); 7408 } 7409 7410 return true; 7411} 7412 7413void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) { 7414 BaseState::onOutputBufferDrained(msg); 7415 7416 changeStateIfWeOwnAllBuffers(); 7417} 7418 7419void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) { 7420 BaseState::onInputBufferFilled(msg); 7421 7422 changeStateIfWeOwnAllBuffers(); 7423} 7424 7425void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() { 7426 if (mFlushComplete[kPortIndexInput] 7427 && mFlushComplete[kPortIndexOutput] 7428 && mCodec->allYourBuffersAreBelongToUs()) { 7429 // We now own all buffers except possibly those still queued with 7430 // the native window for rendering. Let's get those back as well. 7431 mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs(); 7432 7433 mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC)); 7434 7435 sp<AMessage> notify = mCodec->mNotify->dup(); 7436 notify->setInt32("what", CodecBase::kWhatFlushCompleted); 7437 notify->post(); 7438 7439 mCodec->mPortEOS[kPortIndexInput] = 7440 mCodec->mPortEOS[kPortIndexOutput] = false; 7441 7442 mCodec->mInputEOSResult = OK; 7443 7444 if (mCodec->mSkipCutBuffer != NULL) { 7445 mCodec->mSkipCutBuffer->clear(); 7446 } 7447 7448 mCodec->changeState(mCodec->mExecutingState); 7449 } 7450} 7451 7452status_t ACodec::queryCapabilities( 7453 const AString &name, const AString &mime, bool isEncoder, 7454 sp<MediaCodecInfo::Capabilities> *caps) { 7455 (*caps).clear(); 7456 const char *role = getComponentRole(isEncoder, mime.c_str()); 7457 if (role == NULL) { 7458 return BAD_VALUE; 7459 } 7460 7461 OMXClient client; 7462 status_t err = client.connect(); 7463 if (err != OK) { 7464 return err; 7465 } 7466 7467 sp<IOMX> omx = client.interface(); 7468 sp<CodecObserver> observer = new CodecObserver; 7469 IOMX::node_id node = 0; 7470 7471 err = omx->allocateNode(name.c_str(), observer, NULL, &node); 7472 if (err != OK) { 7473 client.disconnect(); 7474 return err; 7475 } 7476 7477 err = setComponentRole(omx, node, role); 7478 if (err != OK) { 7479 omx->freeNode(node); 7480 client.disconnect(); 7481 return err; 7482 } 7483 7484 sp<MediaCodecInfo::CapabilitiesBuilder> builder = new MediaCodecInfo::CapabilitiesBuilder(); 7485 bool isVideo = mime.startsWithIgnoreCase("video/"); 7486 7487 if (isVideo) { 7488 OMX_VIDEO_PARAM_PROFILELEVELTYPE param; 7489 InitOMXParams(¶m); 7490 param.nPortIndex = isEncoder ? kPortIndexOutput : kPortIndexInput; 7491 7492 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { 7493 param.nProfileIndex = index; 7494 status_t err = omx->getParameter( 7495 node, OMX_IndexParamVideoProfileLevelQuerySupported, 7496 ¶m, sizeof(param)); 7497 if (err != OK) { 7498 break; 7499 } 7500 builder->addProfileLevel(param.eProfile, param.eLevel); 7501 7502 if (index == kMaxIndicesToCheck) { 7503 ALOGW("[%s] stopping checking profiles after %u: %x/%x", 7504 name.c_str(), index, 7505 param.eProfile, param.eLevel); 7506 } 7507 } 7508 7509 // Color format query 7510 // return colors in the order reported by the OMX component 7511 // prefix "flexible" standard ones with the flexible equivalent 7512 OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat; 7513 InitOMXParams(&portFormat); 7514 portFormat.nPortIndex = isEncoder ? kPortIndexInput : kPortIndexOutput; 7515 Vector<uint32_t> supportedColors; // shadow copy to check for duplicates 7516 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { 7517 portFormat.nIndex = index; 7518 status_t err = omx->getParameter( 7519 node, OMX_IndexParamVideoPortFormat, 7520 &portFormat, sizeof(portFormat)); 7521 if (err != OK) { 7522 break; 7523 } 7524 7525 OMX_U32 flexibleEquivalent; 7526 if (isFlexibleColorFormat( 7527 omx, node, portFormat.eColorFormat, false /* usingNativeWindow */, 7528 &flexibleEquivalent)) { 7529 bool marked = false; 7530 for (size_t i = 0; i < supportedColors.size(); ++i) { 7531 if (supportedColors[i] == flexibleEquivalent) { 7532 marked = true; 7533 break; 7534 } 7535 } 7536 if (!marked) { 7537 supportedColors.push(flexibleEquivalent); 7538 builder->addColorFormat(flexibleEquivalent); 7539 } 7540 } 7541 supportedColors.push(portFormat.eColorFormat); 7542 builder->addColorFormat(portFormat.eColorFormat); 7543 7544 if (index == kMaxIndicesToCheck) { 7545 ALOGW("[%s] stopping checking formats after %u: %s(%x)", 7546 name.c_str(), index, 7547 asString(portFormat.eColorFormat), portFormat.eColorFormat); 7548 } 7549 } 7550 } else if (mime.equalsIgnoreCase(MEDIA_MIMETYPE_AUDIO_AAC)) { 7551 // More audio codecs if they have profiles. 7552 OMX_AUDIO_PARAM_ANDROID_PROFILETYPE param; 7553 InitOMXParams(¶m); 7554 param.nPortIndex = isEncoder ? kPortIndexOutput : kPortIndexInput; 7555 for (OMX_U32 index = 0; index <= kMaxIndicesToCheck; ++index) { 7556 param.nProfileIndex = index; 7557 status_t err = omx->getParameter( 7558 node, (OMX_INDEXTYPE)OMX_IndexParamAudioProfileQuerySupported, 7559 ¶m, sizeof(param)); 7560 if (err != OK) { 7561 break; 7562 } 7563 // For audio, level is ignored. 7564 builder->addProfileLevel(param.eProfile, 0 /* level */); 7565 7566 if (index == kMaxIndicesToCheck) { 7567 ALOGW("[%s] stopping checking profiles after %u: %x", 7568 name.c_str(), index, 7569 param.eProfile); 7570 } 7571 } 7572 7573 // NOTE: Without Android extensions, OMX does not provide a way to query 7574 // AAC profile support 7575 if (param.nProfileIndex == 0) { 7576 ALOGW("component %s doesn't support profile query.", name.c_str()); 7577 } 7578 } 7579 7580 if (isVideo && !isEncoder) { 7581 native_handle_t *sidebandHandle = NULL; 7582 if (omx->configureVideoTunnelMode( 7583 node, kPortIndexOutput, OMX_TRUE, 0, &sidebandHandle) == OK) { 7584 // tunneled playback includes adaptive playback 7585 builder->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback 7586 | MediaCodecInfo::Capabilities::kFlagSupportsTunneledPlayback); 7587 } else if (omx->storeMetaDataInBuffers( 7588 node, kPortIndexOutput, OMX_TRUE) == OK || 7589 omx->prepareForAdaptivePlayback( 7590 node, kPortIndexOutput, OMX_TRUE, 7591 1280 /* width */, 720 /* height */) == OK) { 7592 builder->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback); 7593 } 7594 } 7595 7596 if (isVideo && isEncoder) { 7597 OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params; 7598 InitOMXParams(¶ms); 7599 params.nPortIndex = kPortIndexOutput; 7600 // TODO: should we verify if fallback is supported? 7601 if (omx->getConfig( 7602 node, (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, 7603 ¶ms, sizeof(params)) == OK) { 7604 builder->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsIntraRefresh); 7605 } 7606 } 7607 7608 *caps = builder; 7609 omx->freeNode(node); 7610 client.disconnect(); 7611 return OK; 7612} 7613 7614// These are supposed be equivalent to the logic in 7615// "audio_channel_out_mask_from_count". 7616//static 7617status_t ACodec::getOMXChannelMapping(size_t numChannels, OMX_AUDIO_CHANNELTYPE map[]) { 7618 switch (numChannels) { 7619 case 1: 7620 map[0] = OMX_AUDIO_ChannelCF; 7621 break; 7622 case 2: 7623 map[0] = OMX_AUDIO_ChannelLF; 7624 map[1] = OMX_AUDIO_ChannelRF; 7625 break; 7626 case 3: 7627 map[0] = OMX_AUDIO_ChannelLF; 7628 map[1] = OMX_AUDIO_ChannelRF; 7629 map[2] = OMX_AUDIO_ChannelCF; 7630 break; 7631 case 4: 7632 map[0] = OMX_AUDIO_ChannelLF; 7633 map[1] = OMX_AUDIO_ChannelRF; 7634 map[2] = OMX_AUDIO_ChannelLR; 7635 map[3] = OMX_AUDIO_ChannelRR; 7636 break; 7637 case 5: 7638 map[0] = OMX_AUDIO_ChannelLF; 7639 map[1] = OMX_AUDIO_ChannelRF; 7640 map[2] = OMX_AUDIO_ChannelCF; 7641 map[3] = OMX_AUDIO_ChannelLR; 7642 map[4] = OMX_AUDIO_ChannelRR; 7643 break; 7644 case 6: 7645 map[0] = OMX_AUDIO_ChannelLF; 7646 map[1] = OMX_AUDIO_ChannelRF; 7647 map[2] = OMX_AUDIO_ChannelCF; 7648 map[3] = OMX_AUDIO_ChannelLFE; 7649 map[4] = OMX_AUDIO_ChannelLR; 7650 map[5] = OMX_AUDIO_ChannelRR; 7651 break; 7652 case 7: 7653 map[0] = OMX_AUDIO_ChannelLF; 7654 map[1] = OMX_AUDIO_ChannelRF; 7655 map[2] = OMX_AUDIO_ChannelCF; 7656 map[3] = OMX_AUDIO_ChannelLFE; 7657 map[4] = OMX_AUDIO_ChannelLR; 7658 map[5] = OMX_AUDIO_ChannelRR; 7659 map[6] = OMX_AUDIO_ChannelCS; 7660 break; 7661 case 8: 7662 map[0] = OMX_AUDIO_ChannelLF; 7663 map[1] = OMX_AUDIO_ChannelRF; 7664 map[2] = OMX_AUDIO_ChannelCF; 7665 map[3] = OMX_AUDIO_ChannelLFE; 7666 map[4] = OMX_AUDIO_ChannelLR; 7667 map[5] = OMX_AUDIO_ChannelRR; 7668 map[6] = OMX_AUDIO_ChannelLS; 7669 map[7] = OMX_AUDIO_ChannelRS; 7670 break; 7671 default: 7672 return -EINVAL; 7673 } 7674 7675 return OK; 7676} 7677 7678} // namespace android 7679