async_mp4/mp4box/
dops.rs

1use futures::AsyncReadExt;
2use crate::bytes_read::ReadMp4;
3use crate::bytes_write::{Mp4Writable, WriteMp4};
4use crate::error::MP4Error;
5use crate::id::BoxId;
6use crate::mp4box::box_root::MP4Box;
7use crate::mp4box::box_trait::{PartialBox, PartialBoxRead, PartialBoxWrite};
8use crate::r#type::BoxType;
9
10#[derive(Debug, Clone, Eq, PartialEq, Hash)]
11pub struct ChannelMapping {
12    pub stream_count: u8,
13    pub coupled_count: u8,
14    pub channel_mapping: Vec<u8>
15}
16
17impl ChannelMapping {
18    async fn read<R: ReadMp4>(reader: &mut R, channel_count: u8) -> Result<Self, MP4Error> {
19        let stream_count = reader.read().await?;
20        let coupled_count = reader.read().await?;
21        let mut channel_mapping = vec![0u8; channel_count as usize];
22        reader.read_exact(&mut channel_mapping).await?;
23        Ok(Self {
24            stream_count,
25            coupled_count,
26            channel_mapping
27        })
28    }
29
30    fn write<W: WriteMp4>(&self, writer: &mut W) -> Result<usize, MP4Error> {
31        let mut count = 0;
32        count += self.stream_count.write(writer)?;
33        count += self.coupled_count.write(writer)?;
34        count += self.channel_mapping.write(writer)?;
35        Ok(count)
36    }
37}
38
39#[derive(Debug, Clone, Eq, PartialEq, Hash)]
40pub enum ChannelMappingFamily {
41    Family0 {
42        stereo: bool
43    },
44    Family1(ChannelMapping),
45    Unknown(ChannelMapping)
46}
47
48impl ChannelMappingFamily {
49    fn byte_size(&self) -> usize {
50        match self {
51            ChannelMappingFamily::Family0 { .. } => 2,
52            ChannelMappingFamily::Family1(mapping) => 4 + mapping.channel_mapping.len(),
53            ChannelMappingFamily::Unknown(mapping) => 4 + mapping.channel_mapping.len(),
54        }
55    }
56
57    fn get_channel_count(&self) -> u8 {
58        match self {
59            ChannelMappingFamily::Family0 { stereo } => if *stereo { 2 } else { 1 },
60            ChannelMappingFamily::Family1(mapping) => mapping.channel_mapping.len() as u8,
61            ChannelMappingFamily::Unknown(mapping) => mapping.channel_mapping.len() as u8
62        }
63    }
64
65    fn get_channel_family(&self) -> u8 {
66        match self {
67            ChannelMappingFamily::Family0 { .. } => 0,
68            ChannelMappingFamily::Family1(_) => 1,
69            ChannelMappingFamily::Unknown(_) => 255
70        }
71    }
72
73    async fn read<R: ReadMp4>(reader: &mut R, channel_count: u8) -> Result<Self, MP4Error> {
74        let family: u8 = reader.read().await?;
75        Ok(match family {
76            0 => Self::Family0 { stereo: channel_count == 2 },
77            1 => Self::Family1(ChannelMapping::read(reader, channel_count).await?),
78            _ => Self::Unknown(ChannelMapping::read(reader, channel_count).await?)
79        })
80    }
81
82    fn write<W: WriteMp4>(&self, writer: &mut W) -> Result<usize, MP4Error> {
83        let mut count = 0;
84        count += self.get_channel_family().write(writer)?;
85        count += match self {
86            ChannelMappingFamily::Family0 { .. } => 0,
87            ChannelMappingFamily::Family1(mapping) => {
88                debug_assert!(mapping.channel_mapping.len() <= 8, "Opus Family1 cannot have more than 8 output channels");
89                mapping.write(writer)?
90            },
91            ChannelMappingFamily::Unknown(mapping) => {
92                debug_assert!(mapping.channel_mapping.len() <= 255, "Opus Unknown Family cannot have more than 255 output channels");
93                mapping.write(writer)?
94            },
95        };
96        Ok(count)
97    }
98}
99
100
101pub type DOpsBox = MP4Box<DOps>;
102
103#[derive(Debug, Clone, Eq, PartialEq, Hash)]
104pub struct DOps {
105    pub version: u8,
106    pub pre_skip: u16,
107    pub input_sample_rate: u32,
108    pub output_gain: i16,
109    pub channel_mapping_family: ChannelMappingFamily
110}
111
112impl PartialBox for DOps {
113    type ParentData = ();
114    type ThisData = ();
115
116    fn byte_size(&self) -> usize {
117        self.version.byte_size() +
118            self.pre_skip.byte_size() +
119            self.input_sample_rate.byte_size() +
120            self.output_gain.byte_size()+
121            self.channel_mapping_family.byte_size()
122    }
123
124    const ID: BoxType = BoxType::Id(BoxId(*b"dOps"));
125}
126
127#[async_trait::async_trait]
128impl PartialBoxRead for DOps {
129    async fn read_data<R: ReadMp4>(_: Self::ParentData, reader: &mut R) -> Result<Self, MP4Error> {
130        let version = reader.read().await?;
131        let output_channel_count = reader.read().await?;
132        let pre_skip = reader.read().await?;
133        let input_sample_rate = reader.read().await?;
134        let output_gain = reader.read().await?;
135        let channel_mapping_family = ChannelMappingFamily::read(reader, output_channel_count).await?;
136        Ok(Self {
137            version,
138            pre_skip,
139            input_sample_rate,
140            output_gain,
141            channel_mapping_family
142        })
143    }
144}
145
146impl PartialBoxWrite for DOps {
147
148    fn write_data<W: WriteMp4>(&self, writer: &mut W) -> Result<usize, MP4Error> {
149        let mut count = 0;
150        count += self.version.write(writer)?;
151        count += self.channel_mapping_family.get_channel_count().write(writer)?;
152        count += self.pre_skip.write(writer)?;
153        count += self.input_sample_rate.write(writer)?;
154        count += self.output_gain.write(writer)?;
155        count += self.channel_mapping_family.write(writer)?;
156        Ok(count)
157    }
158}