strawberry_x264/
encoder.rs1use crate::{Data, Encoding, Error, Image, Picture, Result, Setup};
2use core::{mem::MaybeUninit, ptr};
3use core::ffi::c_void;
4use x264::*;
5
6pub struct Encoder {
8 raw: *mut x264_t,
9 params: x264_param_t,
10}
11
12impl Encoder {
13 pub fn builder() -> Setup {
17 Setup::default()
18 }
19
20 #[doc(hidden)]
21 pub unsafe fn from_raw(raw: *mut x264_t) -> Self {
22 let mut params = MaybeUninit::uninit();
23 x264_encoder_parameters(raw, params.as_mut_ptr());
24 let params = params.assume_init();
25 Self { raw, params }
26 }
27
28 pub fn encode(&mut self, pts: i64, image: Image) -> Result<(Data, Picture)> {
35 assert_eq!(image.width(), self.width());
36 assert_eq!(image.height(), self.height());
37 assert_eq!(image.encoding(), self.encoding());
38 unsafe { self.encode_unchecked(pts, image) }
39 }
40
41 pub unsafe fn encode_drh(&mut self, image: Image, idr: bool, context: *mut c_void) -> Result<Picture> {
47 let image = image.raw();
48
49 let mut picture = MaybeUninit::uninit();
50 x264_picture_init(picture.as_mut_ptr());
51 let mut picture = picture.assume_init();
52 picture.opaque = context;
53 picture.img = image;
54
55 if idr {
56 picture.i_type = X264_TYPE_IDR as i32;
57 } else {
58 picture.i_type = X264_TYPE_P as i32;
59 }
60
61 let mut len = 0;
62 let mut stuff = MaybeUninit::uninit();
63 let mut raw = MaybeUninit::uninit();
64
65 let err = x264_encoder_encode(
66 self.raw,
67 stuff.as_mut_ptr(),
68 &mut len,
69 &mut picture,
70 raw.as_mut_ptr(),
71 );
72
73 if err < 0 {
74 Err(Error)
75 } else {
76 let raw = raw.assume_init();
77 let picture = Picture::from_raw(raw);
78 Ok(picture)
79 }
80 }
81
82 pub unsafe fn encode_unchecked(&mut self, pts: i64, image: Image) -> Result<(Data, Picture)> {
89 let image = image.raw();
90
91 let mut picture = MaybeUninit::uninit();
92 x264_picture_init(picture.as_mut_ptr());
93 let mut picture = picture.assume_init();
94 picture.i_pts = pts;
95 picture.img = image;
96
97 let mut len = 0;
98 let mut stuff = MaybeUninit::uninit();
99 let mut raw = MaybeUninit::uninit();
100
101 let err = x264_encoder_encode(
102 self.raw,
103 stuff.as_mut_ptr(),
104 &mut len,
105 &mut picture,
106 raw.as_mut_ptr(),
107 );
108
109 if err < 0 {
110 Err(Error)
111 } else {
112 let stuff = stuff.assume_init();
113 let raw = raw.assume_init();
114 let data = Data::from_raw_parts(stuff, len as usize);
115 let picture = Picture::from_raw(raw);
116 Ok((data, picture))
117 }
118 }
119
120 pub fn headers(&mut self) -> Result<Data> {
122 let mut len = 0;
123 let mut stuff = MaybeUninit::uninit();
124
125 let err = unsafe { x264_encoder_headers(self.raw, stuff.as_mut_ptr(), &mut len) };
126
127 if err < 0 {
128 Err(Error)
129 } else {
130 let stuff = unsafe { stuff.assume_init() };
131 Ok(unsafe { Data::from_raw_parts(stuff, len as usize) })
132 }
133 }
134
135 pub fn flush(self) -> Flush {
150 Flush { encoder: self }
151 }
152
153 pub fn width(&self) -> i32 {
155 self.params.i_width
156 }
157 pub fn height(&self) -> i32 {
159 self.params.i_height
160 }
161 pub fn encoding(&self) -> Encoding {
163 unsafe { Encoding::from_raw(self.params.i_csp) }
164 }
165}
166
167impl Drop for Encoder {
168 fn drop(&mut self) {
169 unsafe {
170 x264_encoder_close(self.raw);
171 }
172 }
173}
174
175pub struct Flush {
177 encoder: Encoder,
178}
179
180impl Flush {
181 pub fn next(&mut self) -> Option<Result<(Data, Picture)>> {
183 let enc = self.encoder.raw;
184
185 if unsafe { x264_encoder_delayed_frames(enc) } == 0 {
186 return None;
187 }
188
189 let mut len = 0;
190 let mut stuff = MaybeUninit::uninit();
191 let mut raw = MaybeUninit::uninit();
192
193 let err = unsafe {
194 x264_encoder_encode(
195 enc,
196 stuff.as_mut_ptr(),
197 &mut len,
198 ptr::null_mut(),
199 raw.as_mut_ptr(),
200 )
201 };
202
203 Some(if err < 0 {
204 Err(Error)
205 } else {
206 Ok(unsafe {
207 let stuff = stuff.assume_init();
208 let raw = raw.assume_init();
209 (
210 Data::from_raw_parts(stuff, len as usize),
211 Picture::from_raw(raw),
212 )
213 })
214 })
215 }
216}