x264_next/
image.rs

1use core::marker::PhantomData;
2use core::ptr;
3use x264::*;
4use {Colorspace, Encoding, Modifier};
5
6/// Input image data to be given to the encoder.
7pub 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    /// Makes a new image with the given information.
16    ///
17    /// # Panics
18    ///
19    /// Panics if the plane is invalid.
20    pub fn new<E: Into<Encoding>>(
21        format: E,
22        width: i32,
23        height: i32,
24        planes: &[Plane<'a>],
25    ) -> Self {
26        //TODO: Get someone who knows what they're doing to verify this.
27
28        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        // Check that the number of planes matches pc.
53        assert!(planes.len() == pc);
54        // Check that the width and the height are multiples of wm and hm.
55        assert!(wr == 0 && hr == 0);
56        for (i, plane) in planes.iter().enumerate() {
57            // Check that the plane's stride is at least depth * wq * ws[i].
58            assert!(depth * wq * ws[i] <= plane.stride);
59            // Check that there are at least hq * hs[i] rows in the plane.
60            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    /// Makes a new packed BGR image.
67    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    /// Makes a new packed RGB image.
76    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    /// Makes a new packed BGRA image.
85    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    /// Makes a new image with the given planes and colorspace.
94    ///
95    /// # Unsafety
96    ///
97    /// The caller must ensure that the plane fulfils all the invariants that
98    /// x264 expects it to fulfil. I don't actually know what all of those are,
99    /// but the source of `Encoder::new` is my best guess.
100    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    // Getters
130
131    /// The width of the image.
132    pub fn width(&self) -> i32 {
133        self.width
134    }
135    /// The height of the image.
136    pub fn height(&self) -> i32 {
137        self.height
138    }
139    /// The encoding of the image.
140    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
150/// A single plane of an image.
151pub struct Plane<'a> {
152    /// The plane's stride (the number of bytes for each row).
153    pub stride: i32,
154    /// The plane's pixel data.
155    pub data: &'a [u8],
156}