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
- Re-encode or transcode the media to a widely supported format (8-bit 4:2:0 H.264/HEVC)
- Disable hardware acceleration so decoding falls back to software
- Update GPU drivers / FFmpeg build that supports the codec's hw surface formats
- 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
- Restrict hardware-accelerated playback to 8-bit 4:2:0 H.264/HEVC content
- Keep GPU drivers and the FFmpeg build current
- Provide a software-decode fallback path and test it on target hardware
- Log the offered AVPixelFormat list in get_format to diagnose format mismatches
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
- Could not initialize the conversion context.
- Failed to compile a video asset, ffmpeg was not found.
- Failed to compile a video asset. ffmpeg failed to convert
- No video track found in
- Unsupported codec.
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)