rff_core/frame.rs
1//! A `Frame` is a chunk of *raw, decoded* data — pixels for video, samples for
2//! audio. It flows decoder → (filters) → encoder. Analogous to `AVFrame`.
3
4use crate::media::{PixelFormat, SampleFormat};
5
6/// A decoded raw video frame.
7#[derive(Debug, Clone)]
8pub struct VideoFrame {
9 pub width: u32,
10 pub height: u32,
11 pub format: PixelFormat,
12 /// Plane buffers (e.g. Y, U, V for planar YUV). Packed formats use one plane.
13 pub planes: Vec<Vec<u8>>,
14 /// Bytes per row for each plane (the "stride"; may exceed `width` for alignment).
15 pub strides: Vec<usize>,
16 /// Presentation timestamp in the source stream's time base. `None` if unset.
17 pub pts: Option<i64>,
18}
19
20/// A decoded raw audio frame (one block of samples across all channels).
21#[derive(Debug, Clone)]
22pub struct AudioFrame {
23 pub sample_rate: u32,
24 pub channels: u16,
25 pub format: SampleFormat,
26 /// Sample buffers. Interleaved formats use one buffer; planar formats use
27 /// one per channel.
28 pub planes: Vec<Vec<u8>>,
29 /// Number of samples *per channel* in this frame.
30 pub samples: usize,
31 /// Presentation timestamp in the source stream's time base. `None` if unset.
32 pub pts: Option<i64>,
33}
34
35/// Either a video or audio frame. Decoders emit these; encoders consume them.
36#[derive(Debug, Clone)]
37pub enum Frame {
38 Video(VideoFrame),
39 Audio(AudioFrame),
40}
41
42impl Frame {
43 pub fn pts(&self) -> Option<i64> {
44 match self {
45 Frame::Video(v) => v.pts,
46 Frame::Audio(a) => a.pts,
47 }
48 }
49}