feat(pyrowave): negotiation plumbing for 4:4:4 + HDR — thread chroma/depth/ColorInfo end to end
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 6m49s
ci / web (push) Successful in 58s
ci / docs-site (push) Successful in 1m10s
arch / build-publish (push) Successful in 11m34s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 6m43s
ci / bench (push) Successful in 5m21s
decky / build-publish (push) Successful in 19s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 10s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 9s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 9s
docker / build-push (ci, ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 9s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 8s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 10s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 8m9s
deb / build-publish-host (push) Successful in 9m20s
android / android (push) Successful in 22m17s
flatpak / build-publish (push) Successful in 6m12s
ci / rust (push) Successful in 19m3s
deb / build-publish (push) Successful in 12m40s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 9m8s
apple / swift (push) Successful in 1m18s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 15m17s
docker / deploy-docs (push) Successful in 11s
apple / screenshots (push) Successful in 6m14s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 23m5s
windows-host / package (push) Successful in 16m27s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 6m49s
ci / web (push) Successful in 58s
ci / docs-site (push) Successful in 1m10s
arch / build-publish (push) Successful in 11m34s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 6m43s
ci / bench (push) Successful in 5m21s
decky / build-publish (push) Successful in 19s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 10s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 9s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 9s
docker / build-push (ci, ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 9s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 8s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 10s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 8m9s
deb / build-publish-host (push) Successful in 9m20s
android / android (push) Successful in 22m17s
flatpak / build-publish (push) Successful in 6m12s
ci / rust (push) Successful in 19m3s
deb / build-publish (push) Successful in 12m40s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 9m8s
apple / swift (push) Successful in 1m18s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 15m17s
docker / deploy-docs (push) Successful in 11s
apple / screenshots (push) Successful in 6m14s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 23m5s
windows-host / package (push) Successful in 16m27s
Phase 1 of design/pyrowave-444-hdr.md. No behavior change yet: the handshake's
4:4:4 gate now admits PyroWave (probe = can_encode_444(codec), capture gate
inherently satisfied — the wavelet path always ingests an RGB source and does
its own CSC), but can_encode_444 stays false for PyroWave until the per-OS
full-res-chroma CSC variants land (Phase 2 Linux, Phase 3 Windows), so every
session still resolves 4:2:0/8-bit.
- Both host encoders take the negotiated ChromaFormat (bail on 444 for now);
the PUNKTFUNK_ENCODER=pyrowave lab override pins 4:2:0.
- Bitrate: the automatic ~1.6 bpp pin resolves AFTER depth+chroma and scales
x1.625 for 4:4:4 / x1.15 for 10-bit (factors from the Phase-0 fixture
matrix); the mid-stream mode-switch re-resolve threads the session's values.
- Client: PyroWaveDecoder builds its plane ring (full-res chroma when 444) and
creates the upstream decoder from the negotiated chroma, keeps chroma fixed
across mid-stream resizes, drops the even-dims requirement for 444, and
returns the negotiated Welcome ColorInfo as the frame colour contract
instead of hardcoded BT.709 (the wavelet bitstream has no VUI).
Verified on .21 (RTX 5070 Ti): clippy -D warnings (host+client+encode), host
186 tests, client + pf-encode tests, fmt, and the pyrowave_smoke GPU
round-trip through the patched vendored lib (97cf15e3).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -248,10 +248,11 @@ fn open_video_backend(
|
||||
if fps == 0 || fps > 1000 {
|
||||
anyhow::bail!("invalid refresh/fps {fps}: must be 1..=1000 Hz");
|
||||
}
|
||||
// 4:4:4 is HEVC-only. The negotiator should never pass `Yuv444` for another codec (it gates on
|
||||
// `codec == H265`), but defend the contract here so a future caller can't silently emit a stream
|
||||
// no decoder expects: a non-HEVC 4:4:4 request degrades to 4:2:0 with a warning.
|
||||
let chroma = if chroma.is_444() && codec != Codec::H265 {
|
||||
// 4:4:4 is HEVC- and PyroWave-only. The negotiator should never pass `Yuv444` for another
|
||||
// codec (it gates on the codec + `can_encode_444`), but defend the contract here so a future
|
||||
// caller can't silently emit a stream no decoder expects: an unsupported 4:4:4 request
|
||||
// degrades to 4:2:0 with a warning.
|
||||
let chroma = if chroma.is_444() && codec != Codec::H265 && codec != Codec::PyroWave {
|
||||
tracing::warn!(
|
||||
?codec,
|
||||
"4:4:4 requested for a non-HEVC codec — encoding 4:2:0"
|
||||
@@ -267,7 +268,7 @@ fn open_video_backend(
|
||||
if codec == Codec::PyroWave {
|
||||
#[cfg(feature = "pyrowave")]
|
||||
{
|
||||
return pyrowave::PyroWaveEncoder::open(width, height, fps, bitrate_bps)
|
||||
return pyrowave::PyroWaveEncoder::open(width, height, fps, bitrate_bps, chroma)
|
||||
.map(|e| (Box::new(e) as Box<dyn Encoder>, "pyrowave"));
|
||||
}
|
||||
#[cfg(not(feature = "pyrowave"))]
|
||||
@@ -369,8 +370,17 @@ fn open_video_backend(
|
||||
that ALSO preferred CODEC_PYROWAVE can display it (lab override; \
|
||||
normal sessions negotiate it instead)"
|
||||
);
|
||||
pyrowave::PyroWaveEncoder::open(width, height, fps, bitrate_bps)
|
||||
.map(|e| (Box::new(e) as Box<dyn Encoder>, "pyrowave"))
|
||||
// The lab override forces the wavelet stream onto a session negotiated for
|
||||
// another codec — that session's chroma may be HEVC-4:4:4, which the
|
||||
// pyrowave encoder doesn't do yet, so pin the override to 4:2:0.
|
||||
pyrowave::PyroWaveEncoder::open(
|
||||
width,
|
||||
height,
|
||||
fps,
|
||||
bitrate_bps,
|
||||
ChromaFormat::Yuv420,
|
||||
)
|
||||
.map(|e| (Box::new(e) as Box<dyn Encoder>, "pyrowave"))
|
||||
}
|
||||
#[cfg(not(feature = "pyrowave"))]
|
||||
{
|
||||
@@ -418,8 +428,8 @@ fn open_video_backend(
|
||||
if codec == Codec::PyroWave {
|
||||
#[cfg(feature = "pyrowave")]
|
||||
{
|
||||
let _ = (format, cuda, bit_depth, chroma);
|
||||
return pyrowave::PyroWaveEncoder::open(width, height, fps, bitrate_bps)
|
||||
let _ = (format, cuda, bit_depth);
|
||||
return pyrowave::PyroWaveEncoder::open(width, height, fps, bitrate_bps, chroma)
|
||||
.map(|e| (Box::new(e) as Box<dyn Encoder>, "pyrowave"));
|
||||
}
|
||||
#[cfg(not(feature = "pyrowave"))]
|
||||
@@ -859,6 +869,13 @@ pub fn vaapi_codec_support() -> CodecSupport {
|
||||
pub fn can_encode_444(codec: Codec) -> bool {
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Mutex, OnceLock};
|
||||
if codec == Codec::PyroWave {
|
||||
// PyroWave does its own RGB→YCbCr CSC (capture always hands it a full-chroma source),
|
||||
// so 4:4:4 needs no GPU encode probe — only the full-res-chroma CSC variant, which
|
||||
// hasn't landed yet (design/pyrowave-444-hdr.md: Phase 2 Linux, Phase 3 Windows).
|
||||
// Flip per-OS when it does.
|
||||
return false;
|
||||
}
|
||||
if codec != Codec::H265 {
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user