stride3d/stride · error · ApplicationException

Failed to get HW surface format.

Error message

Failed to get HW surface format.

What it means

Thrown by the get_format callback installed in FFmpegCodec.SetupHardwareAcceleration (D3D11VA path) when none of the pixel formats FFmpeg offers matches the expected HardwarePixelFormat. It means the hardware-accelerated decoder cannot negotiate a D3D11 surface format compatible with what this backend requires.

Solutions

  1. Re-encode or transcode the media to a widely supported format (8-bit 4:2:0 H.264/HEVC)
  2. Disable hardware acceleration so decoding falls back to software
  3. Update GPU drivers / FFmpeg build that supports the codec's hw surface formats
  4. Extend the get_format callback to accept an alternative AVPixelFormat and map it

Example fix

// before
if (*pixelFormat == HardwarePixelFormat)
    return *pixelFormat;
throw new ApplicationException("Failed to get HW surface format.");
// after
if (*pixelFormat == HardwarePixelFormat)
    return *pixelFormat;
Logger.Warning("HW surface format mismatch, falling back to software decode");
return formats[0]; // or AV_PIX_FMT_NONE to let FFmpeg fall back
Defensive patterns

Strategy: fallback

Validate before calling

// Nothing the caller can probe cheaply; prefer an allowlist of known-decodable formats.
var codec = probe.VideoCodec; // e.g. h264, hevc
var pixFmt = probe.PixelFormat; // e.g. yuv420p
bool hwSafe = codec is "h264" or "hevc" && pixFmt == "yuv420p";

Try / catch

try
{
    codecWithHardwareAcceleration = new FFmpegCodec(codecpar); // D3D11VA path
}
catch (ApplicationException ex) when (ex.Message == "Failed to get HW surface format.")
{
    Logger.Warning("D3D11VA format negotiation failed; retrying with software decode");
    codec = new FFmpegCodec(codecpar, useHardwareAcceleration: false);
}

Prevention

When it happens

Trigger: Decoding a codec/pixel-format combination (e.g. 10-bit HEVC, unusual YUV layouts) whose AVPixelFormat list does not include the backend's HardwarePixelFormat, or the D3D11VA hwaccel reports formats the code does not recognize.

Common situations: Playing 10-bit/4:2:2 or HDR content on a GPU/driver combination whose D3D11VA exposes only formats the backend didn't anticipate; older GPU lacking support for the codec's hw surface format; driver updates changing the offered format list.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/61c6424d937d7851. Report an issue: GitHub.

Appendix: source

Thrown at sources/engine/Stride.Video/FFmpeg/FFmpegCodec.Direct3D11.cs:52

                Logger.Info($"FFmpegCodec: D3D11VA hwaccel unavailable (err={hwRet:X8}), using software decode");
                return;
            }

            IsHardwareAccelerated = true;
            pHWDeviceContext = pHWDeviceContextLocal;
            pCodecContext->hw_device_ctx = ffmpeg.av_buffer_ref(pHWDeviceContext);

            getFormat = (context, formats) =>
            {
                AVPixelFormat* pixelFormat;

                for (pixelFormat = formats; *pixelFormat != AVPixelFormat.AV_PIX_FMT_NONE; pixelFormat++)
                {
                    if (*pixelFormat == HardwarePixelFormat)
                        return *pixelFormat;
                }

                throw new ApplicationException("Failed to get HW surface format.");
            };
            pCodecContext->get_format = getFormat;
            Logger.Info("FFmpegCodec: D3D11VA hwaccel enabled");
        }

        // After avcodec_flush_buffers, FFmpeg resets get_format to its default — restoring our
        // callback is required for HW decode to keep picking AV_PIX_FMT_D3D11 (native crash otherwise).
        partial void RestoreGetFormatAfterFlush()
        {
            if (getFormat != null)
                pAVCodecContext->get_format = getFormat;
        }

        partial void DisposeHardwareAcceleration()
        {
            var pHWDeviceContextLocal = pHWDeviceContext;
            ffmpeg.av_buffer_unref(&pHWDeviceContextLocal);
        }

View on GitHub (pinned to 96fad776d2)