ffmpeg_next/codec/
audio.rs

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 = *self.ptr;
84            self.ptr = self.ptr.offset(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 = (*self.ptr).into();
111            self.ptr = self.ptr.offset(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(ChannelLayout::MONO, |acc, cur| {
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}