From 212742bb1a76fef3c2ddbe6d78ddb2102f6cb48a Mon Sep 17 00:00:00 2001 From: Zhizhen Tang Date: Tue, 28 Mar 2023 21:28:21 +0800 Subject: [PATCH] Add B pyramid check when configured hevc level Signed-off-by: Zhizhen Tang --- .../base/hevcehw_base_constraints.cpp | 24 ++++++++++++++++--- .../agnostic/base/hevcehw_base_constraints.h | 5 +++- .../agnostic/base/hevcehw_base_legacy.cpp | 15 ++++++++++-- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/_studio/mfx_lib/encode_hw/hevc/agnostic/base/hevcehw_base_constraints.cpp b/_studio/mfx_lib/encode_hw/hevc/agnostic/base/hevcehw_base_constraints.cpp index b3560c514e..de641ca9a5 100644 --- a/_studio/mfx_lib/encode_hw/hevc/agnostic/base/hevcehw_base_constraints.cpp +++ b/_studio/mfx_lib/encode_hw/hevc/agnostic/base/hevcehw_base_constraints.cpp @@ -153,6 +153,20 @@ const mfxU16 LevelIdxToMfx[] = MFX_LEVEL_HEVC_62, }; +inline mfxU16 MinRefForPyramid(mfxU16 GopRefDist, bool bField) +{ + assert(GopRefDist > 0); + mfxU16 refB = (GopRefDist - 1) / 2; + + for (mfxU16 x = refB; x > 2;) + { + x = (x - 1) / 2; + refB -= x; + } + + return bField ? ((2 + refB)*2 +1) : (2 + refB); +} + inline mfxU16 MaxTidx(mfxU16 l) { return (LevelIdxToMfx[std::min(l, MaxLidx)] >= MFX_LEVEL_HEVC_4); } mfxU16 MfxLevel(mfxU16 l, mfxU16 t) { return LevelIdxToMfx[std::min(l, MaxLidx)] | (MFX_TIER_HEVC_HIGH * !!t); } @@ -163,14 +177,17 @@ mfxU16 HEVCEHW::Base::GetMinLevel( , mfxU16 PicWidthInLumaSamples , mfxU16 PicHeightInLumaSamples , mfxU16 MinRef + , mfxU16 GopRefDist , mfxU16 NumTileColumns , mfxU16 NumTileRows , mfxU32 NumSlice , mfxU32 BufferSizeInKB , mfxU32 MaxKbps - , mfxU16 StartLevel) + , mfxU16 StartLevel + , bool isBPyramid + , bool isField) { - bool bInvalid = frN == 0 || frD == 0; + bool bInvalid = (frN == 0 || frD == 0 || GopRefDist == 0); if (bInvalid) return 0; @@ -208,6 +225,7 @@ mfxU16 HEVCEHW::Base::GetMinLevel( || NumTileColumns > MaxTileCols || NumTileRows > MaxTileRows || NumSlice > MaxSSPP + || (isBPyramid && MaxDpbSize < MinRefForPyramid(GopRefDist, isField)) || bMaxTier; bNextTier &= !bNextLevel; @@ -224,4 +242,4 @@ mfxU16 HEVCEHW::Base::GetMinLevel( -#endif //defined(MFX_ENABLE_H265_VIDEO_ENCODE) \ No newline at end of file +#endif //defined(MFX_ENABLE_H265_VIDEO_ENCODE) diff --git a/_studio/mfx_lib/encode_hw/hevc/agnostic/base/hevcehw_base_constraints.h b/_studio/mfx_lib/encode_hw/hevc/agnostic/base/hevcehw_base_constraints.h index cfb819efa9..edb9a1026e 100644 --- a/_studio/mfx_lib/encode_hw/hevc/agnostic/base/hevcehw_base_constraints.h +++ b/_studio/mfx_lib/encode_hw/hevc/agnostic/base/hevcehw_base_constraints.h @@ -39,12 +39,15 @@ namespace Base , mfxU16 PicWidthInLumaSamples , mfxU16 PicHeightInLumaSamples , mfxU16 MinRef + , mfxU16 GopRefDist , mfxU16 NumTileColumns , mfxU16 NumTileRows , mfxU32 NumSlice , mfxU32 BufferSizeInKB , mfxU32 MaxKbps - , mfxU16 StartLevel); + , mfxU16 StartLevel + , bool isBPyramid + , bool isField); } //Base } //namespace HEVCEHW diff --git a/_studio/mfx_lib/encode_hw/hevc/agnostic/base/hevcehw_base_legacy.cpp b/_studio/mfx_lib/encode_hw/hevc/agnostic/base/hevcehw_base_legacy.cpp index e26d1c2f1e..40984b544b 100644 --- a/_studio/mfx_lib/encode_hw/hevc/agnostic/base/hevcehw_base_legacy.cpp +++ b/_studio/mfx_lib/encode_hw/hevc/agnostic/base/hevcehw_base_legacy.cpp @@ -3503,12 +3503,15 @@ void Legacy::SetDefaults( , defPar.base.GetCodedPicWidth(defPar) , defPar.base.GetCodedPicHeight(defPar) , par.mfx.NumRefFrame + , par.mfx.GopRefDist , nCol , nRow , par.mfx.NumSlice , BufferSizeInKB(par.mfx) , MaxKbps(par.mfx) - , MFX_LEVEL_HEVC_1); + , MFX_LEVEL_HEVC_1 + , (pCO2 && (pCO2->BRefType == MFX_B_REF_PYRAMID)) + , (par.mfx.FrameInfo.PicStruct & (MFX_PICSTRUCT_FIELD_TOP | MFX_PICSTRUCT_FIELD_BOTTOM))); }; if (pHEVC) @@ -3581,6 +3584,8 @@ mfxStatus Legacy::CheckLevelConstraints( { MFX_CHECK(par.mfx.CodecLevel, MFX_ERR_NONE); + mfxExtCodingOption2* pCO2 = ExtBuffer::Get(par); + mfxU16 PicWidthInLumaSamples = defPar.base.GetCodedPicWidth(defPar); mfxU16 PicHeightInLumaSamples = defPar.base.GetCodedPicHeight(defPar); mfxU16 MinRef = defPar.base.GetNumRefFrames(defPar); @@ -3591,6 +3596,9 @@ mfxStatus Legacy::CheckLevelConstraints( auto tiles = defPar.base.GetNumTiles(defPar); auto frND = defPar.base.GetFrameRate(defPar); + bool isBPyramid = (pCO2 && (pCO2->BRefType == MFX_B_REF_PYRAMID)); + bool isField = (par.mfx.FrameInfo.PicStruct & (MFX_PICSTRUCT_FIELD_TOP | MFX_PICSTRUCT_FIELD_BOTTOM)); + SetIf(MaxKbps , rc != MFX_RATECONTROL_CQP && rc != MFX_RATECONTROL_ICQ , [&]() { return defPar.base.GetMaxKbps(defPar); }); @@ -3601,12 +3609,15 @@ mfxStatus Legacy::CheckLevelConstraints( , PicWidthInLumaSamples , PicHeightInLumaSamples , MinRef + , par.mfx.GopRefDist , std::get<0>(tiles) , std::get<1>(tiles) , NumSlice , BufferSizeInKB , MaxKbps - , par.mfx.CodecLevel); + , par.mfx.CodecLevel + , isBPyramid + , isField); MFX_CHECK(!CheckMinOrClip(par.mfx.CodecLevel, minLevel), MFX_WRN_INCOMPATIBLE_VIDEO_PARAM);