From 18568263b3b597564107a0eb5f98a71bd8b2751b Mon Sep 17 00:00:00 2001 From: Eric Knapp Date: Fri, 22 Mar 2024 17:05:10 -0400 Subject: [PATCH 1/3] Write hvc1 with stsd --- src/mp4box/stsd.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/mp4box/stsd.rs b/src/mp4box/stsd.rs index eb00cad8..9c808719 100644 --- a/src/mp4box/stsd.rs +++ b/src/mp4box/stsd.rs @@ -41,6 +41,8 @@ impl StsdBox { size += avc1.box_size(); } else if let Some(ref hev1) = self.hev1 { size += hev1.box_size(); + } else if let Some(ref hvc1) = self.hvc1 { + size += hvc1.box_size(); } else if let Some(ref vp09) = self.vp09 { size += vp09.box_size(); } else if let Some(ref mp4a) = self.mp4a { @@ -145,6 +147,8 @@ impl WriteBox<&mut W> for StsdBox { avc1.write_box(writer)?; } else if let Some(ref hev1) = self.hev1 { hev1.write_box(writer)?; + } else if let Some(ref hvc1) = self.hvc1 { + hvc1.write_box(writer)?; } else if let Some(ref vp09) = self.vp09 { vp09.write_box(writer)?; } else if let Some(ref mp4a) = self.mp4a { From b566dcb5407a674cc26c5e6d5728d4e39bda9e92 Mon Sep 17 00:00:00 2001 From: Eric Knapp Date: Mon, 25 Mar 2024 16:21:23 -0400 Subject: [PATCH 2/3] Check for parameter set completeness in hvc1 box --- src/mp4box/hev1.rs | 6 ++++++ src/mp4box/hvc1.rs | 23 ++++++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/mp4box/hev1.rs b/src/mp4box/hev1.rs index ae37d84f..9de763e8 100644 --- a/src/mp4box/hev1.rs +++ b/src/mp4box/hev1.rs @@ -269,6 +269,12 @@ pub struct HvcCArray { pub nalus: Vec, } +impl HvcCArray { + pub fn is_parameter_set(&self) -> bool { + self.nal_unit_type == VPS || self.nal_unit_type == SPS || self.nal_unit_type == PPS + } +} + impl ReadBox<&mut R> for HvcCBox { fn read_box(reader: &mut R, _size: u64) -> Result { let configuration_version = reader.read_u8()?; diff --git a/src/mp4box/hvc1.rs b/src/mp4box/hvc1.rs index 418ce66f..29206460 100644 --- a/src/mp4box/hvc1.rs +++ b/src/mp4box/hvc1.rs @@ -121,6 +121,12 @@ impl ReadBox<&mut R> for Hvc1Box { return Err(Error::InvalidData("hvcc not found")); }; + for arr in &hvcc.arrays { + if arr.is_parameter_set() && !arr.completeness { + return Err(Error::InvalidData("hvcc parameter set completeness must be 1 for hvc1 box")); + } + } + skip_bytes_to(reader, start + size)?; Ok(Hvc1Box { @@ -159,6 +165,12 @@ impl WriteBox<&mut W> for Hvc1Box { writer.write_u16::(self.depth)?; writer.write_i16::(-1)?; // pre-defined + for arr in &self.hvcc.arrays { + if arr.is_parameter_set() && !arr.completeness { + return Err(Error::InvalidData("hvcc parameter set completeness must be 1 for hvc1 box")); + } + } + self.hvcc.write_box(writer)?; Ok(size) @@ -168,11 +180,19 @@ impl WriteBox<&mut W> for Hvc1Box { #[cfg(test)] mod tests { use super::*; - use crate::mp4box::BoxHeader; + use crate::{hev1::{HvcCArray, HvcCArrayNalu}, mp4box::BoxHeader}; use std::io::Cursor; #[test] fn test_hvc1() { + let hvcc_array = HvcCArray { + completeness: true, + nal_unit_type: 34, + nalus: vec![HvcCArrayNalu { + size: 8, + data: vec![68, 1, 193, 114, 67, 141, 98, 36], + }], + }; let src_box = Hvc1Box { data_reference_index: 1, width: 320, @@ -183,6 +203,7 @@ mod tests { depth: 24, hvcc: HvcCBox { configuration_version: 1, + arrays: vec![hvcc_array], ..Default::default() }, }; From 5650576905b3f47648efa55d4dad2df371a31380 Mon Sep 17 00:00:00 2001 From: Eric Knapp Date: Mon, 25 Mar 2024 16:22:04 -0400 Subject: [PATCH 3/3] Skip unknown boxes inside hev1 --- src/mp4box/hev1.rs | 55 ++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/src/mp4box/hev1.rs b/src/mp4box/hev1.rs index 9de763e8..4987eab7 100644 --- a/src/mp4box/hev1.rs +++ b/src/mp4box/hev1.rs @@ -101,31 +101,38 @@ impl ReadBox<&mut R> for Hev1Box { let depth = reader.read_u16::()?; reader.read_i16::()?; // pre-defined - let header = BoxHeader::read(reader)?; - let BoxHeader { name, size: s } = header; - if s > size { - return Err(Error::InvalidData( - "hev1 box contains a box with a larger size than it", - )); - } - if name == BoxType::HvcCBox { - let hvcc = HvcCBox::read_box(reader, s)?; - - skip_bytes_to(reader, start + size)?; - - Ok(Hev1Box { - data_reference_index, - width, - height, - horizresolution, - vertresolution, - frame_count, - depth, - hvcc, - }) - } else { - Err(Error::InvalidData("hvcc not found")) + let mut hvcc = None; + + while reader.stream_position()? < start + size { + let header = BoxHeader::read(reader)?; + let BoxHeader { name, size: s } = header; + if s > size { + return Err(Error::InvalidData( + "hev1 box contains a box with a larger size than it", + )); + } + if name == BoxType::HvcCBox { + hvcc = Some(HvcCBox::read_box(reader, s)?); + } else { + skip_box(reader, s)?; + } } + let Some(hvcc) = hvcc else { + return Err(Error::InvalidData("hvcc not found")); + }; + + skip_bytes_to(reader, start + size)?; + + Ok(Hev1Box { + data_reference_index, + width, + height, + horizresolution, + vertresolution, + frame_count, + depth, + hvcc, + }) } }