M13.4: hevcenc deblocking filter (in-loop, bit-exact with ffmpeg), scratch buffers, POC-wrap / high-QP tests

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Brandon Thomas 2026-10-03 05:15:09 -04:00
parent 4130172bbe
commit c9d5e7335e
215 changed files with 841 additions and 37 deletions

View File

@ -0,0 +1,149 @@
//! Deblocking filter (8.7.2) over a whole reconstructed picture, mirrored from the filmcraft-hevc
//! decoder: all vertical edges on the 8x8 grid first, then all horizontal edges. One slice, one QP,
//! uni-directional prediction from a single reference picture, offsets 0.
use crate::frame::{Blk, E_EDGE_H, E_EDGE_V, F_CBF, F_INTRA};
use crate::tables::{BETA_TABLE, TC_TABLE, qpc_420};
#[inline]
fn tc_beta(q: i32, bs: i32, bd: u32) -> (i32, i32) {
let qb = q.clamp(0, 51);
let qt = (q + 2 * (bs - 1)).clamp(0, 53);
((TC_TABLE[qt as usize] as i32) << (bd - 8), (BETA_TABLE[qb as usize] as i32) << (bd - 8))
}
/// Boundary strength (8.7.2.4) between 4x4 blocks p and q on a transform / prediction edge.
fn boundary_strength(p: &Blk, q: &Blk) -> i32 {
if (p.flags | q.flags) & F_INTRA != 0 {
return 2;
}
if (p.flags | q.flags) & F_CBF != 0 {
return 1;
}
let far = (p.mv[0] as i32 - q.mv[0] as i32).abs() >= 4 || (p.mv[1] as i32 - q.mv[1] as i32).abs() >= 4;
far as i32
}
/// Deblock the planes in place. `qp` is the slice QpY (without QpBdOffset).
pub fn deblock(planes: &mut [Vec<u16>; 3], blk: &[Blk], w: usize, h: usize, qp: i32, bd: u32) {
let (w4, h4) = (w / 4, h / 4);
let cw = w / 2;
// chroma tc (bS 2 only; QpC from the averaged luma QP, no offsets)
let qt = (qpc_420(qp) + 2).clamp(0, 53);
let tc_c = (TC_TABLE[qt as usize] as i32) << (bd - 8);
// vertical edges
for by in 0..h4 {
for bx in (2..w4).step_by(2) {
let qi = by * w4 + bx;
if blk[qi].flags & E_EDGE_V == 0 {
continue;
}
let bs = boundary_strength(&blk[qi - 1], &blk[qi]);
if bs == 0 {
continue;
}
let (x, y) = (bx * 4, by * 4);
let (tc, beta) = tc_beta(qp, bs, bd);
filter_luma(&mut planes[0], y * w + x, 1, w, tc, beta, bd);
// chroma: 8x8 chroma grid (16 luma samples), one 4-sample chroma segment per 8 luma rows
if bs == 2 && bx % 4 == 0 && by % 2 == 0 {
for c in 1..3 {
filter_chroma(&mut planes[c], (y / 2) * cw + x / 2, 1, cw, tc_c, bd);
}
}
}
}
// horizontal edges
for by in (2..h4).step_by(2) {
for bx in 0..w4 {
let qi = by * w4 + bx;
if blk[qi].flags & E_EDGE_H == 0 {
continue;
}
let bs = boundary_strength(&blk[qi - w4], &blk[qi]);
if bs == 0 {
continue;
}
let (x, y) = (bx * 4, by * 4);
let (tc, beta) = tc_beta(qp, bs, bd);
filter_luma(&mut planes[0], y * w + x, w, 1, tc, beta, bd);
if bs == 2 && by % 4 == 0 && bx % 2 == 0 {
for c in 1..3 {
filter_chroma(&mut planes[c], (y / 2) * cw + x / 2, cw, 1, tc_c, bd);
}
}
}
}
}
/// Filter one 4-sample luma edge segment. `o` = offset of q0 of the first line, `step` = distance
/// between samples across the edge, `along` = distance between lines.
#[allow(clippy::too_many_arguments)]
fn filter_luma(s: &mut [u16], o: usize, step: usize, along: usize, tc: i32, beta: i32, bd: u32) {
let px = |s: &[u16], k: usize, i: usize| s[o + k * along - (i + 1) * step] as i32;
let qx = |s: &[u16], k: usize, i: usize| s[o + k * along + i * step] as i32;
let dp0 = (px(s, 0, 2) - 2 * px(s, 0, 1) + px(s, 0, 0)).abs();
let dp3 = (px(s, 3, 2) - 2 * px(s, 3, 1) + px(s, 3, 0)).abs();
let dq0 = (qx(s, 0, 2) - 2 * qx(s, 0, 1) + qx(s, 0, 0)).abs();
let dq3 = (qx(s, 3, 2) - 2 * qx(s, 3, 1) + qx(s, 3, 0)).abs();
let (dpq0, dpq3) = (dp0 + dq0, dp3 + dq3);
let (dp, dq) = (dp0 + dp3, dq0 + dq3);
let d = dpq0 + dpq3;
if d >= beta {
return;
}
let dsam = |s: &[u16], k: usize, dpq: i32| -> bool {
dpq < (beta >> 2)
&& (px(s, k, 3) - px(s, k, 0)).abs() + (qx(s, k, 0) - qx(s, k, 3)).abs() < (beta >> 3)
&& (px(s, k, 0) - qx(s, k, 0)).abs() < ((5 * tc + 1) >> 1)
};
let strong = dsam(s, 0, 2 * dpq0) && dsam(s, 3, 2 * dpq3);
let dep = dp < ((beta + (beta >> 1)) >> 3);
let deq = dq < ((beta + (beta >> 1)) >> 3);
let max = (1i32 << bd) - 1;
for k in 0..4 {
let base = o + k * along;
let p = |i: usize| s[base - (i + 1) * step] as i32;
let q = |i: usize| s[base + i * step] as i32;
let (p0, p1, p2, p3) = (p(0), p(1), p(2), p(3));
let (q0, q1, q2, q3) = (q(0), q(1), q(2), q(3));
if strong {
let t2 = 2 * tc;
s[base - step] = ((p2 + 2 * p1 + 2 * p0 + 2 * q0 + q1 + 4) >> 3).clamp(p0 - t2, p0 + t2) as u16;
s[base - 2 * step] = ((p2 + p1 + p0 + q0 + 2) >> 2).clamp(p1 - t2, p1 + t2) as u16;
s[base - 3 * step] = ((2 * p3 + 3 * p2 + p1 + p0 + q0 + 4) >> 3).clamp(p2 - t2, p2 + t2) as u16;
s[base] = ((p1 + 2 * p0 + 2 * q0 + 2 * q1 + q2 + 4) >> 3).clamp(q0 - t2, q0 + t2) as u16;
s[base + step] = ((p0 + q0 + q1 + q2 + 2) >> 2).clamp(q1 - t2, q1 + t2) as u16;
s[base + 2 * step] = ((p0 + q0 + q1 + 3 * q2 + 2 * q3 + 4) >> 3).clamp(q2 - t2, q2 + t2) as u16;
} else {
let mut delta = (9 * (q0 - p0) - 3 * (q1 - p1) + 8) >> 4;
if delta.abs() >= tc * 10 {
continue;
}
delta = delta.clamp(-tc, tc);
s[base - step] = (p0 + delta).clamp(0, max) as u16;
s[base] = (q0 - delta).clamp(0, max) as u16;
if dep {
let dp = ((((p2 + p0 + 1) >> 1) - p1 + delta) >> 1).clamp(-(tc >> 1), tc >> 1);
s[base - 2 * step] = (p1 + dp).clamp(0, max) as u16;
}
if deq {
let dq = ((((q2 + q0 + 1) >> 1) - q1 - delta) >> 1).clamp(-(tc >> 1), tc >> 1);
s[base + step] = (q1 + dq).clamp(0, max) as u16;
}
}
}
}
/// Filter one 4-sample chroma edge segment.
fn filter_chroma(s: &mut [u16], o: usize, step: usize, along: usize, tc: i32, bd: u32) {
let max = (1i32 << bd) - 1;
for k in 0..4 {
let base = o + k * along;
let (p0, p1) = (s[base - step] as i32, s[base - 2 * step] as i32);
let (q0, q1) = (s[base] as i32, s[base + step] as i32);
let delta = ((((q0 - p0) << 2) + p1 - q1 + 4) >> 3).clamp(-tc, tc);
s[base - step] = (p0 + delta).clamp(0, max) as u16;
s[base] = (q0 - delta).clamp(0, max) as u16;
}
}

