mediafoundation: setup wpp logging in more of the files and add some error handling on dpb manager and reference frame tracker

Reviewed-by: Yubo Xie <yuboxie@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/38144>
This commit is contained in:
Pohsiang (John) Hsu 2025-10-29 11:03:43 -07:00 committed by Marge Bot
parent ab2457591b
commit 240b9159f4
15 changed files with 344 additions and 200 deletions

View file

@ -28,18 +28,21 @@
#include "pipe/p_screen.h"
#include "util/u_inlines.h"
CD3D12BitstreamMFBuffer::CD3D12BitstreamMFBuffer( pipe_context *pPipeContext,
pipe_resource *pOutputBitRes,
DWORD length,
DWORD offset )
: m_cRef( 1 ),
#include "wpptrace.h"
#include "d3d12_suballoc_mediabuffer.tmh"
CD3D12BitstreamMFBuffer::CD3D12BitstreamMFBuffer(
void *logId, pipe_context *pPipeContext, pipe_resource *pOutputBitRes, DWORD length, DWORD offset )
: m_logId( logId ),
m_cRef( 1 ),
m_dwLength( length ),
m_dwOffset( offset ),
m_pMappedData( nullptr ),
m_pScreen( pPipeContext->screen ),
m_pOutputBitRes( nullptr )
{
debug_printf( "[dx12 hmft 0x%p] CD3D12BitstreamMFBuffer created for length %u, offset %u\n", this, length, offset );
debug_printf( "[dx12 hmft 0x%p] CD3D12BitstreamMFBuffer created for length %u, offset %u\n", m_logId, length, offset );
pipe_resource_reference( &m_pOutputBitRes, pOutputBitRes );
struct winsys_handle whandle = { .type = WINSYS_HANDLE_TYPE_D3D12_RES };

View file

@ -35,6 +35,7 @@ using Microsoft::WRL::ComPtr;
class CD3D12BitstreamMFBuffer : public IMFMediaBuffer
{
private:
const void *m_logId = {};
ULONG m_cRef;
ComPtr<ID3D12Resource> m_spResource;
DWORD m_dwLength;
@ -44,7 +45,7 @@ class CD3D12BitstreamMFBuffer : public IMFMediaBuffer
pipe_resource *m_pOutputBitRes;
public:
CD3D12BitstreamMFBuffer( pipe_context *pPipeContext, pipe_resource *pOutputBitRes, DWORD length, DWORD offset );
CD3D12BitstreamMFBuffer( void *logId, pipe_context *pPipeContext, pipe_resource *pOutputBitRes, DWORD length, DWORD offset );
~CD3D12BitstreamMFBuffer();
// IUnknown

View file

@ -26,6 +26,11 @@
#include "gallium/drivers/d3d12/d3d12_interop_public.h"
#include "vl/vl_video_buffer.h"
#include "wpptrace.h"
#include "dpb_buffer_manager.tmh"
HRESULT
dpb_buffer_manager::get_read_only_handle( struct pipe_video_buffer *buffer,
struct pipe_context *pipe,
@ -120,6 +125,7 @@ dpb_buffer_manager::get_fresh_dpb_buffer()
}
}
MFE_ERROR( "[dx12 hmft 0x%p] failed to find a free buffer", m_logId );
assert( false ); // Did not find an unused buffer
return NULL;
}
@ -138,9 +144,14 @@ dpb_buffer_manager::release_dpb_buffer( struct pipe_video_buffer *target )
}
}
dpb_buffer_manager::dpb_buffer_manager(
struct pipe_video_codec *codec, unsigned width, unsigned height, enum pipe_format buffer_format, unsigned pool_size )
: m_codec( codec ), m_pool( pool_size, { NULL, false } )
dpb_buffer_manager::dpb_buffer_manager( void *logId,
struct pipe_video_codec *codec,
unsigned width,
unsigned height,
enum pipe_format buffer_format,
unsigned pool_size,
HRESULT &hr )
: m_logId( logId ), m_codec( codec ), m_pool( pool_size, { NULL, false } )
{
m_template.width = width;
m_template.height = height;
@ -155,11 +166,36 @@ dpb_buffer_manager::dpb_buffer_manager(
}
for( auto &entry : m_pool )
{
entry.buffer = m_codec->create_dpb_buffer( m_codec, NULL, &m_template );
if( !entry.buffer )
{
MFE_ERROR( "[dx12 hmft 0x%p] create_dpb_buffer failed", m_logId );
assert( false );
hr = E_FAIL;
break;
}
}
if( FAILED( hr ) )
{
for( auto &entry : m_pool )
{
if( entry.buffer )
{
entry.buffer->destroy( entry.buffer );
}
}
}
}
dpb_buffer_manager::~dpb_buffer_manager()
{
for( auto &entry : m_pool )
entry.buffer->destroy( entry.buffer );
{
if( entry.buffer )
{
entry.buffer->destroy( entry.buffer );
}
}
}

View file

@ -29,8 +29,13 @@
class dpb_buffer_manager
{
public:
dpb_buffer_manager(
struct pipe_video_codec *codec, unsigned width, unsigned height, enum pipe_format buffer_format, unsigned pool_size );
dpb_buffer_manager( void *logId,
struct pipe_video_codec *codec,
unsigned width,
unsigned height,
enum pipe_format buffer_format,
unsigned pool_size,
HRESULT &hr );
~dpb_buffer_manager();
// retrieve a buffer from the pool
@ -49,6 +54,7 @@ class dpb_buffer_manager
UINT *pSubresourceIndex );
private:
const void *m_logId = {};
struct pipe_video_codec *m_codec = NULL;
struct pipe_video_buffer m_template = {};

View file

