mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-06-15 02:38:28 +02:00
mediafoundation: Support externally provided motion hints
Added support for externally provided motion hints by reading the MFSampleExtension_MoveRegions sample attribute. The motion hint data is converted into pipe_enc_move_info and passed down to the driver for use during encoding. Reviewed-by: Yubo Xie <yuboxie@microsoft.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/39515>
This commit is contained in:
parent
afcead9158
commit
98f5fa618b
5 changed files with 146 additions and 5 deletions
|
|
@ -44,6 +44,8 @@ CDX12EncHMFT::PrepareForEncode( IMFSample *pSample, LPDX12EncodeContext *ppDX12E
|
|||
UINT textureHeight = 0u;
|
||||
bool bReceivedDirtyRectBlob = false;
|
||||
uint32_t dirtyRectFrameNum = UINT32_MAX;
|
||||
bool bReceivedMoveRegionBlob = false;
|
||||
uint32_t moveRegionFrameNum = UINT32_MAX;
|
||||
LONGLONG inputSampleTime = 0;
|
||||
LONGLONG inputSampleDuration = 0;
|
||||
|
||||
|
|
@ -323,6 +325,26 @@ CDX12EncHMFT::PrepareForEncode( IMFSample *pSample, LPDX12EncodeContext *ppDX12E
|
|||
}
|
||||
}
|
||||
|
||||
// Try to get MFSampleExtension_MoveRegions blob only when the HW supports it.
|
||||
if( m_EncoderCapabilities.m_HWSupportMoveRects.bits.supports_precision_full_pixel && m_EncoderCapabilities.m_HWSupportMoveRects.bits.max_motion_hints > 0)
|
||||
{
|
||||
UINT32 cMoveRegionBlob = 0;
|
||||
pSample->GetBlobSize( MFSampleExtension_MoveRegions, &cMoveRegionBlob );
|
||||
if( cMoveRegionBlob >= sizeof( MOVEREGION_INFO ) )
|
||||
{
|
||||
if( m_pMoveRegionBlob.size() < cMoveRegionBlob )
|
||||
{
|
||||
m_pMoveRegionBlob.resize( cMoveRegionBlob );
|
||||
}
|
||||
if( S_OK == pSample->GetBlob( MFSampleExtension_MoveRegions, m_pMoveRegionBlob.data(), cMoveRegionBlob, &cMoveRegionBlob ) )
|
||||
{
|
||||
MOVEREGION_INFO *pMoveRegionInfo = (MOVEREGION_INFO *) m_pMoveRegionBlob.data();
|
||||
moveRegionFrameNum = pMoveRegionInfo->FrameNumber;
|
||||
bReceivedMoveRegionBlob = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( m_pGOPTracker == nullptr )
|
||||
{
|
||||
CHECKHR_GOTO( CreateGOPTracker( textureWidth, textureHeight ), done );
|
||||
|
|
@ -537,7 +559,7 @@ CDX12EncHMFT::PrepareForEncode( IMFSample *pSample, LPDX12EncodeContext *ppDX12E
|
|||
// Call the helper for encoder specific work
|
||||
pDX12EncodeContext->encoderPicInfo.base.in_fence = pPipeEncoderInputFenceHandle;
|
||||
pDX12EncodeContext->encoderPicInfo.base.in_fence_value = pipeEncoderInputFenceHandleValue;
|
||||
CHECKHR_GOTO( PrepareForEncodeHelper( pDX12EncodeContext, bReceivedDirtyRectBlob, dirtyRectFrameNum ), done );
|
||||
CHECKHR_GOTO( PrepareForEncodeHelper( pDX12EncodeContext, bReceivedDirtyRectBlob, dirtyRectFrameNum, bReceivedMoveRegionBlob, moveRegionFrameNum ), done );
|
||||
|
||||
// Needs to be run after PrepareForEncodeHelper to know if current frame is used as reference
|
||||
// Only allocate reconstructed picture copy buffer if feature is enabled and supported
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ extern DWORD
|
|||
CalculateQualityFromQP( DWORD QP );
|
||||
|
||||
HRESULT
|
||||
CDX12EncHMFT::PrepareForEncodeHelper( LPDX12EncodeContext pDX12EncodeContext, bool dirtyRectFrameNumSet, uint32_t dirtyRectFrameNum )
|
||||
CDX12EncHMFT::PrepareForEncodeHelper( LPDX12EncodeContext pDX12EncodeContext, bool dirtyRectFrameNumSet, uint32_t dirtyRectFrameNum, bool moveRegionFrameNumSet, uint32_t moveRegionFrameNum )
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
// done:
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ UpdateH264EncPictureDesc( pipe_h264_enc_picture_desc *pPicInfo,
|
|||
|
||||
// internal function which contains the codec specific portion of PrepareForEncode
|
||||
HRESULT
|
||||
CDX12EncHMFT::PrepareForEncodeHelper( LPDX12EncodeContext pDX12EncodeContext, bool dirtyRectFrameNumSet, uint32_t dirtyRectFrameNum )
|
||||
CDX12EncHMFT::PrepareForEncodeHelper( LPDX12EncodeContext pDX12EncodeContext, bool dirtyRectFrameNumSet, uint32_t dirtyRectFrameNum, bool moveRegionFrameNumSet, uint32_t moveRegionFrameNum )
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
const reference_frames_tracker_frame_descriptor_h264 *cur_frame_desc = nullptr;
|
||||
|
|
@ -403,6 +403,65 @@ CDX12EncHMFT::PrepareForEncodeHelper( LPDX12EncodeContext pDX12EncodeContext, bo
|
|||
}
|
||||
}
|
||||
|
||||
// ----------------------------
|
||||
// Move Regions (motion hints)
|
||||
// ----------------------------
|
||||
|
||||
// Always reset per-frame optional hint structures
|
||||
memset( &pPicInfo->move_info, 0, sizeof( pPicInfo->move_info ) );
|
||||
|
||||
if( moveRegionFrameNumSet && m_EncoderCapabilities.m_HWSupportMoveRects.bits.max_motion_hints > 0 &&
|
||||
m_EncoderCapabilities.m_HWSupportMoveRects.bits.supports_precision_full_pixel &&
|
||||
pPicInfo->picture_type == PIPE_H2645_ENC_PICTURE_TYPE_P ) // P-frames only
|
||||
{
|
||||
uint32_t current_poc = pPicInfo->pic_order_cnt;
|
||||
|
||||
// Validate frame number first
|
||||
if( moveRegionFrameNum != current_poc )
|
||||
{
|
||||
debug_printf( "[dx12 hmft 0x%p] MoveRegions frame mismatch (MRFN=%u, cur POC=%u), ignoring\n",
|
||||
this,
|
||||
moveRegionFrameNum,
|
||||
current_poc );
|
||||
}
|
||||
else
|
||||
{
|
||||
MOVEREGION_INFO *pMoveInfo = reinterpret_cast<MOVEREGION_INFO *>( m_pMoveRegionBlob.data() );
|
||||
uint32_t maxRects = m_EncoderCapabilities.m_HWSupportMoveRects.bits.max_motion_hints;
|
||||
uint32_t numRects = std::min( pMoveInfo->NumMoveRegions, maxRects );
|
||||
|
||||
if( numRects > 0 )
|
||||
{
|
||||
uint8_t surfaceIndex = pPicInfo->ref_list0[0];
|
||||
|
||||
if( surfaceIndex == PIPE_H2645_LIST_REF_INVALID_ENTRY )
|
||||
{
|
||||
debug_printf( "[dx12 hmft 0x%p] MoveRegions: invalid L0 reference, ignoring\n", this );
|
||||
}
|
||||
else
|
||||
{
|
||||
pPicInfo->move_info.input_mode = PIPE_ENC_MOVE_INFO_INPUT_MODE_RECTS;
|
||||
pPicInfo->move_info.num_rects = numRects;
|
||||
pPicInfo->move_info.dpb_reference_index = surfaceIndex;
|
||||
pPicInfo->move_info.precision = PIPE_ENC_MOVE_INFO_PRECISION_UNIT_FULL_PIXEL;
|
||||
|
||||
for( uint32_t i = 0; i < numRects; i++ )
|
||||
{
|
||||
const MOVE_RECT &mr = pMoveInfo->MoveRegions[i];
|
||||
|
||||
pPicInfo->move_info.rects[i].source_point.x = mr.SourcePoint.x;
|
||||
pPicInfo->move_info.rects[i].source_point.y = mr.SourcePoint.y;
|
||||
|
||||
pPicInfo->move_info.rects[i].dest_rect.left = mr.DestRect.left;
|
||||
pPicInfo->move_info.rects[i].dest_rect.top = mr.DestRect.top;
|
||||
pPicInfo->move_info.rects[i].dest_rect.right = mr.DestRect.right;
|
||||
pPicInfo->move_info.rects[i].dest_rect.bottom = mr.DestRect.bottom;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pPicInfo->gpu_stats_qp_map = pDX12EncodeContext->pPipeResourceQPMapStats;
|
||||
pPicInfo->gpu_stats_satd_map = pDX12EncodeContext->pPipeResourceSATDMapStats;
|
||||
pPicInfo->gpu_stats_rc_bitallocation_map = pDX12EncodeContext->pPipeResourceRCBitAllocMapStats;
|
||||
|
|
|
|||
|
|
@ -233,7 +233,7 @@ UpdateH265EncPictureDesc( pipe_h265_enc_picture_desc *pPicInfo,
|
|||
|
||||
// internal function which contains the codec specific portion of PrepareForEncode
|
||||
HRESULT
|
||||
CDX12EncHMFT::PrepareForEncodeHelper( LPDX12EncodeContext pDX12EncodeContext, bool dirtyRectFrameNumSet, uint32_t dirtyRectFrameNum )
|
||||
CDX12EncHMFT::PrepareForEncodeHelper( LPDX12EncodeContext pDX12EncodeContext, bool dirtyRectFrameNumSet, uint32_t dirtyRectFrameNum, bool moveRegionFrameNumSet, uint32_t moveRegionFrameNum )
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
pipe_h265_enc_picture_desc *pPicInfo = &pDX12EncodeContext->encoderPicInfo.h265enc;
|
||||
|
|
@ -384,6 +384,65 @@ CDX12EncHMFT::PrepareForEncodeHelper( LPDX12EncodeContext pDX12EncodeContext, bo
|
|||
}
|
||||
}
|
||||
|
||||
// ----------------------------
|
||||
// Move Regions (motion hints)
|
||||
// ----------------------------
|
||||
|
||||
// Always reset per-frame optional hint structures
|
||||
memset( &pPicInfo->move_info, 0, sizeof( pPicInfo->move_info ) );
|
||||
|
||||
if( moveRegionFrameNumSet && m_EncoderCapabilities.m_HWSupportMoveRects.bits.max_motion_hints > 0 &&
|
||||
m_EncoderCapabilities.m_HWSupportMoveRects.bits.supports_precision_full_pixel &&
|
||||
pPicInfo->picture_type == PIPE_H2645_ENC_PICTURE_TYPE_P ) // P-frames only
|
||||
{
|
||||
uint32_t current_poc = pPicInfo->pic_order_cnt;
|
||||
|
||||
// Validate frame number first
|
||||
if( moveRegionFrameNum != current_poc )
|
||||
{
|
||||
debug_printf( "[dx12 hmft 0x%p] MoveRegions frame mismatch (MRFN=%u, cur POC=%u), ignoring\n",
|
||||
this,
|
||||
moveRegionFrameNum,
|
||||
current_poc );
|
||||
}
|
||||
else
|
||||
{
|
||||
MOVEREGION_INFO *pMoveInfo = reinterpret_cast<MOVEREGION_INFO *>( m_pMoveRegionBlob.data() );
|
||||
uint32_t maxRects = m_EncoderCapabilities.m_HWSupportMoveRects.bits.max_motion_hints;
|
||||
uint32_t numRects = std::min( pMoveInfo->NumMoveRegions, maxRects );
|
||||
|
||||
if( numRects > 0 )
|
||||
{
|
||||
uint8_t surfaceIndex = pPicInfo->ref_list0[0];
|
||||
|
||||
if( surfaceIndex == PIPE_H2645_LIST_REF_INVALID_ENTRY )
|
||||
{
|
||||
debug_printf( "[dx12 hmft 0x%p] MoveRegions: invalid L0 reference, ignoring\n", this );
|
||||
}
|
||||
else
|
||||
{
|
||||
pPicInfo->move_info.input_mode = PIPE_ENC_MOVE_INFO_INPUT_MODE_RECTS;
|
||||
pPicInfo->move_info.num_rects = numRects;
|
||||
pPicInfo->move_info.dpb_reference_index = surfaceIndex;
|
||||
pPicInfo->move_info.precision = PIPE_ENC_MOVE_INFO_PRECISION_UNIT_FULL_PIXEL;
|
||||
|
||||
for( uint32_t i = 0; i < numRects; i++ )
|
||||
{
|
||||
const MOVE_RECT &mr = pMoveInfo->MoveRegions[i];
|
||||
|
||||
pPicInfo->move_info.rects[i].source_point.x = mr.SourcePoint.x;
|
||||
pPicInfo->move_info.rects[i].source_point.y = mr.SourcePoint.y;
|
||||
|
||||
pPicInfo->move_info.rects[i].dest_rect.left = mr.DestRect.left;
|
||||
pPicInfo->move_info.rects[i].dest_rect.top = mr.DestRect.top;
|
||||
pPicInfo->move_info.rects[i].dest_rect.right = mr.DestRect.right;
|
||||
pPicInfo->move_info.rects[i].dest_rect.bottom = mr.DestRect.bottom;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pPicInfo->gpu_stats_qp_map = pDX12EncodeContext->pPipeResourceQPMapStats;
|
||||
pPicInfo->gpu_stats_satd_map = pDX12EncodeContext->pPipeResourceSATDMapStats;
|
||||
pPicInfo->gpu_stats_rc_bitallocation_map = pDX12EncodeContext->pPipeResourceRCBitAllocMapStats;
|
||||
|
|
|
|||
|
|
@ -841,10 +841,11 @@ class __declspec( uuid( HMFT_GUID ) ) CDX12EncHMFT : CMFD3DManager,
|
|||
bool m_bUnlocked = false;
|
||||
HRESULT IsUnlocked( void );
|
||||
|
||||
HRESULT PrepareForEncodeHelper( LPDX12EncodeContext pDX12EncodeContext, bool dirtyRectFrameNumSet, uint32_t dirtyRectFrameNum );
|
||||
HRESULT PrepareForEncodeHelper( LPDX12EncodeContext pDX12EncodeContext, bool dirtyRectFrameNumSet, uint32_t dirtyRectFrameNum, bool moveRegionFrameNumSet, uint32_t moveRegionFrameNum );
|
||||
HRESULT PrepareForEncode( IMFSample *pSample, LPDX12EncodeContext *ppDX12EncodeContext );
|
||||
|
||||
std::vector<BYTE> m_pDirtyRectBlob = std::vector<BYTE>( sizeof( DIRTYRECT_INFO ) );
|
||||
std::vector<BYTE> m_pMoveRegionBlob = std::vector<BYTE>( sizeof( MOVEREGION_INFO ) );
|
||||
|
||||
public:
|
||||
CDX12EncHMFT();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue