mediafoundation: change frame preanalysis rc from ifdef to runtime control
Some checks are pending
macOS-CI / macOS-CI (dri) (push) Waiting to run
macOS-CI / macOS-CI (xlib) (push) Waiting to run

add support for specifying the following experimental controls

- CODECAPI_AVEncVideoRateControlFramePreAnalysis
- CODECAPI_AVEncVideoRateControlFramePreAnalysisExternalReconDownscale

to make testing easier.

Reviewed-by: Sil Vilerino <sivileri@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36236>
This commit is contained in:
Pohsiang (John) Hsu 2025-07-17 15:25:49 -07:00 committed by Marge Bot
parent 71f61ae7bb
commit 4f7076f458
4 changed files with 139 additions and 25 deletions

View file

@ -266,6 +266,15 @@ StringFromCodecAPI( const GUID *Api )
{
return "CODECAPI_AVEncVideoSatdMapBlockSize";
}
else if (*Api == CODECAPI_AVEncVideoRateControlFramePreAnalysis)
{
return "CODECAPI_AVEncVideoRateControlFramePreAnalysis";
}
else if( *Api == CODECAPI_AVEncVideoRateControlFramePreAnalysisExternalReconDownscale )
{
return "CODECAPI_AVEncVideoRateControlFramePreAnalysisExternalReconDownscale";
}
return "Unknown CodecAPI";
}
@ -376,6 +385,24 @@ CDX12EncHMFT::IsSupported( const GUID *Api )
}
}
if( m_EncoderCapabilities.m_TwoPassSupport.bits.supports_two_pass )
{
if( *Api == CODECAPI_AVEncVideoRateControlFramePreAnalysis )
{
hr = S_OK;
return hr;
}
}
if( m_EncoderCapabilities.m_TwoPassSupport.bits.supports_1pass_recon_writing_skip )
{
if( *Api == CODECAPI_AVEncVideoRateControlFramePreAnalysisExternalReconDownscale )
{
hr = S_OK;
return hr;
}
}
done:
return hr;
}
@ -833,6 +860,16 @@ CDX12EncHMFT::GetValue( const GUID *Api, VARIANT *Value )
(ULONG) ( 1 << m_EncoderCapabilities.m_HWSupportStatsSATDMapOutput.bits.log2_values_block_size ) :
0;
}
else if( *Api == CODECAPI_AVEncVideoRateControlFramePreAnalysis )
{
Value->vt = VT_BOOL;
Value->boolVal = m_bRateControlFramePreAnalysis ? VARIANT_TRUE : VARIANT_FALSE;
}
else if( *Api == CODECAPI_AVEncVideoRateControlFramePreAnalysisExternalReconDownscale )
{
Value->vt = VT_BOOL;
Value->boolVal = m_bRateControlFramePreAnalysisExternalReconDownscale ? VARIANT_TRUE : VARIANT_FALSE;
}
else
{
hr = E_NOTIMPL;
@ -1555,6 +1592,45 @@ CDX12EncHMFT::SetValue( const GUID *Api, VARIANT *Value )
}
m_uiVideoSatdMapBlockSize = Value->ulVal;
}
else if( *Api == CODECAPI_AVEncVideoRateControlFramePreAnalysis )
{
debug_printf( "[dx12 hmft 0x%p] SET CODECAPI_AVEncVideoRateControlFramePreAnalysis - %s\n",
this,
(bool) Value->boolVal ? "true" : "false" );
if( Value->vt != VT_UI4 && Value->vt != VT_BOOL )
{
CHECKHR_GOTO( E_INVALIDARG, done );
}
if( !m_EncoderCapabilities.m_TwoPassSupport.bits.supports_two_pass && Value->boolVal )
{
MFE_ERROR( "[dx12 hmft 0x%p] User tried to set CODECAPI_AVEncVideoRateControlFramePreAnalysis, but this encoder does NOT "
"support this feature.",
this );
CHECKHR_GOTO( E_INVALIDARG, done );
}
m_bRateControlFramePreAnalysis = Value->boolVal == VARIANT_TRUE ? TRUE : FALSE;
}
else if( *Api == CODECAPI_AVEncVideoRateControlFramePreAnalysisExternalReconDownscale )
{
debug_printf( "[dx12 hmft 0x%p] SET CODECAPI_AVEncVideoRateControlFramePreAnalysisExternalReconDownscale - %s\n",
this,
(bool) Value->boolVal ? "true" : "false" );
if( Value->vt != VT_UI4 && Value->vt != VT_BOOL )
{
CHECKHR_GOTO( E_INVALIDARG, done );
}
if( !m_EncoderCapabilities.m_TwoPassSupport.bits.supports_1pass_recon_writing_skip && Value->boolVal )
{
MFE_ERROR( "[dx12 hmft 0x%p] User tried to set CODECAPI_AVEncVideoRateControlFramePreAnalysisExternalReconDownscale, but "
"this encoder does NOT "
"support this feature.",
this );
CHECKHR_GOTO( E_INVALIDARG, done );
}
m_bRateControlFramePreAnalysisExternalReconDownscale = Value->boolVal == VARIANT_TRUE ? TRUE : FALSE;
}
else
{
CHECKHR_GOTO( E_NOTIMPL, done );

View file

@ -220,9 +220,9 @@ CDX12EncHMFT::PrepareForEncode( IMFSample *pSample, LPDX12EncodeContext *ppDX12E
pPipeEncoderInputFenceHandle = m_pPipeFenceHandle;
pipeEncoderInputFenceHandleValue = m_CurrentSyncFenceValue;
}
#if ENCODE_WITH_TWO_PASS
else
{
{ // ENCODE_WITH_TWO_PASS code block
// TODO: In case the app sends the downscaled input remove this
//
@ -276,7 +276,6 @@ CDX12EncHMFT::PrepareForEncode( IMFSample *pSample, LPDX12EncodeContext *ppDX12E
assert(pPipeEncoderInputFenceHandle); // Driver must have returned the completion fence
pDX12EncodeContext->pDownscaledTwoPassPipeVideoBufferCompletionFence = pPipeEncoderInputFenceHandle; // For destruction of the fence later
}
#endif // ENCODE_WITH_TWO_PASS
// validate texture dimensions with surface alignment here for now, will add handling for non-aligned textures later
if( textureWidth % surfaceWidthAlignment != 0 || textureHeight % surfaceHeightAlignment != 0 )

View file

@ -64,9 +64,7 @@ using namespace concurrency;
using namespace Microsoft::WRL;
using Microsoft::WRL::ComPtr;
#define ENCODE_WITH_TWO_PASS 0
#define ENCODE_WITH_TWO_PASS_LOWEST_RES 1
#define ENCODE_WITH_TWO_PASS_EXTERNAL_DPB_RECON_SCALE 1
#define NUM_INPUT_TYPES 3
@ -384,6 +382,48 @@ DEFINE_GUID( MFSampleExtension_VideoEncodeSatdMap, 0xadf61d96, 0xc2d3, 0x4b57, 0
#endif
#ifndef CODECAPI_AVEncVideoRateControlFramePreAnalysis
// AVEncVideoRateControlFramePreAnalysis (VT_BOOL) (Experimental, Testing only)
// Indicates whether to enable or disable rate control frame preanalysis
// VARIANT_FALSE: disable; VARIANT_TRUE: enable
DEFINE_CODECAPI_GUID( AVEncVideoRateControlFramePreAnalysis,
"CF229C1D-FA9A-4BBA-9E08-269F3CF5D621",
0xcf229c1d,
0xfa9a,
0x4bba,
0x9e,
0x8,
0x26,
0x9f,
0x3c,
0xf5,
0xd6,
0x21 )
#define CODECAPI_AVEncVideoRateControlFramePreAnalysis DEFINE_CODECAPI_GUIDNAMED( AVEncVideoRateControlFramePreAnalysis )
#endif
#ifndef CODECAPI_AVEncVideoRateControlFramePreAnalysisExternalReconDownscale
// CODECAPI_AVEncVideoRateControlFramePreAnalysisExternalReconDownscale (VT_BOOL) (Experimental, Testing only)
// Indicates whether to enable or disable external recon downscale in rate control frame preanalysis
// VARIANT_FALSE: disable; VARIANT_TRUE: enable
DEFINE_CODECAPI_GUID( AVEncVideoRateControlFramePreAnalysisExternalReconDownscale,
"C53DEFA4-138A-4310-864F-4516661C56E7",
0xc53defa4,
0x138a,
0x4310,
0x86,
0x4f,
0x45,
0x16,
0x66,
0x1c,
0x56,
0xe7 )
#define CODECAPI_AVEncVideoRateControlFramePreAnalysisExternalReconDownscale \
DEFINE_CODECAPI_GUIDNAMED( AVEncVideoRateControlFramePreAnalysisExternalReconDownscale )
#endif
#if MFT_CODEC_H264ENC
#define HMFT_GUID "8994db7c-288a-4c62-a136-a3c3c2a208a8"
#elif MFT_CODEC_H265ENC
@ -571,6 +611,9 @@ class __declspec( uuid( HMFT_GUID ) ) CDX12EncHMFT : CMFD3DManager,
UINT32 m_uiVideoOutputBitsUsedMapBlockSize = 0;
UINT32 m_uiVideoSatdMapBlockSize = 0;
BOOL m_bRateControlFramePreAnalysis = FALSE;
BOOL m_bRateControlFramePreAnalysisExternalReconDownscale = FALSE;
struct pipe_video_codec *m_pPipeVideoCodec = nullptr;
struct pipe_video_codec *m_pPipeVideoBlitter = nullptr;
reference_frames_tracker *m_pGOPTracker = nullptr;

View file

@ -859,33 +859,29 @@ CDX12EncHMFT::InitializeEncoder( pipe_video_profile videoProfile, UINT32 Width,
CHECKHR_GOTO( E_INVALIDARG, done );
}
#if ENCODE_WITH_TWO_PASS
encoderSettings.two_pass.enable = 1;
if( m_bRateControlFramePreAnalysis )
{
encoderSettings.two_pass.enable = 1;
#if ENCODE_WITH_TWO_PASS_LOWEST_RES
encoderSettings.two_pass.pow2_downscale_factor = m_EncoderCapabilities.m_TwoPassSupport.bits.max_pow2_downscale_factor;
encoderSettings.two_pass.pow2_downscale_factor = m_EncoderCapabilities.m_TwoPassSupport.bits.max_pow2_downscale_factor;
#else
encoderSettings.two_pass.pow2_downscale_factor = m_EncoderCapabilities.m_TwoPassSupport.bits.min_pow2_downscale_factor;
encoderSettings.two_pass.pow2_downscale_factor = m_EncoderCapabilities.m_TwoPassSupport.bits.min_pow2_downscale_factor;
#endif // ENCODE_WITH_TWO_PASS_LOWEST_RES
#if ENCODE_WITH_TWO_PASS_EXTERNAL_DPB_RECON_SCALE
encoderSettings.two_pass.skip_1st_dpb_texture = m_EncoderCapabilities.m_TwoPassSupport.bits.supports_1pass_recon_writing_skip;
#else
encoderSettings.two_pass.skip_1st_dpb_texture = 0u;
#endif // ENCODE_WITH_TWO_PASS_EXTERNAL_DPB_RECON_SCALE
encoderSettings.two_pass.skip_1st_dpb_texture = m_bRateControlFramePreAnalysisExternalReconDownscale ? true : false;
if( encoderSettings.two_pass.enable && ( encoderSettings.two_pass.pow2_downscale_factor > 0 ) )
{
struct pipe_video_codec blitterSettings = {};
blitterSettings.entrypoint = PIPE_VIDEO_ENTRYPOINT_PROCESSING;
blitterSettings.width = Width;
blitterSettings.height = Height;
CHECKNULL_GOTO( m_pPipeVideoBlitter = m_pPipeContext->create_video_codec( m_pPipeContext, &blitterSettings ),
MF_E_UNEXPECTED,
done );
if( encoderSettings.two_pass.enable && ( encoderSettings.two_pass.pow2_downscale_factor > 0 ) )
{
struct pipe_video_codec blitterSettings = {};
blitterSettings.entrypoint = PIPE_VIDEO_ENTRYPOINT_PROCESSING;
blitterSettings.width = Width;
blitterSettings.height = Height;
CHECKNULL_GOTO( m_pPipeVideoBlitter = m_pPipeContext->create_video_codec( m_pPipeContext, &blitterSettings ),
MF_E_UNEXPECTED,
done );
}
}
#endif // ENCODE_WITH_TWO_PASS
CHECKNULL_GOTO( m_pPipeVideoCodec = m_pPipeContext->create_video_codec( m_pPipeContext, &encoderSettings ),
MF_E_UNEXPECTED,
done );