isobmff/boxes/
audio_media.rs

1use std::io;
2
3use fixed::types::extra::{U8, U16};
4use fixed::{FixedI16, FixedU32};
5use scuffle_bytes_util::zero_copy::{Deserialize, DeserializeSeed, Serialize};
6use scuffle_bytes_util::{BitWriter, BytesCow};
7
8use super::SampleEntry;
9use crate::utils::pad_to_u64;
10use crate::{BoxHeader, FullBoxHeader, IsoBox, IsoSized};
11
12/// Sound media header
13///
14/// ISO/IEC 14496-12 - 12.2.2
15#[derive(IsoBox, Debug, PartialEq, Eq, Default)]
16#[iso_box(box_type = b"smhd", skip_impl(deserialize_seed, serialize, sized), crate_path = crate)]
17pub struct SoundMediaHeaderBox {
18    /// The full box header.
19    pub full_header: FullBoxHeader,
20    /// A number that places mono audio tracks in a stereo space; 0 is centre (the
21    /// normal value); full left is -1.0 and full right is 1.0.
22    pub balance: FixedI16<U8>,
23    /// Reserved 16 bits, must be set to 0.
24    pub reserved: u16,
25}
26
27impl<'a> DeserializeSeed<'a, BoxHeader> for SoundMediaHeaderBox {
28    fn deserialize_seed<R>(mut reader: R, _seed: BoxHeader) -> io::Result<Self>
29    where
30        R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
31    {
32        let full_header = FullBoxHeader::deserialize(&mut reader)?;
33        let balance = FixedI16::from_bits(i16::deserialize(&mut reader)?);
34        let reserved = u16::deserialize(&mut reader)?;
35
36        Ok(Self {
37            full_header,
38            balance,
39            reserved,
40        })
41    }
42}
43
44impl Serialize for SoundMediaHeaderBox {
45    fn serialize<W>(&self, mut writer: W) -> io::Result<()>
46    where
47        W: std::io::Write,
48    {
49        self.serialize_box_header(&mut writer)?;
50        self.full_header.serialize(&mut writer)?;
51        self.balance.to_bits().serialize(&mut writer)?;
52        self.reserved.serialize(&mut writer)?;
53        Ok(())
54    }
55}
56
57impl IsoSized for SoundMediaHeaderBox {
58    fn size(&self) -> usize {
59        Self::add_header_size(self.full_header.size() + 2 + 2)
60    }
61}
62
63/// Audio sample entry
64///
65/// ISO/IEC 14496-12 - 12.2.3
66///
67/// Sub boxes:
68/// - [`btrt`](super::BitRateBox)
69/// - [`chnl`](ChannelLayout)
70/// - [`dmix`](DownMixInstructions)
71/// - `udc1` (`DRCCoefficientsBasic`, defined in ISO/IEC 23003-4)
72/// - `udi1` (`DRCInstructionsBasic`, defined in ISO/IEC 23003-4)
73/// - `udc2` (`DRCCoefficientsUniDRC`, defined in ISO/IEC 23003-4)
74/// - `udi2` (`DRCInstructionsUniDRC`, defined in ISO/IEC 23003-4)
75/// - `udex` (`UniDrcConfigExtension`, defined in ISO/IEC 23003-4)
76/// - [`srat`](SamplingRateBox)
77/// - Any other boxes
78#[derive(Debug, PartialEq, Eq)]
79pub struct AudioSampleEntry {
80    /// The sample entry that this entry inherits from.
81    pub sample_entry: SampleEntry,
82    /// Reserved 64 bits, must be set to 0.
83    pub reserved1: u64,
84    /// The number of channels.
85    ///
86    /// - 0: inapplicable/unknown
87    /// - 1: mono
88    /// - 2: stereo (left/right)
89    /// - all other values: the codec configuration should identify the channel assignment.
90    pub channelcount: u16,
91    /// In bits, and takes the default value of 16.
92    pub samplesize: u16,
93    /// Pre-defined 16 bit value, must be set to 0.
94    pub pre_defined: u16,
95    /// Reserved 16 bits, must be set to 0.
96    pub reserved2: u16,
97    /// When a [`SamplingRateBox`] is absent is the sampling rate; when a [`SamplingRateBox`] is present,
98    /// is a suitable integer multiple or division of the actual sampling rate.
99    pub samplerate: FixedU32<U16>,
100}
101
102impl AudioSampleEntry {
103    /// Creates a new [`AudioSampleEntry`] with the given parameters.
104    pub fn new(sample_entry: SampleEntry, channelcount: u16, samplesize: u16, samplerate: FixedU32<U16>) -> Self {
105        Self {
106            sample_entry,
107            reserved1: 0,
108            channelcount,
109            samplesize,
110            pre_defined: 0,
111            reserved2: 0,
112            samplerate,
113        }
114    }
115}
116
117impl<'a> Deserialize<'a> for AudioSampleEntry {
118    fn deserialize<R>(mut reader: R) -> std::io::Result<Self>
119    where
120        R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
121    {
122        let sample_entry = SampleEntry::deserialize(&mut reader)?;
123        let reserved1 = u64::deserialize(&mut reader)?;
124        let channelcount = u16::deserialize(&mut reader)?;
125        let samplesize = u16::deserialize(&mut reader)?;
126        let pre_defined = u16::deserialize(&mut reader)?;
127        let reserved2 = u16::deserialize(&mut reader)?;
128        let samplerate = FixedU32::from_bits(u32::deserialize(&mut reader)?);
129
130        Ok(Self {
131            sample_entry,
132            reserved1,
133            channelcount,
134            samplesize,
135            pre_defined,
136            reserved2,
137            samplerate,
138        })
139    }
140}
141
142impl Serialize for AudioSampleEntry {
143    fn serialize<W>(&self, mut writer: W) -> std::io::Result<()>
144    where
145        W: std::io::Write,
146    {
147        self.sample_entry.serialize(&mut writer)?;
148        self.reserved1.serialize(&mut writer)?;
149        self.channelcount.serialize(&mut writer)?;
150        self.samplesize.serialize(&mut writer)?;
151        self.pre_defined.serialize(&mut writer)?;
152        self.reserved2.serialize(&mut writer)?;
153        self.samplerate.to_bits().serialize(&mut writer)?;
154        Ok(())
155    }
156}
157
158impl IsoSized for AudioSampleEntry {
159    fn size(&self) -> usize {
160        self.sample_entry.size()
161            + 8 // reserved1
162            + 2 // channelcount
163            + 2 // samplesize
164            + 2 // pre_defined
165            + 2 // reserved2
166            + 4 // samplerate
167    }
168}
169
170/// Sampling rate box
171///
172/// ISO/IEC 14496-12 - 12.2.3
173#[derive(IsoBox, Debug, PartialEq, Eq)]
174#[iso_box(box_type = b"srat", crate_path = crate)]
175pub struct SamplingRateBox {
176    /// The full box header.
177    pub full_header: FullBoxHeader,
178    /// The actual sampling rate of the audio media in samples/second, expressed as a 32-bit integer.
179    pub sampling_rate: u32,
180}
181
182/// Audio sample entry version 1
183///
184/// ISO/IEC 14496-12 - 12.2.3
185///
186/// Sub boxes:
187/// - [`btrt`](super::BitRateBox)
188/// - [`srat`](SamplingRateBox)
189/// - [`chnl`](ChannelLayout)
190/// - [`dmix`](DownMixInstructions)
191/// - `udc1` (`DRCCoefficientsBasic`, defined in ISO/IEC 23003-4)
192/// - `udi1` (`DRCInstructionsBasic`, defined in ISO/IEC 23003-4)
193/// - `udc2` (`DRCCoefficientsUniDRC`, defined in ISO/IEC 23003-4)
194/// - `udi2` (`DRCInstructionsUniDRC`, defined in ISO/IEC 23003-4)
195/// - `udex` (`UniDrcConfigExtension`, defined in ISO/IEC 23003-4)
196/// - Any other boxes
197#[derive(Debug, PartialEq, Eq)]
198pub struct AudioSampleEntryV1 {
199    /// The sample entry that this entry inherits from.
200    pub sample_entry: SampleEntry,
201    /// Shall be 1.
202    pub entry_version: u16,
203    /// Reserved 48 bits, must be set to 0.
204    pub reserved1: [u16; 3],
205    /// The number of channels.
206    ///
207    /// - 0: inapplicable/unknown
208    /// - 1: mono
209    /// - 2: stereo (left/right)
210    /// - all other values: the codec configuration should identify the channel assignment.
211    pub channelcount: u16,
212    /// In bits, and takes the default value of 16.
213    pub samplesize: u16,
214    /// Pre-defined 16 bit value, must be set to 0.
215    pub pre_defined: u16,
216    /// Reserved 16 bits, must be set to 0.
217    pub reserved2: u16,
218    /// When a [`SamplingRateBox`] is absent is the sampling rate; when a [`SamplingRateBox`] is present,
219    /// is a suitable integer multiple or division of the actual sampling rate.
220    pub samplerate: FixedU32<U16>,
221}
222
223impl<'a> Deserialize<'a> for AudioSampleEntryV1 {
224    fn deserialize<R>(mut reader: R) -> std::io::Result<Self>
225    where
226        R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
227    {
228        let sample_entry = SampleEntry::deserialize(&mut reader)?;
229        let entry_version = u16::deserialize(&mut reader)?;
230        let reserved1 = <[u16; 3]>::deserialize(&mut reader)?;
231        let channelcount = u16::deserialize(&mut reader)?;
232        let samplesize = u16::deserialize(&mut reader)?;
233        let pre_defined = u16::deserialize(&mut reader)?;
234        let reserved2 = u16::deserialize(&mut reader)?;
235        let samplerate = FixedU32::from_bits(u32::deserialize(&mut reader)?);
236
237        Ok(Self {
238            sample_entry,
239            entry_version,
240            reserved1,
241            channelcount,
242            samplesize,
243            pre_defined,
244            reserved2,
245            samplerate,
246        })
247    }
248}
249
250impl Serialize for AudioSampleEntryV1 {
251    fn serialize<W>(&self, mut writer: W) -> std::io::Result<()>
252    where
253        W: std::io::Write,
254    {
255        self.sample_entry.serialize(&mut writer)?;
256        self.entry_version.serialize(&mut writer)?;
257        self.reserved1.serialize(&mut writer)?;
258        self.channelcount.serialize(&mut writer)?;
259        self.samplesize.serialize(&mut writer)?;
260        self.pre_defined.serialize(&mut writer)?;
261        self.reserved2.serialize(&mut writer)?;
262        self.samplerate.to_bits().serialize(&mut writer)?;
263        Ok(())
264    }
265}
266
267impl IsoSized for AudioSampleEntryV1 {
268    fn size(&self) -> usize {
269        self.sample_entry.size()
270            + 2 // entry_version
271            + 2 * 3 // reserved1
272            + 2 // channelcount
273            + 2 // samplesize
274            + 2 // pre_defined
275            + 2 // reserved2
276            + 4 // samplerate
277    }
278}
279
280/// Channel layout
281///
282/// ISO/IEC 14496-12 - 12.2.4
283#[derive(IsoBox, Debug, PartialEq, Eq)]
284#[iso_box(box_type = b"chnl", crate_path = crate)]
285pub struct ChannelLayout<'a> {
286    /// The full box header.
287    pub full_header: FullBoxHeader,
288    /// The channel layout data. (not further implemented)
289    pub data: BytesCow<'a>,
290}
291
292/// Down mix instructions
293///
294/// ISO/IEC 14496-12 - 12.2.5
295#[derive(IsoBox, Debug, PartialEq, Eq)]
296#[iso_box(box_type = b"dmix", crate_path = crate)]
297pub struct DownMixInstructions<'a> {
298    /// The full box header.
299    pub full_header: FullBoxHeader,
300    /// The down mix instructions data. (not further implemented)
301    pub data: BytesCow<'a>,
302}
303
304/// Audio stream loudness base box
305///
306/// ISO/IEC 14496-12 - 12.2.7
307#[derive(Debug, PartialEq, Eq)]
308pub struct LoudnessBaseBox {
309    /// The type of audio scene described by the loudness information. It shall take a
310    /// value of zero unless other types are supported by the loudness processing. For defined values refer
311    /// to the corresponding `loudnessInfoType` specification in ISO/IEC 23008-3.
312    pub loudness_info_type: Option<u8>,
313    /// Count of loudness bases in the box.
314    pub loudness_base_count: u8,
315    /// `mae_group_ID` or `mae_group_preset_ID` depending on the value of `loudness_info_type`.
316    ///
317    /// - `mae_group_ID` is a unique identifier for a group of metadata elements as specified in ISO/IEC 23008-3.
318    /// - `mae_group_preset_ID` is a unique identifier for a group preset as specified in ISO/IEC 23008-3.
319    pub mae_group_id: Option<u8>,
320    /// The loudness bases contained in this box.
321    pub loudness_bases: Vec<LoudnessBase>,
322}
323
324impl<'a> DeserializeSeed<'a, &FullBoxHeader> for LoudnessBaseBox {
325    fn deserialize_seed<R>(mut reader: R, seed: &FullBoxHeader) -> std::io::Result<Self>
326    where
327        R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
328    {
329        let (loudness_info_type, loudness_base_count, mae_group_id) = if seed.version >= 2 {
330            let byte = u8::deserialize(&mut reader)?;
331            let loudness_info_type = (byte >> 6) & 0b11;
332            let loudness_base_count = byte & 0b0011_1111;
333            let mae_group_id = if loudness_info_type == 1 || loudness_info_type == 2 {
334                Some(u8::deserialize(&mut reader)? & 0b0111_1111)
335            } else if loudness_info_type == 3 {
336                Some(u8::deserialize(&mut reader)? & 0b0001_1111)
337            } else {
338                None
339            };
340            (Some(loudness_info_type), loudness_base_count, mae_group_id)
341        } else if seed.version == 1 {
342            let byte = u8::deserialize(&mut reader)?;
343            (None, byte & 0b0011_1111, None)
344        } else {
345            (None, 1, None)
346        };
347
348        let mut loudness_bases = Vec::with_capacity(loudness_base_count as usize);
349        for _ in 0..loudness_base_count {
350            loudness_bases.push(LoudnessBase::deserialize_seed(&mut reader, seed)?);
351        }
352
353        Ok(Self {
354            loudness_info_type,
355            loudness_base_count,
356            mae_group_id,
357            loudness_bases,
358        })
359    }
360}
361
362impl LoudnessBaseBox {
363    fn serialize<W>(&self, writer: W, version: u8) -> std::io::Result<()>
364    where
365        W: std::io::Write,
366    {
367        let mut bit_writer = BitWriter::new(writer);
368
369        if version >= 2 {
370            let loudness_info_type = self
371                .loudness_info_type
372                .ok_or(io::Error::new(io::ErrorKind::InvalidData, "loudness_info_type is required"))?;
373            bit_writer.write_bits(loudness_info_type as u64, 2)?;
374            bit_writer.write_bits(self.loudness_base_count as u64, 6)?;
375
376            if loudness_info_type == 1 || loudness_info_type == 2 {
377                bit_writer.write_bit(false)?;
378                bit_writer.write_bits(
379                    self.mae_group_id
380                        .ok_or(io::Error::new(io::ErrorKind::InvalidData, "mae_group_ID is required"))?
381                        as u64,
382                    7,
383                )?;
384            } else if loudness_info_type == 3 {
385                bit_writer.write_bits(0, 3)?;
386                bit_writer.write_bits(
387                    self.mae_group_id
388                        .ok_or(io::Error::new(io::ErrorKind::InvalidData, "mae_group_preset_ID is required"))?
389                        as u64,
390                    5,
391                )?;
392            }
393        } else if version == 1 {
394            bit_writer.write_bits(0, 2)?;
395            bit_writer.write_bits(self.loudness_base_count as u64, 6)?;
396        }
397
398        for loudness_base in &self.loudness_bases {
399            loudness_base.serialize(&mut bit_writer, version)?;
400        }
401
402        Ok(())
403    }
404}
405
406impl LoudnessBaseBox {
407    /// Returns the size of the box in bytes, depending on the version.
408    pub fn size(&self, version: u8) -> usize {
409        let mut size = 0;
410
411        if version >= 2 {
412            size += 1; // loudness_base_count + reserved
413            if self.loudness_info_type.is_some_and(|t| t == 1 || t == 2 || t == 3) {
414                size += 1; // mae_group_ID or mae_group_preset_ID + reserved
415            }
416        } else if version == 1 {
417            size += 1; // loudness_base_count + reserved
418        }
419
420        size += self.loudness_bases.size();
421
422        size
423    }
424}
425
426/// Loudness base in [`LoudnessBaseBox`].
427#[derive(Debug, PartialEq, Eq)]
428pub struct LoudnessBase {
429    /// When zero, declares the characteristics without applying EQ. If non-zero, this box declares
430    /// the loudness after applying the EQ with the matching `EQ_set_ID` and shall match a value in exactly
431    /// one box in the `UniDrcConfigExtension` of this track.
432    pub eq_set_id: Option<u8>,
433    /// When zero, declares the loudness characteristics of the layout without downmix. If non-zero,
434    /// this box declares the loudness after applying the downmix with the matching `downmix_ID` and
435    /// shall match a value in exactly one box in the sample entry of this track.
436    pub downmix_id: u8,
437    /// When zero, declares the characteristics without applying a DRC. If non-zero, this box
438    /// declares the loudness after applying the DRC with the matching DRC_set_ID and shall match a
439    /// value in exactly one box in the sample entry of this track.
440    pub drc_set_id: u8,
441    /// A value for the sample peak level as defined in ISO/IEC 23003-4; all other values are reserved.
442    pub bs_sample_peak_level: i16,
443    /// A value for the true peak level as defined in ISO/IEC 23003-4; all other values are reserved.
444    pub bs_true_peak_level: i16,
445    /// An index for the measurement system as defined in ISO/IEC 23003-4; all other values are reserved.
446    pub measurement_system_for_tp: u8,
447    /// - 0: Reliability is unknown.
448    /// - 1: Value is reported/imported but unverified.
449    /// - 2: Value is a 'not to exceed' ceiling.
450    /// - 3: Value is measured and accurate.
451    /// - 4: All other values are reserved.
452    pub reliability_for_tp: u8,
453    /// The number of measurements in the [`measurements`](Self::measurements) vec.
454    pub measurement_count: u8,
455    /// The measurements.
456    pub measurements: Vec<LoudnessBaseMeasurement>,
457}
458
459impl<'a> DeserializeSeed<'a, &FullBoxHeader> for LoudnessBase {
460    fn deserialize_seed<R>(mut reader: R, seed: &FullBoxHeader) -> std::io::Result<Self>
461    where
462        R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
463    {
464        let eq_set_id = if seed.version >= 1 {
465            Some(u8::deserialize(&mut reader)? & 0b0011_1111)
466        } else {
467            None
468        };
469
470        let bytes = u16::deserialize(&mut reader)?;
471        let downmix_id = ((bytes >> 6) & 0b00_0111_1111) as u8;
472        let drc_set_id = (bytes & 0b11_1111) as u8;
473
474        let bytes = u32::deserialize(&mut reader)?;
475        let bs_sample_peak_level = (bytes >> 20) as i16;
476        let bs_true_peak_level = ((bytes >> 8) & 0b1111_1111_1111) as i16;
477        let measurement_system_for_tp = ((bytes >> 4) & 0b1111) as u8;
478        let reliability_for_tp = (bytes & 0b1111) as u8;
479
480        let measurement_count = u8::deserialize(&mut reader)?;
481        let mut measurements = Vec::with_capacity(measurement_count as usize);
482        for _ in 0..measurement_count {
483            measurements.push(LoudnessBaseMeasurement::deserialize(&mut reader)?);
484        }
485
486        Ok(Self {
487            eq_set_id,
488            downmix_id,
489            drc_set_id,
490            bs_sample_peak_level,
491            bs_true_peak_level,
492            measurement_system_for_tp,
493            reliability_for_tp,
494            measurement_count,
495            measurements,
496        })
497    }
498}
499
500impl LoudnessBase {
501    fn serialize<W>(&self, writer: W, version: u8) -> std::io::Result<()>
502    where
503        W: std::io::Write,
504    {
505        let mut bit_writer = BitWriter::new(writer);
506
507        if version >= 1 {
508            bit_writer.write_bits(0, 2)?;
509            bit_writer.write_bits(
510                self.eq_set_id
511                    .ok_or(io::Error::new(io::ErrorKind::InvalidData, "eq_set_ID is required"))? as u64,
512                6,
513            )?;
514        }
515
516        bit_writer.write_bits(0, 3)?;
517        bit_writer.write_bits(self.downmix_id as u64, 7)?;
518        bit_writer.write_bits(self.drc_set_id as u64, 6)?;
519
520        bit_writer.write_bits(pad_to_u64(&self.bs_sample_peak_level.to_be_bytes()), 12)?;
521        bit_writer.write_bits(pad_to_u64(&self.bs_true_peak_level.to_be_bytes()), 12)?;
522        bit_writer.write_bits(self.measurement_system_for_tp as u64, 4)?;
523        bit_writer.write_bits(self.reliability_for_tp as u64, 4)?;
524
525        self.measurement_count.serialize(&mut bit_writer)?;
526        for measurement in &self.measurements {
527            measurement.serialize(&mut bit_writer)?;
528        }
529
530        Ok(())
531    }
532}
533
534impl IsoSized for LoudnessBase {
535    fn size(&self) -> usize {
536        let mut size = 0;
537        if self.eq_set_id.is_some() {
538            size += 1;
539        }
540
541        size += 2; // downmix_id + drc_set_id
542        size += 4; // bs_sample_peak_level + bs_true_peak_level + measurement_system_for_tp + reliability_for_tp
543        size += 1; // measurement_count
544        size += self.measurements.size();
545        size
546    }
547}
548
549/// Measurement in [`LoudnessBase`].
550#[derive(Debug, PartialEq, Eq)]
551pub struct LoudnessBaseMeasurement {
552    /// An index for the measurement method as defined in ISO/IEC 23003-4; all others are reserved.
553    pub method_definition: u8,
554    /// The method value.
555    ///
556    /// See [`method_definition`](Self::method_definition).
557    pub method_value: u8,
558    /// An index for the measurement system as defined in ISO/IEC 23003-4; all others are reserved.
559    pub measurement_system: u8,
560    /// - 0: Reliability is unknown.
561    /// - 1: Value is reported/imported but unverified.
562    /// - 2: Value is a 'not to exceed' ceiling.
563    /// - 3: Value is measured and accurate.
564    /// - 4: All other values are reserved.
565    pub reliability: u8,
566}
567
568impl<'a> Deserialize<'a> for LoudnessBaseMeasurement {
569    fn deserialize<R>(mut reader: R) -> std::io::Result<Self>
570    where
571        R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
572    {
573        let method_definition = u8::deserialize(&mut reader)?;
574        let method_value = u8::deserialize(&mut reader)?;
575        let byte = u8::deserialize(&mut reader)?;
576        let measurement_system = (byte >> 4) & 0x0F;
577        let reliability = byte & 0x0F;
578
579        Ok(Self {
580            method_definition,
581            method_value,
582            measurement_system,
583            reliability,
584        })
585    }
586}
587
588impl Serialize for LoudnessBaseMeasurement {
589    fn serialize<W>(&self, mut writer: W) -> std::io::Result<()>
590    where
591        W: std::io::Write,
592    {
593        self.method_definition.serialize(&mut writer)?;
594        self.method_value.serialize(&mut writer)?;
595
596        let mut byte = 0u8;
597        byte |= (self.measurement_system & 0b1111) << 4;
598        byte |= self.reliability & 0b1111;
599        byte.serialize(&mut writer)?;
600
601        Ok(())
602    }
603}
604
605impl IsoSized for LoudnessBaseMeasurement {
606    fn size(&self) -> usize {
607        1 // method_definition
608            + 1 // method_value
609            + 1 // measurement_system + reliability
610    }
611}
612
613/// Track loudness info
614///
615/// ISO/IEC 14496-12 - 12.2.7
616#[derive(IsoBox, Debug, PartialEq, Eq)]
617#[iso_box(box_type = b"tlou", skip_impl(deserialize_seed, serialize, sized), crate_path = crate)]
618pub struct TrackLoudnessInfo {
619    /// The full box header.
620    pub full_header: FullBoxHeader,
621    /// The loudness base box that this box inherits from.
622    pub base_box: LoudnessBaseBox,
623}
624
625impl<'a> DeserializeSeed<'a, BoxHeader> for TrackLoudnessInfo {
626    fn deserialize_seed<R>(mut reader: R, _seed: BoxHeader) -> std::io::Result<Self>
627    where
628        R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
629    {
630        let full_header = FullBoxHeader::deserialize(&mut reader)?;
631        let base_box = LoudnessBaseBox::deserialize_seed(&mut reader, &full_header)?;
632
633        Ok(Self { full_header, base_box })
634    }
635}
636
637impl Serialize for TrackLoudnessInfo {
638    fn serialize<W>(&self, mut writer: W) -> std::io::Result<()>
639    where
640        W: std::io::Write,
641    {
642        self.serialize_box_header(&mut writer)?;
643        self.full_header.serialize(&mut writer)?;
644        self.base_box.serialize(&mut writer, self.full_header.version)?;
645        Ok(())
646    }
647}
648
649impl IsoSized for TrackLoudnessInfo {
650    fn size(&self) -> usize {
651        Self::add_header_size(self.full_header.size() + self.base_box.size(self.full_header.version))
652    }
653}
654
655/// Album loudness info
656///
657/// ISO/IEC 14496-12 - 12.2.7
658#[derive(IsoBox, Debug, PartialEq, Eq)]
659#[iso_box(box_type = b"alou", skip_impl(deserialize_seed, serialize, sized), crate_path = crate)]
660pub struct AlbumLoudnessInfo {
661    /// The full box header.
662    pub full_header: FullBoxHeader,
663    /// The loudness base box that this box inherits from.
664    pub base_box: LoudnessBaseBox,
665}
666
667impl<'a> DeserializeSeed<'a, BoxHeader> for AlbumLoudnessInfo {
668    fn deserialize_seed<R>(mut reader: R, _seed: BoxHeader) -> std::io::Result<Self>
669    where
670        R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
671    {
672        let full_header = FullBoxHeader::deserialize(&mut reader)?;
673        let base_box = LoudnessBaseBox::deserialize_seed(&mut reader, &full_header)?;
674
675        Ok(Self { full_header, base_box })
676    }
677}
678
679impl Serialize for AlbumLoudnessInfo {
680    fn serialize<W>(&self, mut writer: W) -> std::io::Result<()>
681    where
682        W: std::io::Write,
683    {
684        self.serialize_box_header(&mut writer)?;
685        self.full_header.serialize(&mut writer)?;
686        self.base_box.serialize(&mut writer, self.full_header.version)?;
687        Ok(())
688    }
689}
690
691impl IsoSized for AlbumLoudnessInfo {
692    fn size(&self) -> usize {
693        Self::add_header_size(self.full_header.size() + self.base_box.size(self.full_header.version))
694    }
695}
696
697/// Loudness box
698///
699/// ISO/IEC 14496-12 - 12.2.7
700#[derive(IsoBox, Debug, PartialEq, Eq)]
701#[iso_box(box_type = b"ludt", crate_path = crate)]
702pub struct LoudnessBox {
703    /// The contained [`TrackLoudnessInfo`] boxes. (any quantity)
704    #[iso_box(nested_box(collect))]
705    pub loudness: Vec<TrackLoudnessInfo>,
706    /// The contained [`AlbumLoudnessInfo`] boxes. (any quantity)
707    #[iso_box(nested_box(collect))]
708    pub album_loudness: Vec<AlbumLoudnessInfo>,
709}