1use std::ptr::null_mut;
2
3use cfg_if::cfg_if;
4use core_foundation::{
5 base::{kCFAllocatorDefault, Boolean, CFAllocatorRef, OSStatus, TCFType},
6 string::{CFString, CFStringEncoding, CFStringRef},
7};
8use libc::size_t;
9
10use crate::{
11 block_buffer::{CMBlockBuffer, CMBlockBufferRef},
12 format_description::{
13 CMAudioFormatDescription, CMAudioFormatDescriptionRef, CMClosedCaptionFormatDescriptionRef, CMMediaType, CMMetadataFormatDescriptionRef,
14 CMTextFormatDescriptionRef, CMTimeCodeFormatDescriptionRef, CMVideoFormatDescription, CMVideoFormatDescriptionRef,
15 },
16};
17
18pub const kCMFormatDescriptionBridgeError_InvalidParameter: OSStatus = -12712;
19pub const kCMFormatDescriptionBridgeError_AllocationFailed: OSStatus = -12713;
20pub const kCMFormatDescriptionBridgeError_InvalidSerializedSampleDescription: OSStatus = -12714;
21pub const kCMFormatDescriptionBridgeError_InvalidFormatDescription: OSStatus = -12715;
22pub const kCMFormatDescriptionBridgeError_IncompatibleFormatDescription: OSStatus = -12716;
23pub const kCMFormatDescriptionBridgeError_UnsupportedSampleDescriptionFlavor: OSStatus = -12717;
24pub const kCMFormatDescriptionBridgeError_InvalidSlice: OSStatus = -12719;
25
26extern "C" {
27 pub static kCMImageDescriptionFlavor_QuickTimeMovie: CFStringRef;
28 pub static kCMImageDescriptionFlavor_ISOFamily: CFStringRef;
29 pub static kCMImageDescriptionFlavor_3GPFamily: CFStringRef;
30 pub static kCMImageDescriptionFlavor_ISOFamilyWithAppleExtensions: CFStringRef;
31
32 pub fn CMVideoFormatDescriptionCreateFromBigEndianImageDescriptionData(
33 allocator: CFAllocatorRef,
34 imageDescriptionData: *const u8,
35 size: size_t,
36 stringEncoding: CFStringEncoding,
37 flavor: CFStringRef,
38 formatDescriptionOut: *mut CMVideoFormatDescriptionRef,
39 ) -> OSStatus;
40 pub fn CMVideoFormatDescriptionCreateFromBigEndianImageDescriptionBlockBuffer(
41 allocator: CFAllocatorRef,
42 imageDescriptionBlockBuffer: CMBlockBufferRef,
43 stringEncoding: CFStringEncoding,
44 flavor: CFStringRef,
45 formatDescriptionOut: *mut CMVideoFormatDescriptionRef,
46 ) -> OSStatus;
47 pub fn CMVideoFormatDescriptionCopyAsBigEndianImageDescriptionBlockBuffer(
48 allocator: CFAllocatorRef,
49 videoFormatDescription: CMVideoFormatDescriptionRef,
50 stringEncoding: CFStringEncoding,
51 flavor: CFStringRef,
52 blockBufferOut: *mut CMBlockBufferRef,
53 ) -> OSStatus;
54
55 cfg_if! {
56 if #[cfg(target_endian = "little")] {
57 pub fn CMSwapBigEndianImageDescriptionToHost(imageDescriptionData: *mut u8, imageDescriptionSize: size_t) -> OSStatus;
58 pub fn CMSwapHostEndianImageDescriptionToBig(imageDescriptionData: *mut u8, imageDescriptionSize: size_t) -> OSStatus;
59 }
60 }
61
62 pub static kCMSoundDescriptionFlavor_QuickTimeMovie: CFStringRef;
63 pub static kCMSoundDescriptionFlavor_QuickTimeMovieV2: CFStringRef;
64 pub static kCMSoundDescriptionFlavor_ISOFamily: CFStringRef;
65 pub static kCMSoundDescriptionFlavor_3GPFamily: CFStringRef;
66
67 pub fn CMAudioFormatDescriptionCreateFromBigEndianSoundDescriptionData(
68 allocator: CFAllocatorRef,
69 soundDescriptionData: *const u8,
70 size: size_t,
71 flavor: CFStringRef,
72 formatDescriptionOut: *mut CMAudioFormatDescriptionRef,
73 ) -> OSStatus;
74 pub fn CMAudioFormatDescriptionCreateFromBigEndianSoundDescriptionBlockBuffer(
75 allocator: CFAllocatorRef,
76 soundDescriptionBlockBuffer: CMBlockBufferRef,
77 flavor: CFStringRef,
78 formatDescriptionOut: *mut CMAudioFormatDescriptionRef,
79 ) -> OSStatus;
80 pub fn CMAudioFormatDescriptionCopyAsBigEndianSoundDescriptionBlockBuffer(
81 allocator: CFAllocatorRef,
82 audioFormatDescription: CMAudioFormatDescriptionRef,
83 flavor: CFStringRef,
84 blockBufferOut: *mut CMBlockBufferRef,
85 ) -> OSStatus;
86 pub fn CMDoesBigEndianSoundDescriptionRequireLegacyCBRSampleTableLayout(
87 soundDescriptionBlockBuffer: CMBlockBufferRef,
88 flavor: CFStringRef,
89 ) -> Boolean;
90
91 cfg_if! {
92 if #[cfg(target_endian = "little")] {
93 pub fn CMSwapBigEndianSoundDescriptionToHost(soundDescriptionData: *mut u8, soundDescriptionSize: size_t) -> OSStatus;
94 pub fn CMSwapHostEndianSoundDescriptionToBig(soundDescriptionData: *mut u8, soundDescriptionSize: size_t) -> OSStatus;
95 }
96 }
97
98 pub fn CMTextFormatDescriptionCreateFromBigEndianTextDescriptionData(
99 allocator: CFAllocatorRef,
100 textDescriptionData: *const u8,
101 size: size_t,
102 flavor: CFStringRef,
103 mediaType: CMMediaType,
104 formatDescriptionOut: *mut CMTextFormatDescriptionRef,
105 ) -> OSStatus;
106 pub fn CMTextFormatDescriptionCreateFromBigEndianTextDescriptionBlockBuffer(
107 allocator: CFAllocatorRef,
108 textDescriptionBlockBuffer: CMBlockBufferRef,
109 flavor: CFStringRef,
110 mediaType: CMMediaType,
111 formatDescriptionOut: *mut CMTextFormatDescriptionRef,
112 ) -> OSStatus;
113 pub fn CMTextFormatDescriptionCopyAsBigEndianTextDescriptionBlockBuffer(
114 allocator: CFAllocatorRef,
115 textFormatDescription: CMTextFormatDescriptionRef,
116 flavor: CFStringRef,
117 blockBufferOut: *mut CMBlockBufferRef,
118 ) -> OSStatus;
119
120 cfg_if! {
121 if #[cfg(target_endian = "little")] {
122 pub fn CMSwapBigEndianTextDescriptionToHost(textDescriptionData: *mut u8, textDescriptionSize: size_t) -> OSStatus;
123 pub fn CMSwapHostEndianTextDescriptionToBig(textDescriptionData: *mut u8, textDescriptionSize: size_t) -> OSStatus;
124 }
125 }
126
127 pub fn CMClosedCaptionFormatDescriptionCreateFromBigEndianClosedCaptionDescriptionData(
128 allocator: CFAllocatorRef,
129 closedCaptionDescriptionData: *const u8,
130 size: size_t,
131 flavor: CFStringRef,
132 formatDescriptionOut: *mut CMClosedCaptionFormatDescriptionRef,
133 ) -> OSStatus;
134 pub fn CMClosedCaptionFormatDescriptionCreateFromBigEndianClosedCaptionDescriptionBlockBuffer(
135 allocator: CFAllocatorRef,
136 closedCaptionDescriptionBlockBuffer: CMBlockBufferRef,
137 flavor: CFStringRef,
138 formatDescriptionOut: *mut CMClosedCaptionFormatDescriptionRef,
139 ) -> OSStatus;
140 pub fn CMClosedCaptionFormatDescriptionCopyAsBigEndianClosedCaptionDescriptionBlockBuffer(
141 allocator: CFAllocatorRef,
142 closedCaptionFormatDescription: CMClosedCaptionFormatDescriptionRef,
143 flavor: CFStringRef,
144 blockBufferOut: *mut CMBlockBufferRef,
145 ) -> OSStatus;
146
147 cfg_if! {
148 if #[cfg(target_endian = "little")] {
149 pub fn CMSwapBigEndianClosedCaptionDescriptionToHost(closedCaptionDescriptionData: *mut u8, closedCaptionDescriptionSize: size_t) -> OSStatus;
150 pub fn CMSwapHostEndianClosedCaptionDescriptionToBig(closedCaptionDescriptionData: *mut u8, closedCaptionDescriptionSize: size_t) -> OSStatus;
151 }
152 }
153
154 pub fn CMTimeCodeFormatDescriptionCreateFromBigEndianTimeCodeDescriptionData(
155 allocator: CFAllocatorRef,
156 timeCodeDescriptionData: *const u8,
157 size: size_t,
158 flavor: CFStringRef,
159 formatDescriptionOut: *mut CMTimeCodeFormatDescriptionRef,
160 ) -> OSStatus;
161 pub fn CMTimeCodeFormatDescriptionCreateFromBigEndianTimeCodeDescriptionBlockBuffer(
162 allocator: CFAllocatorRef,
163 timeCodeDescriptionBlockBuffer: CMBlockBufferRef,
164 flavor: CFStringRef,
165 formatDescriptionOut: *mut CMTimeCodeFormatDescriptionRef,
166 ) -> OSStatus;
167 pub fn CMTimeCodeFormatDescriptionCopyAsBigEndianTimeCodeDescriptionBlockBuffer(
168 allocator: CFAllocatorRef,
169 timeCodeFormatDescription: CMTimeCodeFormatDescriptionRef,
170 flavor: CFStringRef,
171 blockBufferOut: *mut CMBlockBufferRef,
172 ) -> OSStatus;
173
174 cfg_if! {
175 if #[cfg(target_endian = "little")] {
176 pub fn CMSwapBigEndianTimeCodeDescriptionToHost(timeCodeDescriptionData: *mut u8, timeCodeDescriptionSize: size_t) -> OSStatus;
177 pub fn CMSwapHostEndianTimeCodeDescriptionToBig(timeCodeDescriptionData: *mut u8, timeCodeDescriptionSize: size_t) -> OSStatus;
178 }
179 }
180
181 pub fn CMMetadataFormatDescriptionCreateFromBigEndianMetadataDescriptionData(
182 allocator: CFAllocatorRef,
183 metadataDescriptionData: *const u8,
184 size: size_t,
185 flavor: CFStringRef,
186 formatDescriptionOut: *mut CMMetadataFormatDescriptionRef,
187 ) -> OSStatus;
188 pub fn CMMetadataFormatDescriptionCreateFromBigEndianMetadataDescriptionBlockBuffer(
189 allocator: CFAllocatorRef,
190 metadataDescriptionBlockBuffer: CMBlockBufferRef,
191 flavor: CFStringRef,
192 formatDescriptionOut: *mut CMMetadataFormatDescriptionRef,
193 ) -> OSStatus;
194 pub fn CMMetadataFormatDescriptionCopyAsBigEndianMetadataDescriptionBlockBuffer(
195 allocator: CFAllocatorRef,
196 metadataFormatDescription: CMMetadataFormatDescriptionRef,
197 flavor: CFStringRef,
198 blockBufferOut: *mut CMBlockBufferRef,
199 ) -> OSStatus;
200
201 cfg_if! {
202 if #[cfg(target_endian = "little")] {
203 pub fn CMSwapBigEndianMetadataDescriptionToHost(metadataDescriptionData: *mut u8, metadataDescriptionSize: size_t) -> OSStatus;
204 pub fn CMSwapHostEndianMetadataDescriptionToBig(metadataDescriptionData: *mut u8, metadataDescriptionSize: size_t) -> OSStatus;
205 }
206 }
207}
208
209impl CMAudioFormatDescription {
210 #[inline]
211 pub fn from_big_endian_sound_description_data(sound_descriptionData: &[u8], flavor: &CFString) -> Result<CMAudioFormatDescription, OSStatus> {
212 let mut format_description: CMAudioFormatDescriptionRef = null_mut();
213 let status = unsafe {
214 CMAudioFormatDescriptionCreateFromBigEndianSoundDescriptionData(
215 kCFAllocatorDefault,
216 sound_descriptionData.as_ptr(),
217 sound_descriptionData.len(),
218 flavor.as_concrete_TypeRef(),
219 &mut format_description,
220 )
221 };
222 if status == 0 {
223 Ok(unsafe { CMAudioFormatDescription::wrap_under_create_rule(format_description) })
224 } else {
225 Err(status)
226 }
227 }
228
229 #[inline]
230 pub fn from_big_endian_sound_description_block_buffer(
231 sound_description_block_buffer: &CMBlockBuffer,
232 flavor: &CFString,
233 ) -> Result<CMAudioFormatDescription, OSStatus> {
234 let mut format_description: CMAudioFormatDescriptionRef = null_mut();
235 let status = unsafe {
236 CMAudioFormatDescriptionCreateFromBigEndianSoundDescriptionBlockBuffer(
237 kCFAllocatorDefault,
238 sound_description_block_buffer.as_concrete_TypeRef(),
239 flavor.as_concrete_TypeRef(),
240 &mut format_description,
241 )
242 };
243 if status == 0 {
244 Ok(unsafe { CMAudioFormatDescription::wrap_under_create_rule(format_description) })
245 } else {
246 Err(status)
247 }
248 }
249
250 #[inline]
251 pub fn copy_as_big_endian_sound_description_block_buffer(&self, flavor: &CFString) -> Result<CMBlockBuffer, OSStatus> {
252 let mut block_buffer: CMBlockBufferRef = null_mut();
253 let status = unsafe {
254 CMAudioFormatDescriptionCopyAsBigEndianSoundDescriptionBlockBuffer(
255 kCFAllocatorDefault,
256 self.as_concrete_TypeRef(),
257 flavor.as_concrete_TypeRef(),
258 &mut block_buffer,
259 )
260 };
261 if status == 0 {
262 Ok(unsafe { CMBlockBuffer::wrap_under_create_rule(block_buffer) })
263 } else {
264 Err(status)
265 }
266 }
267}
268
269impl CMBlockBuffer {
270 #[inline]
271 pub fn does_big_endian_sound_description_require_legacy_cbr_sample_table_layout(&self, flavor: &CFString) -> bool {
272 unsafe { CMDoesBigEndianSoundDescriptionRequireLegacyCBRSampleTableLayout(self.as_concrete_TypeRef(), flavor.as_concrete_TypeRef()) != 0 }
273 }
274}
275
276impl CMVideoFormatDescription {
277 #[inline]
278 pub fn from_big_endian_image_description_data(
279 image_description_data: &[u8],
280 string_encoding: CFStringEncoding,
281 flavor: &CFString,
282 ) -> Result<CMVideoFormatDescription, OSStatus> {
283 let mut format_description: CMVideoFormatDescriptionRef = null_mut();
284 let status = unsafe {
285 CMVideoFormatDescriptionCreateFromBigEndianImageDescriptionData(
286 kCFAllocatorDefault,
287 image_description_data.as_ptr(),
288 image_description_data.len(),
289 string_encoding,
290 flavor.as_concrete_TypeRef(),
291 &mut format_description,
292 )
293 };
294 if status == 0 {
295 Ok(unsafe { CMVideoFormatDescription::wrap_under_create_rule(format_description) })
296 } else {
297 Err(status)
298 }
299 }
300
301 #[inline]
302 pub fn from_big_endian_image_description_block_buffer(
303 image_description_block_buffer: &CMBlockBuffer,
304 string_encoding: CFStringEncoding,
305 flavor: &CFString,
306 ) -> Result<CMVideoFormatDescription, OSStatus> {
307 let mut format_description: CMVideoFormatDescriptionRef = null_mut();
308 let status = unsafe {
309 CMVideoFormatDescriptionCreateFromBigEndianImageDescriptionBlockBuffer(
310 kCFAllocatorDefault,
311 image_description_block_buffer.as_concrete_TypeRef(),
312 string_encoding,
313 flavor.as_concrete_TypeRef(),
314 &mut format_description,
315 )
316 };
317 if status == 0 {
318 Ok(unsafe { CMVideoFormatDescription::wrap_under_create_rule(format_description) })
319 } else {
320 Err(status)
321 }
322 }
323
324 #[inline]
325 pub fn copy_as_big_endian_image_description_block_buffer(
326 &self,
327 string_encoding: CFStringEncoding,
328 flavor: &CFString,
329 ) -> Result<CMBlockBuffer, OSStatus> {
330 let mut block_buffer: CMBlockBufferRef = null_mut();
331 let status = unsafe {
332 CMVideoFormatDescriptionCopyAsBigEndianImageDescriptionBlockBuffer(
333 kCFAllocatorDefault,
334 self.as_concrete_TypeRef(),
335 string_encoding,
336 flavor.as_concrete_TypeRef(),
337 &mut block_buffer,
338 )
339 };
340 if status == 0 {
341 Ok(unsafe { CMBlockBuffer::wrap_under_create_rule(block_buffer) })
342 } else {
343 Err(status)
344 }
345 }
346}