use super::{
GeometryOverflow, InsufficientPlane, InsufficientStride, WidthAlignment, ZeroDimension,
};
use derive_more::{IsVariant, TryUnwrap, Unwrap};
use thiserror::Error;
#[derive(Debug, Clone, Copy)]
pub struct Nv12Frame<'a> {
y: &'a [u8],
uv: &'a [u8],
width: u32,
height: u32,
y_stride: u32,
uv_stride: u32,
}
impl<'a> Nv12Frame<'a> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn try_new(
y: &'a [u8],
uv: &'a [u8],
width: u32,
height: u32,
y_stride: u32,
uv_stride: u32,
) -> Result<Self, Nv12FrameError> {
if width == 0 || height == 0 {
return Err(Nv12FrameError::ZeroDimension(ZeroDimension::new(
width, height,
)));
}
if width & 1 != 0 {
return Err(Nv12FrameError::WidthAlignment(WidthAlignment::odd(
width as usize,
)));
}
if y_stride < width {
return Err(Nv12FrameError::InsufficientYStride(
InsufficientStride::new(y_stride, width),
));
}
let uv_row_bytes = width;
if uv_stride < uv_row_bytes {
return Err(Nv12FrameError::InsufficientUvStride(
InsufficientStride::new(uv_stride, uv_row_bytes),
));
}
let y_min = match (y_stride as usize).checked_mul(height as usize) {
Some(v) => v,
None => {
return Err(Nv12FrameError::GeometryOverflow(GeometryOverflow::new(
y_stride, height,
)));
}
};
if y.len() < y_min {
return Err(Nv12FrameError::InsufficientYPlane(InsufficientPlane::new(
y_min,
y.len(),
)));
}
let chroma_height = height.div_ceil(2);
let uv_min = match (uv_stride as usize).checked_mul(chroma_height as usize) {
Some(v) => v,
None => {
return Err(Nv12FrameError::GeometryOverflow(GeometryOverflow::new(
uv_stride,
chroma_height,
)));
}
};
if uv.len() < uv_min {
return Err(Nv12FrameError::InsufficientUvPlane(InsufficientPlane::new(
uv_min,
uv.len(),
)));
}
Ok(Self {
y,
uv,
width,
height,
y_stride,
uv_stride,
})
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn new(
y: &'a [u8],
uv: &'a [u8],
width: u32,
height: u32,
y_stride: u32,
uv_stride: u32,
) -> Self {
match Self::try_new(y, uv, width, height, y_stride, uv_stride) {
Ok(frame) => frame,
Err(_) => panic!("invalid Nv12Frame dimensions or plane lengths"),
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn y(&self) -> &'a [u8] {
self.y
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn uv(&self) -> &'a [u8] {
self.uv
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn width(&self) -> u32 {
self.width
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn height(&self) -> u32 {
self.height
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn y_stride(&self) -> u32 {
self.y_stride
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn uv_stride(&self) -> u32 {
self.uv_stride
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, IsVariant, TryUnwrap, Unwrap, Error)]
#[non_exhaustive]
#[unwrap(ref, ref_mut)]
#[try_unwrap(ref, ref_mut)]
pub enum Nv12FrameError {
#[error(transparent)]
ZeroDimension(ZeroDimension),
#[error(transparent)]
WidthAlignment(WidthAlignment),
#[error(transparent)]
InsufficientYStride(InsufficientStride),
#[error(transparent)]
InsufficientUvStride(InsufficientStride),
#[error(transparent)]
InsufficientYPlane(InsufficientPlane),
#[error(transparent)]
InsufficientUvPlane(InsufficientPlane),
#[error(transparent)]
GeometryOverflow(GeometryOverflow),
}
#[derive(Debug, Clone, Copy)]
pub struct Nv16Frame<'a> {
y: &'a [u8],
uv: &'a [u8],
width: u32,
height: u32,
y_stride: u32,
uv_stride: u32,
}
impl<'a> Nv16Frame<'a> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn try_new(
y: &'a [u8],
uv: &'a [u8],
width: u32,
height: u32,
y_stride: u32,
uv_stride: u32,
) -> Result<Self, Nv16FrameError> {
if width == 0 || height == 0 {
return Err(Nv16FrameError::ZeroDimension(ZeroDimension::new(
width, height,
)));
}
if width & 1 != 0 {
return Err(Nv16FrameError::WidthAlignment(WidthAlignment::odd(
width as usize,
)));
}
if y_stride < width {
return Err(Nv16FrameError::InsufficientYStride(
InsufficientStride::new(y_stride, width),
));
}
let uv_row_bytes = width;
if uv_stride < uv_row_bytes {
return Err(Nv16FrameError::InsufficientUvStride(
InsufficientStride::new(uv_stride, uv_row_bytes),
));
}
let y_min = match (y_stride as usize).checked_mul(height as usize) {
Some(v) => v,
None => {
return Err(Nv16FrameError::GeometryOverflow(GeometryOverflow::new(
y_stride, height,
)));
}
};
if y.len() < y_min {
return Err(Nv16FrameError::InsufficientYPlane(InsufficientPlane::new(
y_min,
y.len(),
)));
}
let uv_min = match (uv_stride as usize).checked_mul(height as usize) {
Some(v) => v,
None => {
return Err(Nv16FrameError::GeometryOverflow(GeometryOverflow::new(
uv_stride, height,
)));
}
};
if uv.len() < uv_min {
return Err(Nv16FrameError::InsufficientUvPlane(InsufficientPlane::new(
uv_min,
uv.len(),
)));
}
Ok(Self {
y,
uv,
width,
height,
y_stride,
uv_stride,
})
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn new(
y: &'a [u8],
uv: &'a [u8],
width: u32,
height: u32,
y_stride: u32,
uv_stride: u32,
) -> Self {
match Self::try_new(y, uv, width, height, y_stride, uv_stride) {
Ok(frame) => frame,
Err(_) => panic!("invalid Nv16Frame dimensions or plane lengths"),
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn y(&self) -> &'a [u8] {
self.y
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn uv(&self) -> &'a [u8] {
self.uv
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn width(&self) -> u32 {
self.width
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn height(&self) -> u32 {
self.height
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn y_stride(&self) -> u32 {
self.y_stride
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn uv_stride(&self) -> u32 {
self.uv_stride
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, IsVariant, TryUnwrap, Unwrap, Error)]
#[non_exhaustive]
#[unwrap(ref, ref_mut)]
#[try_unwrap(ref, ref_mut)]
pub enum Nv16FrameError {
#[error(transparent)]
ZeroDimension(ZeroDimension),
#[error(transparent)]
WidthAlignment(WidthAlignment),
#[error(transparent)]
InsufficientYStride(InsufficientStride),
#[error(transparent)]
InsufficientUvStride(InsufficientStride),
#[error(transparent)]
InsufficientYPlane(InsufficientPlane),
#[error(transparent)]
InsufficientUvPlane(InsufficientPlane),
#[error(transparent)]
GeometryOverflow(GeometryOverflow),
}
#[derive(Debug, Clone, Copy)]
pub struct Nv24Frame<'a> {
y: &'a [u8],
uv: &'a [u8],
width: u32,
height: u32,
y_stride: u32,
uv_stride: u32,
}
impl<'a> Nv24Frame<'a> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn try_new(
y: &'a [u8],
uv: &'a [u8],
width: u32,
height: u32,
y_stride: u32,
uv_stride: u32,
) -> Result<Self, Nv24FrameError> {
if width == 0 || height == 0 {
return Err(Nv24FrameError::ZeroDimension(ZeroDimension::new(
width, height,
)));
}
if y_stride < width {
return Err(Nv24FrameError::InsufficientYStride(
InsufficientStride::new(y_stride, width),
));
}
let uv_row_bytes = match width.checked_mul(2) {
Some(v) => v,
None => {
return Err(Nv24FrameError::GeometryOverflow(GeometryOverflow::new(
width, 2,
)));
}
};
if uv_stride < uv_row_bytes {
return Err(Nv24FrameError::InsufficientUvStride(
InsufficientStride::new(uv_stride, uv_row_bytes),
));
}
let y_min = match (y_stride as usize).checked_mul(height as usize) {
Some(v) => v,
None => {
return Err(Nv24FrameError::GeometryOverflow(GeometryOverflow::new(
y_stride, height,
)));
}
};
if y.len() < y_min {
return Err(Nv24FrameError::InsufficientYPlane(InsufficientPlane::new(
y_min,
y.len(),
)));
}
let uv_min = match (uv_stride as usize).checked_mul(height as usize) {
Some(v) => v,
None => {
return Err(Nv24FrameError::GeometryOverflow(GeometryOverflow::new(
uv_stride, height,
)));
}
};
if uv.len() < uv_min {
return Err(Nv24FrameError::InsufficientUvPlane(InsufficientPlane::new(
uv_min,
uv.len(),
)));
}
Ok(Self {
y,
uv,
width,
height,
y_stride,
uv_stride,
})
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn new(
y: &'a [u8],
uv: &'a [u8],
width: u32,
height: u32,
y_stride: u32,
uv_stride: u32,
) -> Self {
match Self::try_new(y, uv, width, height, y_stride, uv_stride) {
Ok(frame) => frame,
Err(_) => panic!("invalid Nv24Frame dimensions or plane lengths"),
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn y(&self) -> &'a [u8] {
self.y
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn uv(&self) -> &'a [u8] {
self.uv
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn width(&self) -> u32 {
self.width
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn height(&self) -> u32 {
self.height
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn y_stride(&self) -> u32 {
self.y_stride
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn uv_stride(&self) -> u32 {
self.uv_stride
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, IsVariant, TryUnwrap, Unwrap, Error)]
#[non_exhaustive]
#[unwrap(ref, ref_mut)]
#[try_unwrap(ref, ref_mut)]
pub enum Nv24FrameError {
#[error(transparent)]
ZeroDimension(ZeroDimension),
#[error(transparent)]
InsufficientYStride(InsufficientStride),
#[error(transparent)]
InsufficientUvStride(InsufficientStride),
#[error(transparent)]
InsufficientYPlane(InsufficientPlane),
#[error(transparent)]
InsufficientUvPlane(InsufficientPlane),
#[error(transparent)]
GeometryOverflow(GeometryOverflow),
}
#[derive(Debug, Clone, Copy)]
pub struct Nv42Frame<'a> {
y: &'a [u8],
vu: &'a [u8],
width: u32,
height: u32,
y_stride: u32,
vu_stride: u32,
}
impl<'a> Nv42Frame<'a> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn try_new(
y: &'a [u8],
vu: &'a [u8],
width: u32,
height: u32,
y_stride: u32,
vu_stride: u32,
) -> Result<Self, Nv42FrameError> {
if width == 0 || height == 0 {
return Err(Nv42FrameError::ZeroDimension(ZeroDimension::new(
width, height,
)));
}
if y_stride < width {
return Err(Nv42FrameError::InsufficientYStride(
InsufficientStride::new(y_stride, width),
));
}
let vu_row_bytes = match width.checked_mul(2) {
Some(v) => v,
None => {
return Err(Nv42FrameError::GeometryOverflow(GeometryOverflow::new(
width, 2,
)));
}
};
if vu_stride < vu_row_bytes {
return Err(Nv42FrameError::InsufficientVuStride(
InsufficientStride::new(vu_stride, vu_row_bytes),
));
}
let y_min = match (y_stride as usize).checked_mul(height as usize) {
Some(v) => v,
None => {
return Err(Nv42FrameError::GeometryOverflow(GeometryOverflow::new(
y_stride, height,
)));
}
};
if y.len() < y_min {
return Err(Nv42FrameError::InsufficientYPlane(InsufficientPlane::new(
y_min,
y.len(),
)));
}
let vu_min = match (vu_stride as usize).checked_mul(height as usize) {
Some(v) => v,
None => {
return Err(Nv42FrameError::GeometryOverflow(GeometryOverflow::new(
vu_stride, height,
)));
}
};
if vu.len() < vu_min {
return Err(Nv42FrameError::InsufficientVuPlane(InsufficientPlane::new(
vu_min,
vu.len(),
)));
}
Ok(Self {
y,
vu,
width,
height,
y_stride,
vu_stride,
})
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn new(
y: &'a [u8],
vu: &'a [u8],
width: u32,
height: u32,
y_stride: u32,
vu_stride: u32,
) -> Self {
match Self::try_new(y, vu, width, height, y_stride, vu_stride) {
Ok(frame) => frame,
Err(_) => panic!("invalid Nv42Frame dimensions or plane lengths"),
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn y(&self) -> &'a [u8] {
self.y
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn vu(&self) -> &'a [u8] {
self.vu
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn width(&self) -> u32 {
self.width
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn height(&self) -> u32 {
self.height
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn y_stride(&self) -> u32 {
self.y_stride
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn vu_stride(&self) -> u32 {
self.vu_stride
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, IsVariant, TryUnwrap, Unwrap, Error)]
#[non_exhaustive]
#[unwrap(ref, ref_mut)]
#[try_unwrap(ref, ref_mut)]
pub enum Nv42FrameError {
#[error(transparent)]
ZeroDimension(ZeroDimension),
#[error(transparent)]
InsufficientYStride(InsufficientStride),
#[error(transparent)]
InsufficientVuStride(InsufficientStride),
#[error(transparent)]
InsufficientYPlane(InsufficientPlane),
#[error(transparent)]
InsufficientVuPlane(InsufficientPlane),
#[error(transparent)]
GeometryOverflow(GeometryOverflow),
}
#[derive(Debug, Clone, Copy)]
pub struct Nv21Frame<'a> {
y: &'a [u8],
vu: &'a [u8],
width: u32,
height: u32,
y_stride: u32,
vu_stride: u32,
}
impl<'a> Nv21Frame<'a> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn try_new(
y: &'a [u8],
vu: &'a [u8],
width: u32,
height: u32,
y_stride: u32,
vu_stride: u32,
) -> Result<Self, Nv21FrameError> {
if width == 0 || height == 0 {
return Err(Nv21FrameError::ZeroDimension(ZeroDimension::new(
width, height,
)));
}
if width & 1 != 0 {
return Err(Nv21FrameError::WidthAlignment(WidthAlignment::odd(
width as usize,
)));
}
if y_stride < width {
return Err(Nv21FrameError::InsufficientYStride(
InsufficientStride::new(y_stride, width),
));
}
let vu_row_bytes = width;
if vu_stride < vu_row_bytes {
return Err(Nv21FrameError::InsufficientVuStride(
InsufficientStride::new(vu_stride, vu_row_bytes),
));
}
let y_min = match (y_stride as usize).checked_mul(height as usize) {
Some(v) => v,
None => {
return Err(Nv21FrameError::GeometryOverflow(GeometryOverflow::new(
y_stride, height,
)));
}
};
if y.len() < y_min {
return Err(Nv21FrameError::InsufficientYPlane(InsufficientPlane::new(
y_min,
y.len(),
)));
}
let chroma_height = height.div_ceil(2);
let vu_min = match (vu_stride as usize).checked_mul(chroma_height as usize) {
Some(v) => v,
None => {
return Err(Nv21FrameError::GeometryOverflow(GeometryOverflow::new(
vu_stride,
chroma_height,
)));
}
};
if vu.len() < vu_min {
return Err(Nv21FrameError::InsufficientVuPlane(InsufficientPlane::new(
vu_min,
vu.len(),
)));
}
Ok(Self {
y,
vu,
width,
height,
y_stride,
vu_stride,
})
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn new(
y: &'a [u8],
vu: &'a [u8],
width: u32,
height: u32,
y_stride: u32,
vu_stride: u32,
) -> Self {
match Self::try_new(y, vu, width, height, y_stride, vu_stride) {
Ok(frame) => frame,
Err(_) => panic!("invalid Nv21Frame dimensions or plane lengths"),
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn y(&self) -> &'a [u8] {
self.y
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn vu(&self) -> &'a [u8] {
self.vu
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn width(&self) -> u32 {
self.width
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn height(&self) -> u32 {
self.height
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn y_stride(&self) -> u32 {
self.y_stride
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn vu_stride(&self) -> u32 {
self.vu_stride
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, IsVariant, TryUnwrap, Unwrap, Error)]
#[non_exhaustive]
#[unwrap(ref, ref_mut)]
#[try_unwrap(ref, ref_mut)]
pub enum Nv21FrameError {
#[error(transparent)]
ZeroDimension(ZeroDimension),
#[error(transparent)]
WidthAlignment(WidthAlignment),
#[error(transparent)]
InsufficientYStride(InsufficientStride),
#[error(transparent)]
InsufficientVuStride(InsufficientStride),
#[error(transparent)]
InsufficientYPlane(InsufficientPlane),
#[error(transparent)]
InsufficientVuPlane(InsufficientPlane),
#[error(transparent)]
GeometryOverflow(GeometryOverflow),
}