1use std::ptr::{null, null_mut};
2
3use block::{Block, ConcreteBlock};
4use core_audio_types::base_types::{AudioBufferList, AudioStreamPacketDescription};
5use core_foundation::{
6 array::{CFArray, CFArrayRef},
7 base::{kCFAllocatorDefault, Boolean, CFAllocatorRef, CFRange, CFType, CFTypeID, OSStatus, TCFType},
8 dictionary::CFDictionary,
9 string::{CFString, CFStringRef},
10};
11use core_video::image_buffer::{CVImageBuffer, CVImageBufferRef};
12use libc::{c_void, size_t};
13#[cfg(feature = "objc")]
14use objc2::encode::{Encoding, RefEncode};
15
16use crate::{
17 base::CMItemCount,
18 block_buffer::{CMBlockBuffer, CMBlockBufferRef},
19 format_description::{CMFormatDescription, CMFormatDescriptionRef, CMVideoFormatDescription, CMVideoFormatDescriptionRef},
20 time::CMTime,
21};
22
23pub const kCMSampleBufferError_AllocationFailed: OSStatus = -12730;
24pub const kCMSampleBufferError_RequiredParameterMissing: OSStatus = -12731;
25pub const kCMSampleBufferError_AlreadyHasDataBuffer: OSStatus = -12732;
26pub const kCMSampleBufferError_BufferNotReady: OSStatus = -12733;
27pub const kCMSampleBufferError_SampleIndexOutOfRange: OSStatus = -12734;
28pub const kCMSampleBufferError_BufferHasNoSampleSizes: OSStatus = -12735;
29pub const kCMSampleBufferError_BufferHasNoSampleTimingInfo: OSStatus = -12736;
30pub const kCMSampleBufferError_ArrayTooSmall: OSStatus = -12737;
31pub const kCMSampleBufferError_InvalidEntryCount: OSStatus = -12738;
32pub const kCMSampleBufferError_CannotSubdivide: OSStatus = -12739;
33pub const kCMSampleBufferError_SampleTimingInfoInvalid: OSStatus = -12740;
34pub const kCMSampleBufferError_InvalidMediaTypeForOperation: OSStatus = -12741;
35pub const kCMSampleBufferError_InvalidSampleData: OSStatus = -12742;
36pub const kCMSampleBufferError_InvalidMediaFormat: OSStatus = -12743;
37pub const kCMSampleBufferError_Invalidated: OSStatus = -12744;
38pub const kCMSampleBufferError_DataFailed: OSStatus = -16750;
39pub const kCMSampleBufferError_DataCanceled: OSStatus = -16751;
40
41pub const kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment: u32 = 1 << 0;
42
43#[repr(C)]
44pub struct opaqueCMSampleBuffer(c_void);
45
46pub type CMSampleBufferRef = *mut opaqueCMSampleBuffer;
47
48#[repr(C, align(4))]
49#[derive(Clone, Copy, Debug, Default, PartialEq)]
50pub struct CMSampleTimingInfo {
51 pub duration: CMTime,
52 pub presentationTimeStamp: CMTime,
53 pub decodeTimeStamp: CMTime,
54}
55
56extern "C" {
57 pub static kCMTimingInfoInvalid: CMSampleTimingInfo;
58}
59
60pub type CMSampleBufferMakeDataReadyCallback = extern "C" fn(CMSampleBufferRef, *mut c_void) -> OSStatus;
61pub type CMSampleBufferMakeDataReadyHandler = *const Block<(CMSampleBufferRef,), OSStatus>;
62
63extern "C" {
64 pub fn CMSampleBufferCreate(
65 allocator: CFAllocatorRef,
66 dataBuffer: CMBlockBufferRef,
67 dataReady: Boolean,
68 makeDataReadyCallback: CMSampleBufferMakeDataReadyCallback,
69 makeDataReadyRefcon: *mut c_void,
70 formatDescription: CMFormatDescriptionRef,
71 numSamples: CMItemCount,
72 numSampleTimingEntries: CMItemCount,
73 sampleTimingArray: *const CMSampleTimingInfo,
74 numSampleSizeEntries: CMItemCount,
75 sampleSizeArray: *const size_t,
76 sampleBufferOut: *mut CMSampleBufferRef,
77 ) -> OSStatus;
78 pub fn CMSampleBufferCreateWithMakeDataReadyHandler(
79 allocator: CFAllocatorRef,
80 dataBuffer: CMBlockBufferRef,
81 dataReady: Boolean,
82 formatDescription: CMFormatDescriptionRef,
83 numSamples: CMItemCount,
84 numSampleTimingEntries: CMItemCount,
85 sampleTimingArray: *const CMSampleTimingInfo,
86 numSampleSizeEntries: CMItemCount,
87 sampleSizeArray: *const size_t,
88 sampleBufferOut: *mut CMSampleBufferRef,
89 makeDataReadyHandler: CMSampleBufferMakeDataReadyHandler,
90 ) -> OSStatus;
91 pub fn CMSampleBufferCreateReady(
92 allocator: CFAllocatorRef,
93 dataBuffer: CMBlockBufferRef,
94 formatDescription: CMFormatDescriptionRef,
95 numSamples: CMItemCount,
96 numSampleTimingEntries: CMItemCount,
97 sampleTimingArray: *const CMSampleTimingInfo,
98 numSampleSizeEntries: CMItemCount,
99 sampleSizeArray: *const size_t,
100 sampleBufferOut: *mut CMSampleBufferRef,
101 ) -> OSStatus;
102 pub fn CMAudioSampleBufferCreateWithPacketDescriptions(
103 allocator: CFAllocatorRef,
104 dataBuffer: CMBlockBufferRef,
105 dataReady: Boolean,
106 makeDataReadyCallback: CMSampleBufferMakeDataReadyCallback,
107 makeDataReadyRefcon: *mut c_void,
108 formatDescription: CMFormatDescriptionRef,
109 numSamples: CMItemCount,
110 presentationTimeStamp: CMTime,
111 packetDescriptions: *const AudioStreamPacketDescription,
112 sampleBufferOut: *mut CMSampleBufferRef,
113 ) -> OSStatus;
114 pub fn CMAudioSampleBufferCreateWithPacketDescriptionsAndMakeDataReadyHandler(
115 allocator: CFAllocatorRef,
116 dataBuffer: CMBlockBufferRef,
117 dataReady: Boolean,
118 formatDescription: CMFormatDescriptionRef,
119 numSamples: CMItemCount,
120 presentationTimeStamp: CMTime,
121 packetDescriptions: *const AudioStreamPacketDescription,
122 sampleBufferOut: *mut CMSampleBufferRef,
123 makeDataReadyHandler: CMSampleBufferMakeDataReadyHandler,
124 ) -> OSStatus;
125 pub fn CMAudioSampleBufferCreateReadyWithPacketDescriptions(
126 allocator: CFAllocatorRef,
127 dataBuffer: CMBlockBufferRef,
128 formatDescription: CMFormatDescriptionRef,
129 numSamples: CMItemCount,
130 presentationTimeStamp: CMTime,
131 packetDescriptions: *const AudioStreamPacketDescription,
132 sampleBufferOut: *mut CMSampleBufferRef,
133 ) -> OSStatus;
134 pub fn CMSampleBufferCreateForImageBuffer(
135 allocator: CFAllocatorRef,
136 imageBuffer: CVImageBufferRef,
137 dataReady: Boolean,
138 makeDataReadyCallback: CMSampleBufferMakeDataReadyCallback,
139 makeDataReadyRefcon: *mut c_void,
140 formatDescription: CMVideoFormatDescriptionRef,
141 sampleTiming: *const CMSampleTimingInfo,
142 sampleBufferOut: *mut CMSampleBufferRef,
143 ) -> OSStatus;
144 pub fn CMSampleBufferCreateForImageBufferWithMakeDataReadyHandler(
145 allocator: CFAllocatorRef,
146 imageBuffer: CVImageBufferRef,
147 dataReady: Boolean,
148 formatDescription: CMVideoFormatDescriptionRef,
149 sampleTiming: *const CMSampleTimingInfo,
150 sampleBufferOut: *mut CMSampleBufferRef,
151 makeDataReadyHandler: CMSampleBufferMakeDataReadyHandler,
152 ) -> OSStatus;
153 pub fn CMSampleBufferCreateReadyWithImageBuffer(
154 allocator: CFAllocatorRef,
155 imageBuffer: CVImageBufferRef,
156 formatDescription: CMVideoFormatDescriptionRef,
157 sampleTiming: *const CMSampleTimingInfo,
158 sampleBufferOut: *mut CMSampleBufferRef,
159 ) -> OSStatus;
160 pub fn CMSampleBufferCreateCopy(allocator: CFAllocatorRef, sbuf: CMSampleBufferRef, sampleBufferOut: *mut CMSampleBufferRef) -> OSStatus;
161 pub fn CMSampleBufferCreateCopyWithNewTiming(
162 allocator: CFAllocatorRef,
163 originalSBuf: CMSampleBufferRef,
164 numSampleTimingEntries: CMItemCount,
165 sampleTimingArray: *const CMSampleTimingInfo,
166 sampleBufferOut: *mut CMSampleBufferRef,
167 ) -> OSStatus;
168 pub fn CMSampleBufferCopySampleBufferForRange(
169 allocator: CFAllocatorRef,
170 sbuf: CMSampleBufferRef,
171 sampleRange: CFRange,
172 sampleBufferOut: *mut CMSampleBufferRef,
173 ) -> OSStatus;
174 pub fn CMSampleBufferGetTypeID() -> CFTypeID;
175 pub fn CMSampleBufferSetDataBuffer(sbuf: CMSampleBufferRef, dataBuffer: CMBlockBufferRef) -> OSStatus;
176 pub fn CMSampleBufferGetDataBuffer(sbuf: CMSampleBufferRef) -> CMBlockBufferRef;
177 pub fn CMSampleBufferGetImageBuffer(sbuf: CMSampleBufferRef) -> CVImageBufferRef;
178 pub fn CMSampleBufferSetDataBufferFromAudioBufferList(
179 sbuf: CMSampleBufferRef,
180 blockBufferStructureAllocator: CFAllocatorRef,
181 blockBufferBlockAllocator: CFAllocatorRef,
182 flags: u32,
183 bufferList: *const AudioBufferList,
184 ) -> OSStatus;
185 pub fn CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(
186 sbuf: CMSampleBufferRef,
187 bufferListSizeNeededOut: *mut size_t,
188 bufferListOut: *mut AudioBufferList,
189 bufferListSize: size_t,
190 blockBufferStructureAllocator: CFAllocatorRef,
191 blockBufferBlockAllocator: CFAllocatorRef,
192 flags: u32,
193 blockBufferOut: *mut CMBlockBufferRef,
194 ) -> OSStatus;
195 pub fn CMSampleBufferGetAudioStreamPacketDescriptions(
196 sbuf: CMSampleBufferRef,
197 packetDescriptionsSize: size_t,
198 packetDescriptionsOut: *mut AudioStreamPacketDescription,
199 packetDescriptionsSizeNeededOut: *mut size_t,
200 ) -> OSStatus;
201 pub fn CMSampleBufferGetAudioStreamPacketDescriptionsPtr(
202 sbuf: CMSampleBufferRef,
203 packetDescriptionsPointerOut: *mut *mut AudioStreamPacketDescription,
204 packetDescriptionsSizeOut: *mut size_t,
205 ) -> OSStatus;
206 pub fn CMSampleBufferCopyPCMDataIntoAudioBufferList(
207 sbuf: CMSampleBufferRef,
208 frameOffset: i32,
209 numFrames: i32,
210 bufferList: *mut AudioBufferList,
211 ) -> OSStatus;
212 pub fn CMSampleBufferSetDataReady(sbuf: CMSampleBufferRef) -> OSStatus;
213 pub fn CMSampleBufferDataIsReady(sbuf: CMSampleBufferRef) -> Boolean;
214 pub fn CMSampleBufferSetDataFailed(sbuf: CMSampleBufferRef, status: OSStatus) -> OSStatus;
215 pub fn CMSampleBufferHasDataFailed(sbuf: CMSampleBufferRef, statusOut: *mut OSStatus) -> Boolean;
216 pub fn CMSampleBufferMakeDataReady(sbuf: CMSampleBufferRef) -> OSStatus;
217 pub fn CMSampleBufferTrackDataReadiness(sbuf: CMSampleBufferRef, sampleBufferToTrack: CMSampleBufferRef) -> OSStatus;
218 pub fn CMSampleBufferInvalidate(sbuf: CMSampleBufferRef) -> OSStatus;
219}
220
221pub type CMSampleBufferInvalidateCallback = extern "C" fn(CMSampleBufferRef, u64);
222pub type CMSampleBufferInvalidateHandler = *const Block<(CMSampleBufferRef,), ()>;
223
224extern "C" {
225 pub fn CMSampleBufferSetInvalidateCallback(
226 sbuf: CMSampleBufferRef,
227 invalidateCallback: CMSampleBufferInvalidateCallback,
228 invalidateRefCon: u64,
229 ) -> OSStatus;
230 pub fn CMSampleBufferSetInvalidateHandler(sbuf: CMSampleBufferRef, invalidateHandler: CMSampleBufferInvalidateHandler) -> OSStatus;
231 pub fn CMSampleBufferIsValid(sbuf: CMSampleBufferRef) -> Boolean;
232
233 pub static kCMSampleBufferNotification_DataBecameReady: CFStringRef;
234 pub static kCMSampleBufferNotification_DataFailed: CFStringRef;
235 pub static kCMSampleBufferNotificationParameter_OSStatus: CFStringRef;
236 pub static kCMSampleBufferConduitNotification_InhibitOutputUntil: CFStringRef;
237 pub static kCMSampleBufferConduitNotificationParameter_ResumeTag: CFStringRef;
238 pub static kCMSampleBufferConduitNotification_ResetOutput: CFStringRef;
239 pub static kCMSampleBufferConduitNotification_UpcomingOutputPTSRangeChanged: CFStringRef;
240 pub static kCMSampleBufferConduitNotificationParameter_UpcomingOutputPTSRangeMayOverlapQueuedOutputPTSRange: CFStringRef;
241 pub static kCMSampleBufferConduitNotificationParameter_MinUpcomingOutputPTS: CFStringRef;
242 pub static kCMSampleBufferConduitNotificationParameter_MaxUpcomingOutputPTS: CFStringRef;
243 pub static kCMSampleBufferConsumerNotification_BufferConsumed: CFStringRef;
244
245 pub fn CMSampleBufferGetNumSamples(sbuf: CMSampleBufferRef) -> CMItemCount;
246 pub fn CMSampleBufferGetDuration(sbuf: CMSampleBufferRef) -> CMTime;
247 pub fn CMSampleBufferGetPresentationTimeStamp(sbuf: CMSampleBufferRef) -> CMTime;
248 pub fn CMSampleBufferGetDecodeTimeStamp(sbuf: CMSampleBufferRef) -> CMTime;
249 pub fn CMSampleBufferGetOutputDuration(sbuf: CMSampleBufferRef) -> CMTime;
250 pub fn CMSampleBufferGetOutputPresentationTimeStamp(sbuf: CMSampleBufferRef) -> CMTime;
251 pub fn CMSampleBufferSetOutputPresentationTimeStamp(sbuf: CMSampleBufferRef, outputPresentationTimeStamp: CMTime) -> OSStatus;
252 pub fn CMSampleBufferGetOutputDecodeTimeStamp(sbuf: CMSampleBufferRef) -> CMTime;
253 pub fn CMSampleBufferGetSampleTimingInfoArray(
254 sbuf: CMSampleBufferRef,
255 numSampleTimingEntries: CMItemCount,
256 timingArrayOut: *mut CMSampleTimingInfo,
257 timingArrayEntriesNeededOut: *mut CMItemCount,
258 ) -> OSStatus;
259 pub fn CMSampleBufferGetSampleTimingInfo(sbuf: CMSampleBufferRef, sampleIndex: CMItemCount, timingInfoOut: *mut CMSampleTimingInfo) -> OSStatus;
260 pub fn CMSampleBufferGetSampleSizeArray(
261 sbuf: CMSampleBufferRef,
262 sizeArrayEntries: CMItemCount,
263 sizeArrayOut: *mut size_t,
264 sizeArrayEntriesNeededOut: *mut CMItemCount,
265 ) -> OSStatus;
266 pub fn CMSampleBufferGetSampleSize(sbuf: CMSampleBufferRef, sampleIndex: CMItemCount) -> size_t;
267 pub fn CMSampleBufferGetTotalSampleSize(sbuf: CMSampleBufferRef) -> size_t;
268 pub fn CMSampleBufferGetFormatDescription(sbuf: CMSampleBufferRef) -> CMFormatDescriptionRef;
269 pub fn CMSampleBufferGetSampleAttachmentsArray(sbuf: CMSampleBufferRef, createIfNecessary: Boolean) -> CFArrayRef;
270
271 pub static kCMSampleAttachmentKey_NotSync: CFStringRef;
272 pub static kCMSampleAttachmentKey_PartialSync: CFStringRef;
273 pub static kCMSampleAttachmentKey_HasRedundantCoding: CFStringRef;
274 pub static kCMSampleAttachmentKey_IsDependedOnByOthers: CFStringRef;
275 pub static kCMSampleAttachmentKey_DependsOnOthers: CFStringRef;
276 pub static kCMSampleAttachmentKey_EarlierDisplayTimesAllowed: CFStringRef;
277 pub static kCMSampleAttachmentKey_DisplayImmediately: CFStringRef;
278 pub static kCMSampleAttachmentKey_DoNotDisplay: CFStringRef;
279 pub static kCMSampleBufferAttachmentKey_ResetDecoderBeforeDecoding: CFStringRef;
280 pub static kCMSampleBufferAttachmentKey_DrainAfterDecoding: CFStringRef;
281 pub static kCMSampleBufferAttachmentKey_PostNotificationWhenConsumed: CFStringRef;
282 pub static kCMSampleBufferAttachmentKey_ResumeOutput: CFStringRef;
283 pub static kCMSampleAttachmentKey_HEVCTemporalLevelInfo: CFStringRef;
284 pub static kCMHEVCTemporalLevelInfoKey_TemporalLevel: CFStringRef;
285 pub static kCMHEVCTemporalLevelInfoKey_ProfileSpace: CFStringRef;
286 pub static kCMHEVCTemporalLevelInfoKey_TierFlag: CFStringRef;
287 pub static kCMHEVCTemporalLevelInfoKey_ProfileIndex: CFStringRef;
288 pub static kCMHEVCTemporalLevelInfoKey_ProfileCompatibilityFlags: CFStringRef;
289 pub static kCMHEVCTemporalLevelInfoKey_ConstraintIndicatorFlags: CFStringRef;
290 pub static kCMHEVCTemporalLevelInfoKey_LevelIndex: CFStringRef;
291 pub static kCMSampleAttachmentKey_HEVCTemporalSubLayerAccess: CFStringRef;
292 pub static kCMSampleAttachmentKey_HEVCStepwiseTemporalSubLayerAccess: CFStringRef;
293 pub static kCMSampleAttachmentKey_HEVCSyncSampleNALUnitType: CFStringRef;
294 pub static kCMSampleAttachmentKey_AudioIndependentSampleDecoderRefreshCount: CFStringRef;
295 pub static kCMSampleBufferAttachmentKey_TransitionID: CFStringRef;
296 pub static kCMSampleBufferAttachmentKey_TrimDurationAtStart: CFStringRef;
297 pub static kCMSampleBufferAttachmentKey_TrimDurationAtEnd: CFStringRef;
298 pub static kCMSampleBufferAttachmentKey_SpeedMultiplier: CFStringRef;
299 pub static kCMSampleBufferAttachmentKey_Reverse: CFStringRef;
300 pub static kCMSampleBufferAttachmentKey_FillDiscontinuitiesWithSilence: CFStringRef;
301 pub static kCMSampleBufferAttachmentKey_EmptyMedia: CFStringRef;
302 pub static kCMSampleBufferAttachmentKey_PermanentEmptyMedia: CFStringRef;
303 pub static kCMSampleBufferAttachmentKey_DisplayEmptyMediaImmediately: CFStringRef;
304 pub static kCMSampleBufferAttachmentKey_EndsPreviousSampleDuration: CFStringRef;
305 pub static kCMSampleBufferAttachmentKey_SampleReferenceURL: CFStringRef;
306 pub static kCMSampleBufferAttachmentKey_SampleReferenceByteOffset: CFStringRef;
307 pub static kCMSampleBufferAttachmentKey_GradualDecoderRefresh: CFStringRef;
308 pub static kCMSampleBufferAttachmentKey_DroppedFrameReason: CFStringRef;
309 pub static kCMSampleBufferDroppedFrameReason_FrameWasLate: CFStringRef;
310 pub static kCMSampleBufferDroppedFrameReason_OutOfBuffers: CFStringRef;
311 pub static kCMSampleBufferDroppedFrameReason_Discontinuity: CFStringRef;
312 pub static kCMSampleBufferAttachmentKey_DroppedFrameReasonInfo: CFStringRef;
313 pub static kCMSampleBufferDroppedFrameReasonInfo_CameraModeSwitch: CFStringRef;
314 pub static kCMSampleBufferAttachmentKey_StillImageLensStabilizationInfo: CFStringRef;
315 pub static kCMSampleBufferLensStabilizationInfo_Active: CFStringRef;
316 pub static kCMSampleBufferLensStabilizationInfo_OutOfRange: CFStringRef;
317 pub static kCMSampleBufferLensStabilizationInfo_Unavailable: CFStringRef;
318 pub static kCMSampleBufferLensStabilizationInfo_Off: CFStringRef;
319 pub static kCMSampleBufferAttachmentKey_CameraIntrinsicMatrix: CFStringRef;
320 pub static kCMSampleBufferAttachmentKey_ForceKeyFrame: CFStringRef;
321 pub static kCMSampleAttachmentKey_CryptorSubsampleAuxiliaryData: CFStringRef;
322 pub static kCMSampleAttachmentKey_HDR10PlusPerFrameData: CFStringRef;
323
324 pub fn CMSampleBufferCallForEachSample(
325 sbuf: CMSampleBufferRef,
326 callback: extern "C" fn(CMSampleBufferRef, CMItemCount, *mut c_void) -> OSStatus,
327 refcon: *mut c_void,
328 ) -> OSStatus;
329 pub fn CMSampleBufferCallBlockForEachSample(sbuf: CMSampleBufferRef, block: *const Block<(CMSampleBufferRef, CMItemCount), OSStatus>)
330 -> OSStatus;
331}
332
333#[cfg(feature = "objc")]
334unsafe impl RefEncode for opaqueCMSampleBuffer {
335 const ENCODING_REF: Encoding = Encoding::Pointer(&Encoding::Struct("opaqueCMSampleBuffer", &[]));
336}
337
338declare_TCFType! {
339 CMSampleBuffer, CMSampleBufferRef
340}
341impl_TCFType!(CMSampleBuffer, CMSampleBufferRef, CMSampleBufferGetTypeID);
342impl_CFTypeDescription!(CMSampleBuffer);
343
344impl CMSampleBuffer {
345 #[inline]
346 pub unsafe fn new(
347 data_buffer: Option<&CMBlockBuffer>,
348 data_ready: bool,
349 make_data_ready_callback: CMSampleBufferMakeDataReadyCallback,
350 make_data_ready_refcon: *mut c_void,
351 format_description: Option<&CMFormatDescription>,
352 num_samples: CMItemCount,
353 sample_timing_array: Option<&[CMSampleTimingInfo]>,
354 sample_size_array: Option<&[size_t]>,
355 ) -> Result<CMSampleBuffer, OSStatus> {
356 let mut sample_buffer: CMSampleBufferRef = null_mut();
357 let status = unsafe {
358 CMSampleBufferCreate(
359 kCFAllocatorDefault,
360 data_buffer.map_or(null_mut(), |b| b.as_concrete_TypeRef()),
361 data_ready as Boolean,
362 make_data_ready_callback,
363 make_data_ready_refcon,
364 format_description.map_or(null_mut(), |f| f.as_concrete_TypeRef()),
365 num_samples,
366 sample_timing_array.map_or(0, |a| a.len() as CMItemCount),
367 sample_timing_array.map_or(null(), |a| a.as_ptr()),
368 sample_size_array.map_or(0, |a| a.len() as CMItemCount),
369 sample_size_array.map_or(null(), |a| a.as_ptr()),
370 &mut sample_buffer,
371 )
372 };
373 if status == 0 {
374 Ok(unsafe { CMSampleBuffer::wrap_under_create_rule(sample_buffer) })
375 } else {
376 Err(status)
377 }
378 }
379
380 #[inline]
381 pub fn new_with_make_data_ready_closure<F>(
382 data_buffer: Option<&CMBlockBuffer>,
383 data_ready: bool,
384 format_description: Option<&CMFormatDescription>,
385 num_samples: CMItemCount,
386 sample_timing_array: Option<&[CMSampleTimingInfo]>,
387 sample_size_array: Option<&[size_t]>,
388 make_data_ready_closure: Option<F>,
389 ) -> Result<CMSampleBuffer, OSStatus>
390 where
391 F: Fn(CMSampleBuffer) -> OSStatus + 'static,
392 {
393 let mut sample_buffer: CMSampleBufferRef = null_mut();
394 let handler = make_data_ready_closure.map(|closure| {
395 ConcreteBlock::new(move |sbuf: CMSampleBufferRef| -> OSStatus {
396 let sbuf = unsafe { CMSampleBuffer::wrap_under_get_rule(sbuf) };
397 closure(sbuf)
398 })
399 .copy()
400 });
401 let status = unsafe {
402 CMSampleBufferCreateWithMakeDataReadyHandler(
403 kCFAllocatorDefault,
404 data_buffer.map_or(null_mut(), |b| b.as_concrete_TypeRef()),
405 data_ready as Boolean,
406 format_description.map_or(null_mut(), |f| f.as_concrete_TypeRef()),
407 num_samples,
408 sample_timing_array.map_or(0, |a| a.len() as CMItemCount),
409 sample_timing_array.map_or(null(), |a| a.as_ptr()),
410 sample_size_array.map_or(0, |a| a.len() as CMItemCount),
411 sample_size_array.map_or(null(), |a| a.as_ptr()),
412 &mut sample_buffer,
413 handler.as_ref().map_or(null(), |h| &**h),
414 )
415 };
416 if status == 0 {
417 Ok(unsafe { CMSampleBuffer::wrap_under_create_rule(sample_buffer) })
418 } else {
419 Err(status)
420 }
421 }
422
423 #[inline]
424 pub fn new_ready(
425 data_buffer: &CMBlockBuffer,
426 format_description: Option<&CMFormatDescription>,
427 num_samples: CMItemCount,
428 sample_timing_array: Option<&[CMSampleTimingInfo]>,
429 sample_size_array: Option<&[size_t]>,
430 ) -> Result<CMSampleBuffer, OSStatus> {
431 let mut sample_buffer: CMSampleBufferRef = null_mut();
432 let status = unsafe {
433 CMSampleBufferCreateReady(
434 kCFAllocatorDefault,
435 data_buffer.as_concrete_TypeRef(),
436 format_description.map_or(null_mut(), |f| f.as_concrete_TypeRef()),
437 num_samples,
438 sample_timing_array.map_or(0, |a| a.len() as CMItemCount),
439 sample_timing_array.map_or(null(), |a| a.as_ptr()),
440 sample_size_array.map_or(0, |a| a.len() as CMItemCount),
441 sample_size_array.map_or(null(), |a| a.as_ptr()),
442 &mut sample_buffer,
443 )
444 };
445 if status == 0 {
446 Ok(unsafe { CMSampleBuffer::wrap_under_create_rule(sample_buffer) })
447 } else {
448 Err(status)
449 }
450 }
451
452 pub unsafe fn new_audio_sample_buffer_with_packet_descriptions(
453 data_buffer: Option<&CMBlockBuffer>,
454 data_ready: bool,
455 make_data_ready_callback: CMSampleBufferMakeDataReadyCallback,
456 make_data_ready_refcon: *mut c_void,
457 format_description: &CMFormatDescription,
458 num_samples: CMItemCount,
459 presentation_time_stamp: CMTime,
460 packet_descriptions: Option<&[AudioStreamPacketDescription]>,
461 ) -> Result<CMSampleBuffer, OSStatus> {
462 let mut sample_buffer: CMSampleBufferRef = null_mut();
463 let status = unsafe {
464 CMAudioSampleBufferCreateWithPacketDescriptions(
465 kCFAllocatorDefault,
466 data_buffer.map_or(null_mut(), |b| b.as_concrete_TypeRef()),
467 data_ready as Boolean,
468 make_data_ready_callback,
469 make_data_ready_refcon,
470 format_description.as_concrete_TypeRef(),
471 num_samples,
472 presentation_time_stamp,
473 packet_descriptions.map_or(null(), |a| a.as_ptr()),
474 &mut sample_buffer,
475 )
476 };
477 if status == 0 {
478 Ok(unsafe { CMSampleBuffer::wrap_under_create_rule(sample_buffer) })
479 } else {
480 Err(status)
481 }
482 }
483
484 pub fn new_audio_sample_buffer_with_packet_descriptions_and_make_data_ready_closure<F>(
485 data_buffer: Option<&CMBlockBuffer>,
486 data_ready: bool,
487 format_description: &CMFormatDescription,
488 num_samples: CMItemCount,
489 presentation_time_stamp: CMTime,
490 packet_descriptions: Option<&[AudioStreamPacketDescription]>,
491 make_data_ready_closure: Option<F>,
492 ) -> Result<CMSampleBuffer, OSStatus>
493 where
494 F: Fn(CMSampleBuffer) -> OSStatus + 'static,
495 {
496 let mut sample_buffer: CMSampleBufferRef = null_mut();
497 let handler = make_data_ready_closure.map(|closure| {
498 ConcreteBlock::new(move |sbuf: CMSampleBufferRef| -> OSStatus {
499 let sbuf = unsafe { CMSampleBuffer::wrap_under_get_rule(sbuf) };
500 closure(sbuf)
501 })
502 .copy()
503 });
504 let status = unsafe {
505 CMAudioSampleBufferCreateWithPacketDescriptionsAndMakeDataReadyHandler(
506 kCFAllocatorDefault,
507 data_buffer.map_or(null_mut(), |b| b.as_concrete_TypeRef()),
508 data_ready as Boolean,
509 format_description.as_concrete_TypeRef(),
510 num_samples,
511 presentation_time_stamp,
512 packet_descriptions.map_or(null(), |a| a.as_ptr()),
513 &mut sample_buffer,
514 handler.as_ref().map_or(null(), |h| &**h),
515 )
516 };
517 if status == 0 {
518 Ok(unsafe { CMSampleBuffer::wrap_under_create_rule(sample_buffer) })
519 } else {
520 Err(status)
521 }
522 }
523
524 #[inline]
525 pub fn new_audio_sample_buffer_ready_with_packet_descriptions(
526 data_buffer: &CMBlockBuffer,
527 format_description: &CMFormatDescription,
528 num_samples: CMItemCount,
529 presentation_time_stamp: CMTime,
530 packet_descriptions: Option<&[AudioStreamPacketDescription]>,
531 ) -> Result<CMSampleBuffer, OSStatus> {
532 let mut sample_buffer: CMSampleBufferRef = null_mut();
533 let status = unsafe {
534 CMAudioSampleBufferCreateReadyWithPacketDescriptions(
535 kCFAllocatorDefault,
536 data_buffer.as_concrete_TypeRef(),
537 format_description.as_concrete_TypeRef(),
538 num_samples,
539 presentation_time_stamp,
540 packet_descriptions.map_or(null(), |a| a.as_ptr()),
541 &mut sample_buffer,
542 )
543 };
544 if status == 0 {
545 Ok(unsafe { CMSampleBuffer::wrap_under_create_rule(sample_buffer) })
546 } else {
547 Err(status)
548 }
549 }
550
551 pub unsafe fn from_image_buffer(
552 image_buffer: &CVImageBuffer,
553 data_ready: bool,
554 make_data_ready_callback: CMSampleBufferMakeDataReadyCallback,
555 make_data_ready_refcon: *mut c_void,
556 format_description: &CMVideoFormatDescription,
557 sample_timing: &CMSampleTimingInfo,
558 ) -> Result<CMSampleBuffer, OSStatus> {
559 let mut sample_buffer: CMSampleBufferRef = null_mut();
560 let status = CMSampleBufferCreateForImageBuffer(
561 kCFAllocatorDefault,
562 image_buffer.as_concrete_TypeRef(),
563 data_ready as Boolean,
564 make_data_ready_callback,
565 make_data_ready_refcon,
566 format_description.as_concrete_TypeRef(),
567 sample_timing,
568 &mut sample_buffer,
569 );
570 if status == 0 {
571 Ok(CMSampleBuffer::wrap_under_create_rule(sample_buffer))
572 } else {
573 Err(status)
574 }
575 }
576
577 pub fn from_image_buffer_with_make_data_ready_closure<F>(
578 image_buffer: &CVImageBuffer,
579 data_ready: bool,
580 format_description: &CMVideoFormatDescription,
581 sample_timing: &CMSampleTimingInfo,
582 make_data_ready_closure: Option<F>,
583 ) -> Result<CMSampleBuffer, OSStatus>
584 where
585 F: Fn(CMSampleBuffer) -> OSStatus + 'static,
586 {
587 let mut sample_buffer: CMSampleBufferRef = null_mut();
588 let handler = make_data_ready_closure.map(|closure| {
589 ConcreteBlock::new(move |sbuf: CMSampleBufferRef| -> OSStatus {
590 let sbuf = unsafe { CMSampleBuffer::wrap_under_get_rule(sbuf) };
591 closure(sbuf)
592 })
593 .copy()
594 });
595 let status = unsafe {
596 CMSampleBufferCreateForImageBufferWithMakeDataReadyHandler(
597 kCFAllocatorDefault,
598 image_buffer.as_concrete_TypeRef(),
599 data_ready as Boolean,
600 format_description.as_concrete_TypeRef(),
601 sample_timing,
602 &mut sample_buffer,
603 handler.as_ref().map_or(null(), |h| &**h),
604 )
605 };
606 if status == 0 {
607 Ok(unsafe { CMSampleBuffer::wrap_under_create_rule(sample_buffer) })
608 } else {
609 Err(status)
610 }
611 }
612
613 #[inline]
614 pub fn from_image_buffer_ready(
615 image_buffer: &CVImageBuffer,
616 format_description: &CMVideoFormatDescription,
617 sample_timing: &CMSampleTimingInfo,
618 ) -> Result<CMSampleBuffer, OSStatus> {
619 let mut sample_buffer: CMSampleBufferRef = null_mut();
620 let status = unsafe {
621 CMSampleBufferCreateReadyWithImageBuffer(
622 kCFAllocatorDefault,
623 image_buffer.as_concrete_TypeRef(),
624 format_description.as_concrete_TypeRef(),
625 sample_timing,
626 &mut sample_buffer,
627 )
628 };
629 if status == 0 {
630 Ok(unsafe { CMSampleBuffer::wrap_under_create_rule(sample_buffer) })
631 } else {
632 Err(status)
633 }
634 }
635
636 #[inline]
637 pub fn copy(&self) -> Result<CMSampleBuffer, OSStatus> {
638 let mut sample_buffer: CMSampleBufferRef = null_mut();
639 let status = unsafe { CMSampleBufferCreateCopy(kCFAllocatorDefault, self.as_concrete_TypeRef(), &mut sample_buffer) };
640 if status == 0 {
641 Ok(unsafe { CMSampleBuffer::wrap_under_create_rule(sample_buffer) })
642 } else {
643 Err(status)
644 }
645 }
646
647 #[inline]
648 pub fn copy_with_new_timing(&self, sample_timing_array: Option<&[CMSampleTimingInfo]>) -> Result<CMSampleBuffer, OSStatus> {
649 let mut sample_buffer: CMSampleBufferRef = null_mut();
650 let status = unsafe {
651 CMSampleBufferCreateCopyWithNewTiming(
652 kCFAllocatorDefault,
653 self.as_concrete_TypeRef(),
654 sample_timing_array.map_or(0, |a| a.len() as CMItemCount),
655 sample_timing_array.map_or(null(), |a| a.as_ptr()),
656 &mut sample_buffer,
657 )
658 };
659 if status == 0 {
660 Ok(unsafe { CMSampleBuffer::wrap_under_create_rule(sample_buffer) })
661 } else {
662 Err(status)
663 }
664 }
665
666 #[inline]
667 pub fn copy_for_range(&self, sample_range: CFRange) -> Result<CMSampleBuffer, OSStatus> {
668 let mut sample_buffer: CMSampleBufferRef = null_mut();
669 let status =
670 unsafe { CMSampleBufferCopySampleBufferForRange(kCFAllocatorDefault, self.as_concrete_TypeRef(), sample_range, &mut sample_buffer) };
671 if status == 0 {
672 Ok(unsafe { CMSampleBuffer::wrap_under_create_rule(sample_buffer) })
673 } else {
674 Err(status)
675 }
676 }
677
678 #[inline]
679 pub fn set_data_buffer(&self, data_buffer: &CMBlockBuffer) -> Result<(), OSStatus> {
680 let status = unsafe { CMSampleBufferSetDataBuffer(self.as_concrete_TypeRef(), data_buffer.as_concrete_TypeRef()) };
681 if status == 0 {
682 Ok(())
683 } else {
684 Err(status)
685 }
686 }
687
688 #[inline]
689 pub fn get_data_buffer(&self) -> Option<CMBlockBuffer> {
690 unsafe {
691 let data_buffer = CMSampleBufferGetDataBuffer(self.as_concrete_TypeRef());
692 if data_buffer.is_null() {
693 None
694 } else {
695 Some(TCFType::wrap_under_get_rule(data_buffer))
696 }
697 }
698 }
699
700 #[inline]
701 pub fn get_image_buffer(&self) -> Option<CVImageBuffer> {
702 unsafe {
703 let image_buffer = CMSampleBufferGetImageBuffer(self.as_concrete_TypeRef());
704 if image_buffer.is_null() {
705 None
706 } else {
707 Some(CVImageBuffer::wrap_under_get_rule(image_buffer))
708 }
709 }
710 }
711
712 #[inline]
713 pub fn set_data_buffer_from_audio_buffer_list(&self, flags: u32, buffer_list: &AudioBufferList) -> Result<(), OSStatus> {
714 let status = unsafe {
715 CMSampleBufferSetDataBufferFromAudioBufferList(self.as_concrete_TypeRef(), kCFAllocatorDefault, kCFAllocatorDefault, flags, buffer_list)
716 };
717 if status == 0 {
718 Ok(())
719 } else {
720 Err(status)
721 }
722 }
723
724 #[inline]
725 pub fn set_data_ready(&self) -> Result<(), OSStatus> {
726 let status = unsafe { CMSampleBufferSetDataReady(self.as_concrete_TypeRef()) };
727 if status == 0 {
728 Ok(())
729 } else {
730 Err(status)
731 }
732 }
733
734 #[inline]
735 pub fn is_data_ready(&self) -> bool {
736 unsafe { CMSampleBufferDataIsReady(self.as_concrete_TypeRef()) != 0 }
737 }
738
739 #[inline]
740 pub fn set_data_failed(&self, status: OSStatus) -> Result<(), OSStatus> {
741 let status = unsafe { CMSampleBufferSetDataFailed(self.as_concrete_TypeRef(), status) };
742 if status == 0 {
743 Ok(())
744 } else {
745 Err(status)
746 }
747 }
748
749 #[inline]
750 pub fn has_data_failed(&self) -> (OSStatus, bool) {
751 let mut status = 0;
752 let has_failed = unsafe { CMSampleBufferHasDataFailed(self.as_concrete_TypeRef(), &mut status) != 0 };
753 (status, has_failed)
754 }
755
756 #[inline]
757 pub fn make_data_ready(&self) -> Result<(), OSStatus> {
758 let status = unsafe { CMSampleBufferMakeDataReady(self.as_concrete_TypeRef()) };
759 if status == 0 {
760 Ok(())
761 } else {
762 Err(status)
763 }
764 }
765
766 #[inline]
767 pub fn track_data_readiness(&self, sample_buffer_to_track: &CMSampleBuffer) -> Result<(), OSStatus> {
768 let status = unsafe { CMSampleBufferTrackDataReadiness(self.as_concrete_TypeRef(), sample_buffer_to_track.as_concrete_TypeRef()) };
769 if status == 0 {
770 Ok(())
771 } else {
772 Err(status)
773 }
774 }
775
776 #[inline]
777 pub fn invalidate(&self) -> Result<(), OSStatus> {
778 let status = unsafe { CMSampleBufferInvalidate(self.as_concrete_TypeRef()) };
779 if status == 0 {
780 Ok(())
781 } else {
782 Err(status)
783 }
784 }
785
786 pub unsafe fn set_invalidate_callback(
787 &self,
788 invalidate_callback: CMSampleBufferInvalidateCallback,
789 invalidate_ref_con: u64,
790 ) -> Result<(), OSStatus> {
791 let status = unsafe { CMSampleBufferSetInvalidateCallback(self.as_concrete_TypeRef(), invalidate_callback, invalidate_ref_con) };
792 if status == 0 {
793 Ok(())
794 } else {
795 Err(status)
796 }
797 }
798
799 pub fn set_invalidate_closure<F>(&self, invalidate_closure: Option<F>) -> Result<(), OSStatus>
800 where
801 F: Fn(CMSampleBuffer) + 'static,
802 {
803 let status = unsafe {
804 CMSampleBufferSetInvalidateHandler(
805 self.as_concrete_TypeRef(),
806 invalidate_closure
807 .map(|closure| {
808 ConcreteBlock::new(move |sbuf: CMSampleBufferRef| {
809 let sbuf = CMSampleBuffer::wrap_under_get_rule(sbuf);
810 closure(sbuf);
811 })
812 .copy()
813 })
814 .as_ref()
815 .map_or(null(), |h| &**h),
816 )
817 };
818 if status == 0 {
819 Ok(())
820 } else {
821 Err(status)
822 }
823 }
824
825 #[inline]
826 pub fn is_valid(&self) -> bool {
827 unsafe { CMSampleBufferIsValid(self.as_concrete_TypeRef()) != 0 }
828 }
829
830 #[inline]
831 pub fn get_num_samples(&self) -> CMItemCount {
832 unsafe { CMSampleBufferGetNumSamples(self.as_concrete_TypeRef()) }
833 }
834
835 #[inline]
836 pub fn get_duration(&self) -> CMTime {
837 unsafe { CMSampleBufferGetDuration(self.as_concrete_TypeRef()) }
838 }
839
840 #[inline]
841 pub fn get_presentation_time_stamp(&self) -> CMTime {
842 unsafe { CMSampleBufferGetPresentationTimeStamp(self.as_concrete_TypeRef()) }
843 }
844
845 #[inline]
846 pub fn get_decode_time_stamp(&self) -> CMTime {
847 unsafe { CMSampleBufferGetDecodeTimeStamp(self.as_concrete_TypeRef()) }
848 }
849
850 #[inline]
851 pub fn get_output_duration(&self) -> CMTime {
852 unsafe { CMSampleBufferGetOutputDuration(self.as_concrete_TypeRef()) }
853 }
854
855 #[inline]
856 pub fn get_output_presentation_time_stamp(&self) -> CMTime {
857 unsafe { CMSampleBufferGetOutputPresentationTimeStamp(self.as_concrete_TypeRef()) }
858 }
859
860 #[inline]
861 pub fn set_output_presentation_time_stamp(&self, output_presentation_time_stamp: CMTime) -> Result<(), OSStatus> {
862 let status = unsafe { CMSampleBufferSetOutputPresentationTimeStamp(self.as_concrete_TypeRef(), output_presentation_time_stamp) };
863 if status == 0 {
864 Ok(())
865 } else {
866 Err(status)
867 }
868 }
869
870 #[inline]
871 pub fn get_output_decode_time_stamp(&self) -> CMTime {
872 unsafe { CMSampleBufferGetOutputDecodeTimeStamp(self.as_concrete_TypeRef()) }
873 }
874
875 #[inline]
876 pub fn get_sample_timing_info_array(&self) -> Option<Vec<CMSampleTimingInfo>> {
877 unsafe {
878 let mut timing_array_entries_needed = 0;
879 let status = CMSampleBufferGetSampleTimingInfoArray(self.as_concrete_TypeRef(), 0, null_mut(), &mut timing_array_entries_needed);
880 if status != 0 {
881 return None;
882 }
883 let mut timing_array = vec![CMSampleTimingInfo::default(); timing_array_entries_needed as usize];
884 let status = CMSampleBufferGetSampleTimingInfoArray(
885 self.as_concrete_TypeRef(),
886 timing_array_entries_needed,
887 timing_array.as_mut_ptr(),
888 &mut timing_array_entries_needed,
889 );
890 if status != 0 {
891 return None;
892 }
893 Some(timing_array)
894 }
895 }
896
897 #[inline]
898 pub fn get_sample_timing_info(&self, sample_index: CMItemCount) -> Option<CMSampleTimingInfo> {
899 unsafe {
900 let mut timing_info = CMSampleTimingInfo::default();
901 let status = CMSampleBufferGetSampleTimingInfo(self.as_concrete_TypeRef(), sample_index, &mut timing_info);
902 if status == 0 {
903 Some(timing_info)
904 } else {
905 None
906 }
907 }
908 }
909
910 #[inline]
911 pub fn get_sample_size_array(&self) -> Option<Vec<size_t>> {
912 unsafe {
913 let mut size_array_entries_needed = 0;
914 let status = CMSampleBufferGetSampleSizeArray(self.as_concrete_TypeRef(), 0, null_mut(), &mut size_array_entries_needed);
915 if status != 0 {
916 return None;
917 }
918 let mut size_array = vec![0; size_array_entries_needed as usize];
919 let status = CMSampleBufferGetSampleSizeArray(
920 self.as_concrete_TypeRef(),
921 size_array_entries_needed,
922 size_array.as_mut_ptr(),
923 &mut size_array_entries_needed,
924 );
925 if status != 0 {
926 return None;
927 }
928 Some(size_array)
929 }
930 }
931
932 #[inline]
933 pub fn get_sample_size(&self, sample_index: CMItemCount) -> size_t {
934 unsafe { CMSampleBufferGetSampleSize(self.as_concrete_TypeRef(), sample_index) }
935 }
936
937 #[inline]
938 pub fn get_total_sample_size(&self) -> usize {
939 unsafe { CMSampleBufferGetTotalSampleSize(self.as_concrete_TypeRef()) }
940 }
941
942 #[inline]
943 pub fn get_format_description(&self) -> Option<CMFormatDescription> {
944 unsafe {
945 let format_description = CMSampleBufferGetFormatDescription(self.as_concrete_TypeRef());
946 if format_description.is_null() {
947 None
948 } else {
949 Some(TCFType::wrap_under_create_rule(format_description))
950 }
951 }
952 }
953
954 #[inline]
955 pub fn get_sample_attachments_array(&self, create_if_necessary: bool) -> Option<CFArray<CFDictionary<CFString, CFType>>> {
956 unsafe {
957 let attachments = CMSampleBufferGetSampleAttachmentsArray(self.as_concrete_TypeRef(), create_if_necessary as Boolean);
958 if attachments.is_null() {
959 None
960 } else {
961 Some(TCFType::wrap_under_get_rule(attachments))
962 }
963 }
964 }
965
966 pub unsafe fn call_for_each_sample(
967 &self,
968 callback: extern "C" fn(CMSampleBufferRef, CMItemCount, *mut c_void) -> OSStatus,
969 refcon: *mut c_void,
970 ) -> Result<(), OSStatus> {
971 let status = unsafe { CMSampleBufferCallForEachSample(self.as_concrete_TypeRef(), callback, refcon) };
972 if status == 0 {
973 Ok(())
974 } else {
975 Err(status)
976 }
977 }
978
979 pub fn call_closure_for_each_sample<F>(&self, closure: Option<F>) -> Result<(), OSStatus>
980 where
981 F: Fn(CMSampleBuffer, CMItemCount) -> OSStatus + 'static,
982 {
983 let status = unsafe {
984 CMSampleBufferCallBlockForEachSample(
985 self.as_concrete_TypeRef(),
986 closure
987 .map(|closure| {
988 ConcreteBlock::new(move |sbuf: CMSampleBufferRef, sample_index: CMItemCount| -> OSStatus {
989 let sbuf = CMSampleBuffer::wrap_under_get_rule(sbuf);
990 closure(sbuf, sample_index)
991 })
992 .copy()
993 })
994 .as_ref()
995 .map_or(null(), |h| &**h),
996 )
997 };
998 if status == 0 {
999 Ok(())
1000 } else {
1001 Err(status)
1002 }
1003 }
1004}