Skip to content

Commit

Permalink
Small refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
awxkee committed Oct 29, 2024
1 parent 2e4ec87 commit f400ce8
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 83 deletions.
160 changes: 79 additions & 81 deletions src/codecs/avif/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ impl<R: Read> AvifDecoder<R> {
}
}

/// Reshaping incorrectly aligned or sized FFI data into Rust constraints
fn reshape_plane(source: &[u8], stride: usize, width: usize, height: usize) -> Vec<u16> {
let mut target_plane = vec![0u16; width * height];
for (shaped_row, src_row) in target_plane
Expand All @@ -89,6 +90,80 @@ fn reshape_plane(source: &[u8], stride: usize, width: usize, height: usize) -> V
target_plane
}

/// Getting one of prebuilt matrix of fails
fn get_matrix(
david_matrix: dav1d::pixel::MatrixCoefficients,
) -> Result<YuvStandardMatrix, ImageError> {
match david_matrix {
// Identity just a stub here, we'll handle it in different way
dav1d::pixel::MatrixCoefficients::Identity => Ok(YuvStandardMatrix::Bt709),
dav1d::pixel::MatrixCoefficients::BT709 => Ok(YuvStandardMatrix::Bt709),
// This is arguable, some applications prefer to go with Bt.709 as default,
// and some applications prefer Bt.601 as default.
// For ex. `Chrome` always prefer Bt.709 even for SD content
// However, nowadays standard should be Bt.709 for HD+ size otherwise Bt.601
dav1d::pixel::MatrixCoefficients::Unspecified => Ok(YuvStandardMatrix::Bt709),
dav1d::pixel::MatrixCoefficients::Reserved => Err(ImageError::Unsupported(
UnsupportedError::from_format_and_kind(
ImageFormat::Avif.into(),
UnsupportedErrorKind::GenericFeature(
"Using 'Reserved' color matrix is not supported".to_string(),
),
),
)),
dav1d::pixel::MatrixCoefficients::BT470M => Ok(YuvStandardMatrix::Bt470_6),
dav1d::pixel::MatrixCoefficients::BT470BG => Ok(YuvStandardMatrix::Bt601),
dav1d::pixel::MatrixCoefficients::ST170M => Ok(YuvStandardMatrix::Smpte240),
dav1d::pixel::MatrixCoefficients::ST240M => Ok(YuvStandardMatrix::Smpte240),
// This is an experimental matrix in libavif yet.
dav1d::pixel::MatrixCoefficients::YCgCo => Err(ImageError::Unsupported(
UnsupportedError::from_format_and_kind(
ImageFormat::Avif.into(),
UnsupportedErrorKind::GenericFeature("YCgCo matrix is not supported".to_string()),
),
)),
dav1d::pixel::MatrixCoefficients::BT2020NonConstantLuminance => {
Ok(YuvStandardMatrix::Bt2020)
}
dav1d::pixel::MatrixCoefficients::BT2020ConstantLuminance => {
// This matrix significantly differs from others because linearize values is required
// to compute Y instead of Y'.
// Actually it is almost everywhere is not implemented.
Err(ImageError::Unsupported(
UnsupportedError::from_format_and_kind(
ImageFormat::Avif.into(),
UnsupportedErrorKind::GenericFeature(
"BT2020ConstantLuminance matrix is not supported".to_string(),
),
),
))
}
dav1d::pixel::MatrixCoefficients::ST2085 => Err(ImageError::Unsupported(
UnsupportedError::from_format_and_kind(
ImageFormat::Avif.into(),
UnsupportedErrorKind::GenericFeature("ST2085 matrix is not supported".to_string()),
),
)),
dav1d::pixel::MatrixCoefficients::ChromaticityDerivedConstantLuminance
| dav1d::pixel::MatrixCoefficients::ChromaticityDerivedNonConstantLuminance => Err(
ImageError::Unsupported(UnsupportedError::from_format_and_kind(
ImageFormat::Avif.into(),
UnsupportedErrorKind::GenericFeature(
"Chromaticity Derived Luminance matrix is not supported".to_string(),
),
)),
),
dav1d::pixel::MatrixCoefficients::ICtCp => Err(ImageError::Unsupported(
UnsupportedError::from_format_and_kind(
ImageFormat::Avif.into(),
UnsupportedErrorKind::GenericFeature(
"ICtCp Derived Luminance matrix is not supported".to_string(),
),
),
)),
}
}

