games/moonlight-qt: compatibility with ffmpeg 9.0

Kirill A. Korinsky <[email protected]>
Newsgroups gmane.os.openbsd.ports
Message-ID <[email protected]>
ports@,

I'd like to backport two commits:

- https://github.com/moonlight-stream/moonlight-qt/commit/13880353d8741ae331bf13433c5ad80071d5f44f
- https://github.com/moonlight-stream/moonlight-qt/commit/6ce02616f04fb83cd7c5d1492b03367f2220ac46

which brings support of ffmpeg-9.0 to games/moonlight-qt

Build tested against ffmpeg-9.0 and ffmpeg-8.1.2

Ok?

Index: Makefile
===================================================================
RCS file: /home/cvs/ports/games/moonlight-qt/Makefile,v
diff -u -p -r1.12 Makefile
--- Makefile	18 Feb 2026 18:25:17 -0000	1.12
+++ Makefile	12 Aug 2026 22:45:00 -0000
@@ -5,7 +5,7 @@ PKGNAME =		moonlight-qt-${V}
 
 DISTNAME =		MoonlightSrc-${V}
 SITES =			https://github.com/moonlight-stream/moonlight-qt/releases/download/v${V}/
-REVISION =		1
+REVISION =		2
 
 CATEGORIES =		games
 
