rave_core/codec_traits.rs
1//! Shared codec traits used across crate boundaries.
2//!
3//! These traits break the circular dependency between `rave-nvcodec`,
4//! `rave-ffmpeg`, and `rave-pipeline` by providing a neutral home.
5
6use crate::error::Result;
7use crate::ffi_types::CUevent;
8use crate::types::FrameEnvelope;
9
10// ─── Bitstream source (demuxer → decoder) ────────────────────────────────
11
12/// Demuxed compressed bitstream packets (host-side, NOT raw pixels).
13///
14/// Implementations: file reader, network receiver, FFmpeg demuxer, etc.
15pub trait BitstreamSource: Send + 'static {
16 fn read_packet(&mut self) -> Result<Option<BitstreamPacket>>;
17}
18
19/// A single demuxed NAL unit or access unit.
20pub struct BitstreamPacket {
21 /// Compressed bitstream data (Annex B or length-prefixed).
22 /// Host memory is acceptable — this is codec-compressed (~10 KB/frame).
23 pub data: Vec<u8>,
24 /// Presentation timestamp in microseconds.
25 ///
26 /// Container-specific time bases are converted at the demux boundary
27 /// (for example in `rave-ffmpeg`) so downstream decode/encode stages
28 /// operate on one stable unit.
29 pub pts: i64,
30 /// Whether this packet encodes an IDR/keyframe.
31 pub is_keyframe: bool,
32}
33
34// ─── Bitstream sink (encoder → muxer) ────────────────────────────────────
35
36/// Receives encoded bitstream output.
37///
38/// Implementations: file writer, muxer, network sender, etc.
39pub trait BitstreamSink: Send + 'static {
40 /// Write one encoded packet.
41 ///
42 /// `pts` and `dts` are in microseconds. Container muxers are responsible
43 /// for rescaling to stream time_base at the output boundary.
44 fn write_packet(&mut self, data: &[u8], pts: i64, dts: i64, is_keyframe: bool) -> Result<()>;
45 fn flush(&mut self) -> Result<()>;
46}
47
48// ─── Pipeline stage traits ───────────────────────────────────────────────
49
50/// A decoded NV12 frame with an optional CUDA event for cross-stream sync.
51///
52/// When produced by a real hardware decoder (NVDEC), `decode_event` carries
53/// the event recorded on `decode_stream` after the D2D copy. The preprocess
54/// stage calls `cuStreamWaitEvent(preprocess_stream, event)` before reading
55/// the texture — this ensures the decode data is ready without CPU-blocking.
56///
57/// Mock decoders set both fields to `None`.
58pub struct DecodedFrame {
59 pub envelope: FrameEnvelope,
60 /// CUDA event recorded after decode completes. `None` for mock decoders.
61 pub decode_event: Option<CUevent>,
62 /// Channel to return used events to the decoder's `EventPool` for reuse.
63 pub event_return: Option<std::sync::mpsc::Sender<CUevent>>,
64}
65
66// SAFETY: CUevent is a CUDA handle (*mut c_void) that is safe to send across
67// threads — CUDA events have no thread affinity.
68unsafe impl Send for DecodedFrame {}
69
70/// Video frame decoder producing GPU-resident NV12 frames.
71pub trait FrameDecoder: Send + 'static {
72 fn decode_next(&mut self) -> Result<Option<DecodedFrame>>;
73}
74
75/// Video frame encoder consuming GPU-resident NV12 frames.
76pub trait FrameEncoder: Send + 'static {
77 fn encode(&mut self, frame: FrameEnvelope) -> Result<()>;
78 fn flush(&mut self) -> Result<()>;
79}
80
81// ─── Model precision ─────────────────────────────────────────────────────
82
83/// Which precision the inference model expects.
84#[derive(Clone, Copy, Debug, PartialEq, Eq)]
85pub enum ModelPrecision {
86 F32,
87 F16,
88}