From d501a627f0cbe8f024a0163aba3d7c8d80723e79 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Mon, 22 Dec 2025 23:58:26 -0600 Subject: [PATCH] Test all renderers before use Every renderer except SDL had opted-in for testing due to various quirks discovered over the years, so just do away with this option and test all renderers. --- app/streaming/video/ffmpeg-renderers/cuda.cpp | 5 --- app/streaming/video/ffmpeg-renderers/cuda.h | 1 - .../video/ffmpeg-renderers/d3d11va.cpp | 9 ----- .../video/ffmpeg-renderers/d3d11va.h | 1 - app/streaming/video/ffmpeg-renderers/drm.cpp | 5 --- app/streaming/video/ffmpeg-renderers/drm.h | 1 - .../video/ffmpeg-renderers/genhwaccel.cpp | 5 --- .../video/ffmpeg-renderers/genhwaccel.h | 1 - app/streaming/video/ffmpeg-renderers/mmal.cpp | 7 ---- app/streaming/video/ffmpeg-renderers/mmal.h | 1 - app/streaming/video/ffmpeg-renderers/plvk.cpp | 6 --- app/streaming/video/ffmpeg-renderers/plvk.h | 1 - .../video/ffmpeg-renderers/renderer.h | 6 --- .../video/ffmpeg-renderers/vaapi.cpp | 8 ---- app/streaming/video/ffmpeg-renderers/vaapi.h | 1 - .../video/ffmpeg-renderers/vdpau.cpp | 7 ---- app/streaming/video/ffmpeg-renderers/vdpau.h | 1 - .../ffmpeg-renderers/vt_avsamplelayer.mm | 9 ----- .../video/ffmpeg-renderers/vt_metal.mm | 9 ----- app/streaming/video/ffmpeg.cpp | 38 ++++++++----------- 20 files changed, 15 insertions(+), 107 deletions(-) diff --git a/app/streaming/video/ffmpeg-renderers/cuda.cpp b/app/streaming/video/ffmpeg-renderers/cuda.cpp index e437651a..b2382493 100644 --- a/app/streaming/video/ffmpeg-renderers/cuda.cpp +++ b/app/streaming/video/ffmpeg-renderers/cuda.cpp @@ -48,11 +48,6 @@ void CUDARenderer::renderFrame(AVFrame*) SDL_assert(false); } -bool CUDARenderer::needsTestFrame() -{ - return true; -} - bool CUDARenderer::isDirectRenderingSupported() { // We only support rendering via SDL read-back diff --git a/app/streaming/video/ffmpeg-renderers/cuda.h b/app/streaming/video/ffmpeg-renderers/cuda.h index 8cbcb994..d58a56c7 100644 --- a/app/streaming/video/ffmpeg-renderers/cuda.h +++ b/app/streaming/video/ffmpeg-renderers/cuda.h @@ -15,7 +15,6 @@ public: virtual bool initialize(PDECODER_PARAMETERS) override; virtual bool prepareDecoderContext(AVCodecContext* context, AVDictionary** options) override; virtual void renderFrame(AVFrame* frame) override; - virtual bool needsTestFrame() override; virtual bool isDirectRenderingSupported() override; virtual int getDecoderCapabilities() override; diff --git a/app/streaming/video/ffmpeg-renderers/d3d11va.cpp b/app/streaming/video/ffmpeg-renderers/d3d11va.cpp index 7047a637..af594550 100644 --- a/app/streaming/video/ffmpeg-renderers/d3d11va.cpp +++ b/app/streaming/video/ffmpeg-renderers/d3d11va.cpp @@ -1151,15 +1151,6 @@ int D3D11VARenderer::getDecoderCapabilities() CAPABILITY_REFERENCE_FRAME_INVALIDATION_AV1; } -bool D3D11VARenderer::needsTestFrame() -{ - // We can usually determine when D3D11VA will work based on which decoder GUIDs are supported, - // however there are some strange cases (Quadro P400 + Radeon HD 5570) where something goes - // horribly wrong and D3D11VideoDevice::CreateVideoDecoder() fails inside FFmpeg. We need to - // catch that case before we commit to using D3D11VA. - return true; -} - IFFmpegRenderer::InitFailureReason D3D11VARenderer::getInitFailureReason() { // In the specific case where we found at least one D3D11 hardware device but none of the diff --git a/app/streaming/video/ffmpeg-renderers/d3d11va.h b/app/streaming/video/ffmpeg-renderers/d3d11va.h index e1b36858..3b290b76 100644 --- a/app/streaming/video/ffmpeg-renderers/d3d11va.h +++ b/app/streaming/video/ffmpeg-renderers/d3d11va.h @@ -23,7 +23,6 @@ public: virtual void notifyOverlayUpdated(Overlay::OverlayType) override; virtual int getRendererAttributes() override; virtual int getDecoderCapabilities() override; - virtual bool needsTestFrame() override; virtual InitFailureReason getInitFailureReason() override; enum PixelShaders { diff --git a/app/streaming/video/ffmpeg-renderers/drm.cpp b/app/streaming/video/ffmpeg-renderers/drm.cpp index b2224e74..3683102e 100644 --- a/app/streaming/video/ffmpeg-renderers/drm.cpp +++ b/app/streaming/video/ffmpeg-renderers/drm.cpp @@ -1353,11 +1353,6 @@ void DrmRenderer::renderFrame(AVFrame* frame) drmModeRmFB(m_DrmFd, lastFbId); } -bool DrmRenderer::needsTestFrame() -{ - return true; -} - bool DrmRenderer::testRenderFrame(AVFrame* frame) { uint32_t fbId; diff --git a/app/streaming/video/ffmpeg-renderers/drm.h b/app/streaming/video/ffmpeg-renderers/drm.h index b586abe1..7b26fe63 100644 --- a/app/streaming/video/ffmpeg-renderers/drm.h +++ b/app/streaming/video/ffmpeg-renderers/drm.h @@ -59,7 +59,6 @@ public: virtual enum AVPixelFormat getPreferredPixelFormat(int videoFormat) override; virtual bool isPixelFormatSupported(int videoFormat, AVPixelFormat pixelFormat) override; virtual int getRendererAttributes() override; - virtual bool needsTestFrame() override; virtual bool testRenderFrame(AVFrame* frame) override; virtual bool isDirectRenderingSupported() override; virtual int getDecoderColorspace() override; diff --git a/app/streaming/video/ffmpeg-renderers/genhwaccel.cpp b/app/streaming/video/ffmpeg-renderers/genhwaccel.cpp index 92cae471..31f895c8 100644 --- a/app/streaming/video/ffmpeg-renderers/genhwaccel.cpp +++ b/app/streaming/video/ffmpeg-renderers/genhwaccel.cpp @@ -48,11 +48,6 @@ void GenericHwAccelRenderer::renderFrame(AVFrame*) SDL_assert(false); } -bool GenericHwAccelRenderer::needsTestFrame() -{ - return true; -} - bool GenericHwAccelRenderer::isDirectRenderingSupported() { // We only support rendering via read-back diff --git a/app/streaming/video/ffmpeg-renderers/genhwaccel.h b/app/streaming/video/ffmpeg-renderers/genhwaccel.h index 69e08e07..c801bddd 100644 --- a/app/streaming/video/ffmpeg-renderers/genhwaccel.h +++ b/app/streaming/video/ffmpeg-renderers/genhwaccel.h @@ -10,7 +10,6 @@ public: virtual bool initialize(PDECODER_PARAMETERS) override; virtual bool prepareDecoderContext(AVCodecContext* context, AVDictionary** options) override; virtual void renderFrame(AVFrame* frame) override; - virtual bool needsTestFrame() override; virtual bool isDirectRenderingSupported() override; virtual int getDecoderCapabilities() override; diff --git a/app/streaming/video/ffmpeg-renderers/mmal.cpp b/app/streaming/video/ffmpeg-renderers/mmal.cpp index 6078d7e9..8701b906 100644 --- a/app/streaming/video/ffmpeg-renderers/mmal.cpp +++ b/app/streaming/video/ffmpeg-renderers/mmal.cpp @@ -340,13 +340,6 @@ int MmalRenderer::getRendererAttributes() return RENDERER_ATTRIBUTE_1080P_MAX; } -bool MmalRenderer::needsTestFrame() -{ - // We won't be able to decode if the GPU memory is 64 MB or lower, - // so we must test before allowing the decoder to be used. - return true; -} - void MmalRenderer::renderFrame(AVFrame* frame) { MMAL_BUFFER_HEADER_T* buffer = (MMAL_BUFFER_HEADER_T*)frame->data[3]; diff --git a/app/streaming/video/ffmpeg-renderers/mmal.h b/app/streaming/video/ffmpeg-renderers/mmal.h index 21cf9907..4297a441 100644 --- a/app/streaming/video/ffmpeg-renderers/mmal.h +++ b/app/streaming/video/ffmpeg-renderers/mmal.h @@ -16,7 +16,6 @@ public: virtual void prepareToRender() override; virtual void renderFrame(AVFrame* frame) override; virtual enum AVPixelFormat getPreferredPixelFormat(int videoFormat) override; - virtual bool needsTestFrame() override; virtual int getRendererAttributes() override; virtual int getDecoderColorspace() override; diff --git a/app/streaming/video/ffmpeg-renderers/plvk.cpp b/app/streaming/video/ffmpeg-renderers/plvk.cpp index 5958ea4b..3cdda40d 100644 --- a/app/streaming/video/ffmpeg-renderers/plvk.cpp +++ b/app/streaming/video/ffmpeg-renderers/plvk.cpp @@ -1021,12 +1021,6 @@ int PlVkRenderer::getDecoderCapabilities() CAPABILITY_REFERENCE_FRAME_INVALIDATION_AV1; } -bool PlVkRenderer::needsTestFrame() -{ - // We need a test frame to verify that Vulkan video decoding is working - return true; -} - bool PlVkRenderer::isPixelFormatSupported(int videoFormat, AVPixelFormat pixelFormat) { if (m_HwAccelBackend) { diff --git a/app/streaming/video/ffmpeg-renderers/plvk.h b/app/streaming/video/ffmpeg-renderers/plvk.h index 36f71d41..0422755c 100644 --- a/app/streaming/video/ffmpeg-renderers/plvk.h +++ b/app/streaming/video/ffmpeg-renderers/plvk.h @@ -26,7 +26,6 @@ public: virtual int getDecoderColorspace() override; virtual int getDecoderColorRange() override; virtual int getDecoderCapabilities() override; - virtual bool needsTestFrame() override; virtual bool isPixelFormatSupported(int videoFormat, enum AVPixelFormat pixelFormat) override; virtual AVPixelFormat getPreferredPixelFormat(int videoFormat) override; diff --git a/app/streaming/video/ffmpeg-renderers/renderer.h b/app/streaming/video/ffmpeg-renderers/renderer.h index b1397bf2..27e26421 100644 --- a/app/streaming/video/ffmpeg-renderers/renderer.h +++ b/app/streaming/video/ffmpeg-renderers/renderer.h @@ -193,12 +193,6 @@ public: return true; } - // NOTE: This can be called BEFORE initialize()! - virtual bool needsTestFrame() { - // No test frame required by default - return false; - } - virtual int getDecoderCapabilities() { // No special capabilities by default return 0; diff --git a/app/streaming/video/ffmpeg-renderers/vaapi.cpp b/app/streaming/video/ffmpeg-renderers/vaapi.cpp index 69c78094..b6d31e8e 100644 --- a/app/streaming/video/ffmpeg-renderers/vaapi.cpp +++ b/app/streaming/video/ffmpeg-renderers/vaapi.cpp @@ -574,14 +574,6 @@ VAAPIRenderer::prepareDecoderContext(AVCodecContext* context, AVDictionary**) return true; } -bool -VAAPIRenderer::needsTestFrame() -{ - // We need a test frame to see if this VAAPI driver - // supports the profile used for streaming - return true; -} - bool VAAPIRenderer::isDirectRenderingSupported() { diff --git a/app/streaming/video/ffmpeg-renderers/vaapi.h b/app/streaming/video/ffmpeg-renderers/vaapi.h index 9b6287ff..a1705b43 100644 --- a/app/streaming/video/ffmpeg-renderers/vaapi.h +++ b/app/streaming/video/ffmpeg-renderers/vaapi.h @@ -61,7 +61,6 @@ public: virtual bool initialize(PDECODER_PARAMETERS params) override; virtual bool prepareDecoderContext(AVCodecContext* context, AVDictionary** options) override; virtual void renderFrame(AVFrame* frame) override; - virtual bool needsTestFrame() override; virtual bool isDirectRenderingSupported() override; virtual int getDecoderColorspace() override; virtual int getDecoderCapabilities() override; diff --git a/app/streaming/video/ffmpeg-renderers/vdpau.cpp b/app/streaming/video/ffmpeg-renderers/vdpau.cpp index 7c6fd55e..6ccd330c 100644 --- a/app/streaming/video/ffmpeg-renderers/vdpau.cpp +++ b/app/streaming/video/ffmpeg-renderers/vdpau.cpp @@ -461,13 +461,6 @@ void VDPAURenderer::notifyOverlayUpdated(Overlay::OverlayType type) } } -bool VDPAURenderer::needsTestFrame() -{ - // We need a test frame to see if this VDPAU driver - // supports the profile used for streaming - return true; -} - int VDPAURenderer::getDecoderColorspace() { // VDPAU defaults to Rec 601. diff --git a/app/streaming/video/ffmpeg-renderers/vdpau.h b/app/streaming/video/ffmpeg-renderers/vdpau.h index 5e840f1d..5b2a6aed 100644 --- a/app/streaming/video/ffmpeg-renderers/vdpau.h +++ b/app/streaming/video/ffmpeg-renderers/vdpau.h @@ -18,7 +18,6 @@ public: virtual void notifyOverlayUpdated(Overlay::OverlayType type) override; virtual void waitToRender() override; virtual void renderFrame(AVFrame* frame) override; - virtual bool needsTestFrame() override; virtual int getDecoderColorspace() override; virtual int getDecoderCapabilities() override; diff --git a/app/streaming/video/ffmpeg-renderers/vt_avsamplelayer.mm b/app/streaming/video/ffmpeg-renderers/vt_avsamplelayer.mm index 857b7eca..8858e09a 100644 --- a/app/streaming/video/ffmpeg-renderers/vt_avsamplelayer.mm +++ b/app/streaming/video/ffmpeg-renderers/vt_avsamplelayer.mm @@ -451,15 +451,6 @@ public: return true; } - virtual bool needsTestFrame() override - { - // We used to trust VT to tell us whether decode will work, but - // there are cases where it can lie because the hardware technically - // can decode the format but VT is unserviceable for some other reason. - // Decoding the test frame will tell us for sure whether it will work. - return true; - } - int getDecoderColorspace() override { // macOS seems to handle Rec 601 best diff --git a/app/streaming/video/ffmpeg-renderers/vt_metal.mm b/app/streaming/video/ffmpeg-renderers/vt_metal.mm index 5c34c8cf..957127c8 100644 --- a/app/streaming/video/ffmpeg-renderers/vt_metal.mm +++ b/app/streaming/video/ffmpeg-renderers/vt_metal.mm @@ -809,15 +809,6 @@ public: return false; } - virtual bool needsTestFrame() override - { - // We used to trust VT to tell us whether decode will work, but - // there are cases where it can lie because the hardware technically - // can decode the format but VT is unserviceable for some other reason. - // Decoding the test frame will tell us for sure whether it will work. - return true; - } - int getDecoderColorspace() override { // macOS seems to handle Rec 601 best diff --git a/app/streaming/video/ffmpeg.cpp b/app/streaming/video/ffmpeg.cpp index 2224d562..58c0463f 100644 --- a/app/streaming/video/ffmpeg.cpp +++ b/app/streaming/video/ffmpeg.cpp @@ -1106,39 +1106,31 @@ bool FFmpegVideoDecoder::tryInitializeRenderer(const AVCodec* decoder, break; } - // Initialize the backend renderer itself - if (initializeRendererInternal(m_BackendRenderer, (m_TestOnly || m_BackendRenderer->needsTestFrame()) ? &testFrameDecoderParams : params)) { - if (completeInitialization(decoder, requiredFormat, - (m_TestOnly || m_BackendRenderer->needsTestFrame()) ? &testFrameDecoderParams : params, - m_TestOnly || m_BackendRenderer->needsTestFrame(), - i == 0 /* EGL/DRM */)) { + // Initialize the backend renderer for testing + if (initializeRendererInternal(m_BackendRenderer, &testFrameDecoderParams)) { + if (completeInitialization(decoder, requiredFormat, &testFrameDecoderParams, + true, i == 0 /* EGL/DRM */)) { if (m_TestOnly) { // This decoder is only for testing capabilities, so don't bother // creating a usable renderer return true; } - if (m_BackendRenderer->needsTestFrame()) { - // The test worked, so now let's initialize it for real - reset(); + // The test worked, so now let's initialize it for real + reset(); - if ((m_BackendRenderer = createRendererFunc()) == nullptr) { - // Out of memory - break; - } + if ((m_BackendRenderer = createRendererFunc()) == nullptr) { + // Out of memory + break; + } - if (initializeRendererInternal(m_BackendRenderer, params) && - completeInitialization(decoder, requiredFormat, params, false, i == 0 /* EGL/DRM */)) { - return true; - } - else { - SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, - "Decoder failed to initialize after successful test"); - } + if (initializeRendererInternal(m_BackendRenderer, params) && + completeInitialization(decoder, requiredFormat, params, false, i == 0 /* EGL/DRM */)) { + return true; } else { - // No test required. Good to go now. - return true; + SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, + "Decoder failed to initialize after successful test"); } } }