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}