1 | use std::ops::Deref; |
2 | |
3 | use super::codec::Codec; |
4 | use ffi::*; |
5 | use {format, ChannelLayout}; |
6 | |
7 | #[derive (PartialEq, Eq, Copy, Clone)] |
8 | pub struct Audio { |
9 | codec: Codec, |
10 | } |
11 | |
12 | impl Audio { |
13 | pub unsafe fn new(codec: Codec) -> Audio { |
14 | Audio { codec } |
15 | } |
16 | } |
17 | |
18 | impl 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 | if (*self.codec.as_ptr()).channel_layouts.is_null() { |
42 | None |
43 | } else { |
44 | Some(ChannelLayoutIter::new( |
45 | (*self.codec.as_ptr()).channel_layouts, |
46 | )) |
47 | } |
48 | } |
49 | } |
50 | } |
51 | |
52 | impl Deref for Audio { |
53 | type Target = Codec; |
54 | |
55 | fn deref(&self) -> &Self::Target { |
56 | &self.codec |
57 | } |
58 | } |
59 | |
60 | pub struct RateIter { |
61 | ptr: *const i32, |
62 | } |
63 | |
64 | impl RateIter { |
65 | pub fn new(ptr: *const i32) -> Self { |
66 | RateIter { ptr } |
67 | } |
68 | } |
69 | |
70 | impl Iterator for RateIter { |
71 | type Item = i32; |
72 | |
73 | fn next(&mut self) -> Option<<Self as Iterator>::Item> { |
74 | unsafe { |
75 | if *self.ptr == 0 { |
76 | return None; |
77 | } |
78 | |
79 | let rate: i32 = *self.ptr; |
80 | self.ptr = self.ptr.offset(count:1); |
81 | |
82 | Some(rate) |
83 | } |
84 | } |
85 | } |
86 | |
87 | pub struct FormatIter { |
88 | ptr: *const AVSampleFormat, |
89 | } |
90 | |
91 | impl FormatIter { |
92 | pub fn new(ptr: *const AVSampleFormat) -> Self { |
93 | FormatIter { ptr } |
94 | } |
95 | } |
96 | |
97 | impl Iterator for FormatIter { |
98 | type Item = format::Sample; |
99 | |
100 | fn next(&mut self) -> Option<<Self as Iterator>::Item> { |
101 | unsafe { |
102 | if *self.ptr == AVSampleFormat::AV_SAMPLE_FMT_NONE { |
103 | return None; |
104 | } |
105 | |
106 | let format: Sample = (*self.ptr).into(); |
107 | self.ptr = self.ptr.offset(count:1); |
108 | |
109 | Some(format) |
110 | } |
111 | } |
112 | } |
113 | |
114 | pub struct ChannelLayoutIter { |
115 | ptr: *const u64, |
116 | } |
117 | |
118 | impl ChannelLayoutIter { |
119 | pub fn new(ptr: *const u64) -> Self { |
120 | ChannelLayoutIter { ptr } |
121 | } |
122 | |
123 | pub fn best(self, max: i32) -> ChannelLayout { |
124 | self.fold(init:ChannelLayout::MONO, |acc: ChannelLayout, cur: ChannelLayout| { |
125 | if cur.channels() > acc.channels() && cur.channels() <= max { |
126 | cur |
127 | } else { |
128 | acc |
129 | } |
130 | }) |
131 | } |
132 | } |
133 | |
134 | impl Iterator for ChannelLayoutIter { |
135 | type Item = ChannelLayout; |
136 | |
137 | fn next(&mut self) -> Option<<Self as Iterator>::Item> { |
138 | unsafe { |
139 | if *self.ptr == 0 { |
140 | return None; |
141 | } |
142 | |
143 | let layout: ChannelLayout = ChannelLayout::from_bits_truncate(*self.ptr); |
144 | self.ptr = self.ptr.offset(count:1); |
145 | |
146 | Some(layout) |
147 | } |
148 | } |
149 | } |
150 | |