mediadecode_ffmpeg/
sample_format.rs1use core::fmt;
16
17use ffmpeg_next::ffi::AVSampleFormat;
18
19#[repr(transparent)]
21#[derive(Copy, Clone, Eq, PartialEq, Hash)]
22pub struct SampleFormat(i32);
23
24impl SampleFormat {
25 #[inline]
28 pub const fn from_raw(raw: i32) -> Self {
29 Self(raw)
30 }
31
32 #[inline]
34 pub const fn raw(self) -> i32 {
35 self.0
36 }
37
38 #[inline]
40 pub const fn is_planar(self) -> bool {
41 matches!(
42 self,
43 Self::U8P | Self::S16P | Self::S32P | Self::S64P | Self::FLTP | Self::DBLP,
44 )
45 }
46
47 #[inline]
49 pub const fn is_packed(self) -> bool {
50 matches!(
51 self,
52 Self::U8 | Self::S16 | Self::S32 | Self::S64 | Self::FLT | Self::DBL,
53 )
54 }
55
56 #[inline]
59 pub const fn bytes_per_sample(self) -> Option<u32> {
60 let bytes = match self {
61 Self::U8 | Self::U8P => 1,
62 Self::S16 | Self::S16P => 2,
63 Self::S32 | Self::S32P | Self::FLT | Self::FLTP => 4,
64 Self::S64 | Self::S64P | Self::DBL | Self::DBLP => 8,
65 _ => return None,
66 };
67 Some(bytes)
68 }
69
70 pub const NONE: Self = Self(AVSampleFormat::AV_SAMPLE_FMT_NONE as i32);
74
75 pub const U8: Self = Self(AVSampleFormat::AV_SAMPLE_FMT_U8 as i32);
79 pub const S16: Self = Self(AVSampleFormat::AV_SAMPLE_FMT_S16 as i32);
81 pub const S32: Self = Self(AVSampleFormat::AV_SAMPLE_FMT_S32 as i32);
83 pub const S64: Self = Self(AVSampleFormat::AV_SAMPLE_FMT_S64 as i32);
85 pub const FLT: Self = Self(AVSampleFormat::AV_SAMPLE_FMT_FLT as i32);
87 pub const DBL: Self = Self(AVSampleFormat::AV_SAMPLE_FMT_DBL as i32);
89
90 pub const U8P: Self = Self(AVSampleFormat::AV_SAMPLE_FMT_U8P as i32);
94 pub const S16P: Self = Self(AVSampleFormat::AV_SAMPLE_FMT_S16P as i32);
96 pub const S32P: Self = Self(AVSampleFormat::AV_SAMPLE_FMT_S32P as i32);
98 pub const S64P: Self = Self(AVSampleFormat::AV_SAMPLE_FMT_S64P as i32);
100 pub const FLTP: Self = Self(AVSampleFormat::AV_SAMPLE_FMT_FLTP as i32);
102 pub const DBLP: Self = Self(AVSampleFormat::AV_SAMPLE_FMT_DBLP as i32);
104}
105
106impl fmt::Debug for SampleFormat {
107 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108 let name = match *self {
109 Self::NONE => "NONE",
110 Self::U8 => "U8",
111 Self::S16 => "S16",
112 Self::S32 => "S32",
113 Self::S64 => "S64",
114 Self::FLT => "FLT",
115 Self::DBL => "DBL",
116 Self::U8P => "U8P",
117 Self::S16P => "S16P",
118 Self::S32P => "S32P",
119 Self::S64P => "S64P",
120 Self::FLTP => "FLTP",
121 Self::DBLP => "DBLP",
122 _ => return write!(f, "SampleFormat({})", self.0),
123 };
124 write!(f, "SampleFormat::{name}")
125 }
126}
127
128#[cfg(test)]
129mod tests {
130 use super::*;
131
132 #[test]
133 fn known_constants_match_av_values() {
134 assert_eq!(
135 SampleFormat::S16.raw(),
136 AVSampleFormat::AV_SAMPLE_FMT_S16 as i32
137 );
138 assert_eq!(
139 SampleFormat::FLTP.raw(),
140 AVSampleFormat::AV_SAMPLE_FMT_FLTP as i32
141 );
142 assert_eq!(SampleFormat::NONE.raw(), -1);
143 }
144
145 #[test]
146 fn planar_packed_partition_is_complete() {
147 let all_packed = [
148 SampleFormat::U8,
149 SampleFormat::S16,
150 SampleFormat::S32,
151 SampleFormat::S64,
152 SampleFormat::FLT,
153 SampleFormat::DBL,
154 ];
155 let all_planar = [
156 SampleFormat::U8P,
157 SampleFormat::S16P,
158 SampleFormat::S32P,
159 SampleFormat::S64P,
160 SampleFormat::FLTP,
161 SampleFormat::DBLP,
162 ];
163 for f in all_packed {
164 assert!(f.is_packed());
165 assert!(!f.is_planar());
166 }
167 for f in all_planar {
168 assert!(f.is_planar());
169 assert!(!f.is_packed());
170 }
171 }
172
173 #[test]
174 fn bytes_per_sample_matches_width() {
175 assert_eq!(SampleFormat::U8.bytes_per_sample(), Some(1));
176 assert_eq!(SampleFormat::S16.bytes_per_sample(), Some(2));
177 assert_eq!(SampleFormat::S32P.bytes_per_sample(), Some(4));
178 assert_eq!(SampleFormat::FLTP.bytes_per_sample(), Some(4));
179 assert_eq!(SampleFormat::DBL.bytes_per_sample(), Some(8));
180 assert_eq!(SampleFormat::NONE.bytes_per_sample(), None);
181 assert_eq!(SampleFormat::from_raw(99_999).bytes_per_sample(), None);
182 }
183
184 #[test]
185 fn debug_uses_name_for_known_formats() {
186 assert_eq!(format!("{:?}", SampleFormat::S16), "SampleFormat::S16");
187 assert_eq!(format!("{:?}", SampleFormat::FLTP), "SampleFormat::FLTP");
188 }
189
190 #[test]
191 fn debug_falls_back_to_raw_for_unknown() {
192 assert_eq!(
193 format!("{:?}", SampleFormat::from_raw(99_999)),
194 "SampleFormat(99999)"
195 );
196 }
197}