impl<R: Read> ImageDecoder for AvifDecoder<R> {
fn dimensions(&self) -> (u32, u32) {
(self.picture.width(), self.picture.height())
Expand Down Expand Up @@ -119,87 +194,9 @@ impl<R: Read> ImageDecoder for AvifDecoder<R> {
let is_identity =
self.picture.matrix_coefficients() == dav1d::pixel::MatrixCoefficients::Identity;

let color_matrix = match self.picture.matrix_coefficients() {
// Identity just a stub here, we'll handle it in different way
dav1d::pixel::MatrixCoefficients::Identity => YuvStandardMatrix::Bt709,
dav1d::pixel::MatrixCoefficients::BT709 => YuvStandardMatrix::Bt709,
// This is arguable, some applications prefer to go with Bt.709 as default some applications as Bt.601
// For ex. `Chrome` always prefer Bt.709 even for SD content
// However, nowadays standard should be Bt.709 for HD+ size otherwise Bt.601
dav1d::pixel::MatrixCoefficients::Unspecified => YuvStandardMatrix::Bt709,
dav1d::pixel::MatrixCoefficients::Reserved => {
return Err(ImageError::Unsupported(
UnsupportedError::from_format_and_kind(
ImageFormat::Avif.into(),
UnsupportedErrorKind::GenericFeature(
"Using 'Reserved' color matrix is not supported".to_string(),
),
),
));
}
dav1d::pixel::MatrixCoefficients::BT470M => YuvStandardMatrix::Bt470_6,
dav1d::pixel::MatrixCoefficients::BT470BG => YuvStandardMatrix::Bt601,
dav1d::pixel::MatrixCoefficients::ST170M => YuvStandardMatrix::Smpte240,
dav1d::pixel::MatrixCoefficients::ST240M => YuvStandardMatrix::Smpte240,
dav1d::pixel::MatrixCoefficients::YCgCo => {
return Err(ImageError::Unsupported(
UnsupportedError::from_format_and_kind(
ImageFormat::Avif.into(),
UnsupportedErrorKind::GenericFeature(
"YCgCo matrix is not supported".to_string(),
),
),
));
}
dav1d::pixel::MatrixCoefficients::BT2020NonConstantLuminance => {
YuvStandardMatrix::Bt2020
}
dav1d::pixel::MatrixCoefficients::BT2020ConstantLuminance => {
// This matrix significantly differs from others because linearize values is required
// to compute Y instead of Y'.
// Actually it is almost everywhere is not implemented.
return Err(ImageError::Unsupported(
UnsupportedError::from_format_and_kind(
ImageFormat::Avif.into(),
UnsupportedErrorKind::GenericFeature(
"BT2020ConstantLuminance matrix is not supported".to_string(),
),
),
));
}
dav1d::pixel::MatrixCoefficients::ST2085 => {
return Err(ImageError::Unsupported(
UnsupportedError::from_format_and_kind(
ImageFormat::Avif.into(),
UnsupportedErrorKind::GenericFeature(
"ST2085 matrix is not supported".to_string(),
),
),
));
}
dav1d::pixel::MatrixCoefficients::ChromaticityDerivedConstantLuminance
| dav1d::pixel::MatrixCoefficients::ChromaticityDerivedNonConstantLuminance => {
return Err(ImageError::Unsupported(
UnsupportedError::from_format_and_kind(
ImageFormat::Avif.into(),
UnsupportedErrorKind::GenericFeature(
"Chromaticity Derived Luminance matrix is not supported".to_string(),
),
),
));
}
dav1d::pixel::MatrixCoefficients::ICtCp => {
return Err(ImageError::Unsupported(
UnsupportedError::from_format_and_kind(
ImageFormat::Avif.into(),
UnsupportedErrorKind::GenericFeature(
"ICtCp Derived Luminance matrix is not supported".to_string(),
),
),
));
}
};
let color_matrix = get_matrix(self.picture.matrix_coefficients())?;

// Identity matrix should be possible only on 444
if is_identity && self.picture.pixel_layout() != PixelLayout::I444 {
return Err(ImageError::Unsupported(
UnsupportedError::from_format_and_kind(
Expand All @@ -216,6 +213,7 @@ impl<R: Read> ImageDecoder for AvifDecoder<R> {
let ref_y = self.picture.plane(PlanarImageComponent::Y);
let ref_u = self.picture.plane(PlanarImageComponent::U);
let ref_v = self.picture.plane(PlanarImageComponent::V);

let image = YuvPlanarImage::new(
ref_y.as_ref(),
self.picture.stride(PlanarImageComponent::Y) as usize,
Expand Down Expand Up @@ -321,7 +319,7 @@ impl<R: Read> ImageDecoder for AvifDecoder<R> {
// dav1d may return not aligned and not correctly constrained data,
// or at least I can't find guarantees on that
// so if it is happened, instead casting we'll need to reshape it into a target slice
// required criteria: bytemuck allows this data align, and stride must be dividable by 2
// required criteria: bytemuck allows this align of this data, and stride must be dividable by 2

let mut y_plane_stride = self.picture.stride(PlanarImageComponent::Y) >> 1;

Expand Down
3 changes: 1 addition & 2 deletions src/codecs/avif/yuv.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use num_traits::AsPrimitive;

#[derive(Debug, Copy, Clone)]
/// Representation of inversion matrix
struct CbCrInverseTransform<T> {
pub y_coef: T,
pub cr_coef: T,
Expand Down Expand Up @@ -215,8 +216,6 @@ impl<'a, T> YuvGrayImage<'a, T> {
///
/// * `image`: see [YuvGrayImage]
/// * `rgba`: RGBA image layout
/// * `width`: Image width
/// * `height`: Image height
/// * `range`: see [YuvIntensityRange]
/// * `matrix`: see [YuvStandardMatrix]
///
Expand Down

0 comments on commit f400ce8

Please sign in to comment.