use core::marker::PhantomData;
use core::ptr;
use x264::*;
use {Colorspace, Encoding, Modifier};
pub struct Image<'a> {
raw: x264_image_t,
width: i32,
height: i32,
spooky: PhantomData<&'a [u8]>,
}
impl<'a> Image<'a> {
pub fn new<E: Into<Encoding>>(
format: E,
width: i32,
height: i32,
planes: &[Plane<'a>],
) -> Self {
use self::Colorspace::*;
let format = format.into();
let (pc, wm, hm, ws, hs): (_, _, _, &[_], &[_]) = match format.colorspace() {
I420 | YV12 => (3, 2, 2, &[2, 1, 1], &[2, 1, 1]),
NV12 | NV21 => (2, 2, 2, &[2, 2], &[2, 1]),
I422 | YV16 => (3, 2, 1, &[2, 1, 1], &[1, 1, 1]),
NV16 => (2, 2, 1, &[2, 2], &[1, 1]),
YUYV | UYVY => (1, 1, 1, &[2], &[1]),
V210 => (1, 1, 1, &[4], &[1]),
I444 | YV24 => (3, 1, 1, &[1, 1, 1], &[1, 1, 1]),
BGR | RGB => (1, 1, 1, &[3], &[1]),
BGRA => (1, 1, 1, &[4], &[1]),
};
let (wq, wr) = (width / wm, width % wm);
let (hq, hr) = (height / hm, height % hm);
let depth = if format.has(Modifier::HighDepth) {
2
} else {
1
};
assert!(planes.len() == pc);
assert!(wr == 0 && hr == 0);
for (i, plane) in planes.iter().enumerate() {
assert!(depth * wq * ws[i] <= plane.stride);
assert!(hq * hs[i] <= plane.data.len() as i32 / plane.stride);
}
unsafe { Self::new_unchecked(format, width, height, planes) }
}
pub fn bgr(width: i32, height: i32, data: &'a [u8]) -> Self {
let plane = Plane {
stride: data.len() as i32 / height,
data,
};
Self::new(Colorspace::BGR, width, height, &[plane])
}
pub fn rgb(width: i32, height: i32, data: &'a [u8]) -> Self {
let plane = Plane {
stride: data.len() as i32 / height,
data,
};
Self::new(Colorspace::RGB, width, height, &[plane])
}
pub fn bgra(width: i32, height: i32, data: &'a [u8]) -> Self {
let plane = Plane {
stride: data.len() as i32 / height,
data,
};
Self::new(Colorspace::BGRA, width, height, &[plane])
}
pub unsafe fn new_unchecked(
format: Encoding,
width: i32,
height: i32,
planes: &[Plane<'a>],
) -> Self {
let mut strides = [0; 4];
let mut pointers = [ptr::null_mut(); 4];
for (i, &Plane { stride, data }) in planes.iter().enumerate() {
strides[i] = stride;
pointers[i] = data.as_ptr() as *mut u8;
}
let raw = x264_image_t {
i_csp: format.into_raw(),
i_plane: planes.len() as i32,
i_stride: strides,
plane: pointers,
};
Self {
raw,
width,
height,
spooky: PhantomData,
}
}
pub fn width(&self) -> i32 {
self.width
}
pub fn height(&self) -> i32 {
self.height
}
pub fn encoding(&self) -> Encoding {
unsafe { Encoding::from_raw(self.raw.i_csp) }
}
#[doc(hidden)]
pub fn raw(&self) -> x264_image_t {
self.raw
}
}
pub struct Plane<'a> {
pub stride: i32,
pub data: &'a [u8],
}