ffmpeg_next/codec/
audio.rs1use std::ops::Deref;
2
3use super::codec::Codec;
4use crate::ffi::*;
5use crate::{ChannelLayout, format};
6
7#[derive(PartialEq, Eq, Copy, Clone)]
8pub struct Audio {
9 codec: Codec,
10}
11
12impl Audio {
13 pub unsafe fn new(codec: Codec) -> Audio {
14 Audio { codec }
15 }
16}
17
18impl Audio {
19 pub fn rates(&self) -> Option<RateIter> {
20 unsafe {
21 #[cfg(feature = "ffmpeg_9_0")]
22 let ptr = super::supported_config::<i32>(
23 self.codec.as_ptr(),
24 AVCodecConfig::AV_CODEC_CONFIG_SAMPLE_RATE,
25 );
26 #[cfg(not(feature = "ffmpeg_9_0"))]
27 let ptr = (*self.codec.as_ptr()).supported_samplerates;
28
29 if ptr.is_null() {
30 None
31 } else {
32 Some(RateIter::new(ptr))
33 }
34 }
35 }
36
37 pub fn formats(&self) -> Option<FormatIter> {
38 unsafe {
39 #[cfg(feature = "ffmpeg_9_0")]
40 let ptr = super::supported_config::<AVSampleFormat>(
41 self.codec.as_ptr(),
42 AVCodecConfig::AV_CODEC_CONFIG_SAMPLE_FORMAT,
43 );
44 #[cfg(not(feature = "ffmpeg_9_0"))]
45 let ptr = (*self.codec.as_ptr()).sample_fmts;
46
47 if ptr.is_null() {
48 None
49 } else {
50 Some(FormatIter::new(ptr))
51 }
52 }
53 }
54
55 pub fn channel_layouts(&self) -> Option<ChannelLayoutIter> {
56 unsafe {
57 #[cfg(not(feature = "ffmpeg_7_0"))]
58 let ptr = (*self.codec.as_ptr()).channel_layouts;
59
60 #[cfg(all(feature = "ffmpeg_7_0", not(feature = "ffmpeg_9_0")))]
61 let ptr = (*self.codec.as_ptr()).ch_layouts;
62
63 #[cfg(feature = "ffmpeg_9_0")]
64 let ptr = super::supported_config::<AVChannelLayout>(
65 self.codec.as_ptr(),
66 AVCodecConfig::AV_CODEC_CONFIG_CHANNEL_LAYOUT,
67 );
68
69 if ptr.is_null() {
70 None
71 } else {
72 Some(ChannelLayoutIter::new(ptr))
73 }
74 }
75 }
76}
77
78impl Deref for Audio {
79 type Target = Codec;
80
81 fn deref(&self) -> &Self::Target {
82 &self.codec
83 }
84}
85
86pub struct RateIter {
87 ptr: *const i32,
88}
89
90impl RateIter {
91 pub fn new(ptr: *const i32) -> Self {
92 RateIter { ptr }
93 }
94}
95
96impl Iterator for RateIter {
97 type Item = i32;
98
99 fn next(&mut self) -> Option<<Self as Iterator>::Item> {
100 unsafe {
101 if *self.ptr == 0 {
102 return None;
103 }
104
105 let rate = *self.ptr;
106 self.ptr = self.ptr.offset(1);
107
108 Some(rate)
109 }
110 }
111}
112
113pub struct FormatIter {
114 ptr: *const AVSampleFormat,
115}
116
117impl FormatIter {
118 pub fn new(ptr: *const AVSampleFormat) -> Self {
119 FormatIter { ptr }
120 }
121}
122
123impl Iterator for FormatIter {
124 type Item = format::Sample;
125
126 fn next(&mut self) -> Option<<Self as Iterator>::Item> {
127 unsafe {
128 if *self.ptr == AVSampleFormat::AV_SAMPLE_FMT_NONE {
129 return None;
130 }
131
132 let format = (*self.ptr).into();
133 self.ptr = self.ptr.offset(1);
134
135 Some(format)
136 }
137 }
138}
139
140#[cfg(not(feature = "ffmpeg_7_0"))]
141type ChannelLayoutType = u64;
142#[cfg(feature = "ffmpeg_7_0")]
143type ChannelLayoutType = AVChannelLayout;
144
145pub struct ChannelLayoutIter {
146 ptr: *const ChannelLayoutType,
147}
148
149impl ChannelLayoutIter {
150 pub fn new(ptr: *const ChannelLayoutType) -> Self {
151 ChannelLayoutIter { ptr }
152 }
153
154 pub fn best(self, max: i32) -> ChannelLayout {
155 self.fold(ChannelLayout::MONO, |acc, cur| {
156 if cur.channels() > acc.channels() && cur.channels() <= max as _ {
157 cur
158 } else {
159 acc
160 }
161 })
162 }
163}
164
165impl Iterator for ChannelLayoutIter {
166 type Item = ChannelLayout;
167
168 fn next(&mut self) -> Option<<Self as Iterator>::Item> {
169 unsafe {
170 #[cfg(not(feature = "ffmpeg_7_0"))]
171 if *self.ptr == 0 {
172 return None;
173 }
174
175 #[cfg(feature = "ffmpeg_7_0")]
176 if self.ptr.is_null() || (*self.ptr).u.mask == 0 {
177 return None;
178 }
179
180 #[cfg(not(feature = "ffmpeg_7_0"))]
181 let layout = ChannelLayout::from_bits_truncate(*self.ptr);
182
183 #[cfg(feature = "ffmpeg_7_0")]
184 let layout = ChannelLayout::from(*self.ptr);
185
186 self.ptr = self.ptr.offset(1);
187
188 Some(layout)
189 }
190 }
191}