use super::{
GeometryOverflow, InsufficientPlane, InsufficientStride, WidthOverflow, ZeroDimension,
};
use derive_more::{IsVariant, TryUnwrap, Unwrap};
use thiserror::Error;
#[derive(Debug, Clone, Copy)]
pub struct V410Frame<'a, const BE: bool = false> {
packed: &'a [u32],
width: u32,
height: u32,
stride: u32,
}
pub type V410LeFrame<'a> = V410Frame<'a, false>;
pub type V410BeFrame<'a> = V410Frame<'a, true>;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, IsVariant, TryUnwrap, Unwrap, Error)]
#[non_exhaustive]
#[unwrap(ref, ref_mut)]
#[try_unwrap(ref, ref_mut)]
pub enum V410FrameError {
#[error(transparent)]
ZeroDimension(ZeroDimension),
#[error(transparent)]
InsufficientStride(InsufficientStride),
#[error(transparent)]
InsufficientPlane(InsufficientPlane),
#[error(transparent)]
GeometryOverflow(GeometryOverflow),
}
impl<'a, const BE: bool> V410Frame<'a, BE> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn try_new(
packed: &'a [u32],
width: u32,
height: u32,
stride: u32,
) -> Result<Self, V410FrameError> {
if width == 0 || height == 0 {
return Err(V410FrameError::ZeroDimension(ZeroDimension::new(
width, height,
)));
}
if stride < width {
return Err(V410FrameError::InsufficientStride(InsufficientStride::new(
stride, width,
)));
}
let plane_min = match (stride as usize).checked_mul(height as usize) {
Some(n) => n,
None => {
return Err(V410FrameError::GeometryOverflow(GeometryOverflow::new(
stride, height,
)));
}
};
if packed.len() < plane_min {
return Err(V410FrameError::InsufficientPlane(InsufficientPlane::new(
plane_min,
packed.len(),
)));
}
Ok(Self {
packed,
width,
height,
stride,
})
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn new(packed: &'a [u32], width: u32, height: u32, stride: u32) -> Self {
match Self::try_new(packed, width, height, stride) {
Ok(f) => f,
Err(e) => match e {
V410FrameError::ZeroDimension(_) => panic!("invalid V410Frame: zero dimension"),
V410FrameError::InsufficientStride(_) => panic!("invalid V410Frame: stride too small"),
V410FrameError::InsufficientPlane(_) => panic!("invalid V410Frame: plane too short"),
V410FrameError::GeometryOverflow(_) => panic!("invalid V410Frame: geometry overflow"),
},
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn packed(&self) -> &'a [u32] {
self.packed
}
#[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 stride(&self) -> u32 {
self.stride
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn is_be(&self) -> bool {
BE
}
}
#[derive(Debug, Clone, Copy)]
pub struct V30XFrame<'a> {
packed: &'a [u32],
width: u32,
height: u32,
stride: u32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, IsVariant, TryUnwrap, Unwrap, Error)]
#[non_exhaustive]
#[unwrap(ref, ref_mut)]
#[try_unwrap(ref, ref_mut)]
pub enum V30XFrameError {
#[error(transparent)]
ZeroDimension(ZeroDimension),
#[error(transparent)]
InsufficientStride(InsufficientStride),
#[error(transparent)]
InsufficientPlane(InsufficientPlane),
#[error(transparent)]
GeometryOverflow(GeometryOverflow),
}
impl<'a> V30XFrame<'a> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn try_new(
packed: &'a [u32],
width: u32,
height: u32,
stride: u32,
) -> Result<Self, V30XFrameError> {
if width == 0 || height == 0 {
return Err(V30XFrameError::ZeroDimension(ZeroDimension::new(
width, height,
)));
}
if stride < width {
return Err(V30XFrameError::InsufficientStride(InsufficientStride::new(
stride, width,
)));
}
let plane_min = match (stride as usize).checked_mul(height as usize) {
Some(n) => n,
None => {
return Err(V30XFrameError::GeometryOverflow(GeometryOverflow::new(
stride, height,
)));
}
};
if packed.len() < plane_min {
return Err(V30XFrameError::InsufficientPlane(InsufficientPlane::new(
plane_min,
packed.len(),
)));
}
Ok(Self {
packed,
width,
height,
stride,
})
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn new(packed: &'a [u32], width: u32, height: u32, stride: u32) -> Self {
match Self::try_new(packed, width, height, stride) {
Ok(f) => f,
Err(e) => match e {
V30XFrameError::ZeroDimension(_) => panic!("invalid V30XFrame: zero dimension"),
V30XFrameError::InsufficientStride(_) => panic!("invalid V30XFrame: stride too small"),
V30XFrameError::InsufficientPlane(_) => panic!("invalid V30XFrame: plane too short"),
V30XFrameError::GeometryOverflow(_) => panic!("invalid V30XFrame: geometry overflow"),
},
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn packed(&self) -> &'a [u32] {
self.packed
}
#[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 stride(&self) -> u32 {
self.stride
}
}
#[derive(Debug, Clone, Copy)]
pub struct Xv36Frame<'a, const BE: bool = false> {
packed: &'a [u16],
width: u32,
height: u32,
stride: u32,
}
pub type Xv36LeFrame<'a> = Xv36Frame<'a, false>;
pub type Xv36BeFrame<'a> = Xv36Frame<'a, true>;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, IsVariant, TryUnwrap, Unwrap, Error)]
#[non_exhaustive]
#[unwrap(ref, ref_mut)]
#[try_unwrap(ref, ref_mut)]
pub enum Xv36FrameError {
#[error(transparent)]
ZeroDimension(ZeroDimension),
#[error(transparent)]
WidthOverflow(WidthOverflow),
#[error(transparent)]
InsufficientStride(InsufficientStride),
#[error(transparent)]
InsufficientPlane(InsufficientPlane),
#[error(transparent)]
GeometryOverflow(GeometryOverflow),
#[error("Xv36Frame: sample has non-zero low 4 bits (expected MSB-aligned XV36 data)")]
SampleLowBitsSet,
#[error(
"Xv36Frame: sample {:#06x} at element {} has non-zero low 4 bits (expected MSB-aligned XV36 data)", .0.value(), .0.index()
)]
SampleLowBitsSetAt(Xv36SampleLowBitsSetAt),
}
impl<'a, const BE: bool> Xv36Frame<'a, BE> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn try_new(
packed: &'a [u16],
width: u32,
height: u32,
stride: u32,
) -> Result<Self, Xv36FrameError> {
if width == 0 || height == 0 {
return Err(Xv36FrameError::ZeroDimension(ZeroDimension::new(
width, height,
)));
}
let min_stride = match width.checked_mul(4) {
Some(n) => n,
None => return Err(Xv36FrameError::WidthOverflow(WidthOverflow::new(width))),
};
if stride < min_stride {
return Err(Xv36FrameError::InsufficientStride(InsufficientStride::new(
stride, width,
)));
}
let plane_min = match (stride as usize).checked_mul(height as usize) {
Some(n) => n,
None => {
return Err(Xv36FrameError::GeometryOverflow(GeometryOverflow::new(
stride, height,
)));
}
};
if packed.len() < plane_min {
return Err(Xv36FrameError::InsufficientPlane(InsufficientPlane::new(
plane_min,
packed.len(),
)));
}
Ok(Self {
packed,
width,
height,
stride,
})
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn try_new_checked(
packed: &'a [u16],
width: u32,
height: u32,
stride: u32,
) -> Result<Self, Xv36FrameError> {
let frame = Self::try_new(packed, width, height, stride)?;
let row_elems = (width * 4) as usize;
let h = height as usize;
let stride_us = stride as usize;
for row in 0..h {
let start = row * stride_us;
for (col, &sample) in packed[start..start + row_elems].iter().enumerate() {
let logical = if BE {
u16::from_be(sample)
} else {
u16::from_le(sample)
};
if logical & 0x000F != 0 {
return Err(Xv36FrameError::SampleLowBitsSetAt(
Xv36SampleLowBitsSetAt::new(start + col, logical),
));
}
}
}
Ok(frame)
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn new(packed: &'a [u16], width: u32, height: u32, stride: u32) -> Self {
match Self::try_new(packed, width, height, stride) {
Ok(f) => f,
Err(e) => match e {
Xv36FrameError::ZeroDimension(_) => panic!("invalid Xv36Frame: zero dimension"),
Xv36FrameError::WidthOverflow(_) => panic!("invalid Xv36Frame: width overflow"),
Xv36FrameError::InsufficientStride(_) => panic!("invalid Xv36Frame: stride too small"),
Xv36FrameError::InsufficientPlane(_) => panic!("invalid Xv36Frame: plane too short"),
Xv36FrameError::GeometryOverflow(_) => panic!("invalid Xv36Frame: geometry overflow"),
Xv36FrameError::SampleLowBitsSet | Xv36FrameError::SampleLowBitsSetAt { .. } => {
panic!("invalid Xv36Frame: sample low bits set (unreachable from try_new)")
}
},
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn packed(&self) -> &'a [u16] {
self.packed
}
#[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 stride(&self) -> u32 {
self.stride
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn is_be(&self) -> bool {
BE
}
}
#[derive(Debug, Clone, Copy)]
pub struct VuyaFrame<'a> {
packed: &'a [u8],
width: u32,
height: u32,
stride: u32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, IsVariant, TryUnwrap, Unwrap, Error)]
#[non_exhaustive]
#[unwrap(ref, ref_mut)]
#[try_unwrap(ref, ref_mut)]
pub enum VuyaFrameError {
#[error(transparent)]
ZeroDimension(ZeroDimension),
#[error(transparent)]
WidthOverflow(WidthOverflow),
#[error(transparent)]
InsufficientStride(InsufficientStride),
#[error(transparent)]
InsufficientPlane(InsufficientPlane),
#[error(transparent)]
GeometryOverflow(GeometryOverflow),
}
impl<'a> VuyaFrame<'a> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn try_new(
packed: &'a [u8],
width: u32,
height: u32,
stride: u32,
) -> Result<Self, VuyaFrameError> {
if width == 0 || height == 0 {
return Err(VuyaFrameError::ZeroDimension(ZeroDimension::new(
width, height,
)));
}
let min_stride = match width.checked_mul(4) {
Some(n) => n,
None => return Err(VuyaFrameError::WidthOverflow(WidthOverflow::new(width))),
};
if stride < min_stride {
return Err(VuyaFrameError::InsufficientStride(InsufficientStride::new(
stride, width,
)));
}
let plane_min = match (stride as usize).checked_mul(height as usize) {
Some(n) => n,
None => {
return Err(VuyaFrameError::GeometryOverflow(GeometryOverflow::new(
stride, height,
)));
}
};
if packed.len() < plane_min {
return Err(VuyaFrameError::InsufficientPlane(InsufficientPlane::new(
plane_min,
packed.len(),
)));
}
Ok(Self {
packed,
width,
height,
stride,
})
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn new(packed: &'a [u8], width: u32, height: u32, stride: u32) -> Self {
match Self::try_new(packed, width, height, stride) {
Ok(f) => f,
Err(e) => match e {
VuyaFrameError::ZeroDimension(_) => panic!("invalid VuyaFrame: zero dimension"),
VuyaFrameError::WidthOverflow(_) => panic!("invalid VuyaFrame: width overflow"),
VuyaFrameError::InsufficientStride(_) => panic!("invalid VuyaFrame: stride too small"),
VuyaFrameError::InsufficientPlane(_) => panic!("invalid VuyaFrame: plane too short"),
VuyaFrameError::GeometryOverflow(_) => {
panic!("invalid VuyaFrame: geometry overflow")
}
},
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn packed(&self) -> &'a [u8] {
self.packed
}
#[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 stride(&self) -> u32 {
self.stride
}
}
#[derive(Debug, Clone, Copy)]
pub struct VuyxFrame<'a> {
packed: &'a [u8],
width: u32,
height: u32,
stride: u32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, IsVariant, TryUnwrap, Unwrap, Error)]
#[non_exhaustive]
#[unwrap(ref, ref_mut)]
#[try_unwrap(ref, ref_mut)]
pub enum VuyxFrameError {
#[error(transparent)]
ZeroDimension(ZeroDimension),
#[error(transparent)]
WidthOverflow(WidthOverflow),
#[error(transparent)]
InsufficientStride(InsufficientStride),
#[error(transparent)]
InsufficientPlane(InsufficientPlane),
#[error(transparent)]
GeometryOverflow(GeometryOverflow),
}
impl<'a> VuyxFrame<'a> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn try_new(
packed: &'a [u8],
width: u32,
height: u32,
stride: u32,
) -> Result<Self, VuyxFrameError> {
if width == 0 || height == 0 {
return Err(VuyxFrameError::ZeroDimension(ZeroDimension::new(
width, height,
)));
}
let min_stride = match width.checked_mul(4) {
Some(n) => n,
None => return Err(VuyxFrameError::WidthOverflow(WidthOverflow::new(width))),
};
if stride < min_stride {
return Err(VuyxFrameError::InsufficientStride(InsufficientStride::new(
stride, width,
)));
}
let plane_min = match (stride as usize).checked_mul(height as usize) {
Some(n) => n,
None => {
return Err(VuyxFrameError::GeometryOverflow(GeometryOverflow::new(
stride, height,
)));
}
};
if packed.len() < plane_min {
return Err(VuyxFrameError::InsufficientPlane(InsufficientPlane::new(
plane_min,
packed.len(),
)));
}
Ok(Self {
packed,
width,
height,
stride,
})
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn new(packed: &'a [u8], width: u32, height: u32, stride: u32) -> Self {
match Self::try_new(packed, width, height, stride) {
Ok(f) => f,
Err(e) => match e {
VuyxFrameError::ZeroDimension(_) => panic!("invalid VuyxFrame: zero dimension"),
VuyxFrameError::WidthOverflow(_) => panic!("invalid VuyxFrame: width overflow"),
VuyxFrameError::InsufficientStride(_) => panic!("invalid VuyxFrame: stride too small"),
VuyxFrameError::InsufficientPlane(_) => panic!("invalid VuyxFrame: plane too short"),
VuyxFrameError::GeometryOverflow(_) => {
panic!("invalid VuyxFrame: geometry overflow")
}
},
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn packed(&self) -> &'a [u8] {
self.packed
}
#[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 stride(&self) -> u32 {
self.stride
}
}
#[derive(Debug, Clone, Copy)]
pub struct Ayuv64Frame<'a, const BE: bool = false> {
packed: &'a [u16],
width: u32,
height: u32,
stride: u32,
}
pub type Ayuv64LeFrame<'a> = Ayuv64Frame<'a, false>;
pub type Ayuv64BeFrame<'a> = Ayuv64Frame<'a, true>;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, IsVariant, TryUnwrap, Unwrap, Error)]
#[non_exhaustive]
#[unwrap(ref, ref_mut)]
#[try_unwrap(ref, ref_mut)]
pub enum Ayuv64FrameError {
#[error(transparent)]
ZeroDimension(ZeroDimension),
#[error(transparent)]
WidthOverflow(WidthOverflow),
#[error(transparent)]
InsufficientStride(InsufficientStride),
#[error(transparent)]
InsufficientPlane(InsufficientPlane),
#[error(transparent)]
GeometryOverflow(GeometryOverflow),
}
impl<'a, const BE: bool> Ayuv64Frame<'a, BE> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn try_new(
packed: &'a [u16],
width: u32,
height: u32,
stride: u32,
) -> Result<Self, Ayuv64FrameError> {
if width == 0 || height == 0 {
return Err(Ayuv64FrameError::ZeroDimension(ZeroDimension::new(
width, height,
)));
}
let min_stride = match width.checked_mul(4) {
Some(n) => n,
None => return Err(Ayuv64FrameError::WidthOverflow(WidthOverflow::new(width))),
};
if stride < min_stride {
return Err(Ayuv64FrameError::InsufficientStride(
InsufficientStride::new(stride, width),
));
}
let plane_min = match (stride as usize).checked_mul(height as usize) {
Some(n) => n,
None => {
return Err(Ayuv64FrameError::GeometryOverflow(GeometryOverflow::new(
stride, height,
)));
}
};
if packed.len() < plane_min {
return Err(Ayuv64FrameError::InsufficientPlane(InsufficientPlane::new(
plane_min,
packed.len(),
)));
}
Ok(Self {
packed,
width,
height,
stride,
})
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn new(packed: &'a [u16], width: u32, height: u32, stride: u32) -> Self {
match Self::try_new(packed, width, height, stride) {
Ok(f) => f,
Err(e) => match e {
Ayuv64FrameError::ZeroDimension(_) => panic!("invalid Ayuv64Frame: zero dimension"),
Ayuv64FrameError::WidthOverflow(_) => panic!("invalid Ayuv64Frame: width overflow"),
Ayuv64FrameError::InsufficientStride(_) => panic!("invalid Ayuv64Frame: stride too small"),
Ayuv64FrameError::InsufficientPlane(_) => panic!("invalid Ayuv64Frame: plane too short"),
Ayuv64FrameError::GeometryOverflow(_) => {
panic!("invalid Ayuv64Frame: geometry overflow")
}
},
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn packed(&self) -> &'a [u16] {
self.packed
}
#[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 stride(&self) -> u32 {
self.stride
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn is_be(&self) -> bool {
BE
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Xv36SampleLowBitsSetAt {
index: usize,
value: u16,
}
impl Xv36SampleLowBitsSetAt {
#[inline]
pub const fn new(index: usize, value: u16) -> Self {
Self { index, value }
}
#[inline]
pub const fn index(&self) -> usize {
self.index
}
#[inline]
pub const fn value(&self) -> u16 {
self.value
}
}