Skip to main content

core_media/
block_buffer.rs

1use std::{ptr::null_mut, slice::from_raw_parts_mut};
2
3use core_foundation::{
4    base::{kCFAllocatorDefault, Boolean, CFAllocatorRef, CFTypeID, OSStatus, TCFType},
5    declare_TCFType, impl_CFTypeDescription, impl_TCFType,
6};
7use libc::{c_void, size_t};
8
9pub const kCMBlockBufferNoErr: OSStatus = 0;
10pub const kCMBlockBufferStructureAllocationFailedErr: OSStatus = -12700;
11pub const kCMBlockBufferBlockAllocationFailedErr: OSStatus = -12701;
12pub const kCMBlockBufferBadCustomBlockSourceErr: OSStatus = -12702;
13pub const kCMBlockBufferBadOffsetParameterErr: OSStatus = -12703;
14pub const kCMBlockBufferBadLengthParameterErr: OSStatus = -12704;
15pub const kCMBlockBufferBadPointerParameterErr: OSStatus = -12705;
16pub const kCMBlockBufferEmptyBBufErr: OSStatus = -12706;
17pub const kCMBlockBufferUnallocatedBlock: OSStatus = -12707;
18pub const kCMBlockBufferInsufficientSpaceErr: OSStatus = -12708;
19
20pub type CMBlockBufferFlags = u32;
21
22pub const kCMBlockBufferAssureMemoryNowFlag: CMBlockBufferFlags = 1 << 0;
23pub const kCMBlockBufferAlwaysCopyDataFlag: CMBlockBufferFlags = 1 << 1;
24pub const kCMBlockBufferDontOptimizeDepthFlag: CMBlockBufferFlags = 1 << 2;
25pub const kCMBlockBufferPermitEmptyReferenceFlag: CMBlockBufferFlags = 1 << 3;
26
27#[repr(C)]
28pub struct OpaqueCMBlockBuffer(c_void);
29
30pub type CMBlockBufferRef = *mut OpaqueCMBlockBuffer;
31
32#[repr(C, align(4))]
33pub struct CMBlockBufferCustomBlockSource {
34    pub version: u32,
35    pub AllocateBlock: extern "C" fn(*mut c_void, size_t) -> *mut c_void,
36    pub FreeBlock: extern "C" fn(*mut c_void, *mut c_void, size_t),
37    pub refcon: *mut c_void,
38}
39
40pub const kCMBlockBufferCustomBlockSourceVersion: u32 = 0;
41
42extern "C" {
43    pub fn CMBlockBufferCreateEmpty(
44        structureAllocator: CFAllocatorRef,
45        subBlockCapacity: size_t,
46        flags: CMBlockBufferFlags,
47        blockBufferOut: *mut CMBlockBufferRef,
48    ) -> OSStatus;
49    pub fn CMBlockBufferCreateWithMemoryBlock(
50        structureAllocator: CFAllocatorRef,
51        memoryBlock: *const c_void,
52        blockLength: size_t,
53        blockAllocator: CFAllocatorRef,
54        customBlockSource: *const CMBlockBufferCustomBlockSource,
55        offsetToData: size_t,
56        dataLength: size_t,
57        flags: CMBlockBufferFlags,
58        blockBufferOut: *mut CMBlockBufferRef,
59    ) -> OSStatus;
60    pub fn CMBlockBufferCreateWithBufferReference(
61        structureAllocator: CFAllocatorRef,
62        bufferReference: CMBlockBufferRef,
63        offsetToData: size_t,
64        dataLength: size_t,
65        flags: CMBlockBufferFlags,
66        blockBufferOut: *mut CMBlockBufferRef,
67    ) -> OSStatus;
68    pub fn CMBlockBufferCreateContiguous(
69        structureAllocator: CFAllocatorRef,
70        sourceBuffer: CMBlockBufferRef,
71        blockAllocator: CFAllocatorRef,
72        customBlockSource: *const CMBlockBufferCustomBlockSource,
73        offsetToData: size_t,
74        dataLength: size_t,
75        flags: CMBlockBufferFlags,
76        blockBufferOut: *mut CMBlockBufferRef,
77    ) -> OSStatus;
78    pub fn CMBlockBufferGetTypeID() -> CFTypeID;
79    pub fn CMBlockBufferAppendMemoryBlock(
80        theBuffer: CMBlockBufferRef,
81        memoryBlock: *const c_void,
82        blockLength: size_t,
83        blockAllocator: CFAllocatorRef,
84        customBlockSource: *const CMBlockBufferCustomBlockSource,
85        offsetToData: size_t,
86        dataLength: size_t,
87        flags: CMBlockBufferFlags,
88    ) -> OSStatus;
89    pub fn CMBlockBufferAppendBufferReference(
90        theBuffer: CMBlockBufferRef,
91        targetBBuf: CMBlockBufferRef,
92        offsetToData: size_t,
93        dataLength: size_t,
94        flags: CMBlockBufferFlags,
95    ) -> OSStatus;
96    pub fn CMBlockBufferAssureBlockMemory(theBuffer: CMBlockBufferRef) -> OSStatus;
97    pub fn CMBlockBufferAccessDataBytes(
98        theBuffer: CMBlockBufferRef,
99        offset: size_t,
100        length: size_t,
101        temporaryBlock: *mut c_void,
102        returnedPointer: *mut *mut c_void,
103    ) -> OSStatus;
104    pub fn CMBlockBufferCopyDataBytes(
105        theSourceBuffer: CMBlockBufferRef,
106        offsetToData: size_t,
107        dataLength: size_t,
108        destination: *mut c_void,
109    ) -> OSStatus;
110    pub fn CMBlockBufferReplaceDataBytes(
111        sourceBytes: *const c_void,
112        destinationBuffer: CMBlockBufferRef,
113        offsetIntoDestination: size_t,
114        dataLength: size_t,
115    ) -> OSStatus;
116    pub fn CMBlockBufferFillDataBytes(
117        fillByte: u8,
118        destinationBuffer: CMBlockBufferRef,
119        offsetIntoDestination: size_t,
120        dataLength: size_t,
121    ) -> OSStatus;
122    pub fn CMBlockBufferGetDataPointer(
123        theBuffer: CMBlockBufferRef,
124        offset: size_t,
125        lengthAtOffset: *mut size_t,
126        totalLength: *mut size_t,
127        dataPointer: *mut *mut c_void,
128    ) -> OSStatus;
129    pub fn CMBlockBufferGetDataLength(theBuffer: CMBlockBufferRef) -> size_t;
130    pub fn CMBlockBufferIsRangeContiguous(theBuffer: CMBlockBufferRef, offset: size_t, length: size_t) -> Boolean;
131    pub fn CMBlockBufferIsEmpty(theBuffer: CMBlockBufferRef) -> Boolean;
132}
133
134declare_TCFType! {
135    CMBlockBuffer, CMBlockBufferRef
136}
137impl_TCFType!(CMBlockBuffer, CMBlockBufferRef, CMBlockBufferGetTypeID);
138impl_CFTypeDescription!(CMBlockBuffer);
139
140impl CMBlockBuffer {
141    #[inline]
142    pub fn new_empty(sub_block_capacity: size_t, flags: CMBlockBufferFlags) -> Result<CMBlockBuffer, OSStatus> {
143        unsafe {
144            let mut block_buffer: CMBlockBufferRef = null_mut();
145            let status = CMBlockBufferCreateEmpty(kCFAllocatorDefault, sub_block_capacity, flags, &mut block_buffer);
146            if status == kCMBlockBufferNoErr {
147                Ok(TCFType::wrap_under_create_rule(block_buffer))
148            } else {
149                Err(status)
150            }
151        }
152    }
153
154    #[inline]
155    pub unsafe fn new_with_memory_block(
156        memory_block: &[u8],
157        custom_block_source: *const CMBlockBufferCustomBlockSource,
158        offset_to_data: size_t,
159        data_length: size_t,
160        flags: CMBlockBufferFlags,
161    ) -> Result<CMBlockBuffer, OSStatus> {
162        unsafe {
163            let mut block_buffer: CMBlockBufferRef = null_mut();
164            let status = CMBlockBufferCreateWithMemoryBlock(
165                kCFAllocatorDefault,
166                memory_block.as_ptr() as *const c_void,
167                memory_block.len() as size_t,
168                kCFAllocatorDefault,
169                custom_block_source,
170                offset_to_data,
171                data_length,
172                flags,
173                &mut block_buffer,
174            );
175            if status == kCMBlockBufferNoErr {
176                Ok(TCFType::wrap_under_create_rule(block_buffer))
177            } else {
178                Err(status)
179            }
180        }
181    }
182
183    #[inline]
184    pub fn new_with_buffer_reference(
185        &self,
186        offset_to_data: size_t,
187        data_length: size_t,
188        flags: CMBlockBufferFlags,
189    ) -> Result<CMBlockBuffer, OSStatus> {
190        unsafe {
191            let mut block_buffer: CMBlockBufferRef = null_mut();
192            let status = CMBlockBufferCreateWithBufferReference(
193                kCFAllocatorDefault,
194                self.as_concrete_TypeRef(),
195                offset_to_data,
196                data_length,
197                flags,
198                &mut block_buffer,
199            );
200            if status == kCMBlockBufferNoErr {
201                Ok(TCFType::wrap_under_create_rule(block_buffer))
202            } else {
203                Err(status)
204            }
205        }
206    }
207
208    #[inline]
209    pub unsafe fn new_contiguous(
210        &self,
211        custom_block_source: *const CMBlockBufferCustomBlockSource,
212        offset_to_data: size_t,
213        data_length: size_t,
214        flags: CMBlockBufferFlags,
215    ) -> Result<CMBlockBuffer, OSStatus> {
216        unsafe {
217            let mut block_buffer: CMBlockBufferRef = null_mut();
218            let status = CMBlockBufferCreateContiguous(
219                kCFAllocatorDefault,
220                self.as_concrete_TypeRef(),
221                kCFAllocatorDefault,
222                custom_block_source,
223                offset_to_data,
224                data_length,
225                flags,
226                &mut block_buffer,
227            );
228            if status == kCMBlockBufferNoErr {
229                Ok(TCFType::wrap_under_create_rule(block_buffer))
230            } else {
231                Err(status)
232            }
233        }
234    }
235
236    #[inline]
237    pub unsafe fn append_memory_block(
238        &self,
239        memory_block: &[u8],
240        custom_block_source: *const CMBlockBufferCustomBlockSource,
241        offset_to_data: size_t,
242        data_length: size_t,
243        flags: CMBlockBufferFlags,
244    ) -> Result<(), OSStatus> {
245        unsafe {
246            let status = CMBlockBufferAppendMemoryBlock(
247                self.as_concrete_TypeRef(),
248                memory_block.as_ptr() as *const c_void,
249                memory_block.len() as size_t,
250                kCFAllocatorDefault,
251                custom_block_source,
252                offset_to_data,
253                data_length,
254                flags,
255            );
256            if status == kCMBlockBufferNoErr {
257                Ok(())
258            } else {
259                Err(status)
260            }
261        }
262    }
263
264    #[inline]
265    pub fn append_buffer_reference(
266        &self,
267        target_block_buf: &CMBlockBuffer,
268        offset_to_data: size_t,
269        data_length: size_t,
270        flags: CMBlockBufferFlags,
271    ) -> Result<(), OSStatus> {
272        unsafe {
273            let status = CMBlockBufferAppendBufferReference(self.as_concrete_TypeRef(), target_block_buf.0, offset_to_data, data_length, flags);
274            if status == kCMBlockBufferNoErr {
275                Ok(())
276            } else {
277                Err(status)
278            }
279        }
280    }
281
282    #[inline]
283    pub fn assure_block_memory(&self) -> OSStatus {
284        unsafe { CMBlockBufferAssureBlockMemory(self.as_concrete_TypeRef()) }
285    }
286
287    #[inline]
288    pub fn access_data_bytes(&self, offset: size_t, temporary_block: &mut [u8]) -> Result<&mut [u8], OSStatus> {
289        unsafe {
290            let mut returned_pointer: *mut c_void = null_mut();
291            let status = CMBlockBufferAccessDataBytes(
292                self.as_concrete_TypeRef(),
293                offset,
294                temporary_block.len() as size_t,
295                temporary_block.as_mut_ptr() as *mut c_void,
296                &mut returned_pointer,
297            );
298            if status == kCMBlockBufferNoErr {
299                Ok(from_raw_parts_mut(returned_pointer as *mut u8, temporary_block.len()))
300            } else {
301                Err(status)
302            }
303        }
304    }
305
306    #[inline]
307    pub fn copy_data_bytes(&self, offset_to_data: size_t, destination: &mut [u8]) -> Result<(), OSStatus> {
308        unsafe {
309            let status = CMBlockBufferCopyDataBytes(
310                self.as_concrete_TypeRef(),
311                offset_to_data,
312                destination.len() as size_t,
313                destination.as_mut_ptr() as *mut c_void,
314            );
315            if status == kCMBlockBufferNoErr {
316                Ok(())
317            } else {
318                Err(status)
319            }
320        }
321    }
322
323    #[inline]
324    pub fn replace_data_bytes(&self, source_bytes: &[u8], offset_into_destination: size_t) -> Result<(), OSStatus> {
325        unsafe {
326            let status = CMBlockBufferReplaceDataBytes(
327                source_bytes.as_ptr() as *const c_void,
328                self.as_concrete_TypeRef(),
329                offset_into_destination,
330                source_bytes.len() as size_t,
331            );
332            if status == kCMBlockBufferNoErr {
333                Ok(())
334            } else {
335                Err(status)
336            }
337        }
338    }
339
340    #[inline]
341    pub fn fill_data_bytes(&self, fill_byte: u8, offset_into_destination: size_t, data_length: size_t) -> Result<(), OSStatus> {
342        unsafe {
343            let status = CMBlockBufferFillDataBytes(fill_byte, self.as_concrete_TypeRef(), offset_into_destination, data_length);
344            if status == kCMBlockBufferNoErr {
345                Ok(())
346            } else {
347                Err(status)
348            }
349        }
350    }
351
352    #[inline]
353    pub fn get_data(&self, offset: size_t) -> Result<&mut [u8], OSStatus> {
354        unsafe {
355            let mut length_at_offset: size_t = 0;
356            let mut total_length: size_t = 0;
357            let mut data_pointer: *mut c_void = null_mut();
358            let status = CMBlockBufferGetDataPointer(self.as_concrete_TypeRef(), offset, &mut length_at_offset, &mut total_length, &mut data_pointer);
359            if status == kCMBlockBufferNoErr {
360                Ok(from_raw_parts_mut(data_pointer as *mut u8, length_at_offset))
361            } else {
362                Err(status)
363            }
364        }
365    }
366
367    #[inline]
368    pub fn get_data_length(&self) -> size_t {
369        unsafe { CMBlockBufferGetDataLength(self.as_concrete_TypeRef()) }
370    }
371
372    #[inline]
373    pub fn is_range_contiguous(&self, offset: size_t, length: size_t) -> bool {
374        unsafe { CMBlockBufferIsRangeContiguous(self.as_concrete_TypeRef(), offset, length) != 0 }
375    }
376
377    #[inline]
378    pub fn is_empty(&self) -> bool {
379        unsafe { CMBlockBufferIsEmpty(self.as_concrete_TypeRef()) != 0 }
380    }
381}