1use core::marker::PhantomData;
2use core::ptr;
3use x264::*;
4use {Colorspace, Encoding, Modifier};
5
6pub struct Image<'a> {
8 raw: x264_image_t,
9 width: i32,
10 height: i32,
11 spooky: PhantomData<&'a [u8]>,
12}
13
14impl<'a> Image<'a> {
15 pub fn new<E: Into<Encoding>>(
21 format: E,
22 width: i32,
23 height: i32,
24 planes: &[Plane<'a>],
25 ) -> Self {
26 use self::Colorspace::*;
29
30 let format = format.into();
31
32 let (pc, wm, hm, ws, hs): (_, _, _, &[_], &[_]) = match format.colorspace() {
33 I420 | YV12 => (3, 2, 2, &[2, 1, 1], &[2, 1, 1]),
34 NV12 | NV21 => (2, 2, 2, &[2, 2], &[2, 1]),
35 I422 | YV16 => (3, 2, 1, &[2, 1, 1], &[1, 1, 1]),
36 NV16 => (2, 2, 1, &[2, 2], &[1, 1]),
37 YUYV | UYVY => (1, 1, 1, &[2], &[1]),
38 V210 => (1, 1, 1, &[4], &[1]),
39 I444 | YV24 => (3, 1, 1, &[1, 1, 1], &[1, 1, 1]),
40 BGR | RGB => (1, 1, 1, &[3], &[1]),
41 BGRA => (1, 1, 1, &[4], &[1]),
42 };
43
44 let (wq, wr) = (width / wm, width % wm);
45 let (hq, hr) = (height / hm, height % hm);
46 let depth = if format.has(Modifier::HighDepth) {
47 2
48 } else {
49 1
50 };
51
52 assert!(planes.len() == pc);
54 assert!(wr == 0 && hr == 0);
56 for (i, plane) in planes.iter().enumerate() {
57 assert!(depth * wq * ws[i] <= plane.stride);
59 assert!(hq * hs[i] <= plane.data.len() as i32 / plane.stride);
61 }
62
63 unsafe { Self::new_unchecked(format, width, height, planes) }
64 }
65
66 pub fn bgr(width: i32, height: i32, data: &'a [u8]) -> Self {
68 let plane = Plane {
69 stride: data.len() as i32 / height,
70 data,
71 };
72 Self::new(Colorspace::BGR, width, height, &[plane])
73 }
74
75 pub fn rgb(width: i32, height: i32, data: &'a [u8]) -> Self {
77 let plane = Plane {
78 stride: data.len() as i32 / height,
79 data,
80 };
81 Self::new(Colorspace::RGB, width, height, &[plane])
82 }
83
84 pub fn bgra(width: i32, height: i32, data: &'a [u8]) -> Self {
86 let plane = Plane {
87 stride: data.len() as i32 / height,
88 data,
89 };
90 Self::new(Colorspace::BGRA, width, height, &[plane])
91 }
92
93 pub unsafe fn new_unchecked(
101 format: Encoding,
102 width: i32,
103 height: i32,
104 planes: &[Plane<'a>],
105 ) -> Self {
106 let mut strides = [0; 4];
107 let mut pointers = [ptr::null_mut(); 4];
108
109 for (i, &Plane { stride, data }) in planes.iter().enumerate() {
110 strides[i] = stride;
111 pointers[i] = data.as_ptr() as *mut u8;
112 }
113
114 let raw = x264_image_t {
115 i_csp: format.into_raw(),
116 i_plane: planes.len() as i32,
117 i_stride: strides,
118 plane: pointers,
119 };
120
121 Self {
122 raw,
123 width,
124 height,
125 spooky: PhantomData,
126 }
127 }
128
129 pub fn width(&self) -> i32 {
133 self.width
134 }
135 pub fn height(&self) -> i32 {
137 self.height
138 }
139 pub fn encoding(&self) -> Encoding {
141 unsafe { Encoding::from_raw(self.raw.i_csp) }
142 }
143
144 #[doc(hidden)]
145 pub fn raw(&self) -> x264_image_t {
146 self.raw
147 }
148}
149
150pub struct Plane<'a> {
152 pub stride: i32,
154 pub data: &'a [u8],
156}