From d88edf91a9b1c2d08b11ef3d34ddca17eb5c45ea Mon Sep 17 00:00:00 2001 From: Takeru Ohta Date: Tue, 15 Oct 2024 12:26:42 +0900 Subject: [PATCH 01/16] =?UTF-8?q?`ChunkAccessor`=20=E3=81=A8=20`SampleAcce?= =?UTF-8?q?ssor`=20=E3=81=AE=E4=B8=80=E9=83=A8=E3=81=AE=E3=83=A1=E3=82=BD?= =?UTF-8?q?=E3=83=83=E3=83=89=E3=81=AE=E3=83=A9=E3=82=A4=E3=83=95=E3=82=BF?= =?UTF-8?q?=E3=82=A4=E3=83=A0=E5=88=B6=E7=B4=84=E3=81=8C=E5=BF=85=E8=A6=81?= =?UTF-8?q?=E4=BB=A5=E4=B8=8A=E3=81=AB=E5=8E=B3=E3=81=97=E3=81=8B=E3=81=A3?= =?UTF-8?q?=E3=81=9F=E3=81=AE=E3=82=92=E7=B7=A9=E3=81=8F=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGES.md | 3 +++ src/aux.rs | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 623a238..b921763 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,6 +11,9 @@ ## develop +- [UPDATE] `ChunkAccessor` と `SampleAccessor` の一部のメソッドのライフタイム制約が必要以上に厳しかったのを緩くする + - @sile + ## 2024.3.0 - [CHANGE] `Encode::encode()` が `writer: &mut W` ではなく `writer: W` を引数に取るように変更する diff --git a/src/aux.rs b/src/aux.rs index cec9fef..f4a96f4 100644 --- a/src/aux.rs +++ b/src/aux.rs @@ -299,7 +299,7 @@ pub struct SampleAccessor<'a, T> { index: NonZeroU32, } -impl> SampleAccessor<'_, T> { +impl<'a, T: AsRef> SampleAccessor<'a, T> { /// このサンプルのインデックスを取得する pub fn index(&self) -> NonZeroU32 { self.index @@ -371,7 +371,7 @@ impl> SampleAccessor<'_, T> { } /// サンプルが属するチャンクの情報を返す - pub fn chunk(&self) -> ChunkAccessor { + pub fn chunk(&self) -> ChunkAccessor<'a, T> { let i = self .sample_table .sample_index_offsets @@ -391,7 +391,7 @@ pub struct ChunkAccessor<'a, T> { index: NonZeroU32, } -impl> ChunkAccessor<'_, T> { +impl<'a, T: AsRef> ChunkAccessor<'a, T> { /// このチャンクのインデックスを取得する pub fn index(&self) -> NonZeroU32 { self.index @@ -407,7 +407,7 @@ impl> ChunkAccessor<'_, T> { } /// チャンクが参照するサンプルエントリー返す - pub fn sample_entry(&self) -> &SampleEntry { + pub fn sample_entry(&self) -> &'a SampleEntry { &self.sample_table.stbl_box().stsd_box.entries [self.stsc_entry().sample_description_index.get() as usize - 1] } From 14330368895ae2a559285cba923c10f07f300b3e Mon Sep 17 00:00:00 2001 From: Takeru Ohta Date: Fri, 18 Oct 2024 13:42:50 +0900 Subject: [PATCH 02/16] =?UTF-8?q?=E3=83=89=E3=82=AD=E3=83=A5=E3=83=A1?= =?UTF-8?q?=E3=83=B3=E3=83=88=E5=86=85=E3=81=AE=E3=82=BF=E3=82=A4=E3=83=9D?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/boxes.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/boxes.rs b/src/boxes.rs index 8ad3a7c..8c9180d 100644 --- a/src/boxes.rs +++ b/src/boxes.rs @@ -3623,7 +3623,7 @@ impl FullBox for StszBox { } } -/// [ISO/IEC 14496-12] ChunkOffsetBox class (親: [`StcoBox`]) +/// [ISO/IEC 14496-12] ChunkOffsetBox class (親: [`StblBox`]) #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[allow(missing_docs)] pub struct StcoBox { @@ -3694,7 +3694,7 @@ impl FullBox for StcoBox { } } -/// [ISO/IEC 14496-12] ChunkLargeOffsetBox class (親: [`Co64Box`]) +/// [ISO/IEC 14496-12] ChunkLargeOffsetBox class (親: [`StblBox`]) #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[allow(missing_docs)] pub struct Co64Box { From 2fc020f18e116717cd9126b21b669881a741a414 Mon Sep 17 00:00:00 2001 From: Takeru Ohta Date: Wed, 4 Dec 2024 15:57:04 +0900 Subject: [PATCH 03/16] =?UTF-8?q?AAC=20=E7=94=A8=E3=81=AE=E3=83=86?= =?UTF-8?q?=E3=82=B9=E3=83=88=E3=83=87=E3=83=BC=E3=82=BF=E3=81=A8=E3=83=86?= =?UTF-8?q?=E3=82=B9=E3=83=88=E3=82=B1=E3=83=BC=E3=82=B9=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0=EF=BC=88=E3=81=BE=E3=81=A0=E5=A4=B1=E6=95=97=E3=81=99?= =?UTF-8?q?=E3=82=8B=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/decode_encode_test.rs | 22 ++++++++++++++++++++++ tests/testdata/beep-aac-audio.mp4 | Bin 0 -> 9381 bytes 2 files changed, 22 insertions(+) create mode 100644 tests/testdata/beep-aac-audio.mp4 diff --git a/tests/decode_encode_test.rs b/tests/decode_encode_test.rs index b0c688c..b756c45 100644 --- a/tests/decode_encode_test.rs +++ b/tests/decode_encode_test.rs @@ -125,6 +125,28 @@ fn decode_encode_beep_opus_audio_mp4() -> Result<()> { Ok(()) } +#[test] +fn decode_encode_beep_opus_audio_aac() -> Result<()> { + let input_bytes = include_bytes!("testdata/beep-aac-audio.mp4"); + let file: Mp4File = Mp4File::decode(&input_bytes[..])?; + + // デコード時に未処理のボックスがないことを確認する。 + assert_eq!(collect_unknown_box_types(&file), Vec::new()); + + let mut output_bytes = Vec::new(); + file.encode(&mut output_bytes)?; + + // エンコード結果をデコードしたら同じ MP4 になっていることを確認する。 + let encoded_file: Mp4File = Mp4File::decode(&output_bytes[..])?; + assert_eq!(file, encoded_file); + + // エンコード結果のバイト列が正しいことを確認する。 + assert_eq!(input_bytes.len(), output_bytes.len()); + assert_eq!(&input_bytes[..], output_bytes); + + Ok(()) +} + fn collect_unknown_box_types(mp4: &Mp4File) -> Vec { let mut stack = mp4.iter().collect::>(); let mut unknowns = Vec::new(); diff --git a/tests/testdata/beep-aac-audio.mp4 b/tests/testdata/beep-aac-audio.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..f88390fcc7b236dcbe8b6de31b13ab956b823c58 GIT binary patch literal 9381 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 Date: Wed, 4 Dec 2024 16:08:51 +0900 Subject: [PATCH 04/16] Add mp4a box --- src/boxes.rs | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/src/boxes.rs b/src/boxes.rs index 8c9180d..d94f8b5 100644 --- a/src/boxes.rs +++ b/src/boxes.rs @@ -2188,6 +2188,7 @@ pub enum SampleEntry { Vp09(Vp09Box), Av01(Av01Box), Opus(OpusBox), + Mp4a(Mp4aBox), Unknown(UnknownBox), } @@ -2200,6 +2201,7 @@ impl SampleEntry { Self::Vp09(b) => b, Self::Av01(b) => b, Self::Opus(b) => b, + Self::Mp4a(b) => b, Self::Unknown(b) => b, } } @@ -2214,6 +2216,7 @@ impl Encode for SampleEntry { Self::Vp09(b) => b.encode(writer), Self::Av01(b) => b.encode(writer), Self::Opus(b) => b.encode(writer), + Self::Mp4a(b) => b.encode(writer), Self::Unknown(b) => b.encode(writer), } } @@ -2229,6 +2232,7 @@ impl Decode for SampleEntry { Vp09Box::TYPE => Decode::decode(&mut reader).map(Self::Vp09), Av01Box::TYPE => Decode::decode(&mut reader).map(Self::Av01), OpusBox::TYPE => Decode::decode(&mut reader).map(Self::Opus), + Mp4aBox::TYPE => Decode::decode(&mut reader).map(Self::Mp4a), _ => Decode::decode(&mut reader).map(Self::Unknown), } } @@ -3916,6 +3920,86 @@ impl BaseBox for OpusBox { } } +/// [ISO/IEC 14496-14] MP4AudioSampleEntry class +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[allow(missing_docs)] +pub struct Mp4aBox { + pub audio: AudioSampleEntryFields, + // TODO: esds: pub dops_box: DopsBox, + pub unknown_boxes: Vec, +} + +impl Mp4aBox { + /// ボックス種別 + pub const TYPE: BoxType = BoxType::Normal(*b"mp4a"); + + fn encode_payload(&self, mut writer: W) -> Result<()> { + self.audio.encode(&mut writer)?; + // self.dops_box.encode(&mut writer)?; + for b in &self.unknown_boxes { + b.encode(&mut writer)?; + } + Ok(()) + } + + fn decode_payload(mut reader: &mut std::io::Take) -> Result { + let audio = AudioSampleEntryFields::decode(&mut reader)?; + //let mut dops_box = None; + let mut unknown_boxes = Vec::new(); + while reader.limit() > 0 { + let (header, mut reader) = BoxHeader::peek(&mut reader)?; + match header.box_type { + // DopsBox::TYPE if dops_box.is_none() => { + // dops_box = Some(DopsBox::decode(&mut reader)?); + // } + _ => { + unknown_boxes.push(UnknownBox::decode(&mut reader)?); + } + } + } + //let dops_box = dops_box.ok_or_else(|| Error::missing_box("dops", Self::TYPE))?; + Ok(Self { + audio, + //dops_box, + unknown_boxes, + }) + } +} + +impl Encode for Mp4aBox { + fn encode(&self, mut writer: W) -> Result<()> { + BoxHeader::from_box(self).encode(&mut writer)?; + self.encode_payload(writer)?; + Ok(()) + } +} + +impl Decode for Mp4aBox { + fn decode(mut reader: R) -> Result { + let header = BoxHeader::decode(&mut reader)?; + header.box_type.expect(Self::TYPE)?; + header.with_box_payload_reader(reader, Self::decode_payload) + } +} + +impl BaseBox for Mp4aBox { + fn box_type(&self) -> BoxType { + Self::TYPE + } + + fn box_payload_size(&self) -> u64 { + ExternalBytes::calc(|writer| self.encode_payload(writer)) + } + + fn children<'a>(&'a self) -> Box> { + Box::new( + std::iter::empty() + // TODO: .chain(std::iter::once(&self.dops_box).map(as_box_object)) + .chain(self.unknown_boxes.iter().map(as_box_object)), + ) + } +} + /// 音声系の [`SampleEntry`] に共通のフィールドをまとめた構造体 #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[allow(missing_docs)] From 7eb9e247eba180348ec6206655b0c05f7819fa96 Mon Sep 17 00:00:00 2001 From: Takeru Ohta Date: Wed, 4 Dec 2024 16:36:20 +0900 Subject: [PATCH 05/16] =?UTF-8?q?esds=20=E3=83=9C=E3=83=83=E3=82=AF?= =?UTF-8?q?=E3=82=B9=E3=82=92=E3=83=9A=E3=82=A4=E3=83=AD=E3=83=BC=E3=83=89?= =?UTF-8?q?=E3=82=92=E4=BB=AE=E6=B1=BA=E3=82=81=E3=81=A7=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/boxes.rs | 83 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 74 insertions(+), 9 deletions(-) diff --git a/src/boxes.rs b/src/boxes.rs index d94f8b5..a10f819 100644 --- a/src/boxes.rs +++ b/src/boxes.rs @@ -3925,7 +3925,7 @@ impl BaseBox for OpusBox { #[allow(missing_docs)] pub struct Mp4aBox { pub audio: AudioSampleEntryFields, - // TODO: esds: pub dops_box: DopsBox, + pub esds_box: EsdsBox, pub unknown_boxes: Vec, } @@ -3935,7 +3935,7 @@ impl Mp4aBox { fn encode_payload(&self, mut writer: W) -> Result<()> { self.audio.encode(&mut writer)?; - // self.dops_box.encode(&mut writer)?; + self.esds_box.encode(&mut writer)?; for b in &self.unknown_boxes { b.encode(&mut writer)?; } @@ -3944,23 +3944,23 @@ impl Mp4aBox { fn decode_payload(mut reader: &mut std::io::Take) -> Result { let audio = AudioSampleEntryFields::decode(&mut reader)?; - //let mut dops_box = None; + let mut esds_box = None; let mut unknown_boxes = Vec::new(); while reader.limit() > 0 { let (header, mut reader) = BoxHeader::peek(&mut reader)?; match header.box_type { - // DopsBox::TYPE if dops_box.is_none() => { - // dops_box = Some(DopsBox::decode(&mut reader)?); - // } + EsdsBox::TYPE if esds_box.is_none() => { + esds_box = Some(EsdsBox::decode(&mut reader)?); + } _ => { unknown_boxes.push(UnknownBox::decode(&mut reader)?); } } } - //let dops_box = dops_box.ok_or_else(|| Error::missing_box("dops", Self::TYPE))?; + let esds_box = esds_box.ok_or_else(|| Error::missing_box("esds", Self::TYPE))?; Ok(Self { audio, - //dops_box, + esds_box, unknown_boxes, }) } @@ -3994,7 +3994,7 @@ impl BaseBox for Mp4aBox { fn children<'a>(&'a self) -> Box> { Box::new( std::iter::empty() - // TODO: .chain(std::iter::once(&self.dops_box).map(as_box_object)) + .chain(std::iter::once(&self.esds_box).map(as_box_object)) .chain(self.unknown_boxes.iter().map(as_box_object)), ) } @@ -4130,3 +4130,68 @@ impl BaseBox for DopsBox { Box::new(std::iter::empty()) } } + +/// [ISO/IEC 14496-14] ESDBox class +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[allow(missing_docs)] +pub struct EsdsBox { + pub payload: Vec, // TODO +} + +impl EsdsBox { + /// ボックス種別 + pub const TYPE: BoxType = BoxType::Normal(*b"esds"); + + fn encode_payload(&self, mut writer: W) -> Result<()> { + FullBoxHeader::from_box(self).encode(&mut writer)?; + writer.write_all(&self.payload)?; + Ok(()) + } + + fn decode_payload(mut reader: &mut std::io::Take) -> Result { + let _ = FullBoxHeader::decode(&mut reader)?; + let mut payload = Vec::new(); + reader.read_to_end(&mut payload)?; + Ok(Self { payload }) + } +} + +impl Encode for EsdsBox { + fn encode(&self, mut writer: W) -> Result<()> { + BoxHeader::from_box(self).encode(&mut writer)?; + self.encode_payload(writer)?; + Ok(()) + } +} + +impl Decode for EsdsBox { + fn decode(mut reader: R) -> Result { + let header = BoxHeader::decode(&mut reader)?; + header.box_type.expect(Self::TYPE)?; + header.with_box_payload_reader(reader, Self::decode_payload) + } +} + +impl BaseBox for EsdsBox { + fn box_type(&self) -> BoxType { + Self::TYPE + } + + fn box_payload_size(&self) -> u64 { + ExternalBytes::calc(|writer| self.encode_payload(writer)) + } + + fn children<'a>(&'a self) -> Box> { + Box::new(std::iter::empty()) + } +} + +impl FullBox for EsdsBox { + fn full_box_version(&self) -> u8 { + 0 + } + + fn full_box_flags(&self) -> FullBoxFlags { + FullBoxFlags::new(0) + } +} From a1b77089f36f6c6252810aec37619e9e1b724564 Mon Sep 17 00:00:00 2001 From: Takeru Ohta Date: Wed, 4 Dec 2024 17:01:59 +0900 Subject: [PATCH 06/16] =?UTF-8?q?=E3=80=8C=E8=A6=8F=E6=A0=BC=E6=9B=B8?= =?UTF-8?q?=E3=80=8D=E3=82=BB=E3=82=AF=E3=82=B7=E3=83=A7=E3=83=B3=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 4a567c0..ca799cb 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,16 @@ WebAssembly を使ったサンプルを GitHub Pages に用意しています。 - [MP4 Dump](https://shiguredo.github.io/mp4-rust/examples/dump/) - [MP4 Transcode](https://shiguredo.github.io/mp4-rust/examples/transcode/) +## 規格書 + +- ISO/IEC 14496-1 +- ISO/IEC 14496-12 +- ISO/IEC 14496-14 +- ISO/IEC 14496-15 +- https://www.webmproject.org/vp9/mp4/ +- https://aomediacodec.github.io/av1-isobmff/ +- https://gitlab.xiph.org/xiph/opus/-/blob/main/doc/opus_in_isobmff.html + ## ライセンス Apache License 2.0 From 871729918d31c18cfbf603f8ae98c00dc3794af2 Mon Sep 17 00:00:00 2001 From: Takeru Ohta Date: Thu, 5 Dec 2024 12:27:15 +0900 Subject: [PATCH 07/16] =?UTF-8?q?esds=20=E3=81=AE=E3=83=91=E3=83=BC?= =?UTF-8?q?=E3=82=B9=E9=80=94=E4=B8=AD=EF=BC=88=E3=81=BE=E3=81=A0=E5=A4=B1?= =?UTF-8?q?=E6=95=97=E3=81=99=E3=82=8B=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/boxes.rs | 137 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 131 insertions(+), 6 deletions(-) diff --git a/src/boxes.rs b/src/boxes.rs index a10f819..c7c81e6 100644 --- a/src/boxes.rs +++ b/src/boxes.rs @@ -4131,11 +4131,73 @@ impl BaseBox for DopsBox { } } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[allow(missing_docs)] +pub struct DecoderConfigDescriptor { + object_type_indication: u8, + stream_type: Uint, + up_stream: Uint, + buffer_size_db: Uint, + max_bitrate: u32, + avg_bitrate: u32, + // dec_specific_info: (), // tag=DecSpecificInfoTag + // profile_level_indication_index_descr: (), +} + +impl Decode for DecoderConfigDescriptor { + fn decode(mut reader: R) -> Result { + let tag = u8::decode(&mut reader)?; + if tag != 4 { + // 4 = DecoderConfigDescrTag + return Err(Error::invalid_data(&format!( + "Unexpected descriptor tag: expected=4, actual={tag}" + ))); + } + + // TODO: + let mut size = 0; + let mut has_next_byte = true; + while has_next_byte { + let b = u8::decode(&mut reader)?; + has_next_byte = Uint::::from_bits(b).get() == 1; + size = (size << 7) | Uint::::from_bits(b).get() as usize + } + dbg!(size); + + let object_type_indication = u8::decode(&mut reader)?; + + let b = u8::decode(&mut reader)?; + let stream_type = Uint::from_bits(b); + let up_stream = Uint::from_bits(b); + + let mut buf = [0; 4]; + reader.read_exact(&mut buf[1..])?; + let buffer_size_db = Uint::from_bits(u32::from_be_bytes(buf)); + + let max_bitrate = u32::decode(&mut reader)?; + let avg_bitrate = u32::decode(&mut reader)?; + + Ok(Self { + object_type_indication, + stream_type, + up_stream, + buffer_size_db, + max_bitrate, + avg_bitrate, + }) + } +} + /// [ISO/IEC 14496-14] ESDBox class #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[allow(missing_docs)] pub struct EsdsBox { - pub payload: Vec, // TODO + pub es_id: u16, + pub stream_priority: Uint, + pub depends_on_es_id: Option, + pub url_string: Option, + pub ocr_es_id: Option, + pub dec_config_descr: DecoderConfigDescriptor, } impl EsdsBox { @@ -4144,15 +4206,78 @@ impl EsdsBox { fn encode_payload(&self, mut writer: W) -> Result<()> { FullBoxHeader::from_box(self).encode(&mut writer)?; - writer.write_all(&self.payload)?; - Ok(()) + + // Ok(()) + todo!() } fn decode_payload(mut reader: &mut std::io::Take) -> Result { let _ = FullBoxHeader::decode(&mut reader)?; - let mut payload = Vec::new(); - reader.read_to_end(&mut payload)?; - Ok(Self { payload }) + let tag = u8::decode(&mut reader)?; + if tag != 3 { + // 3 = ES_DescrTag + return Err(Error::invalid_data(&format!( + "Unexpected descriptor tag: expected=3, actual={tag}" + ))); + } + + // TODO: + let mut size = 0; + let mut has_next_byte = true; + while has_next_byte { + let b = u8::decode(&mut reader)?; + has_next_byte = Uint::::from_bits(b).get() == 1; + size = (size << 7) | Uint::::from_bits(b).get() as usize + } + if size != reader.limit() as usize { + return Err(Error::invalid_data(&format!( + "Unexpected descriptor size: expected={}, actual={size}", + reader.limit() + ))); + } + + let es_id = u16::decode(&mut reader)?; + + let b = u8::decode(&mut reader)?; + let stream_dependence_flag: Uint = Uint::from_bits(b); + let url_flag: Uint = Uint::from_bits(b); + let ocr_stream_flag: Uint = Uint::from_bits(b); + let stream_priority = Uint::from_bits(b); + + let depends_on_es_id = (stream_dependence_flag.get() == 1) + .then(|| u16::decode(&mut reader)) + .transpose()?; + + let url_string = if url_flag.get() == 1 { + let len = u8::decode(&mut reader)? as u64; + let mut s = String::new(); + reader.take(len).read_to_string(&mut s)?; + Some(s) + } else { + None + }; + + let ocr_es_id = (ocr_stream_flag.get() == 1) + .then(|| u16::decode(&mut reader)) + .transpose()?; + + let dec_config_descr = DecoderConfigDescriptor::decode(&mut reader)?; + + dbg!(es_id); + dbg!(stream_priority); + dbg!(&url_string); + dbg!(ocr_es_id); + dbg!(&dec_config_descr); + // 残りのフィールドは必要になるまでは未対応 + + Ok(Self { + es_id, + stream_priority, + depends_on_es_id, + url_string, + ocr_es_id, + dec_config_descr, + }) } } From 93448dedd82d8416ecc69b5939c8df95ba1d750f Mon Sep 17 00:00:00 2001 From: Takeru Ohta Date: Thu, 5 Dec 2024 12:49:28 +0900 Subject: [PATCH 08/16] =?UTF-8?q?=E3=81=84=E3=81=A3=E3=81=9F=E3=82=93?= =?UTF-8?q?=E3=83=87=E3=82=B3=E3=83=BC=E3=83=89=E3=81=AF=E5=8B=95=E3=81=84?= =?UTF-8?q?=E3=81=9F=EF=BC=88=E3=82=B3=E3=83=BC=E3=83=89=E6=95=B4=E7=90=86?= =?UTF-8?q?=E5=89=8D=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/boxes.rs | 77 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 73 insertions(+), 4 deletions(-) diff --git a/src/boxes.rs b/src/boxes.rs index c7c81e6..69e33d9 100644 --- a/src/boxes.rs +++ b/src/boxes.rs @@ -4140,8 +4140,7 @@ pub struct DecoderConfigDescriptor { buffer_size_db: Uint, max_bitrate: u32, avg_bitrate: u32, - // dec_specific_info: (), // tag=DecSpecificInfoTag - // profile_level_indication_index_descr: (), + dec_specific_info: DecoderSpecificInfo, } impl Decode for DecoderConfigDescriptor { @@ -4177,6 +4176,7 @@ impl Decode for DecoderConfigDescriptor { let max_bitrate = u32::decode(&mut reader)?; let avg_bitrate = u32::decode(&mut reader)?; + let dec_specific_info = DecoderSpecificInfo::decode(&mut reader)?; Ok(Self { object_type_indication, stream_type, @@ -4184,10 +4184,78 @@ impl Decode for DecoderConfigDescriptor { buffer_size_db, max_bitrate, avg_bitrate, + dec_specific_info, }) } } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[allow(missing_docs)] +pub struct DecoderSpecificInfo { + pub payload: Vec, +} + +impl Decode for DecoderSpecificInfo { + fn decode(mut reader: R) -> Result { + let tag = u8::decode(&mut reader)?; + if tag != 5 { + // 5 = DecSpecificInfoTag + return Err(Error::invalid_data(&format!( + "Unexpected descriptor tag: expected=5, actual={tag}" + ))); + } + + // TODO: + let mut size = 0; + let mut has_next_byte = true; + while has_next_byte { + let b = u8::decode(&mut reader)?; + has_next_byte = Uint::::from_bits(b).get() == 1; + size = (size << 7) | Uint::::from_bits(b).get() as usize + } + + let mut payload = vec![0; size]; + reader.read_exact(&mut payload)?; + + Ok(Self { payload }) + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[allow(missing_docs)] +pub struct SlConfigDescriptor { + pub payload: Vec, +} + +impl Decode for SlConfigDescriptor { + fn decode(mut reader: R) -> Result { + let tag = u8::decode(&mut reader)?; + if tag != 6 { + // 6 = SLConfigDescrTag + return Err(Error::invalid_data(&format!( + "Unexpected descriptor tag: expected=6, actual={tag}" + ))); + } + + // TODO: + let mut size = 0; + let mut has_next_byte = true; + while has_next_byte { + let b = u8::decode(&mut reader)?; + has_next_byte = Uint::::from_bits(b).get() == 1; + size = (size << 7) | Uint::::from_bits(b).get() as usize + } + dbg!(size); + + // TODO: + let mut payload = vec![0; size]; + reader.read_exact(&mut payload)?; + dbg!(&payload); + + Ok(Self { payload }) + } +} + /// [ISO/IEC 14496-14] ESDBox class #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[allow(missing_docs)] @@ -4198,6 +4266,7 @@ pub struct EsdsBox { pub url_string: Option, pub ocr_es_id: Option, pub dec_config_descr: DecoderConfigDescriptor, + pub sl_config_descr: SlConfigDescriptor, } impl EsdsBox { @@ -4262,13 +4331,12 @@ impl EsdsBox { .transpose()?; let dec_config_descr = DecoderConfigDescriptor::decode(&mut reader)?; - + let sl_config_descr = SlConfigDescriptor::decode(&mut reader)?; dbg!(es_id); dbg!(stream_priority); dbg!(&url_string); dbg!(ocr_es_id); dbg!(&dec_config_descr); - // 残りのフィールドは必要になるまでは未対応 Ok(Self { es_id, @@ -4277,6 +4345,7 @@ impl EsdsBox { url_string, ocr_es_id, dec_config_descr, + sl_config_descr, }) } } From b1b0f9d22d933e5af0d66139c0b7629325681223 Mon Sep 17 00:00:00 2001 From: Takeru Ohta Date: Thu, 5 Dec 2024 14:44:33 +0900 Subject: [PATCH 09/16] Add descriptors module --- src/boxes.rs | 41 +++--------------------------------- src/descriptors.rs | 52 ++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 3 files changed, 56 insertions(+), 38 deletions(-) create mode 100644 src/descriptors.rs diff --git a/src/boxes.rs b/src/boxes.rs index 69e33d9..3362920 100644 --- a/src/boxes.rs +++ b/src/boxes.rs @@ -5,9 +5,9 @@ use std::{ }; use crate::{ - basic_types::as_box_object, io::ExternalBytes, BaseBox, BoxHeader, BoxSize, BoxType, Decode, - Either, Encode, Error, FixedPointNumber, FullBox, FullBoxFlags, FullBoxHeader, Mp4FileTime, - Result, Uint, Utf8String, + basic_types::as_box_object, descriptors::SlConfigDescriptor, io::ExternalBytes, BaseBox, + BoxHeader, BoxSize, BoxType, Decode, Either, Encode, Error, FixedPointNumber, FullBox, + FullBoxFlags, FullBoxHeader, Mp4FileTime, Result, Uint, Utf8String, }; /// ペイロードの解釈方法が不明なボックスを保持するための構造体 @@ -4221,41 +4221,6 @@ impl Decode for DecoderSpecificInfo { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -#[allow(missing_docs)] -pub struct SlConfigDescriptor { - pub payload: Vec, -} - -impl Decode for SlConfigDescriptor { - fn decode(mut reader: R) -> Result { - let tag = u8::decode(&mut reader)?; - if tag != 6 { - // 6 = SLConfigDescrTag - return Err(Error::invalid_data(&format!( - "Unexpected descriptor tag: expected=6, actual={tag}" - ))); - } - - // TODO: - let mut size = 0; - let mut has_next_byte = true; - while has_next_byte { - let b = u8::decode(&mut reader)?; - has_next_byte = Uint::::from_bits(b).get() == 1; - size = (size << 7) | Uint::::from_bits(b).get() as usize - } - dbg!(size); - - // TODO: - let mut payload = vec![0; size]; - reader.read_exact(&mut payload)?; - dbg!(&payload); - - Ok(Self { payload }) - } -} - /// [ISO/IEC 14496-14] ESDBox class #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[allow(missing_docs)] diff --git a/src/descriptors.rs b/src/descriptors.rs new file mode 100644 index 0000000..996dd9a --- /dev/null +++ b/src/descriptors.rs @@ -0,0 +1,52 @@ +//! ISO_IEC_14496-1 で定義されているディスクリプター群 +use std::io::Read; + +use crate::{Decode, Error, Result, Uint}; + +/// [ISO_IEC_14496-1] SLConfigDescriptor class +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[allow(missing_docs)] +pub struct SlConfigDescriptor; + +impl SlConfigDescriptor { + const TAG: u8 = 6; // SLConfigDescrTag +} + +impl Decode for SlConfigDescriptor { + fn decode(mut reader: R) -> Result { + let (tag, _size) = decode_tag_and_size(&mut reader)?; + if tag != Self::TAG { + return Err(Error::invalid_data(&format!( + "Unexpected descriptor tag: expected={}, actual={tag}", + Self::TAG + ))); + } + + let predefined = u8::decode(&mut reader)?; + if predefined != 2 { + // MP4 では 2 が主に使われていそうなので、いったんそれ以外は未対応にしておいて、 + // 必要に応じて随時対応を追加していく + return Err(Error::unsupported(&format!( + "Unsupported `SLConfigDescriptor.predefined` value: {predefined}" + ))); + } + + // predefined == 2 の場合には、追加の処理は不要 + + Ok(Self) + } +} + +fn decode_tag_and_size(mut reader: R) -> Result<(u8, usize)> { + let tag = u8::decode(&mut reader)?; + + let mut size = 0; + let mut has_next_byte = true; + while has_next_byte { + let b = u8::decode(&mut reader)?; + has_next_byte = Uint::::from_bits(b).get() == 1; + size = (size << 7) | Uint::::from_bits(b).get() as usize + } + + Ok((tag, size)) +} diff --git a/src/lib.rs b/src/lib.rs index 9d2b78d..247c5cd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,7 @@ pub mod aux; mod basic_types; pub mod boxes; +pub mod descriptors; mod io; pub use basic_types::{ From 4cef4b6f7335f64dad189e9f9b614e5cfaf6671d Mon Sep 17 00:00:00 2001 From: Takeru Ohta Date: Thu, 5 Dec 2024 15:00:22 +0900 Subject: [PATCH 10/16] Add SlConfigDescriptor --- src/descriptors.rs | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/src/descriptors.rs b/src/descriptors.rs index 996dd9a..fd0491f 100644 --- a/src/descriptors.rs +++ b/src/descriptors.rs @@ -1,7 +1,7 @@ //! ISO_IEC_14496-1 で定義されているディスクリプター群 -use std::io::Read; +use std::io::{Read, Write}; -use crate::{Decode, Error, Result, Uint}; +use crate::{Decode, Encode, Error, Result, Uint}; /// [ISO_IEC_14496-1] SLConfigDescriptor class #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -37,6 +37,18 @@ impl Decode for SlConfigDescriptor { } } +impl Encode for SlConfigDescriptor { + fn encode(&self, mut writer: W) -> Result<()> { + let predefined = 2; + let payload = [predefined]; + + encode_tag_and_size(&mut writer, Self::TAG, payload.len())?; + writer.write_all(&payload)?; + + Ok(()) + } +} + fn decode_tag_and_size(mut reader: R) -> Result<(u8, usize)> { let tag = u8::decode(&mut reader)?; @@ -50,3 +62,23 @@ fn decode_tag_and_size(mut reader: R) -> Result<(u8, usize)> { Ok((tag, size)) } + +fn encode_tag_and_size(mut writer: W, tag: u8, mut size: usize) -> Result<()> { + writer.write_all(&[tag])?; + + loop { + let mut b = (size & 0b0111_1111) as u8; + size >>= 7; + + if size != 0 { + b |= 0b1000_0000; + } + writer.write_all(&[b])?; + + if size == 0 { + break; + } + } + + Ok(()) +} From e9168d0ec6d44b0fb470657de0295f16c9fa4931 Mon Sep 17 00:00:00 2001 From: Takeru Ohta Date: Thu, 5 Dec 2024 15:03:53 +0900 Subject: [PATCH 11/16] Add DecoderSpecificInfo --- src/boxes.rs | 38 ++++---------------------------------- src/descriptors.rs | 37 ++++++++++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 35 deletions(-) diff --git a/src/boxes.rs b/src/boxes.rs index 3362920..0c91a3e 100644 --- a/src/boxes.rs +++ b/src/boxes.rs @@ -5,8 +5,10 @@ use std::{ }; use crate::{ - basic_types::as_box_object, descriptors::SlConfigDescriptor, io::ExternalBytes, BaseBox, - BoxHeader, BoxSize, BoxType, Decode, Either, Encode, Error, FixedPointNumber, FullBox, + basic_types::as_box_object, + descriptors::{DecoderSpecificInfo, SlConfigDescriptor}, + io::ExternalBytes, + BaseBox, BoxHeader, BoxSize, BoxType, Decode, Either, Encode, Error, FixedPointNumber, FullBox, FullBoxFlags, FullBoxHeader, Mp4FileTime, Result, Uint, Utf8String, }; @@ -4189,38 +4191,6 @@ impl Decode for DecoderConfigDescriptor { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -#[allow(missing_docs)] -pub struct DecoderSpecificInfo { - pub payload: Vec, -} - -impl Decode for DecoderSpecificInfo { - fn decode(mut reader: R) -> Result { - let tag = u8::decode(&mut reader)?; - if tag != 5 { - // 5 = DecSpecificInfoTag - return Err(Error::invalid_data(&format!( - "Unexpected descriptor tag: expected=5, actual={tag}" - ))); - } - - // TODO: - let mut size = 0; - let mut has_next_byte = true; - while has_next_byte { - let b = u8::decode(&mut reader)?; - has_next_byte = Uint::::from_bits(b).get() == 1; - size = (size << 7) | Uint::::from_bits(b).get() as usize - } - - let mut payload = vec![0; size]; - reader.read_exact(&mut payload)?; - - Ok(Self { payload }) - } -} - /// [ISO/IEC 14496-14] ESDBox class #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[allow(missing_docs)] diff --git a/src/descriptors.rs b/src/descriptors.rs index fd0491f..d09cbae 100644 --- a/src/descriptors.rs +++ b/src/descriptors.rs @@ -3,9 +3,44 @@ use std::io::{Read, Write}; use crate::{Decode, Encode, Error, Result, Uint}; -/// [ISO_IEC_14496-1] SLConfigDescriptor class +/// [ISO_IEC_14496-1] DecoderSpecificInfo class #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[allow(missing_docs)] +pub struct DecoderSpecificInfo { + pub payload: Vec, +} + +impl DecoderSpecificInfo { + const TAG: u8 = 5; // DecSpecificInfoTag +} + +impl Decode for DecoderSpecificInfo { + fn decode(mut reader: R) -> Result { + let (tag, size) = decode_tag_and_size(&mut reader)?; + if tag != Self::TAG { + return Err(Error::invalid_data(&format!( + "Unexpected descriptor tag: expected={}, actual={tag}", + Self::TAG + ))); + } + + let mut payload = vec![0; size]; + reader.read_exact(&mut payload)?; + + Ok(Self { payload }) + } +} + +impl Encode for DecoderSpecificInfo { + fn encode(&self, mut writer: W) -> Result<()> { + encode_tag_and_size(&mut writer, Self::TAG, self.payload.len())?; + writer.write_all(&self.payload)?; + Ok(()) + } +} + +/// [ISO_IEC_14496-1] SLConfigDescriptor class +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct SlConfigDescriptor; impl SlConfigDescriptor { From a517d3fa9b1fabac0f12b148694757b1eea1ff40 Mon Sep 17 00:00:00 2001 From: Takeru Ohta Date: Thu, 5 Dec 2024 15:23:16 +0900 Subject: [PATCH 12/16] Add DecoderConfigDescriptor --- src/boxes.rs | 60 +-------------------------------------- src/descriptors.rs | 71 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 59 deletions(-) diff --git a/src/boxes.rs b/src/boxes.rs index 0c91a3e..16f7f7c 100644 --- a/src/boxes.rs +++ b/src/boxes.rs @@ -6,7 +6,7 @@ use std::{ use crate::{ basic_types::as_box_object, - descriptors::{DecoderSpecificInfo, SlConfigDescriptor}, + descriptors::{DecoderConfigDescriptor, SlConfigDescriptor}, io::ExternalBytes, BaseBox, BoxHeader, BoxSize, BoxType, Decode, Either, Encode, Error, FixedPointNumber, FullBox, FullBoxFlags, FullBoxHeader, Mp4FileTime, Result, Uint, Utf8String, @@ -4133,64 +4133,6 @@ impl BaseBox for DopsBox { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -#[allow(missing_docs)] -pub struct DecoderConfigDescriptor { - object_type_indication: u8, - stream_type: Uint, - up_stream: Uint, - buffer_size_db: Uint, - max_bitrate: u32, - avg_bitrate: u32, - dec_specific_info: DecoderSpecificInfo, -} - -impl Decode for DecoderConfigDescriptor { - fn decode(mut reader: R) -> Result { - let tag = u8::decode(&mut reader)?; - if tag != 4 { - // 4 = DecoderConfigDescrTag - return Err(Error::invalid_data(&format!( - "Unexpected descriptor tag: expected=4, actual={tag}" - ))); - } - - // TODO: - let mut size = 0; - let mut has_next_byte = true; - while has_next_byte { - let b = u8::decode(&mut reader)?; - has_next_byte = Uint::::from_bits(b).get() == 1; - size = (size << 7) | Uint::::from_bits(b).get() as usize - } - dbg!(size); - - let object_type_indication = u8::decode(&mut reader)?; - - let b = u8::decode(&mut reader)?; - let stream_type = Uint::from_bits(b); - let up_stream = Uint::from_bits(b); - - let mut buf = [0; 4]; - reader.read_exact(&mut buf[1..])?; - let buffer_size_db = Uint::from_bits(u32::from_be_bytes(buf)); - - let max_bitrate = u32::decode(&mut reader)?; - let avg_bitrate = u32::decode(&mut reader)?; - - let dec_specific_info = DecoderSpecificInfo::decode(&mut reader)?; - Ok(Self { - object_type_indication, - stream_type, - up_stream, - buffer_size_db, - max_bitrate, - avg_bitrate, - dec_specific_info, - }) - } -} - /// [ISO/IEC 14496-14] ESDBox class #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[allow(missing_docs)] diff --git a/src/descriptors.rs b/src/descriptors.rs index d09cbae..df52ca2 100644 --- a/src/descriptors.rs +++ b/src/descriptors.rs @@ -3,6 +3,77 @@ use std::io::{Read, Write}; use crate::{Decode, Encode, Error, Result, Uint}; +/// [ISO_IEC_14496-1] DecoderConfigDescriptor class +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[allow(missing_docs)] +pub struct DecoderConfigDescriptor { + pub object_type_indication: u8, + pub stream_type: Uint, + pub up_stream: Uint, + pub buffer_size_db: Uint, + pub max_bitrate: u32, + pub avg_bitrate: u32, + pub dec_specific_info: DecoderSpecificInfo, +} + +impl DecoderConfigDescriptor { + const TAG: u8 = 4; // DecoderConfigDescrTag +} + +impl Decode for DecoderConfigDescriptor { + fn decode(mut reader: R) -> Result { + let (tag, _size) = decode_tag_and_size(&mut reader)?; + if tag != Self::TAG { + return Err(Error::invalid_data(&format!( + "Unexpected descriptor tag: expected={}, actual={tag}", + Self::TAG + ))); + } + + let object_type_indication = u8::decode(&mut reader)?; + + let b = u8::decode(&mut reader)?; + let stream_type = Uint::from_bits(b); + let up_stream = Uint::from_bits(b); + + let mut buf = [0; 4]; + reader.read_exact(&mut buf[1..])?; + let buffer_size_db = Uint::from_bits(u32::from_be_bytes(buf)); + + let max_bitrate = u32::decode(&mut reader)?; + let avg_bitrate = u32::decode(&mut reader)?; + + let dec_specific_info = DecoderSpecificInfo::decode(&mut reader)?; + Ok(Self { + object_type_indication, + stream_type, + up_stream, + buffer_size_db, + max_bitrate, + avg_bitrate, + dec_specific_info, + }) + } +} + +impl Encode for DecoderConfigDescriptor { + fn encode(&self, mut writer: W) -> Result<()> { + let mut payload = Vec::new(); + + self.object_type_indication.encode(&mut payload)?; + (self.stream_type.to_bits() | self.up_stream.to_bits()).encode(&mut payload)?; + writer.write_all(&self.buffer_size_db.to_bits().to_be_bytes()[1..])?; + self.max_bitrate.encode(&mut writer)?; + self.avg_bitrate.encode(&mut writer)?; + self.dec_specific_info.encode(&mut writer)?; + + encode_tag_and_size(&mut writer, Self::TAG, payload.len())?; + writer.write_all(&payload)?; + + Ok(()) + } +} + /// [ISO_IEC_14496-1] DecoderSpecificInfo class #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[allow(missing_docs)] From 507b5bd0125f50a2f849b4346e880bd5b6e99e31 Mon Sep 17 00:00:00 2001 From: Takeru Ohta Date: Thu, 5 Dec 2024 15:40:38 +0900 Subject: [PATCH 13/16] Add EsDescriptor --- src/boxes.rs | 88 ++++--------------------------------- src/descriptors.rs | 105 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 109 insertions(+), 84 deletions(-) diff --git a/src/boxes.rs b/src/boxes.rs index 16f7f7c..891652d 100644 --- a/src/boxes.rs +++ b/src/boxes.rs @@ -5,11 +5,9 @@ use std::{ }; use crate::{ - basic_types::as_box_object, - descriptors::{DecoderConfigDescriptor, SlConfigDescriptor}, - io::ExternalBytes, - BaseBox, BoxHeader, BoxSize, BoxType, Decode, Either, Encode, Error, FixedPointNumber, FullBox, - FullBoxFlags, FullBoxHeader, Mp4FileTime, Result, Uint, Utf8String, + basic_types::as_box_object, descriptors::EsDescriptor, io::ExternalBytes, BaseBox, BoxHeader, + BoxSize, BoxType, Decode, Either, Encode, Error, FixedPointNumber, FullBox, FullBoxFlags, + FullBoxHeader, Mp4FileTime, Result, Uint, Utf8String, }; /// ペイロードの解釈方法が不明なボックスを保持するための構造体 @@ -4137,13 +4135,7 @@ impl BaseBox for DopsBox { #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[allow(missing_docs)] pub struct EsdsBox { - pub es_id: u16, - pub stream_priority: Uint, - pub depends_on_es_id: Option, - pub url_string: Option, - pub ocr_es_id: Option, - pub dec_config_descr: DecoderConfigDescriptor, - pub sl_config_descr: SlConfigDescriptor, + pub es: EsDescriptor, } impl EsdsBox { @@ -4152,78 +4144,14 @@ impl EsdsBox { fn encode_payload(&self, mut writer: W) -> Result<()> { FullBoxHeader::from_box(self).encode(&mut writer)?; - - // Ok(()) - todo!() + self.es.encode(&mut writer)?; + Ok(()) } fn decode_payload(mut reader: &mut std::io::Take) -> Result { let _ = FullBoxHeader::decode(&mut reader)?; - let tag = u8::decode(&mut reader)?; - if tag != 3 { - // 3 = ES_DescrTag - return Err(Error::invalid_data(&format!( - "Unexpected descriptor tag: expected=3, actual={tag}" - ))); - } - - // TODO: - let mut size = 0; - let mut has_next_byte = true; - while has_next_byte { - let b = u8::decode(&mut reader)?; - has_next_byte = Uint::::from_bits(b).get() == 1; - size = (size << 7) | Uint::::from_bits(b).get() as usize - } - if size != reader.limit() as usize { - return Err(Error::invalid_data(&format!( - "Unexpected descriptor size: expected={}, actual={size}", - reader.limit() - ))); - } - - let es_id = u16::decode(&mut reader)?; - - let b = u8::decode(&mut reader)?; - let stream_dependence_flag: Uint = Uint::from_bits(b); - let url_flag: Uint = Uint::from_bits(b); - let ocr_stream_flag: Uint = Uint::from_bits(b); - let stream_priority = Uint::from_bits(b); - - let depends_on_es_id = (stream_dependence_flag.get() == 1) - .then(|| u16::decode(&mut reader)) - .transpose()?; - - let url_string = if url_flag.get() == 1 { - let len = u8::decode(&mut reader)? as u64; - let mut s = String::new(); - reader.take(len).read_to_string(&mut s)?; - Some(s) - } else { - None - }; - - let ocr_es_id = (ocr_stream_flag.get() == 1) - .then(|| u16::decode(&mut reader)) - .transpose()?; - - let dec_config_descr = DecoderConfigDescriptor::decode(&mut reader)?; - let sl_config_descr = SlConfigDescriptor::decode(&mut reader)?; - dbg!(es_id); - dbg!(stream_priority); - dbg!(&url_string); - dbg!(ocr_es_id); - dbg!(&dec_config_descr); - - Ok(Self { - es_id, - stream_priority, - depends_on_es_id, - url_string, - ocr_es_id, - dec_config_descr, - sl_config_descr, - }) + let es = EsDescriptor::decode(&mut reader)?; + Ok(Self { es }) } } diff --git a/src/descriptors.rs b/src/descriptors.rs index df52ca2..58ff785 100644 --- a/src/descriptors.rs +++ b/src/descriptors.rs @@ -3,6 +3,103 @@ use std::io::{Read, Write}; use crate::{Decode, Encode, Error, Result, Uint}; +/// [ISO_IEC_14496-1] ES_Descriptor class +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[allow(missing_docs)] +pub struct EsDescriptor { + pub es_id: u16, + pub stream_priority: Uint, + pub depends_on_es_id: Option, + pub url_string: Option, + pub ocr_es_id: Option, + pub dec_config_descr: DecoderConfigDescriptor, + pub sl_config_descr: SlConfigDescriptor, +} + +impl EsDescriptor { + const TAG: u8 = 3; // ES_DescrTag +} + +impl Decode for EsDescriptor { + fn decode(mut reader: R) -> Result { + let (tag, _size) = decode_tag_and_size(&mut reader)?; + if tag != Self::TAG { + return Err(Error::invalid_data(&format!( + "Unexpected descriptor tag: expected={}, actual={tag}", + Self::TAG + ))); + } + + let es_id = u16::decode(&mut reader)?; + + let b = u8::decode(&mut reader)?; + let stream_dependence_flag: Uint = Uint::from_bits(b); + let url_flag: Uint = Uint::from_bits(b); + let ocr_stream_flag: Uint = Uint::from_bits(b); + let stream_priority = Uint::from_bits(b); + + let depends_on_es_id = (stream_dependence_flag.get() == 1) + .then(|| u16::decode(&mut reader)) + .transpose()?; + + let url_string = if url_flag.get() == 1 { + let len = u8::decode(&mut reader)? as u64; + let mut s = String::new(); + (&mut reader).take(len).read_to_string(&mut s)?; + Some(s) + } else { + None + }; + + let ocr_es_id = (ocr_stream_flag.get() == 1) + .then(|| u16::decode(&mut reader)) + .transpose()?; + + let dec_config_descr = DecoderConfigDescriptor::decode(&mut reader)?; + let sl_config_descr = SlConfigDescriptor::decode(&mut reader)?; + + Ok(Self { + es_id, + stream_priority, + depends_on_es_id, + url_string, + ocr_es_id, + dec_config_descr, + sl_config_descr, + }) + } +} + +impl Encode for EsDescriptor { + fn encode(&self, mut writer: W) -> Result<()> { + let mut payload = Vec::new(); + + self.es_id.encode(&mut payload)?; + (Uint::::new(self.depends_on_es_id.is_some() as u8).to_bits() + | Uint::::new(self.url_string.is_some() as u8).to_bits() + | Uint::::new(self.ocr_es_id.is_some() as u8).to_bits() + | self.stream_priority.to_bits()) + .encode(&mut payload)?; + if let Some(v) = self.depends_on_es_id { + v.encode(&mut payload)?; + } + if let Some(v) = &self.url_string { + (v.len() as u8).encode(&mut payload)?; + payload.write_all(v.as_bytes())?; + } + if let Some(v) = self.ocr_es_id { + v.encode(&mut payload)?; + } + self.dec_config_descr.encode(&mut payload)?; + self.sl_config_descr.encode(&mut payload)?; + + encode_tag_and_size(&mut writer, Self::TAG, payload.len())?; + writer.write_all(&payload)?; + + Ok(()) + } +} + /// [ISO_IEC_14496-1] DecoderConfigDescriptor class #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[allow(missing_docs)] @@ -62,10 +159,10 @@ impl Encode for DecoderConfigDescriptor { self.object_type_indication.encode(&mut payload)?; (self.stream_type.to_bits() | self.up_stream.to_bits()).encode(&mut payload)?; - writer.write_all(&self.buffer_size_db.to_bits().to_be_bytes()[1..])?; - self.max_bitrate.encode(&mut writer)?; - self.avg_bitrate.encode(&mut writer)?; - self.dec_specific_info.encode(&mut writer)?; + payload.write_all(&self.buffer_size_db.to_bits().to_be_bytes()[1..])?; + self.max_bitrate.encode(&mut payload)?; + self.avg_bitrate.encode(&mut payload)?; + self.dec_specific_info.encode(&mut payload)?; encode_tag_and_size(&mut writer, Self::TAG, payload.len())?; writer.write_all(&payload)?; From 8ea281a53ee16dc0aa22043982089ec5e19c0dae Mon Sep 17 00:00:00 2001 From: Takeru Ohta Date: Thu, 5 Dec 2024 16:05:47 +0900 Subject: [PATCH 14/16] Update test case --- tests/decode_encode_test.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/decode_encode_test.rs b/tests/decode_encode_test.rs index b756c45..a25d23a 100644 --- a/tests/decode_encode_test.rs +++ b/tests/decode_encode_test.rs @@ -141,8 +141,14 @@ fn decode_encode_beep_opus_audio_aac() -> Result<()> { assert_eq!(file, encoded_file); // エンコード結果のバイト列が正しいことを確認する。 - assert_eq!(input_bytes.len(), output_bytes.len()); - assert_eq!(&input_bytes[..], output_bytes); + // + // [NOTE] + // descriptor のサイズのエンコード形式は可変長だが、 + // ffmpeg で生成したテストファイルでは常に 4 バイト使われていた。 + // そのため、decode / encode を通すとバイト列の中身が変わってしまうので、 + // ここでは調整したサイズ (+ 12 部分)で比較している。 + // またバイト列の厳密な一致チェックはこのテストケースでは行わないようにした。 + assert_eq!(input_bytes.len(), output_bytes.len() + 12); Ok(()) } From 2a299fbcf85cc45f9b4002849866b605b6ef5314 Mon Sep 17 00:00:00 2001 From: Takeru Ohta Date: Thu, 5 Dec 2024 16:10:15 +0900 Subject: [PATCH 15/16] Update CHANGES.md --- CHANGES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index b921763..fdbda3d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,6 +11,8 @@ ## develop +- [ADD] AAC 用のボックスを追加する + - @sile - [UPDATE] `ChunkAccessor` と `SampleAccessor` の一部のメソッドのライフタイム制約が必要以上に厳しかったのを緩くする - @sile From 0dd67299f471d93bb29c76b3be986cc6e717448e Mon Sep 17 00:00:00 2001 From: Takeru Ohta Date: Thu, 5 Dec 2024 16:28:29 +0900 Subject: [PATCH 16/16] =?UTF-8?q?=E3=83=90=E3=83=BC=E3=82=B8=E3=83=A7?= =?UTF-8?q?=E3=83=B3=E3=82=92=202024.4.0=20=E3=81=AB=E4=B8=8A=E3=81=92?= =?UTF-8?q?=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGES.md | 2 ++ Cargo.lock | 72 +++++++++++++++++++++++++++--------------------------- Cargo.toml | 2 +- 3 files changed, 39 insertions(+), 37 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index fdbda3d..edf043f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,6 +11,8 @@ ## develop +## 2024.4.0 + - [ADD] AAC 用のボックスを追加する - @sile - [UPDATE] `ChunkAccessor` と `SampleAccessor` の一部のメソッドのライフタイム制約が必要以上に厳しかったのを緩くする diff --git a/Cargo.lock b/Cargo.lock index b6390b4..bc9224a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "autocfg" @@ -19,9 +19,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -34,9 +34,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -44,15 +44,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -61,15 +61,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", @@ -78,21 +78,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -108,9 +108,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "memchr" @@ -129,9 +129,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -141,9 +141,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -165,18 +165,18 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "serde" -version = "1.0.210" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", @@ -185,9 +185,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", "memchr", @@ -197,7 +197,7 @@ dependencies = [ [[package]] name = "shiguredo_mp4" -version = "2024.3.0" +version = "2024.4.0" [[package]] name = "slab" @@ -210,9 +210,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.77" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -232,6 +232,6 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" diff --git a/Cargo.toml b/Cargo.toml index 20136dd..705debd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "shiguredo_mp4" -version = "2024.3.0" +version = "2024.4.0" edition = "2021" authors = ["Shiguredo Inc."] license = "Apache-2.0"