ac_ffmpeg/codec/audio/frame/
channels_v2.rs1use std::{
2 borrow::Borrow,
3 ffi::CString,
4 io,
5 ops::Deref,
6 os::raw::{c_char, c_int, c_void},
7 ptr,
8 str::FromStr,
9};
10
11use super::UnknownChannelLayout;
12
13use crate::Error;
14
15extern "C" {
16 fn ffw_channel_layout_get_default(layout: *mut *mut c_void, channels: u32) -> c_int;
17 fn ffw_channel_layout_from_string(layout: *mut *mut c_void, s: *const c_char) -> c_int;
18 fn ffw_channel_layout_clone(dst: *mut *mut c_void, src: *const c_void) -> c_int;
19 fn ffw_channel_layout_is_valid(layout: *const c_void) -> c_int;
20 fn ffw_channel_layout_get_channels(layout: *const c_void) -> u32;
21 fn ffw_channel_layout_compare(a: *const c_void, b: *const c_void) -> c_int;
22 fn ffw_channel_layout_free(layout: *mut c_void);
23}
24
25pub struct ChannelLayoutRef(());
27
28impl ChannelLayoutRef {
29 #[inline]
31 pub(crate) unsafe fn from_raw_ptr<'a>(ptr: *const c_void) -> &'a Self {
32 &*(ptr as *const Self)
33 }
34
35 pub(crate) fn as_ptr(&self) -> *const c_void {
37 self as *const Self as *const c_void
38 }
39
40 pub fn channels(&self) -> u32 {
42 unsafe { ffw_channel_layout_get_channels(self.as_ptr()) }
43 }
44
45 fn is_valid(&self) -> bool {
47 unsafe { ffw_channel_layout_is_valid(self.as_ptr()) != 0 }
48 }
49}
50
51impl PartialEq for ChannelLayoutRef {
52 fn eq(&self, other: &Self) -> bool {
53 unsafe { ffw_channel_layout_compare(self.as_ptr(), other.as_ptr()) == 0 }
54 }
55}
56
57impl ToOwned for ChannelLayoutRef {
58 type Owned = ChannelLayout;
59
60 fn to_owned(&self) -> Self::Owned {
61 unsafe {
62 let mut dst = ptr::null_mut();
63
64 let ret = ffw_channel_layout_clone(&mut dst, self.as_ptr());
65
66 if ret == 0 {
67 ChannelLayout::from_raw_ptr(dst)
68 } else {
69 panic!("unable to allocate channel layout")
70 }
71 }
72 }
73}
74
75pub struct ChannelLayout {
77 ptr: *mut c_void,
78}
79
80impl ChannelLayout {
81 unsafe fn from_raw_ptr(ptr: *mut c_void) -> Self {
83 Self { ptr }
84 }
85
86 pub fn from_channels(channels: u32) -> Option<Self> {
88 unsafe {
89 let mut ptr = ptr::null_mut();
90
91 let ret = ffw_channel_layout_get_default(&mut ptr, channels);
92
93 if ret != 0 {
94 panic!("unable to allocate channel layout");
95 }
96
97 let res = Self::from_raw_ptr(ptr);
98
99 if res.is_valid() {
100 Some(res)
101 } else {
102 None
103 }
104 }
105 }
106}
107
108impl Drop for ChannelLayout {
109 fn drop(&mut self) {
110 unsafe {
111 ffw_channel_layout_free(self.ptr);
112 }
113 }
114}
115
116impl AsRef<ChannelLayoutRef> for ChannelLayout {
117 #[inline]
118 fn as_ref(&self) -> &ChannelLayoutRef {
119 unsafe { ChannelLayoutRef::from_raw_ptr(self.ptr) }
120 }
121}
122
123impl Borrow<ChannelLayoutRef> for ChannelLayout {
124 #[inline]
125 fn borrow(&self) -> &ChannelLayoutRef {
126 self.as_ref()
127 }
128}
129
130impl Deref for ChannelLayout {
131 type Target = ChannelLayoutRef;
132
133 #[inline]
134 fn deref(&self) -> &Self::Target {
135 self.as_ref()
136 }
137}
138
139impl PartialEq for ChannelLayout {
140 #[inline]
141 fn eq(&self, other: &Self) -> bool {
142 self.as_ref() == other.as_ref()
143 }
144}
145
146impl PartialEq<ChannelLayoutRef> for ChannelLayout {
147 #[inline]
148 fn eq(&self, other: &ChannelLayoutRef) -> bool {
149 self.as_ref() == other
150 }
151}
152
153impl PartialEq<ChannelLayout> for ChannelLayoutRef {
154 #[inline]
155 fn eq(&self, other: &ChannelLayout) -> bool {
156 self == other.as_ref()
157 }
158}
159
160impl Clone for ChannelLayout {
161 #[inline]
162 fn clone(&self) -> Self {
163 self.as_ref().to_owned()
164 }
165}
166
167impl FromStr for ChannelLayout {
168 type Err = UnknownChannelLayout;
169
170 fn from_str(s: &str) -> Result<Self, Self::Err> {
171 let name = CString::new(s).expect("invalid channel layout name");
172
173 let mut ptr = ptr::null_mut();
174
175 let ret = unsafe { ffw_channel_layout_from_string(&mut ptr, name.as_ptr()) };
176
177 if ret == 0 {
178 unsafe { Ok(Self::from_raw_ptr(ptr)) }
179 } else {
180 let err = Error::from_raw_error_code(ret)
181 .to_io_error()
182 .map(|err| err.kind());
183
184 if err == Some(io::ErrorKind::OutOfMemory) {
185 panic!("unable to allocate channel layout")
186 } else {
187 Err(UnknownChannelLayout)
188 }
189 }
190 }
191}
192
193unsafe impl Send for ChannelLayout {}
194unsafe impl Sync for ChannelLayout {}