use derive_more::{Display, IsVariant};
#[cfg(any(feature = "std", feature = "alloc"))]
use smol_str::SmolStr;
pub const DOMAIN_EXT_BASE: u32 = 0x8000_0000;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Display, IsVariant)]
#[display("{}", self.as_str())]
#[non_exhaustive]
#[cfg_attr(
feature = "quickcheck",
derive(::quickcheck_richderive::Arbitrary),
quickcheck(arbitrary = "crate::quickcheck_helpers::coded::matrix")
)]
pub enum Matrix {
Rgb,
Bt601,
Bt709,
Unspecified,
Fcc,
Bt470Bg,
Smpte170M,
Smpte240m,
YCgCo,
Bt2020Ncl,
Bt2020Cl,
Smpte2085,
ChromaDerivedNcl,
ChromaDerivedCl,
Ictcp,
IptC2,
YCgCoRe,
YCgCoRo,
#[cfg(any(feature = "std", feature = "alloc"))]
Other(SmolStr),
}
impl Default for Matrix {
#[inline]
fn default() -> Self {
Self::Unspecified
}
}
impl Matrix {
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn as_str(&self) -> &str {
match self {
Self::Rgb => "rgb",
Self::Bt601 => "bt601",
Self::Bt709 => "bt709",
Self::Unspecified => "unspecified",
Self::Fcc => "fcc",
Self::Bt470Bg => "bt470bg",
Self::Smpte170M => "smpte170m",
Self::Smpte240m => "smpte240m",
Self::YCgCo => "ycgco",
Self::Bt2020Ncl => "bt2020nc",
Self::Bt2020Cl => "bt2020c",
Self::Smpte2085 => "smpte2085",
Self::ChromaDerivedNcl => "chroma-derived-nc",
Self::ChromaDerivedCl => "chroma-derived-c",
Self::Ictcp => "ictcp",
Self::IptC2 => "ipt-c2",
Self::YCgCoRe => "ycgco-re",
Self::YCgCoRo => "ycgco-ro",
#[cfg(any(feature = "std", feature = "alloc"))]
Self::Other(s) => s.as_str(),
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn to_u32(&self) -> Option<u32> {
Some(match self {
Self::Rgb => 0,
Self::Bt601 => DOMAIN_EXT_BASE,
Self::Bt709 => 1,
Self::Unspecified => 2,
Self::Fcc => 4,
Self::Bt470Bg => 5,
Self::Smpte170M => 6,
Self::Smpte240m => 7,
Self::YCgCo => 8,
Self::Bt2020Ncl => 9,
Self::Bt2020Cl => 10,
Self::Smpte2085 => 11,
Self::ChromaDerivedNcl => 12,
Self::ChromaDerivedCl => 13,
Self::Ictcp => 14,
Self::IptC2 => 15,
Self::YCgCoRe => 16,
Self::YCgCoRo => 17,
#[cfg(any(feature = "std", feature = "alloc"))]
Self::Other(_) => return None,
})
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn from_u32(v: u32) -> Option<Self> {
Some(match v {
0 => Self::Rgb,
1 => Self::Bt709,
2 => Self::Unspecified,
4 => Self::Fcc,
5 => Self::Bt470Bg,
6 => Self::Smpte170M,
7 => Self::Smpte240m,
8 => Self::YCgCo,
9 => Self::Bt2020Ncl,
10 => Self::Bt2020Cl,
11 => Self::Smpte2085,
12 => Self::ChromaDerivedNcl,
13 => Self::ChromaDerivedCl,
14 => Self::Ictcp,
15 => Self::IptC2,
16 => Self::YCgCoRe,
17 => Self::YCgCoRo,
DOMAIN_EXT_BASE => Self::Bt601,
_ => return None,
})
}
#[cfg(any(feature = "std", feature = "alloc"))]
pub fn other(slug: impl AsRef<str>) -> Self {
Self::Other(crate::parse::fold_owned(slug.as_ref()))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, thiserror::Error)]
#[error("not a colour-matrix name")]
#[non_exhaustive]
pub struct ParseMatrixError;
impl core::str::FromStr for Matrix {
type Err = ParseMatrixError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut buf = [0u8; crate::parse::FOLD_CAP];
let folded = crate::parse::fold(s, &mut buf).unwrap_or(s.as_bytes());
Ok(match folded {
b"rgb" => Self::Rgb,
b"bt601" => Self::Bt601,
b"bt709" => Self::Bt709,
b"unspecified" => Self::Unspecified,
b"fcc" => Self::Fcc,
b"bt470bg" => Self::Bt470Bg,
b"smpte170m" => Self::Smpte170M,
b"smpte240m" => Self::Smpte240m,
b"ycgco" => Self::YCgCo,
b"bt2020nc" => Self::Bt2020Ncl,
b"bt2020c" => Self::Bt2020Cl,
b"smpte2085" => Self::Smpte2085,
b"chroma-derived-nc" => Self::ChromaDerivedNcl,
b"chroma-derived-c" => Self::ChromaDerivedCl,
b"ictcp" => Self::Ictcp,
b"ipt-c2" => Self::IptC2,
b"ycgco-re" => Self::YCgCoRe,
b"ycgco-ro" => Self::YCgCoRo,
b"gbr" => Self::Rgb,
b"unknown" => Self::Unspecified,
#[cfg(any(feature = "std", feature = "alloc"))]
_ => Self::other(s),
#[cfg(not(any(feature = "std", feature = "alloc")))]
_ => return Err(ParseMatrixError),
})
}
}
#[cfg(test)]
const MATRIX_FFMPEG_SYNONYMS: &[(&str, &str)] = &[("gbr", "rgb"), ("unknown", "unspecified")];
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum KernelMatrix {
Bt601,
Bt709,
Unspecified,
Fcc,
Bt470Bg,
Smpte170M,
Smpte240m,
YCgCo,
Bt2020Ncl,
ChromaDerivedNcl,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, thiserror::Error)]
#[error("this colour matrix has no conversion-kernel coefficients")]
#[non_exhaustive]
pub struct UnsupportedKernelMatrixError;
impl TryFrom<&Matrix> for KernelMatrix {
type Error = UnsupportedKernelMatrixError;
fn try_from(m: &Matrix) -> Result<Self, Self::Error> {
Ok(match m {
Matrix::Bt601 => Self::Bt601,
Matrix::Bt709 => Self::Bt709,
Matrix::Unspecified => Self::Unspecified,
Matrix::Fcc => Self::Fcc,
Matrix::Bt470Bg => Self::Bt470Bg,
Matrix::Smpte170M => Self::Smpte170M,
Matrix::Smpte240m => Self::Smpte240m,
Matrix::YCgCo => Self::YCgCo,
Matrix::Bt2020Ncl => Self::Bt2020Ncl,
Matrix::ChromaDerivedNcl => Self::ChromaDerivedNcl,
Matrix::Rgb
| Matrix::Bt2020Cl
| Matrix::Smpte2085
| Matrix::ChromaDerivedCl
| Matrix::Ictcp
| Matrix::IptC2
| Matrix::YCgCoRe
| Matrix::YCgCoRo => return Err(UnsupportedKernelMatrixError),
#[cfg(any(feature = "std", feature = "alloc"))]
Matrix::Other(_) => return Err(UnsupportedKernelMatrixError),
})
}
}
impl From<KernelMatrix> for Matrix {
#[cfg_attr(not(tarpaulin), inline(always))]
fn from(k: KernelMatrix) -> Self {
match k {
KernelMatrix::Bt601 => Self::Bt601,
KernelMatrix::Bt709 => Self::Bt709,
KernelMatrix::Unspecified => Self::Unspecified,
KernelMatrix::Fcc => Self::Fcc,
KernelMatrix::Bt470Bg => Self::Bt470Bg,
KernelMatrix::Smpte170M => Self::Smpte170M,
KernelMatrix::Smpte240m => Self::Smpte240m,
KernelMatrix::YCgCo => Self::YCgCo,
KernelMatrix::Bt2020Ncl => Self::Bt2020Ncl,
KernelMatrix::ChromaDerivedNcl => Self::ChromaDerivedNcl,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Display, IsVariant)]
#[display("{}", self.as_str())]
#[non_exhaustive]
#[cfg_attr(
feature = "quickcheck",
derive(::quickcheck_richderive::Arbitrary),
quickcheck(arbitrary = "crate::quickcheck_helpers::coded::primaries")
)]
pub enum Primaries {
Bt709,
Unspecified,
Bt470M,
Bt470Bg,
Smpte170M,
Smpte240M,
Film,
Bt2020,
SmpteSt428,
SmpteRp431,
SmpteEg432,
Ebu3213E,
#[cfg(any(feature = "std", feature = "alloc"))]
Other(SmolStr),
}
impl Default for Primaries {
#[inline]
fn default() -> Self {
Self::Unspecified
}
}
impl Primaries {
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn as_str(&self) -> &str {
match self {
Self::Bt709 => "bt709",
Self::Unspecified => "unspecified",
Self::Bt470M => "bt470m",
Self::Bt470Bg => "bt470bg",
Self::Smpte170M => "smpte170m",
Self::Smpte240M => "smpte240m",
Self::Film => "film",
Self::Bt2020 => "bt2020",
Self::SmpteSt428 => "smpte428",
Self::SmpteRp431 => "smpte431",
Self::SmpteEg432 => "smpte432",
Self::Ebu3213E => "ebu3213",
#[cfg(any(feature = "std", feature = "alloc"))]
Self::Other(s) => s.as_str(),
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn to_u32(&self) -> Option<u32> {
Some(match self {
Self::Bt709 => 1,
Self::Unspecified => 2,
Self::Bt470M => 4,
Self::Bt470Bg => 5,
Self::Smpte170M => 6,
Self::Smpte240M => 7,
Self::Film => 8,
Self::Bt2020 => 9,
Self::SmpteSt428 => 10,
Self::SmpteRp431 => 11,
Self::SmpteEg432 => 12,
Self::Ebu3213E => 22,
#[cfg(any(feature = "std", feature = "alloc"))]
Self::Other(_) => return None,
})
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn from_u32(v: u32) -> Option<Self> {
Some(match v {
1 => Self::Bt709,
2 => Self::Unspecified,
4 => Self::Bt470M,
5 => Self::Bt470Bg,
6 => Self::Smpte170M,
7 => Self::Smpte240M,
8 => Self::Film,
9 => Self::Bt2020,
10 => Self::SmpteSt428,
11 => Self::SmpteRp431,
12 => Self::SmpteEg432,
22 => Self::Ebu3213E,
_ => return None,
})
}
const WHITE_D65: ChromaCoord = ChromaCoord::new(15635, 16450);
const WHITE_C: ChromaCoord = ChromaCoord::new(15500, 15800);
const WHITE_DCI: ChromaCoord = ChromaCoord::new(15700, 17550);
const WHITE_E: ChromaCoord = ChromaCoord::new(16667, 16667);
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn chromaticities(&self) -> Option<[ChromaCoord; 3]> {
match self {
#[cfg(any(feature = "std", feature = "alloc"))]
Self::Other(_) => None,
Self::Unspecified => None,
Self::Bt709 => Some([
ChromaCoord::new(32000, 16500),
ChromaCoord::new(15000, 30000),
ChromaCoord::new(7500, 3000),
]),
Self::Bt470M => Some([
ChromaCoord::new(33500, 16500),
ChromaCoord::new(10500, 35500),
ChromaCoord::new(7000, 4000),
]),
Self::Bt470Bg => Some([
ChromaCoord::new(32000, 16500),
ChromaCoord::new(14500, 30000),
ChromaCoord::new(7500, 3000),
]),
Self::Smpte170M | Self::Smpte240M => Some([
ChromaCoord::new(31500, 17000),
ChromaCoord::new(15500, 29750),
ChromaCoord::new(7750, 3500),
]),
Self::Film => Some([
ChromaCoord::new(34050, 15950),
ChromaCoord::new(12150, 34600),
ChromaCoord::new(7250, 2450),
]),
Self::Bt2020 => Some([
ChromaCoord::new(35400, 14600),
ChromaCoord::new(8500, 39850),
ChromaCoord::new(6550, 2300),
]),
Self::SmpteSt428 => Some([
ChromaCoord::new(36750, 13250),
ChromaCoord::new(13700, 35900),
ChromaCoord::new(8350, 450),
]),
Self::SmpteRp431 | Self::SmpteEg432 => Some([
ChromaCoord::new(34000, 16000),
ChromaCoord::new(13250, 34500),
ChromaCoord::new(7500, 3000),
]),
Self::Ebu3213E => Some([
ChromaCoord::new(31500, 17000),
ChromaCoord::new(14750, 30250),
ChromaCoord::new(7750, 3850),
]),
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn white_point(&self) -> Option<ChromaCoord> {
match self {
#[cfg(any(feature = "std", feature = "alloc"))]
Self::Other(_) => None,
Self::Unspecified => None,
Self::Bt709
| Self::Bt470Bg
| Self::Smpte170M
| Self::Smpte240M
| Self::Bt2020
| Self::SmpteEg432
| Self::Ebu3213E => Some(Self::WHITE_D65),
Self::Bt470M | Self::Film => Some(Self::WHITE_C),
Self::SmpteRp431 => Some(Self::WHITE_DCI),
Self::SmpteSt428 => Some(Self::WHITE_E),
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn is_cie_xyz(&self) -> bool {
matches!(self, Self::SmpteSt428)
}
#[cfg(any(feature = "std", feature = "alloc"))]
pub fn other(slug: impl AsRef<str>) -> Self {
Self::Other(crate::parse::fold_owned(slug.as_ref()))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, thiserror::Error)]
#[error("not a colour-primaries name")]
#[non_exhaustive]
pub struct ParsePrimariesError;
impl core::str::FromStr for Primaries {
type Err = ParsePrimariesError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut buf = [0u8; crate::parse::FOLD_CAP];
let folded = crate::parse::fold(s, &mut buf).unwrap_or(s.as_bytes());
Ok(match folded {
b"bt709" => Self::Bt709,
b"unspecified" => Self::Unspecified,
b"bt470m" => Self::Bt470M,
b"bt470bg" => Self::Bt470Bg,
b"smpte170m" => Self::Smpte170M,
b"smpte240m" => Self::Smpte240M,
b"film" => Self::Film,
b"bt2020" => Self::Bt2020,
b"smpte428" => Self::SmpteSt428,
b"smpte431" => Self::SmpteRp431,
b"smpte432" => Self::SmpteEg432,
b"ebu3213" => Self::Ebu3213E,
b"unknown" => Self::Unspecified,
#[cfg(any(feature = "std", feature = "alloc"))]
_ => Self::other(s),
#[cfg(not(any(feature = "std", feature = "alloc")))]
_ => return Err(ParsePrimariesError),
})
}
}
#[cfg(test)]
const PRIMARIES_FFMPEG_SYNONYMS: &[(&str, &str)] = &[("unknown", "unspecified")];
#[derive(Debug, Clone, PartialEq, Eq, Hash, Display, IsVariant)]
#[display("{}", self.as_str())]
#[non_exhaustive]
#[cfg_attr(
feature = "quickcheck",
derive(::quickcheck_richderive::Arbitrary),
quickcheck(arbitrary = "crate::quickcheck_helpers::coded::transfer")
)]
pub enum Transfer {
Bt709,
Unspecified,
Gamma22,
Gamma28,
Smpte170M,
Smpte240M,
Linear,
Log100,
Log316,
Iec6196624,
Bt1361Ecg,
Iec6196621,
Bt2020_10Bit,
Bt2020_12Bit,
SmpteSt2084Pq,
SmpteSt428,
AribStdB67Hlg,
#[cfg(any(feature = "std", feature = "alloc"))]
Other(SmolStr),
}
impl Default for Transfer {
#[inline]
fn default() -> Self {
Self::Unspecified
}
}
impl Transfer {
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn as_str(&self) -> &str {
match self {
Self::Bt709 => "bt709",
Self::Unspecified => "unspecified",
Self::Gamma22 => "gamma22",
Self::Gamma28 => "gamma28",
Self::Smpte170M => "smpte170m",
Self::Smpte240M => "smpte240m",
Self::Linear => "linear",
Self::Log100 => "log100",
Self::Log316 => "log316",
Self::Iec6196624 => "iec61966-2-4",
Self::Bt1361Ecg => "bt1361e",
Self::Iec6196621 => "iec61966-2-1",
Self::Bt2020_10Bit => "bt2020-10",
Self::Bt2020_12Bit => "bt2020-12",
Self::SmpteSt2084Pq => "smpte2084",
Self::SmpteSt428 => "smpte428",
Self::AribStdB67Hlg => "arib-std-b67",
#[cfg(any(feature = "std", feature = "alloc"))]
Self::Other(s) => s.as_str(),
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn to_u32(&self) -> Option<u32> {
Some(match self {
Self::Bt709 => 1,
Self::Unspecified => 2,
Self::Gamma22 => 4,
Self::Gamma28 => 5,
Self::Smpte170M => 6,
Self::Smpte240M => 7,
Self::Linear => 8,
Self::Log100 => 9,
Self::Log316 => 10,
Self::Iec6196624 => 11,
Self::Bt1361Ecg => 12,
Self::Iec6196621 => 13,
Self::Bt2020_10Bit => 14,
Self::Bt2020_12Bit => 15,
Self::SmpteSt2084Pq => 16,
Self::SmpteSt428 => 17,
Self::AribStdB67Hlg => 18,
#[cfg(any(feature = "std", feature = "alloc"))]
Self::Other(_) => return None,
})
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn from_u32(v: u32) -> Option<Self> {
Some(match v {
1 => Self::Bt709,
2 => Self::Unspecified,
4 => Self::Gamma22,
5 => Self::Gamma28,
6 => Self::Smpte170M,
7 => Self::Smpte240M,
8 => Self::Linear,
9 => Self::Log100,
10 => Self::Log316,
11 => Self::Iec6196624,
12 => Self::Bt1361Ecg,
13 => Self::Iec6196621,
14 => Self::Bt2020_10Bit,
15 => Self::Bt2020_12Bit,
16 => Self::SmpteSt2084Pq,
17 => Self::SmpteSt428,
18 => Self::AribStdB67Hlg,
_ => return None,
})
}
#[cfg(any(feature = "std", feature = "alloc"))]
pub fn other(slug: impl AsRef<str>) -> Self {
Self::Other(crate::parse::fold_owned(slug.as_ref()))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, thiserror::Error)]
#[error("not a transfer-characteristics name")]
#[non_exhaustive]
pub struct ParseTransferError;
impl core::str::FromStr for Transfer {
type Err = ParseTransferError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut buf = [0u8; crate::parse::FOLD_CAP];
let folded = crate::parse::fold(s, &mut buf).unwrap_or(s.as_bytes());
Ok(match folded {
b"bt709" => Self::Bt709,
b"unspecified" => Self::Unspecified,
b"gamma22" => Self::Gamma22,
b"gamma28" => Self::Gamma28,
b"smpte170m" => Self::Smpte170M,
b"smpte240m" => Self::Smpte240M,
b"linear" => Self::Linear,
b"log100" => Self::Log100,
b"log316" => Self::Log316,
b"iec61966-2-4" => Self::Iec6196624,
b"bt1361e" => Self::Bt1361Ecg,
b"iec61966-2-1" => Self::Iec6196621,
b"bt2020-10" => Self::Bt2020_10Bit,
b"bt2020-12" => Self::Bt2020_12Bit,
b"smpte2084" => Self::SmpteSt2084Pq,
b"smpte428" => Self::SmpteSt428,
b"arib-std-b67" => Self::AribStdB67Hlg,
b"unknown" => Self::Unspecified,
b"bt470m" => Self::Gamma22,
b"bt470bg" => Self::Gamma28,
#[cfg(any(feature = "std", feature = "alloc"))]
_ => Self::other(s),
#[cfg(not(any(feature = "std", feature = "alloc")))]
_ => return Err(ParseTransferError),
})
}
}
#[cfg(test)]
const TRANSFER_FFMPEG_SYNONYMS: &[(&str, &str)] = &[
("bt470bg", "gamma28"),
("bt470m", "gamma22"),
("unknown", "unspecified"),
];
#[derive(Debug, Clone, PartialEq, Eq, Hash, Display, IsVariant)]
#[display("{}", self.as_str())]
#[non_exhaustive]
#[cfg_attr(
feature = "quickcheck",
derive(::quickcheck_richderive::Arbitrary),
quickcheck(arbitrary = "crate::quickcheck_helpers::coded::dynamic_range")
)]
pub enum DynamicRange {
Unspecified,
Limited,
Full,
#[cfg(any(feature = "std", feature = "alloc"))]
Other(SmolStr),
}
impl Default for DynamicRange {
#[inline]
fn default() -> Self {
Self::Unspecified
}
}
impl DynamicRange {
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn as_str(&self) -> &str {
match self {
Self::Unspecified => "unspecified",
Self::Limited => "tv",
Self::Full => "pc",
#[cfg(any(feature = "std", feature = "alloc"))]
Self::Other(s) => s.as_str(),
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn to_u32(&self) -> Option<u32> {
Some(match self {
Self::Unspecified => 0,
Self::Limited => 1,
Self::Full => 2,
#[cfg(any(feature = "std", feature = "alloc"))]
Self::Other(_) => return None,
})
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn from_u32(v: u32) -> Option<Self> {
Some(match v {
0 => Self::Unspecified,
1 => Self::Limited,
2 => Self::Full,
_ => return None,
})
}
#[cfg(any(feature = "std", feature = "alloc"))]
pub fn other(slug: impl AsRef<str>) -> Self {
Self::Other(crate::parse::fold_owned(slug.as_ref()))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, thiserror::Error)]
#[error("not a sample-range name")]
#[non_exhaustive]
pub struct ParseDynamicRangeError;
impl core::str::FromStr for DynamicRange {
type Err = ParseDynamicRangeError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut buf = [0u8; crate::parse::FOLD_CAP];
let folded = crate::parse::fold(s, &mut buf).unwrap_or(s.as_bytes());
Ok(match folded {
b"unspecified" => Self::Unspecified,
b"tv" => Self::Limited,
b"pc" => Self::Full,
b"unknown" => Self::Unspecified,
#[cfg(any(feature = "std", feature = "alloc"))]
_ => Self::other(s),
#[cfg(not(any(feature = "std", feature = "alloc")))]
_ => return Err(ParseDynamicRangeError),
})
}
}
#[cfg(test)]
const DYNAMIC_RANGE_FFMPEG_SYNONYMS: &[(&str, &str)] = &[("unknown", "unspecified")];
#[derive(Debug, Clone, PartialEq, Eq, Hash, Display, IsVariant)]
#[display("{}", self.as_str())]
#[non_exhaustive]
#[cfg_attr(
feature = "quickcheck",
derive(::quickcheck_richderive::Arbitrary),
quickcheck(arbitrary = "crate::quickcheck_helpers::coded::chroma_location")
)]
pub enum ChromaLocation {
Unspecified,
Left,
Center,
TopLeft,
Top,
BottomLeft,
Bottom,
#[cfg(any(feature = "std", feature = "alloc"))]
Other(SmolStr),
}
impl Default for ChromaLocation {
#[inline]
fn default() -> Self {
Self::Unspecified
}
}
impl ChromaLocation {
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn as_str(&self) -> &str {
match self {
Self::Unspecified => "unspecified",
Self::Left => "left",
Self::Center => "center",
Self::TopLeft => "topleft",
Self::Top => "top",
Self::BottomLeft => "bottomleft",
Self::Bottom => "bottom",
#[cfg(any(feature = "std", feature = "alloc"))]
Self::Other(s) => s.as_str(),
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn to_u32(&self) -> Option<u32> {
Some(match self {
Self::Unspecified => 0,
Self::Left => 1,
Self::Center => 2,
Self::TopLeft => 3,
Self::Top => 4,
Self::BottomLeft => 5,
Self::Bottom => 6,
#[cfg(any(feature = "std", feature = "alloc"))]
Self::Other(_) => return None,
})
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn from_u32(v: u32) -> Option<Self> {
Some(match v {
0 => Self::Unspecified,
1 => Self::Left,
2 => Self::Center,
3 => Self::TopLeft,
4 => Self::Top,
5 => Self::BottomLeft,
6 => Self::Bottom,
_ => return None,
})
}
#[cfg(any(feature = "std", feature = "alloc"))]
pub fn other(slug: impl AsRef<str>) -> Self {
Self::Other(crate::parse::fold_owned(slug.as_ref()))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, thiserror::Error)]
#[error("not a chroma-location name")]
#[non_exhaustive]
pub struct ParseChromaLocationError;
impl core::str::FromStr for ChromaLocation {
type Err = ParseChromaLocationError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut buf = [0u8; crate::parse::FOLD_CAP];
let folded = crate::parse::fold(s, &mut buf).unwrap_or(s.as_bytes());
Ok(match folded {
b"unspecified" => Self::Unspecified,
b"left" => Self::Left,
b"center" => Self::Center,
b"topleft" => Self::TopLeft,
b"top" => Self::Top,
b"bottomleft" => Self::BottomLeft,
b"bottom" => Self::Bottom,
#[cfg(any(feature = "std", feature = "alloc"))]
_ => Self::other(s),
#[cfg(not(any(feature = "std", feature = "alloc")))]
_ => return Err(ParseChromaLocationError),
})
}
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "quickcheck",
derive(::quickcheck_richderive::Arbitrary),
quickcheck(arbitrary = "crate::quickcheck_helpers::coded::info")
)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Info {
primaries: Primaries,
transfer: Transfer,
matrix: Matrix,
range: DynamicRange,
chroma_location: ChromaLocation,
}
impl Default for Info {
#[cfg_attr(not(tarpaulin), inline(always))]
fn default() -> Self {
Self::UNSPECIFIED
}
}
impl Info {
pub const UNSPECIFIED: Self = Self {
primaries: Primaries::Unspecified,
transfer: Transfer::Unspecified,
matrix: Matrix::Unspecified,
range: DynamicRange::Unspecified,
chroma_location: ChromaLocation::Unspecified,
};
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn new(
primaries: Primaries,
transfer: Transfer,
matrix: Matrix,
range: DynamicRange,
chroma_location: ChromaLocation,
) -> Self {
Self {
primaries,
transfer,
matrix,
range,
chroma_location,
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn primaries(&self) -> Primaries {
self.primaries.clone()
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn transfer(&self) -> Transfer {
self.transfer.clone()
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn matrix(&self) -> Matrix {
self.matrix.clone()
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn range(&self) -> DynamicRange {
self.range.clone()
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn chroma_location(&self) -> ChromaLocation {
self.chroma_location.clone()
}
#[must_use]
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn with_primaries(mut self, v: Primaries) -> Self {
self.primaries = v;
self
}
#[must_use]
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn with_transfer(mut self, v: Transfer) -> Self {
self.transfer = v;
self
}
#[must_use]
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn with_matrix(mut self, v: Matrix) -> Self {
self.matrix = v;
self
}
#[must_use]
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn with_range(mut self, v: DynamicRange) -> Self {
self.range = v;
self
}
#[must_use]
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn with_chroma_location(mut self, v: ChromaLocation) -> Self {
self.chroma_location = v;
self
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn set_primaries(&mut self, v: Primaries) -> &mut Self {
self.primaries = v;
self
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn set_transfer(&mut self, v: Transfer) -> &mut Self {
self.transfer = v;
self
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn set_matrix(&mut self, v: Matrix) -> &mut Self {
self.matrix = v;
self
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn set_range(&mut self, v: DynamicRange) -> &mut Self {
self.range = v;
self
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn set_chroma_location(&mut self, v: ChromaLocation) -> &mut Self {
self.chroma_location = v;
self
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, IsVariant, Display)]
#[display("{}", self.as_str())]
#[non_exhaustive]
#[cfg_attr(
feature = "quickcheck",
derive(::quickcheck_richderive::Arbitrary),
quickcheck(arbitrary = "crate::quickcheck_helpers::coded::dcp_target_gamut")
)]
pub enum DcpTargetGamut {
DciP3,
Rec709,
Rec2020,
#[cfg(any(feature = "std", feature = "alloc"))]
Other(SmolStr),
}
impl Default for DcpTargetGamut {
#[inline]
fn default() -> Self {
Self::DciP3
}
}
impl DcpTargetGamut {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn default_dcp() -> Self {
Self::DciP3
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn as_str(&self) -> &str {
match self {
Self::DciP3 => "dci-p3",
Self::Rec709 => "rec709",
Self::Rec2020 => "rec2020",
#[cfg(any(feature = "std", feature = "alloc"))]
Self::Other(s) => s.as_str(),
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn to_u32(&self) -> Option<u32> {
Some(match self {
Self::DciP3 => 0,
Self::Rec709 => 1,
Self::Rec2020 => 2,
#[cfg(any(feature = "std", feature = "alloc"))]
Self::Other(_) => return None,
})
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn from_u32(v: u32) -> Option<Self> {
Some(match v {
0 => Self::DciP3,
1 => Self::Rec709,
2 => Self::Rec2020,
_ => return None,
})
}
#[cfg(any(feature = "std", feature = "alloc"))]
pub fn other(slug: impl AsRef<str>) -> Self {
Self::Other(crate::parse::fold_owned(slug.as_ref()))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum KernelGamut {
DciP3,
Rec709,
Rec2020,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, thiserror::Error)]
#[error("this target gamut has no conversion-kernel matrix")]
#[non_exhaustive]
pub struct UnsupportedKernelGamutError;
impl TryFrom<&DcpTargetGamut> for KernelGamut {
type Error = UnsupportedKernelGamutError;
fn try_from(g: &DcpTargetGamut) -> Result<Self, Self::Error> {
Ok(match g {
DcpTargetGamut::DciP3 => Self::DciP3,
DcpTargetGamut::Rec709 => Self::Rec709,
DcpTargetGamut::Rec2020 => Self::Rec2020,
#[cfg(any(feature = "std", feature = "alloc"))]
DcpTargetGamut::Other(_) => return Err(UnsupportedKernelGamutError),
})
}
}
impl From<KernelGamut> for DcpTargetGamut {
#[cfg_attr(not(tarpaulin), inline(always))]
fn from(k: KernelGamut) -> Self {
match k {
KernelGamut::DciP3 => Self::DciP3,
KernelGamut::Rec709 => Self::Rec709,
KernelGamut::Rec2020 => Self::Rec2020,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, thiserror::Error)]
#[error("not a DCP target-gamut name")]
#[non_exhaustive]
pub struct ParseDcpTargetGamutError;
impl core::str::FromStr for DcpTargetGamut {
type Err = ParseDcpTargetGamutError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut buf = [0u8; crate::parse::FOLD_CAP];
let folded = crate::parse::fold(s, &mut buf).unwrap_or(s.as_bytes());
Ok(match folded {
b"dci-p3" => Self::DciP3,
b"rec709" => Self::Rec709,
b"rec2020" => Self::Rec2020,
#[cfg(any(feature = "std", feature = "alloc"))]
_ => Self::other(s),
#[cfg(not(any(feature = "std", feature = "alloc")))]
_ => return Err(ParseDcpTargetGamutError),
})
}
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "quickcheck",
derive(::quickcheck_richderive::Arbitrary),
quickcheck(arbitrary = "crate::quickcheck_helpers::coded::content_light_level")
)]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ContentLightLevel {
max_cll: u32,
max_fall: u32,
}
impl ContentLightLevel {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn new(max_cll: u32, max_fall: u32) -> Self {
Self { max_cll, max_fall }
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn max_cll(&self) -> u32 {
self.max_cll
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn max_fall(&self) -> u32 {
self.max_fall
}
#[must_use]
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn with_max_cll(mut self, v: u32) -> Self {
self.max_cll = v;
self
}
#[must_use]
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn with_max_fall(mut self, v: u32) -> Self {
self.max_fall = v;
self
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn set_max_cll(&mut self, v: u32) -> &mut Self {
self.max_cll = v;
self
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn set_max_fall(&mut self, v: u32) -> &mut Self {
self.max_fall = v;
self
}
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "quickcheck",
derive(::quickcheck_richderive::Arbitrary),
quickcheck(arbitrary = "crate::quickcheck_helpers::coded::chroma_coord")
)]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ChromaCoord {
x: u32,
y: u32,
}
impl ChromaCoord {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn new(x: u32, y: u32) -> Self {
Self { x, y }
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn x(&self) -> u32 {
self.x
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn y(&self) -> u32 {
self.y
}
#[must_use]
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn with_x(mut self, x: u32) -> Self {
self.x = x;
self
}
#[must_use]
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn with_y(mut self, y: u32) -> Self {
self.y = y;
self
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn set_x(&mut self, x: u32) -> &mut Self {
self.x = x;
self
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn set_y(&mut self, y: u32) -> &mut Self {
self.y = y;
self
}
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "quickcheck",
derive(::quickcheck_richderive::Arbitrary),
quickcheck(arbitrary = "crate::quickcheck_helpers::coded::mastering_display")
)]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
pub struct MasteringDisplay {
display_primaries: [ChromaCoord; 3],
white_point: ChromaCoord,
max_luminance: u32,
min_luminance: u32,
}
impl MasteringDisplay {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn new(
display_primaries: [ChromaCoord; 3],
white_point: ChromaCoord,
max_luminance: u32,
min_luminance: u32,
) -> Self {
Self {
display_primaries,
white_point,
max_luminance,
min_luminance,
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn display_primaries(&self) -> [ChromaCoord; 3] {
self.display_primaries
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn white_point(&self) -> ChromaCoord {
self.white_point
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn max_luminance(&self) -> u32 {
self.max_luminance
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn min_luminance(&self) -> u32 {
self.min_luminance
}
#[must_use]
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn with_display_primaries(mut self, v: [ChromaCoord; 3]) -> Self {
self.display_primaries = v;
self
}
#[must_use]
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn with_white_point(mut self, v: ChromaCoord) -> Self {
self.white_point = v;
self
}
#[must_use]
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn with_max_luminance(mut self, v: u32) -> Self {
self.max_luminance = v;
self
}
#[must_use]
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn with_min_luminance(mut self, v: u32) -> Self {
self.min_luminance = v;
self
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn set_display_primaries(&mut self, v: [ChromaCoord; 3]) -> &mut Self {
self.display_primaries = v;
self
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn set_white_point(&mut self, v: ChromaCoord) -> &mut Self {
self.white_point = v;
self
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn set_max_luminance(&mut self, v: u32) -> &mut Self {
self.max_luminance = v;
self
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn set_min_luminance(&mut self, v: u32) -> &mut Self {
self.min_luminance = v;
self
}
}
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(default)
)]
#[cfg_attr(
feature = "quickcheck",
derive(::quickcheck_richderive::Arbitrary),
quickcheck(arbitrary = "crate::quickcheck_helpers::coded::hdr_static_metadata")
)]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
pub struct HdrStaticMetadata {
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
mastering: Option<MasteringDisplay>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
content_light: Option<ContentLightLevel>,
}
impl HdrStaticMetadata {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn new(
mastering: Option<MasteringDisplay>,
content_light: Option<ContentLightLevel>,
) -> Self {
Self {
mastering,
content_light,
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn mastering(&self) -> Option<MasteringDisplay> {
self.mastering
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn content_light(&self) -> Option<ContentLightLevel> {
self.content_light
}
#[must_use]
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn with_mastering(mut self, v: Option<MasteringDisplay>) -> Self {
self.mastering = v;
self
}
#[must_use]
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn with_content_light(mut self, v: Option<ContentLightLevel>) -> Self {
self.content_light = v;
self
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn set_mastering(&mut self, v: Option<MasteringDisplay>) -> &mut Self {
self.mastering = v;
self
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn set_content_light(&mut self, v: Option<ContentLightLevel>) -> &mut Self {
self.content_light = v;
self
}
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "quickcheck",
derive(::quickcheck_richderive::Arbitrary),
quickcheck(arbitrary = "crate::quickcheck_helpers::coded::dolby_vision_config")
)]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DolbyVisionConfig {
profile: u8,
level: u8,
rpu_present: bool,
el_present: bool,
bl_signal_compat_id: u8,
}
impl DolbyVisionConfig {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn new(
profile: u8,
level: u8,
rpu_present: bool,
el_present: bool,
bl_signal_compat_id: u8,
) -> Self {
Self {
profile,
level,
rpu_present,
el_present,
bl_signal_compat_id,
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn profile(&self) -> u8 {
self.profile
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn level(&self) -> u8 {
self.level
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn rpu_present(&self) -> bool {
self.rpu_present
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn el_present(&self) -> bool {
self.el_present
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn bl_signal_compat_id(&self) -> u8 {
self.bl_signal_compat_id
}
#[must_use]
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn with_profile(mut self, v: u8) -> Self {
self.profile = v;
self
}
#[must_use]
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn with_level(mut self, v: u8) -> Self {
self.level = v;
self
}
#[must_use]
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn with_rpu_present(mut self) -> Self {
self.rpu_present = true;
self
}
#[must_use]
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn maybe_rpu_present(mut self, v: bool) -> Self {
self.rpu_present = v;
self
}
#[must_use]
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn with_el_present(mut self) -> Self {
self.el_present = true;
self
}
#[must_use]
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn maybe_el_present(mut self, v: bool) -> Self {
self.el_present = v;
self
}
#[must_use]
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn with_bl_signal_compat_id(mut self, v: u8) -> Self {
self.bl_signal_compat_id = v;
self
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn set_profile(&mut self, v: u8) -> &mut Self {
self.profile = v;
self
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn set_level(&mut self, v: u8) -> &mut Self {
self.level = v;
self
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn set_rpu_present(&mut self) -> &mut Self {
self.rpu_present = true;
self
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn update_rpu_present(&mut self, v: bool) -> &mut Self {
self.rpu_present = v;
self
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn clear_rpu_present(&mut self) -> &mut Self {
self.rpu_present = false;
self
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn set_el_present(&mut self) -> &mut Self {
self.el_present = true;
self
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn update_el_present(&mut self, v: bool) -> &mut Self {
self.el_present = v;
self
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn clear_el_present(&mut self) -> &mut Self {
self.el_present = false;
self
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn set_bl_signal_compat_id(&mut self, v: u8) -> &mut Self {
self.bl_signal_compat_id = v;
self
}
}
#[cfg(test)]
mod kernel_tests;
#[cfg(test)]
mod tests;