@ -345,16 +345,17 @@ CDX12EncHMFT::PrepareForEncode( IMFSample *pSample, LPDX12EncodeContext *ppDX12E
}
}
m_pGOPTracker->begin_frame( pDX12EncodeContext->pAsyncDPBToken,
m_bForceKeyFrame,
markLTR,
markLTRindex,
useLTR,
useLTRbitmap,
m_bLayerCountSet,
m_uiLayerCount,
bReceivedDirtyRectBlob,
dirtyRectFrameNum );
CHECKHR_GOTO( m_pGOPTracker->begin_frame( pDX12EncodeContext->pAsyncDPBToken,
m_bForceKeyFrame,
markLTR,
markLTRindex,
useLTR,
useLTRbitmap,
m_bLayerCountSet,
m_uiLayerCount,
bReceivedDirtyRectBlob,
dirtyRectFrameNum ),
done );
if( m_bForceKeyFrame )
{
m_bForceKeyFrame = FALSE;
@ -385,7 +386,8 @@ CDX12EncHMFT::PrepareForEncode( IMFSample *pSample, LPDX12EncodeContext *ppDX12E
uint32_t width0 = static_cast<uint32_t>( std::ceil( m_uiOutputWidth / static_cast<float>( block_size ) ) );
uint16_t height0 = static_cast<uint16_t>( std::ceil( m_uiOutputHeight / static_cast<float>( block_size ) ) );
CHECKHR_GOTO( stats_buffer_manager::Create( m_pVlScreen,
CHECKHR_GOTO( stats_buffer_manager::Create( this,
m_pVlScreen,
m_pPipeContext,
MFSampleExtension_VideoEncodeSatdMap,
width0,
@ -410,7 +412,8 @@ CDX12EncHMFT::PrepareForEncode( IMFSample *pSample, LPDX12EncodeContext *ppDX12E
uint32_t width0 = static_cast<uint32_t>( std::ceil( m_uiOutputWidth / static_cast<float>( block_size ) ) );
uint16_t height0 = static_cast<uint16_t>( std::ceil( m_uiOutputHeight / static_cast<float>( block_size ) ) );
CHECKHR_GOTO( stats_buffer_manager::Create( m_pVlScreen,
CHECKHR_GOTO( stats_buffer_manager::Create( this,
m_pVlScreen,
m_pPipeContext,
MFSampleExtension_VideoEncodeBitsUsedMap,
width0,
@ -433,7 +436,8 @@ CDX12EncHMFT::PrepareForEncode( IMFSample *pSample, LPDX12EncodeContext *ppDX12E
uint32_t width0 = static_cast<uint32_t>( std::ceil( m_uiOutputWidth / static_cast<float>( block_size ) ) );
uint16_t height0 = static_cast<uint16_t>( std::ceil( m_uiOutputHeight / static_cast<float>( block_size ) ) );
CHECKHR_GOTO( stats_buffer_manager::Create( m_pVlScreen,
CHECKHR_GOTO( stats_buffer_manager::Create( this,
m_pVlScreen,
m_pPipeContext,
MFSampleExtension_VideoEncodeQPMap,
width0,
@ -545,7 +549,8 @@ CDX12EncHMFT::PrepareForEncode( IMFSample *pSample, LPDX12EncodeContext *ppDX12E
{
if( !m_spReconstructedPictureBufferPool )
{
CHECKHR_GOTO( stats_buffer_manager::Create( m_pVlScreen,
CHECKHR_GOTO( stats_buffer_manager::Create( this,
m_pVlScreen,
m_pPipeContext,
MFSampleExtension_VideoEncodeReconstructedPicture,
pDX12EncodeContext->pPipeVideoBuffer->width,

View file

@ -1114,16 +1114,19 @@ CDX12EncHMFT::CreateGOPTracker( uint32_t textureWidth, uint32_t textureHeight )
if( m_pPipeVideoCodec->two_pass.enable && ( m_pPipeVideoCodec->two_pass.pow2_downscale_factor > 0 ) )
{
upTwoPassDPBManager = std::make_unique<dpb_buffer_manager>(
this,
m_pPipeVideoCodec,
static_cast<unsigned>( std::ceil( textureWidth / ( 1 << m_pPipeVideoCodec->two_pass.pow2_downscale_factor ) ) ),
static_cast<unsigned>( std::ceil( textureHeight / ( 1 << m_pPipeVideoCodec->two_pass.pow2_downscale_factor ) ) ),
ConvertProfileToFormat( m_pPipeVideoCodec->profile ),
m_pPipeVideoCodec->max_references + 1 /*curr pic*/ +
( m_bLowLatency ? 0 :
MFT_INPUT_QUEUE_DEPTH ) /*MFT process input queue depth for delayed in flight recon pic release*/ );
( m_bLowLatency ? 0 : MFT_INPUT_QUEUE_DEPTH ), /*MFT process input queue depth for delayed in flight recon pic release*/
hr );
CHECKHR_GOTO( hr, done );
}
m_pGOPTracker = new reference_frames_tracker_h264( m_pPipeVideoCodec,
m_pGOPTracker = new reference_frames_tracker_h264( this,
m_pPipeVideoCodec,
textureWidth,
textureHeight,
m_uiGopSize,
@ -1135,9 +1138,9 @@ CDX12EncHMFT::CreateGOPTracker( uint32_t textureWidth, uint32_t textureHeight )
m_pPipeVideoCodec->max_references,
m_uiMaxLongTermReferences,
m_gpuFeatureFlags.m_bH264SendUnwrappedPOC,
std::move( upTwoPassDPBManager ) );
CHECKNULL_GOTO( m_pGOPTracker, MF_E_INVALIDMEDIATYPE, done );
std::move( upTwoPassDPBManager ),
hr );
CHECKHR_GOTO( hr, done );
done:
return hr;

View file

@ -955,16 +955,19 @@ CDX12EncHMFT::CreateGOPTracker( uint32_t textureWidth, uint32_t textureHeight )
if( m_pPipeVideoCodec->two_pass.enable && ( m_pPipeVideoCodec->two_pass.pow2_downscale_factor > 0 ) )
{
upTwoPassDPBManager = std::make_unique<dpb_buffer_manager>(
this,
m_pPipeVideoCodec,
static_cast<unsigned>( std::ceil( textureWidth / ( 1 << m_pPipeVideoCodec->two_pass.pow2_downscale_factor ) ) ),
static_cast<unsigned>( std::ceil( textureHeight / ( 1 << m_pPipeVideoCodec->two_pass.pow2_downscale_factor ) ) ),
ConvertProfileToFormat( m_pPipeVideoCodec->profile ),
m_pPipeVideoCodec->max_references + 1 /*curr pic*/ +
( m_bLowLatency ? 0 :
MFT_INPUT_QUEUE_DEPTH ) /*MFT process input queue depth for delayed in flight recon pic release*/ );
( m_bLowLatency ? 0 : MFT_INPUT_QUEUE_DEPTH ) /*MFT process input queue depth for delayed in flight recon pic release*/,
hr );
CHECKHR_GOTO( hr, done );
}
m_pGOPTracker = new reference_frames_tracker_hevc( m_pPipeVideoCodec,
m_pGOPTracker = new reference_frames_tracker_hevc( this,
m_pPipeVideoCodec,
textureWidth,
textureHeight,
m_uiGopSize,
@ -975,8 +978,9 @@ CDX12EncHMFT::CreateGOPTracker( uint32_t textureWidth, uint32_t textureHeight )
MaxHWL0Ref,
m_pPipeVideoCodec->max_references,
m_uiMaxLongTermReferences,
std::move( upTwoPassDPBManager ) );
CHECKNULL_GOTO( m_pGOPTracker, MF_E_INVALIDMEDIATYPE, done );
std::move( upTwoPassDPBManager ),
hr );
CHECKHR_GOTO( hr, done );
done:
return hr;

View file

@ -1319,7 +1319,8 @@ CDX12EncHMFT::ProcessSliceBitstreamZeroCopy( LPDX12EncodeContext pDX12EncodeCont
// Create IMFMediaBuffer from the D3D12Resource (zero-copy)
spMediaBuffer.Attach(
new CD3D12BitstreamMFBuffer( m_pPipeContext,
new CD3D12BitstreamMFBuffer( this,
m_pPipeContext,
pDX12EncodeContext->pOutputBitRes[slice_idx],
static_cast<DWORD>( total_slice_size ),
static_cast<DWORD>( codec_unit_metadata[0 /*offset to first NAL*/].offset ) ) );
@ -1823,7 +1824,8 @@ CDX12EncHMFT::xThreadProc( void *pCtx )
}
// Create IMFMediaBuffer from the D3D12Resource (zero-copy)
spMemoryBuffer.Attach( new CD3D12BitstreamMFBuffer( pThis->m_pPipeContext,
spMemoryBuffer.Attach( new CD3D12BitstreamMFBuffer( pThis,
pThis->m_pPipeContext,
pDX12EncodeContext->pOutputBitRes[0],
static_cast<DWORD>( encoded_bitstream_bytes ),
static_cast<DWORD>( metadata.codec_unit_metadata[0].offset ) ) );

View file

@ -47,16 +47,16 @@ class reference_frames_tracker
{
public:
// pass control variables for current frame to reference tracker and compute reference frame states
virtual void begin_frame( reference_frames_tracker_dpb_async_token *pAsyncDPBToken,
bool forceKey,
bool markLTR,
uint32_t markLTRIndex,
bool useLTR,
uint32_t useLTRBitmap,
bool layerCountSet,
uint32_t layerCount,
bool dirtyRectFrameNumSet,
uint32_t dirtyRectFrameNum ) = 0;
virtual HRESULT begin_frame( reference_frames_tracker_dpb_async_token *pAsyncDPBToken,
bool forceKey,
bool markLTR,
uint32_t markLTRIndex,
bool useLTR,
uint32_t useLTRBitmap,
bool layerCountSet,
uint32_t layerCount,
bool dirtyRectFrameNumSet,
uint32_t dirtyRectFrameNum ) = 0;
// moves the GOP state to the next frame for next frame
virtual void advance_frame() = 0;

View file

@ -32,7 +32,8 @@
#include "reference_frames_tracker_h264.tmh"
reference_frames_tracker_h264::reference_frames_tracker_h264( struct pipe_video_codec *codec,
reference_frames_tracker_h264::reference_frames_tracker_h264( void *logId,
struct pipe_video_codec *codec,
uint32_t textureWidth,
uint32_t textureHeight,
uint32_t gopLength,
@ -44,43 +45,50 @@ reference_frames_tracker_h264::reference_frames_tracker_h264( struct pipe_video_
uint32_t MaxDPBCapacity,
uint32_t MaxLongTermReferences,
bool bSendUnwrappedPOC,
std::unique_ptr<dpb_buffer_manager> upTwoPassDPBManager )
: m_codec( codec ),
std::unique_ptr<dpb_buffer_manager> upTwoPassDPBManager,
HRESULT &hr )
: m_logId( logId ),
m_codec( codec ),
m_MaxL0References( MaxL0References ),
m_MaxDPBCapacity( MaxDPBCapacity ),
m_MaxLongTermReferences( MaxLongTermReferences ),
m_bSendUnwrappedPOC( bSendUnwrappedPOC ),
m_ALL_LTR_VALID_MASK( ( 1 << m_MaxLongTermReferences ) - 1 ),
m_DPBManager(
logId,
m_codec,
textureWidth,
textureHeight,
ConvertProfileToFormat( m_codec->profile ),
m_codec->max_references + 1 /*curr pic*/ +
( bLowLatency ? 0 : MFT_INPUT_QUEUE_DEPTH ) /*MFT process input queue depth for delayed in flight recon pic release*/ ),
( bLowLatency ? 0 : MFT_INPUT_QUEUE_DEPTH ), /*MFT process input queue depth for delayed in flight recon pic release*/
hr ),
m_upTwoPassDPBManager( std::move( upTwoPassDPBManager ) )
{
assert( m_MaxL0References == 1 );
m_bLayerCountSet = bLayerCountSet;
m_uiLayerCount = layerCount;
m_ValidLTRBitmap = m_ALL_LTR_VALID_MASK;
if( SUCCEEDED( hr ) )
{
assert( m_MaxL0References == 1 );
m_bLayerCountSet = bLayerCountSet;
m_uiLayerCount = layerCount;
m_ValidLTRBitmap = m_ALL_LTR_VALID_MASK;
m_gopLength = gopLength;
m_layer_count_set = bLayerCountSet;
m_layer_count = layerCount;
m_force_idr_on_gop_start = true;
m_gopLength = gopLength;
m_layer_count_set = bLayerCountSet;
m_layer_count = layerCount;
m_force_idr_on_gop_start = true;
assert( uiBPictureCount == 0 );
m_p_picture_period = uiBPictureCount + 1;
m_gop_state.idr_pic_id = 0;
assert( uiBPictureCount == 0 );
m_p_picture_period = uiBPictureCount + 1;
m_gop_state.idr_pic_id = 0;
const uint32_t maxFrameNumBitsMinus4 = 4; // legal range is 0 to 12, we will fix to 4 which corresponds to [0..255]
m_gop_state.log2_max_frame_num_minus4 = maxFrameNumBitsMinus4;
m_gop_state.log2_max_pic_order_cnt_lsb_minus4 = maxFrameNumBitsMinus4 + 1;
m_max_frame_num = 1 << ( maxFrameNumBitsMinus4 + 4 );
ResetGopStateToIDR();
const uint32_t maxFrameNumBitsMinus4 = 4; // legal range is 0 to 12, we will fix to 4 which corresponds to [0..255]
m_gop_state.log2_max_frame_num_minus4 = maxFrameNumBitsMinus4;
m_gop_state.log2_max_pic_order_cnt_lsb_minus4 = maxFrameNumBitsMinus4 + 1;
m_max_frame_num = 1 << ( maxFrameNumBitsMinus4 + 4 );
ResetGopStateToIDR();
m_frame_state_descriptor.gop_info = &m_gop_state;
m_frame_state_descriptor.gop_info = &m_gop_state;
}
}
// release reference frame buffers
@ -103,7 +111,7 @@ reference_frames_tracker_h264::release_reconpic( reference_frames_tracker_dpb_as
}
// pass control variables for current frame to reference tracker and compute reference frame states
void
HRESULT
reference_frames_tracker_h264::begin_frame( reference_frames_tracker_dpb_async_token *pAsyncDPBToken,
bool forceKey,
bool markLTR,
@ -115,9 +123,20 @@ reference_frames_tracker_h264::begin_frame( reference_frames_tracker_dpb_async_t
bool dirtyRectFrameNumSet,
uint32_t dirtyRectFrameNum )
{
struct pipe_video_buffer *curframe_dpb_buffer = m_DPBManager.get_fresh_dpb_buffer();
struct pipe_video_buffer *curframe_dpb_downscaled_buffer =
m_upTwoPassDPBManager ? m_upTwoPassDPBManager->get_fresh_dpb_buffer() : NULL;
HRESULT hr = S_OK;
struct pipe_video_buffer *curframe_dpb_buffer = nullptr;
struct pipe_video_buffer *curframe_dpb_downscaled_buffer = nullptr;
uint32_t ltrUsedBitMask = 0;
bool isLTR;
uint32_t longTermReferenceFrameInfo;
curframe_dpb_buffer = m_DPBManager.get_fresh_dpb_buffer();
CHECKNULL_GOTO( curframe_dpb_buffer, E_OUTOFMEMORY, done );
if( m_upTwoPassDPBManager )
{
curframe_dpb_downscaled_buffer = m_upTwoPassDPBManager->get_fresh_dpb_buffer();
CHECKNULL_GOTO( curframe_dpb_downscaled_buffer, E_OUTOFMEMORY, done );
}
if( markLTR )
{
@ -191,16 +210,13 @@ reference_frames_tracker_h264::begin_frame( reference_frames_tracker_dpb_async_t
}
}
const bool isLTR = ( m_frame_state_descriptor.gop_info->reference_type == frame_descriptor_reference_type_long_term );
uint32_t ltrUsedBitMask = 0;
isLTR = ( m_frame_state_descriptor.gop_info->reference_type == frame_descriptor_reference_type_long_term );
if( m_frame_state_descriptor.gop_info->frame_type == PIPE_H2645_ENC_PICTURE_TYPE_P )
{
ltrUsedBitMask = PrepareFrameRefLists( useLTR, useLTRBitmap );
}
uint32_t longTermReferenceFrameInfo =
( ltrUsedBitMask << 16 ) | ( isLTR ? m_frame_state_descriptor.gop_info->ltr_index : 0xFFFF );
longTermReferenceFrameInfo = ( ltrUsedBitMask << 16 ) | ( isLTR ? m_frame_state_descriptor.gop_info->ltr_index : 0xFFFF );
m_gop_state.long_term_reference_frame_info = longTermReferenceFrameInfo; // update GOP state
// fill dpb descriptor
@ -319,6 +335,9 @@ reference_frames_tracker_h264::begin_frame( reference_frames_tracker_dpb_async_t
if( m_upTwoPassDPBManager )
( pAsyncDPBToken )->dpb_downscaled_buffers_to_release.push_back( curframe_dpb_downscaled_buffer );
}
done:
return hr;
}
// prepare the reference list for the current frame
@ -698,7 +717,7 @@ intra_refresh_tracker_row_h264::release_reconpic( reference_frames_tracker_dpb_a
}
// start intra refresh wave and then forward to underlying reference tracker
void
HRESULT
intra_refresh_tracker_row_h264::begin_frame( reference_frames_tracker_dpb_async_token *pAsyncDPBToken,
bool forceKey,
bool markLTR,
@ -710,6 +729,7 @@ intra_refresh_tracker_row_h264::begin_frame( reference_frames_tracker_dpb_async_
bool dirtyRectFrameNumSet,
uint32_t dirtyRectFrameNum )
{
HRESULT hr = S_OK;
if( m_ir_state_desc.intra_refresh_params.mode == INTRA_REFRESH_MODE_UNIT_ROWS )
{
if( ( ++m_ir_state_desc.current_ir_wave_frame_index ) < m_ir_wave_duration )
@ -723,31 +743,36 @@ intra_refresh_tracker_row_h264::begin_frame( reference_frames_tracker_dpb_async_
}
}
m_ref_pics_tracker->begin_frame( pAsyncDPBToken,
forceKey,
markLTR,
mark_ltr_index,
useLTR,
use_ltr_bitmap,
layerCountSet,
layerCount,
dirtyRectFrameNumSet,
dirtyRectFrameNum );
CHECKHR_GOTO( m_ref_pics_tracker->begin_frame( pAsyncDPBToken,
forceKey,
markLTR,
mark_ltr_index,
useLTR,
use_ltr_bitmap,
layerCountSet,
layerCount,
dirtyRectFrameNumSet,
dirtyRectFrameNum ),
done );
// If the underlying GOP tracker signaled an IDR (e.g a new GOP started) let's end any active IR wave
reference_frames_tracker_frame_descriptor_h264 *underlying_frame_desc =
(reference_frames_tracker_frame_descriptor_h264 *) m_ref_pics_tracker->get_frame_descriptor();
if( underlying_frame_desc->gop_info->frame_type == PIPE_H2645_ENC_PICTURE_TYPE_IDR )
{
reset_ir_state_desc();
}
else if( // For P, B frames, restart the continuous IR wave if not already active
( ( underlying_frame_desc->gop_info->frame_type == PIPE_H2645_ENC_PICTURE_TYPE_P ) ||
( underlying_frame_desc->gop_info->frame_type == PIPE_H2645_ENC_PICTURE_TYPE_B ) ) &&
( m_continuous_refresh && ( m_ir_state_desc.intra_refresh_params.mode == INTRA_REFRESH_MODE_NONE ) ) )
{
start_ir_wave();
// If the underlying GOP tracker signaled an IDR (e.g a new GOP started) let's end any active IR wave
reference_frames_tracker_frame_descriptor_h264 *underlying_frame_desc =
(reference_frames_tracker_frame_descriptor_h264 *) m_ref_pics_tracker->get_frame_descriptor();
if( underlying_frame_desc->gop_info->frame_type == PIPE_H2645_ENC_PICTURE_TYPE_IDR )
{
reset_ir_state_desc();
}
else if( // For P, B frames, restart the continuous IR wave if not already active
( ( underlying_frame_desc->gop_info->frame_type == PIPE_H2645_ENC_PICTURE_TYPE_P ) ||
( underlying_frame_desc->gop_info->frame_type == PIPE_H2645_ENC_PICTURE_TYPE_B ) ) &&
( m_continuous_refresh && ( m_ir_state_desc.intra_refresh_params.mode == INTRA_REFRESH_MODE_NONE ) ) )
{
start_ir_wave();
}
}
done:
return hr;
}
// forward to underlying reference tracker

View file

@ -89,23 +89,24 @@ class reference_frames_tracker_h264 : public reference_frames_tracker
uint8_t temporal_id;
} RefSortList;
void begin_frame( reference_frames_tracker_dpb_async_token *pAsyncDPBToken,
bool forceKey,
bool markLTR,
uint32_t markLTRIndex,
bool useLTR,
uint32_t useLTRBitmap,
bool layerCountSet,
uint32_t layerCount,
bool dirtyRectFrameNumSet,
uint32_t dirtyRectFrameNum );
HRESULT begin_frame( reference_frames_tracker_dpb_async_token *pAsyncDPBToken,
bool forceKey,
bool markLTR,
uint32_t markLTRIndex,
bool useLTR,
uint32_t useLTRBitmap,
bool layerCountSet,
uint32_t layerCount,
bool dirtyRectFrameNumSet,
uint32_t dirtyRectFrameNum );
void advance_frame();
const reference_frames_tracker_frame_descriptor *get_frame_descriptor();
void release_reconpic( reference_frames_tracker_dpb_async_token *pAsyncDPBToken );
// Declare other methods
reference_frames_tracker_h264( struct pipe_video_codec *codec,
reference_frames_tracker_h264( void *logId,
struct pipe_video_codec *codec,
uint32_t textureWidth,
uint32_t textureHeight,
uint32_t gopLength,
@ -117,7 +118,8 @@ class reference_frames_tracker_h264 : public reference_frames_tracker
uint32_t MaxDPBCapacity,
uint32_t MaxLongTermReferences,
bool bSendUnwrappedPOC,
std::unique_ptr<dpb_buffer_manager> upTwoPassDPBManager = nullptr );
std::unique_ptr<dpb_buffer_manager> upTwoPassDPBManager,
HRESULT &hr );
private:
uint32_t PrepareFrameRefLists( bool useLTR, uint32_t useLTRBitmap );
@ -150,6 +152,8 @@ class reference_frames_tracker_h264 : public reference_frames_tracker
uint64_t m_ValidSTRFrameNumNoWrap = UINT64_MAX;
std::deque<struct PrevFrameInfo> m_PrevFramesInfos;
const void *m_logId = {};
struct pipe_video_codec *m_codec;
dpb_buffer_manager m_DPBManager;
std::unique_ptr<dpb_buffer_manager> m_upTwoPassDPBManager;
@ -193,16 +197,16 @@ class intra_refresh_tracker_row_h264 : public reference_frames_tracker, public i
{
// reference_frames_tracker
public:
void begin_frame( reference_frames_tracker_dpb_async_token *pAsyncDPBToken,
bool forceKey,
bool markLTR,
uint32_t mark_ltr_index,
bool useLTR,
uint32_t use_ltr_bitmap,
bool layerCountSet,
uint32_t layerCount,
bool dirtyRectFrameNumSet,
uint32_t dirtyRectFrameNum );
HRESULT begin_frame( reference_frames_tracker_dpb_async_token *pAsyncDPBToken,
bool forceKey,
bool markLTR,
uint32_t mark_ltr_index,
bool useLTR,
uint32_t use_ltr_bitmap,
bool layerCountSet,
uint32_t layerCount,
bool dirtyRectFrameNumSet,
uint32_t dirtyRectFrameNum );
void advance_frame(); // GOP Tracker
const reference_frames_tracker_frame_descriptor *get_frame_descriptor();
void release_reconpic( reference_frames_tracker_dpb_async_token *pAsyncDPBToken );

View file

@ -30,7 +30,8 @@
#include "reference_frames_tracker_hevc.tmh"
reference_frames_tracker_hevc::reference_frames_tracker_hevc( struct pipe_video_codec *codec,
reference_frames_tracker_hevc::reference_frames_tracker_hevc( void *logId,
struct pipe_video_codec *codec,
uint32_t textureWidth,
uint32_t textureHeight,
uint32_t gopLength,
@ -41,32 +42,39 @@ reference_frames_tracker_hevc::reference_frames_tracker_hevc( struct pipe_video_
uint32_t MaxL0References,
uint32_t MaxDPBCapacity,
uint32_t MaxLongTermReferences,
std::unique_ptr<dpb_buffer_manager> upTwoPassDPBManager )
: m_codec( codec ),
std::unique_ptr<dpb_buffer_manager> upTwoPassDPBManager,
HRESULT &hr )
: m_logId( logId ),
m_codec( codec ),
m_MaxL0References( MaxL0References ),
m_MaxDPBCapacity( MaxDPBCapacity ),
m_MaxLongTermReferences( MaxLongTermReferences ),
m_DPBManager(
logId,
m_codec,
textureWidth,
textureHeight,
ConvertProfileToFormat( m_codec->profile ),
m_codec->max_references + 1 /*curr pic*/ +
( bLowLatency ? 0 : MFT_INPUT_QUEUE_DEPTH ) /*MFT process input queue depth for delayed in flight recon pic release*/ ),
( bLowLatency ? 0 : MFT_INPUT_QUEUE_DEPTH ) /*MFT process input queue depth for delayed in flight recon pic release*/,
hr ),
m_upTwoPassDPBManager( std::move( upTwoPassDPBManager ) )
{
assert( m_MaxL0References == 1 );
if( SUCCEEDED( hr ) )
{
assert( m_MaxL0References == 1 );
m_gopLength = gopLength;
m_force_idr_on_gop_start = true;
m_p_picture_period = uiBPictureCount + 1;
m_gop_state.log2_max_pic_order_cnt_lsb_minus4 = 4; // legal range is 0 to 12, we will fix to 4 which corresponds to [0..255]
ResetGopStateToIDR();
m_frame_state_descriptor.gop_info = &m_gop_state;
m_gopLength = gopLength;
m_force_idr_on_gop_start = true;
m_p_picture_period = uiBPictureCount + 1;
m_gop_state.log2_max_pic_order_cnt_lsb_minus4 = 4; // legal range is 0 to 12, we will fix to 4 which corresponds to [0..255]
ResetGopStateToIDR();
m_frame_state_descriptor.gop_info = &m_gop_state;
m_frame_state_descriptor.l0_reference_list.resize( 1 );
m_frame_state_descriptor.dpb_snapshot.reserve( m_MaxDPBCapacity + 1 );
m_frame_state_descriptor.dirty_rect_frame_num.reserve( m_MaxDPBCapacity + 1 );
m_frame_state_descriptor.l0_reference_list.resize( 1 );
m_frame_state_descriptor.dpb_snapshot.reserve( m_MaxDPBCapacity + 1 );
m_frame_state_descriptor.dirty_rect_frame_num.reserve( m_MaxDPBCapacity + 1 );
}
}
// release reference frame buffers
@ -89,7 +97,7 @@ reference_frames_tracker_hevc::release_reconpic( reference_frames_tracker_dpb_as
}
// pass control variables for current frame to reference tracker and compute reference frame states
void
HRESULT
reference_frames_tracker_hevc::begin_frame( reference_frames_tracker_dpb_async_token *pAsyncDPBToken,
bool forceKey,
bool markLTR,
@ -101,9 +109,21 @@ reference_frames_tracker_hevc::begin_frame( reference_frames_tracker_dpb_async_t
bool dirtyRectFrameNumSet,
uint32_t dirtyRectFrameNum )
{
struct pipe_video_buffer *curframe_dpb_buffer = m_DPBManager.get_fresh_dpb_buffer();
struct pipe_video_buffer *curframe_dpb_downscaled_buffer =
m_upTwoPassDPBManager ? m_upTwoPassDPBManager->get_fresh_dpb_buffer() : NULL;
HRESULT hr = S_OK;
struct pipe_video_buffer *curframe_dpb_buffer = nullptr;
struct pipe_video_buffer *curframe_dpb_downscaled_buffer = nullptr;
uint32_t ltrUsedBitMask = 0;
uint32_t longTermReferenceFrameInfo;
bool isLTR;
curframe_dpb_buffer = m_DPBManager.get_fresh_dpb_buffer();
CHECKNULL_GOTO( curframe_dpb_buffer, E_OUTOFMEMORY, done );
if( m_upTwoPassDPBManager )
{
curframe_dpb_downscaled_buffer = m_upTwoPassDPBManager->get_fresh_dpb_buffer();
CHECKNULL_GOTO( curframe_dpb_downscaled_buffer, E_OUTOFMEMORY, done );
}
if( markLTR )
{
@ -144,9 +164,8 @@ reference_frames_tracker_hevc::begin_frame( reference_frames_tracker_dpb_async_t
}
}
const bool isLTR = ( m_frame_state_descriptor.gop_info->reference_type == frame_descriptor_reference_type_long_term );
isLTR = ( m_frame_state_descriptor.gop_info->reference_type == frame_descriptor_reference_type_long_term );
uint32_t ltrUsedBitMask = 0;
if( m_frame_state_descriptor.gop_info->frame_type == PIPE_H2645_ENC_PICTURE_TYPE_P )
{
if( useLTR )
@ -176,8 +195,7 @@ reference_frames_tracker_hevc::begin_frame( reference_frames_tracker_dpb_async_t
ltrUsedBitMask = PrepareFrameRefLists();
}
uint32_t longTermReferenceFrameInfo =
( ltrUsedBitMask << 16 ) | ( isLTR ? m_frame_state_descriptor.gop_info->ltr_index : 0xFFFF );
longTermReferenceFrameInfo = ( ltrUsedBitMask << 16 ) | ( isLTR ? m_frame_state_descriptor.gop_info->ltr_index : 0xFFFF );
m_gop_state.long_term_reference_frame_info = longTermReferenceFrameInfo; // Update GOP State
// fill dpb descriptor
@ -267,6 +285,9 @@ reference_frames_tracker_hevc::begin_frame( reference_frames_tracker_dpb_async_t
if( m_upTwoPassDPBManager )
( pAsyncDPBToken )->dpb_downscaled_buffers_to_release.push_back( curframe_dpb_downscaled_buffer );
}
done:
return hr;
}
// prepare the reference list for the current frame
@ -412,7 +433,7 @@ intra_refresh_tracker_row_hevc::release_reconpic( reference_frames_tracker_dpb_a
}
// start intra refresh wave and then forward to underlying reference tracker
void
HRESULT
intra_refresh_tracker_row_hevc::begin_frame( reference_frames_tracker_dpb_async_token *pAsyncDPBToken,
bool forceKey,
bool markLTR,
@ -424,6 +445,7 @@ intra_refresh_tracker_row_hevc::begin_frame( reference_frames_tracker_dpb_async_
bool dirtyRectFrameNumSet,
uint32_t dirtyRectFrameNum )
{
HRESULT hr = S_OK;
if( m_ir_state_desc.intra_refresh_params.mode == INTRA_REFRESH_MODE_UNIT_ROWS )
{
if( ( ++m_ir_state_desc.current_ir_wave_frame_index ) < m_ir_wave_duration )
@ -437,31 +459,36 @@ intra_refresh_tracker_row_hevc::begin_frame( reference_frames_tracker_dpb_async_
}
}
m_ref_pics_tracker->begin_frame( pAsyncDPBToken,
forceKey,
markLTR,
mark_ltr_index,
useLTR,
use_ltr_bitmap,
layerCountSet,
layerCount,
dirtyRectFrameNumSet,
dirtyRectFrameNum );
CHECKHR_GOTO( m_ref_pics_tracker->begin_frame( pAsyncDPBToken,
forceKey,
markLTR,
mark_ltr_index,
useLTR,
use_ltr_bitmap,
layerCountSet,
layerCount,
dirtyRectFrameNumSet,
dirtyRectFrameNum ),
done );
// If the underlying GOP tracker signaled an IDR (e.g a new GOP started) let's end any active IR wave
reference_frames_tracker_frame_descriptor_hevc *underlying_frame_desc =
(reference_frames_tracker_frame_descriptor_hevc *) m_ref_pics_tracker->get_frame_descriptor();
if( underlying_frame_desc->gop_info->frame_type == PIPE_H2645_ENC_PICTURE_TYPE_IDR )
{
reset_ir_state_desc();
}
else if( // For P, B frames, restart the continuous IR wave if not already active
( ( underlying_frame_desc->gop_info->frame_type == PIPE_H2645_ENC_PICTURE_TYPE_P ) ||
( underlying_frame_desc->gop_info->frame_type == PIPE_H2645_ENC_PICTURE_TYPE_B ) ) &&
( m_continuous_refresh && ( m_ir_state_desc.intra_refresh_params.mode == INTRA_REFRESH_MODE_NONE ) ) )
{
start_ir_wave();
// If the underlying GOP tracker signaled an IDR (e.g a new GOP started) let's end any active IR wave
reference_frames_tracker_frame_descriptor_hevc *underlying_frame_desc =
(reference_frames_tracker_frame_descriptor_hevc *) m_ref_pics_tracker->get_frame_descriptor();
if( underlying_frame_desc->gop_info->frame_type == PIPE_H2645_ENC_PICTURE_TYPE_IDR )
{
reset_ir_state_desc();
}
else if( // For P, B frames, restart the continuous IR wave if not already active
( ( underlying_frame_desc->gop_info->frame_type == PIPE_H2645_ENC_PICTURE_TYPE_P ) ||
( underlying_frame_desc->gop_info->frame_type == PIPE_H2645_ENC_PICTURE_TYPE_B ) ) &&
( m_continuous_refresh && ( m_ir_state_desc.intra_refresh_params.mode == INTRA_REFRESH_MODE_NONE ) ) )
{
start_ir_wave();
}
}
done:
return hr;
}
// forward to underlying reference tracker

View file

@ -83,16 +83,16 @@ class reference_frames_tracker_hevc : public reference_frames_tracker
} RefSortList;
// Declare reference_frames_tracker interface methods
void begin_frame( reference_frames_tracker_dpb_async_token *pAsyncDPBToken,
bool forceKey,
bool markLTR,
uint32_t markLTRIndex,
bool useLTR,
uint32_t useLTRBitmap,
bool layerCountSet,
uint32_t layerCount,
bool dirtyRectFrameNumSet,
uint32_t dirtyRectFrameNum );
HRESULT begin_frame( reference_frames_tracker_dpb_async_token *pAsyncDPBToken,
bool forceKey,
bool markLTR,
uint32_t markLTRIndex,
bool useLTR,
uint32_t useLTRBitmap,
bool layerCountSet,
uint32_t layerCount,
bool dirtyRectFrameNumSet,
uint32_t dirtyRectFrameNum );
void advance_frame(); // GOPTracker
@ -100,7 +100,8 @@ class reference_frames_tracker_hevc : public reference_frames_tracker
void release_reconpic( reference_frames_tracker_dpb_async_token *pAsyncDPBToken );
// Declare other methods
reference_frames_tracker_hevc( struct pipe_video_codec *codec,
reference_frames_tracker_hevc( void *logId,
struct pipe_video_codec *codec,
uint32_t textureWidth,
uint32_t textureHeight,
uint32_t gopLength,
@ -111,7 +112,8 @@ class reference_frames_tracker_hevc : public reference_frames_tracker
uint32_t MaxL0References,
uint32_t MaxDPBCapacity,
uint32_t MaxLongTermReferences,
std::unique_ptr<dpb_buffer_manager> upTwoPassDPBManager = nullptr );
std::unique_ptr<dpb_buffer_manager> upTwoPassDPBManager,
HRESULT &hr );
private:
uint32_t PrepareFrameRefLists();
@ -128,6 +130,8 @@ class reference_frames_tracker_hevc : public reference_frames_tracker
uint32_t m_ActiveLTRBitmap = 0;
std::deque<struct PrevFrameInfo> m_PrevFramesInfos;
const void *m_logId = {};
struct pipe_video_codec *m_codec;
dpb_buffer_manager m_DPBManager;
std::unique_ptr<dpb_buffer_manager> m_upTwoPassDPBManager;
@ -163,16 +167,16 @@ class intra_refresh_tracker_row_hevc : public reference_frames_tracker, public i
{
// reference_frames_tracker
public:
void begin_frame( reference_frames_tracker_dpb_async_token *pAsyncDPBToken,
bool forceKey,
bool markLTR,
uint32_t mark_ltr_index,
bool useLTR,
uint32_t use_ltr_bitmap,
bool layerCountSet,
uint32_t layerCount,
bool dirtyRectFrameNumSet,
uint32_t dirtyRectFrameNum );
HRESULT begin_frame( reference_frames_tracker_dpb_async_token *pAsyncDPBToken,
bool forceKey,
bool markLTR,
uint32_t mark_ltr_index,
bool useLTR,
uint32_t use_ltr_bitmap,
bool layerCountSet,
uint32_t layerCount,
bool dirtyRectFrameNumSet,
uint32_t dirtyRectFrameNum );
void advance_frame();
const reference_frames_tracker_frame_descriptor *get_frame_descriptor();
void release_reconpic( reference_frames_tracker_dpb_async_token *pAsyncDPBToken );

View file

@ -65,7 +65,8 @@ ULONG __stdcall stats_buffer_manager::Release()
}
HRESULT
stats_buffer_manager::Create( struct vl_screen *pVlScreen,
stats_buffer_manager::Create( void *logId,
struct vl_screen *pVlScreen,
struct pipe_context *pPipeContext,
REFGUID guidExtension,
uint32_t width,
@ -81,7 +82,7 @@ stats_buffer_manager::Create( struct vl_screen *pVlScreen,
HRESULT hr;
auto pInstance = new ( std::nothrow )
stats_buffer_manager( pVlScreen, pPipeContext, guidExtension, width, height, buffer_format, pool_size, hr );
stats_buffer_manager( logId, pVlScreen, pPipeContext, guidExtension, width, height, buffer_format, pool_size, hr );
if( !pInstance )
return E_OUTOFMEMORY;
@ -110,6 +111,7 @@ stats_buffer_manager::get_new_tracked_buffer()
}
}
MFE_ERROR( "[dx12 hmft 0x%p] failed to find a free buffer", m_logId );
assert( false ); // Did not find an unused buffer
return NULL;
}
@ -119,20 +121,34 @@ void
stats_buffer_manager::release_tracked_buffer( void *target )
{
auto lock = std::lock_guard<std::mutex>( m_lock );
bool found = false;
for( auto &entry : m_pool )
{
bool ret;
struct winsys_handle whandle = {};
whandle.type = WINSYS_HANDLE_TYPE_D3D12_RES;
m_pVlScreen->pscreen->resource_get_handle( m_pVlScreen->pscreen, m_pPipeContext, entry.buffer, &whandle, 0u );
ret = m_pVlScreen->pscreen->resource_get_handle( m_pVlScreen->pscreen, m_pPipeContext, entry.buffer, &whandle, 0u );
if( !ret )
{
MFE_ERROR( "[dx12 hmft 0x%p] resource_get_handle failed", m_logId );
break;
}
if( whandle.com_obj == target )
{
entry.used = false;
found = true;
break;
}
}
if( !found )
{
MFE_ERROR( "[dx12 hmft 0x%p] returned buffer was not found in the pool", m_logId );
}
}
stats_buffer_manager::stats_buffer_manager( struct vl_screen *pVlScreen,
stats_buffer_manager::stats_buffer_manager( void *logId,
struct vl_screen *pVlScreen,
struct pipe_context *pPipeContext,
REFGUID resourceGUID,
uint32_t width,
@ -140,7 +156,11 @@ stats_buffer_manager::stats_buffer_manager( struct vl_screen *pVlScreen,
enum pipe_format buffer_format,
unsigned pool_size,
HRESULT &hr )
: m_pVlScreen( pVlScreen ), m_pPipeContext( pPipeContext ), m_resourceGUID( resourceGUID ), m_pool( pool_size, { NULL, false } )
: m_logId( logId ),
m_pVlScreen( pVlScreen ),
m_pPipeContext( pPipeContext ),
m_resourceGUID( resourceGUID ),
m_pool( pool_size, { NULL, false } )
{
hr = S_OK;
m_template.target = PIPE_TEXTURE_2D;
@ -157,7 +177,8 @@ stats_buffer_manager::stats_buffer_manager( struct vl_screen *pVlScreen,
entry.buffer = m_pVlScreen->pscreen->resource_create( m_pVlScreen->pscreen, &m_template );
if( !entry.buffer )
{
assert( true );
MFE_ERROR( "[dx12 hmft 0x%p] resource_create failed", m_logId );
assert( false );
hr = E_FAIL;
break;
}

View file

@ -56,7 +56,8 @@ class stats_buffer_manager : public IUnknown
HRESULT
AttachPipeResourceAsSampleExtension( struct pipe_resource *pPipeRes, ID3D12CommandQueue *pSyncObjectQueue, IMFSample *pSample );
static HRESULT Create( struct vl_screen *pVlScreen,
static HRESULT Create( void *logId,
struct vl_screen *pVlScreen,
struct pipe_context *pPipeContext,
REFGUID guidExtension,
uint32_t width,
@ -66,7 +67,8 @@ class stats_buffer_manager : public IUnknown
stats_buffer_manager **ppInstance );
private:
stats_buffer_manager( struct vl_screen *m_pVlScreen,
stats_buffer_manager( void *logId,
struct vl_screen *m_pVlScreen,
pipe_context *pPipeContext,
REFGUID guidExtension,
uint32_t width,
@ -80,6 +82,7 @@ class stats_buffer_manager : public IUnknown
STDMETHOD( OnSampleAvailable )( __in IMFAsyncResult *pAsyncResult );
METHODASYNCCALLBACKEX( OnSampleAvailable, stats_buffer_manager, 0, MFASYNC_CALLBACK_QUEUE_MULTITHREADED );
const void *m_logId = {};
std::mutex m_lock;
GUID m_resourceGUID {};
ULONG m_refCount = 0;