Skip to main content

VideoFrame

Struct VideoFrame 

Source
pub struct VideoFrame { /* private fields */ }
Expand description

A decoded video frame.

This structure holds the pixel data and metadata for a single video frame. It supports both packed formats (like RGBA) where all data is in a single plane, and planar formats (like YUV420P) where each color component is stored in a separate plane.

§Memory Layout

For packed formats (RGB, RGBA, BGR, BGRA):

  • Single plane containing all pixel data
  • Stride equals width × bytes_per_pixel (plus optional padding)

For planar YUV formats (YUV420P, YUV422P, YUV444P):

  • Plane 0: Y (luma) - full resolution
  • Plane 1: U (Cb) - may be subsampled
  • Plane 2: V (Cr) - may be subsampled

For semi-planar formats (NV12, NV21):

  • Plane 0: Y (luma) - full resolution
  • Plane 1: UV interleaved - half height

§Strides

Each plane has an associated stride (also called line size or pitch), which is the number of bytes from the start of one row to the start of the next. This may be larger than the actual data width due to alignment requirements.

Implementations§

Source§

impl VideoFrame

Source

pub fn new( planes: Vec<PooledBuffer>, strides: Vec<usize>, width: u32, height: u32, format: PixelFormat, timestamp: Timestamp, key_frame: bool, ) -> Result<Self, FrameError>

Creates a new video frame with the specified parameters.

§Arguments
  • planes - Pixel data for each plane
  • strides - Stride (bytes per row) for each plane
  • width - Frame width in pixels
  • height - Frame height in pixels
  • format - Pixel format
  • timestamp - Presentation timestamp
  • key_frame - Whether this is a key frame
§Errors

Returns FrameError::MismatchedPlaneStride if planes.len() != strides.len().

§Examples
use ff_format::{PixelFormat, PooledBuffer, Rational, Timestamp, VideoFrame};

// Create a 640x480 YUV420P frame
let width = 640u32;
let height = 480u32;

// Y plane: full resolution
let y_stride = width as usize;
let y_data = vec![128u8; y_stride * height as usize];

// U/V planes: half resolution in both dimensions
let uv_stride = (width / 2) as usize;
let uv_height = (height / 2) as usize;
let u_data = vec![128u8; uv_stride * uv_height];
let v_data = vec![128u8; uv_stride * uv_height];

let frame = VideoFrame::new(
    vec![
        PooledBuffer::standalone(y_data),
        PooledBuffer::standalone(u_data),
        PooledBuffer::standalone(v_data),
    ],
    vec![y_stride, uv_stride, uv_stride],
    width,
    height,
    PixelFormat::Yuv420p,
    Timestamp::default(),
    true,
).unwrap();

assert_eq!(frame.num_planes(), 3);
Source

pub fn empty( width: u32, height: u32, format: PixelFormat, ) -> Result<Self, FrameError>

Creates an empty video frame with the specified dimensions and format.

The frame will have properly sized planes filled with zeros based on the pixel format.

§Arguments
  • width - Frame width in pixels
  • height - Frame height in pixels
  • format - Pixel format
§Errors

Returns FrameError::UnsupportedPixelFormat if the format is PixelFormat::Other, as the memory layout cannot be determined.

§Examples
use ff_format::{PixelFormat, VideoFrame};

let frame = VideoFrame::empty(1920, 1080, PixelFormat::Rgba).unwrap();
assert_eq!(frame.width(), 1920);
assert_eq!(frame.height(), 1080);
assert_eq!(frame.num_planes(), 1);
Source

pub const fn width(&self) -> u32

Returns the frame width in pixels.

§Examples
use ff_format::{PixelFormat, VideoFrame};

let frame = VideoFrame::empty(1920, 1080, PixelFormat::Rgba).unwrap();
assert_eq!(frame.width(), 1920);
Source

pub const fn height(&self) -> u32

Returns the frame height in pixels.

§Examples
use ff_format::{PixelFormat, VideoFrame};

let frame = VideoFrame::empty(1920, 1080, PixelFormat::Rgba).unwrap();
assert_eq!(frame.height(), 1080);
Source

pub const fn format(&self) -> PixelFormat

Returns the pixel format of this frame.

§Examples
use ff_format::{PixelFormat, VideoFrame};

