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