1use std::{
2 borrow::Cow,
3 num::{NonZeroU32, NonZeroU8},
4};
5
6use aligned_vec::avec;
7
8use super::audio::{AudioFrameDescriptor, SampleFormat};
9use crate::{
10 error::Error,
11 frame::{Data, Frame, FrameData, FrameSpec, MemoryData},
12 invalid_param_error, unsupported_error, FrameDescriptor, MediaType, Result, DEFAULT_ALIGNMENT,
13};
14
15pub type AudioFrame<'a> = Frame<'a, AudioFrameDescriptor>;
16
17pub struct AudioDataCreator;
18
19impl AudioDataCreator {
20 fn create(format: SampleFormat, channels: NonZeroU8, samples: NonZeroU32) -> Result<MemoryData<'static>> {
21 let (size, planes) = format.calc_data_size(channels.get(), samples.get(), DEFAULT_ALIGNMENT as u32);
22 let initial_value = if matches!(format, SampleFormat::U8 | SampleFormat::U8P) {
23 0x80
24 } else {
25 0
26 };
27
28 Ok(MemoryData {
29 data: Data::Owned(avec![[DEFAULT_ALIGNMENT]| initial_value; size]),
30 planes,
31 })
32 }
33
34 fn create_from_buffer<'a, T>(format: SampleFormat, channels: NonZeroU8, samples: NonZeroU32, buffer: T) -> Result<MemoryData<'a>>
35 where
36 T: Into<Cow<'a, [u8]>>,
37 {
38 let (size, planes) = format.calc_data_size(channels.get(), samples.get(), 1);
39 let buffer = buffer.into();
40
41 if buffer.len() != size {
42 return Err(Error::Invalid("buffer size".to_string()));
43 }
44
45 Ok(MemoryData {
46 data: buffer.into(),
47 planes,
48 })
49 }
50}
51
52pub struct AudioFrameCreator;
53
54impl AudioFrameCreator {
55 pub fn create(&self, format: SampleFormat, channels: u8, samples: u32, sample_rate: u32) -> Result<Frame<'static>> {
56 let desc = AudioFrameDescriptor::try_new(format, channels, samples, sample_rate)?;
57
58 self.create_with_descriptor(desc)
59 }
60
61 pub fn create_with_descriptor(&self, desc: AudioFrameDescriptor) -> Result<Frame<'static>> {
62 let data = AudioDataCreator::create(desc.format, desc.channels(), desc.samples)?;
63
64 Ok(Frame::from_data(FrameDescriptor::Audio(desc), FrameData::Memory(data)))
65 }
66
67 pub fn create_from_buffer<'a, T>(&self, format: SampleFormat, channels: u8, samples: u32, sample_rate: u32, buffer: T) -> Result<Frame<'a>>
68 where
69 T: Into<Cow<'a, [u8]>>,
70 {
71 let desc = AudioFrameDescriptor::try_new(format, channels, samples, sample_rate)?;
72
73 self.create_from_buffer_with_descriptor(desc, buffer)
74 }
75
76 pub fn create_from_buffer_with_descriptor<'a, T>(&self, desc: AudioFrameDescriptor, buffer: T) -> Result<Frame<'a>>
77 where
78 T: Into<Cow<'a, [u8]>>,
79 {
80 let data = AudioDataCreator::create_from_buffer(desc.format, desc.channels(), desc.samples, buffer)?;
81
82 Ok(Frame::from_data(FrameDescriptor::Audio(desc), FrameData::Memory(data)))
83 }
84
85 pub fn create_empty(&self, format: SampleFormat, channels: u8, samples: u32, sample_rate: u32) -> Result<Frame<'static>> {
86 let desc = AudioFrameDescriptor::try_new(format, channels, samples, sample_rate)?;
87
88 self.create_empty_with_descriptor(desc)
89 }
90
91 pub fn create_empty_with_descriptor(&self, desc: AudioFrameDescriptor) -> Result<Frame<'static>> {
92 let data = FrameData::Empty;
93
94 Ok(Frame::from_data(FrameDescriptor::Audio(desc), data))
95 }
96}
97
98impl Frame<'_> {
99 pub fn audio_creator() -> AudioFrameCreator {
100 AudioFrameCreator
101 }
102
103 pub fn audio_descriptor(&self) -> Option<&AudioFrameDescriptor> {
104 if let FrameDescriptor::Audio(desc) = &self.desc {
105 Some(desc)
106 } else {
107 None
108 }
109 }
110
111 pub fn is_audio(&self) -> bool {
112 self.desc.is_audio()
113 }
114
115 pub fn truncate(&mut self, samples: u32) -> Result<()> {
116 let FrameDescriptor::Audio(desc) = &mut self.desc else {
117 return Err(unsupported_error!(self.desc));
118 };
119
120 AudioFrame::truncate_internal(desc, &mut self.data, samples)
121 }
122}
123
124impl AudioFrame<'_> {
125 pub fn new(format: SampleFormat, channels: u8, samples: u32, sample_rate: u32) -> Result<Self> {
126 let desc = AudioFrameDescriptor::try_new(format, channels, samples, sample_rate)?;
127
128 Self::new_with_descriptor(desc)
129 }
130
131 pub fn new_with_descriptor(desc: AudioFrameDescriptor) -> Result<Self> {
132 let data = AudioDataCreator::create(desc.format, desc.channels(), desc.samples)?;
133
134 Ok(Frame::from_data_with_generic_descriptor(desc, FrameData::Memory(data)))
135 }
136
137 pub fn from_buffer<'a, T>(format: SampleFormat, channels: u8, samples: u32, sample_rate: u32, buffer: T) -> Result<AudioFrame<'a>>
138 where
139 T: Into<Cow<'a, [u8]>>,
140 {
141 let desc = AudioFrameDescriptor::try_new(format, channels, samples, sample_rate)?;
142
143 Self::from_buffer_with_descriptor(desc, buffer)
144 }
145
146 pub fn from_buffer_with_descriptor<'a, T>(desc: AudioFrameDescriptor, buffer: T) -> Result<AudioFrame<'a>>
147 where
148 T: Into<Cow<'a, [u8]>>,
149 {
150 let data = AudioDataCreator::create_from_buffer(desc.format, desc.channels(), desc.samples, buffer)?;
151
152 Ok(Frame::from_data_with_generic_descriptor(desc, FrameData::Memory(data)))
153 }
154
155 pub fn new_empty(format: SampleFormat, channels: u8, samples: u32, sample_rate: u32) -> Result<Self> {
156 let desc = AudioFrameDescriptor::try_new(format, channels, samples, sample_rate)?;
157
158 Self::new_empty_with_descriptor(desc)
159 }
160
161 pub fn new_empty_with_descriptor(desc: AudioFrameDescriptor) -> Result<Self> {
162 let data = FrameData::Empty;
163
164 Ok(Frame::from_data_with_generic_descriptor(desc, data))
165 }
166
167 fn truncate_internal(desc: &mut AudioFrameDescriptor, data: &mut FrameData, samples: u32) -> Result<()> {
168 if desc.samples.get() < samples || samples == 0 {
169 return Err(invalid_param_error!(samples));
170 }
171
172 let actual_bytes = desc.format.calc_plane_size(desc.channels().get(), samples);
173 data.truncate(actual_bytes)?;
174
175 desc.samples = NonZeroU32::new(samples).unwrap();
176
177 Ok(())
178 }
179
180 pub fn truncate(&mut self, samples: u32) -> Result<()> {
181 Self::truncate_internal(&mut self.desc, &mut self.data, samples)
182 }
183}
184
185impl<'a> From<AudioFrame<'a>> for Frame<'a> {
186 fn from(frame: AudioFrame<'a>) -> Self {
187 Frame {
188 desc: FrameDescriptor::Audio(frame.desc),
189 source: frame.source,
190 pts: frame.pts,
191 dts: frame.dts,
192 duration: frame.duration,
193 time_base: frame.time_base,
194 metadata: frame.metadata,
195 data: frame.data,
196 }
197 }
198}
199
200impl<'a> TryFrom<Frame<'a>> for AudioFrame<'a> {
201 type Error = Error;
202
203 fn try_from(frame: Frame<'a>) -> Result<Self> {
204 if let FrameDescriptor::Audio(desc) = frame.desc {
205 Ok(Frame {
206 desc,
207 source: frame.source,
208 pts: frame.pts,
209 dts: frame.dts,
210 duration: frame.duration,
211 time_base: frame.time_base,
212 metadata: frame.metadata,
213 data: frame.data,
214 })
215 } else {
216 Err(Error::Invalid("not audio frame".to_string()))
217 }
218 }
219}
220
221impl FrameSpec<AudioFrameDescriptor> for AudioFrame<'_> {
222 fn new_with_descriptor(desc: AudioFrameDescriptor) -> Result<Frame<'static, AudioFrameDescriptor>> {
223 AudioFrame::new_with_descriptor(desc)
224 }
225
226 fn media_type(&self) -> MediaType {
227 MediaType::Audio
228 }
229}