1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#![allow(non_snake_case, non_camel_case_types, non_upper_case_globals, improper_ctypes)]
#![cfg(any(target_os = "macos", target_os = "ios"))]

extern crate libc;
extern crate core_foundation_sys;


use libc::{c_void, size_t, c_long};
use core_foundation_sys::base::{Boolean, CFAllocatorRef, CFTypeID};
use core_foundation_sys::dictionary::CFDictionaryRef;
use core_foundation_sys::string::CFStringRef;


pub type OSStatus = i32;
pub type OSType = u32;

pub type CMItemCount = c_long;
pub type CMItemIndex = c_long;

pub type CMTimeValue = i64;
pub type CMTimeScale = i32;
pub type CMTimeFlags = u32;
pub type CMTimeEpoch = i64;

pub type CMVideoCodecType = u32;
pub type CMVideoFormatDescriptionRef = CMFormatDescriptionRef;

pub type CMBlockBufferFlags = u32;
pub type CMBlockBufferRef = *mut OpaqueCMBlockBuffer;
pub type CMFormatDescriptionRef = *mut OpaqueCMFormatDescription;
pub type CMSampleBufferRef = *mut OpaqueCMSampleBuffer;

pub type CMSampleBufferMakeDataReadyCallback =
    extern "C" fn(sbuf: CMSampleBufferRef, makeDataReadyRefcon: *mut c_void)
                  -> OSStatus;

pub const kCMTimeFlags_Valid: CMTimeFlags = 1 << 0;
#[allow(non_upper_case_globals)]
pub const kCMVideoCodecType_H264: CMVideoCodecType =
    ((b'a' as u32) << 24) | ((b'v' as u32) << 16) | ((b'c' as u32) << 8) | (b'1' as u32);

#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct CMTime {
    pub value: CMTimeValue,
    pub timescale: CMTimeScale,
    pub flags: CMTimeFlags,
    pub epoch: CMTimeEpoch,
}

#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct CMSampleTimingInfo {
    pub duration: CMTime,
    pub presentation_time_stamp: CMTime,
    pub decode_time_stamp: CMTime,
}

#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct OpaqueCMBlockBuffer;

#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct OpaqueCMFormatDescription;

#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct OpaqueCMSampleBuffer;


#[repr(C)]
#[allow(missing_copy_implementations)]
#[derive(Debug, Copy, Clone)]
pub struct CMBlockBufferCustomBlockSource {
    version: u32,
    AllocateBlock: extern "C" fn(refCon: *mut c_void, sizeInBytes: size_t) -> *mut c_void,
    FreeBlock: extern "C" fn(refCon: *mut c_void, doomedMemoryBlock: *mut c_void, sizeInBytes: size_t),
    refCon: *mut c_void,
}


#[link(name="CoreMedia", kind="framework")]
extern {
    pub static kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms: CFStringRef;

    pub fn CMFormatDescriptionGetTypeID() -> CFTypeID;
    pub fn CMVideoFormatDescriptionCreate(allocator: CFAllocatorRef,
                                          codecType: CMVideoCodecType,
                                          width: i32,
                                          height: i32,
                                          extensions: CFDictionaryRef,
                                          outDesc: *mut CMVideoFormatDescriptionRef)
                                          -> OSStatus;
    pub fn CMBlockBufferGetTypeID() -> CFTypeID;
    pub fn CMBlockBufferCreateWithMemoryBlock(structureAllocator: CFAllocatorRef,
                                              memoryBlock: *mut c_void,
                                              blockLength: size_t,
                                              blockAllocator: CFAllocatorRef,
                                              customBlockSource: *const
                                                CMBlockBufferCustomBlockSource,
                                              offsetToData: size_t,
                                              dataLength: size_t,
                                              flags: CMBlockBufferFlags,
                                              newBBufOut: *mut CMBlockBufferRef)
                                              -> OSStatus;
    pub fn CMBlockBufferReplaceDataBytes(sourceBytes: *const c_void,
                                         destinationBuffer: CMBlockBufferRef,
                                         offsetIntoDestination: size_t,
                                         dataLength: size_t)
                                         -> OSStatus;
    pub fn CMSampleBufferGetTypeID() -> CFTypeID;
    pub fn CMSampleBufferCreate(allocator: CFAllocatorRef,
                                dataBuffer: CMBlockBufferRef,
                                dataReady: Boolean,
                                makeDataReadyCallback: CMSampleBufferMakeDataReadyCallback,
                                makeDataReadyRefcon: *mut c_void,
                                formatDescription: CMFormatDescriptionRef,
                                numSamples: CMItemCount,
                                numSampleTimingEntries: CMItemCount,
                                sampleTimingArray: *const CMSampleTimingInfo,
                                numSampleSizeEntries: CMItemCount,
                                sampleSizeArray: *const size_t,
                                sBufOut: *mut CMSampleBufferRef)
                                -> OSStatus;
    pub fn CMSampleBufferGetSampleTimingInfo(sbuf: CMSampleBufferRef,
                                             sampleIndex: CMItemIndex,
                                             timingInfoOut: *mut CMSampleTimingInfo)
                                             -> OSStatus;
}


#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test(){
        unsafe {
            assert_eq!(CMFormatDescriptionGetTypeID(), 269);
        }
    }
}