Skip to content

Commit b374ba1

Browse files
fix(nodes): register HW codec nodes, fix i420_to_nv12 truncation, remove dead code
- Add cfg-gated registration calls for vulkan_video, vaapi, and nvcodec nodes in register_video_nodes() — without these, users enabling the features would get 'node not found' errors at runtime. - Fix i420_to_nv12 in vulkan_video.rs to use div_ceil(2) for chroma dimensions instead of truncating integer division (h/2, w/2), matching the correct implementation in nv_av1.rs. - Update HwAccelMode::Auto doc comment to accurately reflect that HW-only nodes do not implement CPU fallback — Auto and ForceHw behave identically; CPU fallback is achieved by selecting a different (software) node at the pipeline level. - Remove dead default_quality() and default_framerate() functions in vaapi_av1.rs (unused — the struct uses a manual Default impl). - Add registration regression tests to nv_av1 and vaapi_av1 modules. Signed-off-by: StreamKit Devin <devin@streamkit.dev> Co-Authored-By: Claudio Costa <cstcld91@gmail.com>
1 parent 62341bd commit b374ba1

File tree

4 files changed

+54
-14
lines changed

4 files changed

+54
-14
lines changed

crates/nodes/src/video/mod.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,12 @@ pub const H264_CONTENT_TYPE: &str = "video/h264";
8484
)]
8585
#[serde(rename_all = "lowercase")]
8686
pub enum HwAccelMode {
87-
/// Auto-detect: use HW if available, fall back to CPU otherwise.
87+
/// Auto-detect: attempt hardware acceleration.
88+
///
89+
/// For HW-only nodes (Vulkan Video, VA-API, NVENC/NVDEC) this behaves
90+
/// identically to `ForceHw` — the node will fail if the required
91+
/// hardware is unavailable. CPU fallback is achieved by selecting a
92+
/// different (software) node at the pipeline level.
8893
#[default]
8994
Auto,
9095
/// Force HW acceleration — fail if unavailable.
@@ -631,4 +636,13 @@ pub fn register_video_nodes(registry: &mut NodeRegistry, constraints: &GlobalNod
631636

632637
#[cfg(feature = "dav1d")]
633638
dav1d::register_dav1d_nodes(registry);
639+
640+
#[cfg(feature = "vulkan_video")]
641+
vulkan_video::register_vulkan_video_nodes(registry);
642+
643+
#[cfg(feature = "vaapi")]
644+
vaapi_av1::register_vaapi_av1_nodes(registry);
645+
646+
#[cfg(feature = "nvcodec")]
647+
nv_av1::register_nv_av1_nodes(registry);
634648
}

crates/nodes/src/video/nv_av1.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1182,4 +1182,21 @@ mod tests {
11821182
}
11831183
}
11841184
}
1185+
1186+
// ── Registration test ────────────────────────────────────────────────
1187+
1188+
#[test]
1189+
fn test_node_registration() {
1190+
let mut registry = NodeRegistry::new();
1191+
register_nv_av1_nodes(&mut registry);
1192+
1193+
assert!(
1194+
registry.create_node("video::nv::av1_decoder", None).is_ok(),
1195+
"NV AV1 decoder should be registered"
1196+
);
1197+
assert!(
1198+
registry.create_node("video::nv::av1_encoder", None).is_ok(),
1199+
"NV AV1 encoder should be registered"
1200+
);
1201+
}
11851202
}

crates/nodes/src/video/vaapi_av1.rs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -747,14 +747,6 @@ pub struct VaapiAv1EncoderConfig {
747747
pub hw_accel: HwAccelMode,
748748
}
749749

750-
const fn default_quality() -> u32 {
751-
DEFAULT_QUALITY
752-
}
753-
754-
const fn default_framerate() -> u32 {
755-
DEFAULT_FRAMERATE
756-
}
757-
758750
impl Default for VaapiAv1EncoderConfig {
759751
fn default() -> Self {
760752
Self {
@@ -1804,4 +1796,21 @@ mod tests {
18041796
let result: Result<VaapiAv1EncoderConfig, _> = serde_json::from_str(json);
18051797
assert!(result.is_err(), "Unknown fields should be rejected");
18061798
}
1799+
1800+
// ── Registration test ────────────────────────────────────────────────
1801+
1802+
#[test]
1803+
fn test_node_registration() {
1804+
let mut registry = NodeRegistry::new();
1805+
register_vaapi_av1_nodes(&mut registry);
1806+
1807+
assert!(
1808+
registry.create_node("video::vaapi::av1_decoder", None).is_ok(),
1809+
"VA-API AV1 decoder should be registered"
1810+
);
1811+
assert!(
1812+
registry.create_node("video::vaapi::av1_encoder", None).is_ok(),
1813+
"VA-API AV1 encoder should be registered"
1814+
);
1815+
}
18071816
}

crates/nodes/src/video/vulkan_video.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -737,9 +737,11 @@ fn i420_to_nv12(frame: &VideoFrame) -> Vec<u8> {
737737
let h = frame.height as usize;
738738
let layout = frame.layout();
739739

740+
let chroma_w = w.div_ceil(2);
741+
let chroma_h = h.div_ceil(2);
742+
let uv_row_bytes = chroma_w * 2;
740743
let y_size = w * h;
741-
let uv_size = w * (h / 2);
742-
let mut nv12 = vec![0u8; y_size + uv_size];
744+
let mut nv12 = vec![0u8; y_size + uv_row_bytes * chroma_h];
743745

744746
let src = frame.data.as_slice();
745747
let planes = layout.planes();
@@ -756,12 +758,10 @@ fn i420_to_nv12(frame: &VideoFrame) -> Vec<u8> {
756758
}
757759

758760
// Interleave U and V into NV12 UV plane.
759-
let chroma_h = h / 2;
760-
let chroma_w = w / 2;
761761
for row in 0..chroma_h {
762762
let u_src_start = u_plane.offset + row * u_plane.stride;
763763
let v_src_start = v_plane.offset + row * v_plane.stride;
764-
let dst_start = y_size + row * w;
764+
let dst_start = y_size + row * uv_row_bytes;
765765
for col in 0..chroma_w {
766766
nv12[dst_start + col * 2] = src[u_src_start + col];
767767
nv12[dst_start + col * 2 + 1] = src[v_src_start + col];

0 commit comments

Comments
 (0)