let frame = VideoFrame::empty(1920, 1080, PixelFormat::Yuv420p).unwrap();
assert_eq!(frame.format(), PixelFormat::Yuv420p);
Source

pub const fn timestamp(&self) -> Timestamp

Returns the presentation timestamp of this frame.

§Examples
use ff_format::{PixelFormat, PooledBuffer, Rational, Timestamp, VideoFrame};

let ts = Timestamp::new(90000, Rational::new(1, 90000));
let frame = VideoFrame::new(
    vec![PooledBuffer::standalone(vec![0u8; 1920 * 1080 * 4])],
    vec![1920 * 4],
    1920,
    1080,
    PixelFormat::Rgba,
    ts,
    true,
).unwrap();
assert_eq!(frame.timestamp(), ts);
Source

pub const fn is_key_frame(&self) -> bool

Returns whether this frame is a key frame (I-frame).

Key frames are complete frames that don’t depend on any other frames for decoding. They are used as reference points for seeking.

§Examples
use ff_format::{PixelFormat, VideoFrame};

let mut frame = VideoFrame::empty(1920, 1080, PixelFormat::Rgba).unwrap();
assert!(!frame.is_key_frame());

frame.set_key_frame(true);
assert!(frame.is_key_frame());
Source

pub fn set_key_frame(&mut self, key_frame: bool)

Sets whether this frame is a key frame.

§Examples
use ff_format::{PixelFormat, VideoFrame};

let mut frame = VideoFrame::empty(640, 480, PixelFormat::Rgba).unwrap();
frame.set_key_frame(true);
assert!(frame.is_key_frame());
Source

pub fn set_timestamp(&mut self, timestamp: Timestamp)

Sets the timestamp of this frame.

§Examples
use ff_format::{PixelFormat, Rational, Timestamp, VideoFrame};

let mut frame = VideoFrame::empty(640, 480, PixelFormat::Rgba).unwrap();
let ts = Timestamp::new(3000, Rational::new(1, 90000));
frame.set_timestamp(ts);
assert_eq!(frame.timestamp(), ts);
Source

pub fn num_planes(&self) -> usize

Returns the number of planes in this frame.

  • Packed formats (RGBA, RGB24, etc.): 1 plane
  • Planar YUV (YUV420P, YUV422P, YUV444P): 3 planes
  • Semi-planar (NV12, NV21): 2 planes
§Examples
use ff_format::{PixelFormat, VideoFrame};

let rgba = VideoFrame::empty(640, 480, PixelFormat::Rgba).unwrap();
assert_eq!(rgba.num_planes(), 1);

let yuv = VideoFrame::empty(640, 480, PixelFormat::Yuv420p).unwrap();
assert_eq!(yuv.num_planes(), 3);

let nv12 = VideoFrame::empty(640, 480, PixelFormat::Nv12).unwrap();
assert_eq!(nv12.num_planes(), 2);
Source

pub fn planes(&self) -> &[PooledBuffer]

Returns a slice of all plane buffers.

§Examples
use ff_format::{PixelFormat, VideoFrame};

let frame = VideoFrame::empty(640, 480, PixelFormat::Yuv420p).unwrap();
let planes = frame.planes();
assert_eq!(planes.len(), 3);
Source

pub fn plane(&self, index: usize) -> Option<&[u8]>

Returns the data for a specific plane, or None if the index is out of bounds.

§Arguments
  • index - The plane index (0 for Y/RGB, 1 for U/UV, 2 for V)
§Examples
use ff_format::{PixelFormat, VideoFrame};

let frame = VideoFrame::empty(640, 480, PixelFormat::Yuv420p).unwrap();

// Y plane exists
assert!(frame.plane(0).is_some());

// U and V planes exist
assert!(frame.plane(1).is_some());
assert!(frame.plane(2).is_some());

// No fourth plane
assert!(frame.plane(3).is_none());
Source

pub fn plane_mut(&mut self, index: usize) -> Option<&mut [u8]>

Returns mutable access to a specific plane’s data.

§Arguments
  • index - The plane index
§Examples
use ff_format::{PixelFormat, VideoFrame};

let mut frame = VideoFrame::empty(640, 480, PixelFormat::Rgba).unwrap();
if let Some(data) = frame.plane_mut(0) {
    // Fill with red (RGBA)
    for chunk in data.chunks_exact_mut(4) {
        chunk[0] = 255; // R
        chunk[1] = 0;   // G
        chunk[2] = 0;   // B
        chunk[3] = 255; // A
    }
}
Source

