1 // Copyright (c) 2018-2019 Intel Corporation 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in all 11 // copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 // SOFTWARE. 20 21 #pragma once 22 23 #include "mfx_common.h" 24 #include "mfx_ext_buffers.h" 25 #include "mfx_trace.h" 26 #include "umc_mutex.h" 27 #include <vector> 28 #include <list> 29 #include <memory> 30 #include "mfxstructures.h" 31 #include "mfx_enc_common.h" 32 #include "assert.h" 33 34 static inline bool operator==(mfxVP9SegmentParam const& l, mfxVP9SegmentParam const& r) 35 { 36 return MFX_EQ_FIELD(FeatureEnabled) 37 && MFX_EQ_FIELD(QIndexDelta) 38 && MFX_EQ_FIELD(LoopFilterLevelDelta) 39 && MFX_EQ_FIELD(ReferenceFrame); 40 } 41 42 namespace MfxHwVP9Encode 43 { 44 45 constexpr auto DPB_SIZE = 8; // DPB size by VP9 spec 46 constexpr auto DPB_SIZE_REAL = 3; // DPB size really used by encoder 47 constexpr auto MAX_SEGMENTS = 8; 48 constexpr auto REF_FRAMES_LOG2 = 3; 49 constexpr auto REF_FRAMES = (1 << REF_FRAMES_LOG2); 50 constexpr auto MAX_REF_LF_DELTAS = 4; 51 constexpr auto MAX_MODE_LF_DELTAS = 2; 52 constexpr auto SEG_LVL_MAX = 4; 53 54 constexpr auto IVF_SEQ_HEADER_SIZE_BYTES = 32; 55 constexpr auto IVF_PIC_HEADER_SIZE_BYTES = 12; 56 constexpr auto MAX_IVF_HEADER_SIZE = IVF_SEQ_HEADER_SIZE_BYTES + IVF_PIC_HEADER_SIZE_BYTES; 57 58 constexpr auto MAX_Q_INDEX = 255; 59 constexpr auto MAX_ICQ_QUALITY_INDEX = 255; 60 constexpr auto MAX_LF_LEVEL = 63; 61 62 constexpr auto MAX_ABS_COEFF_TYPE_Q_INDEX_DELTA = 15; 63 64 constexpr auto MAX_TASK_ID = 0xffff; 65 constexpr auto MAX_NUM_TEMP_LAYERS = 8; 66 constexpr auto MAX_NUM_TEMP_LAYERS_SUPPORTED = 4; 67 68 constexpr auto MAX_UPSCALE_RATIO = 16; 69 constexpr auto MAX_DOWNSCALE_RATIO = 2; 70 71 constexpr auto MIN_TILE_HEIGHT = 128; 72 constexpr auto MIN_TILE_WIDTH = 256; 73 constexpr auto MAX_TILE_WIDTH = 4096; 74 constexpr auto MAX_NUM_TILE_ROWS = 4; 75 constexpr auto MAX_NUM_TILES = 16; 76 77 const mfxU16 segmentSkipMask = 0xf0; 78 const mfxU16 segmentRefMask = 0x0f; 79 80 enum 81 { 82 MFX_MEMTYPE_D3D_INT = MFX_MEMTYPE_FROM_ENCODE | MFX_MEMTYPE_DXVA2_DECODER_TARGET | MFX_MEMTYPE_INTERNAL_FRAME, 83 MFX_MEMTYPE_D3D_EXT = MFX_MEMTYPE_FROM_ENCODE | MFX_MEMTYPE_DXVA2_DECODER_TARGET | MFX_MEMTYPE_EXTERNAL_FRAME, 84 MFX_MEMTYPE_SYS_EXT = MFX_MEMTYPE_FROM_ENCODE | MFX_MEMTYPE_SYSTEM_MEMORY | MFX_MEMTYPE_EXTERNAL_FRAME, 85 MFX_MEMTYPE_SYS_INT = MFX_MEMTYPE_FROM_ENCODE | MFX_MEMTYPE_SYSTEM_MEMORY | MFX_MEMTYPE_INTERNAL_FRAME 86 }; 87 88 static const mfxU16 MFX_IOPATTERN_IN_MASK_SYS_OR_D3D = 89 MFX_IOPATTERN_IN_SYSTEM_MEMORY | MFX_IOPATTERN_IN_VIDEO_MEMORY; 90 91 static const mfxU16 MFX_IOPATTERN_IN_MASK = 92 MFX_IOPATTERN_IN_MASK_SYS_OR_D3D | MFX_IOPATTERN_IN_OPAQUE_MEMORY; 93 94 static const mfxU16 MFX_MEMTYPE_SYS_OR_D3D = 95 MFX_MEMTYPE_DXVA2_DECODER_TARGET | MFX_MEMTYPE_SYSTEM_MEMORY; 96 97 enum // identifies memory type at encoder input w/o any details 98 { 99 INPUT_SYSTEM_MEMORY, 100 INPUT_VIDEO_MEMORY 101 }; 102 103 104 enum eTaskStatus 105 { 106 TASK_FREE = 0, 107 TASK_INITIALIZED, 108 TASK_SUBMITTED 109 }; 110 enum 111 { 112 REF_LAST = 0, 113 REF_GOLD = 1, 114 REF_ALT = 2, 115 REF_TOTAL = 3 116 }; 117 118 enum { 119 KEY_FRAME = 0, 120 INTER_FRAME = 1, 121 NUM_FRAME_TYPES 122 }; 123 124 enum { 125 UNKNOWN_COLOR_SPACE = 0, 126 BT_601 = 1, 127 BT_709 = 2, 128 SMPTE_170 = 3, 129 SMPTE_240 = 4, 130 BT_2020 = 5, 131 RESERVED = 6, 132 SRGB = 7 133 }; 134 135 enum { 136 BITDEPTH_8 = 8, 137 BITDEPTH_10 = 10, 138 BITDEPTH_12 = 12 139 }; 140 141 enum { 142 PROFILE_0 = 0, 143 PROFILE_1 = 1, 144 PROFILE_2 = 2, 145 PROFILE_3 = 3, 146 MAX_PROFILES 147 }; 148 149 // Sequence level parameters should contain only parameters that will not change during encoding 150 struct VP9SeqLevelParam 151 { 152 mfxU8 profile; 153 mfxU8 bitDepth;; 154 mfxU8 colorSpace; 155 mfxU8 colorRange; 156 mfxU8 subsamplingX; 157 mfxU8 subsamplingY; 158 159 mfxU8 frameParallelDecoding; 160 }; 161 162 enum 163 { 164 NO_SEGMENTATION = 0, 165 APP_SEGMENTATION = 1, 166 BRC_SEGMENTATION = 2 167 }; 168 169 struct VP9FrameLevelParam 170 { 171 mfxU8 frameType; 172 mfxU8 baseQIndex; 173 mfxI8 qIndexDeltaLumaDC; 174 mfxI8 qIndexDeltaChromaAC; 175 mfxI8 qIndexDeltaChromaDC; 176 177 mfxU32 width; 178 mfxU32 height; 179 mfxU32 renderWidth; 180 mfxU32 renderHeight; 181 182 mfxU8 refreshFrameContext; 183 mfxU8 resetFrameContext; 184 mfxU8 refList[REF_TOTAL]; // indexes of last, gold, alt refs for current frame 185 mfxU8 refBiases[REF_TOTAL]; 186 mfxU8 refreshRefFrames[DPB_SIZE]; // which reference frames are refreshed with current reconstructed frame 187 mfxU16 modeInfoCols; 188 mfxU16 modeInfoRows; 189 mfxU8 allowHighPrecisionMV; 190 191 mfxU8 showFrame; 192 mfxU8 intraOnly; 193 194 mfxU8 lfLevel; 195 mfxI8 lfRefDelta[4]; 196 mfxI8 lfModeDelta[2]; 197 mfxU8 modeRefDeltaEnabled; 198 mfxU8 modeRefDeltaUpdate; 199 200 mfxU8 sharpness; 201 mfxU8 segmentation; 202 mfxU8 segmentationUpdateMap; 203 mfxU8 segmentationUpdateData; 204 mfxU8 segmentationTemporalUpdate; 205 mfxU16 segmentIdBlockSize; 206 mfxU8 errorResilentMode; 207 mfxU8 interpFilter; 208 mfxU8 frameContextIdx; 209 mfxU8 log2TileCols; 210 mfxU8 log2TileRows; 211 212 mfxU16 temporalLayer; 213 mfxU16 nextTemporalLayer; 214 }; 215 216 struct sFrameEx 217 { 218 mfxFrameSurface1 *pSurface; 219 mfxU32 idInPool; 220 mfxU32 frameOrder; 221 mfxU8 refCount; 222 }; 223 LockSurface(sFrameEx * pFrame,VideoCORE * pCore)224 inline mfxStatus LockSurface(sFrameEx* pFrame, VideoCORE* pCore) 225 { 226 return (pFrame) ? pCore->IncreaseReference(&pFrame->pSurface->Data) : MFX_ERR_NONE; 227 } FreeSurface(sFrameEx * & pFrame,VideoCORE * pCore)228 inline mfxStatus FreeSurface(sFrameEx* &pFrame, VideoCORE* pCore) 229 { 230 mfxStatus sts = MFX_ERR_NONE; 231 if (pFrame && pFrame->pSurface) 232 { 233 sts = pCore->DecreaseReference(&pFrame->pSurface->Data); 234 pFrame = 0; 235 } 236 return sts; 237 } isFreeSurface(sFrameEx * pFrame)238 inline bool isFreeSurface (sFrameEx* pFrame) 239 { 240 return (pFrame->pSurface->Data.Locked == 0); 241 } IncreaseRef(sFrameEx * & pFrame)242 inline void IncreaseRef(sFrameEx* &pFrame) 243 { 244 pFrame->refCount++; 245 } DecreaseRef(sFrameEx * & pFrame,VideoCORE * pCore)246 inline mfxStatus DecreaseRef(sFrameEx* &pFrame, VideoCORE* pCore) 247 { 248 if (pFrame->refCount) 249 { 250 pFrame->refCount--; 251 if (pFrame->refCount == 0) 252 { 253 mfxStatus sts = FreeSurface(pFrame, pCore); 254 MFX_CHECK_STS(sts); 255 } 256 } 257 258 return MFX_ERR_NONE; 259 } 260 Zero(T & obj)261 template<class T> inline void Zero(T & obj) { obj = T(); } Zero(T (& obj)[N])262 template<class T, size_t N> inline void Zero(T (&obj)[N]) { std::fill_n(obj, N, T()); } Zero(std::vector<T> & vec)263 template<class T> inline void Zero(std::vector<T> & vec) { vec.assign(vec.size(), T()); } ZeroExtBuffer(T & obj)264 template<class T> inline void ZeroExtBuffer(T & obj) 265 { 266 mfxExtBuffer header = obj.Header; 267 obj = T(); 268 obj.Header = header; 269 } 270 CeilDiv(mfxU32 x,mfxU32 y)271 inline mfxU32 CeilDiv(mfxU32 x, mfxU32 y) { return (x + y - 1) / y; } CeilLog2(mfxU32 x)272 inline mfxU32 CeilLog2(mfxU32 x) { mfxU32 l = 0; while (x > (1U << l)) l++; return l; } FloorLog2(mfxU32 x)273 inline mfxU32 FloorLog2(mfxU32 x) { mfxU32 l = 0; while (x >= (1U << (l + 1))) l++; return l; } 274 275 template<class T> struct ExtBufTypeToId {}; 276 277 #define BIND_EXTBUF_TYPE_TO_ID(TYPE, ID) template<> struct ExtBufTypeToId<TYPE> { enum { id = ID }; } 278 BIND_EXTBUF_TYPE_TO_ID (mfxExtVP9Param, MFX_EXTBUFF_VP9_PARAM); 279 BIND_EXTBUF_TYPE_TO_ID (mfxExtOpaqueSurfaceAlloc,MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION); 280 BIND_EXTBUF_TYPE_TO_ID (mfxExtCodingOption2, MFX_EXTBUFF_CODING_OPTION2); 281 BIND_EXTBUF_TYPE_TO_ID (mfxExtCodingOption3, MFX_EXTBUFF_CODING_OPTION3); 282 BIND_EXTBUF_TYPE_TO_ID (mfxExtCodingOptionDDI, MFX_EXTBUFF_DDI); 283 BIND_EXTBUF_TYPE_TO_ID (mfxExtVP9Segmentation, MFX_EXTBUFF_VP9_SEGMENTATION); 284 BIND_EXTBUF_TYPE_TO_ID (mfxExtVP9TemporalLayers, MFX_EXTBUFF_VP9_TEMPORAL_LAYERS); 285 #undef BIND_EXTBUF_TYPE_TO_ID 286 InitExtBufHeader(T & extBuf)287 template <class T> inline void InitExtBufHeader(T & extBuf) 288 { 289 Zero(extBuf); 290 extBuf.Header.BufferId = ExtBufTypeToId<T>::id; 291 extBuf.Header.BufferSz = sizeof(T); 292 } 293 294 template <class T> struct GetPointedType {}; 295 template <class T> struct GetPointedType<T *> { typedef T Type; }; 296 template <class T> struct GetPointedType<T const *> { typedef T Type; }; 297 298 struct mfxExtBufferProxy 299 { 300 public: 301 template <typename T> operator T() 302 { 303 mfxExtBuffer * p = GetExtBuffer( 304 m_extParam, 305 m_numExtParam, 306 ExtBufTypeToId<typename GetPointedType<T>::Type>::id); 307 return reinterpret_cast<T>(p); 308 } 309 310 template <typename T> friend mfxExtBufferProxy GetExtBuffer(const T & par); 311 312 protected: 313 mfxExtBufferProxy(mfxExtBuffer ** extParam, mfxU32 numExtParam) 314 : m_extParam(extParam) 315 , m_numExtParam(numExtParam) 316 { 317 } 318 319 private: 320 mfxExtBuffer ** m_extParam; 321 mfxU32 m_numExtParam; 322 }; 323 324 template <typename T> mfxExtBufferProxy GetExtBuffer(T const & par) 325 { 326 return mfxExtBufferProxy(par.ExtParam, par.NumExtParam); 327 } 328 329 struct mfxExtBufferRefProxy{ 330 public: 331 template <typename T> operator T&() 332 { 333 mfxExtBuffer * p = GetExtBuffer( 334 m_extParam, 335 m_numExtParam, 336 ExtBufTypeToId<typename GetPointedType<T*>::Type>::id); 337 assert(p); 338 return *(reinterpret_cast<T*>(p)); 339 } 340 341 template <typename T> friend mfxExtBufferRefProxy GetExtBufferRef(const T & par); 342 343 protected: 344 mfxExtBufferRefProxy(mfxExtBuffer ** extParam, mfxU32 numExtParam) 345 : m_extParam(extParam) 346 , m_numExtParam(numExtParam) 347 { 348 } 349 private: 350 mfxExtBuffer ** m_extParam; 351 mfxU32 m_numExtParam; 352 }; 353 354 template <typename T> mfxExtBufferRefProxy GetExtBufferRef(T const & par) 355 { 356 return mfxExtBufferRefProxy(par.ExtParam, par.NumExtParam); 357 } 358 359 class VP9MfxVideoParam; 360 361 struct ActualExtBufferExtractor { 362 public: 363 template <typename T> operator T&() 364 { 365 mfxExtBuffer * p = GetExtBuffer( 366 m_newParam, 367 m_newNum, 368 ExtBufTypeToId<typename GetPointedType<T*>::Type>::id); 369 if (p) 370 { 371 return *(reinterpret_cast<T*>(p)); 372 } 373 else 374 { 375 p = GetExtBuffer( 376 m_basicParam, 377 m_basicNum, 378 ExtBufTypeToId<typename GetPointedType<T*>::Type>::id); 379 assert(p); 380 return *(reinterpret_cast<T*>(p)); 381 } 382 } 383 384 template <typename T> friend ActualExtBufferExtractor GetActualExtBufferRef(const VP9MfxVideoParam & basicPar, const T & newPar); 385 386 protected: 387 ActualExtBufferExtractor(mfxExtBuffer ** basicParam, mfxU32 basicNum, 388 mfxExtBuffer ** newParam, mfxU32 newNum) 389 : m_basicParam(basicParam) 390 , m_basicNum(basicNum) 391 , m_newParam(newParam) 392 , m_newNum(newNum) 393 394 { 395 } 396 private: 397 mfxExtBuffer ** m_basicParam; 398 mfxU32 m_basicNum; 399 mfxExtBuffer ** m_newParam; 400 mfxU32 m_newNum; 401 }; 402 403 // remove first entry of extended buffer 404 template <typename T> mfxStatus RemoveExtBuffer(T & par, mfxU32 id) 405 { 406 if (par.ExtParam == 0) 407 { 408 return MFX_ERR_NONE; 409 } 410 411 for (mfxU16 i = 0; i < par.NumExtParam; i++) 412 { 413 mfxExtBuffer* pBuf = par.ExtParam[i]; 414 MFX_CHECK_NULL_PTR1(pBuf); 415 if (pBuf->BufferId == id) 416 { 417 for (mfxU16 j = i + 1; j < par.NumExtParam; j++) 418 { 419 par.ExtParam[j - 1] = par.ExtParam[j]; 420 par.ExtParam[j] = 0; 421 } 422 par.NumExtParam--; 423 break; 424 } 425 } 426 427 return MFX_ERR_NONE; 428 } 429 430 class MfxFrameAllocResponse : public mfxFrameAllocResponse 431 { 432 public: 433 MfxFrameAllocResponse(); 434 435 MfxFrameAllocResponse(MfxFrameAllocResponse const &) = delete; 436 MfxFrameAllocResponse & operator =(MfxFrameAllocResponse const &) = delete; 437 438 ~MfxFrameAllocResponse(); 439 440 mfxStatus Alloc( 441 VideoCORE* pCore, 442 mfxFrameAllocRequest & req, 443 bool isCopyRequired); 444 445 mfxStatus Release(); 446 447 mfxFrameInfo m_info; 448 449 private: 450 VideoCORE* m_pCore; 451 mfxU16 m_numFrameActualReturnedByAllocFrames; 452 453 std::vector<mfxFrameAllocResponse> m_responseQueue; 454 std::vector<mfxMemId> m_mids; 455 }; 456 457 struct FrameLocker 458 { 459 FrameLocker(VideoCORE * pCore, mfxFrameData & data) 460 : m_core(pCore) 461 , m_data(data) 462 , m_memId(data.MemId) 463 , m_status(Lock()) 464 { 465 } 466 467 FrameLocker(VideoCORE * pCore, mfxFrameData & data, mfxMemId memId) 468 : m_core(pCore) 469 , m_data(data) 470 , m_memId(memId) 471 , m_status(Lock()) 472 { 473 } 474 475 ~FrameLocker() { Unlock(); } 476 477 mfxStatus Unlock() 478 { 479 mfxStatus mfxSts = MFX_ERR_NONE; 480 mfxSts = m_core->UnlockFrame(m_memId, &m_data); 481 482 m_status = LOCK_NO; 483 return mfxSts; 484 } 485 486 protected: 487 enum { LOCK_NO, LOCK_DONE }; 488 489 mfxU32 Lock() 490 { 491 mfxU32 status = LOCK_NO; 492 493 if (m_data.Y == 0 && 494 MFX_ERR_NONE == m_core->LockFrame(m_memId, &m_data)) 495 status = LOCK_DONE; 496 497 return status; 498 } 499 500 private: 501 FrameLocker(FrameLocker const &); 502 FrameLocker & operator =(FrameLocker const &); 503 504 VideoCORE* m_core; 505 mfxFrameData& m_data; 506 mfxMemId m_memId; 507 mfxU32 m_status; 508 }; 509 510 struct TempLayerParam 511 { 512 mfxU16 Scale; 513 mfxU32 targetKbps; 514 }; 515 516 constexpr auto NUM_OF_SUPPORTED_EXT_BUFFERS = 7; // mfxExtVP9Param, mfxExtOpaqueSurfaceAlloc, mfxExtCodingOption2, mfxExtCodingOption3, mfxExtCodingOptionDDI, mfxExtVP9Segmentation, mfxExtVP9TemporalLayers 517 518 class VP9MfxVideoParam : public mfxVideoParam 519 { 520 public: 521 VP9MfxVideoParam(); 522 VP9MfxVideoParam(VP9MfxVideoParam const &); 523 VP9MfxVideoParam(mfxVideoParam const &); 524 VP9MfxVideoParam(mfxVideoParam const & par, eMFXHWType const & platform); 525 526 VP9MfxVideoParam & operator = (VP9MfxVideoParam const &); 527 VP9MfxVideoParam & operator = (mfxVideoParam const &); 528 529 eMFXHWType m_platform; 530 mfxU16 m_inMemType; 531 mfxU32 m_targetKbps; 532 mfxU32 m_maxKbps; 533 mfxU32 m_bufferSizeInKb; 534 mfxU32 m_initialDelayInKb; 535 536 TempLayerParam m_layerParam[MAX_NUM_TEMP_LAYERS]; 537 538 bool m_segBufPassed; 539 540 bool m_tempLayersBufPassed; 541 bool m_webRTCMode; 542 mfxU16 m_numLayers; 543 544 void CalculateInternalParams(); 545 void SyncInternalParamToExternal(); 546 547 protected: 548 void Construct(mfxVideoParam const & par); 549 550 private: 551 mfxExtBuffer* m_extParam[NUM_OF_SUPPORTED_EXT_BUFFERS]; 552 mfxExtVP9Param m_extPar; 553 mfxExtOpaqueSurfaceAlloc m_extOpaque; 554 mfxExtCodingOption2 m_extOpt2; 555 mfxExtCodingOption3 m_extOpt3; 556 mfxExtCodingOptionDDI m_extOptDDI; 557 mfxExtVP9Segmentation m_extSeg; 558 mfxExtVP9TemporalLayers m_extTempLayers; 559 }; 560 561 template <typename T> ActualExtBufferExtractor GetActualExtBufferRef(VP9MfxVideoParam const & basicPar, T const & newPar) 562 { 563 return ActualExtBufferExtractor(basicPar.ExtParam, basicPar.NumExtParam, newPar.ExtParam, newPar.NumExtParam); 564 } 565 566 class Task; 567 mfxStatus SetFramesParams(VP9MfxVideoParam const &par, 568 Task const & task, 569 mfxU8 frameType, 570 VP9FrameLevelParam &frameParam, 571 eMFXHWType platform); 572 573 mfxStatus InitVp9SeqLevelParam(VP9MfxVideoParam const &video, VP9SeqLevelParam ¶m); 574 575 mfxStatus DecideOnRefListAndDPBRefresh(VP9MfxVideoParam const & par, 576 Task *pTask, 577 std::vector<sFrameEx*>& dpb, 578 VP9FrameLevelParam &frameParam, 579 mfxU32 prevFrameOrderInRefStructure); 580 581 mfxStatus UpdateDpb(VP9FrameLevelParam &frameParam, 582 sFrameEx *pRecFrame, 583 std::vector<sFrameEx*>&dpb, 584 VideoCORE *pCore); 585 586 class ExternalFrames 587 { 588 protected: 589 std::list<sFrameEx> m_frames; 590 public: 591 ExternalFrames() {} 592 void Init(mfxU32 numFrames); 593 mfxStatus GetFrame(mfxFrameSurface1 *pInFrame, sFrameEx *&pOutFrame); 594 }; 595 596 class InternalFrames 597 { 598 protected: 599 std::vector<sFrameEx> m_frames; 600 MfxFrameAllocResponse m_response; 601 std::vector<mfxFrameSurface1> m_surfaces; 602 public: 603 InternalFrames() {} 604 mfxStatus Init(VideoCORE *pCore, mfxFrameAllocRequest *pAllocReq, bool isCopyRequired); 605 sFrameEx * GetFreeFrame(); 606 mfxStatus GetFrame(mfxU32 numFrame, sFrameEx * &Frame); 607 mfxStatus Release(); 608 609 inline mfxU16 Height() 610 { 611 return m_response.m_info.Height; 612 } 613 inline mfxU16 Width() 614 { 615 return m_response.m_info.Width; 616 } 617 inline mfxU32 Num() 618 { 619 return m_response.NumFrameActual; 620 } 621 inline MfxFrameAllocResponse& GetFrameAllocReponse() {return m_response;} 622 }; 623 624 bool isVideoSurfInput(mfxVideoParam const & video); 625 626 inline bool isOpaq(mfxVideoParam const & video) 627 { 628 return (video.IOPattern & MFX_IOPATTERN_IN_OPAQUE_MEMORY)!=0; 629 } 630 631 inline mfxU32 CalcNumTasks(mfxVideoParam const & video) 632 { 633 return video.AsyncDepth; 634 } 635 636 inline mfxU32 CalcNumSurfRecon(mfxVideoParam const & video) 637 { 638 return video.mfx.NumRefFrame + CalcNumTasks(video); 639 } 640 641 inline mfxU32 CalcNumSurfRaw(mfxVideoParam const & video) 642 { 643 // number of input surfaces is same for VIDEO and SYSTEM memory 644 // because so far encoder doesn't support LookAhead and B-frames 645 return video.AsyncDepth + ((video.AsyncDepth > 1)? 1: 0); 646 } 647 648 class Task 649 { 650 public: 651 652 sFrameEx* m_pRawFrame; 653 sFrameEx* m_pRawLocalFrame; 654 mfxBitstream* m_pBitsteam; 655 656 VP9FrameLevelParam m_frameParam; 657 sFrameEx* m_pRecFrame; 658 sFrameEx* m_pRecRefFrames[3]; 659 sFrameEx* m_pOutBs; 660 sFrameEx* m_pSegmentMap; 661 mfxU32 m_frameOrder; 662 mfxU64 m_timeStamp; 663 mfxU32 m_taskIdForDriver; 664 mfxU32 m_frameOrderInGop; 665 mfxU32 m_frameOrderInRefStructure; 666 667 mfxEncodeCtrl m_ctrl; 668 669 mfxU32 m_bsDataLength; 670 671 VP9MfxVideoParam* m_pParam; 672 673 bool m_insertIVFSeqHeader; 674 bool m_resetBrc; 675 676 mfxExtVP9Segmentation const * m_pPrevSegment; 677 678 Task (): 679 m_pRawFrame(NULL), 680 m_pRawLocalFrame(NULL), 681 m_pBitsteam(0), 682 m_pRecFrame(NULL), 683 m_pOutBs(NULL), 684 m_pSegmentMap(NULL), 685 m_frameOrder(0), 686 m_timeStamp(0), 687 m_taskIdForDriver(0), 688 m_frameOrderInGop(0), 689 m_frameOrderInRefStructure(0), 690 m_bsDataLength(0), 691 m_pParam(NULL), 692 m_insertIVFSeqHeader(false), 693 m_resetBrc(false), 694 m_pPrevSegment(NULL) 695 { 696 Zero(m_pRecRefFrames); 697 Zero(m_frameParam); 698 Zero(m_ctrl); 699 } 700 701 ~Task() {}; 702 }; 703 704 inline mfxStatus FreeTask(VideoCORE *pCore, Task &task) 705 { 706 mfxStatus sts = FreeSurface(task.m_pRawFrame, pCore); 707 MFX_CHECK_STS(sts); 708 sts = FreeSurface(task.m_pRawLocalFrame, pCore); 709 MFX_CHECK_STS(sts); 710 sts = FreeSurface(task.m_pOutBs, pCore); 711 MFX_CHECK_STS(sts); 712 sts = FreeSurface(task.m_pSegmentMap, pCore); 713 MFX_CHECK_STS(sts); 714 sts = DecreaseRef(task.m_pRecFrame, pCore); 715 MFX_CHECK_STS(sts); 716 task.m_pRecFrame = 0; 717 718 const VP9MfxVideoParam& curMfxPar = *task.m_pParam; 719 if (curMfxPar.m_numLayers && task.m_frameParam.temporalLayer == curMfxPar.m_numLayers - 1 && 720 curMfxPar.m_numLayers > curMfxPar.mfx.NumRefFrame) 721 { 722 // if last temporal layer is non-reference, need to free reconstructed surface right away. 723 sts = FreeSurface(task.m_pRecFrame, pCore); 724 MFX_CHECK_STS(sts); 725 } 726 727 task.m_pBitsteam = 0; 728 Zero(task.m_frameParam); 729 Zero(task.m_ctrl); 730 731 return MFX_ERR_NONE; 732 } 733 734 inline bool IsBufferBasedBRC(mfxU16 brcMethod) 735 { 736 return brcMethod == MFX_RATECONTROL_CBR 737 || brcMethod == MFX_RATECONTROL_VBR; 738 } 739 740 inline bool IsBitrateBasedBRC(mfxU16 brcMethod) 741 { 742 return IsBufferBasedBRC(brcMethod); 743 } 744 745 inline bool isBrcResetRequired(VP9MfxVideoParam const & parBefore, VP9MfxVideoParam const & parAfter) 746 { 747 mfxU16 brc = parAfter.mfx.RateControlMethod; 748 if (false == IsBitrateBasedBRC(brc)) 749 { 750 return false; 751 } 752 753 double frameRateBefore = (double)parBefore.mfx.FrameInfo.FrameRateExtN / (double)parBefore.mfx.FrameInfo.FrameRateExtD; 754 double frameRateAfter = (double)parAfter.mfx.FrameInfo.FrameRateExtN / (double)parAfter.mfx.FrameInfo.FrameRateExtD; 755 756 mfxExtVP9Param const & extParBefore = GetExtBufferRef(parBefore); 757 mfxExtVP9Param const & extParAfter = GetExtBufferRef(parAfter); 758 759 if (parBefore.m_targetKbps != parAfter.m_targetKbps 760 || ((brc == MFX_RATECONTROL_VBR) && (parBefore.m_maxKbps != parAfter.m_maxKbps)) 761 || frameRateBefore != frameRateAfter 762 || (IsBufferBasedBRC(brc) && (parBefore.m_bufferSizeInKb != parAfter.m_bufferSizeInKb)) 763 || ((brc == MFX_RATECONTROL_ICQ) && (parBefore.mfx.ICQQuality != parAfter.mfx.ICQQuality)) 764 || extParBefore.FrameWidth != extParAfter.FrameWidth 765 || extParBefore.FrameHeight != extParAfter.FrameHeight) 766 { 767 return true; 768 } 769 else 770 { 771 return false; 772 } 773 } 774 775 inline mfxU16 CalcTemporalLayerIndex(VP9MfxVideoParam const & par, mfxU32 frameOrder) 776 { 777 mfxU16 i = 0; 778 mfxExtVP9TemporalLayers const & tl = GetExtBufferRef(par); 779 780 if (par.m_numLayers > 0) 781 { 782 mfxU32 maxScale = tl.Layer[par.m_numLayers - 1].FrameRateScale; 783 for (; i < par.m_numLayers; i++) 784 if (frameOrder % (maxScale / tl.Layer[i].FrameRateScale) == 0) 785 break; 786 } 787 788 return i; 789 } 790 791 // for TS-encoding: context refreshing should be disabled for the 1st frame in each layer 792 // in case if this frame can appear next to the key-frame after layers extraction 793 // this is demand by kernel processing logic 794 inline bool IsNeedDisableRefreshForFrameTS(VP9MfxVideoParam const & par, mfxU32 frameOrderInGop) 795 { 796 if (par.m_numLayers > 1 && frameOrderInGop >= 2) 797 { 798 mfxExtVP9TemporalLayers const & tl = GetExtBufferRef(par); 799 mfxU32 maxScale = tl.Layer[par.m_numLayers - 1].FrameRateScale; 800 if (frameOrderInGop > maxScale) 801 { 802 // not applicable outside of the 1st GOP 803 return false; 804 } 805 else if (frameOrderInGop == maxScale) 806 { 807 // the last affected frame is the first frame in the 2nd GOP 808 return true; 809 } 810 else if (frameOrderInGop <= (maxScale / 2)) 811 { 812 // inside the first GOP affected all frames in the beginning of Layer-2 and Layer-3 813 // (Layer-0 and Layer-1 not affected) 814 if (CalcTemporalLayerIndex(par, frameOrderInGop) < CalcTemporalLayerIndex(par, frameOrderInGop - 1)) 815 { 816 return true; 817 } 818 } 819 } 820 821 return false; 822 } 823 824 mfxStatus GetRealSurface( 825 VideoCORE *pCore, 826 VP9MfxVideoParam const &par, 827 Task const &task, 828 mfxFrameSurface1 *& pSurface); 829 830 mfxStatus GetInputSurface( 831 VideoCORE *pCore, 832 VP9MfxVideoParam const &par, 833 Task const &task, 834 mfxFrameSurface1 *& pSurface); 835 836 mfxStatus CopyRawSurfaceToVideoMemory( 837 VideoCORE *pCore, 838 VP9MfxVideoParam const &par, 839 Task const &task); 840 841 /*mfxStatus ReleaseDpbFrames(VideoCORE* pCore, std::vector<sFrameEx*> & dpb) 842 { 843 for (mfxU8 refIdx = 0; refIdx < dpb.size(); refIdx ++) 844 { 845 if (dpb[refIdx]) 846 { 847 dpb[refIdx]->refCount = 0; 848 MFX_CHECK_STS(FreeSurface(dpb[refIdx], pCore)); 849 } 850 } 851 852 return MFX_ERR_NONE; 853 }*/ 854 855 struct FindTaskByRawSurface 856 { 857 FindTaskByRawSurface(mfxFrameSurface1 * pSurf) : m_pSurface(pSurf) {} 858 859 bool operator ()(Task const & task) 860 { 861 return task.m_pRawFrame->pSurface == m_pSurface; 862 } 863 864 mfxFrameSurface1* m_pSurface; 865 }; 866 867 struct FindTaskByMfxVideoParam 868 { 869 FindTaskByMfxVideoParam(mfxVideoParam* pPar) : m_pPar(pPar) {} 870 871 bool operator ()(Task const & task) 872 { 873 return task.m_pParam == m_pPar; 874 } 875 876 mfxVideoParam* m_pPar; 877 }; 878 879 // full list of essential segmentation parametes is provided 880 inline bool AllMandatorySegMapParams(mfxExtVP9Segmentation const & seg) 881 { 882 return seg.SegmentIdBlockSize && 883 seg.NumSegmentIdAlloc && seg.SegmentId; 884 } 885 886 // at least one essential segmentation parameter is provided 887 inline bool AnyMandatorySegMapParam(mfxExtVP9Segmentation const & seg) 888 { 889 return seg.SegmentIdBlockSize || 890 seg.NumSegmentIdAlloc || seg.SegmentId; 891 } 892 893 inline mfxU16 MapIdToBlockSize(mfxU16 id) 894 { 895 return id; 896 } 897 898 inline bool CompareSegmentMaps(mfxExtVP9Segmentation const & first, mfxExtVP9Segmentation const & second) 899 { 900 if (!first.SegmentId || !second.SegmentId || 901 first.SegmentIdBlockSize != second.SegmentIdBlockSize || 902 !first.NumSegmentIdAlloc || !second.NumSegmentIdAlloc) 903 return false; 904 905 return std::equal(first.SegmentId, first.SegmentId + std::min(first.NumSegmentIdAlloc, second.NumSegmentIdAlloc), second.SegmentId); 906 } 907 908 inline bool CompareSegmentParams(mfxExtVP9Segmentation const & first, mfxExtVP9Segmentation const & second) 909 { 910 if (first.NumSegments != second.NumSegments) 911 return false; 912 913 return std::equal(first.Segment, first.Segment + first.NumSegments, second.Segment); 914 } 915 916 inline void CopySegmentationBuffer(mfxExtVP9Segmentation & dst, mfxExtVP9Segmentation const & src) 917 { 918 mfxU8* tmp = dst.SegmentId; 919 ZeroExtBuffer(dst); 920 dst = src; 921 dst.SegmentId = tmp; 922 if (dst.SegmentId && src.SegmentId && dst.NumSegmentIdAlloc) 923 { 924 std::copy(src.SegmentId, src.SegmentId + dst.NumSegmentIdAlloc, dst.SegmentId); 925 } 926 } 927 928 inline void CombineInitAndRuntimeSegmentBuffers(mfxExtVP9Segmentation & runtime, mfxExtVP9Segmentation const & init) 929 { 930 if (runtime.SegmentId == 0 && init.SegmentId != 0) 931 { 932 runtime.SegmentId = init.SegmentId; 933 runtime.SegmentIdBlockSize = init.SegmentIdBlockSize; 934 runtime.NumSegmentIdAlloc = init.NumSegmentIdAlloc; 935 } 936 } 937 938 enum 939 { 940 FEAT_QIDX = 0, 941 FEAT_LF_LVL = 1, 942 FEAT_REF = 2, 943 FEAT_SKIP = 3 944 }; 945 946 inline bool IsFeatureEnabled(mfxU16 features, mfxU8 feature) 947 { 948 return (features & (1 << feature)) != 0; 949 } 950 951 mfxStatus GetNativeHandleToRawSurface( 952 VideoCORE & core, 953 mfxMemId mid, 954 mfxHDL *handle, 955 VP9MfxVideoParam const & video); 956 957 } // MfxHwVP9Encode 958 959 template<class T, class I> 960 inline bool Clamp(T & opt, I min, I max) 961 { 962 if (opt < static_cast<T>(min)) 963 { 964 opt = static_cast<T>(min); 965 return false; 966 } 967 968 if (opt > static_cast<T>(max)) 969 { 970 opt = static_cast<T>(max); 971 return false; 972 } 973 974 return true; 975 } 976