Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions crates/compositor/src/cpu_frames_windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ use windows::Win32::Graphics::Dxgi::Common::{DXGI_FORMAT_NV12, DXGI_SAMPLE_DESC}

/// Le flag d'algorithme de swscale. Bindgen ne génère pas les `SWS_*` d'algorithme (des
/// macros), et leurs valeurs sont figées par l'ABI de libswscale. `POINT` (plus proche
/// voisin) est le choix honnête : la conversion se fait à dimensions ÉGALES, donc aucun
/// rééchantillonnage n'a lieu — seul le convertisseur de format travaille, et le filtre
/// choisi n'a aucun effet sur la sortie.
/// voisin) est le choix honnête : la conversion se fait à dimensions ÉGALES, donc la luma
/// n'est jamais rééchantillonnée. Seule exception : une source 4:2:2 ou 4:4:4 (H.264
/// importé) perd sa chroma pleine en passant en NV12, et POINT la décime par voisin.
const SWS_POINT: i32 = 0x10;

/// Source de frames du backend CPU, attachée à un `Decoder` quand `Backend::Cpu`.
Expand Down
38 changes: 34 additions & 4 deletions crates/compositor/src/pipeline_windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,21 @@ fn d3d11va_for_codec(codec_id: AVCodecID::Type) -> bool {
codec_id == AVCodecID::AV_CODEC_ID_H264
}

/// Per-stream refinement of `d3d11va_for_codec`: FFmpeg only offers a D3D11
/// NV12 surface for 8-bit 4:2:0 H.264. High 10 (yuv420p10le) and 4:2:2 / 4:4:4
/// get none, `get_hw_format` rejects everything and `send_packet` fails with
/// AVERROR_INVALIDDATA, so those streams take the software `CpuFrames` path.
/// An unknown pixel format (`AV_PIX_FMT_NONE`) keeps the hardware path.
fn d3d11va_for_stream(codec_id: AVCodecID::Type, format: AVPixelFormat::Type) -> bool {
d3d11va_for_codec(codec_id)
&& matches!(
format,
AVPixelFormat::AV_PIX_FMT_NONE
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
| AVPixelFormat::AV_PIX_FMT_YUV420P
| AVPixelFormat::AV_PIX_FMT_YUVJ420P
)
}

unsafe fn require_decoder_id(
codec_id: AVCodecID::Type,
) -> Result<(*const AVCodec, *mut AVCodecContext)> {
Expand Down Expand Up @@ -847,10 +862,12 @@ impl Decoder {
)?;
allow_d3d11va_h264_baseline(resources.dctx);

// Hardware D3D11VA is the H.264 capture path. WARP has no video decoder
// (`tests/warp_device_cannot_decode.rs`). AV1/VP9 (legacy WebMs, #554)
// take the same software CpuFrames axis as Backend::Cpu.
let want_hw = gpu.backend != Backend::Cpu && d3d11va_for_codec(codec_id);
// Hardware D3D11VA is the H.264 8-bit 4:2:0 capture path. WARP has no video
// decoder (`tests/warp_device_cannot_decode.rs`). AV1/VP9 (legacy WebMs, #554)
// and H.264 High 10 / 4:2:2 / 4:4:4 (no D3D11 surface exists for them) take
// the same software CpuFrames axis as Backend::Cpu.
let want_hw = gpu.backend != Backend::Cpu
&& d3d11va_for_stream(codec_id, (*codecpar).format as AVPixelFormat::Type);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
let cpu = if want_hw {
None
} else {
Expand Down Expand Up @@ -2168,6 +2185,19 @@ mod tests {
assert!(!d3d11va_for_codec(AVCodecID::AV_CODEC_ID_VP9));
}

#[test]
fn d3d11va_is_8bit_420_h264_only() {
use AVPixelFormat::*;
let h264 = AVCodecID::AV_CODEC_ID_H264;
assert!(d3d11va_for_stream(h264, AV_PIX_FMT_YUV420P));
assert!(d3d11va_for_stream(h264, AV_PIX_FMT_YUVJ420P));
assert!(d3d11va_for_stream(h264, AV_PIX_FMT_NONE));
assert!(!d3d11va_for_stream(h264, AV_PIX_FMT_YUV420P10LE));
assert!(!d3d11va_for_stream(h264, AV_PIX_FMT_YUV422P));
assert!(!d3d11va_for_stream(h264, AV_PIX_FMT_YUV444P));
assert!(!d3d11va_for_stream(AVCodecID::AV_CODEC_ID_AV1, AV_PIX_FMT_YUV420P));
}

#[test]
fn require_decoder_rejects_none() {
let err = unsafe { require_decoder_id(AVCodecID::AV_CODEC_ID_NONE) }
Expand Down
Loading