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