shiguredo_mp4/
boxes.rs

1//! ボックス群
2use core::num::{NonZeroU16, NonZeroU32};
3
4#[cfg(not(feature = "std"))]
5use alloc::{boxed::Box, format, vec::Vec};
6
7use crate::{
8    BaseBox, BoxHeader, BoxSize, BoxType, Decode, Either, Encode, Error, FixedPointNumber, FullBox,
9    FullBoxFlags, FullBoxHeader, Mp4FileTime, Result, Uint, Utf8String, basic_types::as_box_object,
10    descriptors::EsDescriptor,
11};
12
13/// ペイロードの解釈方法が不明なボックスを保持するための構造体
14///
15/// ペイロードは単なるバイト列として扱われる
16#[derive(Debug, Clone, PartialEq, Eq, Hash)]
17pub struct UnknownBox {
18    /// ボックス種別
19    pub box_type: BoxType,
20
21    /// ボックスサイズ
22    pub box_size: BoxSize,
23
24    /// ペイロード
25    pub payload: Vec<u8>,
26}
27
28impl Encode for UnknownBox {
29    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
30        let mut offset = BoxHeader::new(self.box_type, self.box_size).encode(buf)?;
31        offset += self.payload.encode(&mut buf[offset..])?;
32        Ok(offset)
33    }
34}
35
36impl Decode for UnknownBox {
37    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
38        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
39        Ok((
40            Self {
41                box_type: header.box_type,
42                box_size: header.box_size,
43                payload: payload.to_vec(),
44            },
45            header.external_size() + payload.len(),
46        ))
47    }
48}
49
50impl BaseBox for UnknownBox {
51    fn box_type(&self) -> BoxType {
52        self.box_type
53    }
54
55    fn is_unknown_box(&self) -> bool {
56        true
57    }
58
59    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
60        Box::new(core::iter::empty())
61    }
62}
63
64/// [`FtypBox`] で使われるブランド定義
65///
66/// ブランドは、対象の MP4 ファイルを読み込んで処理する際に必要となる要件(登場する可能性があるボックス群やハンドリングすべきフラグなど)を指定する
67#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
68pub struct Brand([u8; 4]);
69
70impl Brand {
71    /// [ISO/IEC 14496-12] `isom` ブランド
72    pub const ISOM: Self = Self::new(*b"isom");
73
74    /// [ISO/IEC 14496-12] `avc1` ブランド
75    pub const AVC1: Self = Self::new(*b"avc1");
76
77    /// [ISO/IEC 14496-12] `iso2` ブランド
78    pub const ISO2: Self = Self::new(*b"iso2");
79
80    /// [ISO/IEC 14496-12] `mp71` ブランド
81    pub const MP71: Self = Self::new(*b"mp71");
82
83    /// [ISO/IEC 14496-12] `iso3` ブランド
84    pub const ISO3: Self = Self::new(*b"iso3");
85
86    /// [ISO/IEC 14496-12] `iso4` ブランド
87    pub const ISO4: Self = Self::new(*b"iso4");
88
89    /// [ISO/IEC 14496-12] `iso5` ブランド
90    pub const ISO5: Self = Self::new(*b"iso5");
91
92    /// [ISO/IEC 14496-12] `iso6` ブランド
93    pub const ISO6: Self = Self::new(*b"iso6");
94
95    /// [ISO/IEC 14496-12] `iso7` ブランド
96    pub const ISO7: Self = Self::new(*b"iso7");
97
98    /// [ISO/IEC 14496-12] `iso8` ブランド
99    pub const ISO8: Self = Self::new(*b"iso8");
100
101    /// [ISO/IEC 14496-12] `iso9` ブランド
102    pub const ISO9: Self = Self::new(*b"iso9");
103
104    /// [ISO/IEC 14496-12] `isoa` ブランド
105    pub const ISOA: Self = Self::new(*b"isoa");
106
107    /// [ISO/IEC 14496-12] `isob` ブランド
108    pub const ISOB: Self = Self::new(*b"isob");
109
110    /// [ISO/IEC 14496-12] `relo` ブランド
111    pub const RELO: Self = Self::new(*b"relo");
112
113    /// [ISO/IEC 14496-14] `mp41` ブランド
114    pub const MP41: Self = Self::new(*b"mp41");
115
116    /// [<https://aomediacodec.github.io/av1-isobmff/>] `av01` ブランド
117    pub const AV01: Self = Self::new(*b"av01");
118
119    /// バイト列を渡して、対応するブランドを作成する
120    pub const fn new(brand: [u8; 4]) -> Self {
121        Self(brand)
122    }
123
124    /// このブランドを表すバイト列を取得する
125    pub const fn get(self) -> [u8; 4] {
126        self.0
127    }
128}
129
130impl core::fmt::Debug for Brand {
131    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
132        if let Ok(s) = core::str::from_utf8(&self.0) {
133            f.debug_tuple("Brand").field(&s).finish()
134        } else {
135            f.debug_tuple("Brand").field(&self.0).finish()
136        }
137    }
138}
139
140impl Encode for Brand {
141    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
142        self.0.encode(buf)
143    }
144}
145
146impl Decode for Brand {
147    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
148        let (bytes, offset) = <[u8; 4]>::decode(buf)?;
149        Ok((Self(bytes), offset))
150    }
151}
152
153/// [ISO/IEC 14496-12] FileTypeBox class
154#[derive(Debug, Clone, PartialEq, Eq, Hash)]
155#[allow(missing_docs)]
156pub struct FtypBox {
157    pub major_brand: Brand,
158    pub minor_version: u32,
159    pub compatible_brands: Vec<Brand>,
160}
161
162impl FtypBox {
163    /// ボックス種別
164    pub const TYPE: BoxType = BoxType::Normal(*b"ftyp");
165}
166
167impl Encode for FtypBox {
168    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
169        let header = BoxHeader::new_variable_size(Self::TYPE);
170        let mut offset = header.encode(buf)?;
171        offset += self.major_brand.encode(&mut buf[offset..])?;
172        offset += self.minor_version.encode(&mut buf[offset..])?;
173        for brand in &self.compatible_brands {
174            offset += brand.encode(&mut buf[offset..])?;
175        }
176        header.finalize_box_size(&mut buf[..offset])?;
177        Ok(offset)
178    }
179}
180
181impl Decode for FtypBox {
182    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
183        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
184        header.box_type.expect(Self::TYPE)?;
185
186        let mut offset = 0;
187        let major_brand = Brand::decode_at(payload, &mut offset)?;
188        let minor_version = u32::decode_at(payload, &mut offset)?;
189
190        let mut compatible_brands = Vec::new();
191        while offset < payload.len() {
192            compatible_brands.push(Brand::decode_at(payload, &mut offset)?);
193        }
194
195        Ok((
196            Self {
197                major_brand,
198                minor_version,
199                compatible_brands,
200            },
201            header.external_size() + payload.len(),
202        ))
203    }
204}
205
206impl BaseBox for FtypBox {
207    fn box_type(&self) -> BoxType {
208        Self::TYPE
209    }
210
211    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
212        Box::new(core::iter::empty())
213    }
214}
215
216/// [`Mp4File`](crate::Mp4File) のトップレベルに位置するボックス群のデフォルト実装
217#[derive(Debug, Clone, PartialEq, Eq, Hash)]
218#[allow(missing_docs)]
219pub enum RootBox {
220    Free(FreeBox),
221    Mdat(MdatBox),
222    Moov(MoovBox),
223    Unknown(UnknownBox),
224}
225
226impl RootBox {
227    fn inner_box(&self) -> &dyn BaseBox {
228        match self {
229            RootBox::Free(b) => b,
230            RootBox::Mdat(b) => b,
231            RootBox::Moov(b) => b,
232            RootBox::Unknown(b) => b,
233        }
234    }
235}
236
237impl Encode for RootBox {
238    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
239        match self {
240            RootBox::Free(b) => b.encode(buf),
241            RootBox::Mdat(b) => b.encode(buf),
242            RootBox::Moov(b) => b.encode(buf),
243            RootBox::Unknown(b) => b.encode(buf),
244        }
245    }
246}
247
248impl Decode for RootBox {
249    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
250        let (header, _header_size) = BoxHeader::decode(buf)?;
251        match header.box_type {
252            FreeBox::TYPE => FreeBox::decode(buf).map(|(b, n)| (RootBox::Free(b), n)),
253            MdatBox::TYPE => MdatBox::decode(buf).map(|(b, n)| (RootBox::Mdat(b), n)),
254            MoovBox::TYPE => MoovBox::decode(buf).map(|(b, n)| (RootBox::Moov(b), n)),
255            _ => UnknownBox::decode(buf).map(|(b, n)| (RootBox::Unknown(b), n)),
256        }
257    }
258}
259
260impl BaseBox for RootBox {
261    fn box_type(&self) -> BoxType {
262        self.inner_box().box_type()
263    }
264
265    fn is_unknown_box(&self) -> bool {
266        self.inner_box().is_unknown_box()
267    }
268
269    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
270        self.inner_box().children()
271    }
272}
273
274/// [ISO/IEC 14496-12] FreeSpaceBox class
275#[derive(Debug, Clone, PartialEq, Eq, Hash)]
276#[allow(missing_docs)]
277pub struct FreeBox {
278    pub payload: Vec<u8>,
279}
280
281impl FreeBox {
282    /// ボックス種別
283    pub const TYPE: BoxType = BoxType::Normal(*b"free");
284}
285
286impl Encode for FreeBox {
287    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
288        let box_size = BoxSize::with_payload_size(Self::TYPE, self.payload.len() as u64);
289        let mut offset = BoxHeader::new(Self::TYPE, box_size).encode(buf)?;
290        offset += self.payload.encode(&mut buf[offset..])?;
291        Ok(offset)
292    }
293}
294
295impl Decode for FreeBox {
296    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
297        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
298        header.box_type.expect(Self::TYPE)?;
299
300        Ok((
301            Self {
302                payload: payload.to_vec(),
303            },
304            header.external_size() + payload.len(),
305        ))
306    }
307}
308
309impl BaseBox for FreeBox {
310    fn box_type(&self) -> BoxType {
311        Self::TYPE
312    }
313
314    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
315        Box::new(core::iter::empty())
316    }
317}
318
319/// [ISO/IEC 14496-12] MediaDataBox class
320///
321/// # NOTE
322///
323/// 可変長ペイロードを表現したい場合には、この構造体ではなく [`BoxHeader`] を直接使用する必要がある
324#[derive(Debug, Clone, PartialEq, Eq, Hash)]
325pub struct MdatBox {
326    /// ペイロード
327    pub payload: Vec<u8>,
328}
329
330impl MdatBox {
331    /// ボックス種別
332    pub const TYPE: BoxType = BoxType::Normal(*b"mdat");
333}
334
335impl Encode for MdatBox {
336    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
337        let box_size = BoxSize::with_payload_size(Self::TYPE, self.payload.len() as u64);
338        let mut offset = BoxHeader::new(Self::TYPE, box_size).encode(buf)?;
339        offset += self.payload.encode(&mut buf[offset..])?;
340        Ok(offset)
341    }
342}
343
344impl Decode for MdatBox {
345    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
346        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
347        header.box_type.expect(Self::TYPE)?;
348
349        Ok((
350            Self {
351                payload: payload.to_vec(),
352            },
353            header.external_size() + payload.len(),
354        ))
355    }
356}
357
358impl BaseBox for MdatBox {
359    fn box_type(&self) -> BoxType {
360        Self::TYPE
361    }
362
363    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
364        Box::new(core::iter::empty())
365    }
366}
367
368/// [ISO/IEC 14496-12] MovieBox class
369#[derive(Debug, Clone, PartialEq, Eq, Hash)]
370#[allow(missing_docs)]
371pub struct MoovBox {
372    pub mvhd_box: MvhdBox,
373    pub trak_boxes: Vec<TrakBox>,
374    pub unknown_boxes: Vec<UnknownBox>,
375}
376
377impl MoovBox {
378    /// ボックス種別
379    pub const TYPE: BoxType = BoxType::Normal(*b"moov");
380}
381
382impl Encode for MoovBox {
383    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
384        let header = BoxHeader::new_variable_size(Self::TYPE);
385        let mut offset = header.encode(buf)?;
386        offset += self.mvhd_box.encode(&mut buf[offset..])?;
387        for b in &self.trak_boxes {
388            offset += b.encode(&mut buf[offset..])?;
389        }
390        for b in &self.unknown_boxes {
391            offset += b.encode(&mut buf[offset..])?;
392        }
393        header.finalize_box_size(&mut buf[..offset])?;
394        Ok(offset)
395    }
396}
397
398impl Decode for MoovBox {
399    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
400        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
401        header.box_type.expect(Self::TYPE)?;
402
403        let mut offset = 0;
404        let mut mvhd_box = None;
405        let mut trak_boxes = Vec::new();
406        let mut unknown_boxes = Vec::new();
407
408        while offset < payload.len() {
409            let (child_header, _) = BoxHeader::decode(&payload[offset..])?;
410            match child_header.box_type {
411                MvhdBox::TYPE if mvhd_box.is_none() => {
412                    mvhd_box = Some(MvhdBox::decode_at(payload, &mut offset)?);
413                }
414                TrakBox::TYPE => {
415                    trak_boxes.push(TrakBox::decode_at(payload, &mut offset)?);
416                }
417                _ => {
418                    unknown_boxes.push(UnknownBox::decode_at(payload, &mut offset)?);
419                }
420            }
421        }
422
423        Ok((
424            Self {
425                mvhd_box: check_mandatory_box(mvhd_box, "mvhd", "moov")?,
426                trak_boxes,
427                unknown_boxes,
428            },
429            header.external_size() + payload.len(),
430        ))
431    }
432}
433
434impl BaseBox for MoovBox {
435    fn box_type(&self) -> BoxType {
436        Self::TYPE
437    }
438
439    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
440        Box::new(
441            core::iter::empty()
442                .chain(core::iter::once(&self.mvhd_box).map(as_box_object))
443                .chain(self.trak_boxes.iter().map(as_box_object))
444                .chain(self.unknown_boxes.iter().map(as_box_object)),
445        )
446    }
447}
448
449/// [ISO/IEC 14496-12] MovieHeaderBox class (親: [`MoovBox`])
450#[derive(Debug, Clone, PartialEq, Eq, Hash)]
451#[allow(missing_docs)]
452pub struct MvhdBox {
453    pub creation_time: Mp4FileTime,
454    pub modification_time: Mp4FileTime,
455    pub timescale: NonZeroU32,
456    pub duration: u64,
457    pub rate: FixedPointNumber<i16, u16>,
458    pub volume: FixedPointNumber<i8, u8>,
459    pub matrix: [i32; 9],
460    pub next_track_id: u32,
461}
462
463impl MvhdBox {
464    /// ボックス種別
465    pub const TYPE: BoxType = BoxType::Normal(*b"mvhd");
466
467    /// [`MvhdBox::rate`] のデフォルト値(通常の再生速度)
468    pub const DEFAULT_RATE: FixedPointNumber<i16, u16> = FixedPointNumber::new(1, 0);
469
470    /// [`MvhdBox::volume`] のデフォルト値(最大音量)
471    pub const DEFAULT_VOLUME: FixedPointNumber<i8, u8> = FixedPointNumber::new(1, 0);
472
473    /// [`MvhdBox::matrix`] のデフォルト値
474    pub const DEFAULT_MATRIX: [i32; 9] = [0x00010000, 0, 0, 0, 0x00010000, 0, 0, 0, 0x40000000];
475}
476
477impl Encode for MvhdBox {
478    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
479        let header = BoxHeader::new_variable_size(Self::TYPE);
480        let mut offset = header.encode(buf)?;
481        offset += FullBoxHeader::from_box(self).encode(&mut buf[offset..])?;
482        if self.full_box_version() == 1 {
483            offset += self.creation_time.as_secs().encode(&mut buf[offset..])?;
484            offset += self
485                .modification_time
486                .as_secs()
487                .encode(&mut buf[offset..])?;
488            offset += self.timescale.encode(&mut buf[offset..])?;
489            offset += self.duration.encode(&mut buf[offset..])?;
490        } else {
491            offset += (self.creation_time.as_secs() as u32).encode(&mut buf[offset..])?;
492            offset += (self.modification_time.as_secs() as u32).encode(&mut buf[offset..])?;
493            offset += self.timescale.encode(&mut buf[offset..])?;
494            offset += (self.duration as u32).encode(&mut buf[offset..])?;
495        }
496        offset += self.rate.encode(&mut buf[offset..])?;
497        offset += self.volume.encode(&mut buf[offset..])?;
498        offset += [0u8; 2 + 4 * 2].encode(&mut buf[offset..])?;
499        offset += self.matrix.encode(&mut buf[offset..])?;
500        offset += [0u8; 4 * 6].encode(&mut buf[offset..])?;
501        offset += self.next_track_id.encode(&mut buf[offset..])?;
502        header.finalize_box_size(&mut buf[..offset])?;
503        Ok(offset)
504    }
505}
506
507impl Decode for MvhdBox {
508    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
509        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
510        header.box_type.expect(Self::TYPE)?;
511
512        let mut offset = 0;
513        let full_header = FullBoxHeader::decode_at(payload, &mut offset)?;
514
515        let mut this = Self {
516            creation_time: Mp4FileTime::default(),
517            modification_time: Mp4FileTime::default(),
518            timescale: NonZeroU32::MIN,
519            duration: 0,
520            rate: Self::DEFAULT_RATE,
521            volume: Self::DEFAULT_VOLUME,
522            matrix: Self::DEFAULT_MATRIX,
523            next_track_id: 0,
524        };
525
526        if full_header.version == 1 {
527            this.creation_time =
528                u64::decode_at(payload, &mut offset).map(Mp4FileTime::from_secs)?;
529            this.modification_time =
530                u64::decode_at(payload, &mut offset).map(Mp4FileTime::from_secs)?;
531            this.timescale = NonZeroU32::decode_at(payload, &mut offset)?;
532            this.duration = u64::decode_at(payload, &mut offset)?;
533        } else {
534            this.creation_time =
535                u32::decode_at(payload, &mut offset).map(|v| Mp4FileTime::from_secs(v as u64))?;
536            this.modification_time =
537                u32::decode_at(payload, &mut offset).map(|v| Mp4FileTime::from_secs(v as u64))?;
538            this.timescale = NonZeroU32::decode_at(payload, &mut offset)?;
539            this.duration = u32::decode_at(payload, &mut offset).map(|v| v as u64)?;
540        }
541
542        this.rate = FixedPointNumber::decode_at(payload, &mut offset)?;
543        this.volume = FixedPointNumber::decode_at(payload, &mut offset)?;
544        let _ = <[u8; 2 + 4 * 2]>::decode_at(payload, &mut offset)?;
545        this.matrix = <[i32; 9]>::decode_at(payload, &mut offset)?;
546        let _ = <[u8; 4 * 6]>::decode_at(payload, &mut offset)?;
547        this.next_track_id = u32::decode_at(payload, &mut offset)?;
548
549        Ok((this, header.external_size() + payload.len()))
550    }
551}
552
553impl BaseBox for MvhdBox {
554    fn box_type(&self) -> BoxType {
555        Self::TYPE
556    }
557
558    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
559        Box::new(core::iter::empty())
560    }
561}
562
563impl FullBox for MvhdBox {
564    fn full_box_version(&self) -> u8 {
565        if self.creation_time.as_secs() > u32::MAX as u64
566            || self.modification_time.as_secs() > u32::MAX as u64
567            || self.duration > u32::MAX as u64
568        {
569            1
570        } else {
571            0
572        }
573    }
574
575    fn full_box_flags(&self) -> FullBoxFlags {
576        FullBoxFlags::new(0)
577    }
578}
579
580/// [ISO/IEC 14496-12] TrackBox class (親: [`MoovBox`])
581#[derive(Debug, Clone, PartialEq, Eq, Hash)]
582#[allow(missing_docs)]
583pub struct TrakBox {
584    pub tkhd_box: TkhdBox,
585    pub edts_box: Option<EdtsBox>,
586    pub mdia_box: MdiaBox,
587    pub unknown_boxes: Vec<UnknownBox>,
588}
589
590impl TrakBox {
591    /// ボックス種別
592    pub const TYPE: BoxType = BoxType::Normal(*b"trak");
593}
594
595impl Encode for TrakBox {
596    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
597        let header = BoxHeader::new_variable_size(Self::TYPE);
598        let mut offset = header.encode(buf)?;
599        offset += self.tkhd_box.encode(&mut buf[offset..])?;
600        if let Some(b) = &self.edts_box {
601            offset += b.encode(&mut buf[offset..])?;
602        }
603        offset += self.mdia_box.encode(&mut buf[offset..])?;
604        for b in &self.unknown_boxes {
605            offset += b.encode(&mut buf[offset..])?;
606        }
607        header.finalize_box_size(&mut buf[..offset])?;
608        Ok(offset)
609    }
610}
611
612impl Decode for TrakBox {
613    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
614        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
615        header.box_type.expect(Self::TYPE)?;
616
617        let mut offset = 0;
618        let mut tkhd_box = None;
619        let mut edts_box = None;
620        let mut mdia_box = None;
621        let mut unknown_boxes = Vec::new();
622
623        while offset < payload.len() {
624            let (child_header, _) = BoxHeader::decode(&payload[offset..])?;
625            match child_header.box_type {
626                TkhdBox::TYPE if tkhd_box.is_none() => {
627                    tkhd_box = Some(TkhdBox::decode_at(payload, &mut offset)?);
628                }
629                EdtsBox::TYPE if edts_box.is_none() => {
630                    edts_box = Some(EdtsBox::decode_at(payload, &mut offset)?);
631                }
632                MdiaBox::TYPE if mdia_box.is_none() => {
633                    mdia_box = Some(MdiaBox::decode_at(payload, &mut offset)?);
634                }
635                _ => {
636                    unknown_boxes.push(UnknownBox::decode_at(payload, &mut offset)?);
637                }
638            }
639        }
640
641        Ok((
642            Self {
643                tkhd_box: check_mandatory_box(tkhd_box, "tkhd", "trak")?,
644                edts_box,
645                mdia_box: check_mandatory_box(mdia_box, "mdia", "trak")?,
646                unknown_boxes,
647            },
648            header.external_size() + payload.len(),
649        ))
650    }
651}
652
653impl BaseBox for TrakBox {
654    fn box_type(&self) -> BoxType {
655        Self::TYPE
656    }
657
658    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
659        Box::new(
660            core::iter::empty()
661                .chain(core::iter::once(&self.tkhd_box).map(as_box_object))
662                .chain(self.edts_box.iter().map(as_box_object))
663                .chain(core::iter::once(&self.mdia_box).map(as_box_object))
664                .chain(self.unknown_boxes.iter().map(as_box_object)),
665        )
666    }
667}
668
669/// [ISO/IEC 14496-12] TrackHeaderBox class (親: [`TrakBox`])
670#[derive(Debug, Clone, PartialEq, Eq, Hash)]
671#[allow(missing_docs)]
672pub struct TkhdBox {
673    pub flag_track_enabled: bool,
674    pub flag_track_in_movie: bool,
675    pub flag_track_in_preview: bool,
676    pub flag_track_size_is_aspect_ratio: bool,
677
678    pub creation_time: Mp4FileTime,
679    pub modification_time: Mp4FileTime,
680    pub track_id: u32,
681    pub duration: u64,
682    pub layer: i16,
683    pub alternate_group: i16,
684    pub volume: FixedPointNumber<i8, u8>,
685    pub matrix: [i32; 9],
686    pub width: FixedPointNumber<i16, u16>,
687    pub height: FixedPointNumber<i16, u16>,
688}
689
690impl TkhdBox {
691    /// ボックス種別
692    pub const TYPE: BoxType = BoxType::Normal(*b"tkhd");
693
694    /// [`TkhdBox::layer`] のデフォルト値
695    pub const DEFAULT_LAYER: i16 = 0;
696
697    /// [`TkhdBox::alternate_group`] のデフォルト値
698    pub const DEFAULT_ALTERNATE_GROUP: i16 = 0;
699
700    /// 音声用の [`TkhdBox::volume`] のデフォルト値(最大音量)
701    pub const DEFAULT_AUDIO_VOLUME: FixedPointNumber<i8, u8> = FixedPointNumber::new(1, 0);
702
703    /// 映像用の [`TkhdBox::volume`] のデフォルト値(無音)
704    pub const DEFAULT_VIDEO_VOLUME: FixedPointNumber<i8, u8> = FixedPointNumber::new(0, 0);
705
706    /// [`TkhdBox::matrix`] のデフォルト値
707    pub const DEFAULT_MATRIX: [i32; 9] = [0x00010000, 0, 0, 0, 0x00010000, 0, 0, 0, 0x40000000];
708}
709
710impl Encode for TkhdBox {
711    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
712        let header = BoxHeader::new_variable_size(Self::TYPE);
713        let mut offset = header.encode(buf)?;
714        offset += FullBoxHeader::from_box(self).encode(&mut buf[offset..])?;
715        if self.full_box_version() == 1 {
716            offset += self.creation_time.as_secs().encode(&mut buf[offset..])?;
717            offset += self
718                .modification_time
719                .as_secs()
720                .encode(&mut buf[offset..])?;
721            offset += self.track_id.encode(&mut buf[offset..])?;
722            offset += [0u8; 4].encode(&mut buf[offset..])?;
723            offset += self.duration.encode(&mut buf[offset..])?;
724        } else {
725            offset += (self.creation_time.as_secs() as u32).encode(&mut buf[offset..])?;
726            offset += (self.modification_time.as_secs() as u32).encode(&mut buf[offset..])?;
727            offset += self.track_id.encode(&mut buf[offset..])?;
728            offset += [0u8; 4].encode(&mut buf[offset..])?;
729            offset += (self.duration as u32).encode(&mut buf[offset..])?;
730        }
731        offset += [0u8; 4 * 2].encode(&mut buf[offset..])?;
732        offset += self.layer.encode(&mut buf[offset..])?;
733        offset += self.alternate_group.encode(&mut buf[offset..])?;
734        offset += self.volume.encode(&mut buf[offset..])?;
735        offset += [0u8; 2].encode(&mut buf[offset..])?;
736        offset += self.matrix.encode(&mut buf[offset..])?;
737        offset += self.width.encode(&mut buf[offset..])?;
738        offset += self.height.encode(&mut buf[offset..])?;
739        header.finalize_box_size(&mut buf[..offset])?;
740        Ok(offset)
741    }
742}
743
744impl Decode for TkhdBox {
745    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
746        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
747        header.box_type.expect(Self::TYPE)?;
748
749        let mut offset = 0;
750        let full_header = FullBoxHeader::decode_at(payload, &mut offset)?;
751
752        let mut this = Self {
753            flag_track_enabled: false,
754            flag_track_in_movie: false,
755            flag_track_in_preview: false,
756            flag_track_size_is_aspect_ratio: false,
757            creation_time: Mp4FileTime::default(),
758            modification_time: Mp4FileTime::default(),
759            track_id: 0,
760            duration: 0,
761            layer: Self::DEFAULT_LAYER,
762            alternate_group: Self::DEFAULT_ALTERNATE_GROUP,
763            volume: Self::DEFAULT_AUDIO_VOLUME,
764            matrix: Self::DEFAULT_MATRIX,
765            width: FixedPointNumber::new(0, 0),
766            height: FixedPointNumber::new(0, 0),
767        };
768
769        this.flag_track_enabled = full_header.flags.is_set(0);
770        this.flag_track_in_movie = full_header.flags.is_set(1);
771        this.flag_track_in_preview = full_header.flags.is_set(2);
772        this.flag_track_size_is_aspect_ratio = full_header.flags.is_set(3);
773
774        if full_header.version == 1 {
775            this.creation_time =
776                u64::decode_at(payload, &mut offset).map(Mp4FileTime::from_secs)?;
777            this.modification_time =
778                u64::decode_at(payload, &mut offset).map(Mp4FileTime::from_secs)?;
779            this.track_id = u32::decode_at(payload, &mut offset)?;
780            let _ = <[u8; 4]>::decode_at(payload, &mut offset)?;
781            this.duration = u64::decode_at(payload, &mut offset)?;
782        } else {
783            this.creation_time =
784                u32::decode_at(payload, &mut offset).map(|v| Mp4FileTime::from_secs(v as u64))?;
785            this.modification_time =
786                u32::decode_at(payload, &mut offset).map(|v| Mp4FileTime::from_secs(v as u64))?;
787            this.track_id = u32::decode_at(payload, &mut offset)?;
788            let _ = <[u8; 4]>::decode_at(payload, &mut offset)?;
789            this.duration = u32::decode_at(payload, &mut offset).map(|v| v as u64)?;
790        }
791
792        let _ = <[u8; 4 * 2]>::decode_at(payload, &mut offset)?;
793        this.layer = i16::decode_at(payload, &mut offset)?;
794        this.alternate_group = i16::decode_at(payload, &mut offset)?;
795        this.volume = FixedPointNumber::decode_at(payload, &mut offset)?;
796        let _ = <[u8; 2]>::decode_at(payload, &mut offset)?;
797        this.matrix = <[i32; 9]>::decode_at(payload, &mut offset)?;
798        this.width = FixedPointNumber::decode_at(payload, &mut offset)?;
799        this.height = FixedPointNumber::decode_at(payload, &mut offset)?;
800
801        Ok((this, header.external_size() + payload.len()))
802    }
803}
804
805impl BaseBox for TkhdBox {
806    fn box_type(&self) -> BoxType {
807        Self::TYPE
808    }
809
810    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
811        Box::new(core::iter::empty())
812    }
813}
814
815impl FullBox for TkhdBox {
816    fn full_box_version(&self) -> u8 {
817        if self.creation_time.as_secs() > u32::MAX as u64
818            || self.modification_time.as_secs() > u32::MAX as u64
819            || self.duration > u32::MAX as u64
820        {
821            1
822        } else {
823            0
824        }
825    }
826
827    fn full_box_flags(&self) -> FullBoxFlags {
828        FullBoxFlags::from_flags([
829            (0, self.flag_track_enabled),
830            (1, self.flag_track_in_movie),
831            (2, self.flag_track_in_preview),
832            (3, self.flag_track_size_is_aspect_ratio),
833        ])
834    }
835}
836
837/// [ISO/IEC 14496-12] EditBox class (親: [`TrakBox`])
838#[derive(Debug, Clone, PartialEq, Eq, Hash)]
839#[allow(missing_docs)]
840pub struct EdtsBox {
841    pub elst_box: Option<ElstBox>,
842    pub unknown_boxes: Vec<UnknownBox>,
843}
844
845impl EdtsBox {
846    /// ボックス種別
847    pub const TYPE: BoxType = BoxType::Normal(*b"edts");
848}
849
850impl Encode for EdtsBox {
851    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
852        let header = BoxHeader::new_variable_size(Self::TYPE);
853        let mut offset = header.encode(buf)?;
854        if let Some(b) = &self.elst_box {
855            offset += b.encode(&mut buf[offset..])?;
856        }
857        for b in &self.unknown_boxes {
858            offset += b.encode(&mut buf[offset..])?;
859        }
860        header.finalize_box_size(&mut buf[..offset])?;
861        Ok(offset)
862    }
863}
864
865impl Decode for EdtsBox {
866    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
867        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
868        header.box_type.expect(Self::TYPE)?;
869
870        let mut offset = 0;
871        let mut elst_box = None;
872        let mut unknown_boxes = Vec::new();
873
874        while offset < payload.len() {
875            let (child_header, _) = BoxHeader::decode(&payload[offset..])?;
876            match child_header.box_type {
877                ElstBox::TYPE if elst_box.is_none() => {
878                    elst_box = Some(ElstBox::decode_at(payload, &mut offset)?);
879                }
880                _ => {
881                    unknown_boxes.push(UnknownBox::decode_at(payload, &mut offset)?);
882                }
883            }
884        }
885
886        Ok((
887            Self {
888                elst_box,
889                unknown_boxes,
890            },
891            header.external_size() + payload.len(),
892        ))
893    }
894}
895
896impl BaseBox for EdtsBox {
897    fn box_type(&self) -> BoxType {
898        Self::TYPE
899    }
900
901    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
902        Box::new(
903            core::iter::empty()
904                .chain(self.elst_box.iter().map(as_box_object))
905                .chain(self.unknown_boxes.iter().map(as_box_object)),
906        )
907    }
908}
909
910/// [`ElstBox`] に含まれるエントリー
911#[derive(Debug, Clone, PartialEq, Eq, Hash)]
912#[allow(missing_docs)]
913pub struct ElstEntry {
914    pub edit_duration: u64,
915    pub media_time: i64,
916    pub media_rate: FixedPointNumber<i16, i16>,
917}
918
919/// [ISO/IEC 14496-12] EditListBox class (親: [`EdtsBox`])
920#[derive(Debug, Clone, PartialEq, Eq, Hash)]
921#[allow(missing_docs)]
922pub struct ElstBox {
923    pub entries: Vec<ElstEntry>,
924}
925
926impl ElstBox {
927    /// ボックス種別
928    pub const TYPE: BoxType = BoxType::Normal(*b"elst");
929}
930
931impl Encode for ElstBox {
932    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
933        let header = BoxHeader::new_variable_size(Self::TYPE);
934        let mut offset = header.encode(buf)?;
935        offset += FullBoxHeader::from_box(self).encode(&mut buf[offset..])?;
936
937        let version = self.full_box_version();
938        offset += (self.entries.len() as u32).encode(&mut buf[offset..])?;
939        for entry in &self.entries {
940            if version == 1 {
941                offset += entry.edit_duration.encode(&mut buf[offset..])?;
942                offset += entry.media_time.encode(&mut buf[offset..])?;
943            } else {
944                offset += (entry.edit_duration as u32).encode(&mut buf[offset..])?;
945                offset += (entry.media_time as i32).encode(&mut buf[offset..])?;
946            }
947            offset += entry.media_rate.encode(&mut buf[offset..])?;
948        }
949        header.finalize_box_size(&mut buf[..offset])?;
950        Ok(offset)
951    }
952}
953
954impl Decode for ElstBox {
955    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
956        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
957        header.box_type.expect(Self::TYPE)?;
958
959        let mut offset = 0;
960        let full_header = FullBoxHeader::decode_at(payload, &mut offset)?;
961
962        let mut entries = Vec::new();
963        let count = u32::decode_at(payload, &mut offset)?;
964        for _ in 0..count {
965            let edit_duration;
966            let media_time;
967            if full_header.version == 1 {
968                edit_duration = u64::decode_at(payload, &mut offset)?;
969                media_time = i64::decode_at(payload, &mut offset)?;
970            } else {
971                edit_duration = u32::decode_at(payload, &mut offset)? as u64;
972                media_time = i32::decode_at(payload, &mut offset)? as i64;
973            }
974            let media_rate = FixedPointNumber::decode_at(payload, &mut offset)?;
975            entries.push(ElstEntry {
976                edit_duration,
977                media_time,
978                media_rate,
979            });
980        }
981
982        Ok((Self { entries }, header.external_size() + payload.len()))
983    }
984}
985
986impl BaseBox for ElstBox {
987    fn box_type(&self) -> BoxType {
988        Self::TYPE
989    }
990
991    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
992        Box::new(core::iter::empty())
993    }
994}
995
996impl FullBox for ElstBox {
997    fn full_box_version(&self) -> u8 {
998        let large = self.entries.iter().any(|x| {
999            u32::try_from(x.edit_duration).is_err() || i32::try_from(x.media_time).is_err()
1000        });
1001        if large { 1 } else { 0 }
1002    }
1003
1004    fn full_box_flags(&self) -> FullBoxFlags {
1005        FullBoxFlags::new(0)
1006    }
1007}
1008
1009/// [ISO/IEC 14496-12] MediaBox class (親: [`TrakBox`])
1010#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1011#[allow(missing_docs)]
1012pub struct MdiaBox {
1013    pub mdhd_box: MdhdBox,
1014    pub hdlr_box: HdlrBox,
1015    pub minf_box: MinfBox,
1016    pub unknown_boxes: Vec<UnknownBox>,
1017}
1018
1019impl MdiaBox {
1020    /// ボックス種別
1021    pub const TYPE: BoxType = BoxType::Normal(*b"mdia");
1022}
1023
1024impl Encode for MdiaBox {
1025    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
1026        let header = BoxHeader::new_variable_size(Self::TYPE);
1027        let mut offset = header.encode(buf)?;
1028        offset += self.mdhd_box.encode(&mut buf[offset..])?;
1029        offset += self.hdlr_box.encode(&mut buf[offset..])?;
1030        offset += self.minf_box.encode(&mut buf[offset..])?;
1031        for b in &self.unknown_boxes {
1032            offset += b.encode(&mut buf[offset..])?;
1033        }
1034        header.finalize_box_size(&mut buf[..offset])?;
1035        Ok(offset)
1036    }
1037}
1038
1039impl Decode for MdiaBox {
1040    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
1041        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
1042        header.box_type.expect(Self::TYPE)?;
1043
1044        let mut offset = 0;
1045        let mut mdhd_box = None;
1046        let mut hdlr_box = None;
1047        let mut minf_box = None;
1048        let mut unknown_boxes = Vec::new();
1049
1050        while offset < payload.len() {
1051            let (child_header, _) = BoxHeader::decode(&payload[offset..])?;
1052            match child_header.box_type {
1053                MdhdBox::TYPE if mdhd_box.is_none() => {
1054                    mdhd_box = Some(MdhdBox::decode_at(payload, &mut offset)?);
1055                }
1056                HdlrBox::TYPE if hdlr_box.is_none() => {
1057                    hdlr_box = Some(HdlrBox::decode_at(payload, &mut offset)?);
1058                }
1059                MinfBox::TYPE if minf_box.is_none() => {
1060                    minf_box = Some(MinfBox::decode_at(payload, &mut offset)?);
1061                }
1062                _ => {
1063                    unknown_boxes.push(UnknownBox::decode_at(payload, &mut offset)?);
1064                }
1065            }
1066        }
1067
1068        Ok((
1069            Self {
1070                mdhd_box: check_mandatory_box(mdhd_box, "mdhd", "mdia")?,
1071                hdlr_box: check_mandatory_box(hdlr_box, "hdlr", "mdia")?,
1072                minf_box: check_mandatory_box(minf_box, "minf", "mdia")?,
1073                unknown_boxes,
1074            },
1075            header.external_size() + payload.len(),
1076        ))
1077    }
1078}
1079
1080impl BaseBox for MdiaBox {
1081    fn box_type(&self) -> BoxType {
1082        Self::TYPE
1083    }
1084
1085    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
1086        Box::new(
1087            core::iter::empty()
1088                .chain(core::iter::once(&self.mdhd_box).map(as_box_object))
1089                .chain(core::iter::once(&self.hdlr_box).map(as_box_object))
1090                .chain(core::iter::once(&self.minf_box).map(as_box_object))
1091                .chain(self.unknown_boxes.iter().map(as_box_object)),
1092        )
1093    }
1094}
1095
1096/// [ISO/IEC 14496-12] MediaHeaderBox class (親: [`MdiaBox`])
1097#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1098#[allow(missing_docs)]
1099pub struct MdhdBox {
1100    pub creation_time: Mp4FileTime,
1101    pub modification_time: Mp4FileTime,
1102    pub timescale: NonZeroU32,
1103    pub duration: u64,
1104
1105    /// ISO-639-2/T language code
1106    pub language: [u8; 3],
1107}
1108
1109impl MdhdBox {
1110    /// ボックス種別
1111    pub const TYPE: BoxType = BoxType::Normal(*b"mdhd");
1112
1113    /// 未定義を表す言語コード
1114    pub const LANGUAGE_UNDEFINED: [u8; 3] = *b"und";
1115}
1116
1117impl Encode for MdhdBox {
1118    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
1119        let header = BoxHeader::new_variable_size(Self::TYPE);
1120        let mut offset = header.encode(buf)?;
1121        offset += FullBoxHeader::from_box(self).encode(&mut buf[offset..])?;
1122        if self.full_box_version() == 1 {
1123            offset += self.creation_time.as_secs().encode(&mut buf[offset..])?;
1124            offset += self
1125                .modification_time
1126                .as_secs()
1127                .encode(&mut buf[offset..])?;
1128            offset += self.timescale.encode(&mut buf[offset..])?;
1129            offset += self.duration.encode(&mut buf[offset..])?;
1130        } else {
1131            offset += (self.creation_time.as_secs() as u32).encode(&mut buf[offset..])?;
1132            offset += (self.modification_time.as_secs() as u32).encode(&mut buf[offset..])?;
1133            offset += self.timescale.encode(&mut buf[offset..])?;
1134            offset += (self.duration as u32).encode(&mut buf[offset..])?;
1135        }
1136
1137        let mut language: u16 = 0;
1138        for l in &self.language {
1139            let Some(code) = l.checked_sub(0x60) else {
1140                return Err(Error::invalid_input(format!(
1141                    "Invalid language code: {:?}",
1142                    self.language
1143                )));
1144            };
1145            language = (language << 5) | code as u16;
1146        }
1147        offset += language.encode(&mut buf[offset..])?;
1148        offset += [0u8; 2].encode(&mut buf[offset..])?;
1149        header.finalize_box_size(&mut buf[..offset])?;
1150        Ok(offset)
1151    }
1152}
1153
1154impl Decode for MdhdBox {
1155    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
1156        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
1157        header.box_type.expect(Self::TYPE)?;
1158
1159        let mut offset = 0;
1160        let full_header = FullBoxHeader::decode_at(payload, &mut offset)?;
1161
1162        let mut this = Self {
1163            creation_time: Mp4FileTime::default(),
1164            modification_time: Mp4FileTime::default(),
1165            timescale: NonZeroU32::MIN,
1166            duration: 0,
1167            language: Self::LANGUAGE_UNDEFINED,
1168        };
1169
1170        if full_header.version == 1 {
1171            this.creation_time =
1172                u64::decode_at(payload, &mut offset).map(Mp4FileTime::from_secs)?;
1173            this.modification_time =
1174                u64::decode_at(payload, &mut offset).map(Mp4FileTime::from_secs)?;
1175            this.timescale = NonZeroU32::decode_at(payload, &mut offset)?;
1176            this.duration = u64::decode_at(payload, &mut offset)?;
1177        } else {
1178            this.creation_time =
1179                u32::decode_at(payload, &mut offset).map(|v| Mp4FileTime::from_secs(v as u64))?;
1180            this.modification_time =
1181                u32::decode_at(payload, &mut offset).map(|v| Mp4FileTime::from_secs(v as u64))?;
1182            this.timescale = NonZeroU32::decode_at(payload, &mut offset)?;
1183            this.duration = u32::decode_at(payload, &mut offset).map(|v| v as u64)?;
1184        }
1185
1186        let language = u16::decode_at(payload, &mut offset)?;
1187        this.language = [
1188            ((language >> 10) & 0b11111) as u8 + 0x60,
1189            ((language >> 5) & 0b11111) as u8 + 0x60,
1190            (language & 0b11111) as u8 + 0x60,
1191        ];
1192
1193        let _ = <[u8; 2]>::decode_at(payload, &mut offset)?;
1194
1195        Ok((this, header.external_size() + payload.len()))
1196    }
1197}
1198
1199impl BaseBox for MdhdBox {
1200    fn box_type(&self) -> BoxType {
1201        Self::TYPE
1202    }
1203
1204    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
1205        Box::new(core::iter::empty())
1206    }
1207}
1208
1209impl FullBox for MdhdBox {
1210    fn full_box_version(&self) -> u8 {
1211        if self.creation_time.as_secs() > u32::MAX as u64
1212            || self.modification_time.as_secs() > u32::MAX as u64
1213            || self.duration > u32::MAX as u64
1214        {
1215            1
1216        } else {
1217            0
1218        }
1219    }
1220
1221    fn full_box_flags(&self) -> FullBoxFlags {
1222        FullBoxFlags::new(0)
1223    }
1224}
1225
1226/// [ISO/IEC 14496-12] HandlerBox class (親: [`MdiaBox`])
1227#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1228#[allow(missing_docs)]
1229pub struct HdlrBox {
1230    pub handler_type: [u8; 4],
1231
1232    /// ハンドラ名
1233    ///
1234    /// ISO の仕様書上はここは [`Utf8String`] であるべきだが、
1235    /// 中身が UTF-8 ではなかったり、
1236    /// null 終端文字列ではなく先頭にサイズバイトを格納する形式で
1237    /// MP4 ファイルを作成する実装が普通に存在するため、
1238    /// ここでは単なるバイト列として扱っている
1239    pub name: Vec<u8>,
1240}
1241
1242impl HdlrBox {
1243    /// ボックス種別
1244    pub const TYPE: BoxType = BoxType::Normal(*b"hdlr");
1245
1246    /// 音声用のハンドラー種別
1247    pub const HANDLER_TYPE_SOUN: [u8; 4] = *b"soun";
1248
1249    /// 映像用のハンドラー種別
1250    pub const HANDLER_TYPE_VIDE: [u8; 4] = *b"vide";
1251}
1252
1253impl Encode for HdlrBox {
1254    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
1255        let header = BoxHeader::new_variable_size(Self::TYPE);
1256        let mut offset = header.encode(buf)?;
1257        offset += FullBoxHeader::from_box(self).encode(&mut buf[offset..])?;
1258        offset += [0u8; 4].encode(&mut buf[offset..])?;
1259        offset += self.handler_type.encode(&mut buf[offset..])?;
1260        offset += [0u8; 4 * 3].encode(&mut buf[offset..])?;
1261        offset += self.name.encode(&mut buf[offset..])?;
1262        header.finalize_box_size(&mut buf[..offset])?;
1263        Ok(offset)
1264    }
1265}
1266
1267impl Decode for HdlrBox {
1268    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
1269        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
1270        header.box_type.expect(Self::TYPE)?;
1271
1272        let mut offset = 0;
1273        let _full_header = FullBoxHeader::decode_at(payload, &mut offset)?;
1274        let _ = <[u8; 4]>::decode_at(payload, &mut offset)?;
1275        let handler_type = <[u8; 4]>::decode_at(payload, &mut offset)?;
1276        let _ = <[u8; 4 * 3]>::decode_at(payload, &mut offset)?;
1277        let name = payload[offset..].to_vec();
1278
1279        Ok((
1280            Self { handler_type, name },
1281            header.external_size() + payload.len(),
1282        ))
1283    }
1284}
1285
1286impl BaseBox for HdlrBox {
1287    fn box_type(&self) -> BoxType {
1288        Self::TYPE
1289    }
1290
1291    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
1292        Box::new(core::iter::empty())
1293    }
1294}
1295
1296impl FullBox for HdlrBox {
1297    fn full_box_version(&self) -> u8 {
1298        0
1299    }
1300
1301    fn full_box_flags(&self) -> FullBoxFlags {
1302        FullBoxFlags::new(0)
1303    }
1304}
1305
1306/// [ISO/IEC 14496-12] MediaInformationBox class (親: [`MdiaBox`])
1307#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1308#[allow(missing_docs)]
1309pub struct MinfBox {
1310    pub smhd_or_vmhd_box: Either<SmhdBox, VmhdBox>,
1311    pub dinf_box: DinfBox,
1312    pub stbl_box: StblBox,
1313    pub unknown_boxes: Vec<UnknownBox>,
1314}
1315
1316impl MinfBox {
1317    /// ボックス種別
1318    pub const TYPE: BoxType = BoxType::Normal(*b"minf");
1319}
1320
1321impl Encode for MinfBox {
1322    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
1323        let header = BoxHeader::new_variable_size(Self::TYPE);
1324        let mut offset = header.encode(buf)?;
1325        match &self.smhd_or_vmhd_box {
1326            Either::A(b) => offset += b.encode(&mut buf[offset..])?,
1327            Either::B(b) => offset += b.encode(&mut buf[offset..])?,
1328        }
1329        offset += self.dinf_box.encode(&mut buf[offset..])?;
1330        offset += self.stbl_box.encode(&mut buf[offset..])?;
1331        for b in &self.unknown_boxes {
1332            offset += b.encode(&mut buf[offset..])?;
1333        }
1334        header.finalize_box_size(&mut buf[..offset])?;
1335        Ok(offset)
1336    }
1337}
1338
1339impl Decode for MinfBox {
1340    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
1341        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
1342        header.box_type.expect(Self::TYPE)?;
1343
1344        let mut offset = 0;
1345        let mut smhd_box = None;
1346        let mut vmhd_box = None;
1347        let mut dinf_box = None;
1348        let mut stbl_box = None;
1349        let mut unknown_boxes = Vec::new();
1350
1351        while offset < payload.len() {
1352            let (child_header, _) = BoxHeader::decode(&payload[offset..])?;
1353            match child_header.box_type {
1354                SmhdBox::TYPE if smhd_box.is_none() => {
1355                    smhd_box = Some(SmhdBox::decode_at(payload, &mut offset)?);
1356                }
1357                VmhdBox::TYPE if vmhd_box.is_none() => {
1358                    vmhd_box = Some(VmhdBox::decode_at(payload, &mut offset)?);
1359                }
1360                DinfBox::TYPE if dinf_box.is_none() => {
1361                    dinf_box = Some(DinfBox::decode_at(payload, &mut offset)?);
1362                }
1363                StblBox::TYPE if stbl_box.is_none() => {
1364                    stbl_box = Some(StblBox::decode_at(payload, &mut offset)?);
1365                }
1366                _ => {
1367                    unknown_boxes.push(UnknownBox::decode_at(payload, &mut offset)?);
1368                }
1369            }
1370        }
1371
1372        Ok((
1373            Self {
1374                smhd_or_vmhd_box: {
1375                    let smhd = smhd_box.map(Either::A);
1376                    let vmhd = vmhd_box.map(Either::B);
1377                    check_mandatory_box(smhd.or(vmhd), "smhd' or 'vmhd", "box")?
1378                },
1379                dinf_box: check_mandatory_box(dinf_box, "dinf", "minf")?,
1380                stbl_box: check_mandatory_box(stbl_box, "stbl", "minf")?,
1381                unknown_boxes,
1382            },
1383            header.external_size() + payload.len(),
1384        ))
1385    }
1386}
1387
1388impl BaseBox for MinfBox {
1389    fn box_type(&self) -> BoxType {
1390        Self::TYPE
1391    }
1392
1393    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
1394        Box::new(
1395            core::iter::empty()
1396                .chain(core::iter::once(&self.smhd_or_vmhd_box).map(as_box_object))
1397                .chain(core::iter::once(&self.dinf_box).map(as_box_object))
1398                .chain(core::iter::once(&self.stbl_box).map(as_box_object))
1399                .chain(self.unknown_boxes.iter().map(as_box_object)),
1400        )
1401    }
1402}
1403
1404/// [ISO/IEC 14496-12] SoundMediaHeaderBox class (親: [`MinfBox`])
1405#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
1406#[allow(missing_docs)]
1407pub struct SmhdBox {
1408    pub balance: FixedPointNumber<u8, u8>,
1409}
1410
1411impl SmhdBox {
1412    /// ボックス種別
1413    pub const TYPE: BoxType = BoxType::Normal(*b"smhd");
1414
1415    /// [`SmhdBox::balance`] のデフォルト値(中央)
1416    pub const DEFAULT_BALANCE: FixedPointNumber<u8, u8> = FixedPointNumber::new(0, 0);
1417}
1418
1419impl Encode for SmhdBox {
1420    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
1421        let header = BoxHeader::new_variable_size(Self::TYPE);
1422        let mut offset = header.encode(buf)?;
1423        offset += FullBoxHeader::from_box(self).encode(&mut buf[offset..])?;
1424        offset += self.balance.encode(&mut buf[offset..])?;
1425        offset += [0u8; 2].encode(&mut buf[offset..])?;
1426        header.finalize_box_size(&mut buf[..offset])?;
1427        Ok(offset)
1428    }
1429}
1430
1431impl Decode for SmhdBox {
1432    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
1433        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
1434        header.box_type.expect(Self::TYPE)?;
1435
1436        let mut offset = 0;
1437        let _full_header = FullBoxHeader::decode_at(payload, &mut offset)?;
1438        let balance = FixedPointNumber::decode_at(payload, &mut offset)?;
1439        let _ = <[u8; 2]>::decode_at(payload, &mut offset)?;
1440
1441        Ok((Self { balance }, header.external_size() + payload.len()))
1442    }
1443}
1444
1445impl BaseBox for SmhdBox {
1446    fn box_type(&self) -> BoxType {
1447        Self::TYPE
1448    }
1449
1450    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
1451        Box::new(core::iter::empty())
1452    }
1453}
1454
1455impl FullBox for SmhdBox {
1456    fn full_box_version(&self) -> u8 {
1457        0
1458    }
1459
1460    fn full_box_flags(&self) -> FullBoxFlags {
1461        FullBoxFlags::new(0)
1462    }
1463}
1464
1465/// [ISO/IEC 14496-12] VideoMediaHeaderBox class (親: [`MinfBox`])
1466#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
1467#[allow(missing_docs)]
1468pub struct VmhdBox {
1469    pub graphicsmode: u16,
1470    pub opcolor: [u16; 3],
1471}
1472
1473impl VmhdBox {
1474    /// ボックス種別
1475    pub const TYPE: BoxType = BoxType::Normal(*b"vmhd");
1476
1477    /// [`Vmhd::graphicsmode`] のデフォルト値(コピー)
1478    pub const DEFAULT_GRAPHICSMODE: u16 = 0;
1479
1480    /// [`Vmhd::graphicsmode`] のデフォルト値
1481    pub const DEFAULT_OPCOLOR: [u16; 3] = [0, 0, 0];
1482}
1483
1484impl Encode for VmhdBox {
1485    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
1486        let header = BoxHeader::new_variable_size(Self::TYPE);
1487        let mut offset = header.encode(buf)?;
1488        offset += FullBoxHeader::from_box(self).encode(&mut buf[offset..])?;
1489        offset += self.graphicsmode.encode(&mut buf[offset..])?;
1490        offset += self.opcolor.encode(&mut buf[offset..])?;
1491        header.finalize_box_size(&mut buf[..offset])?;
1492        Ok(offset)
1493    }
1494}
1495
1496impl Decode for VmhdBox {
1497    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
1498        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
1499        header.box_type.expect(Self::TYPE)?;
1500
1501        let mut offset = 0;
1502        let full_header = FullBoxHeader::decode_at(payload, &mut offset)?;
1503        if full_header.flags.get() != 1 {
1504            return Err(Error::invalid_data(format!(
1505                "Unexpected FullBox header flags of 'vmhd' box: {}",
1506                full_header.flags.get()
1507            )));
1508        }
1509
1510        let graphicsmode = u16::decode_at(payload, &mut offset)?;
1511        let opcolor = <[u16; 3]>::decode_at(payload, &mut offset)?;
1512
1513        Ok((
1514            Self {
1515                graphicsmode,
1516                opcolor,
1517            },
1518            header.external_size() + payload.len(),
1519        ))
1520    }
1521}
1522
1523impl BaseBox for VmhdBox {
1524    fn box_type(&self) -> BoxType {
1525        Self::TYPE
1526    }
1527
1528    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
1529        Box::new(core::iter::empty())
1530    }
1531}
1532
1533impl FullBox for VmhdBox {
1534    fn full_box_version(&self) -> u8 {
1535        0
1536    }
1537
1538    fn full_box_flags(&self) -> FullBoxFlags {
1539        FullBoxFlags::new(1)
1540    }
1541}
1542
1543/// [ISO/IEC 14496-12] DataInformationBox class (親: [`MinfBox`])
1544#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1545#[allow(missing_docs)]
1546pub struct DinfBox {
1547    pub dref_box: DrefBox,
1548    pub unknown_boxes: Vec<UnknownBox>,
1549}
1550
1551impl DinfBox {
1552    /// ボックス種別
1553    pub const TYPE: BoxType = BoxType::Normal(*b"dinf");
1554
1555    /// メディアデータが同じファイル内に格納されていることを示す [`DinfBox`] の値
1556    pub const LOCAL_FILE: Self = Self {
1557        dref_box: DrefBox::LOCAL_FILE,
1558        unknown_boxes: Vec::new(),
1559    };
1560}
1561
1562impl Encode for DinfBox {
1563    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
1564        let header = BoxHeader::new_variable_size(Self::TYPE);
1565        let mut offset = header.encode(buf)?;
1566        offset += self.dref_box.encode(&mut buf[offset..])?;
1567        for b in &self.unknown_boxes {
1568            offset += b.encode(&mut buf[offset..])?;
1569        }
1570        header.finalize_box_size(&mut buf[..offset])?;
1571        Ok(offset)
1572    }
1573}
1574
1575impl Decode for DinfBox {
1576    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
1577        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
1578        header.box_type.expect(Self::TYPE)?;
1579
1580        let mut offset = 0;
1581        let mut dref_box = None;
1582        let mut unknown_boxes = Vec::new();
1583
1584        while offset < payload.len() {
1585            let (child_header, _) = BoxHeader::decode(&payload[offset..])?;
1586            match child_header.box_type {
1587                DrefBox::TYPE if dref_box.is_none() => {
1588                    dref_box = Some(DrefBox::decode_at(payload, &mut offset)?);
1589                }
1590                _ => {
1591                    unknown_boxes.push(UnknownBox::decode_at(payload, &mut offset)?);
1592                }
1593            }
1594        }
1595
1596        Ok((
1597            Self {
1598                dref_box: check_mandatory_box(dref_box, "dref", "dinf")?,
1599                unknown_boxes,
1600            },
1601            header.external_size() + payload.len(),
1602        ))
1603    }
1604}
1605
1606impl BaseBox for DinfBox {
1607    fn box_type(&self) -> BoxType {
1608        Self::TYPE
1609    }
1610
1611    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
1612        Box::new(
1613            core::iter::empty()
1614                .chain(core::iter::once(&self.dref_box).map(as_box_object))
1615                .chain(self.unknown_boxes.iter().map(as_box_object)),
1616        )
1617    }
1618}
1619
1620/// [ISO/IEC 14496-12] DataReferenceBox class (親: [`DinfBox`])
1621#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1622#[allow(missing_docs)]
1623pub struct DrefBox {
1624    pub url_box: Option<UrlBox>,
1625    pub unknown_boxes: Vec<UnknownBox>,
1626}
1627
1628impl DrefBox {
1629    /// ボックス種別
1630    pub const TYPE: BoxType = BoxType::Normal(*b"dref");
1631
1632    /// メディアデータが同じファイル内に格納されていることを示す [`DrefBox`] の値
1633    pub const LOCAL_FILE: Self = Self {
1634        url_box: Some(UrlBox::LOCAL_FILE),
1635        unknown_boxes: Vec::new(),
1636    };
1637}
1638
1639impl Encode for DrefBox {
1640    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
1641        let header = BoxHeader::new_variable_size(Self::TYPE);
1642        let mut offset = header.encode(buf)?;
1643        offset += FullBoxHeader::from_box(self).encode(&mut buf[offset..])?;
1644        let entry_count = (self.url_box.is_some() as usize + self.unknown_boxes.len()) as u32;
1645        offset += entry_count.encode(&mut buf[offset..])?;
1646        if let Some(b) = &self.url_box {
1647            offset += b.encode(&mut buf[offset..])?;
1648        }
1649        for b in &self.unknown_boxes {
1650            offset += b.encode(&mut buf[offset..])?;
1651        }
1652        header.finalize_box_size(&mut buf[..offset])?;
1653        Ok(offset)
1654    }
1655}
1656
1657impl Decode for DrefBox {
1658    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
1659        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
1660        header.box_type.expect(Self::TYPE)?;
1661
1662        let mut offset = 0;
1663        let _full_header = FullBoxHeader::decode_at(payload, &mut offset)?;
1664        let entry_count = u32::decode_at(payload, &mut offset)?;
1665
1666        let mut url_box = None;
1667        let mut unknown_boxes = Vec::new();
1668
1669        for _ in 0..entry_count {
1670            let (child_header, _) = BoxHeader::decode(&payload[offset..])?;
1671            match child_header.box_type {
1672                UrlBox::TYPE if url_box.is_none() => {
1673                    url_box = Some(UrlBox::decode_at(payload, &mut offset)?);
1674                }
1675                _ => {
1676                    unknown_boxes.push(UnknownBox::decode_at(payload, &mut offset)?);
1677                }
1678            }
1679        }
1680
1681        Ok((
1682            Self {
1683                url_box,
1684                unknown_boxes,
1685            },
1686            header.external_size() + payload.len(),
1687        ))
1688    }
1689}
1690
1691impl BaseBox for DrefBox {
1692    fn box_type(&self) -> BoxType {
1693        Self::TYPE
1694    }
1695
1696    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
1697        Box::new(
1698            core::iter::empty()
1699                .chain(self.url_box.iter().map(as_box_object))
1700                .chain(self.unknown_boxes.iter().map(as_box_object)),
1701        )
1702    }
1703}
1704
1705impl FullBox for DrefBox {
1706    fn full_box_version(&self) -> u8 {
1707        0
1708    }
1709
1710    fn full_box_flags(&self) -> FullBoxFlags {
1711        FullBoxFlags::new(0)
1712    }
1713}
1714
1715/// [ISO/IEC 14496-12] DataEntryUrlBox class (親: [`DrefBox`])
1716#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1717#[allow(missing_docs)]
1718pub struct UrlBox {
1719    pub location: Option<Utf8String>,
1720}
1721
1722impl UrlBox {
1723    /// ボックス種別
1724    pub const TYPE: BoxType = BoxType::Normal(*b"url ");
1725
1726    /// メディアデータが同じファイル内に格納されていることを示す [`UrlBox`] の値
1727    pub const LOCAL_FILE: Self = Self { location: None };
1728}
1729
1730impl Encode for UrlBox {
1731    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
1732        let header = BoxHeader::new_variable_size(Self::TYPE);
1733        let mut offset = header.encode(buf)?;
1734        offset += FullBoxHeader::from_box(self).encode(&mut buf[offset..])?;
1735        if let Some(l) = &self.location {
1736            offset += l.encode(&mut buf[offset..])?;
1737        }
1738        header.finalize_box_size(&mut buf[..offset])?;
1739        Ok(offset)
1740    }
1741}
1742
1743impl Decode for UrlBox {
1744    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
1745        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
1746        header.box_type.expect(Self::TYPE)?;
1747
1748        let mut offset = 0;
1749        let full_header = FullBoxHeader::decode_at(payload, &mut offset)?;
1750        let location = if full_header.flags.is_set(0) {
1751            None
1752        } else {
1753            Some(Utf8String::decode_at(payload, &mut offset)?)
1754        };
1755
1756        Ok((Self { location }, header.external_size() + payload.len()))
1757    }
1758}
1759
1760impl BaseBox for UrlBox {
1761    fn box_type(&self) -> BoxType {
1762        Self::TYPE
1763    }
1764
1765    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
1766        Box::new(core::iter::empty())
1767    }
1768}
1769
1770impl FullBox for UrlBox {
1771    fn full_box_version(&self) -> u8 {
1772        0
1773    }
1774
1775    fn full_box_flags(&self) -> FullBoxFlags {
1776        FullBoxFlags::new(self.location.is_none() as u32)
1777    }
1778}
1779
1780/// [ISO/IEC 14496-12] SampleTableBox class (親: [`MinfBox`])
1781#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1782#[allow(missing_docs)]
1783pub struct StblBox {
1784    pub stsd_box: StsdBox,
1785    pub stts_box: SttsBox,
1786    pub stsc_box: StscBox,
1787    pub stsz_box: StszBox,
1788    pub stco_or_co64_box: Either<StcoBox, Co64Box>,
1789    pub stss_box: Option<StssBox>,
1790    pub unknown_boxes: Vec<UnknownBox>,
1791}
1792
1793impl StblBox {
1794    /// ボックス種別
1795    pub const TYPE: BoxType = BoxType::Normal(*b"stbl");
1796}
1797
1798impl Encode for StblBox {
1799    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
1800        let header = BoxHeader::new_variable_size(Self::TYPE);
1801        let mut offset = header.encode(buf)?;
1802        offset += self.stsd_box.encode(&mut buf[offset..])?;
1803        offset += self.stts_box.encode(&mut buf[offset..])?;
1804        offset += self.stsc_box.encode(&mut buf[offset..])?;
1805        offset += self.stsz_box.encode(&mut buf[offset..])?;
1806        match &self.stco_or_co64_box {
1807            Either::A(b) => offset += b.encode(&mut buf[offset..])?,
1808            Either::B(b) => offset += b.encode(&mut buf[offset..])?,
1809        }
1810        if let Some(b) = &self.stss_box {
1811            offset += b.encode(&mut buf[offset..])?;
1812        }
1813        for b in &self.unknown_boxes {
1814            offset += b.encode(&mut buf[offset..])?;
1815        }
1816        header.finalize_box_size(&mut buf[..offset])?;
1817        Ok(offset)
1818    }
1819}
1820
1821impl Decode for StblBox {
1822    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
1823        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
1824        header.box_type.expect(Self::TYPE)?;
1825
1826        let mut offset = 0;
1827        let mut stsd_box = None;
1828        let mut stts_box = None;
1829        let mut stsc_box = None;
1830        let mut stsz_box = None;
1831        let mut stco_box = None;
1832        let mut co64_box = None;
1833        let mut stss_box = None;
1834        let mut unknown_boxes = Vec::new();
1835
1836        while offset < payload.len() {
1837            let (child_header, _) = BoxHeader::decode(&payload[offset..])?;
1838            match child_header.box_type {
1839                StsdBox::TYPE if stsd_box.is_none() => {
1840                    stsd_box = Some(StsdBox::decode_at(payload, &mut offset)?);
1841                }
1842                SttsBox::TYPE if stts_box.is_none() => {
1843                    stts_box = Some(SttsBox::decode_at(payload, &mut offset)?);
1844                }
1845                StscBox::TYPE if stsc_box.is_none() => {
1846                    stsc_box = Some(StscBox::decode_at(payload, &mut offset)?);
1847                }
1848                StszBox::TYPE if stsz_box.is_none() => {
1849                    stsz_box = Some(StszBox::decode_at(payload, &mut offset)?);
1850                }
1851                StcoBox::TYPE if stco_box.is_none() => {
1852                    stco_box = Some(StcoBox::decode_at(payload, &mut offset)?);
1853                }
1854                Co64Box::TYPE if co64_box.is_none() => {
1855                    co64_box = Some(Co64Box::decode_at(payload, &mut offset)?);
1856                }
1857                StssBox::TYPE if stss_box.is_none() => {
1858                    stss_box = Some(StssBox::decode_at(payload, &mut offset)?);
1859                }
1860                _ => {
1861                    unknown_boxes.push(UnknownBox::decode_at(payload, &mut offset)?);
1862                }
1863            }
1864        }
1865
1866        Ok((
1867            Self {
1868                stsd_box: check_mandatory_box(stsd_box, "stsd", "stbl")?,
1869                stts_box: check_mandatory_box(stts_box, "stts", "stbl")?,
1870                stsc_box: check_mandatory_box(stsc_box, "stsc", "stbl")?,
1871                stsz_box: check_mandatory_box(stsz_box, "stsz", "stbl")?,
1872                stco_or_co64_box: check_mandatory_box(
1873                    stco_box.map(Either::A).or(co64_box.map(Either::B)),
1874                    "stco' or 'co64",
1875                    "stbl",
1876                )?,
1877                stss_box,
1878                unknown_boxes,
1879            },
1880            header.external_size() + payload.len(),
1881        ))
1882    }
1883}
1884
1885impl BaseBox for StblBox {
1886    fn box_type(&self) -> BoxType {
1887        Self::TYPE
1888    }
1889
1890    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
1891        Box::new(
1892            core::iter::empty()
1893                .chain(core::iter::once(&self.stsd_box).map(as_box_object))
1894                .chain(core::iter::once(&self.stts_box).map(as_box_object))
1895                .chain(core::iter::once(&self.stsc_box).map(as_box_object))
1896                .chain(core::iter::once(&self.stsz_box).map(as_box_object))
1897                .chain(core::iter::once(&self.stco_or_co64_box).map(as_box_object))
1898                .chain(self.stss_box.iter().map(as_box_object))
1899                .chain(self.unknown_boxes.iter().map(as_box_object)),
1900        )
1901    }
1902}
1903
1904impl AsRef<StblBox> for StblBox {
1905    fn as_ref(&self) -> &StblBox {
1906        self
1907    }
1908}
1909
1910/// [ISO/IEC 14496-12] SampleDescriptionBox class (親: [`StblBox`])
1911#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1912#[allow(missing_docs)]
1913pub struct StsdBox {
1914    pub entries: Vec<SampleEntry>,
1915}
1916
1917impl StsdBox {
1918    /// ボックス種別
1919    pub const TYPE: BoxType = BoxType::Normal(*b"stsd");
1920}
1921
1922impl Encode for StsdBox {
1923    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
1924        let header = BoxHeader::new_variable_size(Self::TYPE);
1925        let mut offset = header.encode(buf)?;
1926        offset += FullBoxHeader::from_box(self).encode(&mut buf[offset..])?;
1927        let entry_count = (self.entries.len()) as u32;
1928        offset += entry_count.encode(&mut buf[offset..])?;
1929        for b in &self.entries {
1930            offset += b.encode(&mut buf[offset..])?;
1931        }
1932        header.finalize_box_size(&mut buf[..offset])?;
1933        Ok(offset)
1934    }
1935}
1936
1937impl Decode for StsdBox {
1938    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
1939        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
1940        header.box_type.expect(Self::TYPE)?;
1941
1942        let mut offset = 0;
1943        let _full_header = FullBoxHeader::decode_at(payload, &mut offset)?;
1944        let entry_count = u32::decode_at(payload, &mut offset)?;
1945
1946        let mut entries = Vec::new();
1947        for _ in 0..entry_count {
1948            entries.push(SampleEntry::decode_at(payload, &mut offset)?);
1949        }
1950
1951        Ok((Self { entries }, header.external_size() + payload.len()))
1952    }
1953}
1954
1955impl BaseBox for StsdBox {
1956    fn box_type(&self) -> BoxType {
1957        Self::TYPE
1958    }
1959
1960    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
1961        Box::new(self.entries.iter().map(as_box_object))
1962    }
1963}
1964
1965impl FullBox for StsdBox {
1966    fn full_box_version(&self) -> u8 {
1967        0
1968    }
1969
1970    fn full_box_flags(&self) -> FullBoxFlags {
1971        FullBoxFlags::new(0)
1972    }
1973}
1974
1975/// [`StsdBox`] に含まれるエントリー
1976#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1977#[allow(missing_docs)]
1978pub enum SampleEntry {
1979    Avc1(Avc1Box),
1980    Hev1(Hev1Box),
1981    Vp08(Vp08Box),
1982    Vp09(Vp09Box),
1983    Av01(Av01Box),
1984    Opus(OpusBox),
1985    Mp4a(Mp4aBox),
1986    Unknown(UnknownBox),
1987}
1988
1989impl SampleEntry {
1990    /// チャンネル数を取得する
1991    ///
1992    /// 音声の場合はチャンネル数、映像の場合は None を返す
1993    pub fn audio_channel_count(&self) -> Option<u8> {
1994        match self {
1995            Self::Opus(b) => Some(b.audio.channelcount as u8),
1996            Self::Mp4a(b) => Some(b.audio.channelcount as u8),
1997            _ => None,
1998        }
1999    }
2000
2001    /// サンプリングレートを取得する
2002    ///
2003    /// 音声の場合はサンプリングレート、映像の場合は None を返す
2004    ///
2005    /// # NOTE
2006    ///
2007    /// このメソッドはサンプリングレートの整数部分のみを返し、小数部分は切り捨てられる。
2008    /// ただし通常は、MP4 ファイルでは音声のサンプリングレートは常に整数値(例: 44100 Hz, 48000 Hz)であり、
2009    /// 小数部分が 0 以外の値を持つことはないため、問題ないと想定している。
2010    pub fn audio_sample_rate(&self) -> Option<u16> {
2011        match self {
2012            Self::Opus(b) => Some(b.audio.samplerate.integer),
2013            Self::Mp4a(b) => Some(b.audio.samplerate.integer),
2014            _ => None,
2015        }
2016    }
2017
2018    /// サンプルサイズ(ビット深度)を取得する
2019    ///
2020    /// 音声の場合はサンプルサイズ、映像の場合は None を返す
2021    pub fn audio_sample_size(&self) -> Option<u16> {
2022        match self {
2023            Self::Opus(b) => Some(b.audio.samplesize),
2024            Self::Mp4a(b) => Some(b.audio.samplesize),
2025            _ => None,
2026        }
2027    }
2028
2029    /// 解像度を取得する
2030    ///
2031    /// 映像の場合は (幅, 高さ)、音声の場合は None を返す
2032    pub fn video_resolution(&self) -> Option<(u16, u16)> {
2033        match self {
2034            Self::Avc1(b) => Some((b.visual.width, b.visual.height)),
2035            Self::Hev1(b) => Some((b.visual.width, b.visual.height)),
2036            Self::Vp08(b) => Some((b.visual.width, b.visual.height)),
2037            Self::Vp09(b) => Some((b.visual.width, b.visual.height)),
2038            Self::Av01(b) => Some((b.visual.width, b.visual.height)),
2039            _ => None,
2040        }
2041    }
2042
2043    fn inner_box(&self) -> &dyn BaseBox {
2044        match self {
2045            Self::Avc1(b) => b,
2046            Self::Hev1(b) => b,
2047            Self::Vp08(b) => b,
2048            Self::Vp09(b) => b,
2049            Self::Av01(b) => b,
2050            Self::Opus(b) => b,
2051            Self::Mp4a(b) => b,
2052            Self::Unknown(b) => b,
2053        }
2054    }
2055}
2056
2057impl Encode for SampleEntry {
2058    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
2059        match self {
2060            Self::Avc1(b) => b.encode(buf),
2061            Self::Hev1(b) => b.encode(buf),
2062            Self::Vp08(b) => b.encode(buf),
2063            Self::Vp09(b) => b.encode(buf),
2064            Self::Av01(b) => b.encode(buf),
2065            Self::Opus(b) => b.encode(buf),
2066            Self::Mp4a(b) => b.encode(buf),
2067            Self::Unknown(b) => b.encode(buf),
2068        }
2069    }
2070}
2071
2072impl Decode for SampleEntry {
2073    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
2074        let (header, _) = BoxHeader::decode(buf)?;
2075        match header.box_type {
2076            Avc1Box::TYPE => Avc1Box::decode(buf).map(|(b, n)| (Self::Avc1(b), n)),
2077            Hev1Box::TYPE => Hev1Box::decode(buf).map(|(b, n)| (Self::Hev1(b), n)),
2078            Vp08Box::TYPE => Vp08Box::decode(buf).map(|(b, n)| (Self::Vp08(b), n)),
2079            Vp09Box::TYPE => Vp09Box::decode(buf).map(|(b, n)| (Self::Vp09(b), n)),
2080            Av01Box::TYPE => Av01Box::decode(buf).map(|(b, n)| (Self::Av01(b), n)),
2081            OpusBox::TYPE => OpusBox::decode(buf).map(|(b, n)| (Self::Opus(b), n)),
2082            Mp4aBox::TYPE => Mp4aBox::decode(buf).map(|(b, n)| (Self::Mp4a(b), n)),
2083            _ => UnknownBox::decode(buf).map(|(b, n)| (Self::Unknown(b), n)),
2084        }
2085    }
2086}
2087
2088impl BaseBox for SampleEntry {
2089    fn box_type(&self) -> BoxType {
2090        self.inner_box().box_type()
2091    }
2092
2093    fn is_unknown_box(&self) -> bool {
2094        self.inner_box().is_unknown_box()
2095    }
2096
2097    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
2098        self.inner_box().children()
2099    }
2100}
2101
2102/// 映像系の [`SampleEntry`] に共通のフィールドをまとめた構造体
2103#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2104#[allow(missing_docs)]
2105pub struct VisualSampleEntryFields {
2106    pub data_reference_index: NonZeroU16,
2107    pub width: u16,
2108    pub height: u16,
2109    pub horizresolution: FixedPointNumber<u16, u16>,
2110    pub vertresolution: FixedPointNumber<u16, u16>,
2111    pub frame_count: u16,
2112    pub compressorname: [u8; 32],
2113    pub depth: u16,
2114}
2115
2116impl VisualSampleEntryFields {
2117    /// [`VisualSampleEntryFields::data_reference_index`] のデフォルト値
2118    pub const DEFAULT_DATA_REFERENCE_INDEX: NonZeroU16 = NonZeroU16::MIN;
2119
2120    /// [`VisualSampleEntryFields::horizresolution`] のデフォルト値 (72 dpi)
2121    pub const DEFAULT_HORIZRESOLUTION: FixedPointNumber<u16, u16> = FixedPointNumber::new(0x48, 0);
2122
2123    /// [`VisualSampleEntryFields::vertresolution`] のデフォルト値 (72 dpi)
2124    pub const DEFAULT_VERTRESOLUTION: FixedPointNumber<u16, u16> = FixedPointNumber::new(0x48, 0);
2125
2126    /// [`VisualSampleEntryFields::frame_count`] のデフォルト値 (1)
2127    pub const DEFAULT_FRAME_COUNT: u16 = 1;
2128
2129    /// [`VisualSampleEntryFields::depth`] のデフォルト値 (images are in colour with no alpha)
2130    pub const DEFAULT_DEPTH: u16 = 0x0018;
2131
2132    /// 名前なしを表す [`VisualSampleEntryFields::compressorname`] の値
2133    pub const NULL_COMPRESSORNAME: [u8; 32] = [0; 32];
2134}
2135
2136impl Encode for VisualSampleEntryFields {
2137    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
2138        let mut offset = 0;
2139        offset += [0u8; 6].encode(&mut buf[offset..])?;
2140        offset += self.data_reference_index.encode(&mut buf[offset..])?;
2141        offset += [0u8; 2 + 2 + 4 * 3].encode(&mut buf[offset..])?;
2142        offset += self.width.encode(&mut buf[offset..])?;
2143        offset += self.height.encode(&mut buf[offset..])?;
2144        offset += self.horizresolution.encode(&mut buf[offset..])?;
2145        offset += self.vertresolution.encode(&mut buf[offset..])?;
2146        offset += [0u8; 4].encode(&mut buf[offset..])?;
2147        offset += self.frame_count.encode(&mut buf[offset..])?;
2148        offset += self.compressorname.encode(&mut buf[offset..])?;
2149        offset += self.depth.encode(&mut buf[offset..])?;
2150        offset += (-1i16).encode(&mut buf[offset..])?;
2151        Ok(offset)
2152    }
2153}
2154
2155impl Decode for VisualSampleEntryFields {
2156    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
2157        let mut offset = 0;
2158        let _ = <[u8; 6]>::decode_at(buf, &mut offset)?;
2159        let data_reference_index = NonZeroU16::decode_at(buf, &mut offset)?;
2160        let _ = <[u8; 2 + 2 + 4 * 3]>::decode_at(buf, &mut offset)?;
2161        let width = u16::decode_at(buf, &mut offset)?;
2162        let height = u16::decode_at(buf, &mut offset)?;
2163        let horizresolution = FixedPointNumber::decode_at(buf, &mut offset)?;
2164        let vertresolution = FixedPointNumber::decode_at(buf, &mut offset)?;
2165        let _ = <[u8; 4]>::decode_at(buf, &mut offset)?;
2166        let frame_count = u16::decode_at(buf, &mut offset)?;
2167        let compressorname = <[u8; 32]>::decode_at(buf, &mut offset)?;
2168        let depth = u16::decode_at(buf, &mut offset)?;
2169        let _ = <[u8; 2]>::decode_at(buf, &mut offset)?;
2170        Ok((
2171            Self {
2172                data_reference_index,
2173                width,
2174                height,
2175                horizresolution,
2176                vertresolution,
2177                frame_count,
2178                compressorname,
2179                depth,
2180            },
2181            offset,
2182        ))
2183    }
2184}
2185
2186/// [ISO/IEC 14496-15] AVCSampleEntry class (親: [`StsdBox`])
2187#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2188#[allow(missing_docs)]
2189pub struct Avc1Box {
2190    pub visual: VisualSampleEntryFields,
2191    pub avcc_box: AvccBox,
2192    pub unknown_boxes: Vec<UnknownBox>,
2193}
2194
2195impl Avc1Box {
2196    /// ボックス種別
2197    pub const TYPE: BoxType = BoxType::Normal(*b"avc1");
2198}
2199
2200impl Encode for Avc1Box {
2201    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
2202        let header = BoxHeader::new_variable_size(Self::TYPE);
2203        let mut offset = header.encode(buf)?;
2204        offset += self.visual.encode(&mut buf[offset..])?;
2205        offset += self.avcc_box.encode(&mut buf[offset..])?;
2206        for b in &self.unknown_boxes {
2207            offset += b.encode(&mut buf[offset..])?;
2208        }
2209        header.finalize_box_size(&mut buf[..offset])?;
2210        Ok(offset)
2211    }
2212}
2213
2214impl Decode for Avc1Box {
2215    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
2216        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
2217        header.box_type.expect(Self::TYPE)?;
2218
2219        let mut offset = 0;
2220        let visual = VisualSampleEntryFields::decode_at(payload, &mut offset)?;
2221
2222        let mut avcc_box = None;
2223        let mut unknown_boxes = Vec::new();
2224
2225        while offset < payload.len() {
2226            let (child_header, _) = BoxHeader::decode(&payload[offset..])?;
2227            match child_header.box_type {
2228                AvccBox::TYPE if avcc_box.is_none() => {
2229                    avcc_box = Some(AvccBox::decode_at(payload, &mut offset)?);
2230                }
2231                _ => {
2232                    unknown_boxes.push(UnknownBox::decode_at(payload, &mut offset)?);
2233                }
2234            }
2235        }
2236
2237        Ok((
2238            Self {
2239                visual,
2240                avcc_box: check_mandatory_box(avcc_box, "avcc", "avc1")?,
2241                unknown_boxes,
2242            },
2243            header.external_size() + payload.len(),
2244        ))
2245    }
2246}
2247
2248impl BaseBox for Avc1Box {
2249    fn box_type(&self) -> BoxType {
2250        Self::TYPE
2251    }
2252
2253    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
2254        Box::new(
2255            core::iter::empty()
2256                .chain(core::iter::once(&self.avcc_box).map(as_box_object))
2257                .chain(self.unknown_boxes.iter().map(as_box_object)),
2258        )
2259    }
2260}
2261
2262/// [ISO/IEC 14496-15] AVCConfigurationBox class (親: [`Avc1Box`])
2263#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2264#[allow(missing_docs)]
2265pub struct AvccBox {
2266    pub avc_profile_indication: u8,
2267    pub profile_compatibility: u8,
2268    pub avc_level_indication: u8,
2269    pub length_size_minus_one: Uint<u8, 2>,
2270    pub sps_list: Vec<Vec<u8>>,
2271    pub pps_list: Vec<Vec<u8>>,
2272    pub chroma_format: Option<Uint<u8, 2>>,
2273    pub bit_depth_luma_minus8: Option<Uint<u8, 3>>,
2274    pub bit_depth_chroma_minus8: Option<Uint<u8, 3>>,
2275    pub sps_ext_list: Vec<Vec<u8>>,
2276}
2277
2278impl AvccBox {
2279    /// ボックス種別
2280    pub const TYPE: BoxType = BoxType::Normal(*b"avcC");
2281
2282    const CONFIGURATION_VERSION: u8 = 1;
2283}
2284
2285impl Encode for AvccBox {
2286    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
2287        let header = BoxHeader::new_variable_size(Self::TYPE);
2288        let mut offset = header.encode(buf)?;
2289
2290        offset += Self::CONFIGURATION_VERSION.encode(&mut buf[offset..])?;
2291        offset += self.avc_profile_indication.encode(&mut buf[offset..])?;
2292        offset += self.profile_compatibility.encode(&mut buf[offset..])?;
2293        offset += self.avc_level_indication.encode(&mut buf[offset..])?;
2294        offset += (0b1111_1100 | self.length_size_minus_one.get()).encode(&mut buf[offset..])?;
2295
2296        let sps_count =
2297            u8::try_from(self.sps_list.len()).map_err(|_| Error::invalid_input("Too many SPSs"))?;
2298        offset += (0b1110_0000 | sps_count).encode(&mut buf[offset..])?;
2299        for sps in &self.sps_list {
2300            let size =
2301                u16::try_from(sps.len()).map_err(|_| Error::invalid_input("Too long SPS"))?;
2302            offset += size.encode(&mut buf[offset..])?;
2303            offset += sps.encode(&mut buf[offset..])?;
2304        }
2305
2306        let pps_count =
2307            u8::try_from(self.pps_list.len()).map_err(|_| Error::invalid_input("Too many PPSs"))?;
2308        offset += pps_count.encode(&mut buf[offset..])?;
2309        for pps in &self.pps_list {
2310            let size =
2311                u16::try_from(pps.len()).map_err(|_| Error::invalid_input("Too long PPS"))?;
2312            offset += size.encode(&mut buf[offset..])?;
2313            offset += pps.encode(&mut buf[offset..])?;
2314        }
2315
2316        if !matches!(self.avc_profile_indication, 66 | 77 | 88) {
2317            let chroma_format = self.chroma_format.ok_or_else(|| {
2318                Error::invalid_input("Missing 'chroma_format' field in 'avcC' box")
2319            })?;
2320            let bit_depth_luma_minus8 = self.bit_depth_luma_minus8.ok_or_else(|| {
2321                Error::invalid_input("Missing 'bit_depth_luma_minus8' field in 'avcC' box")
2322            })?;
2323            let bit_depth_chroma_minus8 = self.bit_depth_chroma_minus8.ok_or_else(|| {
2324                Error::invalid_input("Missing 'bit_depth_chroma_minus8' field in 'avcC' box")
2325            })?;
2326            offset += (0b1111_1100 | chroma_format.get()).encode(&mut buf[offset..])?;
2327            offset += (0b1111_1000 | bit_depth_luma_minus8.get()).encode(&mut buf[offset..])?;
2328            offset += (0b1111_1000 | bit_depth_chroma_minus8.get()).encode(&mut buf[offset..])?;
2329
2330            let sps_ext_count = u8::try_from(self.sps_ext_list.len())
2331                .map_err(|_| Error::invalid_input("Too many SPS EXTs"))?;
2332            offset += sps_ext_count.encode(&mut buf[offset..])?;
2333            for sps_ext in &self.sps_ext_list {
2334                let size = u16::try_from(sps_ext.len())
2335                    .map_err(|_| Error::invalid_input("Too long SPS EXT"))?;
2336                offset += size.encode(&mut buf[offset..])?;
2337                offset += sps_ext.encode(&mut buf[offset..])?;
2338            }
2339        }
2340
2341        header.finalize_box_size(&mut buf[..offset])?;
2342        Ok(offset)
2343    }
2344}
2345
2346impl Decode for AvccBox {
2347    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
2348        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
2349        header.box_type.expect(Self::TYPE)?;
2350
2351        let mut offset = 0;
2352        let configuration_version = u8::decode_at(payload, &mut offset)?;
2353        if configuration_version != Self::CONFIGURATION_VERSION {
2354            return Err(Error::invalid_data(format!(
2355                "Unsupported avcC configuration version: {configuration_version}"
2356            )));
2357        }
2358
2359        let avc_profile_indication = u8::decode_at(payload, &mut offset)?;
2360        let profile_compatibility = u8::decode_at(payload, &mut offset)?;
2361        let avc_level_indication = u8::decode_at(payload, &mut offset)?;
2362        let length_size_minus_one = Uint::from_bits(u8::decode_at(payload, &mut offset)?);
2363
2364        let sps_count =
2365            Uint::<u8, 5>::from_bits(u8::decode_at(payload, &mut offset)?).get() as usize;
2366        let mut sps_list = Vec::with_capacity(sps_count);
2367        for _ in 0..sps_count {
2368            let size = u16::decode_at(payload, &mut offset)? as usize;
2369            let sps = payload[offset..offset + size].to_vec();
2370            offset += size;
2371            sps_list.push(sps);
2372        }
2373
2374        let pps_count = u8::decode_at(payload, &mut offset)? as usize;
2375        let mut pps_list = Vec::with_capacity(pps_count);
2376        for _ in 0..pps_count {
2377            let size = u16::decode_at(payload, &mut offset)? as usize;
2378            let pps = payload[offset..offset + size].to_vec();
2379            offset += size;
2380            pps_list.push(pps);
2381        }
2382
2383        let mut chroma_format = None;
2384        let mut bit_depth_luma_minus8 = None;
2385        let mut bit_depth_chroma_minus8 = None;
2386        let mut sps_ext_list = Vec::new();
2387        if !matches!(avc_profile_indication, 66 | 77 | 88) {
2388            chroma_format = Some(Uint::from_bits(u8::decode_at(payload, &mut offset)?));
2389            bit_depth_luma_minus8 = Some(Uint::from_bits(u8::decode_at(payload, &mut offset)?));
2390            bit_depth_chroma_minus8 = Some(Uint::from_bits(u8::decode_at(payload, &mut offset)?));
2391
2392            let sps_ext_count = u8::decode_at(payload, &mut offset)? as usize;
2393            for _ in 0..sps_ext_count {
2394                let size = u16::decode_at(payload, &mut offset)? as usize;
2395                let sps_ext = payload[offset..offset + size].to_vec();
2396                offset += size;
2397                sps_ext_list.push(sps_ext);
2398            }
2399        }
2400
2401        Ok((
2402            Self {
2403                avc_profile_indication,
2404                profile_compatibility,
2405                avc_level_indication,
2406                length_size_minus_one,
2407                sps_list,
2408                pps_list,
2409                chroma_format,
2410                bit_depth_luma_minus8,
2411                bit_depth_chroma_minus8,
2412                sps_ext_list,
2413            },
2414            header.external_size() + payload.len(),
2415        ))
2416    }
2417}
2418
2419impl BaseBox for AvccBox {
2420    fn box_type(&self) -> BoxType {
2421        Self::TYPE
2422    }
2423
2424    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
2425        Box::new(core::iter::empty())
2426    }
2427}
2428
2429/// [ISO/IEC 14496-15] HEVCSampleEntry class (親: [`StsdBox`])
2430#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2431#[allow(missing_docs)]
2432pub struct Hev1Box {
2433    pub visual: VisualSampleEntryFields,
2434    pub hvcc_box: HvccBox,
2435    pub unknown_boxes: Vec<UnknownBox>,
2436}
2437
2438impl Hev1Box {
2439    /// ボックス種別
2440    pub const TYPE: BoxType = BoxType::Normal(*b"hev1");
2441}
2442
2443impl Encode for Hev1Box {
2444    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
2445        let header = BoxHeader::new_variable_size(Self::TYPE);
2446        let mut offset = header.encode(buf)?;
2447        offset += self.visual.encode(&mut buf[offset..])?;
2448        offset += self.hvcc_box.encode(&mut buf[offset..])?;
2449        for b in &self.unknown_boxes {
2450            offset += b.encode(&mut buf[offset..])?;
2451        }
2452        header.finalize_box_size(&mut buf[..offset])?;
2453        Ok(offset)
2454    }
2455}
2456
2457impl Decode for Hev1Box {
2458    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
2459        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
2460        header.box_type.expect(Self::TYPE)?;
2461
2462        let mut offset = 0;
2463        let visual = VisualSampleEntryFields::decode_at(payload, &mut offset)?;
2464
2465        let mut hvcc_box = None;
2466        let mut unknown_boxes = Vec::new();
2467
2468        while offset < payload.len() {
2469            let (child_header, _) = BoxHeader::decode(&payload[offset..])?;
2470            match child_header.box_type {
2471                HvccBox::TYPE if hvcc_box.is_none() => {
2472                    hvcc_box = Some(HvccBox::decode_at(payload, &mut offset)?);
2473                }
2474                _ => {
2475                    unknown_boxes.push(UnknownBox::decode_at(payload, &mut offset)?);
2476                }
2477            }
2478        }
2479
2480        Ok((
2481            Self {
2482                visual,
2483                hvcc_box: check_mandatory_box(hvcc_box, "hvcc", "hev1")?,
2484                unknown_boxes,
2485            },
2486            header.external_size() + payload.len(),
2487        ))
2488    }
2489}
2490
2491impl BaseBox for Hev1Box {
2492    fn box_type(&self) -> BoxType {
2493        Self::TYPE
2494    }
2495
2496    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
2497        Box::new(
2498            core::iter::empty()
2499                .chain(core::iter::once(&self.hvcc_box).map(as_box_object))
2500                .chain(self.unknown_boxes.iter().map(as_box_object)),
2501        )
2502    }
2503}
2504
2505/// [`HvccBox`] 内の NAL ユニット配列を保持する構造体
2506#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2507#[allow(missing_docs)]
2508pub struct HvccNalUintArray {
2509    pub array_completeness: Uint<u8, 1, 7>,
2510    pub nal_unit_type: Uint<u8, 6, 0>,
2511    pub nalus: Vec<Vec<u8>>,
2512}
2513
2514/// [ISO/IEC 14496-15] HVCConfigurationBox class (親: [`Hev1Box`])
2515#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2516#[allow(missing_docs)]
2517pub struct HvccBox {
2518    pub general_profile_space: Uint<u8, 2, 6>,
2519    pub general_tier_flag: Uint<u8, 1, 5>,
2520    pub general_profile_idc: Uint<u8, 5, 0>,
2521    pub general_profile_compatibility_flags: u32,
2522    pub general_constraint_indicator_flags: Uint<u64, 48>,
2523    pub general_level_idc: u8,
2524    pub min_spatial_segmentation_idc: Uint<u16, 12>,
2525    pub parallelism_type: Uint<u8, 2>,
2526    pub chroma_format_idc: Uint<u8, 2>,
2527    pub bit_depth_luma_minus8: Uint<u8, 3>,
2528    pub bit_depth_chroma_minus8: Uint<u8, 3>,
2529    pub avg_frame_rate: u16,
2530    pub constant_frame_rate: Uint<u8, 2, 6>,
2531    pub num_temporal_layers: Uint<u8, 3, 3>,
2532    pub temporal_id_nested: Uint<u8, 1, 2>,
2533    pub length_size_minus_one: Uint<u8, 2, 0>,
2534    pub nalu_arrays: Vec<HvccNalUintArray>,
2535}
2536
2537impl HvccBox {
2538    /// ボックス種別
2539    pub const TYPE: BoxType = BoxType::Normal(*b"hvcC");
2540
2541    const CONFIGURATION_VERSION: u8 = 1;
2542}
2543
2544impl Encode for HvccBox {
2545    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
2546        let header = BoxHeader::new_variable_size(Self::TYPE);
2547        let mut offset = header.encode(buf)?;
2548        offset += Self::CONFIGURATION_VERSION.encode(&mut buf[offset..])?;
2549        offset += (self.general_profile_space.to_bits()
2550            | self.general_tier_flag.to_bits()
2551            | self.general_profile_idc.to_bits())
2552        .encode(&mut buf[offset..])?;
2553        offset += self
2554            .general_profile_compatibility_flags
2555            .encode(&mut buf[offset..])?;
2556        offset += self.general_constraint_indicator_flags.get().to_be_bytes()[2..]
2557            .encode(&mut buf[offset..])?;
2558        offset += self.general_level_idc.encode(&mut buf[offset..])?;
2559        offset += (0b1111_0000_0000_0000 | self.min_spatial_segmentation_idc.to_bits())
2560            .encode(&mut buf[offset..])?;
2561        offset += (0b1111_1100 | self.parallelism_type.to_bits()).encode(&mut buf[offset..])?;
2562        offset += (0b1111_1100 | self.chroma_format_idc.to_bits()).encode(&mut buf[offset..])?;
2563        offset +=
2564            (0b1111_1000 | self.bit_depth_luma_minus8.to_bits()).encode(&mut buf[offset..])?;
2565        offset +=
2566            (0b1111_1000 | self.bit_depth_chroma_minus8.to_bits()).encode(&mut buf[offset..])?;
2567        offset += self.avg_frame_rate.encode(&mut buf[offset..])?;
2568        offset += (self.constant_frame_rate.to_bits()
2569            | self.num_temporal_layers.to_bits()
2570            | self.temporal_id_nested.to_bits()
2571            | self.length_size_minus_one.to_bits())
2572        .encode(&mut buf[offset..])?;
2573        offset += u8::try_from(self.nalu_arrays.len())
2574            .map_err(|_| {
2575                Error::invalid_input(format!("Too many NALU arrays: {}", self.nalu_arrays.len()))
2576            })?
2577            .encode(&mut buf[offset..])?;
2578        for nalu_array in &self.nalu_arrays {
2579            offset += (nalu_array.array_completeness.to_bits()
2580                | nalu_array.nal_unit_type.to_bits())
2581            .encode(&mut buf[offset..])?;
2582            offset += u16::try_from(nalu_array.nalus.len())
2583                .map_err(|_| {
2584                    Error::invalid_input(format!("Too many NALUs: {}", nalu_array.nalus.len()))
2585                })?
2586                .encode(&mut buf[offset..])?;
2587            for nalu in &nalu_array.nalus {
2588                offset += u16::try_from(nalu.len())
2589                    .map_err(|_| Error::invalid_input(format!("Too large NALU: {}", nalu.len())))?
2590                    .encode(&mut buf[offset..])?;
2591                offset += nalu.encode(&mut buf[offset..])?;
2592            }
2593        }
2594        header.finalize_box_size(&mut buf[..offset])?;
2595        Ok(offset)
2596    }
2597}
2598
2599impl Decode for HvccBox {
2600    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
2601        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
2602        header.box_type.expect(Self::TYPE)?;
2603
2604        let mut offset = 0;
2605        let configuration_version = u8::decode_at(payload, &mut offset)?;
2606        if configuration_version != Self::CONFIGURATION_VERSION {
2607            return Err(Error::invalid_data(format!(
2608                "Unsupported hvcC version: {configuration_version}"
2609            )));
2610        }
2611
2612        let b = u8::decode_at(payload, &mut offset)?;
2613        let general_profile_space = Uint::from_bits(b);
2614        let general_tier_flag = Uint::from_bits(b);
2615        let general_profile_idc = Uint::from_bits(b);
2616
2617        let general_profile_compatibility_flags = u32::decode_at(payload, &mut offset)?;
2618
2619        let mut buf_constraint = [0; 8];
2620        buf_constraint[2..].copy_from_slice(&payload[offset..offset + 6]);
2621        offset += 6;
2622        let general_constraint_indicator_flags =
2623            Uint::from_bits(u64::from_be_bytes(buf_constraint));
2624
2625        let general_level_idc = u8::decode_at(payload, &mut offset)?;
2626        let min_spatial_segmentation_idc = Uint::from_bits(u16::decode_at(payload, &mut offset)?);
2627        let parallelism_type = Uint::from_bits(u8::decode_at(payload, &mut offset)?);
2628        let chroma_format_idc = Uint::from_bits(u8::decode_at(payload, &mut offset)?);
2629        let bit_depth_luma_minus8 = Uint::from_bits(u8::decode_at(payload, &mut offset)?);
2630        let bit_depth_chroma_minus8 = Uint::from_bits(u8::decode_at(payload, &mut offset)?);
2631        let avg_frame_rate = u16::decode_at(payload, &mut offset)?;
2632
2633        let b = u8::decode_at(payload, &mut offset)?;
2634        let constant_frame_rate = Uint::from_bits(b);
2635        let num_temporal_layers = Uint::from_bits(b);
2636        let temporal_id_nested = Uint::from_bits(b);
2637        let length_size_minus_one = Uint::from_bits(b);
2638
2639        let num_of_arrays = u8::decode_at(payload, &mut offset)?;
2640        let mut nalu_arrays = Vec::new();
2641        for _ in 0..num_of_arrays {
2642            let b = u8::decode_at(payload, &mut offset)?;
2643            let array_completeness = Uint::from_bits(b);
2644            let nal_unit_type = Uint::from_bits(b);
2645
2646            let num_nalus = u16::decode_at(payload, &mut offset)?;
2647            let mut nalus = Vec::new();
2648            for _ in 0..num_nalus {
2649                let nal_unit_length = u16::decode_at(payload, &mut offset)? as usize;
2650                let nal_unit = payload[offset..offset + nal_unit_length].to_vec();
2651                offset += nal_unit_length;
2652                nalus.push(nal_unit);
2653            }
2654            nalu_arrays.push(HvccNalUintArray {
2655                array_completeness,
2656                nal_unit_type,
2657                nalus,
2658            });
2659        }
2660
2661        Ok((
2662            Self {
2663                general_profile_space,
2664                general_tier_flag,
2665                general_profile_idc,
2666                general_profile_compatibility_flags,
2667                general_constraint_indicator_flags,
2668                general_level_idc,
2669                min_spatial_segmentation_idc,
2670                parallelism_type,
2671                chroma_format_idc,
2672                bit_depth_luma_minus8,
2673                bit_depth_chroma_minus8,
2674                avg_frame_rate,
2675                constant_frame_rate,
2676                num_temporal_layers,
2677                temporal_id_nested,
2678                length_size_minus_one,
2679                nalu_arrays,
2680            },
2681            header.external_size() + payload.len(),
2682        ))
2683    }
2684}
2685
2686impl BaseBox for HvccBox {
2687    fn box_type(&self) -> BoxType {
2688        Self::TYPE
2689    }
2690
2691    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
2692        Box::new(core::iter::empty())
2693    }
2694}
2695
2696/// [<https://www.webmproject.org/vp9/mp4/>] VP8SampleEntry class (親: [`StsdBox`])
2697#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2698#[allow(missing_docs)]
2699pub struct Vp08Box {
2700    pub visual: VisualSampleEntryFields,
2701    pub vpcc_box: VpccBox,
2702    pub unknown_boxes: Vec<UnknownBox>,
2703}
2704
2705impl Vp08Box {
2706    /// ボックス種別
2707    pub const TYPE: BoxType = BoxType::Normal(*b"vp08");
2708}
2709
2710impl Encode for Vp08Box {
2711    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
2712        let header = BoxHeader::new_variable_size(Self::TYPE);
2713        let mut offset = header.encode(buf)?;
2714        offset += self.visual.encode(&mut buf[offset..])?;
2715        offset += self.vpcc_box.encode(&mut buf[offset..])?;
2716        for b in &self.unknown_boxes {
2717            offset += b.encode(&mut buf[offset..])?;
2718        }
2719        header.finalize_box_size(&mut buf[..offset])?;
2720        Ok(offset)
2721    }
2722}
2723
2724impl Decode for Vp08Box {
2725    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
2726        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
2727        header.box_type.expect(Self::TYPE)?;
2728
2729        let mut offset = 0;
2730        let visual = VisualSampleEntryFields::decode_at(payload, &mut offset)?;
2731
2732        let mut vpcc_box = None;
2733        let mut unknown_boxes = Vec::new();
2734
2735        while offset < payload.len() {
2736            let (child_header, _) = BoxHeader::decode(&payload[offset..])?;
2737            match child_header.box_type {
2738                VpccBox::TYPE if vpcc_box.is_none() => {
2739                    vpcc_box = Some(VpccBox::decode_at(payload, &mut offset)?);
2740                }
2741                _ => {
2742                    unknown_boxes.push(UnknownBox::decode_at(payload, &mut offset)?);
2743                }
2744            }
2745        }
2746
2747        Ok((
2748            Self {
2749                visual,
2750                vpcc_box: check_mandatory_box(vpcc_box, "vpcC", "vp08")?,
2751                unknown_boxes,
2752            },
2753            header.external_size() + payload.len(),
2754        ))
2755    }
2756}
2757
2758impl BaseBox for Vp08Box {
2759    fn box_type(&self) -> BoxType {
2760        Self::TYPE
2761    }
2762
2763    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
2764        Box::new(
2765            core::iter::empty()
2766                .chain(core::iter::once(&self.vpcc_box).map(as_box_object))
2767                .chain(self.unknown_boxes.iter().map(as_box_object)),
2768        )
2769    }
2770}
2771
2772/// [<https://www.webmproject.org/vp9/mp4/>] VP9SampleEntry class (親: [`StsdBox`])
2773#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2774#[allow(missing_docs)]
2775pub struct Vp09Box {
2776    pub visual: VisualSampleEntryFields,
2777    pub vpcc_box: VpccBox,
2778    pub unknown_boxes: Vec<UnknownBox>,
2779}
2780
2781impl Vp09Box {
2782    /// ボックス種別
2783    pub const TYPE: BoxType = BoxType::Normal(*b"vp09");
2784}
2785
2786impl Encode for Vp09Box {
2787    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
2788        let header = BoxHeader::new_variable_size(Self::TYPE);
2789        let mut offset = header.encode(buf)?;
2790        offset += self.visual.encode(&mut buf[offset..])?;
2791        offset += self.vpcc_box.encode(&mut buf[offset..])?;
2792        for b in &self.unknown_boxes {
2793            offset += b.encode(&mut buf[offset..])?;
2794        }
2795        header.finalize_box_size(&mut buf[..offset])?;
2796        Ok(offset)
2797    }
2798}
2799
2800impl Decode for Vp09Box {
2801    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
2802        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
2803        header.box_type.expect(Self::TYPE)?;
2804
2805        let mut offset = 0;
2806        let visual = VisualSampleEntryFields::decode_at(payload, &mut offset)?;
2807
2808        let mut vpcc_box = None;
2809        let mut unknown_boxes = Vec::new();
2810
2811        while offset < payload.len() {
2812            let (child_header, _) = BoxHeader::decode(&payload[offset..])?;
2813            match child_header.box_type {
2814                VpccBox::TYPE if vpcc_box.is_none() => {
2815                    vpcc_box = Some(VpccBox::decode_at(payload, &mut offset)?);
2816                }
2817                _ => {
2818                    unknown_boxes.push(UnknownBox::decode_at(payload, &mut offset)?);
2819                }
2820            }
2821        }
2822
2823        Ok((
2824            Self {
2825                visual,
2826                vpcc_box: check_mandatory_box(vpcc_box, "vpcC", "vp09")?,
2827                unknown_boxes,
2828            },
2829            header.external_size() + payload.len(),
2830        ))
2831    }
2832}
2833
2834impl BaseBox for Vp09Box {
2835    fn box_type(&self) -> BoxType {
2836        Self::TYPE
2837    }
2838
2839    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
2840        Box::new(
2841            core::iter::empty()
2842                .chain(core::iter::once(&self.vpcc_box).map(as_box_object))
2843                .chain(self.unknown_boxes.iter().map(as_box_object)),
2844        )
2845    }
2846}
2847
2848/// [<https://www.webmproject.org/vp9/mp4/>] VPCodecConfigurationBox class (親: [`Vp08Box`], [`Vp09Box`])
2849#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2850#[allow(missing_docs)]
2851pub struct VpccBox {
2852    pub profile: u8,
2853    pub level: u8,
2854    pub bit_depth: Uint<u8, 4, 4>,
2855    pub chroma_subsampling: Uint<u8, 3, 1>,
2856    pub video_full_range_flag: Uint<u8, 1>,
2857    pub colour_primaries: u8,
2858    pub transfer_characteristics: u8,
2859    pub matrix_coefficients: u8,
2860    pub codec_initialization_data: Vec<u8>,
2861}
2862
2863impl VpccBox {
2864    /// ボックス種別
2865    pub const TYPE: BoxType = BoxType::Normal(*b"vpcC");
2866}
2867
2868impl Encode for VpccBox {
2869    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
2870        let header = BoxHeader::new_variable_size(Self::TYPE);
2871        let mut offset = header.encode(buf)?;
2872        offset += FullBoxHeader::from_box(self).encode(&mut buf[offset..])?;
2873        offset += self.profile.encode(&mut buf[offset..])?;
2874        offset += self.level.encode(&mut buf[offset..])?;
2875        offset += (self.bit_depth.to_bits()
2876            | self.chroma_subsampling.to_bits()
2877            | self.video_full_range_flag.to_bits())
2878        .encode(&mut buf[offset..])?;
2879        offset += self.colour_primaries.encode(&mut buf[offset..])?;
2880        offset += self.transfer_characteristics.encode(&mut buf[offset..])?;
2881        offset += self.matrix_coefficients.encode(&mut buf[offset..])?;
2882        offset += (self.codec_initialization_data.len() as u16).encode(&mut buf[offset..])?;
2883        offset += self.codec_initialization_data.encode(&mut buf[offset..])?;
2884        header.finalize_box_size(&mut buf[..offset])?;
2885        Ok(offset)
2886    }
2887}
2888
2889impl Decode for VpccBox {
2890    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
2891        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
2892        header.box_type.expect(Self::TYPE)?;
2893
2894        let mut offset = 0;
2895        let header_obj = FullBoxHeader::decode_at(payload, &mut offset)?;
2896        if header_obj.version != 1 {
2897            return Err(Error::invalid_data(format!(
2898                "Unexpected full box header version: box=vpcC, version={}",
2899                header_obj.version
2900            )));
2901        }
2902
2903        let profile = u8::decode_at(payload, &mut offset)?;
2904        let level = u8::decode_at(payload, &mut offset)?;
2905
2906        let b = u8::decode_at(payload, &mut offset)?;
2907        let bit_depth = Uint::from_bits(b);
2908        let chroma_subsampling = Uint::from_bits(b);
2909        let video_full_range_flag = Uint::from_bits(b);
2910        let colour_primaries = u8::decode_at(payload, &mut offset)?;
2911        let transfer_characteristics = u8::decode_at(payload, &mut offset)?;
2912        let matrix_coefficients = u8::decode_at(payload, &mut offset)?;
2913        let codec_init_size = u16::decode_at(payload, &mut offset)? as usize;
2914        let codec_initialization_data = payload[offset..offset + codec_init_size].to_vec();
2915
2916        Ok((
2917            Self {
2918                profile,
2919                level,
2920                bit_depth,
2921                chroma_subsampling,
2922                video_full_range_flag,
2923                colour_primaries,
2924                transfer_characteristics,
2925                matrix_coefficients,
2926                codec_initialization_data,
2927            },
2928            header.external_size() + payload.len(),
2929        ))
2930    }
2931}
2932
2933impl BaseBox for VpccBox {
2934    fn box_type(&self) -> BoxType {
2935        Self::TYPE
2936    }
2937
2938    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
2939        Box::new(core::iter::empty())
2940    }
2941}
2942
2943impl FullBox for VpccBox {
2944    fn full_box_version(&self) -> u8 {
2945        1
2946    }
2947
2948    fn full_box_flags(&self) -> FullBoxFlags {
2949        FullBoxFlags::new(0)
2950    }
2951}
2952
2953/// [<https://aomediacodec.github.io/av1-isobmff/>] AV1SampleEntry class (親: [`StsdBox`])
2954#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2955#[allow(missing_docs)]
2956pub struct Av01Box {
2957    pub visual: VisualSampleEntryFields,
2958    pub av1c_box: Av1cBox,
2959    pub unknown_boxes: Vec<UnknownBox>,
2960}
2961
2962impl Av01Box {
2963    /// ボックス種別
2964    pub const TYPE: BoxType = BoxType::Normal(*b"av01");
2965}
2966
2967impl Encode for Av01Box {
2968    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
2969        let header = BoxHeader::new_variable_size(Self::TYPE);
2970        let mut offset = header.encode(buf)?;
2971        offset += self.visual.encode(&mut buf[offset..])?;
2972        offset += self.av1c_box.encode(&mut buf[offset..])?;
2973        for b in &self.unknown_boxes {
2974            offset += b.encode(&mut buf[offset..])?;
2975        }
2976        header.finalize_box_size(&mut buf[..offset])?;
2977        Ok(offset)
2978    }
2979}
2980
2981impl Decode for Av01Box {
2982    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
2983        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
2984        header.box_type.expect(Self::TYPE)?;
2985
2986        let mut offset = 0;
2987        let visual = VisualSampleEntryFields::decode_at(payload, &mut offset)?;
2988
2989        let mut av1c_box = None;
2990        let mut unknown_boxes = Vec::new();
2991
2992        while offset < payload.len() {
2993            let (child_header, _) = BoxHeader::decode(&payload[offset..])?;
2994            match child_header.box_type {
2995                Av1cBox::TYPE if av1c_box.is_none() => {
2996                    av1c_box = Some(Av1cBox::decode_at(payload, &mut offset)?);
2997                }
2998                _ => {
2999                    unknown_boxes.push(UnknownBox::decode_at(payload, &mut offset)?);
3000                }
3001            }
3002        }
3003
3004        Ok((
3005            Self {
3006                visual,
3007                av1c_box: check_mandatory_box(av1c_box, "av1c", "av01")?,
3008                unknown_boxes,
3009            },
3010            header.external_size() + payload.len(),
3011        ))
3012    }
3013}
3014
3015impl BaseBox for Av01Box {
3016    fn box_type(&self) -> BoxType {
3017        Self::TYPE
3018    }
3019
3020    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
3021        Box::new(
3022            core::iter::empty()
3023                .chain(core::iter::once(&self.av1c_box).map(as_box_object))
3024                .chain(self.unknown_boxes.iter().map(as_box_object)),
3025        )
3026    }
3027}
3028
3029/// [<https://aomediacodec.github.io/av1-isobmff/>] AV1CodecConfigurationBox class (親: [`StsdBox`])
3030#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3031#[allow(missing_docs)]
3032pub struct Av1cBox {
3033    pub seq_profile: Uint<u8, 3, 5>,
3034    pub seq_level_idx_0: Uint<u8, 5, 0>,
3035    pub seq_tier_0: Uint<u8, 1, 7>,
3036    pub high_bitdepth: Uint<u8, 1, 6>,
3037    pub twelve_bit: Uint<u8, 1, 5>,
3038    pub monochrome: Uint<u8, 1, 4>,
3039    pub chroma_subsampling_x: Uint<u8, 1, 3>,
3040    pub chroma_subsampling_y: Uint<u8, 1, 2>,
3041    pub chroma_sample_position: Uint<u8, 2, 0>,
3042    pub initial_presentation_delay_minus_one: Option<Uint<u8, 4, 0>>,
3043    pub config_obus: Vec<u8>,
3044}
3045
3046impl Av1cBox {
3047    /// ボックス種別
3048    pub const TYPE: BoxType = BoxType::Normal(*b"av1C");
3049
3050    const MARKER: Uint<u8, 1, 7> = Uint::new(1);
3051    const VERSION: Uint<u8, 7, 0> = Uint::new(1);
3052}
3053
3054impl Encode for Av1cBox {
3055    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
3056        let header = BoxHeader::new_variable_size(Self::TYPE);
3057        let mut offset = header.encode(buf)?;
3058        offset += (Self::MARKER.to_bits() | Self::VERSION.to_bits()).encode(&mut buf[offset..])?;
3059        offset += (self.seq_profile.to_bits() | self.seq_level_idx_0.to_bits())
3060            .encode(&mut buf[offset..])?;
3061        offset += (self.seq_tier_0.to_bits()
3062            | self.high_bitdepth.to_bits()
3063            | self.twelve_bit.to_bits()
3064            | self.monochrome.to_bits()
3065            | self.chroma_subsampling_x.to_bits()
3066            | self.chroma_subsampling_y.to_bits()
3067            | self.chroma_sample_position.to_bits())
3068        .encode(&mut buf[offset..])?;
3069        if let Some(v) = self.initial_presentation_delay_minus_one {
3070            offset += (0b1_0000 | v.to_bits()).encode(&mut buf[offset..])?;
3071        } else {
3072            offset += 0u8.encode(&mut buf[offset..])?;
3073        }
3074        offset += self.config_obus.encode(&mut buf[offset..])?;
3075        header.finalize_box_size(&mut buf[..offset])?;
3076        Ok(offset)
3077    }
3078}
3079
3080impl Decode for Av1cBox {
3081    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
3082        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
3083        header.box_type.expect(Self::TYPE)?;
3084
3085        let mut offset = 0;
3086        let b = u8::decode_at(payload, &mut offset)?;
3087        let marker = Uint::from_bits(b);
3088        let version = Uint::from_bits(b);
3089        if marker != Self::MARKER {
3090            return Err(Error::invalid_data("Unexpected av1C marker"));
3091        }
3092        if version != Self::VERSION {
3093            return Err(Error::invalid_data(format!(
3094                "Unsupported av1C version: {}",
3095                version.get()
3096            )));
3097        }
3098
3099        let b = u8::decode_at(payload, &mut offset)?;
3100        let seq_profile = Uint::from_bits(b);
3101        let seq_level_idx_0 = Uint::from_bits(b);
3102
3103        let b = u8::decode_at(payload, &mut offset)?;
3104        let seq_tier_0 = Uint::from_bits(b);
3105        let high_bitdepth = Uint::from_bits(b);
3106        let twelve_bit = Uint::from_bits(b);
3107        let monochrome = Uint::from_bits(b);
3108        let chroma_subsampling_x = Uint::from_bits(b);
3109        let chroma_subsampling_y = Uint::from_bits(b);
3110        let chroma_sample_position = Uint::from_bits(b);
3111
3112        let b = u8::decode_at(payload, &mut offset)?;
3113        let initial_presentation_delay_minus_one = if Uint::<u8, 1, 4>::from_bits(b).get() == 1 {
3114            Some(Uint::from_bits(b))
3115        } else {
3116            None
3117        };
3118
3119        let config_obus = payload[offset..].to_vec();
3120
3121        Ok((
3122            Self {
3123                seq_profile,
3124                seq_level_idx_0,
3125                seq_tier_0,
3126                high_bitdepth,
3127                twelve_bit,
3128                monochrome,
3129                chroma_subsampling_x,
3130                chroma_subsampling_y,
3131                chroma_sample_position,
3132                initial_presentation_delay_minus_one,
3133                config_obus,
3134            },
3135            header.external_size() + payload.len(),
3136        ))
3137    }
3138}
3139
3140impl BaseBox for Av1cBox {
3141    fn box_type(&self) -> BoxType {
3142        Self::TYPE
3143    }
3144
3145    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
3146        Box::new(core::iter::empty())
3147    }
3148}
3149
3150/// [`SttsBox`] が保持するエントリー
3151#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3152#[allow(missing_docs)]
3153pub struct SttsEntry {
3154    pub sample_count: u32,
3155    pub sample_delta: u32,
3156}
3157
3158/// [ISO/IEC 14496-12] TimeToSampleBox class (親: [`StblBox`])
3159#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3160#[allow(missing_docs)]
3161pub struct SttsBox {
3162    pub entries: Vec<SttsEntry>,
3163}
3164
3165impl SttsBox {
3166    /// ボックス種別
3167    pub const TYPE: BoxType = BoxType::Normal(*b"stts");
3168
3169    /// サンプル群の尺を走査するイテレーターを受け取って、対応する [`SttsBox`] インスタンスを作成する
3170    pub fn from_sample_deltas<I>(sample_deltas: I) -> Self
3171    where
3172        I: IntoIterator<Item = u32>,
3173    {
3174        let mut entries = Vec::<SttsEntry>::new();
3175        for sample_delta in sample_deltas {
3176            if let Some(last) = entries.last_mut()
3177                && last.sample_delta == sample_delta
3178            {
3179                last.sample_count += 1;
3180                continue;
3181            }
3182            entries.push(SttsEntry {
3183                sample_count: 1,
3184                sample_delta,
3185            });
3186        }
3187        Self { entries }
3188    }
3189}
3190
3191impl Encode for SttsBox {
3192    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
3193        let header = BoxHeader::new_variable_size(Self::TYPE);
3194        let mut offset = header.encode(buf)?;
3195        offset += FullBoxHeader::from_box(self).encode(&mut buf[offset..])?;
3196        offset += (self.entries.len() as u32).encode(&mut buf[offset..])?;
3197        for entry in &self.entries {
3198            offset += entry.sample_count.encode(&mut buf[offset..])?;
3199            offset += entry.sample_delta.encode(&mut buf[offset..])?;
3200        }
3201        header.finalize_box_size(&mut buf[..offset])?;
3202        Ok(offset)
3203    }
3204}
3205
3206impl Decode for SttsBox {
3207    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
3208        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
3209        header.box_type.expect(Self::TYPE)?;
3210
3211        let mut offset = 0;
3212        let _full_header = FullBoxHeader::decode_at(payload, &mut offset)?;
3213        let count = u32::decode_at(payload, &mut offset)? as usize;
3214
3215        let mut entries = Vec::with_capacity(count);
3216        for _ in 0..count {
3217            entries.push(SttsEntry {
3218                sample_count: u32::decode_at(payload, &mut offset)?,
3219                sample_delta: u32::decode_at(payload, &mut offset)?,
3220            });
3221        }
3222
3223        Ok((Self { entries }, header.external_size() + payload.len()))
3224    }
3225}
3226
3227impl BaseBox for SttsBox {
3228    fn box_type(&self) -> BoxType {
3229        Self::TYPE
3230    }
3231
3232    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
3233        Box::new(core::iter::empty())
3234    }
3235}
3236
3237impl FullBox for SttsBox {
3238    fn full_box_version(&self) -> u8 {
3239        0
3240    }
3241
3242    fn full_box_flags(&self) -> FullBoxFlags {
3243        FullBoxFlags::new(0)
3244    }
3245}
3246
3247/// [`StscBox`] が保持するエントリー
3248#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3249#[allow(missing_docs)]
3250pub struct StscEntry {
3251    pub first_chunk: NonZeroU32,
3252    pub sample_per_chunk: u32,
3253    pub sample_description_index: NonZeroU32,
3254}
3255
3256/// [ISO/IEC 14496-12] SampleToChunkBox class (親: [`StblBox`])
3257#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3258#[allow(missing_docs)]
3259pub struct StscBox {
3260    pub entries: Vec<StscEntry>,
3261}
3262
3263impl StscBox {
3264    /// ボックス種別
3265    pub const TYPE: BoxType = BoxType::Normal(*b"stsc");
3266}
3267
3268impl Encode for StscBox {
3269    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
3270        let header = BoxHeader::new_variable_size(Self::TYPE);
3271        let mut offset = header.encode(buf)?;
3272        offset += FullBoxHeader::from_box(self).encode(&mut buf[offset..])?;
3273        offset += (self.entries.len() as u32).encode(&mut buf[offset..])?;
3274        for entry in &self.entries {
3275            offset += entry.first_chunk.encode(&mut buf[offset..])?;
3276            offset += entry.sample_per_chunk.encode(&mut buf[offset..])?;
3277            offset += entry.sample_description_index.encode(&mut buf[offset..])?;
3278        }
3279        header.finalize_box_size(&mut buf[..offset])?;
3280        Ok(offset)
3281    }
3282}
3283
3284impl Decode for StscBox {
3285    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
3286        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
3287        header.box_type.expect(Self::TYPE)?;
3288
3289        let mut offset = 0;
3290        let _full_header = FullBoxHeader::decode_at(payload, &mut offset)?;
3291        let count = u32::decode_at(payload, &mut offset)?;
3292
3293        let mut entries = Vec::with_capacity(count as usize);
3294        for _ in 0..count {
3295            entries.push(StscEntry {
3296                first_chunk: NonZeroU32::decode_at(payload, &mut offset)?,
3297                sample_per_chunk: u32::decode_at(payload, &mut offset)?,
3298                sample_description_index: NonZeroU32::decode_at(payload, &mut offset)?,
3299            });
3300        }
3301
3302        Ok((Self { entries }, header.external_size() + payload.len()))
3303    }
3304}
3305
3306impl BaseBox for StscBox {
3307    fn box_type(&self) -> BoxType {
3308        Self::TYPE
3309    }
3310
3311    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
3312        Box::new(core::iter::empty())
3313    }
3314}
3315
3316impl FullBox for StscBox {
3317    fn full_box_version(&self) -> u8 {
3318        0
3319    }
3320
3321    fn full_box_flags(&self) -> FullBoxFlags {
3322        FullBoxFlags::new(0)
3323    }
3324}
3325
3326/// [ISO/IEC 14496-12] SampleSizeBox class (親: [`StblBox`])
3327#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3328#[allow(missing_docs)]
3329pub enum StszBox {
3330    Fixed {
3331        sample_size: NonZeroU32,
3332        sample_count: u32,
3333    },
3334    Variable {
3335        entry_sizes: Vec<u32>,
3336    },
3337}
3338
3339impl StszBox {
3340    /// ボックス種別
3341    pub const TYPE: BoxType = BoxType::Normal(*b"stsz");
3342}
3343
3344impl Encode for StszBox {
3345    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
3346        let header = BoxHeader::new_variable_size(Self::TYPE);
3347        let mut offset = header.encode(buf)?;
3348        offset += FullBoxHeader::from_box(self).encode(&mut buf[offset..])?;
3349        match self {
3350            StszBox::Fixed {
3351                sample_size,
3352                sample_count,
3353            } => {
3354                offset += sample_size.get().encode(&mut buf[offset..])?;
3355                offset += sample_count.encode(&mut buf[offset..])?;
3356            }
3357            StszBox::Variable { entry_sizes } => {
3358                offset += 0u32.encode(&mut buf[offset..])?;
3359                offset += (entry_sizes.len() as u32).encode(&mut buf[offset..])?;
3360                for size in entry_sizes {
3361                    offset += size.encode(&mut buf[offset..])?;
3362                }
3363            }
3364        }
3365        header.finalize_box_size(&mut buf[..offset])?;
3366        Ok(offset)
3367    }
3368}
3369
3370impl Decode for StszBox {
3371    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
3372        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
3373        header.box_type.expect(Self::TYPE)?;
3374
3375        let mut offset = 0;
3376        let _full_header = FullBoxHeader::decode_at(payload, &mut offset)?;
3377        let sample_size = u32::decode_at(payload, &mut offset)?;
3378        let sample_count = u32::decode_at(payload, &mut offset)?;
3379
3380        let stsz_box = if let Some(sample_size) = NonZeroU32::new(sample_size) {
3381            Self::Fixed {
3382                sample_size,
3383                sample_count,
3384            }
3385        } else {
3386            let mut entry_sizes = Vec::with_capacity(sample_count as usize);
3387            for _ in 0..sample_count {
3388                entry_sizes.push(u32::decode_at(payload, &mut offset)?);
3389            }
3390            Self::Variable { entry_sizes }
3391        };
3392
3393        Ok((stsz_box, header.external_size() + payload.len()))
3394    }
3395}
3396
3397impl BaseBox for StszBox {
3398    fn box_type(&self) -> BoxType {
3399        Self::TYPE
3400    }
3401
3402    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
3403        Box::new(core::iter::empty())
3404    }
3405}
3406
3407impl FullBox for StszBox {
3408    fn full_box_version(&self) -> u8 {
3409        0
3410    }
3411
3412    fn full_box_flags(&self) -> FullBoxFlags {
3413        FullBoxFlags::new(0)
3414    }
3415}
3416
3417/// [ISO/IEC 14496-12] ChunkOffsetBox class (親: [`StblBox`])
3418#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3419#[allow(missing_docs)]
3420pub struct StcoBox {
3421    pub chunk_offsets: Vec<u32>,
3422}
3423
3424impl StcoBox {
3425    /// ボックス種別
3426    pub const TYPE: BoxType = BoxType::Normal(*b"stco");
3427}
3428
3429impl Encode for StcoBox {
3430    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
3431        let header = BoxHeader::new_variable_size(Self::TYPE);
3432        let mut offset = header.encode(buf)?;
3433        offset += FullBoxHeader::from_box(self).encode(&mut buf[offset..])?;
3434        offset += (self.chunk_offsets.len() as u32).encode(&mut buf[offset..])?;
3435        for offset_val in &self.chunk_offsets {
3436            offset += offset_val.encode(&mut buf[offset..])?;
3437        }
3438        header.finalize_box_size(&mut buf[..offset])?;
3439        Ok(offset)
3440    }
3441}
3442
3443impl Decode for StcoBox {
3444    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
3445        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
3446        header.box_type.expect(Self::TYPE)?;
3447
3448        let mut offset = 0;
3449        let _full_header = FullBoxHeader::decode_at(payload, &mut offset)?;
3450        let count = u32::decode_at(payload, &mut offset)?;
3451
3452        let mut chunk_offsets = Vec::with_capacity(count as usize);
3453        for _ in 0..count {
3454            chunk_offsets.push(u32::decode_at(payload, &mut offset)?);
3455        }
3456
3457        Ok((
3458            Self { chunk_offsets },
3459            header.external_size() + payload.len(),
3460        ))
3461    }
3462}
3463
3464impl BaseBox for StcoBox {
3465    fn box_type(&self) -> BoxType {
3466        Self::TYPE
3467    }
3468
3469    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
3470        Box::new(core::iter::empty())
3471    }
3472}
3473
3474impl FullBox for StcoBox {
3475    fn full_box_version(&self) -> u8 {
3476        0
3477    }
3478
3479    fn full_box_flags(&self) -> FullBoxFlags {
3480        FullBoxFlags::new(0)
3481    }
3482}
3483
3484/// [ISO/IEC 14496-12] ChunkLargeOffsetBox class (親: [`StblBox`])
3485#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3486#[allow(missing_docs)]
3487pub struct Co64Box {
3488    pub chunk_offsets: Vec<u64>,
3489}
3490
3491impl Co64Box {
3492    /// ボックス種別
3493    pub const TYPE: BoxType = BoxType::Normal(*b"co64");
3494}
3495
3496impl Encode for Co64Box {
3497    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
3498        let header = BoxHeader::new_variable_size(Self::TYPE);
3499        let mut offset = header.encode(buf)?;
3500        offset += FullBoxHeader::from_box(self).encode(&mut buf[offset..])?;
3501        offset += (self.chunk_offsets.len() as u32).encode(&mut buf[offset..])?;
3502        for offset_val in &self.chunk_offsets {
3503            offset += offset_val.encode(&mut buf[offset..])?;
3504        }
3505        header.finalize_box_size(&mut buf[..offset])?;
3506        Ok(offset)
3507    }
3508}
3509
3510impl Decode for Co64Box {
3511    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
3512        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
3513        header.box_type.expect(Self::TYPE)?;
3514
3515        let mut offset = 0;
3516        let _full_header = FullBoxHeader::decode_at(payload, &mut offset)?;
3517        let count = u32::decode_at(payload, &mut offset)?;
3518
3519        let mut chunk_offsets = Vec::with_capacity(count as usize);
3520        for _ in 0..count {
3521            chunk_offsets.push(u64::decode_at(payload, &mut offset)?);
3522        }
3523
3524        Ok((
3525            Self { chunk_offsets },
3526            header.external_size() + payload.len(),
3527        ))
3528    }
3529}
3530
3531impl BaseBox for Co64Box {
3532    fn box_type(&self) -> BoxType {
3533        Self::TYPE
3534    }
3535
3536    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
3537        Box::new(core::iter::empty())
3538    }
3539}
3540
3541impl FullBox for Co64Box {
3542    fn full_box_version(&self) -> u8 {
3543        0
3544    }
3545
3546    fn full_box_flags(&self) -> FullBoxFlags {
3547        FullBoxFlags::new(0)
3548    }
3549}
3550
3551/// [ISO/IEC 14496-12] SyncSampleBox class (親: [`StssBox`])
3552#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3553#[allow(missing_docs)]
3554pub struct StssBox {
3555    pub sample_numbers: Vec<NonZeroU32>,
3556}
3557
3558impl StssBox {
3559    /// ボックス種別
3560    pub const TYPE: BoxType = BoxType::Normal(*b"stss");
3561}
3562
3563impl Encode for StssBox {
3564    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
3565        let header = BoxHeader::new_variable_size(Self::TYPE);
3566        let mut offset = header.encode(buf)?;
3567        offset += FullBoxHeader::from_box(self).encode(&mut buf[offset..])?;
3568        offset += (self.sample_numbers.len() as u32).encode(&mut buf[offset..])?;
3569        for offset_val in &self.sample_numbers {
3570            offset += offset_val.encode(&mut buf[offset..])?;
3571        }
3572        header.finalize_box_size(&mut buf[..offset])?;
3573        Ok(offset)
3574    }
3575}
3576
3577impl Decode for StssBox {
3578    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
3579        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
3580        header.box_type.expect(Self::TYPE)?;
3581
3582        let mut offset = 0;
3583        let _full_header = FullBoxHeader::decode_at(payload, &mut offset)?;
3584        let count = u32::decode_at(payload, &mut offset)?;
3585
3586        let mut sample_numbers = Vec::with_capacity(count as usize);
3587        for _ in 0..count {
3588            sample_numbers.push(NonZeroU32::decode_at(payload, &mut offset)?);
3589        }
3590
3591        Ok((
3592            Self { sample_numbers },
3593            header.external_size() + payload.len(),
3594        ))
3595    }
3596}
3597
3598impl BaseBox for StssBox {
3599    fn box_type(&self) -> BoxType {
3600        Self::TYPE
3601    }
3602
3603    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
3604        Box::new(core::iter::empty())
3605    }
3606}
3607
3608impl FullBox for StssBox {
3609    fn full_box_version(&self) -> u8 {
3610        0
3611    }
3612
3613    fn full_box_flags(&self) -> FullBoxFlags {
3614        FullBoxFlags::new(0)
3615    }
3616}
3617
3618/// [<https://gitlab.xiph.org/xiph/opus/-/blob/main/doc/opus_in_isobmff.html>] OpusSampleEntry class (親: [`StsdBox`])
3619#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3620#[allow(missing_docs)]
3621pub struct OpusBox {
3622    pub audio: AudioSampleEntryFields,
3623    pub dops_box: DopsBox,
3624    pub unknown_boxes: Vec<UnknownBox>,
3625}
3626
3627impl OpusBox {
3628    /// ボックス種別
3629    pub const TYPE: BoxType = BoxType::Normal(*b"Opus");
3630}
3631
3632impl Encode for OpusBox {
3633    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
3634        let header = BoxHeader::new_variable_size(Self::TYPE);
3635        let mut offset = header.encode(buf)?;
3636        offset += self.audio.encode(&mut buf[offset..])?;
3637        offset += self.dops_box.encode(&mut buf[offset..])?;
3638        for b in &self.unknown_boxes {
3639            offset += b.encode(&mut buf[offset..])?;
3640        }
3641        header.finalize_box_size(&mut buf[..offset])?;
3642        Ok(offset)
3643    }
3644}
3645
3646impl Decode for OpusBox {
3647    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
3648        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
3649        header.box_type.expect(Self::TYPE)?;
3650
3651        let mut offset = 0;
3652        let audio = AudioSampleEntryFields::decode_at(payload, &mut offset)?;
3653
3654        let mut dops_box = None;
3655        let mut unknown_boxes = Vec::new();
3656
3657        while offset < payload.len() {
3658            let (child_header, _) = BoxHeader::decode(&payload[offset..])?;
3659            match child_header.box_type {
3660                DopsBox::TYPE if dops_box.is_none() => {
3661                    dops_box = Some(DopsBox::decode_at(payload, &mut offset)?);
3662                }
3663                _ => {
3664                    unknown_boxes.push(UnknownBox::decode_at(payload, &mut offset)?);
3665                }
3666            }
3667        }
3668
3669        Ok((
3670            Self {
3671                audio,
3672                dops_box: check_mandatory_box(dops_box, "dops", "Opus")?,
3673                unknown_boxes,
3674            },
3675            header.external_size() + payload.len(),
3676        ))
3677    }
3678}
3679
3680impl BaseBox for OpusBox {
3681    fn box_type(&self) -> BoxType {
3682        Self::TYPE
3683    }
3684
3685    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
3686        Box::new(
3687            core::iter::empty()
3688                .chain(core::iter::once(&self.dops_box).map(as_box_object))
3689                .chain(self.unknown_boxes.iter().map(as_box_object)),
3690        )
3691    }
3692}
3693
3694/// [ISO/IEC 14496-14] MP4AudioSampleEntry class
3695#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3696#[allow(missing_docs)]
3697pub struct Mp4aBox {
3698    pub audio: AudioSampleEntryFields,
3699    pub esds_box: EsdsBox,
3700    pub unknown_boxes: Vec<UnknownBox>,
3701}
3702
3703impl Mp4aBox {
3704    /// ボックス種別
3705    pub const TYPE: BoxType = BoxType::Normal(*b"mp4a");
3706}
3707
3708impl Encode for Mp4aBox {
3709    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
3710        let header = BoxHeader::new_variable_size(Self::TYPE);
3711        let mut offset = header.encode(buf)?;
3712        offset += self.audio.encode(&mut buf[offset..])?;
3713        offset += self.esds_box.encode(&mut buf[offset..])?;
3714        for b in &self.unknown_boxes {
3715            offset += b.encode(&mut buf[offset..])?;
3716        }
3717        header.finalize_box_size(&mut buf[..offset])?;
3718        Ok(offset)
3719    }
3720}
3721
3722impl Decode for Mp4aBox {
3723    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
3724        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
3725        header.box_type.expect(Self::TYPE)?;
3726
3727        let mut offset = 0;
3728        let audio = AudioSampleEntryFields::decode_at(payload, &mut offset)?;
3729
3730        let mut esds_box = None;
3731        let mut unknown_boxes = Vec::new();
3732
3733        while offset < payload.len() {
3734            let (child_header, _) = BoxHeader::decode(&payload[offset..])?;
3735            match child_header.box_type {
3736                EsdsBox::TYPE if esds_box.is_none() => {
3737                    esds_box = Some(EsdsBox::decode_at(payload, &mut offset)?);
3738                }
3739                _ => {
3740                    unknown_boxes.push(UnknownBox::decode_at(payload, &mut offset)?);
3741                }
3742            }
3743        }
3744
3745        Ok((
3746            Self {
3747                audio,
3748                esds_box: check_mandatory_box(esds_box, "esds", "mp4a")?,
3749                unknown_boxes,
3750            },
3751            header.external_size() + payload.len(),
3752        ))
3753    }
3754}
3755
3756impl BaseBox for Mp4aBox {
3757    fn box_type(&self) -> BoxType {
3758        Self::TYPE
3759    }
3760
3761    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
3762        Box::new(
3763            core::iter::empty()
3764                .chain(core::iter::once(&self.esds_box).map(as_box_object))
3765                .chain(self.unknown_boxes.iter().map(as_box_object)),
3766        )
3767    }
3768}
3769
3770/// 音声系の [`SampleEntry`] に共通のフィールドをまとめた構造体
3771#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3772#[allow(missing_docs)]
3773pub struct AudioSampleEntryFields {
3774    pub data_reference_index: NonZeroU16,
3775    pub channelcount: u16,
3776    pub samplesize: u16,
3777    pub samplerate: FixedPointNumber<u16, u16>,
3778}
3779
3780impl AudioSampleEntryFields {
3781    /// [`AudioSampleEntryFields::data_reference_index`] のデフォルト値
3782    pub const DEFAULT_DATA_REFERENCE_INDEX: NonZeroU16 = NonZeroU16::MIN;
3783
3784    /// [`AudioSampleEntryFields::sample_size`] のデフォルト値 (16)
3785    pub const DEFAULT_SAMPLESIZE: u16 = 16;
3786}
3787
3788impl Encode for AudioSampleEntryFields {
3789    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
3790        let mut offset = 0;
3791        offset += [0u8; 6].encode(&mut buf[offset..])?;
3792        offset += self.data_reference_index.encode(&mut buf[offset..])?;
3793        offset += [0u8; 4 * 2].encode(&mut buf[offset..])?;
3794        offset += self.channelcount.encode(&mut buf[offset..])?;
3795        offset += self.samplesize.encode(&mut buf[offset..])?;
3796        offset += [0u8; 2].encode(&mut buf[offset..])?;
3797        offset += [0u8; 2].encode(&mut buf[offset..])?;
3798        offset += self.samplerate.encode(&mut buf[offset..])?;
3799        Ok(offset)
3800    }
3801}
3802
3803impl Decode for AudioSampleEntryFields {
3804    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
3805        let mut offset = 0;
3806        let _ = <[u8; 6]>::decode_at(buf, &mut offset)?;
3807        let data_reference_index = NonZeroU16::decode_at(buf, &mut offset)?;
3808        let _ = <[u8; 4 * 2]>::decode_at(buf, &mut offset)?;
3809        let channelcount = u16::decode_at(buf, &mut offset)?;
3810        let samplesize = u16::decode_at(buf, &mut offset)?;
3811        let _ = <[u8; 2]>::decode_at(buf, &mut offset)?;
3812        let _ = <[u8; 2]>::decode_at(buf, &mut offset)?;
3813        let samplerate = FixedPointNumber::decode_at(buf, &mut offset)?;
3814        Ok((
3815            Self {
3816                data_reference_index,
3817                channelcount,
3818                samplesize,
3819                samplerate,
3820            },
3821            offset,
3822        ))
3823    }
3824}
3825
3826/// [<https://gitlab.xiph.org/xiph/opus/-/blob/main/doc/opus_in_isobmff.html>] OpusSpecificBox class (親: [`OpusBox`])
3827#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3828#[allow(missing_docs)]
3829pub struct DopsBox {
3830    pub output_channel_count: u8,
3831    pub pre_skip: u16,
3832    pub input_sample_rate: u32,
3833    pub output_gain: i16,
3834}
3835
3836impl DopsBox {
3837    /// ボックス種別
3838    pub const TYPE: BoxType = BoxType::Normal(*b"dOps");
3839
3840    const VERSION: u8 = 0;
3841}
3842
3843impl Encode for DopsBox {
3844    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
3845        let header = BoxHeader::new_variable_size(Self::TYPE);
3846        let mut offset = header.encode(buf)?;
3847        offset += Self::VERSION.encode(&mut buf[offset..])?;
3848        offset += self.output_channel_count.encode(&mut buf[offset..])?;
3849        offset += self.pre_skip.encode(&mut buf[offset..])?;
3850        offset += self.input_sample_rate.encode(&mut buf[offset..])?;
3851        offset += self.output_gain.encode(&mut buf[offset..])?;
3852        offset += 0u8.encode(&mut buf[offset..])?; // ChannelMappingFamily
3853        header.finalize_box_size(&mut buf[..offset])?;
3854        Ok(offset)
3855    }
3856}
3857
3858impl Decode for DopsBox {
3859    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
3860        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
3861        header.box_type.expect(Self::TYPE)?;
3862
3863        let mut offset = 0;
3864        let version = u8::decode_at(payload, &mut offset)?;
3865        if version != Self::VERSION {
3866            return Err(Error::invalid_data(format!(
3867                "Unsupported dOps version: {version}"
3868            )));
3869        }
3870
3871        let output_channel_count = u8::decode_at(payload, &mut offset)?;
3872        let pre_skip = u16::decode_at(payload, &mut offset)?;
3873        let input_sample_rate = u32::decode_at(payload, &mut offset)?;
3874        let output_gain = i16::decode_at(payload, &mut offset)?;
3875        let channel_mapping_family = u8::decode_at(payload, &mut offset)?;
3876        if channel_mapping_family != 0 {
3877            return Err(Error::unsupported(
3878                "`ChannelMappingFamily != 0` in 'dOps' box is not supported",
3879            ));
3880        }
3881
3882        Ok((
3883            Self {
3884                output_channel_count,
3885                pre_skip,
3886                input_sample_rate,
3887                output_gain,
3888            },
3889            header.external_size() + payload.len(),
3890        ))
3891    }
3892}
3893
3894impl BaseBox for DopsBox {
3895    fn box_type(&self) -> BoxType {
3896        Self::TYPE
3897    }
3898
3899    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
3900        Box::new(core::iter::empty())
3901    }
3902}
3903
3904/// [ISO/IEC 14496-14] ESDBox class
3905#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3906#[allow(missing_docs)]
3907pub struct EsdsBox {
3908    pub es: EsDescriptor,
3909}
3910
3911impl EsdsBox {
3912    /// ボックス種別
3913    pub const TYPE: BoxType = BoxType::Normal(*b"esds");
3914}
3915
3916impl Encode for EsdsBox {
3917    fn encode(&self, buf: &mut [u8]) -> Result<usize> {
3918        let header = BoxHeader::new_variable_size(Self::TYPE);
3919        let mut offset = header.encode(buf)?;
3920        offset += FullBoxHeader::from_box(self).encode(&mut buf[offset..])?;
3921        offset += self.es.encode(&mut buf[offset..])?;
3922        header.finalize_box_size(&mut buf[..offset])?;
3923        Ok(offset)
3924    }
3925}
3926
3927impl Decode for EsdsBox {
3928    fn decode(buf: &[u8]) -> Result<(Self, usize)> {
3929        let (header, payload) = BoxHeader::decode_header_and_payload(buf)?;
3930        header.box_type.expect(Self::TYPE)?;
3931
3932        let mut offset = 0;
3933        let _full_header = FullBoxHeader::decode_at(payload, &mut offset)?;
3934        let es = EsDescriptor::decode_at(payload, &mut offset)?;
3935
3936        Ok((Self { es }, header.external_size() + payload.len()))
3937    }
3938}
3939
3940impl BaseBox for EsdsBox {
3941    fn box_type(&self) -> BoxType {
3942        Self::TYPE
3943    }
3944
3945    fn children<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = &'a dyn BaseBox>> {
3946        Box::new(core::iter::empty())
3947    }
3948}
3949
3950impl FullBox for EsdsBox {
3951    fn full_box_version(&self) -> u8 {
3952        0
3953    }
3954
3955    fn full_box_flags(&self) -> FullBoxFlags {
3956        FullBoxFlags::new(0)
3957    }
3958}
3959
3960#[track_caller]
3961fn check_mandatory_box<T>(maybe_box: Option<T>, expected: &str, parent: &str) -> Result<T> {
3962    maybe_box.ok_or_else(|| {
3963        Error::invalid_data(format!(
3964            "Missing mandatory '{expected}' box in '{parent}' box"
3965        ))
3966    })
3967}