use bytes::Bytes;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PixelFormat {
Yuv420p,
Yuv420p10le,
Yuv420p12le,
Yuv422p,
Yuv422p10le,
Yuv444p,
Yuv444p10le,
Yuva444p10le,
Nv12,
Nv21,
Rgb24,
Rgba32,
}
impl PixelFormat {
pub fn bytes_per_frame(&self, width: u32, height: u32) -> usize {
let pixels = (width as usize) * (height as usize);
match self {
Self::Yuv420p | Self::Nv12 | Self::Nv21 => pixels * 3 / 2,
Self::Yuv420p10le | Self::Yuv420p12le => pixels * 3,
Self::Yuv422p => pixels * 2,
Self::Yuv422p10le => pixels * 4,
Self::Yuv444p => pixels * 3,
Self::Yuv444p10le => pixels * 6,
Self::Yuva444p10le => pixels * 8,
Self::Rgb24 => pixels * 3,
Self::Rgba32 => pixels * 4,
}
}
pub fn as_ffmpeg_str(&self) -> &'static str {
match self {
Self::Yuv420p => "yuv420p",
Self::Yuv420p10le => "yuv420p10le",
Self::Yuv420p12le => "yuv420p12le",
Self::Yuv422p => "yuv422p",
Self::Yuv422p10le => "yuv422p10le",
Self::Yuv444p => "yuv444p",
Self::Yuv444p10le => "yuv444p10le",
Self::Yuva444p10le => "yuva444p10le",
Self::Nv12 => "nv12",
Self::Nv21 => "nv21",
Self::Rgb24 => "rgb24",
Self::Rgba32 => "rgba",
}
}
pub fn from_chroma_and_depth(chroma_idc: u8, bit_depth: u8) -> Self {
match (chroma_idc, bit_depth) {
(1, 8) => Self::Yuv420p,
(1, 10) => Self::Yuv420p10le,
(1, 12) => Self::Yuv420p12le,
(2, 8) => Self::Yuv422p,
(2, 10) => Self::Yuv422p10le,
(3, 8) => Self::Yuv444p,
(3, 10) => Self::Yuv444p10le,
_ => Self::Yuv420p, }
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ColorSpace {
Bt601,
Bt709,
Bt2020,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum TransferFn {
#[default]
Bt709,
Bt470Bg,
Linear,
St2084,
AribStdB67,
Unspecified,
}
impl TransferFn {
pub fn from_h273(value: u8) -> Self {
match value {
1 | 6 | 14 | 15 => Self::Bt709, 4 => Self::Bt470Bg,
8 => Self::Linear,
16 => Self::St2084,
18 => Self::AribStdB67,
_ => Self::Unspecified,
}
}
}
#[derive(Debug, Clone)]
pub struct VideoFrame {
pub data: Bytes,
pub width: u32,
pub height: u32,
pub format: PixelFormat,
pub color_space: ColorSpace,
pub pts: u64,
}
impl VideoFrame {
pub fn new(
data: Bytes,
width: u32,
height: u32,
format: PixelFormat,
color_space: ColorSpace,
pts: u64,
) -> Self {
Self {
data,
width,
height,
format,
color_space,
pts,
}
}
}
#[derive(Debug, Clone)]
pub struct StreamInfo {
pub codec: String,
pub width: u32,
pub height: u32,
pub frame_rate: f64,
pub duration: f64,
pub pixel_format: PixelFormat,
pub color_space: ColorSpace,
pub total_frames: u64,
pub bitrate: u64,
pub color_metadata: ColorMetadata,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ColorMetadata {
pub transfer: TransferFn,
pub matrix_coefficients: u8,
pub colour_primaries: u8,
pub full_range: bool,
pub mastering_display: Option<MasteringDisplay>,
pub content_light_level: Option<ContentLightLevel>,
}
impl Default for ColorMetadata {
fn default() -> Self {
Self {
transfer: TransferFn::Bt709,
matrix_coefficients: 1,
colour_primaries: 1,
full_range: false,
mastering_display: None,
content_light_level: None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MasteringDisplay {
pub primaries_r_x: u16,
pub primaries_r_y: u16,
pub primaries_g_x: u16,
pub primaries_g_y: u16,
pub primaries_b_x: u16,
pub primaries_b_y: u16,
pub white_point_x: u16,
pub white_point_y: u16,
pub max_luminance: u32,
pub min_luminance: u32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ContentLightLevel {
pub max_cll: u16,
pub max_fall: u16,
}