diff --git a/CHANGELOG.md b/CHANGELOG.md index d36e46c..9b90e60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ * BREAKING CHANGE: The `ParamSetId` type has been removed and replaced with separate `PicParamSetId` and `SeqParamSetId` types, since the allowed range of values needs to be different in these two usages. +### Added + +* Parsing of scaling lists + ## 0.7.0 - 2023-05-30 ### Changed diff --git a/src/nal/pps.rs b/src/nal/pps.rs index 8b4f6d2..972aa13 100644 --- a/src/nal/pps.rs +++ b/src/nal/pps.rs @@ -1,4 +1,4 @@ -use super::sps; +use super::sps::{self, ScalingList}; use crate::nal::sps::{SeqParamSetId, SeqParamSetIdError}; use crate::rbsp::BitRead; use crate::{rbsp, Context}; @@ -142,7 +142,8 @@ impl SliceGroup { #[derive(Debug, Clone)] pub struct PicScalingMatrix { - // TODO + pub scaling_list4x4: Vec>, + pub scaling_list8x8: Vec>, } impl PicScalingMatrix { fn read( @@ -166,17 +167,22 @@ impl PicScalingMatrix { }; for i in 0..6 + count { let seq_scaling_list_present_flag = r.read_bool("seq_scaling_list_present_flag")?; - if seq_scaling_list_present_flag { - if i < 6 { - scaling_list4x4 - .push(sps::ScalingList::read(r, 16).map_err(PpsError::ScalingMatrix)?); - } else { - scaling_list8x8 - .push(sps::ScalingList::read(r, 64).map_err(PpsError::ScalingMatrix)?); - } + if i < 6 { + scaling_list4x4.push( + sps::ScalingList::<16>::read(r, seq_scaling_list_present_flag) + .map_err(PpsError::ScalingMatrix)?, + ); + } else { + scaling_list8x8.push( + sps::ScalingList::<64>::read(r, seq_scaling_list_present_flag) + .map_err(PpsError::ScalingMatrix)?, + ); } } - Some(PicScalingMatrix {}) + Some(PicScalingMatrix { + scaling_list4x4, + scaling_list8x8, + }) } else { None }) @@ -360,9 +366,9 @@ mod test { pps.extension, Some(PicParameterSetExtra { transform_8x8_mode_flag: true, - pic_scaling_matrix: Some(_), + pic_scaling_matrix: Some(PicScalingMatrix { scaling_list4x4, scaling_list8x8 }), .. - }) + }) if scaling_list4x4.len() == 6 && scaling_list8x8.len() == 2 )); } diff --git a/src/nal/sps.rs b/src/nal/sps.rs index 8ba2ac4..3adfba4 100644 --- a/src/nal/sps.rs +++ b/src/nal/sps.rs @@ -278,33 +278,48 @@ impl From for u8 { } } -pub struct ScalingList { - // TODO +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum ScalingList { + NotPresent, + UseDefault, + List(Box<[i32; S]>), } -impl ScalingList { - pub fn read(r: &mut R, size: u8) -> Result { - let mut scaling_list = vec![]; + +impl ScalingList { + pub fn read( + r: &mut R, + present: bool, + ) -> Result, ScalingMatrixError> { + if !present { + return Ok(ScalingList::NotPresent); + } + let mut scaling_list = Box::new([0; S]); let mut last_scale = 8; let mut next_scale = 8; - let mut _use_default_scaling_matrix_flag = false; - for j in 0..size { + let mut use_default_scaling_matrix_flag = false; + for j in 0..S { if next_scale != 0 { let delta_scale = r.read_se("delta_scale")?; if delta_scale < -128 || delta_scale > 127 { return Err(ScalingMatrixError::DeltaScaleOutOfRange(delta_scale)); } next_scale = (last_scale + delta_scale + 256) % 256; - _use_default_scaling_matrix_flag = j == 0 && next_scale == 0; + use_default_scaling_matrix_flag = j == 0 && next_scale == 0; } let new_value = if next_scale == 0 { last_scale } else { next_scale }; - scaling_list.push(new_value); + scaling_list[j] = new_value; last_scale = new_value; } - Ok(ScalingList {}) + + if use_default_scaling_matrix_flag { + Ok(ScalingList::UseDefault) + } else { + Ok(ScalingList::List(scaling_list)) + } } } @@ -323,7 +338,8 @@ impl From for ScalingMatrixError { #[derive(Clone, Debug, Default, PartialEq, Eq)] pub struct SeqScalingMatrix { - // TODO + pub scaling_list4x4: Vec>, + pub scaling_list8x8: Vec>, } impl SeqScalingMatrix { @@ -337,15 +353,16 @@ impl SeqScalingMatrix { let count = if chroma_format_idc == 3 { 12 } else { 8 }; for i in 0..count { let seq_scaling_list_present_flag = r.read_bool("seq_scaling_list_present_flag")?; - if seq_scaling_list_present_flag { - if i < 6 { - scaling_list4x4.push(ScalingList::read(r, 16)?); - } else { - scaling_list8x8.push(ScalingList::read(r, 64)?); - } + if i < 6 { + scaling_list4x4.push(ScalingList::<16>::read(r, seq_scaling_list_present_flag)?); + } else { + scaling_list8x8.push(ScalingList::<64>::read(r, seq_scaling_list_present_flag)?); } } - Ok(SeqScalingMatrix {}) + Ok(SeqScalingMatrix { + scaling_list4x4, + scaling_list8x8, + }) } } @@ -356,7 +373,7 @@ pub struct ChromaInfo { pub bit_depth_luma_minus8: u8, pub bit_depth_chroma_minus8: u8, pub qpprime_y_zero_transform_bypass_flag: bool, - pub scaling_matrix: SeqScalingMatrix, + pub scaling_matrix: Option, } impl ChromaInfo { pub fn read(r: &mut R, profile_idc: ProfileIdc) -> Result { @@ -390,12 +407,14 @@ impl ChromaInfo { fn read_scaling_matrix( r: &mut R, chroma_format_idc: u32, - ) -> Result { + ) -> Result, SpsError> { let scaling_matrix_present_flag = r.read_bool("scaling_matrix_present_flag")?; if scaling_matrix_present_flag { - SeqScalingMatrix::read(r, chroma_format_idc).map_err(SpsError::ScalingMatrix) + Ok(Some( + SeqScalingMatrix::read(r, chroma_format_idc).map_err(SpsError::ScalingMatrix)?, + )) } else { - Ok(SeqScalingMatrix::default()) + Ok(None) } } } @@ -1414,6 +1433,20 @@ mod test { seq_parameter_set_id: SeqParamSetId::from_u32(0).unwrap(), chroma_info: ChromaInfo{ chroma_format: ChromaFormat::YUV420, + scaling_matrix: Some(SeqScalingMatrix { + scaling_list4x4: vec![ + ScalingList::List(Box::new([16; 16])), + ScalingList::List(Box::new([16; 16])), + ScalingList::List(Box::new([16; 16])), + ScalingList::List(Box::new([16; 16])), + ScalingList::List(Box::new([16; 16])), + ScalingList::List(Box::new([16; 16])), + ], + scaling_list8x8: vec![ + ScalingList::NotPresent, + ScalingList::NotPresent, + ] + }), ..ChromaInfo::default() }, /*seq_scaling_list: Some(SeqScalingList{