View File

@ -12,6 +12,11 @@ use crate::transform;
pub const F_INTRA: u8 = 1;
pub const F_SKIP: u8 = 2;
/// The luma transform block covering this 4x4 block has non-zero coefficients.
pub const F_CBF: u8 = 4;
/// The left / top edge of this 4x4 block is a transform (and prediction) block edge.
pub const E_EDGE_V: u8 = 8;
pub const E_EDGE_H: u8 = 16;
/// Per 4x4 luma block state of the current picture.
#[derive(Clone, Copy, Default)]
@ -79,6 +84,7 @@ pub struct FrameCoder<'a> {
hctb: usize,
pub kind: SliceKind,
/// QP' (with QpBdOffset) for luma and chroma.
slice_qp: i32,
qp_y: i32,
qp_c: i32,
lambda: f64,
@ -91,6 +97,7 @@ pub struct FrameCoder<'a> {
tbs: Vec<Tb>,
coefs: Vec<i32>,
pred: Vec<i16>,
scratch: [Vec<i32>; 2],
}
#[inline]
@ -134,6 +141,7 @@ impl<'a> FrameCoder<'a> {
wctb: w.div_ceil(ctb),
hctb: h.div_ceil(ctb),
kind,
slice_qp,
qp_y: slice_qp + off,
qp_c,
lambda,
@ -146,6 +154,7 @@ impl<'a> FrameCoder<'a> {
tbs: Vec::with_capacity(16),
coefs: Vec::with_capacity(64 * 64 * 2),
pred: vec![0; 64 * 64],
scratch: [vec![0; 32 * 32], vec![0; 32 * 32]],
}
}
@ -182,6 +191,28 @@ impl<'a> FrameCoder<'a> {
}
}
/// Mark the CU's left / top edges and, for CUs larger than the maximum transform size, the
/// inner transform edges (deblocking).
fn mark_edges(&mut self, x: usize, y: usize, log2: u32) {
let n = 1usize << log2;
let t = 1usize << log2.min(LOG2_MAX_TB);
for ty in (y..y + n).step_by(t) {
for tx in (x..x + n).step_by(t) {
for by in ty / 4..(ty + t) / 4 {
self.blk[by * self.w4 + tx / 4].flags |= E_EDGE_V;
}
for b in &mut self.blk[(ty / 4) * self.w4 + tx / 4..(ty / 4) * self.w4 + (tx + t) / 4] {
b.flags |= E_EDGE_H;
}
}
}
}
/// In-loop deblocking of the finished picture.
pub fn deblock(&mut self) {
crate::deblock::deblock(&mut self.rec, &self.blk, self.w, self.h, self.slice_qp, self.bd);
}
fn snap(&self, x: usize, y: usize, n: usize) -> Snap {
let mut planes: [Vec<u16>; 3] = Default::default();
for (c, p) in planes.iter_mut().enumerate() {
@ -387,6 +418,7 @@ impl<'a> FrameCoder<'a> {
b.flags = F_INTRA;
b.ipm = modes[0];
});
self.mark_edges(x, y, log2);
if nxn {
let h = n / 2;
for k in 1..4 {
@ -430,6 +462,7 @@ impl<'a> FrameCoder<'a> {
b.ipm = 1;
b.mv = mv;
});
self.mark_edges(x, y, log2);
self.predict_inter(x, y, n, mv);
let mut eff = mode;
let mut root = false;
@ -439,7 +472,7 @@ impl<'a> FrameCoder<'a> {
if !root && let CuMode::Merge { idx } = mode {
// rqt_root_cbf would be inferred: code a skipped CU instead
eff = CuMode::Skip { idx };
self.fill(x, y, n, |b| b.flags = F_SKIP);
self.fill(x, y, n, |b| b.flags |= F_SKIP);
}
}
match eff {
@ -515,7 +548,8 @@ impl<'a> FrameCoder<'a> {
let bd = self.bd;
predict_from_refs(&refs, c, m, n, bd, &mut self.rec[c][y * stride + x..], stride);
}
let mut r = [0i32; 32 * 32];
let mut scr = std::mem::take(&mut self.scratch);
let [r, coef] = &mut scr;
for yy in 0..n {
let o = (y + yy) * stride + x;
for xx in 0..n {
@ -524,15 +558,16 @@ impl<'a> FrameCoder<'a> {
}
let intra = intra_mode.is_some();
let dst = intra && c == 0 && n == 4;
let mut coef = [0i32; 32 * 32];
transform::forward(&r[..n * n], &mut coef[..n * n], n, dst, self.bd);
let qp = if c == 0 { self.qp_y } else { self.qp_c };
let mut lv = [0i32; 32 * 32];
let nz = transform::quantize(&coef[..n * n], &mut lv[..n * n], n, qp, intra, self.bd) > 0;
let off = self.coefs.len();
self.coefs.resize(off + n * n, 0);
let lv = &mut self.coefs[off..off + n * n];
let nz = transform::quantize(&coef[..n * n], lv, n, qp, intra, self.bd) > 0;
if nz {
let mut d = [0i32; 32 * 32];
transform::dequantize(&lv[..n * n], &mut d[..n * n], n, qp, self.bd);
transform::inverse(&mut d[..n * n], n, dst, self.bd);
let d = &mut r[..n * n];
transform::dequantize(lv, d, n, qp, self.bd);
transform::inverse(d, n, dst, self.bd);
let max = (1i32 << self.bd) - 1;
for yy in 0..n {
let o = (y + yy) * stride + x;
@ -542,12 +577,14 @@ impl<'a> FrameCoder<'a> {
}
}
}
self.scratch = scr;
if nz && c == 0 {
self.fill(x, y, n, |b| b.flags |= F_CBF);
}
let scan = match intra_mode {
Some(m) if log2 == 2 || (log2 == 3 && c == 0) => scan_idx_for_mode(m),
_ => 0,
};
let off = self.coefs.len();
self.coefs.extend_from_slice(&lv[..n * n]);
self.tbs.push(Tb { c: c as u8, lx: lpos.0 as u32, ly: lpos.1 as u32, log2, nz, off, scan });
}

View File

@ -3,9 +3,6 @@
use crate::tables::{CHROMA_FILTER, LUMA_FILTER};
/// Max prediction block size + filter margin.
const WIN: usize = 64 + 7;
/// One plane of a reference picture.
#[derive(Clone, Copy)]
pub struct PlaneRef<'a> {
@ -44,22 +41,23 @@ pub fn mc_luma(f: PlaneRef, bd: u32, x: i32, y: i32, mv: [i16; 2], w: usize, h:
let yi = y + (mv[1] as i32 >> 2);
let shift1 = bd.min(12) - 8;
let shift3 = 14 - bd;
let mut win = [0i16; WIN * WIN];
let ws = w + 7;
let mut win = vec![0i16; ws * (h + 7)];
if fx == 0 && fy == 0 {
f.window(xi, yi, w, h, &mut win, WIN);
f.window(xi, yi, w, h, &mut win, ws);
for r in 0..h {
for c in 0..w {
out[r * w + c] = win[r * WIN + c] << shift3;
out[r * w + c] = win[r * ws + c] << shift3;
}
}
return;
}
f.window(xi - 3, yi - 3, w + 7, h + 7, &mut win, WIN);
f.window(xi - 3, yi - 3, w + 7, h + 7, &mut win, ws);
let hf = &LUMA_FILTER[fx];
let vf = &LUMA_FILTER[fy];
if fy == 0 {
for r in 0..h {
let row = &win[(r + 3) * WIN..];
let row = &win[(r + 3) * ws..];
for c in 0..w {
let s: i32 = (0..8).map(|k| hf[k] as i32 * row[c + k] as i32).sum();
out[r * w + c] = (s >> shift1) as i16;
@ -68,22 +66,22 @@ pub fn mc_luma(f: PlaneRef, bd: u32, x: i32, y: i32, mv: [i16; 2], w: usize, h:
} else if fx == 0 {
for r in 0..h {
for c in 0..w {
let s: i32 = (0..8).map(|k| vf[k] as i32 * win[(r + k) * WIN + c + 3] as i32).sum();
let s: i32 = (0..8).map(|k| vf[k] as i32 * win[(r + k) * ws + c + 3] as i32).sum();
out[r * w + c] = (s >> shift1) as i16;
}
}
} else {
let mut tmp = [0i16; WIN * WIN];
let mut tmp = vec![0i16; ws * (h + 7)];
for r in 0..h + 7 {
let row = &win[r * WIN..];
let row = &win[r * ws..];
for c in 0..w {
let s: i32 = (0..8).map(|k| hf[k] as i32 * row[c + k] as i32).sum();
tmp[r * WIN + c] = (s >> shift1) as i16;
tmp[r * ws + c] = (s >> shift1) as i16;
}
}
for r in 0..h {
for c in 0..w {
let s: i32 = (0..8).map(|k| vf[k] as i32 * tmp[(r + k) * WIN + c] as i32).sum();
let s: i32 = (0..8).map(|k| vf[k] as i32 * tmp[(r + k) * ws + c] as i32).sum();
out[r * w + c] = (s >> 6) as i16;
}
}
@ -97,22 +95,23 @@ pub fn mc_chroma(f: PlaneRef, bd: u32, x: i32, y: i32, mv: [i16; 2], w: usize, h
let yi = y + (mv[1] as i32 >> 3);
let shift1 = bd.min(12) - 8;
let shift3 = 14 - bd;
let mut win = [0i16; WIN * WIN];
let ws = w + 7;
let mut win = vec![0i16; ws * (h + 7)];
if fx == 0 && fy == 0 {
f.window(xi, yi, w, h, &mut win, WIN);
f.window(xi, yi, w, h, &mut win, ws);
for r in 0..h {
for c in 0..w {
out[r * w + c] = win[r * WIN + c] << shift3;
out[r * w + c] = win[r * ws + c] << shift3;
}
}
return;
}
f.window(xi - 1, yi - 1, w + 3, h + 3, &mut win, WIN);
f.window(xi - 1, yi - 1, w + 3, h + 3, &mut win, ws);
let hf = &CHROMA_FILTER[fx];
let vf = &CHROMA_FILTER[fy];
if fy == 0 {
for r in 0..h {
let row = &win[(r + 1) * WIN..];
let row = &win[(r + 1) * ws..];
for c in 0..w {
let s: i32 = (0..4).map(|k| hf[k] as i32 * row[c + k] as i32).sum();
out[r * w + c] = (s >> shift1) as i16;
@ -121,22 +120,22 @@ pub fn mc_chroma(f: PlaneRef, bd: u32, x: i32, y: i32, mv: [i16; 2], w: usize, h
} else if fx == 0 {
for r in 0..h {
for c in 0..w {
let s: i32 = (0..4).map(|k| vf[k] as i32 * win[(r + k) * WIN + c + 1] as i32).sum();
let s: i32 = (0..4).map(|k| vf[k] as i32 * win[(r + k) * ws + c + 1] as i32).sum();
out[r * w + c] = (s >> shift1) as i16;
}
}
} else {
let mut tmp = [0i16; WIN * WIN];
let mut tmp = vec![0i16; ws * (h + 7)];
for r in 0..h + 3 {
let row = &win[r * WIN..];
let row = &win[r * ws..];
for c in 0..w {
let s: i32 = (0..4).map(|k| hf[k] as i32 * row[c + k] as i32).sum();
tmp[r * WIN + c] = (s >> shift1) as i16;
tmp[r * ws + c] = (s >> shift1) as i16;
}
}
for r in 0..h {
for c in 0..w {
let s: i32 = (0..4).map(|k| vf[k] as i32 * tmp[(r + k) * WIN + c] as i32).sum();
let s: i32 = (0..4).map(|k| vf[k] as i32 * tmp[(r + k) * ws + c] as i32).sum();
out[r * w + c] = (s >> 6) as i16;
}
}

View File

@ -3,7 +3,7 @@
//! Main and Main 10 profiles, 4:2:0, one slice per picture: IDR pictures and single-reference P
//! pictures (no reordering), 64x64 CTUs with rate-distortion coding-unit decisions (8x8 .. 64x64),
//! intra (35 modes, NxN at 8x8), merge / skip and AMVP inter prediction with quarter-sample motion,
//! DCT / DST transforms and CABAC. In-loop filters (deblocking, SAO) are disabled.
//! DCT / DST transforms and CABAC. The deblocking filter is on; SAO is not used.
//!
//! ```
//! use effectcraft_hevcenc::{Encoder, EncoderConfig, Frame};
@ -19,6 +19,7 @@
mod bitstream;
mod cabac;
mod deblock;
mod frame;
mod inter;
mod intra;
@ -333,6 +334,7 @@ impl Encoder {
let ctx = cabac::init_contexts(qp, if idr { 0 } else { 1 });
let mut enc = cabac::CabacEncoder::new(bw, ctx);
fc.encode(&mut enc);
fc.deblock();
let rbsp = enc.finish().into_bytes();
let nal = nal_unit(if idr { NAL_IDR_N_LP } else { NAL_TRAIL_R }, &rbsp);
let mut data = Vec::with_capacity(nal.len() + 4);

View File

@ -208,7 +208,9 @@ pub fn pps() -> Vec<u8> {
w.put(0, 1); // pps_loop_filter_across_slices_enabled_flag
w.put(1, 1); // deblocking_filter_control_present_flag
w.put(0, 1); // deblocking_filter_override_enabled_flag
w.put(1, 1); // pps_deblocking_filter_disabled_flag
w.put(0, 1); // pps_deblocking_filter_disabled_flag
w.se(0); // pps_beta_offset_div2
w.se(0); // pps_tc_offset_div2
w.put(0, 1); // pps_scaling_list_data_present_flag
w.put(0, 1); // lists_modification_present_flag
w.ue(0); // log2_parallel_merge_level_minus2

View File

@ -230,3 +230,7 @@ pub static TRANS_MATRIX: [[i8; 32]; 32] = [
[9, -25, 43, -57, 70, -80, 87, -90, 90, -87, 80, -70, 57, -43, 25, -9, -9, 25, -43, 57, -70, 80, -87, 90, -90, 87, -80, 70, -57, 43, -25, 9],
[4, -13, 22, -31, 38, -46, 54, -61, 67, -73, 78, -82, 85, -88, 90, -90, 90, -90, 88, -85, 82, -78, 73, -67, 61, -54, 46, -38, 31, -22, 13, -4],
];
/// Table 8-12: beta' for Q = 0..51.
pub static BETA_TABLE: [u8; 52] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64];
/// Table 8-12: tC' for Q = 0..53.
pub static TC_TABLE: [u8; 54] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 9, 10, 11, 13, 14, 16, 18, 20, 22, 24];

View File

@ -95,7 +95,7 @@ pub fn forward(r: &[i32], c: &mut [i32], n: usize, dst: bool, bit_depth: u32) {
let shift1 = log2 + bit_depth - 9;
let shift2 = log2 + 6;
let (r1, r2) = (1i32 << (shift1 - 1), 1i32 << (shift2 - 1));
let mut tmp = [0i32; 32 * 32];
let mut tmp = vec![0i32; n * n];
let mut out = [0i32; 32];
// rows (horizontal frequencies)
for y in 0..n {
@ -127,7 +127,7 @@ pub fn forward(r: &[i32], c: &mut [i32], n: usize, dst: bool, bit_depth: u32) {
/// Inverse 2-D transform (8.6.4.2) of scaled coefficients `d` in place, producing residuals.
pub fn inverse(d: &mut [i32], n: usize, dst: bool, bit_depth: u32) {
let bd_shift = 20 - bit_depth;
let mut tmp = [0i32; 32 * 32];
let mut tmp = vec![0i32; n * n];
let mut col = [0i32; 32];
let mut out = [0i32; 32];
// max non-zero row, to skip empty work

View File

@ -0,0 +1 @@
{"rustc_fingerprint":9559367331539902066,"outputs":{"4233666815994275565":{"success":true,"status":"","code":0,"stdout":"rustc 1.96.0 (ac68faa20 2026-05-25)\nbinary: rustc\ncommit-hash: ac68faa20c58cbccd01ee7208bf3b6e93a7d7f96\ncommit-date: 2026-05-25\nhost: aarch64-apple-darwin\nrelease: 1.96.0\nLLVM version: 22.1.2\n","stderr":""},"7971740275564407648":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.dylib\nlib___.dylib\nlib___.a\nlib___.dylib\n/Users/bt/.rustup/toolchains/stable-aarch64-apple-darwin\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"aarch64\"\ntarget_endian=\"little\"\ntarget_env=\"\"\ntarget_family=\"unix\"\ntarget_feature=\"aes\"\ntarget_feature=\"crc\"\ntarget_feature=\"dit\"\ntarget_feature=\"dotprod\"\ntarget_feature=\"dpb\"\ntarget_feature=\"dpb2\"\ntarget_feature=\"fcma\"\ntarget_feature=\"fhm\"\ntarget_feature=\"flagm\"\ntarget_feature=\"fp16\"\ntarget_feature=\"frintts\"\ntarget_feature=\"jsconv\"\ntarget_feature=\"lor\"\ntarget_feature=\"lse\"\ntarget_feature=\"neon\"\ntarget_feature=\"paca\"\ntarget_feature=\"pacg\"\ntarget_feature=\"pan\"\ntarget_feature=\"pmuv3\"\ntarget_feature=\"ras\"\ntarget_feature=\"rcpc\"\ntarget_feature=\"rcpc2\"\ntarget_feature=\"rdm\"\ntarget_feature=\"sb\"\ntarget_feature=\"sha2\"\ntarget_feature=\"sha3\"\ntarget_feature=\"ssbs\"\ntarget_feature=\"vh\"\ntarget_has_atomic=\"128\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"macos\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"apple\"\nunix\n","stderr":""}},"successes":{}}

View File

@ -0,0 +1,3 @@
Signature: 8a477f597d28d172789f06886806bc55
# This file is a cache directory tag created by cargo.
# For information about cache directory tags see https://bford.info/cachedir/

View File

@ -0,0 +1 @@
{"rustc":17467972547956852243,"features":"[\"default\", \"std\"]","declared_features":"[\"default\", \"std\"]","target":5408242616063297496,"profile":3185167420583542146,"path":6080947815111469725,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/crossbeam-deque-5b3c4336788f7174/dep-build-script-build-script-build","checksum":false}}],"rustflags":[],"config":8247474407144887393,"compile_kind":0}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
{"rustc":17467972547956852243,"features":"[\"default\", \"std\"]","declared_features":"[\"default\", \"std\"]","target":15353977948366730291,"profile":3185167420583542146,"path":2714696676876033032,"deps":[[2543204310390312751,"crossbeam_epoch",false,15863831904650651516],[11050506297539643678,"crossbeam_utils",false,11092378776446818952],[15481973119957668846,"build_script_build",false,7352081084529830974]],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/crossbeam-deque-d9775930f3a59590/dep-lib-crossbeam_deque","checksum":false}}],"rustflags":[],"config":8247474407144887393,"compile_kind":0}

View File

@ -0,0 +1 @@
{"rustc":17467972547956852243,"features":"","declared_features":"","target":0,"profile":0,"path":0,"deps":[[15481973119957668846,"build_script_build",false,7450707238475295241]],"local":[{"RerunIfChanged":{"output":"debug/build/crossbeam-deque-f51f1776f2c514b1/output","paths":["build.rs"]}}],"rustflags":[],"config":0,"compile_kind":0}

View File

@ -0,0 +1 @@
{"rustc":17467972547956852243,"features":"[\"alloc\", \"std\"]","declared_features":"[\"alloc\", \"default\", \"loom\", \"loom-crate\", \"nightly\", \"std\"]","target":5408242616063297496,"profile":3185167420583542146,"path":5028293854929153649,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/crossbeam-epoch-1347d2207ea061ce/dep-build-script-build-script-build","checksum":false}}],"rustflags":[],"config":8247474407144887393,"compile_kind":0}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
{"rustc":17467972547956852243,"features":"","declared_features":"","target":0,"profile":0,"path":0,"deps":[[2543204310390312751,"build_script_build",false,8243769256497239062]],"local":[{"RerunIfChanged":{"output":"debug/build/crossbeam-epoch-2092bf031b9d9a01/output","paths":["build.rs"]}}],"rustflags":[],"config":0,"compile_kind":0}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
{"rustc":17467972547956852243,"features":"[\"alloc\", \"std\"]","declared_features":"[\"alloc\", \"default\", \"loom\", \"loom-crate\", \"nightly\", \"std\"]","target":16242420667881341737,"profile":3185167420583542146,"path":7266900391393874633,"deps":[[2543204310390312751,"build_script_build",false,5592067657492884931],[11050506297539643678,"crossbeam_utils",false,11092378776446818952]],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/crossbeam-epoch-72c18a120600cf42/dep-lib-crossbeam_epoch","checksum":false}}],"rustflags":[],"config":8247474407144887393,"compile_kind":0}

View File

@ -0,0 +1 @@
{"rustc":17467972547956852243,"features":"[\"default\", \"std\"]","declared_features":"[\"default\", \"loom\", \"nightly\", \"std\"]","target":5408242616063297496,"profile":3185167420583542146,"path":14844284517995534797,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/crossbeam-utils-5b2ff6828cdce4c3/dep-build-script-build-script-build","checksum":false}}],"rustflags":[],"config":8247474407144887393,"compile_kind":0}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
{"rustc":17467972547956852243,"features":"[\"default\", \"std\"]","declared_features":"[\"default\", \"loom\", \"nightly\", \"std\"]","target":9626079250877207070,"profile":3185167420583542146,"path":16937405451120399764,"deps":[[11050506297539643678,"build_script_build",false,8108134710804475658]],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/crossbeam-utils-799e464d44773a7d/dep-lib-crossbeam_utils","checksum":false}}],"rustflags":[],"config":8247474407144887393,"compile_kind":0}

View File

@ -0,0 +1 @@
{"rustc":17467972547956852243,"features":"","declared_features":"","target":0,"profile":0,"path":0,"deps":[[11050506297539643678,"build_script_build",false,11686781118169869501]],"local":[{"RerunIfChanged":{"output":"debug/build/crossbeam-utils-99f1d686cf22430f/output","paths":["no_atomic.rs"]}}],"rustflags":[],"config":0,"compile_kind":0}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
{"rustc":17467972547956852243,"features":"[]","declared_features":"[]","target":13741281541045977916,"profile":14861435456621666076,"path":1524816848624354599,"deps":[[5706705931987278984,"filmcraft_hevc",false,1065779467293311985],[10103226027885832861,"effectcraft_hevcenc",false,3919018516886026431]],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/effectcraft-hevcenc-335f1f822197d831/dep-test-integration-test-roundtrip","checksum":false}}],"rustflags":[],"config":8247474407144887393,"compile_kind":0}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
{"rustc":17467972547956852243,"features":"[]","declared_features":"[]","target":11125424694902762418,"profile":15209061013077869454,"path":6858098780819335099,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/effectcraft-hevcenc-955aee250b2c2a4e/dep-lib-effectcraft_hevcenc","checksum":false}}],"rustflags":[],"config":8247474407144887393,"compile_kind":0}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
{"rustc":17467972547956852243,"features":"[]","declared_features":"[\"default\", \"serde\", \"std\", \"use_std\"]","target":17124342308084364240,"profile":2785734998891497023,"path":5546998507963859579,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/either-72952a75ef45a16d/dep-lib-either","checksum":false}}],"rustflags":[],"config":8247474407144887393,"compile_kind":0}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
{"rustc":17467972547956852243,"features":"[]","declared_features":"[]","target":18127681992696119206,"profile":12938959104297781942,"path":12854803809928081657,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/filmcraft-bitstream-2ad770771b023a77/dep-lib-filmcraft_bitstream","checksum":false}}],"rustflags":[],"config":8247474407144887393,"compile_kind":0}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
{"rustc":17467972547956852243,"features":"[\"default\", \"threads\"]","declared_features":"[\"default\", \"threads\"]","target":9847609124140232008,"profile":15209061013077869454,"path":2590569095805419776,"deps":[[1957009224993739128,"thiserror",false,17538703420373504327],[4943083844709074312,"filmcraft_bitstream",false,14245647949184604933],[11910974697091955563,"rayon",false,13044872296819726823]],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/filmcraft-hevc-71cf1ac5fd5debba/dep-lib-filmcraft_hevc","checksum":false}}],"rustflags":[],"config":8247474407144887393,"compile_kind":0}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
{"rustc":17467972547956852243,"features":"[\"default\", \"proc-macro\"]","declared_features":"[\"default\", \"nightly\", \"proc-macro\", \"span-locations\"]","target":369203346396300798,"profile":2785734998891497023,"path":2809009335364014821,"deps":[[12333832803962989937,"unicode_ident",false,16793811267078206154],[16346726298725429545,"build_script_build",false,12224304350208236698]],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/proc-macro2-67c058b976f66fb4/dep-lib-proc_macro2","checksum":false}}],"rustflags":[],"config":8247474407144887393,"compile_kind":0}

View File

@ -0,0 +1 @@
{"rustc":17467972547956852243,"features":"","declared_features":"","target":0,"profile":0,"path":0,"deps":[[16346726298725429545,"build_script_build",false,11266185680237871916]],"local":[{"RerunIfChanged":{"output":"debug/build/proc-macro2-73f2303f90bf5dd8/output","paths":["src/probe/proc_macro_span.rs","src/probe/proc_macro_span_location.rs","src/probe/proc_macro_span_file.rs"]}},{"RerunIfEnvChanged":{"var":"RUSTC_BOOTSTRAP","val":null}}],"rustflags":[],"config":0,"compile_kind":0}

View File

@ -0,0 +1 @@
{"rustc":17467972547956852243,"features":"[\"default\", \"proc-macro\"]","declared_features":"[\"default\", \"nightly\", \"proc-macro\", \"span-locations\"]","target":5408242616063297496,"profile":2785734998891497023,"path":15930204402656880288,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/proc-macro2-8b5400504772b527/dep-build-script-build-script-build","checksum":false}}],"rustflags":[],"config":8247474407144887393,"compile_kind":0}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
{"rustc":17467972547956852243,"features":"[\"default\", \"proc-macro\"]","declared_features":"[\"default\", \"proc-macro\"]","target":8313845041260779044,"profile":2785734998891497023,"path":8077693039016294807,"deps":[[8949245912927223590,"build_script_build",false,2599661241357163625],[16346726298725429545,"proc_macro2",false,8059170461296913469]],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/quote-0f85966d6f134e44/dep-lib-quote","checksum":false}}],"rustflags":[],"config":8247474407144887393,"compile_kind":0}

View File

@ -0,0 +1 @@
{"rustc":17467972547956852243,"features":"[\"default\", \"proc-macro\"]","declared_features":"[\"default\", \"proc-macro\"]","target":5408242616063297496,"profile":2785734998891497023,"path":2672923304195493942,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/quote-4b484c95cbb303f6/dep-build-script-build-script-build","checksum":false}}],"rustflags":[],"config":8247474407144887393,"compile_kind":0}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
{"rustc":17467972547956852243,"features":"","declared_features":"","target":0,"profile":0,"path":0,"deps":[[8949245912927223590,"build_script_build",false,6801077628558105620]],"local":[{"RerunIfChanged":{"output":"debug/build/quote-d3fa970117425bd7/output","paths":["build.rs"]}}],"rustflags":[],"config":0,"compile_kind":0}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
{"rustc":17467972547956852243,"features":"[]","declared_features":"[\"web_spin_lock\"]","target":4732152328429177609,"profile":2785734998891497023,"path":17431103954642750794,"deps":[[3746573929696391749,"rayon_core",false,11362863269611761524],[13370710369771896710,"either",false,1697150408193231268]],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/rayon-6e2dc17155d9fd34/dep-lib-rayon","checksum":false}}],"rustflags":[],"config":8247474407144887393,"compile_kind":0}

View File

@ -0,0 +1 @@
{"rustc":17467972547956852243,"features":"","declared_features":"","target":0,"profile":0,"path":0,"deps":[[3746573929696391749,"build_script_build",false,5512398614385402082]],"local":[{"RerunIfChanged":{"output":"debug/build/rayon-core-1b6fdb81fee9810e/output","paths":["build.rs"]}}],"rustflags":[],"config":0,"compile_kind":0}

View File

@ -0,0 +1 @@
{"rustc":17467972547956852243,"features":"[]","declared_features":"[\"web_spin_lock\"]","target":5408242616063297496,"profile":2785734998891497023,"path":10372009197711997420,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/rayon-core-b409a671b98b8570/dep-build-script-build-script-build","checksum":false}}],"rustflags":[],"config":8247474407144887393,"compile_kind":0}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
{"rustc":17467972547956852243,"features":"[]","declared_features":"[\"web_spin_lock\"]","target":12465439074827573786,"profile":2785734998891497023,"path":7184092575742886946,"deps":[[3746573929696391749,"build_script_build",false,11822094963353688590],[11050506297539643678,"crossbeam_utils",false,11092378776446818952],[15481973119957668846,"crossbeam_deque",false,12816530492324934566]],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/rayon-core-d9d479d6cc7ea71c/dep-lib-rayon_core","checksum":false}}],"rustflags":[],"config":8247474407144887393,"compile_kind":0}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
{"rustc":17467972547956852243,"features":"[\"clone-impls\", \"default\", \"derive\", \"parsing\", \"printing\", \"proc-macro\"]","declared_features":"[\"clone-impls\", \"default\", \"derive\", \"extra-traits\", \"fold\", \"full\", \"parsing\", \"printing\", \"proc-macro\", \"test\", \"visit\", \"visit-mut\"]","target":9442126953582868550,"profile":2785734998891497023,"path":8687046859460428135,"deps":[[8949245912927223590,"quote",false,10592669266501340001],[12333832803962989937,"unicode_ident",false,16793811267078206154],[16346726298725429545,"proc_macro2",false,8059170461296913469]],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/syn-86f5aa6c6ace4240/dep-lib-syn","checksum":false}}],"rustflags":[],"config":8247474407144887393,"compile_kind":0}

Some files were not shown because too many files have changed in this diff Show More