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