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