mediafoundation: Check driver caps for intra-refresh CodecAPI advertisement

Reviewed-by: Pohsiang (John) Hsu <pohhsu@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37479>
This commit is contained in:
Sil Vilerino 2025-09-16 11:33:25 -04:00 committed by Marge Bot
parent bb42497ee4
commit 0186ff9af5
5 changed files with 61 additions and 16 deletions

View file

@ -342,7 +342,7 @@ CDX12EncHMFT::IsSupported( const GUID *Api )
*Api == CODECAPI_AVEncVideoSelectLayer || *Api == CODECAPI_AVEncVideoEncodeFrameTypeQP ||
*Api == CODECAPI_AVEncSliceControlMode || *Api == CODECAPI_AVEncSliceControlSize ||
*Api == CODECAPI_AVEncVideoMaxNumRefFrame || *Api == CODECAPI_AVEncVideoMeanAbsoluteDifference ||
*Api == CODECAPI_AVEncVideoMaxQP || *Api == CODECAPI_AVEncVideoGradualIntraRefresh || *Api == CODECAPI_AVScenarioInfo ||
*Api == CODECAPI_AVEncVideoMaxQP || *Api == CODECAPI_AVScenarioInfo ||
*Api == CODECAPI_AVEncVideoROIEnabled || *Api == CODECAPI_AVEncVideoLTRBufferControl ||
*Api == CODECAPI_AVEncVideoMarkLTRFrame || *Api == CODECAPI_AVEncVideoUseLTRFrame )
{
@ -350,6 +350,15 @@ CDX12EncHMFT::IsSupported( const GUID *Api )
return hr;
}
if( m_EncoderCapabilities.m_HWSupportsIntraRefreshModes != PIPE_VIDEO_ENC_INTRA_REFRESH_NONE)
{
if( *Api == CODECAPI_AVEncVideoGradualIntraRefresh )
{
hr = S_OK;
return hr;
}
}
if( m_EncoderCapabilities.m_HWSupportDirtyRects.bits.supports_info_type_dirty )
{
if( *Api == CODECAPI_AVEncVideoDirtyRectEnabled )
@ -650,13 +659,19 @@ CDX12EncHMFT::GetParameterValues( const GUID *Api, VARIANT **Values, ULONG *Valu
}
else if( *Api == CODECAPI_AVEncVideoGradualIntraRefresh )
{
// Our HMFT doesn't support HMFT_INTRA_REFRESH_MODE_PERIODIC
*ValuesCount = 2;
CHECKNULL_GOTO( *Values = (VARIANT *) CoTaskMemAlloc( ( *ValuesCount ) * sizeof( VARIANT ) ), E_OUTOFMEMORY, done );
( *Values )[0].vt = VT_UI4;
( *Values )[0].ulVal = HMFT_INTRA_REFRESH_MODE_NONE;
( *Values )[1].vt = VT_UI4;
( *Values )[1].ulVal = HMFT_INTRA_REFRESH_MODE_CONTINUAL;
*ValuesCount = 0; // Assume no support unless reported by driver's capabilities
if( m_EncoderCapabilities.m_HWSupportsIntraRefreshModes != PIPE_VIDEO_ENC_INTRA_REFRESH_NONE)
{
// Our HMFT doesn't support HMFT_INTRA_REFRESH_MODE_PERIODIC
*ValuesCount = 2;
CHECKNULL_GOTO( *Values = (VARIANT *) CoTaskMemAlloc( ( *ValuesCount ) * sizeof( VARIANT ) ), E_OUTOFMEMORY, done );
( *Values )[0].vt = VT_UI4;
( *Values )[0].ulVal = HMFT_INTRA_REFRESH_MODE_NONE;
( *Values )[1].vt = VT_UI4;
( *Values )[1].ulVal = HMFT_INTRA_REFRESH_MODE_CONTINUAL;
}
}
else if( *Api == CODECAPI_AVEncVideoLTRBufferControl )
{
@ -1526,11 +1541,38 @@ CDX12EncHMFT::SetValue( const GUID *Api, VARIANT *Value )
}
else if( *Api == CODECAPI_AVEncVideoGradualIntraRefresh )
{
debug_printf( "[dx12 hmft 0x%p] SET CODECAPI_AVEncVideoGradualIntraRefresh - %u\n", this, Value->ulVal );
if( Value->vt != VT_UI4 || ( ( Value->ulVal & 0xFFFF ) >= HMFT_INTRA_REFRESH_MODE_MAX ) )
UINT uiIntraRefreshMode = Value->ulVal & 0xFFFF;
UINT uiIntraRefreshSize = Value->ulVal >> 16 & 0xFFFF;
if ((uiIntraRefreshMode != 0) && (m_EncoderCapabilities.m_HWSupportsIntraRefreshModes == PIPE_VIDEO_ENC_INTRA_REFRESH_NONE))
{
debug_printf( "[dx12 hmft 0x%p] User tried to set CODECAPI_AVEncVideoGradualIntraRefresh with mode %u, but this "
"encoder does NOT support intra refresh.",
this, uiIntraRefreshMode );
CHECKHR_GOTO( E_INVALIDARG, done );
}
if (uiIntraRefreshSize > m_EncoderCapabilities.m_uiMaxHWSupportedIntraRefreshSize)
{
debug_printf( "[dx12 hmft 0x%p] User tried to set CODECAPI_AVEncVideoGradualIntraRefresh with size %u, but this "
"exceeds the maximum supported by hardware %u.",
this, uiIntraRefreshSize, m_EncoderCapabilities.m_uiMaxHWSupportedIntraRefreshSize );
CHECKHR_GOTO( E_INVALIDARG, done );
}
debug_printf( "[dx12 hmft 0x%p] SET CODECAPI_AVEncVideoGradualIntraRefresh - %u\n", this, Value->ulVal );
if( Value->vt != VT_UI4 )
{
debug_printf( "[dx12 hmft 0x%p] User tried to set CODECAPI_AVEncVideoGradualIntraRefresh with invalid vt %u\n", this, Value->vt );
CHECKHR_GOTO( E_INVALIDARG, done );
}
if( uiIntraRefreshMode >= HMFT_INTRA_REFRESH_MODE_MAX )
{
debug_printf( "[dx12 hmft 0x%p] User tried to set CODECAPI_AVEncVideoGradualIntraRefresh with invalid mode %u\n", this, uiIntraRefreshMode );
CHECKHR_GOTO( E_INVALIDARG, done );
}
m_uiIntraRefreshMode = Value->ulVal & 0xFFFF;
m_uiIntraRefreshSize = Value->ulVal >> 16 & 0xFFFF;
}

View file

@ -492,7 +492,7 @@ CDX12EncHMFT::PrepareForEncodeHelper( LPDX12EncodeContext pDX12EncodeContext, bo
{
// Use current encoder slice config for when NOT doing an intra-refresh wave
intra_refresh_slices_config non_ir_wave_slices_config = {};
CHECKBOOL_GOTO( m_EncoderCapabilities.m_uiHWSupportsIntraRefreshModes, MF_E_UNEXPECTED, done );
CHECKBOOL_GOTO( (m_EncoderCapabilities.m_HWSupportsIntraRefreshModes != PIPE_VIDEO_ENC_INTRA_REFRESH_NONE), MF_E_UNEXPECTED, done );
non_ir_wave_slices_config.slice_mode = pPicInfo->slice_mode;
non_ir_wave_slices_config.num_slice_descriptors = pPicInfo->num_slice_descriptors;
memcpy( non_ir_wave_slices_config.slices_descriptors,

View file

@ -472,7 +472,7 @@ CDX12EncHMFT::PrepareForEncodeHelper( LPDX12EncodeContext pDX12EncodeContext, bo
{
// Use current encoder slice config for when NOT doing an intra-refresh wave
intra_refresh_slices_config non_ir_wave_slices_config = {};
CHECKBOOL_GOTO( m_EncoderCapabilities.m_uiHWSupportsIntraRefreshModes, MF_E_UNEXPECTED, done );
CHECKBOOL_GOTO( (m_EncoderCapabilities.m_HWSupportsIntraRefreshModes != PIPE_VIDEO_ENC_INTRA_REFRESH_NONE), MF_E_UNEXPECTED, done );
non_ir_wave_slices_config.slice_mode = pPicInfo->slice_mode;
non_ir_wave_slices_config.num_slice_descriptors = pPicInfo->num_slice_descriptors;
memcpy( non_ir_wave_slices_config.slices_descriptors,

View file

@ -68,8 +68,11 @@ encoder_capabilities::initialize( pipe_screen *pScreen, pipe_video_profile video
( pScreen->get_video_param( pScreen, videoProfile, PIPE_VIDEO_ENTRYPOINT_ENCODE, PIPE_VIDEO_CAP_ENC_RATE_CONTROL_QVBR ) ==
1 );
m_uiHWSupportsIntraRefreshModes =
pScreen->get_video_param( pScreen, videoProfile, PIPE_VIDEO_ENTRYPOINT_ENCODE, PIPE_VIDEO_CAP_ENC_INTRA_REFRESH );
m_HWSupportsIntraRefreshModes =
(enum pipe_video_enc_intra_refresh_mode) pScreen->get_video_param( pScreen,
videoProfile,
PIPE_VIDEO_ENTRYPOINT_ENCODE,
PIPE_VIDEO_CAP_ENC_INTRA_REFRESH );
m_HWSupportedMetadataFlags =
(enum pipe_video_feedback_metadata_type) pScreen->get_video_param( pScreen,
@ -83,7 +86,7 @@ encoder_capabilities::initialize( pipe_screen *pScreen, pipe_video_profile video
PIPE_VIDEO_ENTRYPOINT_ENCODE,
PIPE_VIDEO_CAP_ENC_H264_DISABLE_DBK_FILTER_MODES_SUPPORTED );
if( m_uiHWSupportsIntraRefreshModes )
if( m_HWSupportsIntraRefreshModes )
{
m_uiMaxHWSupportedIntraRefreshSize = pScreen->get_video_param( pScreen,
videoProfile,

View file

@ -75,7 +75,7 @@ class encoder_capabilities
BOOL m_bHWSupportsQualityVBRRateControlMode = FALSE;
// PIPE_VIDEO_CAP_ENC_INTRA_REFRESH
BOOL m_uiHWSupportsIntraRefreshModes = FALSE;
enum pipe_video_enc_intra_refresh_mode m_HWSupportsIntraRefreshModes = PIPE_VIDEO_ENC_INTRA_REFRESH_NONE;
// PIPE_VIDEO_CAP_ENC_SUPPORTS_FEEDBACK_METADATA
enum pipe_video_feedback_metadata_type m_HWSupportedMetadataFlags = PIPE_VIDEO_FEEDBACK_METADATA_TYPE_BITSTREAM_SIZE;