mediafoundation: set reasonable number of reference frames if the user didn't set CODECAPI_AVEncVideoMaxNumRefFrame

Reviewed-by: Yubo Xie <yuboxie@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40511>
This commit is contained in:
Pohsiang (John) Hsu 2026-03-18 12:38:26 -07:00 committed by Marge Bot
parent c97ff97df6
commit d2ad51fc0a
4 changed files with 30 additions and 19 deletions

View file

@ -615,7 +615,7 @@ CDX12EncHMFT::GetParameterRange( const GUID *Api, VARIANT *ValueMin, VARIANT *Va
ValueMin->ulVal = 1;
ValueMax->vt = VT_UI4;
ValueMax->ulVal = m_uiMaxNumRefFrame;
ValueMax->ulVal = GetMaxReferences( m_uiOutputWidth, m_uiOutputHeight );
SteppingDelta->vt = VT_UI4;
SteppingDelta->ulVal = 1;
@ -1572,7 +1572,8 @@ CDX12EncHMFT::SetValue( const GUID *Api, VARIANT *Value )
else if( *Api == CODECAPI_AVEncVideoMaxNumRefFrame )
{
debug_printf( "[dx12 hmft 0x%p] SET CODECAPI_AVEncVideoMaxNumRefFrame - %u\n", this, Value->ulVal );
if( Value->vt != VT_UI4 )
UINT32 maxReferences = GetMaxReferences( m_uiOutputWidth, m_uiOutputHeight );
if( Value->vt != VT_UI4 || Value->ulVal > maxReferences )
{
CHECKHR_GOTO( E_INVALIDARG, done );
}

View file

@ -1143,8 +1143,12 @@ GetMaxDPBSize( int width, int height, eAVEncH264VLevel level_idc )
UINT32
CDX12EncHMFT::GetMaxReferences( unsigned int width, unsigned int height )
{
int maxDPBSize = GetMaxDPBSize( width, height, m_uiLevel );
UINT32 uiMaxReferences = std::min( (int) m_EncoderCapabilities.m_uiMaxHWSupportedDPBCapacity, maxDPBSize );
UINT32 uiMaxReferences = m_EncoderCapabilities.m_uiMaxHWSupportedDPBCapacity;
if( width != 0 && height != 0 )
{
int maxDPBSize = GetMaxDPBSize( width, height, m_uiLevel );
uiMaxReferences = std::min( (int) m_EncoderCapabilities.m_uiMaxHWSupportedDPBCapacity, maxDPBSize );
}
return uiMaxReferences;
}

View file

@ -980,9 +980,13 @@ GetMaxDPBSize( int width, int height, eAVEncH265VLevel level_idc, int minCBSizeY
UINT32
CDX12EncHMFT::GetMaxReferences( unsigned int width, unsigned int height )
{
const int minCbSizeY = 1 << ( m_EncoderCapabilities.m_HWSupportH265BlockSizes.bits.log2_min_luma_coding_block_size_minus3 + 3 );
int maxDPBSize = GetMaxDPBSize( width, height, m_uiLevel, minCbSizeY );
UINT32 uiMaxReferences = std::min( (int) m_EncoderCapabilities.m_uiMaxHWSupportedDPBCapacity, maxDPBSize );
UINT32 uiMaxReferences = m_EncoderCapabilities.m_uiMaxHWSupportedDPBCapacity;
if( width != 0 && height != 0 )
{
const int minCbSizeY = 1 << ( m_EncoderCapabilities.m_HWSupportH265BlockSizes.bits.log2_min_luma_coding_block_size_minus3 + 3 );
int maxDPBSize = GetMaxDPBSize( width, height, m_uiLevel, minCbSizeY );
uiMaxReferences = std::min( (int) m_EncoderCapabilities.m_uiMaxHWSupportedDPBCapacity, maxDPBSize );
}
return uiMaxReferences;
}

View file

@ -888,23 +888,25 @@ CDX12EncHMFT::InitializeEncoder( pipe_video_profile videoProfile, UINT32 Width,
CHECKHR_GOTO( MF_E_OUT_OF_RANGE, done );
}
// Please note in scenarios (e.g LTR or SVC) the backend may need to keep track of more references
// than the m_uiMaxNumRefFrame, since the references may be more in the past (up to 16, 8 frames max before
// depending on the codec)
// TODO: If we know at this point that we're not using LTR nor SVC we can set max_references to
// m_uiMaxNumRefFrame and use less ram, but not sure how would this work with codecapi reconfigurations/dynamic
// LTR/SVC requests
// max_references is the number of previous submitted frame recon pics the frontend reference
// pic trackers will keep track of and can be indexed by current frame submissions by from the L0/L1 reference lists
UINT32 uiMaxNumRefFrame = GetMaxReferences( Width, Height );
// if user sets m_uiMaxNumRefFrame, use that to limit
if( m_bMaxNumRefFrameSet )
// if user didn't set max reference, try to set a reasonable amount
if( !m_bMaxNumRefFrameSet )
{
uiMaxNumRefFrame = std::min( uiMaxNumRefFrame, m_uiMaxNumRefFrame );
UINT32 uiMaxNumRefFrame = GetMaxReferences( Width, Height );
UINT32 uiEstimatedRefFrame = 1 /*current frame*/ + 1 /* slack */ + m_uiMaxLongTermReferences;
if( m_uiLayerCount > 1 )
{
uiEstimatedRefFrame += ( m_uiLayerCount - 1 );
}
if( uiEstimatedRefFrame > uiMaxNumRefFrame )
{
CHECKHR_GOTO( E_INVALIDARG, done );
}
MFE_INFO( "[dx12 hmft 0x%p] HMFT adjusted max_references from %u to %u", this, uiMaxNumRefFrame, uiEstimatedRefFrame );
m_uiMaxNumRefFrame = uiEstimatedRefFrame; // update CodecAPI value.
}
m_uiMaxNumRefFrame = uiMaxNumRefFrame; // update CodecAPI value.
encoderSettings.profile = videoProfile;
encoderSettings.level = m_uiLevel;