Index: patches/patch-app_streaming_video_ffmpeg-renderers_plvk_cpp
===================================================================
RCS file: patches/patch-app_streaming_video_ffmpeg-renderers_plvk_cpp
diff -N patches/patch-app_streaming_video_ffmpeg-renderers_plvk_cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ patches/patch-app_streaming_video_ffmpeg-renderers_plvk_cpp	12 Aug 2026 22:46:11 -0000
@@ -0,0 +1,166 @@
+https://github.com/moonlight-stream/moonlight-qt/commit/6ce02616f04fb83cd7c5d1492b03367f2220ac46
+
+Index: app/streaming/video/ffmpeg-renderers/plvk.cpp
+--- app/streaming/video/ffmpeg-renderers/plvk.cpp.orig
++++ app/streaming/video/ffmpeg-renderers/plvk.cpp
+@@ -14,8 +14,9 @@
+ #include <vector>
+ #include <set>
+ 
+-#ifndef VK_KHR_VIDEO_DECODE_AV1_EXTENSION_NAME
++#ifndef VK_KHR_video_decode_av1
+ #define VK_KHR_VIDEO_DECODE_AV1_EXTENSION_NAME "VK_KHR_video_decode_av1"
++#define VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR ((VkVideoCodecOperationFlagBitsKHR)0x00000004)
+ #endif
+ 
+ // Keep these in sync with hwcontext_vulkan.c
+@@ -317,7 +318,7 @@ bool PlVkRenderer::tryInitializeDevice(VkPhysicalDevic
+     vkParams.device = device;
+     vkParams.opt_extensions = k_OptionalDeviceExtensions;
+     vkParams.num_opt_extensions = SDL_arraysize(k_OptionalDeviceExtensions);
+-    vkParams.extra_queues = VK_QUEUE_VIDEO_DECODE_BIT_KHR;
++    vkParams.extra_queues = m_HwAccelBackend ? VK_QUEUE_FLAG_BITS_MAX_ENUM : 0;
+     m_Vulkan = pl_vulkan_create(m_Log, &vkParams);
+     if (m_Vulkan == nullptr) {
+         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
+@@ -399,7 +400,7 @@ bool PlVkRenderer::initialize(PDECODER_PARAMETERS para
+ 
+     // Lookup all Vulkan functions we require
+     POPULATE_FUNCTION(vkDestroySurfaceKHR);
+-    POPULATE_FUNCTION(vkGetPhysicalDeviceQueueFamilyProperties);
++    POPULATE_FUNCTION(vkGetPhysicalDeviceQueueFamilyProperties2);
+     POPULATE_FUNCTION(vkGetPhysicalDeviceSurfacePresentModesKHR);
+     POPULATE_FUNCTION(vkGetPhysicalDeviceSurfaceFormatsKHR);
+     POPULATE_FUNCTION(vkEnumeratePhysicalDevices);
+@@ -504,24 +505,13 @@ bool PlVkRenderer::initialize(PDECODER_PARAMETERS para
+         vkDeviceContext->nb_enabled_inst_extensions = m_PlVkInstance->num_extensions;
+         vkDeviceContext->enabled_dev_extensions = m_Vulkan->extensions;
+         vkDeviceContext->nb_enabled_dev_extensions = m_Vulkan->num_extensions;
+-        vkDeviceContext->queue_family_index = m_Vulkan->queue_graphics.index;
+-        vkDeviceContext->nb_graphics_queues = m_Vulkan->queue_graphics.count;
+-        vkDeviceContext->queue_family_tx_index = m_Vulkan->queue_transfer.index;
+-        vkDeviceContext->nb_tx_queues = m_Vulkan->queue_transfer.count;
+-        vkDeviceContext->queue_family_comp_index = m_Vulkan->queue_compute.index;
+-        vkDeviceContext->nb_comp_queues = m_Vulkan->queue_compute.count;
+ #if LIBAVUTIL_VERSION_INT > AV_VERSION_INT(58, 9, 100)
+         vkDeviceContext->lock_queue = lockQueue;
+         vkDeviceContext->unlock_queue = unlockQueue;
+ #endif
+ 
+-        static_assert(sizeof(vkDeviceContext->queue_family_decode_index) == sizeof(uint32_t), "sizeof(int) != sizeof(uint32_t)");
+-        static_assert(sizeof(vkDeviceContext->nb_decode_queues) == sizeof(uint32_t), "sizeof(int) != sizeof(uint32_t)");
+-        if (!getQueue(VK_QUEUE_VIDEO_DECODE_BIT_KHR, (uint32_t*)&vkDeviceContext->queue_family_decode_index, (uint32_t*)&vkDeviceContext->nb_decode_queues)) {
+-            SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
+-                        "Vulkan video decoding is not supported by the Vulkan device");
+-            return false;
+-        }
++        // Populate the device queues for decoding this video format
++        populateQueues(params->videoFormat);
+ 
+         int err = av_hwdevice_ctx_init(m_HwDeviceCtx);
+         if (err < 0) {
+@@ -581,23 +571,86 @@ bool PlVkRenderer::mapAvFrameToPlacebo(const AVFrame *
+     return true;
+ }
+ 
+-bool PlVkRenderer::getQueue(VkQueueFlags requiredFlags, uint32_t *queueIndex, uint32_t *queueCount)
++bool PlVkRenderer::populateQueues(int videoFormat)
+ {
++    auto vkDeviceContext = (AVVulkanDeviceContext*)((AVHWDeviceContext *)m_HwDeviceCtx->data)->hwctx;
++
+     uint32_t queueFamilyCount = 0;
+-    fn_vkGetPhysicalDeviceQueueFamilyProperties(m_Vulkan->phys_device, &queueFamilyCount, nullptr);
++    fn_vkGetPhysicalDeviceQueueFamilyProperties2(m_Vulkan->phys_device, &queueFamilyCount, nullptr);
+ 
+-    std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
+-    fn_vkGetPhysicalDeviceQueueFamilyProperties(m_Vulkan->phys_device, &queueFamilyCount, queueFamilies.data());
++    std::vector<VkQueueFamilyProperties2> queueFamilies(queueFamilyCount);
++    std::vector<VkQueueFamilyVideoPropertiesKHR> queueFamilyVideoProps(queueFamilyCount);
++    for (uint32_t i = 0; i < queueFamilyCount; i++) {
++        queueFamilyVideoProps[i].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR;
++        queueFamilies[i].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2;
++        queueFamilies[i].pNext = &queueFamilyVideoProps[i];
++    }
+ 
++    fn_vkGetPhysicalDeviceQueueFamilyProperties2(m_Vulkan->phys_device, &queueFamilyCount, queueFamilies.data());
++
++#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(58, 34, 100)
++    Q_UNUSED(videoFormat);
++
+     for (uint32_t i = 0; i < queueFamilyCount; i++) {
+-        if ((queueFamilies[i].queueFlags & requiredFlags) == requiredFlags) {
+-            *queueIndex = i;
+-            *queueCount = queueFamilies[i].queueCount;
+-            return true;
++        vkDeviceContext->qf[i].idx = i;
++        vkDeviceContext->qf[i].num = queueFamilies[i].queueFamilyProperties.queueCount;
++        vkDeviceContext->qf[i].flags = (VkQueueFlagBits)queueFamilies[i].queueFamilyProperties.queueFlags;
++        vkDeviceContext->qf[i].video_caps = (VkVideoCodecOperationFlagBitsKHR)queueFamilyVideoProps[i].videoCodecOperations;
++    }
++    vkDeviceContext->nb_qf = queueFamilyCount;
++#else
++    vkDeviceContext->queue_family_index = m_Vulkan->queue_graphics.index;
++    vkDeviceContext->nb_graphics_queues = m_Vulkan->queue_graphics.count;
++    vkDeviceContext->queue_family_tx_index = m_Vulkan->queue_transfer.index;
++    vkDeviceContext->nb_tx_queues = m_Vulkan->queue_transfer.count;
++    vkDeviceContext->queue_family_comp_index = m_Vulkan->queue_compute.index;
++    vkDeviceContext->nb_comp_queues = m_Vulkan->queue_compute.count;
++
++    // Select a video decode queue that is capable of decoding our chosen format
++    for (uint32_t i = 0; i < queueFamilyCount; i++) {
++        if (queueFamilies[i].queueFamilyProperties.queueFlags & VK_QUEUE_VIDEO_DECODE_BIT_KHR) {
++            if (videoFormat & VIDEO_FORMAT_MASK_H264) {
++                if (queueFamilyVideoProps[i].videoCodecOperations & VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR) {
++                    vkDeviceContext->queue_family_decode_index = i;
++                    vkDeviceContext->nb_decode_queues = queueFamilies[i].queueFamilyProperties.queueCount;
++                    break;
++                }
++            }
++            else if (videoFormat & VIDEO_FORMAT_MASK_H265) {
++                if (queueFamilyVideoProps[i].videoCodecOperations & VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR) {
++                    vkDeviceContext->queue_family_decode_index = i;
++                    vkDeviceContext->nb_decode_queues = queueFamilies[i].queueFamilyProperties.queueCount;
++                    break;
++                }
++            }
++            else if (videoFormat & VIDEO_FORMAT_MASK_AV1) {
++#if LIBAVCODEC_VERSION_MAJOR >= 61
++                // VK_KHR_video_decode_av1 added VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR to check for AV1
++                // decoding support on this queue. Since FFmpeg 6.1 used the older Mesa-specific AV1 extension,
++                // we'll just assume all video decode queues on this device support AV1 (since we checked that
++                // the physical device supports it earlier.
++                if (queueFamilyVideoProps[i].videoCodecOperations & VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR)
++#endif
++                {
++                    vkDeviceContext->queue_family_decode_index = i;
++                    vkDeviceContext->nb_decode_queues = queueFamilies[i].queueFamilyProperties.queueCount;
++                    break;
++                }
++            }
++            else {
++                SDL_assert(false);
++            }
+         }
+     }
+ 
+-    return false;
++    if (vkDeviceContext->queue_family_decode_index < 0) {
++        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
++                     "Unable to find compatible video decode queue!");
++        return false;
++    }
++#endif
++
++    return true;
+ }
+ 
+ bool PlVkRenderer::isPresentModeSupportedByPhysicalDevice(VkPhysicalDevice device, VkPresentModeKHR presentMode)
+@@ -637,7 +690,7 @@ bool PlVkRenderer::isColorSpaceSupportedByPhysicalDevi
+ bool PlVkRenderer::isSurfacePresentationSupportedByPhysicalDevice(VkPhysicalDevice device)
+ {
+     uint32_t queueFamilyCount = 0;
+-    fn_vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
++    fn_vkGetPhysicalDeviceQueueFamilyProperties2(device, &queueFamilyCount, nullptr);
+ 
+     for (uint32_t i = 0; i < queueFamilyCount; i++) {
+         VkBool32 supported = VK_FALSE;
Index: patches/patch-app_streaming_video_ffmpeg-renderers_plvk_h
===================================================================
RCS file: patches/patch-app_streaming_video_ffmpeg-renderers_plvk_h
diff -N patches/patch-app_streaming_video_ffmpeg-renderers_plvk_h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ patches/patch-app_streaming_video_ffmpeg-renderers_plvk_h	12 Aug 2026 22:46:14 -0000
@@ -0,0 +1,23 @@
+https://github.com/moonlight-stream/moonlight-qt/commit/6ce02616f04fb83cd7c5d1492b03367f2220ac46
+
+Index: app/streaming/video/ffmpeg-renderers/plvk.h
+--- app/streaming/video/ffmpeg-renderers/plvk.h.orig
++++ app/streaming/video/ffmpeg-renderers/plvk.h
+@@ -37,7 +37,7 @@ class PlVkRenderer : public IFFmpegRenderer { (private
+     static void overlayUploadComplete(void* opaque);
+ 
+     bool mapAvFrameToPlacebo(const AVFrame *frame, pl_frame* mappedFrame);
+-    bool getQueue(VkQueueFlags requiredFlags, uint32_t* queueIndex, uint32_t* queueCount);
++    bool populateQueues(int videoFormat);
+     bool chooseVulkanDevice(PDECODER_PARAMETERS params, bool hdrOutputRequired);
+     bool tryInitializeDevice(VkPhysicalDevice device, VkPhysicalDeviceProperties* deviceProps,
+                              PDECODER_PARAMETERS decoderParams, bool hdrOutputRequired);
+@@ -95,7 +95,7 @@ class PlVkRenderer : public IFFmpegRenderer { (private
+ 
+     // Vulkan functions we call directly
+     PFN_vkDestroySurfaceKHR fn_vkDestroySurfaceKHR = nullptr;
+-    PFN_vkGetPhysicalDeviceQueueFamilyProperties fn_vkGetPhysicalDeviceQueueFamilyProperties = nullptr;
++    PFN_vkGetPhysicalDeviceQueueFamilyProperties2 fn_vkGetPhysicalDeviceQueueFamilyProperties2 = nullptr;
+     PFN_vkGetPhysicalDeviceSurfacePresentModesKHR fn_vkGetPhysicalDeviceSurfacePresentModesKHR = nullptr;
+     PFN_vkGetPhysicalDeviceSurfaceFormatsKHR fn_vkGetPhysicalDeviceSurfaceFormatsKHR = nullptr;
+     PFN_vkEnumeratePhysicalDevices fn_vkEnumeratePhysicalDevices = nullptr;
Index: patches/patch-app_streaming_video_ffmpeg_cpp
===================================================================
RCS file: patches/patch-app_streaming_video_ffmpeg_cpp
diff -N patches/patch-app_streaming_video_ffmpeg_cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ patches/patch-app_streaming_video_ffmpeg_cpp	12 Aug 2026 22:45:37 -0000
@@ -0,0 +1,152 @@
+https://github.com/moonlight-stream/moonlight-qt/commit/13880353d8741ae331bf13433c5ad80071d5f44f
+
+Index: app/streaming/video/ffmpeg.cpp
+--- app/streaming/video/ffmpeg.cpp.orig
++++ app/streaming/video/ffmpeg.cpp
+@@ -1076,15 +1076,15 @@ bool FFmpegVideoDecoder::tryInitializeRenderer(const A
+ #define TRY_PREFERRED_PIXEL_FORMAT(RENDERER_TYPE) \
+     { \
+         RENDERER_TYPE renderer; \
+-        if (renderer.getPreferredPixelFormat(params->videoFormat) == decoder->pix_fmts[i]) { \
++        if (renderer.getPreferredPixelFormat(params->videoFormat) == decoder_pix_fmts[i]) { \
+             SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, \
+                         "Trying " #RENDERER_TYPE " for codec %s due to preferred pixel format: 0x%x", \
+-                        decoder->name, decoder->pix_fmts[i]); \
+-            if (tryInitializeRenderer(decoder, decoder->pix_fmts[i], params, nullptr, nullptr, \
++                        decoder->name, decoder_pix_fmts[i]); \
++            if (tryInitializeRenderer(decoder, decoder_pix_fmts[i], params, nullptr, nullptr, \
+                                       []() -> IFFmpegRenderer* { return new RENDERER_TYPE(); })) { \
+                 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, \
+                             "Chose " #RENDERER_TYPE " for codec %s due to preferred pixel format: 0x%x", \
+-                            decoder->name, decoder->pix_fmts[i]); \
++                            decoder->name, decoder_pix_fmts[i]); \
+                 return true; \
+             } \
+         } \
+@@ -1093,16 +1093,16 @@ bool FFmpegVideoDecoder::tryInitializeRenderer(const A
+ #define TRY_SUPPORTED_NON_PREFERRED_PIXEL_FORMAT(RENDERER_TYPE) \
+     { \
+         RENDERER_TYPE renderer; \
+-        if (decoder->pix_fmts[i] != renderer.getPreferredPixelFormat(params->videoFormat) && \
+-            renderer.isPixelFormatSupported(params->videoFormat, decoder->pix_fmts[i])) { \
++        if (decoder_pix_fmts[i] != renderer.getPreferredPixelFormat(params->videoFormat) && \
++            renderer.isPixelFormatSupported(params->videoFormat, decoder_pix_fmts[i])) { \
+             SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, \
+                         "Trying " #RENDERER_TYPE " for codec %s due to compatible pixel format: 0x%x", \
+-                        decoder->name, decoder->pix_fmts[i]); \
+-            if (tryInitializeRenderer(decoder, decoder->pix_fmts[i], params, nullptr, nullptr, \
++                        decoder->name, decoder_pix_fmts[i]); \
++            if (tryInitializeRenderer(decoder, decoder_pix_fmts[i], params, nullptr, nullptr, \
+                                       []() -> IFFmpegRenderer* { return new RENDERER_TYPE(); })) { \
+                 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, \
+                             "Chose " #RENDERER_TYPE " for codec %s due to compatible pixel format: 0x%x", \
+-                            decoder->name, decoder->pix_fmts[i]); \
++                            decoder->name, decoder_pix_fmts[i]); \
+                 return true; \
+             } \
+         } \
+@@ -1116,6 +1116,16 @@ bool FFmpegVideoDecoder::tryInitializeRendererForUnkno
+         return false;
+     }
+ 
++    const AVPixelFormat* decoder_pix_fmts;
++#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(61, 13, 100)
++    if (avcodec_get_supported_config(nullptr, decoder, AV_CODEC_CONFIG_PIX_FORMAT, 0,
++                                     (const void**)&decoder_pix_fmts, nullptr) < 0) {
++        decoder_pix_fmts = nullptr;
++    }
++#else
++    decoder_pix_fmts = decoder->pix_fmts;
++#endif
++
+     // This might be a hwaccel decoder, so try any hw configs first
+     if (tryHwAccel) {
+         for (int pass = 0; pass <= MAX_DECODER_PASS; pass++) {
+@@ -1141,7 +1151,7 @@ bool FFmpegVideoDecoder::tryInitializeRendererForUnkno
+         }
+     }
+ 
+-    if (decoder->pix_fmts == NULL) {
++    if (decoder_pix_fmts == NULL) {
+         // Supported output pixel formats are unknown. We'll just try DRM/SDL and hope it can cope.
+ 
+ #if defined(HAVE_DRM) && defined(GL_IS_SLOW)
+@@ -1177,11 +1187,11 @@ bool FFmpegVideoDecoder::tryInitializeRendererForUnkno
+     // Even if it didn't completely deadlock us, the performance would likely be atrocious.
+     if (strcmp(decoder->name, "h264_mmal") == 0) {
+ #ifdef HAVE_MMAL
+-        for (int i = 0; decoder->pix_fmts[i] != AV_PIX_FMT_NONE; i++) {
++        for (int i = 0; decoder_pix_fmts[i] != AV_PIX_FMT_NONE; i++) {
+             TRY_PREFERRED_PIXEL_FORMAT(MmalRenderer);
+         }
+ 
+-        for (int i = 0; decoder->pix_fmts[i] != AV_PIX_FMT_NONE; i++) {
++        for (int i = 0; decoder_pix_fmts[i] != AV_PIX_FMT_NONE; i++) {
+             TRY_SUPPORTED_NON_PREFERRED_PIXEL_FORMAT(MmalRenderer);
+         }
+ #endif
+@@ -1191,7 +1201,7 @@ bool FFmpegVideoDecoder::tryInitializeRendererForUnkno
+     }
+ 
+     // Check if any of our decoders prefer any of the pixel formats first
+-    for (int i = 0; decoder->pix_fmts[i] != AV_PIX_FMT_NONE; i++) {
++    for (int i = 0; decoder_pix_fmts[i] != AV_PIX_FMT_NONE; i++) {
+ #ifdef HAVE_DRM
+         TRY_PREFERRED_PIXEL_FORMAT(DrmRenderer);
+ #endif
+@@ -1204,7 +1214,7 @@ bool FFmpegVideoDecoder::tryInitializeRendererForUnkno
+     }
+ 
+     // Nothing prefers any of them. Let's see if anyone will tolerate one.
+-    for (int i = 0; decoder->pix_fmts[i] != AV_PIX_FMT_NONE; i++) {
++    for (int i = 0; decoder_pix_fmts[i] != AV_PIX_FMT_NONE; i++) {
+ #ifdef HAVE_DRM
+         TRY_SUPPORTED_NON_PREFERRED_PIXEL_FORMAT(DrmRenderer);
+ #endif
+@@ -1219,10 +1229,10 @@ bool FFmpegVideoDecoder::tryInitializeRendererForUnkno
+ #if defined(HAVE_LIBPLACEBO_VULKAN) && defined(VULKAN_IS_SLOW)
+     // If we got here with VULKAN_IS_SLOW, DrmRenderer didn't work,
+     // so we have to resort to PlVkRenderer.
+-    for (int i = 0; decoder->pix_fmts[i] != AV_PIX_FMT_NONE; i++) {
++    for (int i = 0; decoder_pix_fmts[i] != AV_PIX_FMT_NONE; i++) {
+         TRY_PREFERRED_PIXEL_FORMAT(PlVkRenderer);
+     }
+-    for (int i = 0; decoder->pix_fmts[i] != AV_PIX_FMT_NONE; i++) {
++    for (int i = 0; decoder_pix_fmts[i] != AV_PIX_FMT_NONE; i++) {
+         TRY_SUPPORTED_NON_PREFERRED_PIXEL_FORMAT(PlVkRenderer);
+     }
+ #endif
+@@ -1230,10 +1240,10 @@ bool FFmpegVideoDecoder::tryInitializeRendererForUnkno
+ #ifdef GL_IS_SLOW
+     // If we got here with GL_IS_SLOW, DrmRenderer didn't work, so we have
+     // to resort to SdlRenderer.
+-    for (int i = 0; decoder->pix_fmts[i] != AV_PIX_FMT_NONE; i++) {
++    for (int i = 0; decoder_pix_fmts[i] != AV_PIX_FMT_NONE; i++) {
+         TRY_PREFERRED_PIXEL_FORMAT(SdlRenderer);
+     }
+-    for (int i = 0; decoder->pix_fmts[i] != AV_PIX_FMT_NONE; i++) {
++    for (int i = 0; decoder_pix_fmts[i] != AV_PIX_FMT_NONE; i++) {
+         TRY_SUPPORTED_NON_PREFERRED_PIXEL_FORMAT(SdlRenderer);
+     }
+ #endif
+@@ -1369,9 +1379,18 @@ bool FFmpegVideoDecoder::tryInitializeNonHwAccelDecode
+ 
+         // Skip decoders without zero-copy output formats if requested
+         if (requireZeroCopyFormat) {
++            const AVPixelFormat* decoder_pix_fmts;
++#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(61, 13, 100)
++            if (avcodec_get_supported_config(nullptr, decoder, AV_CODEC_CONFIG_PIX_FORMAT, 0,
++                                             (const void**)&decoder_pix_fmts, nullptr) < 0) {
++                decoder_pix_fmts = nullptr;
++            }
++#else
++            decoder_pix_fmts = decoder->pix_fmts;
++#endif
+             bool foundZeroCopyFormat = false;
+-            for (int i = 0; decoder->pix_fmts && decoder->pix_fmts[i] != AV_PIX_FMT_NONE; i++) {
+-                if (isZeroCopyFormat(decoder->pix_fmts[i])) {
++            for (int i = 0; decoder_pix_fmts && decoder_pix_fmts[i] != AV_PIX_FMT_NONE; i++) {
++                if (isZeroCopyFormat(decoder_pix_fmts[i])) {
+                     foundZeroCopyFormat = true;
+                     break;
+                 }


-- 
wbr, Kirill
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.