pub fn strides(&self) -> &[usize]

Returns a slice of all stride values.

Strides indicate the number of bytes between the start of consecutive rows in each plane.

§Examples
use ff_format::{PixelFormat, VideoFrame};

let frame = VideoFrame::empty(1920, 1080, PixelFormat::Rgba).unwrap();
let strides = frame.strides();
assert_eq!(strides[0], 1920 * 4); // RGBA = 4 bytes per pixel
Source

pub fn stride(&self, plane: usize) -> Option<usize>

Returns the stride for a specific plane, or None if the index is out of bounds.

§Arguments
  • plane - The plane index
§Examples
use ff_format::{PixelFormat, VideoFrame};

let frame = VideoFrame::empty(640, 480, PixelFormat::Yuv420p).unwrap();

// Y plane stride = width
assert_eq!(frame.stride(0), Some(640));

// U/V plane stride = width / 2
assert_eq!(frame.stride(1), Some(320));
assert_eq!(frame.stride(2), Some(320));
Source

pub fn data(&self) -> Vec<u8>

Returns the frame data as a contiguous byte vector.

For packed formats with a single plane, this returns a copy of the plane data. For planar formats, this concatenates all planes into a single buffer.

§Note

This method allocates a new vector and copies the data. For zero-copy access, use plane() or planes() instead.

§Examples
use ff_format::{PixelFormat, VideoFrame};

let frame = VideoFrame::empty(4, 4, PixelFormat::Rgba).unwrap();
let data = frame.data();
assert_eq!(data.len(), 4 * 4 * 4); // 4x4 pixels, 4 bytes each
Source

pub fn data_ref(&self) -> Option<&[u8]>

Returns a reference to the first plane’s data as a contiguous slice.

This is only meaningful for packed formats (RGBA, RGB24, etc.) where all data is in a single plane. Returns None if the format is planar or if no planes exist.

§Examples
use ff_format::{PixelFormat, VideoFrame};

// Packed format - returns data
let rgba = VideoFrame::empty(640, 480, PixelFormat::Rgba).unwrap();
assert!(rgba.data_ref().is_some());

// Planar format - returns None
let yuv = VideoFrame::empty(640, 480, PixelFormat::Yuv420p).unwrap();
assert!(yuv.data_ref().is_none());
Source

pub fn data_mut(&mut self) -> Option<&mut [u8]>

Returns a mutable reference to the first plane’s data.

This is only meaningful for packed formats where all data is in a single plane. Returns None if the format is planar.

§Examples
use ff_format::{PixelFormat, VideoFrame};

let mut frame = VideoFrame::empty(4, 4, PixelFormat::Rgba).unwrap();
if let Some(data) = frame.data_mut() {
    data[0] = 255; // Modify first byte
}
Source

pub fn total_size(&self) -> usize

Returns the total size in bytes of all plane data.

§Examples
use ff_format::{PixelFormat, VideoFrame};

let frame = VideoFrame::empty(1920, 1080, PixelFormat::Rgba).unwrap();
assert_eq!(frame.total_size(), 1920 * 1080 * 4);
Source

pub const fn resolution(&self) -> (u32, u32)

Returns the resolution as a (width, height) tuple.

§Examples
use ff_format::{PixelFormat, VideoFrame};

let frame = VideoFrame::empty(1920, 1080, PixelFormat::Rgba).unwrap();
assert_eq!(frame.resolution(), (1920, 1080));
Source

pub fn aspect_ratio(&self) -> f64

Returns the aspect ratio as a floating-point value.

§Examples
use ff_format::{PixelFormat, VideoFrame};

let frame = VideoFrame::empty(1920, 1080, PixelFormat::Rgba).unwrap();
let aspect = frame.aspect_ratio();
assert!((aspect - 16.0 / 9.0).abs() < 0.01);

Trait Implementations§

Source§

impl Clone for VideoFrame

Source§

fn clone(&self) -> VideoFrame

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for VideoFrame

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for VideoFrame

Source§

fn default() -> Self

Returns a default empty 1x1 YUV420P frame.

This constructs a minimal valid frame directly.

Source§

impl Display for VideoFrame

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.