Skip to content

Commit c9c6942

Browse files
feat: implement video compositor review recommendations (#136)
- Add debug assertions for Y-plane raw pointer aliasing in convert.rs - Clarify AVX2 packus cross-lane comments in simd_x86_64.rs - Shrink ConversionCache entries when resolution decreases (>2x) - Add max-entry bound (64) to FONT_CACHE with eviction - Validate decoded image dimensions against max_canvas_dimension - Fix fragile sleep-based test in pixel_convert.rs - Derive Copy for Rect and BlitRect, remove unnecessary clones - Remove compositor/pixel_ops/mod.rs re-export shim - Extract shared bench_utils module for generate_rgba_frame - Use font.metrics() instead of rasterize() for measurement - Migrate compositor_only and pixel_convert benchmarks to criterion Signed-off-by: Devin AI <devin@cognition.ai> Co-authored-by: bot_apk <apk@cognition.ai> Co-authored-by: Staging-Devin AI <166158716+staging-devin-ai-integration[bot]@users.noreply.github.com>
1 parent d4ad4c0 commit c9c6942

File tree

17 files changed

+375
-780
lines changed

17 files changed

+375
-780
lines changed

Cargo.lock

Lines changed: 116 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ indexmap = { version = "2.13", features = ["serde"] }
4545

4646
opentelemetry = "0.31.0"
4747

48+
criterion = { version = "0.5", default-features = false }
49+
4850
# Profile settings
4951
[profile.release]
5052
debug = 1 # Include line tables for better stack traces in profiling

crates/engine/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ keywords = ["audio", "pipeline", "engine", "streaming", "realtime"]
1111
categories = ["multimedia", "network-programming"]
1212
readme = "README.md"
1313
publish = false
14+
autobenches = false
1415

1516
[dependencies]
1617
# Skit's core library
@@ -56,6 +57,7 @@ script = ["streamkit-nodes/script"]
5657
compositor = ["streamkit-nodes/compositor"]
5758

5859
[dev-dependencies]
60+
criterion = { workspace = true }
5961
serde_json = { workspace = true }
6062
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
6163
futures = { workspace = true }
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// SPDX-FileCopyrightText: © 2025 StreamKit Contributors
2+
//
3+
// SPDX-License-Identifier: MPL-2.0
4+
5+
//! Shared utilities for benchmark binaries.
6+
7+
#![allow(dead_code)] // Not every bench uses every helper.
8+
9+
use streamkit_nodes::video::pixel_ops::{rgba8_to_i420_buf, rgba8_to_nv12_buf};
10+
11+
/// Standard resolutions used across benchmark suites.
12+
pub const RESOLUTIONS: &[(u32, u32)] = &[(640, 480), (1280, 720), (1920, 1080)];
13+
14+
/// Generate an RGBA8 color-bar frame (opaque, all alpha = 255).
15+
#[allow(
16+
clippy::many_single_char_names,
17+
clippy::cast_possible_truncation,
18+
clippy::cast_sign_loss,
19+
clippy::cast_precision_loss
20+
)]
21+
pub fn generate_rgba_frame(width: u32, height: u32) -> Vec<u8> {
22+
let w = width as usize;
23+
let h = height as usize;
24+
let mut data = vec![0u8; w * h * 4];
25+
let bar_colors: &[(u8, u8, u8)] = &[
26+
(191, 191, 191), // white
27+
(191, 191, 0), // yellow
28+
(0, 191, 191), // cyan
29+
(0, 191, 0), // green
30+
(191, 0, 191), // magenta
31+
(191, 0, 0), // red
32+
(0, 0, 191), // blue
33+
];
34+
for row in 0..h {
35+
for col in 0..w {
36+
let bar_idx = col * bar_colors.len() / w;
37+
let (r, g, b) = bar_colors[bar_idx];
38+
let off = (row * w + col) * 4;
39+
data[off] = r;
40+
data[off + 1] = g;
41+
data[off + 2] = b;
42+
data[off + 3] = 255;
43+
}
44+
}
45+
data
46+
}
47+
48+
/// Generate an I420 frame by converting an RGBA frame.
49+
pub fn generate_i420_frame(width: u32, height: u32) -> Vec<u8> {
50+
let rgba = generate_rgba_frame(width, height);
51+
let w = width as usize;
52+
let h = height as usize;
53+
let chroma_w = w.div_ceil(2);
54+
let chroma_h = h.div_ceil(2);
55+
let i420_size = w * h + 2 * chroma_w * chroma_h;
56+
let mut i420 = vec![0u8; i420_size];
57+
rgba8_to_i420_buf(&rgba, width, height, &mut i420);
58+
i420
59+
}
60+
61+
/// Generate an NV12 frame by converting an RGBA frame.
62+
pub fn generate_nv12_frame(width: u32, height: u32) -> Vec<u8> {
63+
let rgba = generate_rgba_frame(width, height);
64+
let w = width as usize;
65+
let h = height as usize;
66+
let chroma_w = w.div_ceil(2);
67+
let chroma_h = h.div_ceil(2);
68+
let nv12_size = w * h + chroma_w * 2 * chroma_h;
69+
let mut nv12 = vec![0u8; nv12_size];
70+
rgba8_to_nv12_buf(&rgba, width, height, &mut nv12);
71+
nv12
72+
}

0 commit comments

Comments
 (0)