Skip to main content

x264_next/
encoder.rs

1use core::{mem::MaybeUninit, ptr};
2use x264::*;
3use {Data, Encoding, Error, Image, Picture, Result, Setup};
4
5/// Encodes video.
6pub struct Encoder {
7    raw: *mut x264_t,
8    params: x264_param_t,
9}
10
11impl Encoder {
12    /// Creates a new builder with default options.
13    ///
14    /// For more options see `Setup::new`.
15    pub fn builder() -> Setup {
16        Setup::default()
17    }
18
19    #[doc(hidden)]
20    pub unsafe fn from_raw(raw: *mut x264_t) -> Self {
21        let mut params = MaybeUninit::uninit();
22        x264_encoder_parameters(raw, params.as_mut_ptr());
23        Self {
24            raw,
25            params: params.assume_init(),
26        }
27    }
28
29    /// Feeds a frame to the encoder.
30    ///
31    /// # Panics
32    ///
33    /// Panics if there is a mismatch between the image and the encoder
34    /// regarding width, height or colorspace.
35    pub fn encode(&mut self, pts: i64, image: Image) -> Result<(Data, Picture)> {
36        assert_eq!(image.width(), self.width());
37        assert_eq!(image.height(), self.height());
38        assert_eq!(image.encoding(), self.encoding());
39        unsafe { self.encode_unchecked(pts, image) }
40    }
41
42    /// Feeds a frame to the encoder.
43    ///
44    /// # Unsafety
45    ///
46    /// The caller must ensure that the width, height *and* colorspace
47    /// of the image are the same as that of the encoder.
48    pub unsafe fn encode_unchecked(&mut self, pts: i64, image: Image) -> Result<(Data, Picture)> {
49        let image = image.raw();
50
51        let mut picture = MaybeUninit::uninit();
52        x264_picture_init(picture.as_mut_ptr());
53        let mut picture = picture.assume_init();
54        picture.i_pts = pts;
55        picture.img = image;
56
57        let mut len = 0;
58        let mut stuff = MaybeUninit::uninit();
59        let mut raw = MaybeUninit::uninit();
60
61        let err = x264_encoder_encode(self.raw, stuff.as_mut_ptr(), &mut len, &mut picture, raw.as_mut_ptr());
62
63        if err < 0 {
64            Err(Error)
65        } else {
66            let stuff = stuff.assume_init();
67            let raw = raw.assume_init();
68            let data = Data::from_raw_parts(stuff, len as usize);
69            let picture = Picture::from_raw(raw);
70            Ok((data, picture))
71        }
72    }
73
74    /// Gets the video headers, which should be sent first.
75    pub fn headers(&mut self) -> Result<Data> {
76        let mut len = 0;
77        let mut stuff = MaybeUninit::uninit();
78
79        let err = unsafe { x264_encoder_headers(self.raw, stuff.as_mut_ptr(), &mut len) };
80
81        if err < 0 {
82            Err(Error)
83        } else {
84            let stuff = unsafe { stuff.assume_init() };
85            Ok(unsafe { Data::from_raw_parts(stuff, len as usize) })
86        }
87    }
88
89    /// Begins flushing the encoder, to handle any delayed frames.
90    ///
91    /// ```rust
92    /// # use x264::{Colorspace, Setup};
93    /// # let encoder = Setup::default().build(Colorspace::RGB, 1920, 1080).unwrap();
94    /// #
95    /// let mut flush = encoder.flush();
96    ///
97    /// while let Some(result) = flush.next() {
98    ///     if let Ok((data, picture)) = result {
99    ///         // Handle data.
100    ///     }
101    /// }
102    /// ```
103    pub fn flush(self) -> Flush {
104        Flush { encoder: self }
105    }
106
107    /// The width required of any input images.
108    pub fn width(&self) -> i32 {
109        self.params.i_width
110    }
111    /// The height required of any input images.
112    pub fn height(&self) -> i32 {
113        self.params.i_height
114    }
115    /// The encoding required of any input images.
116    pub fn encoding(&self) -> Encoding {
117        unsafe { Encoding::from_raw(self.params.i_csp) }
118    }
119}
120
121impl Drop for Encoder {
122    fn drop(&mut self) {
123        unsafe {
124            x264_encoder_close(self.raw);
125        }
126    }
127}
128
129/// Iterate through any delayed frames.
130pub struct Flush {
131    encoder: Encoder,
132}
133
134// TODO: Change to iterator when GATs are stabilized
135
136//impl Iterator for Flush {
137impl Flush {
138    //type Item<'a> = Result<(Data<'a>, Picture)>;
139
140    /// Keeps flushing.
141    pub fn next(&mut self) -> Option<Result<(Data, Picture)>> {
142        let enc = self.encoder.raw;
143
144        if unsafe { x264_encoder_delayed_frames(enc) } == 0 {
145            return None;
146        }
147
148        let mut len = 0;
149        let mut stuff = MaybeUninit::uninit();
150        let mut raw = MaybeUninit::uninit();
151
152        let err =
153            unsafe { x264_encoder_encode(enc, stuff.as_mut_ptr(), &mut len, ptr::null_mut(), raw.as_mut_ptr()) };
154
155        Some(if err < 0 {
156            Err(Error)
157        } else {
158            Ok(unsafe {
159                (
160                    Data::from_raw_parts(stuff.assume_init(), len as usize),
161                    Picture::from_raw(raw.assume_init()),
162                )
163            })
164        })
165    }
166}