Skip to main content

core_media/
format_description.rs

1use std::{
2    mem::{forget, size_of_val},
3    ptr::{null, null_mut},
4    slice::from_raw_parts,
5};
6
7use core_audio_types::base_types::{AudioChannelLayout, AudioFormatListItem, AudioStreamBasicDescription};
8use core_foundation::{
9    array::{CFArray, CFArrayRef},
10    base::{kCFAllocatorDefault, Boolean, CFAllocatorRef, CFType, CFTypeID, CFTypeRef, OSStatus, TCFType, TCFTypeRef},
11    declare_TCFType,
12    dictionary::{CFDictionary, CFDictionaryRef},
13    impl_CFTypeDescription, impl_TCFType,
14    propertylist::{CFPropertyList, CFPropertyListRef},
15    string::{CFString, CFStringRef},
16};
17use core_graphics::{
18    base::CGFloat,
19    geometry::{CGRect, CGSize},
20};
21use core_video::image_buffer::{CVImageBuffer, CVImageBufferRef};
22use libc::{c_int, c_void, size_t};
23#[cfg(feature = "objc")]
24use objc2::encode::{Encoding, RefEncode};
25
26use crate::{time::CMTime, OSType};
27
28pub const kCMFormatDescriptionError_InvalidParameter: OSStatus = -12710;
29pub const kCMFormatDescriptionError_AllocationFailed: OSStatus = -12711;
30pub const kCMFormatDescriptionError_ValueNotAvailable: OSStatus = -12718;
31
32type FourCharCode = u32;
33
34pub type CMMediaType = FourCharCode;
35
36#[inline]
37const fn fourcc(code: &[u8; 4]) -> u32 {
38    ((code[0] as u32) << 24) | ((code[1] as u32) << 16) | ((code[2] as u32) << 8) | ((code[3] as u32) << 0)
39}
40
41pub const kCMMediaType_Video: CMMediaType = fourcc(b"vide");
42pub const kCMMediaType_Audio: CMMediaType = fourcc(b"soun");
43pub const kCMMediaType_Muxed: CMMediaType = fourcc(b"muxx");
44pub const kCMMediaType_Text: CMMediaType = fourcc(b"text");
45pub const kCMMediaType_ClosedCaption: CMMediaType = fourcc(b"clcp");
46pub const kCMMediaType_Subtitle: CMMediaType = fourcc(b"sbtl");
47pub const kCMMediaType_TimeCode: CMMediaType = fourcc(b"tmcd");
48pub const kCMMediaType_Metadata: CMMediaType = fourcc(b"meta");
49pub const kCMMediaType_TaggedBufferGroup: CMMediaType = fourcc(b"tbgr");
50
51#[repr(C)]
52pub struct opaqueCMFormatDescription(c_void);
53
54pub type CMFormatDescriptionRef = *mut opaqueCMFormatDescription;
55
56extern "C" {
57    pub fn CMFormatDescriptionCreate(
58        allocator: CFAllocatorRef,
59        mediaType: CMMediaType,
60        mediaSubType: FourCharCode,
61        extensions: CFDictionaryRef,
62        formatDescriptionOut: *mut CMFormatDescriptionRef,
63    ) -> OSStatus;
64    pub fn CMFormatDescriptionGetTypeID() -> CFTypeID;
65    pub fn CMFormatDescriptionEqual(formatDescription: CMFormatDescriptionRef, otherFormatDescription: CMFormatDescriptionRef) -> Boolean;
66    pub fn CMFormatDescriptionEqualIgnoringExtensionKeys(
67        formatDescription: CMFormatDescriptionRef,
68        otherFormatDescription: CMFormatDescriptionRef,
69        formatDescriptionExtensionKeysToIgnore: CFTypeRef,
70        sampleDescriptionExtensionAtomKeysToIgnore: CFTypeRef,
71    ) -> Boolean;
72    pub fn CMFormatDescriptionGetMediaType(desc: CMFormatDescriptionRef) -> CMMediaType;
73    pub fn CMFormatDescriptionGetMediaSubType(desc: CMFormatDescriptionRef) -> FourCharCode;
74    pub fn CMFormatDescriptionGetExtensions(desc: CMFormatDescriptionRef) -> CFDictionaryRef;
75
76    pub static kCMFormatDescriptionExtension_OriginalCompressionSettings: CFStringRef;
77    pub static kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms: CFStringRef;
78    pub static kCMFormatDescriptionExtension_VerbatimSampleDescription: CFStringRef;
79    pub static kCMFormatDescriptionExtension_VerbatimISOSampleEntry: CFStringRef;
80
81    pub fn CMFormatDescriptionGetExtension(desc: CMFormatDescriptionRef, extensionKey: CFStringRef) -> CFPropertyListRef;
82}
83
84pub type CMAudioCodecType = FourCharCode;
85
86pub const kCMAudioCodecType_AAC_LCProtected: CMAudioCodecType = fourcc(b"paac");
87pub const kCMAudioCodecType_AAC_AudibleProtected: CMAudioCodecType = fourcc(b"aaac");
88
89pub type CMAudioFormatDescriptionRef = CMFormatDescriptionRef;
90
91extern "C" {
92    pub fn CMAudioFormatDescriptionCreate(
93        allocator: CFAllocatorRef,
94        asbd: *const AudioStreamBasicDescription,
95        layoutSize: size_t,
96        layout: *const AudioChannelLayout,
97        magicCookieSize: size_t,
98        magicCookie: *const c_void,
99        extensions: CFDictionaryRef,
100        formatDescriptionOut: *mut CMAudioFormatDescriptionRef,
101    ) -> OSStatus;
102    pub fn CMAudioFormatDescriptionGetStreamBasicDescription(desc: CMAudioFormatDescriptionRef) -> *const AudioStreamBasicDescription;
103    pub fn CMAudioFormatDescriptionGetMagicCookie(desc: CMAudioFormatDescriptionRef, sizeOut: *mut size_t) -> *const c_void;
104    pub fn CMAudioFormatDescriptionGetChannelLayout(desc: CMAudioFormatDescriptionRef, sizeOut: *mut size_t) -> *const AudioChannelLayout;
105    pub fn CMAudioFormatDescriptionGetFormatList(desc: CMAudioFormatDescriptionRef, sizeOut: *mut size_t) -> *const AudioFormatListItem;
106    pub fn CMAudioFormatDescriptionGetRichestDecodableFormat(desc: CMAudioFormatDescriptionRef) -> *const AudioFormatListItem;
107    pub fn CMAudioFormatDescriptionGetMostCompatibleFormat(desc: CMAudioFormatDescriptionRef) -> *const AudioFormatListItem;
108    pub fn CMAudioFormatDescriptionCreateSummary(
109        allocator: CFAllocatorRef,
110        formatDescriptionArray: CFArrayRef,
111        flags: u32,
112        formatDescriptionOut: *mut CMAudioFormatDescriptionRef,
113    ) -> OSStatus;
114}
115
116pub type CMAudioFormatDescriptionMask = u32;
117
118pub const kCMAudioFormatDescriptionMask_StreamBasicDescription: CMAudioFormatDescriptionMask = 1 << 0;
119pub const kCMAudioFormatDescriptionMask_MagicCookie: CMAudioFormatDescriptionMask = 1 << 1;
120pub const kCMAudioFormatDescriptionMask_ChannelLayout: CMAudioFormatDescriptionMask = 1 << 2;
121pub const kCMAudioFormatDescriptionMask_Extensions: CMAudioFormatDescriptionMask = 1 << 3;
122pub const kCMAudioFormatDescriptionMask_All: CMAudioFormatDescriptionMask = kCMAudioFormatDescriptionMask_StreamBasicDescription |
123    kCMAudioFormatDescriptionMask_MagicCookie |
124    kCMAudioFormatDescriptionMask_ChannelLayout |
125    kCMAudioFormatDescriptionMask_Extensions;
126
127extern "C" {
128    pub fn CMAudioFormatDescriptionEqual(
129        formatDescription: CMAudioFormatDescriptionRef,
130        otherFormatDescription: CMAudioFormatDescriptionRef,
131        equalityMask: CMAudioFormatDescriptionMask,
132        equalityMaskOut: *mut CMAudioFormatDescriptionMask,
133    ) -> Boolean;
134}
135
136pub type CMVideoFormatDescriptionRef = CMFormatDescriptionRef;
137
138pub type CMPixelFormatType = FourCharCode;
139
140pub const kCMPixelFormat_32ARGB: CMPixelFormatType = 32;
141pub const kCMPixelFormat_32BGRA: CMPixelFormatType = fourcc(b"BGRA");
142pub const kCMPixelFormat_24RGB: CMPixelFormatType = 24;
143pub const kCMPixelFormat_16BE555: CMPixelFormatType = 16;
144pub const kCMPixelFormat_16BE565: CMPixelFormatType = fourcc(b"B565");
145pub const kCMPixelFormat_16LE555: CMPixelFormatType = fourcc(b"L555");
146pub const kCMPixelFormat_16LE565: CMPixelFormatType = fourcc(b"L565");
147pub const kCMPixelFormat_16LE5551: CMPixelFormatType = fourcc(b"5551");
148pub const kCMPixelFormat_422YpCbCr8: CMPixelFormatType = fourcc(b"2vuy");
149pub const kCMPixelFormat_422YpCbCr8_yuvs: CMPixelFormatType = fourcc(b"yuvs");
150pub const kCMPixelFormat_444YpCbCr8: CMPixelFormatType = fourcc(b"v308");
151pub const kCMPixelFormat_4444YpCbCrA8: CMPixelFormatType = fourcc(b"v408");
152pub const kCMPixelFormat_422YpCbCr16: CMPixelFormatType = fourcc(b"v216");
153pub const kCMPixelFormat_422YpCbCr10: CMPixelFormatType = fourcc(b"v210");
154pub const kCMPixelFormat_444YpCbCr10: CMPixelFormatType = fourcc(b"v410");
155pub const kCMPixelFormat_8IndexedGray_WhiteIsZero: CMPixelFormatType = 0x00000028;
156
157pub type CMVideoCodecType = FourCharCode;
158
159pub const kCMVideoCodecType_422YpCbCr8: CMVideoCodecType = kCMPixelFormat_422YpCbCr8;
160pub const kCMVideoCodecType_Animation: CMVideoCodecType = fourcc(b"rle ");
161pub const kCMVideoCodecType_Cinepak: CMVideoCodecType = fourcc(b"cvid");
162pub const kCMVideoCodecType_JPEG: CMVideoCodecType = fourcc(b"jpeg");
163pub const kCMVideoCodecType_JPEG_OpenDML: CMVideoCodecType = fourcc(b"dmb1");
164pub const kCMVideoCodecType_SorensonVideo: CMVideoCodecType = fourcc(b"SVQ1");
165pub const kCMVideoCodecType_SorensonVideo3: CMVideoCodecType = fourcc(b"SVQ3");
166pub const kCMVideoCodecType_H263: CMVideoCodecType = fourcc(b"h263");
167pub const kCMVideoCodecType_H264: CMVideoCodecType = fourcc(b"avc1");
168pub const kCMVideoCodecType_HEVC: CMVideoCodecType = fourcc(b"hvc1");
169pub const kCMVideoCodecType_HEVCWithAlpha: CMVideoCodecType = fourcc(b"muxa");
170pub const kCMVideoCodecType_DolbyVisionHEVC: CMVideoCodecType = fourcc(b"dvh1");
171pub const kCMVideoCodecType_MPEG4Video: CMVideoCodecType = fourcc(b"mp4v");
172pub const kCMVideoCodecType_MPEG2Video: CMVideoCodecType = fourcc(b"mp2v");
173pub const kCMVideoCodecType_MPEG1Video: CMVideoCodecType = fourcc(b"mp1v");
174pub const kCMVideoCodecType_VP9: CMVideoCodecType = fourcc(b"vp09");
175pub const kCMVideoCodecType_DVCNTSC: CMVideoCodecType = fourcc(b"dvc ");
176pub const kCMVideoCodecType_DVCPAL: CMVideoCodecType = fourcc(b"dvcp");
177pub const kCMVideoCodecType_DVCProPAL: CMVideoCodecType = fourcc(b"dvpp");
178pub const kCMVideoCodecType_DVCPro50NTSC: CMVideoCodecType = fourcc(b"dv5n");
179pub const kCMVideoCodecType_DVCPro50PAL: CMVideoCodecType = fourcc(b"dv5p");
180pub const kCMVideoCodecType_DVCPROHD720p60: CMVideoCodecType = fourcc(b"dvhp");
181pub const kCMVideoCodecType_DVCPROHD720p50: CMVideoCodecType = fourcc(b"dvhq");
182pub const kCMVideoCodecType_DVCPROHD1080i60: CMVideoCodecType = fourcc(b"dvh6");
183pub const kCMVideoCodecType_DVCPROHD1080i50: CMVideoCodecType = fourcc(b"dvh5");
184pub const kCMVideoCodecType_DVCPROHD1080p30: CMVideoCodecType = fourcc(b"dvh3");
185pub const kCMVideoCodecType_DVCPROHD1080p25: CMVideoCodecType = fourcc(b"dvh2");
186pub const kCMVideoCodecType_AppleProRes4444XQ: CMVideoCodecType = fourcc(b"ap4x");
187pub const kCMVideoCodecType_AppleProRes4444: CMVideoCodecType = fourcc(b"ap4h");
188pub const kCMVideoCodecType_AppleProRes422HQ: CMVideoCodecType = fourcc(b"apch");
189pub const kCMVideoCodecType_AppleProRes422: CMVideoCodecType = fourcc(b"apcn");
190pub const kCMVideoCodecType_AppleProRes422LT: CMVideoCodecType = fourcc(b"apcs");
191pub const kCMVideoCodecType_AppleProRes422Proxy: CMVideoCodecType = fourcc(b"apco");
192pub const kCMVideoCodecType_AppleProResRAW: CMVideoCodecType = fourcc(b"aprn");
193pub const kCMVideoCodecType_AppleProResRAWHQ: CMVideoCodecType = fourcc(b"aprh");
194pub const kCMVideoCodecType_DisparityHEVC: CMVideoCodecType = fourcc(b"dish");
195pub const kCMVideoCodecType_DepthHEVC: CMVideoCodecType = fourcc(b"deph");
196pub const kCMVideoCodecType_AV1: CMVideoCodecType = fourcc(b"av01");
197
198#[repr(C, align(4))]
199#[derive(Clone, Copy, Debug, Default, PartialEq)]
200pub struct CMVideoDimensions {
201    pub width: i32,
202    pub height: i32,
203}
204
205extern "C" {
206    pub static kCMFormatDescriptionExtension_FormatName: CFStringRef;
207    pub static kCMFormatDescriptionExtension_Depth: CFStringRef;
208    pub static kCMFormatDescriptionExtension_CleanAperture: CFStringRef;
209    pub static kCMFormatDescriptionKey_CleanApertureWidth: CFStringRef;
210    pub static kCMFormatDescriptionKey_CleanApertureHeight: CFStringRef;
211    pub static kCMFormatDescriptionKey_CleanApertureHorizontalOffset: CFStringRef;
212    pub static kCMFormatDescriptionKey_CleanApertureVerticalOffset: CFStringRef;
213    pub static kCMFormatDescriptionKey_CleanApertureWidthRational: CFStringRef;
214    pub static kCMFormatDescriptionKey_CleanApertureHeightRational: CFStringRef;
215    pub static kCMFormatDescriptionKey_CleanApertureHorizontalOffsetRational: CFStringRef;
216    pub static kCMFormatDescriptionKey_CleanApertureVerticalOffsetRational: CFStringRef;
217    pub static kCMFormatDescriptionExtension_FieldCount: CFStringRef;
218    pub static kCMFormatDescriptionFieldDetail_TemporalTopFirst: CFStringRef;
219    pub static kCMFormatDescriptionFieldDetail_TemporalBottomFirst: CFStringRef;
220    pub static kCMFormatDescriptionFieldDetail_SpatialFirstLineEarly: CFStringRef;
221    pub static kCMFormatDescriptionFieldDetail_SpatialFirstLineLate: CFStringRef;
222    pub static kCMFormatDescriptionExtension_PixelAspectRatio: CFStringRef;
223    pub static kCMFormatDescriptionKey_PixelAspectRatioHorizontalSpacing: CFStringRef;
224    pub static kCMFormatDescriptionKey_PixelAspectRatioVerticalSpacing: CFStringRef;
225    pub static kCMFormatDescriptionExtension_ColorPrimaries: CFStringRef;
226    pub static kCMFormatDescriptionColorPrimaries_ITU_R_709_2: CFStringRef;
227    pub static kCMFormatDescriptionColorPrimaries_EBU_3213: CFStringRef;
228    pub static kCMFormatDescriptionColorPrimaries_SMPTE_C: CFStringRef;
229    pub static kCMFormatDescriptionColorPrimaries_DCI_P3: CFStringRef;
230    pub static kCMFormatDescriptionColorPrimaries_P3_D65: CFStringRef;
231    pub static kCMFormatDescriptionColorPrimaries_ITU_R_2020: CFStringRef;
232    pub static kCMFormatDescriptionColorPrimaries_P22: CFStringRef;
233    pub static kCMFormatDescriptionExtension_TransferFunction: CFStringRef;
234    pub static kCMFormatDescriptionTransferFunction_ITU_R_709_2: CFStringRef;
235    pub static kCMFormatDescriptionTransferFunction_SMPTE_240M_1995: CFStringRef;
236    pub static kCMFormatDescriptionTransferFunction_UseGamma: CFStringRef;
237    pub static kCMFormatDescriptionTransferFunction_ITU_R_2020: CFStringRef;
238    pub static kCMFormatDescriptionTransferFunction_SMPTE_ST_428_1: CFStringRef;
239    pub static kCMFormatDescriptionTransferFunction_SMPTE_ST_2084_PQ: CFStringRef;
240    pub static kCMFormatDescriptionTransferFunction_ITU_R_2100_HLG: CFStringRef;
241    pub static kCMFormatDescriptionTransferFunction_Linear: CFStringRef;
242    pub static kCMFormatDescriptionTransferFunction_sRGB: CFStringRef;
243    pub static kCMFormatDescriptionExtension_GammaLevel: CFStringRef;
244    pub static kCMFormatDescriptionExtension_YCbCrMatrix: CFStringRef;
245    pub static kCMFormatDescriptionYCbCrMatrix_ITU_R_709_2: CFStringRef;
246    pub static kCMFormatDescriptionYCbCrMatrix_ITU_R_601_4: CFStringRef;
247    pub static kCMFormatDescriptionYCbCrMatrix_SMPTE_240M_1995: CFStringRef;
248    pub static kCMFormatDescriptionYCbCrMatrix_ITU_R_2020: CFStringRef;
249    pub static kCMFormatDescriptionExtension_FullRangeVideo: CFStringRef;
250    pub static kCMFormatDescriptionExtension_ICCProfile: CFStringRef;
251    pub static kCMFormatDescriptionExtension_BytesPerRow: CFStringRef;
252    pub static kCMFormatDescriptionExtension_ChromaLocationTopField: CFStringRef;
253    pub static kCMFormatDescriptionExtension_ChromaLocationBottomField: CFStringRef;
254    pub static kCMFormatDescriptionChromaLocation_Left: CFStringRef;
255    pub static kCMFormatDescriptionChromaLocation_Center: CFStringRef;
256    pub static kCMFormatDescriptionChromaLocation_TopLeft: CFStringRef;
257    pub static kCMFormatDescriptionChromaLocation_Top: CFStringRef;
258    pub static kCMFormatDescriptionChromaLocation_BottomLeft: CFStringRef;
259    pub static kCMFormatDescriptionChromaLocation_Bottom: CFStringRef;
260    pub static kCMFormatDescriptionChromaLocation_DV420: CFStringRef;
261    pub static kCMFormatDescriptionConformsToMPEG2VideoProfile: CFStringRef;
262    pub static kCMFormatDescriptionExtension_ProtectedContentOriginalFormat: CFStringRef;
263}
264
265pub const kCMMPEG2VideoProfile_HDV_720p30: i32 = fourcc(b"hdv1") as i32;
266pub const kCMMPEG2VideoProfile_HDV_1080i60: i32 = fourcc(b"hdv2") as i32;
267pub const kCMMPEG2VideoProfile_HDV_1080i50: i32 = fourcc(b"hdv3") as i32;
268pub const kCMMPEG2VideoProfile_HDV_720p24: i32 = fourcc(b"hdv4") as i32;
269pub const kCMMPEG2VideoProfile_HDV_720p25: i32 = fourcc(b"hdv5") as i32;
270pub const kCMMPEG2VideoProfile_HDV_1080p24: i32 = fourcc(b"hdv6") as i32;
271pub const kCMMPEG2VideoProfile_HDV_1080p25: i32 = fourcc(b"hdv7") as i32;
272pub const kCMMPEG2VideoProfile_HDV_1080p30: i32 = fourcc(b"hdv8") as i32;
273pub const kCMMPEG2VideoProfile_HDV_720p60: i32 = fourcc(b"hdv9") as i32;
274pub const kCMMPEG2VideoProfile_HDV_720p50: i32 = fourcc(b"hdva") as i32;
275pub const kCMMPEG2VideoProfile_XDCAM_HD_1080i60_VBR35: i32 = fourcc(b"xdv2") as i32;
276pub const kCMMPEG2VideoProfile_XDCAM_HD_1080i50_VBR35: i32 = fourcc(b"xdv3") as i32;
277pub const kCMMPEG2VideoProfile_XDCAM_HD_1080p24_VBR35: i32 = fourcc(b"xdv6") as i32;
278pub const kCMMPEG2VideoProfile_XDCAM_HD_1080p25_VBR35: i32 = fourcc(b"xdv7") as i32;
279pub const kCMMPEG2VideoProfile_XDCAM_HD_1080p30_VBR35: i32 = fourcc(b"xdv8") as i32;
280pub const kCMMPEG2VideoProfile_XDCAM_EX_720p24_VBR35: i32 = fourcc(b"xdv4") as i32;
281pub const kCMMPEG2VideoProfile_XDCAM_EX_720p25_VBR35: i32 = fourcc(b"xdv5") as i32;
282pub const kCMMPEG2VideoProfile_XDCAM_EX_720p30_VBR35: i32 = fourcc(b"xdv1") as i32;
283pub const kCMMPEG2VideoProfile_XDCAM_EX_720p50_VBR35: i32 = fourcc(b"xdva") as i32;
284pub const kCMMPEG2VideoProfile_XDCAM_EX_720p60_VBR35: i32 = fourcc(b"xdv9") as i32;
285pub const kCMMPEG2VideoProfile_XDCAM_EX_1080i60_VBR35: i32 = fourcc(b"xdvb") as i32;
286pub const kCMMPEG2VideoProfile_XDCAM_EX_1080i50_VBR35: i32 = fourcc(b"xdvc") as i32;
287pub const kCMMPEG2VideoProfile_XDCAM_EX_1080p24_VBR35: i32 = fourcc(b"xdvd") as i32;
288pub const kCMMPEG2VideoProfile_XDCAM_EX_1080p25_VBR35: i32 = fourcc(b"xdve") as i32;
289pub const kCMMPEG2VideoProfile_XDCAM_EX_1080p30_VBR35: i32 = fourcc(b"xdvf") as i32;
290pub const kCMMPEG2VideoProfile_XDCAM_HD422_720p50_CBR50: i32 = fourcc(b"xd5a") as i32;
291pub const kCMMPEG2VideoProfile_XDCAM_HD422_720p60_CBR50: i32 = fourcc(b"xd59") as i32;
292pub const kCMMPEG2VideoProfile_XDCAM_HD422_1080i60_CBR50: i32 = fourcc(b"xd5b") as i32;
293pub const kCMMPEG2VideoProfile_XDCAM_HD422_1080i50_CBR50: i32 = fourcc(b"xd5c") as i32;
294pub const kCMMPEG2VideoProfile_XDCAM_HD422_1080p24_CBR50: i32 = fourcc(b"xd5d") as i32;
295pub const kCMMPEG2VideoProfile_XDCAM_HD422_1080p25_CBR50: i32 = fourcc(b"xd5e") as i32;
296pub const kCMMPEG2VideoProfile_XDCAM_HD422_1080p30_CBR50: i32 = fourcc(b"xd5f") as i32;
297pub const kCMMPEG2VideoProfile_XDCAM_HD_540p: i32 = fourcc(b"xdhd") as i32;
298pub const kCMMPEG2VideoProfile_XDCAM_HD422_540p: i32 = fourcc(b"xdh2") as i32;
299pub const kCMMPEG2VideoProfile_XDCAM_HD422_720p24_CBR50: i32 = fourcc(b"xd54") as i32;
300pub const kCMMPEG2VideoProfile_XDCAM_HD422_720p25_CBR50: i32 = fourcc(b"xd55") as i32;
301pub const kCMMPEG2VideoProfile_XDCAM_HD422_720p30_CBR50: i32 = fourcc(b"xd51") as i32;
302pub const kCMMPEG2VideoProfile_XF: i32 = fourcc(b"xfz1") as i32;
303
304extern "C" {
305    pub static kCMFormatDescriptionExtension_TemporalQuality: CFStringRef;
306    pub static kCMFormatDescriptionExtension_SpatialQuality: CFStringRef;
307    pub static kCMFormatDescriptionExtension_VerbatimImageDescription: CFStringRef;
308    pub static kCMFormatDescriptionExtension_Version: CFStringRef;
309    pub static kCMFormatDescriptionExtension_RevisionLevel: CFStringRef;
310    pub static kCMFormatDescriptionExtension_Vendor: CFStringRef;
311    pub static kCMFormatDescriptionVendor_Apple: CFStringRef;
312    pub static kCMFormatDescriptionExtension_MasteringDisplayColorVolume: CFStringRef;
313    pub static kCMFormatDescriptionExtension_ContentLightLevelInfo: CFStringRef;
314    pub static kCMFormatDescriptionExtension_ContentColorVolume: CFStringRef;
315    pub static kCMFormatDescriptionExtension_AlternativeTransferCharacteristics: CFStringRef;
316    pub static kCMFormatDescriptionExtension_AuxiliaryTypeInfo: CFStringRef;
317    pub static kCMFormatDescriptionExtension_AlphaChannelMode: CFStringRef;
318    pub static kCMFormatDescriptionAlphaChannelMode_StraightAlpha: CFStringRef;
319    pub static kCMFormatDescriptionAlphaChannelMode_PremultipliedAlpha: CFStringRef;
320    pub static kCMFormatDescriptionExtension_ContainsAlphaChannel: CFStringRef;
321    pub static kCMFormatDescriptionExtension_BitsPerComponent: CFStringRef;
322    pub static kCMFormatDescriptionExtension_HorizontalFieldOfView: CFStringRef;
323    pub static kCMFormatDescriptionExtension_HeroEye: CFStringRef;
324    pub static kCMFormatDescriptionHeroEye_Left: CFStringRef;
325    pub static kCMFormatDescriptionHeroEye_Right: CFStringRef;
326    pub static kCMFormatDescriptionExtension_StereoCameraBaseline: CFStringRef;
327    pub static kCMFormatDescriptionExtension_HorizontalDisparityAdjustment: CFStringRef;
328
329    pub fn CMVideoFormatDescriptionCreate(
330        allocator: CFAllocatorRef,
331        codecType: CMVideoCodecType,
332        width: i32,
333        height: i32,
334        extensions: CFDictionaryRef,
335        formatDescriptionOut: *mut CMVideoFormatDescriptionRef,
336    ) -> OSStatus;
337    pub fn CMVideoFormatDescriptionCreateForImageBuffer(
338        allocator: CFAllocatorRef,
339        imageBuffer: CVImageBufferRef,
340        formatDescriptionOut: *mut CMVideoFormatDescriptionRef,
341    ) -> OSStatus;
342    pub fn CMVideoFormatDescriptionCreateFromH264ParameterSets(
343        allocator: CFAllocatorRef,
344        parameterSetCount: size_t,
345        parameterSetPointers: *const *const u8,
346        parameterSetSizes: *const size_t,
347        NALUnitHeaderLength: c_int,
348        formatDescriptionOut: *mut CMFormatDescriptionRef,
349    ) -> OSStatus;
350    pub fn CMVideoFormatDescriptionCreateFromHEVCParameterSets(
351        allocator: CFAllocatorRef,
352        parameterSetCount: size_t,
353        parameterSetPointers: *const *const u8,
354        parameterSetSizes: *const size_t,
355        NALUnitHeaderLength: c_int,
356        extensions: CFDictionaryRef,
357        formatDescriptionOut: *mut CMFormatDescriptionRef,
358    ) -> OSStatus;
359    pub fn CMVideoFormatDescriptionGetH264ParameterSetAtIndex(
360        videoDesc: CMFormatDescriptionRef,
361        parameterSetIndex: size_t,
362        parameterSetPointerOut: *mut *const u8,
363        parameterSetSizeOut: *mut size_t,
364        parameterSetCountOut: *mut size_t,
365        NALUnitHeaderLengthOut: *mut c_int,
366    ) -> OSStatus;
367    pub fn CMVideoFormatDescriptionGetHEVCParameterSetAtIndex(
368        videoDesc: CMFormatDescriptionRef,
369        parameterSetIndex: size_t,
370        parameterSetPointerOut: *mut *const u8,
371        parameterSetSizeOut: *mut size_t,
372        parameterSetCountOut: *mut size_t,
373        NALUnitHeaderLengthOut: *mut c_int,
374    ) -> OSStatus;
375    pub fn CMVideoFormatDescriptionGetDimensions(videoDesc: CMVideoFormatDescriptionRef) -> CMVideoDimensions;
376    pub fn CMVideoFormatDescriptionGetPresentationDimensions(
377        videoDesc: CMVideoFormatDescriptionRef,
378        usePixelAspectRatio: Boolean,
379        useCleanAperture: Boolean,
380    ) -> CGSize;
381    pub fn CMVideoFormatDescriptionGetCleanAperture(videoDesc: CMVideoFormatDescriptionRef, originIsAtTopLeft: Boolean) -> CGRect;
382    pub fn CMVideoFormatDescriptionGetExtensionKeysCommonWithImageBuffers() -> CFArrayRef;
383    pub fn CMVideoFormatDescriptionMatchesImageBuffer(videoDesc: CMVideoFormatDescriptionRef, imageBuffer: CVImageBufferRef) -> Boolean;
384    pub fn CMVideoFormatDescriptionCopyTagCollectionArray(
385        formatDescription: CMVideoFormatDescriptionRef,
386        tagCollectionsOut: *mut CFArrayRef,
387    ) -> OSStatus;
388}
389
390pub type CMTaggedBufferGroupFormatDescriptionRef = CMFormatDescriptionRef;
391
392pub type CMTaggedBufferGroupFormatType = FourCharCode;
393
394pub const kCMTaggedBufferGroupFormatType_TaggedBufferGroup: CMTaggedBufferGroupFormatType = fourcc(b"tbgr");
395
396pub type CMMuxedFormatDescriptionRef = CMFormatDescriptionRef;
397
398pub type CMMuxedStreamType = FourCharCode;
399
400pub const kCMMuxedStreamType_MPEG1System: CMMuxedStreamType = fourcc(b"mp1s");
401pub const kCMMuxedStreamType_MPEG2Transport: CMMuxedStreamType = fourcc(b"mp2t");
402pub const kCMMuxedStreamType_MPEG2Program: CMMuxedStreamType = fourcc(b"mp2p");
403pub const kCMMuxedStreamType_DV: CMMuxedStreamType = fourcc(b"dv  ");
404pub const kCMMuxedStreamType_EmbeddedDeviceScreenRecording: CMMuxedStreamType = fourcc(b"isr ");
405
406extern "C" {
407    pub fn CMMuxedFormatDescriptionCreate(
408        allocator: CFAllocatorRef,
409        muxType: CMMuxedStreamType,
410        extensions: CFDictionaryRef,
411        formatDescriptionOut: *mut CMMuxedFormatDescriptionRef,
412    ) -> OSStatus;
413}
414
415pub type CMClosedCaptionFormatDescriptionRef = CMFormatDescriptionRef;
416
417pub type CMClosedCaptionFormatType = FourCharCode;
418
419pub const kCMClosedCaptionFormatType_CEA608: CMClosedCaptionFormatType = fourcc(b"c608");
420pub const kCMClosedCaptionFormatType_CEA708: CMClosedCaptionFormatType = fourcc(b"c708");
421pub const kCMClosedCaptionFormatType_ATSC: CMClosedCaptionFormatType = fourcc(b"atcc");
422
423pub type CMTextFormatDescriptionRef = CMFormatDescriptionRef;
424
425pub type CMTextFormatType = FourCharCode;
426
427pub const kCMTextFormatType_QTText: CMTextFormatType = fourcc(b"text");
428pub const kCMTextFormatType_3GText: CMTextFormatType = fourcc(b"tx3g");
429
430pub type CMTextDisplayFlags = u32;
431
432pub const kCMTextDisplayFlag_scrollIn: CMTextDisplayFlags = 0x00000020;
433pub const kCMTextDisplayFlag_scrollOut: CMTextDisplayFlags = 0x00000040;
434pub const kCMTextDisplayFlag_scrollDirectionMask: CMTextDisplayFlags = 0x00000180;
435pub const kCMTextDisplayFlag_scrollDirection_bottomToTop: CMTextDisplayFlags = 0x00000000;
436pub const kCMTextDisplayFlag_scrollDirection_rightToLeft: CMTextDisplayFlags = 0x00000080;
437pub const kCMTextDisplayFlag_scrollDirection_topToBottom: CMTextDisplayFlags = 0x00000100;
438pub const kCMTextDisplayFlag_scrollDirection_leftToRight: CMTextDisplayFlags = 0x00000180;
439pub const kCMTextDisplayFlag_continuousKaraoke: CMTextDisplayFlags = 0x00000800;
440pub const kCMTextDisplayFlag_writeTextVertically: CMTextDisplayFlags = 0x00020000;
441pub const kCMTextDisplayFlag_fillTextRegion: CMTextDisplayFlags = 0x00040000;
442pub const kCMTextDisplayFlag_obeySubtitleFormatting: CMTextDisplayFlags = 0x20000000;
443pub const kCMTextDisplayFlag_forcedSubtitlesPresent: CMTextDisplayFlags = 0x40000000;
444pub const kCMTextDisplayFlag_allSubtitlesForced: CMTextDisplayFlags = 0x80000000;
445
446pub type CMTextJustificationValue = i8;
447
448pub const kCMTextJustification_left_top: CMTextJustificationValue = 0;
449pub const kCMTextJustification_centered: CMTextJustificationValue = 1;
450pub const kCMTextJustification_bottom_right: CMTextJustificationValue = -1;
451
452extern "C" {
453    pub static kCMTextFormatDescriptionExtension_DisplayFlags: CFStringRef;
454    pub static kCMTextFormatDescriptionExtension_BackgroundColor: CFStringRef;
455    pub static kCMTextFormatDescriptionColor_Red: CFStringRef;
456    pub static kCMTextFormatDescriptionColor_Green: CFStringRef;
457    pub static kCMTextFormatDescriptionColor_Blue: CFStringRef;
458    pub static kCMTextFormatDescriptionColor_Alpha: CFStringRef;
459    pub static kCMTextFormatDescriptionExtension_DefaultTextBox: CFStringRef;
460    pub static kCMTextFormatDescriptionRect_Top: CFStringRef;
461    pub static kCMTextFormatDescriptionRect_Left: CFStringRef;
462    pub static kCMTextFormatDescriptionRect_Bottom: CFStringRef;
463    pub static kCMTextFormatDescriptionRect_Right: CFStringRef;
464    pub static kCMTextFormatDescriptionExtension_DefaultStyle: CFStringRef;
465    pub static kCMTextFormatDescriptionStyle_StartChar: CFStringRef;
466    pub static kCMTextFormatDescriptionStyle_Font: CFStringRef;
467    pub static kCMTextFormatDescriptionStyle_FontFace: CFStringRef;
468    pub static kCMTextFormatDescriptionStyle_ForegroundColor: CFStringRef;
469    pub static kCMTextFormatDescriptionStyle_FontSize: CFStringRef;
470    pub static kCMTextFormatDescriptionExtension_HorizontalJustification: CFStringRef;
471    pub static kCMTextFormatDescriptionExtension_VerticalJustification: CFStringRef;
472    pub static kCMTextFormatDescriptionStyle_EndChar: CFStringRef;
473    pub static kCMTextFormatDescriptionExtension_FontTable: CFStringRef;
474    pub static kCMTextFormatDescriptionExtension_TextJustification: CFStringRef;
475    pub static kCMTextFormatDescriptionStyle_Height: CFStringRef;
476    pub static kCMTextFormatDescriptionStyle_Ascent: CFStringRef;
477    pub static kCMTextFormatDescriptionExtension_DefaultFontName: CFStringRef;
478    pub static kCMFormatDescriptionExtension_AmbientViewingEnvironment: CFStringRef;
479
480    pub fn CMTextFormatDescriptionGetDisplayFlags(desc: CMFormatDescriptionRef, displayFlagsOut: *mut CMTextDisplayFlags) -> OSStatus;
481    pub fn CMTextFormatDescriptionGetJustification(
482        desc: CMFormatDescriptionRef,
483        horizontaJustificationlOut: *mut CMTextJustificationValue,
484        verticalJustificationOut: *mut CMTextJustificationValue,
485    ) -> OSStatus;
486    pub fn CMTextFormatDescriptionGetDefaultTextBox(
487        desc: CMFormatDescriptionRef,
488        originIsAtTopLeft: Boolean,
489        heightOfTextTrack: CGFloat,
490        defaultTextBoxOut: *mut CGRect,
491    ) -> OSStatus;
492    pub fn CMTextFormatDescriptionGetDefaultStyle(
493        desc: CMFormatDescriptionRef,
494        localFontIDOut: *mut u16,
495        boldOut: *mut Boolean,
496        italicOut: *mut Boolean,
497        underlineOut: *mut Boolean,
498        fontSizeOut: *mut CGFloat,
499        colorComponentsOut: *mut [CGFloat; 4usize],
500    ) -> OSStatus;
501    pub fn CMTextFormatDescriptionGetFontName(desc: CMFormatDescriptionRef, localFontID: u16, fontNameOut: *mut CFStringRef) -> OSStatus;
502}
503
504pub type CMSubtitleFormatType = FourCharCode;
505
506pub const kCMSubtitleFormatType_3GText: CMSubtitleFormatType = fourcc(b"tx3g");
507pub const kCMSubtitleFormatType_WebVTT: CMSubtitleFormatType = fourcc(b"wvtt");
508
509pub type CMTimeCodeFormatDescriptionRef = CMFormatDescriptionRef;
510
511pub type CMTimeCodeFormatType = FourCharCode;
512
513pub const kCMTimeCodeFormatType_TimeCode32: CMTimeCodeFormatType = fourcc(b"tmcd");
514pub const kCMTimeCodeFormatType_TimeCode64: CMTimeCodeFormatType = fourcc(b"tc64");
515pub const kCMTimeCodeFormatType_Counter32: CMTimeCodeFormatType = fourcc(b"cn32");
516pub const kCMTimeCodeFormatType_Counter64: CMTimeCodeFormatType = fourcc(b"cn64");
517
518pub const kCMTimeCodeFlag_DropFrame: u32 = 1 << 0;
519pub const kCMTimeCodeFlag_24HourMax: u32 = 1 << 1;
520pub const kCMTimeCodeFlag_NegTimesOK: u32 = 1 << 2;
521
522extern "C" {
523    pub fn CMTimeCodeFormatDescriptionCreate(
524        allocator: CFAllocatorRef,
525        timeCodeFormatType: CMTimeCodeFormatType,
526        frameDuration: CMTime,
527        frameQuanta: u32,
528        flags: u32,
529        extensions: CFDictionaryRef,
530        formatDescriptionOut: *mut CMTimeCodeFormatDescriptionRef,
531    ) -> OSStatus;
532    pub fn CMTimeCodeFormatDescriptionGetFrameDuration(desc: CMTimeCodeFormatDescriptionRef) -> CMTime;
533    pub fn CMTimeCodeFormatDescriptionGetFrameQuanta(desc: CMTimeCodeFormatDescriptionRef) -> u32;
534    pub fn CMTimeCodeFormatDescriptionGetTimeCodeFlags(desc: CMTimeCodeFormatDescriptionRef) -> u32;
535
536    pub static kCMTimeCodeFormatDescriptionExtension_SourceReferenceName: CFStringRef;
537    pub static kCMTimeCodeFormatDescriptionKey_Value: CFStringRef;
538    pub static kCMTimeCodeFormatDescriptionKey_LangCode: CFStringRef;
539}
540
541pub type CMMetadataFormatDescriptionRef = CMFormatDescriptionRef;
542
543pub type CMMetadataFormatType = FourCharCode;
544
545pub const kCMMetadataFormatType_ICY: CMMetadataFormatType = fourcc(b"icy ");
546pub const kCMMetadataFormatType_ID3: CMMetadataFormatType = fourcc(b"id3 ");
547pub const kCMMetadataFormatType_Boxed: CMMetadataFormatType = fourcc(b"mebx");
548pub const kCMMetadataFormatType_EMSG: CMMetadataFormatType = fourcc(b"emsg");
549
550extern "C" {
551    pub static kCMFormatDescriptionExtensionKey_MetadataKeyTable: CFStringRef;
552    pub static kCMMetadataFormatDescriptionKey_Namespace: CFStringRef;
553    pub static kCMMetadataFormatDescriptionKey_Value: CFStringRef;
554    pub static kCMMetadataFormatDescriptionKey_LocalID: CFStringRef;
555    pub static kCMMetadataFormatDescriptionKey_DataType: CFStringRef;
556    pub static kCMMetadataFormatDescriptionKey_DataTypeNamespace: CFStringRef;
557    pub static kCMMetadataFormatDescriptionKey_ConformingDataTypes: CFStringRef;
558    pub static kCMMetadataFormatDescriptionKey_LanguageTag: CFStringRef;
559    pub static kCMMetadataFormatDescriptionKey_StructuralDependency: CFStringRef;
560    pub static kCMMetadataFormatDescriptionKey_SetupData: CFStringRef;
561    pub static kCMMetadataFormatDescription_StructuralDependencyKey_DependencyIsInvalidFlag: CFStringRef;
562    pub static kCMMetadataFormatDescriptionMetadataSpecificationKey_Identifier: CFStringRef;
563    pub static kCMMetadataFormatDescriptionMetadataSpecificationKey_DataType: CFStringRef;
564    pub static kCMMetadataFormatDescriptionMetadataSpecificationKey_ExtendedLanguageTag: CFStringRef;
565    pub static kCMMetadataFormatDescriptionMetadataSpecificationKey_StructuralDependency: CFStringRef;
566    pub static kCMMetadataFormatDescriptionMetadataSpecificationKey_SetupData: CFStringRef;
567
568    pub fn CMMetadataFormatDescriptionCreateWithKeys(
569        allocator: CFAllocatorRef,
570        metadataType: CMMetadataFormatType,
571        keys: CFArrayRef,
572        formatDescriptionOut: *mut CMMetadataFormatDescriptionRef,
573    ) -> OSStatus;
574    pub fn CMMetadataFormatDescriptionCreateWithMetadataSpecifications(
575        allocator: CFAllocatorRef,
576        metadataType: CMMetadataFormatType,
577        metadataSpecifications: CFArrayRef,
578        formatDescriptionOut: *mut CMMetadataFormatDescriptionRef,
579    ) -> OSStatus;
580    pub fn CMMetadataFormatDescriptionCreateWithMetadataFormatDescriptionAndMetadataSpecifications(
581        allocator: CFAllocatorRef,
582        sourceDescription: CMMetadataFormatDescriptionRef,
583        metadataSpecifications: CFArrayRef,
584        formatDescriptionOut: *mut CMMetadataFormatDescriptionRef,
585    ) -> OSStatus;
586    pub fn CMMetadataFormatDescriptionCreateByMergingMetadataFormatDescriptions(
587        allocator: CFAllocatorRef,
588        sourceDescription: CMMetadataFormatDescriptionRef,
589        otherSourceDescription: CMMetadataFormatDescriptionRef,
590        formatDescriptionOut: *mut CMMetadataFormatDescriptionRef,
591    ) -> OSStatus;
592    pub fn CMMetadataFormatDescriptionGetKeyWithLocalID(desc: CMMetadataFormatDescriptionRef, localKeyID: OSType) -> CFDictionaryRef;
593    pub fn CMMetadataFormatDescriptionGetIdentifiers(desc: CMMetadataFormatDescriptionRef) -> CFArrayRef;
594}
595
596#[cfg(feature = "objc")]
597unsafe impl RefEncode for opaqueCMFormatDescription {
598    const ENCODING_REF: Encoding = Encoding::Pointer(&Encoding::Struct("opaqueCMFormatDescription", &[]));
599}
600
601pub trait TCMFormatDescription: TCFType {
602    #[inline]
603    fn as_buffer(&self) -> CMFormatDescription {
604        unsafe { CMFormatDescription::wrap_under_get_rule(self.as_concrete_TypeRef().as_void_ptr() as CMFormatDescriptionRef) }
605    }
606
607    #[inline]
608    fn into_buffer(self) -> CMFormatDescription
609    where
610        Self: Sized,
611    {
612        let reference = self.as_concrete_TypeRef().as_void_ptr() as CMFormatDescriptionRef;
613        forget(self);
614        unsafe { CMFormatDescription::wrap_under_create_rule(reference) }
615    }
616}
617
618impl CMFormatDescription {
619    #[inline]
620    pub fn downcast<T: TCMFormatDescription>(&self) -> Option<T> {
621        if self.instance_of::<T>() {
622            unsafe { Some(T::wrap_under_get_rule(T::Ref::from_void_ptr(self.as_concrete_TypeRef() as *const c_void))) }
623        } else {
624            None
625        }
626    }
627
628    #[inline]
629    pub fn downcast_into<T: TCMFormatDescription>(self) -> Option<T> {
630        if self.instance_of::<T>() {
631            unsafe {
632                let reference = T::Ref::from_void_ptr(self.as_concrete_TypeRef() as *const c_void);
633                forget(self);
634                Some(T::wrap_under_create_rule(reference))
635            }
636        } else {
637            None
638        }
639    }
640}
641
642declare_TCFType! {
643    CMFormatDescription, CMFormatDescriptionRef
644}
645impl_TCFType!(CMFormatDescription, CMFormatDescriptionRef, CMFormatDescriptionGetTypeID);
646impl_CFTypeDescription!(CMFormatDescription);
647
648impl CMFormatDescription {
649    #[inline]
650    pub fn new(media_type: CMMediaType, media_subtype: FourCharCode, extensions: Option<&CFDictionary<CFString, CFType>>) -> Result<Self, OSStatus> {
651        let mut format_description: CMFormatDescriptionRef = null_mut();
652        let status = unsafe {
653            CMFormatDescriptionCreate(
654                kCFAllocatorDefault,
655                media_type,
656                media_subtype,
657                extensions.map_or(null(), |exts| exts.as_concrete_TypeRef()),
658                &mut format_description,
659            )
660        };
661        if status == 0 {
662            Ok(unsafe { TCFType::wrap_under_create_rule(format_description) })
663        } else {
664            Err(status)
665        }
666    }
667
668    #[inline]
669    pub fn equal(&self, other: &Self) -> bool {
670        unsafe { CMFormatDescriptionEqual(self.as_concrete_TypeRef(), other.as_concrete_TypeRef()) != 0 }
671    }
672
673    #[inline]
674    pub fn equal_ignoring_extension_keys(
675        &self,
676        other: &Self,
677        extension_keys_to_ignore: &CFType,
678        sample_description_extension_atom_keys_to_ignore: &CFType,
679    ) -> bool {
680        unsafe {
681            CMFormatDescriptionEqualIgnoringExtensionKeys(
682                self.as_concrete_TypeRef(),
683                other.as_concrete_TypeRef(),
684                extension_keys_to_ignore.as_concrete_TypeRef(),
685                sample_description_extension_atom_keys_to_ignore.as_concrete_TypeRef(),
686            ) != 0
687        }
688    }
689
690    #[inline]
691    pub fn get_media_type(&self) -> CMMediaType {
692        unsafe { CMFormatDescriptionGetMediaType(self.as_concrete_TypeRef()) }
693    }
694
695    #[inline]
696    pub fn get_media_subtype(&self) -> FourCharCode {
697        unsafe { CMFormatDescriptionGetMediaSubType(self.as_concrete_TypeRef()) }
698    }
699
700    #[inline]
701    pub fn get_extensions(&self) -> Option<CFDictionary<CFString, CFType>> {
702        unsafe {
703            let extensions = CMFormatDescriptionGetExtensions(self.as_concrete_TypeRef());
704            if extensions.is_null() {
705                None
706            } else {
707                Some(TCFType::wrap_under_get_rule(extensions))
708            }
709        }
710    }
711
712    #[inline]
713    pub fn get_extension(&self, extension_key: &CFString) -> Option<CFPropertyList> {
714        unsafe {
715            let extension = CMFormatDescriptionGetExtension(self.as_concrete_TypeRef(), extension_key.as_concrete_TypeRef());
716            if extension.is_null() {
717                None
718            } else {
719                Some(CFPropertyList::wrap_under_get_rule(extension))
720            }
721        }
722    }
723}
724
725impl TCMFormatDescription for CMAudioFormatDescription {}
726
727declare_TCFType! {
728    CMAudioFormatDescription, CMAudioFormatDescriptionRef
729}
730impl_TCFType!(CMAudioFormatDescription, CMAudioFormatDescriptionRef, CMFormatDescriptionGetTypeID);
731impl_CFTypeDescription!(CMAudioFormatDescription);
732
733impl CMAudioFormatDescription {
734    #[inline]
735    pub fn new(
736        asbd: &AudioStreamBasicDescription,
737        layout: &AudioChannelLayout,
738        magic_cookie: &[u8],
739        extensions: Option<&CFDictionary<CFString, CFType>>,
740    ) -> Result<Self, OSStatus> {
741        let mut format_description: CMAudioFormatDescriptionRef = null_mut();
742        let status = unsafe {
743            CMAudioFormatDescriptionCreate(
744                kCFAllocatorDefault,
745                asbd,
746                size_of_val(layout),
747                layout,
748                magic_cookie.len(),
749                magic_cookie.as_ptr() as *const _,
750                extensions.map_or(null(), |exts| exts.as_concrete_TypeRef()),
751                &mut format_description,
752            )
753        };
754        if status == 0 {
755            Ok(unsafe { TCFType::wrap_under_create_rule(format_description) })
756        } else {
757            Err(status)
758        }
759    }
760
761    #[inline]
762    pub fn get_codec_type(&self) -> CMAudioCodecType {
763        unsafe { CMFormatDescriptionGetMediaSubType(self.as_concrete_TypeRef()) }
764    }
765
766    #[inline]
767    pub fn get_stream_basic_description(&self) -> Option<&AudioStreamBasicDescription> {
768        unsafe {
769            let asbd = CMAudioFormatDescriptionGetStreamBasicDescription(self.as_concrete_TypeRef());
770            if asbd.is_null() {
771                None
772            } else {
773                Some(&*asbd)
774            }
775        }
776    }
777
778    #[inline]
779    pub fn get_magic_cookie(&self) -> Option<&[u8]> {
780        unsafe {
781            let mut size = 0;
782            let cookie = CMAudioFormatDescriptionGetMagicCookie(self.as_concrete_TypeRef(), &mut size);
783            if cookie.is_null() {
784                None
785            } else {
786                Some(from_raw_parts(cookie as *const u8, size))
787            }
788        }
789    }
790
791    #[inline]
792    pub fn get_channel_layout(&self) -> Option<(&AudioChannelLayout, usize)> {
793        unsafe {
794            let mut size = 0;
795            let layout = CMAudioFormatDescriptionGetChannelLayout(self.as_concrete_TypeRef(), &mut size);
796            if layout.is_null() {
797                None
798            } else {
799                Some((&*layout, size))
800            }
801        }
802    }
803
804    #[inline]
805    pub fn get_format_list(&self) -> Option<&[AudioFormatListItem]> {
806        unsafe {
807            let mut size = 0;
808            let list = CMAudioFormatDescriptionGetFormatList(self.as_concrete_TypeRef(), &mut size);
809            if list.is_null() {
810                None
811            } else {
812                Some(from_raw_parts(list, size))
813            }
814        }
815    }
816
817    #[inline]
818    pub fn get_richest_decodable_format(&self) -> Option<&AudioFormatListItem> {
819        unsafe {
820            let format = CMAudioFormatDescriptionGetRichestDecodableFormat(self.as_concrete_TypeRef());
821            if format.is_null() {
822                None
823            } else {
824                Some(&*format)
825            }
826        }
827    }
828
829    #[inline]
830    pub fn get_most_compatible_format(&self) -> Option<&AudioFormatListItem> {
831        unsafe {
832            let format = CMAudioFormatDescriptionGetMostCompatibleFormat(self.as_concrete_TypeRef());
833            if format.is_null() {
834                None
835            } else {
836                Some(&*format)
837            }
838        }
839    }
840
841    #[inline]
842    pub fn new_summary(format_description_array: &CFArray<CMAudioFormatDescription>, flags: u32) -> Result<Self, OSStatus> {
843        let mut format_description: CMAudioFormatDescriptionRef = null_mut();
844        let status = unsafe {
845            CMAudioFormatDescriptionCreateSummary(kCFAllocatorDefault, format_description_array.as_concrete_TypeRef(), flags, &mut format_description)
846        };
847        if status == 0 {
848            Ok(unsafe { TCFType::wrap_under_create_rule(format_description) })
849        } else {
850            Err(status)
851        }
852    }
853
854    #[inline]
855    pub fn equal(&self, other: &Self, eequality_mask: CMAudioFormatDescriptionMask) -> (bool, CMAudioFormatDescriptionMask) {
856        let mut mask = 0;
857        let equal = unsafe { CMAudioFormatDescriptionEqual(self.as_concrete_TypeRef(), other.as_concrete_TypeRef(), eequality_mask, &mut mask) != 0 };
858        (equal, mask)
859    }
860}
861
862impl TCMFormatDescription for CMVideoFormatDescription {}
863
864declare_TCFType! {
865    CMVideoFormatDescription, CMVideoFormatDescriptionRef
866}
867impl_TCFType!(CMVideoFormatDescription, CMVideoFormatDescriptionRef, CMFormatDescriptionGetTypeID);
868impl_CFTypeDescription!(CMVideoFormatDescription);
869
870impl CMVideoFormatDescription {
871    #[inline]
872    pub fn new(codec_type: CMVideoCodecType, width: i32, height: i32, extensions: Option<&CFDictionary<CFString, CFType>>) -> Result<Self, OSStatus> {
873        let mut format_description: CMVideoFormatDescriptionRef = null_mut();
874        let status = unsafe {
875            CMVideoFormatDescriptionCreate(
876                kCFAllocatorDefault,
877                codec_type,
878                width,
879                height,
880                extensions.as_ref().map_or(null(), |exts| exts.as_concrete_TypeRef()),
881                &mut format_description,
882            )
883        };
884        if status == 0 {
885            Ok(unsafe { TCFType::wrap_under_create_rule(format_description) })
886        } else {
887            Err(status)
888        }
889    }
890
891    #[inline]
892    pub fn from_image_buffer(image_buffer: &CVImageBuffer) -> Result<Self, OSStatus> {
893        let mut format_description: CMVideoFormatDescriptionRef = null_mut();
894        let status =
895            unsafe { CMVideoFormatDescriptionCreateForImageBuffer(kCFAllocatorDefault, image_buffer.as_concrete_TypeRef(), &mut format_description) };
896        if status == 0 {
897            Ok(unsafe { TCFType::wrap_under_create_rule(format_description) })
898        } else {
899            Err(status)
900        }
901    }
902
903    #[inline]
904    pub fn from_h264_parameter_sets(parameter_sets: &[&[u8]], nal_unit_header_length: i32) -> Result<Self, OSStatus> {
905        let mut format_description: CMVideoFormatDescriptionRef = null_mut();
906        let status = unsafe {
907            CMVideoFormatDescriptionCreateFromH264ParameterSets(
908                kCFAllocatorDefault,
909                parameter_sets.len(),
910                parameter_sets.iter().map(|data| data.as_ptr()).collect::<Vec<_>>().as_ptr(),
911                parameter_sets.iter().map(|data| data.len()).collect::<Vec<_>>().as_ptr(),
912                nal_unit_header_length,
913                &mut format_description,
914            )
915        };
916        if status == 0 {
917            Ok(unsafe { TCFType::wrap_under_create_rule(format_description) })
918        } else {
919            Err(status)
920        }
921    }
922
923    #[inline]
924    pub fn from_hevc_parameter_sets(
925        parameter_sets: &[&[u8]],
926        nal_unit_header_length: i32,
927        extensions: &CFDictionary<CFString, CFType>,
928    ) -> Result<Self, OSStatus> {
929        let mut format_description: CMVideoFormatDescriptionRef = null_mut();
930        let status = unsafe {
931            CMVideoFormatDescriptionCreateFromHEVCParameterSets(
932                kCFAllocatorDefault,
933                parameter_sets.len(),
934                parameter_sets.iter().map(|data| data.as_ptr()).collect::<Vec<_>>().as_ptr(),
935                parameter_sets.iter().map(|data| data.len()).collect::<Vec<_>>().as_ptr(),
936                nal_unit_header_length,
937                extensions.as_concrete_TypeRef(),
938                &mut format_description,
939            )
940        };
941        if status == 0 {
942            Ok(unsafe { TCFType::wrap_under_create_rule(format_description) })
943        } else {
944            Err(status)
945        }
946    }
947
948    #[inline]
949    pub fn get_h264_parameter_set_at_index(&self, parameter_set_index: usize) -> Result<(&[u8], usize, i32), OSStatus> {
950        let mut parameter_set_pointer = null();
951        let mut parameter_set_size = 0;
952        let mut parameter_set_count = 0;
953        let mut nal_unit_header_length = 0;
954        let status = unsafe {
955            CMVideoFormatDescriptionGetH264ParameterSetAtIndex(
956                self.as_concrete_TypeRef(),
957                parameter_set_index,
958                &mut parameter_set_pointer,
959                &mut parameter_set_size,
960                &mut parameter_set_count,
961                &mut nal_unit_header_length,
962            )
963        };
964        if status == 0 {
965            Ok((unsafe { from_raw_parts(parameter_set_pointer, parameter_set_size) }, parameter_set_count, nal_unit_header_length))
966        } else {
967            Err(status)
968        }
969    }
970
971    #[inline]
972    pub fn get_hevc_parameter_set_at_index(&self, parameter_set_index: usize) -> Result<(&[u8], usize, i32), OSStatus> {
973        let mut parameter_set_pointer = null();
974        let mut parameter_set_size = 0;
975        let mut parameter_set_count = 0;
976        let mut nal_unit_header_length = 0;
977        let status = unsafe {
978            CMVideoFormatDescriptionGetHEVCParameterSetAtIndex(
979                self.as_concrete_TypeRef(),
980                parameter_set_index,
981                &mut parameter_set_pointer,
982                &mut parameter_set_size,
983                &mut parameter_set_count,
984                &mut nal_unit_header_length,
985            )
986        };
987        if status == 0 {
988            Ok((unsafe { from_raw_parts(parameter_set_pointer, parameter_set_size) }, parameter_set_count, nal_unit_header_length))
989        } else {
990            Err(status)
991        }
992    }
993
994    #[inline]
995    pub fn get_codec_type(&self) -> CMVideoCodecType {
996        unsafe { CMFormatDescriptionGetMediaSubType(self.as_concrete_TypeRef()) }
997    }
998
999    #[inline]
1000    pub fn get_dimensions(&self) -> CMVideoDimensions {
1001        unsafe { CMVideoFormatDescriptionGetDimensions(self.as_concrete_TypeRef()) }
1002    }
1003
1004    #[inline]
1005    pub fn get_presentation_dimensions(&self, use_pixel_aspect_ratio: bool, use_clean_aperture: bool) -> CGSize {
1006        unsafe { CMVideoFormatDescriptionGetPresentationDimensions(self.as_concrete_TypeRef(), use_pixel_aspect_ratio as _, use_clean_aperture as _) }
1007    }
1008
1009    #[inline]
1010    pub fn get_clean_aperture(&self, origin_is_at_top_left: bool) -> CGRect {
1011        unsafe { CMVideoFormatDescriptionGetCleanAperture(self.as_concrete_TypeRef(), origin_is_at_top_left as _) }
1012    }
1013
1014    #[inline]
1015    pub fn get_extension_keys_common_with_image_buffers() -> CFArray<CFString> {
1016        unsafe { TCFType::wrap_under_create_rule(CMVideoFormatDescriptionGetExtensionKeysCommonWithImageBuffers()) }
1017    }
1018
1019    #[inline]
1020    pub fn matches_image_buffer(&self, image_buffer: &CVImageBuffer) -> bool {
1021        unsafe { CMVideoFormatDescriptionMatchesImageBuffer(self.as_concrete_TypeRef(), image_buffer.as_concrete_TypeRef()) != 0 }
1022    }
1023}
1024
1025impl TCMFormatDescription for CMMuxedFormatDescription {}
1026
1027declare_TCFType! {
1028    CMMuxedFormatDescription, CMMuxedFormatDescriptionRef
1029}
1030impl_TCFType!(CMMuxedFormatDescription, CMMuxedFormatDescriptionRef, CMFormatDescriptionGetTypeID);
1031impl_CFTypeDescription!(CMMuxedFormatDescription);
1032
1033impl CMMuxedFormatDescription {
1034    #[inline]
1035    pub fn new(mux_type: CMMuxedStreamType, extensions: &CFDictionary<CFString, CFType>) -> Result<Self, OSStatus> {
1036        let mut format_description: CMMuxedFormatDescriptionRef = null_mut();
1037        let status =
1038            unsafe { CMMuxedFormatDescriptionCreate(kCFAllocatorDefault, mux_type, extensions.as_concrete_TypeRef(), &mut format_description) };
1039        if status == 0 {
1040            Ok(unsafe { TCFType::wrap_under_create_rule(format_description) })
1041        } else {
1042            Err(status)
1043        }
1044    }
1045
1046    #[inline]
1047    pub fn get_stream_type(&self) -> CMMuxedStreamType {
1048        unsafe { CMFormatDescriptionGetMediaSubType(self.as_concrete_TypeRef()) }
1049    }
1050}
1051
1052impl TCMFormatDescription for CMClosedCaptionFormatDescription {}
1053
1054declare_TCFType! {
1055    CMClosedCaptionFormatDescription, CMClosedCaptionFormatDescriptionRef
1056}
1057impl_TCFType!(CMClosedCaptionFormatDescription, CMClosedCaptionFormatDescriptionRef, CMFormatDescriptionGetTypeID);
1058impl_CFTypeDescription!(CMClosedCaptionFormatDescription);
1059
1060impl CMClosedCaptionFormatDescription {
1061    #[inline]
1062    pub fn new(format_type: CMClosedCaptionFormatType, extensions: Option<&CFDictionary<CFString, CFType>>) -> Result<Self, OSStatus> {
1063        let mut format_description: CMClosedCaptionFormatDescriptionRef = null_mut();
1064        let status = unsafe {
1065            CMFormatDescriptionCreate(
1066                kCFAllocatorDefault,
1067                kCMMediaType_ClosedCaption,
1068                format_type,
1069                extensions.map_or(null(), |exts| exts.as_concrete_TypeRef()),
1070                &mut format_description,
1071            )
1072        };
1073        if status == 0 {
1074            Ok(unsafe { TCFType::wrap_under_create_rule(format_description) })
1075        } else {
1076            Err(status)
1077        }
1078    }
1079
1080    #[inline]
1081    pub fn get_format_type(&self) -> CMClosedCaptionFormatType {
1082        unsafe { CMFormatDescriptionGetMediaSubType(self.as_concrete_TypeRef()) }
1083    }
1084}
1085
1086impl TCMFormatDescription for CMTextFormatDescription {}
1087
1088declare_TCFType! {
1089    CMTextFormatDescription, CMTextFormatDescriptionRef
1090}
1091impl_TCFType!(CMTextFormatDescription, CMTextFormatDescriptionRef, CMFormatDescriptionGetTypeID);
1092impl_CFTypeDescription!(CMTextFormatDescription);
1093
1094impl CMTextFormatDescription {
1095    #[inline]
1096    pub fn new(format_type: CMTextFormatType, extensions: Option<&CFDictionary<CFString, CFType>>) -> Result<Self, OSStatus> {
1097        let mut format_description: CMTextFormatDescriptionRef = null_mut();
1098        let status = unsafe {
1099            CMFormatDescriptionCreate(
1100                kCFAllocatorDefault,
1101                kCMMediaType_Text,
1102                format_type,
1103                extensions.map_or(null(), |exts| exts.as_concrete_TypeRef()),
1104                &mut format_description,
1105            )
1106        };
1107        if status == 0 {
1108            Ok(unsafe { TCFType::wrap_under_create_rule(format_description) })
1109        } else {
1110            Err(status)
1111        }
1112    }
1113
1114    #[inline]
1115    pub fn get_format_type(&self) -> CMTextFormatType {
1116        unsafe { CMFormatDescriptionGetMediaSubType(self.as_concrete_TypeRef()) }
1117    }
1118
1119    #[inline]
1120    pub fn get_display_flags(&self) -> Result<CMTextDisplayFlags, OSStatus> {
1121        let mut display_flags = 0;
1122        let status = unsafe { CMTextFormatDescriptionGetDisplayFlags(self.as_concrete_TypeRef(), &mut display_flags) };
1123        if status == 0 {
1124            Ok(display_flags)
1125        } else {
1126            Err(status)
1127        }
1128    }
1129
1130    #[inline]
1131    pub fn get_justification(&self) -> Result<(CMTextJustificationValue, CMTextJustificationValue), OSStatus> {
1132        let mut horizontal_justification = 0;
1133        let mut vertical_justification = 0;
1134        let status = unsafe {
1135            CMTextFormatDescriptionGetJustification(self.as_concrete_TypeRef(), &mut horizontal_justification, &mut vertical_justification)
1136        };
1137        if status == 0 {
1138            Ok((horizontal_justification, vertical_justification))
1139        } else {
1140            Err(status)
1141        }
1142    }
1143
1144    #[inline]
1145    pub fn get_default_text_box(&self, origin_is_at_top_left: bool, height_of_text_track: CGFloat) -> Result<CGRect, OSStatus> {
1146        let mut default_text_box = CGRect::default();
1147        let status = unsafe {
1148            CMTextFormatDescriptionGetDefaultTextBox(
1149                self.as_concrete_TypeRef(),
1150                origin_is_at_top_left as _,
1151                height_of_text_track,
1152                &mut default_text_box,
1153            )
1154        };
1155        if status == 0 {
1156            Ok(default_text_box)
1157        } else {
1158            Err(status)
1159        }
1160    }
1161
1162    #[inline]
1163    pub fn get_default_style(&self) -> Result<(u16, bool, bool, bool, CGFloat, [CGFloat; 4]), OSStatus> {
1164        let mut local_font_id = 0;
1165        let mut bold: Boolean = 0;
1166        let mut italic: Boolean = 0;
1167        let mut underline: Boolean = 0;
1168        let mut font_size = 0.0;
1169        let mut color_components = [0.0; 4];
1170        let status = unsafe {
1171            CMTextFormatDescriptionGetDefaultStyle(
1172                self.as_concrete_TypeRef(),
1173                &mut local_font_id,
1174                &mut bold,
1175                &mut italic,
1176                &mut underline,
1177                &mut font_size,
1178                &mut color_components,
1179            )
1180        };
1181        if status == 0 {
1182            Ok((local_font_id, bold != 0, italic != 0, underline != 0, font_size, color_components))
1183        } else {
1184            Err(status)
1185        }
1186    }
1187
1188    #[inline]
1189    pub fn get_font_name(&self, local_font_id: u16) -> Result<CFString, OSStatus> {
1190        let mut font_name = null();
1191        let status = unsafe { CMTextFormatDescriptionGetFontName(self.as_concrete_TypeRef(), local_font_id, &mut font_name) };
1192        if status == 0 {
1193            Ok(unsafe { TCFType::wrap_under_create_rule(font_name) })
1194        } else {
1195            Err(status)
1196        }
1197    }
1198}
1199
1200impl TCMFormatDescription for CMTimeCodeFormatDescription {}
1201
1202declare_TCFType! {
1203    CMTimeCodeFormatDescription, CMTimeCodeFormatDescriptionRef
1204}
1205impl_TCFType!(CMTimeCodeFormatDescription, CMTimeCodeFormatDescriptionRef, CMFormatDescriptionGetTypeID);
1206impl_CFTypeDescription!(CMTimeCodeFormatDescription);
1207
1208impl CMTimeCodeFormatDescription {
1209    #[inline]
1210    pub fn new(
1211        time_code_format_type: CMTimeCodeFormatType,
1212        frame_duration: CMTime,
1213        frame_quanta: u32,
1214        flags: u32,
1215        extensions: Option<&CFDictionary<CFString, CFType>>,
1216    ) -> Result<Self, OSStatus> {
1217        let mut format_description: CMTimeCodeFormatDescriptionRef = null_mut();
1218        let status = unsafe {
1219            CMTimeCodeFormatDescriptionCreate(
1220                kCFAllocatorDefault,
1221                time_code_format_type,
1222                frame_duration,
1223                frame_quanta,
1224                flags,
1225                extensions.map_or(null(), |exts| exts.as_concrete_TypeRef()),
1226                &mut format_description,
1227            )
1228        };
1229        if status == 0 {
1230            Ok(unsafe { TCFType::wrap_under_create_rule(format_description) })
1231        } else {
1232            Err(status)
1233        }
1234    }
1235
1236    #[inline]
1237    pub fn get_format_type(&self) -> CMTimeCodeFormatType {
1238        unsafe { CMFormatDescriptionGetMediaSubType(self.as_concrete_TypeRef()) }
1239    }
1240
1241    #[inline]
1242    pub fn get_frame_duration(&self) -> CMTime {
1243        unsafe { CMTimeCodeFormatDescriptionGetFrameDuration(self.as_concrete_TypeRef()) }
1244    }
1245
1246    #[inline]
1247    pub fn get_frame_quanta(&self) -> u32 {
1248        unsafe { CMTimeCodeFormatDescriptionGetFrameQuanta(self.as_concrete_TypeRef()) }
1249    }
1250
1251    #[inline]
1252    pub fn get_time_code_flags(&self) -> u32 {
1253        unsafe { CMTimeCodeFormatDescriptionGetTimeCodeFlags(self.as_concrete_TypeRef()) }
1254    }
1255}
1256
1257impl TCMFormatDescription for CMMetadataFormatDescription {}
1258
1259declare_TCFType! {
1260    CMMetadataFormatDescription, CMMetadataFormatDescriptionRef
1261}
1262impl_TCFType!(CMMetadataFormatDescription, CMMetadataFormatDescriptionRef, CMFormatDescriptionGetTypeID);
1263impl_CFTypeDescription!(CMMetadataFormatDescription);
1264
1265impl CMMetadataFormatDescription {
1266    #[inline]
1267    pub fn new_with_keys(metadata_type: CMMetadataFormatType, keys: Option<&CFArray<CFString>>) -> Result<Self, OSStatus> {
1268        let mut format_description: CMMetadataFormatDescriptionRef = null_mut();
1269        let status = unsafe {
1270            CMMetadataFormatDescriptionCreateWithKeys(
1271                kCFAllocatorDefault,
1272                metadata_type,
1273                keys.map_or(null(), |keys| keys.as_concrete_TypeRef()),
1274                &mut format_description,
1275            )
1276        };
1277        if status == 0 {
1278            Ok(unsafe { TCFType::wrap_under_create_rule(format_description) })
1279        } else {
1280            Err(status)
1281        }
1282    }
1283
1284    #[inline]
1285    pub fn new_with_metadata_specifications(
1286        metadata_type: CMMetadataFormatType,
1287        metadata_specifications: &CFArray<CFDictionary<CFString, CFType>>,
1288    ) -> Result<Self, OSStatus> {
1289        let mut format_description: CMMetadataFormatDescriptionRef = null_mut();
1290        let status = unsafe {
1291            CMMetadataFormatDescriptionCreateWithMetadataSpecifications(
1292                kCFAllocatorDefault,
1293                metadata_type,
1294                metadata_specifications.as_concrete_TypeRef(),
1295                &mut format_description,
1296            )
1297        };
1298        if status == 0 {
1299            Ok(unsafe { TCFType::wrap_under_create_rule(format_description) })
1300        } else {
1301            Err(status)
1302        }
1303    }
1304
1305    #[inline]
1306    pub fn new_with_metadata_format_description_and_metadata_specifications(
1307        source_description: &CMMetadataFormatDescription,
1308        metadata_specifications: &CFArray<CFDictionary<CFString, CFType>>,
1309    ) -> Result<Self, OSStatus> {
1310        let mut format_description: CMMetadataFormatDescriptionRef = null_mut();
1311        let status = unsafe {
1312            CMMetadataFormatDescriptionCreateWithMetadataFormatDescriptionAndMetadataSpecifications(
1313                kCFAllocatorDefault,
1314                source_description.as_concrete_TypeRef(),
1315                metadata_specifications.as_concrete_TypeRef(),
1316                &mut format_description,
1317            )
1318        };
1319        if status == 0 {
1320            Ok(unsafe { TCFType::wrap_under_create_rule(format_description) })
1321        } else {
1322            Err(status)
1323        }
1324    }
1325
1326    #[inline]
1327    pub fn new_by_merging_metadata_format_descriptions(
1328        source_description: &CMMetadataFormatDescription,
1329        other_source_description: &CMMetadataFormatDescription,
1330    ) -> Result<Self, OSStatus> {
1331        let mut format_description: CMMetadataFormatDescriptionRef = null_mut();
1332        let status = unsafe {
1333            CMMetadataFormatDescriptionCreateByMergingMetadataFormatDescriptions(
1334                kCFAllocatorDefault,
1335                source_description.as_concrete_TypeRef(),
1336                other_source_description.as_concrete_TypeRef(),
1337                &mut format_description,
1338            )
1339        };
1340        if status == 0 {
1341            Ok(unsafe { TCFType::wrap_under_create_rule(format_description) })
1342        } else {
1343            Err(status)
1344        }
1345    }
1346
1347    #[inline]
1348    pub fn get_key_with_local_id(&self, local_key_id: OSType) -> Option<CFDictionary<CFString, CFType>> {
1349        unsafe {
1350            let key = CMMetadataFormatDescriptionGetKeyWithLocalID(self.as_concrete_TypeRef(), local_key_id);
1351            if key.is_null() {
1352                None
1353            } else {
1354                Some(TCFType::wrap_under_get_rule(key))
1355            }
1356        }
1357    }
1358
1359    #[inline]
1360    pub fn get_identifiers(&self) -> Option<CFArray<CFString>> {
1361        unsafe {
1362            let identifiers = CMMetadataFormatDescriptionGetIdentifiers(self.as_concrete_TypeRef());
1363            if identifiers.is_null() {
1364                None
1365            } else {
1366                Some(TCFType::wrap_under_get_rule(identifiers))
1367            }
1368        }
1369    }
1370}