From be6a1e3e330532f732e4f99c3c2feb810ade84aa Mon Sep 17 00:00:00 2001 From: BlackSpirits Date: Sun, 13 Sep 2026 21:47:39 +0200 Subject: [PATCH 1/2] FFmpeg: fall back when hardware decoder open fails --- src/ui/Logic/VideoPlayers/Ffmpeg/FfmpegPlayer.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/ui/Logic/VideoPlayers/Ffmpeg/FfmpegPlayer.cs b/src/ui/Logic/VideoPlayers/Ffmpeg/FfmpegPlayer.cs index 9d9e4deda3..6425b2f9a7 100644 --- a/src/ui/Logic/VideoPlayers/Ffmpeg/FfmpegPlayer.cs +++ b/src/ui/Logic/VideoPlayers/Ffmpeg/FfmpegPlayer.cs @@ -1219,6 +1219,14 @@ private static bool SupportsHardwareDevice(AVCodec* decoder, AVHWDeviceType devi result = ffmpeg.avcodec_open2(codec, decoder, null); if (result < 0) { + if (hardware && codec->hw_device_ctx != null) + { + var deviceName = HardwareDeviceName(codec); + Se.LogError($"ffmpeg player: {deviceName} decoder open failed for {ffmpeg.avcodec_get_name(stream->codecpar->codec_id)} ({FfmpegLibraries.ErrorText(result)}), falling back to software decoding"); + ffmpeg.avcodec_free_context(&codec); + return OpenDecoder(stream, hardware: false); + } + ffmpeg.avcodec_free_context(&codec); throw new InvalidOperationException($"avcodec_open2: {FfmpegLibraries.ErrorText(result)}"); } From 3c6c0b1219c1b207ece1f5248d9a60ffa10de78a Mon Sep 17 00:00:00 2001 From: BlackSpirits Date: Sun, 13 Sep 2026 22:18:21 +0200 Subject: [PATCH 2/2] FFmpeg: try remaining hardware decoders before software --- src/ui/Logic/VideoPlayers/Ffmpeg/FfmpegPlayer.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/ui/Logic/VideoPlayers/Ffmpeg/FfmpegPlayer.cs b/src/ui/Logic/VideoPlayers/Ffmpeg/FfmpegPlayer.cs index 6425b2f9a7..01a5ee9c5f 100644 --- a/src/ui/Logic/VideoPlayers/Ffmpeg/FfmpegPlayer.cs +++ b/src/ui/Logic/VideoPlayers/Ffmpeg/FfmpegPlayer.cs @@ -1162,7 +1162,7 @@ private static bool SupportsHardwareDevice(AVCodec* decoder, AVHWDeviceType devi /// is attached; the caller can tell by hw_device_ctx being set. Any hardware setup /// failure silently means software. /// - private AVCodecContext* OpenDecoder(AVStream* stream, bool hardware = false) + private AVCodecContext* OpenDecoder(AVStream* stream, bool hardware = false, int hardwareStartIndex = 0) { var decoder = ffmpeg.avcodec_find_decoder(stream->codecpar->codec_id); if (decoder == null) @@ -1186,10 +1186,12 @@ private static bool SupportsHardwareDevice(AVCodec* decoder, AVHWDeviceType devi codec->pkt_timebase = stream->time_base; codec->thread_count = 0; // auto + var selectedHardwareIndex = -1; if (hardware && stream->codecpar->codec_type == AVMediaType.AVMEDIA_TYPE_VIDEO) { - foreach (var deviceType in HardwareDeviceTypes) + for (var i = hardwareStartIndex; i < HardwareDeviceTypes.Length; i++) { + var deviceType = HardwareDeviceTypes[i]; if (!SupportsHardwareDevice(decoder, deviceType)) { continue; @@ -1212,6 +1214,7 @@ private static bool SupportsHardwareDevice(AVCodec* decoder, AVHWDeviceType devi codec->hw_device_ctx = device; // freed with the codec context codec->get_format = GetHardwareFormatDelegate; + selectedHardwareIndex = i; break; } } @@ -1219,12 +1222,12 @@ private static bool SupportsHardwareDevice(AVCodec* decoder, AVHWDeviceType devi result = ffmpeg.avcodec_open2(codec, decoder, null); if (result < 0) { - if (hardware && codec->hw_device_ctx != null) + if (hardware && selectedHardwareIndex >= 0) { var deviceName = HardwareDeviceName(codec); - Se.LogError($"ffmpeg player: {deviceName} decoder open failed for {ffmpeg.avcodec_get_name(stream->codecpar->codec_id)} ({FfmpegLibraries.ErrorText(result)}), falling back to software decoding"); + Se.LogError($"ffmpeg player: {deviceName} decoder open failed for {ffmpeg.avcodec_get_name(stream->codecpar->codec_id)} ({FfmpegLibraries.ErrorText(result)}), trying the next hardware decoder or software"); ffmpeg.avcodec_free_context(&codec); - return OpenDecoder(stream, hardware: false); + return OpenDecoder(stream, hardware: true, hardwareStartIndex: selectedHardwareIndex + 1); } ffmpeg.avcodec_free_context(&codec);