refactor: video branch code de-duplication and simplification#103
refactor: video branch code de-duplication and simplification#103streamer45 merged 10 commits intovideofrom
Conversation
Move the pixel-level operations (blit, convert, SIMD kernels) from video::compositor::pixel_ops to video::pixel_ops so they can be shared between the compositor, pixel-convert node, and future video nodes. - Introduce BlitRect in pixel_ops::blit to decouple from compositor config::Rect - Add From<Rect> for BlitRect in kernel.rs for seamless conversion - Replace compositor/pixel_ops with thin re-export shim - Update all import paths (pixel_convert.rs, kernel.rs, tests, benchmarks) Co-Authored-By: Claudio Costa <cstcld91@gmail.com>
Co-Authored-By: Claudio Costa <cstcld91@gmail.com>
Move the generic select-loop from video/vp9.rs into a new crate::codec_utils module so that PixelConvertNode, OpusEncoderNode, and OpusDecoderNode can reuse it instead of hand-rolling near-identical loops. - VP9 decoder/encoder: import from crate::codec_utils - PixelConvertNode: replace ~80-line hand-rolled loop - OpusEncoderNode: replace ~100-line hand-rolled loop - OpusDecoderNode: move AudioFrame construction into blocking task so the result channel sends Result<Packet, String> directly, enabling use of the shared loop Co-Authored-By: Claudio Costa <cstcld91@gmail.com>
Co-Authored-By: Claudio Costa <cstcld91@gmail.com>
Move ~1050 lines of tests from compositor/mod.rs into compositor/tests.rs, included via #[path = "tests.rs"]. No test logic changes — purely a file split for readability. Co-Authored-By: Claudio Costa <cstcld91@gmail.com>
Co-Authored-By: Claudio Costa <cstcld91@gmail.com>
Extract validate_layout() to deduplicate identical validation logic between from_pooled_with_layout and from_arc_with_layout. Co-Authored-By: Claudio Costa <cstcld91@gmail.com>
Co-Authored-By: Claudio Costa <cstcld91@gmail.com>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
pixel_ops contains general-purpose pixel format conversion functions that don't depend on any compositor-specific crates. Gate it on the broader 'video' feature so it's available whenever any video node (vp9, colorbars, or compositor) is enabled. Co-Authored-By: Claudio Costa <cstcld91@gmail.com>
crates/nodes/src/video/mod.rs
Outdated
| #[cfg(feature = "video")] | ||
| pub mod pixel_ops; |
There was a problem hiding this comment.
🔴 Feature gate mismatch: pixel_ops gated on video but consumed by compositor-gated modules
Before this PR, the pixel_ops module lived inside video::compositor::pixel_ops and was always available when the compositor feature was enabled. The PR moves it to video::pixel_ops and gates it on #[cfg(feature = "video")] (crates/nodes/src/video/mod.rs:40-41). However, the compositor feature does NOT depend on video — the dependency is the other direction (video = ["vp9", "colorbars", "compositor"] at crates/nodes/Cargo.toml:132). This means enabling just compositor (without video) breaks two modules:
- The compositor shim at
crates/nodes/src/video/compositor/pixel_ops/mod.rs:12doespub use crate::video::pixel_ops::*;— the target module doesn't exist. pixel_convert(crates/nodes/src/video/pixel_convert.rs:39) imports fromcrate::video::pixel_ops— same issue.
CI likely only builds with default features (which include video), so this regression won't be caught automatically. The fix is to gate pixel_ops on a feature that compositor implies — e.g. #[cfg(any(feature = "video", feature = "compositor"))] — or add pixel_ops as a separate internal feature that compositor depends on.
| #[cfg(feature = "video")] | |
| pub mod pixel_ops; | |
| #[cfg(any(feature = "video", feature = "compositor"))] | |
| pub mod pixel_ops; |
Was this helpful? React with 👍 or 👎 to provide feedback.
Debug
…or builds Using just 'video' would break compositor-only builds since compositor doesn't depend on video (the dependency is reversed). Use any(video, compositor) so pixel_ops is available for both. Co-Authored-By: Claudio Costa <cstcld91@gmail.com>
refactor: video branch code de-duplication and simplification
Summary
Addresses high and medium priority findings from a code review of the
videofeature branch. The goal is reducing duplication, loosening coupling, and improving module organization — no behavioral changes intended.1. Extract
codec_forward_loopinto sharedcodec_utilsmodule (~400 lines removed)vp9.rsintocrate::codec_utils.Packet::Audio(AudioFrame)inside the blocking task so it can share the samecodec_forward_loop<T=Packet>signature.2. Move
pixel_opsout of compositor (coupling fix)video/compositor/pixel_ops/→video/pixel_ops/as a sibling module. The compositor andpixel_convertboth import from the new location.BlitRectinblit.rsto replace the dependency oncompositor::config::Rect, sopixel_opshas zero imports from the compositor.#[cfg(any(feature = "video", feature = "compositor"))]so the module is available both when the umbrellavideofeature is enabled and whencompositoris enabled standalone (sincecompositordoes not depend onvideo).3. Split compositor tests (~1050 lines moved)
compositor/mod.rsintocompositor/tests.rsvia#[path = "tests.rs"] mod tests;.4. Consolidate
VideoFrameconstructor validationfn validate_layout(...)to deduplicate identical validation logic betweenfrom_pooled_with_layoutandfrom_arc_with_layout.Skipped items (analyzed, decided not worth the abstraction):
ConversionCachevs pixel_convert's single-slot cache) are structurally different enough that a shared abstraction adds complexity without real benefit.overlay.rsalready delegates to the sharedblit_text_wrapped/measure_text_wrappedhelpers. The only separate path is colorbars' YUV-plane-direct writing, which is inherently different from RGBA blitting.Review & Testing Checklist for Human
AudioFrameinsidespawn_blockingand sendsResult<Packet, String>(wasResult<PooledSamples, String>+ separate metadata). Empty decode results are nowcontinued inside the blocking task instead of being filtered in the forward loop. Verify this doesn't change observable behavior (metadata propagation, empty-frame handling, timing of packet construction).BlitRect↔Rectconversion inkernel.rs: The compositor now converts its configRecttoBlitRectbefore calling blit functions. Verify the field mapping (x,y,width,height) is correct and no call sites were missed.codec_forward_loopgeneric correctness across all 5 callers: VP9 dec/enc pass domain objects with ato_packetclosure; Opus dec/enc and PixelConvert passPacketdirectly (identity-ishto_packet). Verify the type signatures and closure semantics are correct for each.pixel_opsis gated onany(feature = "video", feature = "compositor"). Confirm no build issues when enabling individual sub-features (e.g.--features compositoralone, or--features vp9alone).Suggested test plan:
just lint && just testshould be sufficient — all changes are structural refactoring. If relevant benchmarks exist incrates/engine/benches/, running them before/after would confirm no performance regression from the module moves.Notes