Ensure there are enough hwframes for Pacer

This commit is contained in:
Cameron Gutman
2026-01-10 18:13:49 -06:00
parent 788675ad59
commit b41c4022ea
5 changed files with 25 additions and 3 deletions

View File

@@ -568,6 +568,11 @@ bool D3D11VARenderer::prepareDecoderContextInGetFormat(AVCodecContext *context,
d3d11vaFramesContext->BindFlags |= D3D11_BIND_SHADER_RESOURCE; d3d11vaFramesContext->BindFlags |= D3D11_BIND_SHADER_RESOURCE;
} }
// Mimic the logic in ff_decode_get_hw_frames_ctx() which adds an extra 3 frames
if (framesContext->initial_pool_size) {
framesContext->initial_pool_size += 3;
}
err = av_hwframe_ctx_init(context->hw_frames_ctx); err = av_hwframe_ctx_init(context->hw_frames_ctx);
if (err < 0) { if (err < 0) {
av_buffer_unref(&context->hw_frames_ctx); av_buffer_unref(&context->hw_frames_ctx);

View File

@@ -57,8 +57,11 @@ private:
int m_DisplayHeight; int m_DisplayHeight;
struct dxva_context m_DXVAContext; struct dxva_context m_DXVAContext;
std::array<Microsoft::WRL::ComPtr<IDirect3DSurface9>, 19> m_DecSurfaces;
std::array<IDirect3DSurface9*, 19> m_DecSurfacesRaw; // Referenced by m_DecSurfaces // H.264 uses a maximum of 16 reference frames
std::array<Microsoft::WRL::ComPtr<IDirect3DSurface9>, 16 + PACER_MAX_OUTSTANDING_FRAMES> m_DecSurfaces;
std::array<IDirect3DSurface9*, 16 + PACER_MAX_OUTSTANDING_FRAMES> m_DecSurfacesRaw; // Referenced by m_DecSurfaces
DXVA2_ConfigPictureDecode m_Config; DXVA2_ConfigPictureDecode m_Config;
Microsoft::WRL::ComPtr<IDirectXVideoDecoderService> m_DecService; Microsoft::WRL::ComPtr<IDirectXVideoDecoderService> m_DecService;
Microsoft::WRL::ComPtr<IDirectXVideoDecoder> m_Decoder; Microsoft::WRL::ComPtr<IDirectXVideoDecoder> m_Decoder;

View File

@@ -19,7 +19,9 @@
// that the sum of all queued frames between both pacing and rendering queues // that the sum of all queued frames between both pacing and rendering queues
// must not exceed the number buffer pool size to avoid running the decoder // must not exceed the number buffer pool size to avoid running the decoder
// out of available decoding surfaces. // out of available decoding surfaces.
#define MAX_QUEUED_FRAMES 4 #define MAX_QUEUED_FRAMES 3
static_assert(PACER_MAX_OUTSTANDING_FRAMES == MAX_QUEUED_FRAMES + 2,
"PACER_MAX_OUTSTANDING_FRAMES and MAX_QUEUED_FRAMES must agree");
// We may be woken up slightly late so don't go all the way // We may be woken up slightly late so don't go all the way
// up to the next V-sync since we may accidentally step into // up to the next V-sync since we may accidentally step into

View File

@@ -7,6 +7,12 @@
#include <QMutex> #include <QMutex>
#include <QWaitCondition> #include <QWaitCondition>
// The maximum number of frames pacer will ever hold is:
// - 3 frames in the pacing queue
// - 1 frame removed from the render queue in the process of rendering
// - 1 frame for deferred free
#define PACER_MAX_OUTSTANDING_FRAMES (3 + 1 + 1)
class IVsyncSource { class IVsyncSource {
public: public:
virtual ~IVsyncSource() {} virtual ~IVsyncSource() {}

View File

@@ -542,6 +542,12 @@ bool FFmpegVideoDecoder::completeInitialization(const AVCodec* decoder, enum AVP
m_VideoDecoderCtx->pkt_timebase.num = 1; m_VideoDecoderCtx->pkt_timebase.num = 1;
m_VideoDecoderCtx->pkt_timebase.den = 90000; m_VideoDecoderCtx->pkt_timebase.den = 90000;
// Allocate enough extra frames for Pacer to avoid stalling the decoder
//
// NB: Subtract 4 because FFmpeg always allocates 4 working surfaces when
// constructing a hwframes context (see ff_decode_get_hw_frames_ctx()).
m_VideoDecoderCtx->extra_hw_frames = std::max<int>(0, PACER_MAX_OUTSTANDING_FRAMES - 4);
// For non-hwaccel decoders, set the pix_fmt to hint to the decoder which // For non-hwaccel decoders, set the pix_fmt to hint to the decoder which
// format should be used. This is necessary for certain decoders like the // format should be used. This is necessary for certain decoders like the
// out-of-tree nvv4l2dec decoders for L4T platforms. We do not do this // out-of-tree nvv4l2dec decoders for L4T platforms. We do not do this