1 | use std::ops::{Deref, DerefMut}; |
2 | use std::ptr; |
3 | |
4 | use ffi::*; |
5 | use libc::{c_float, c_int}; |
6 | |
7 | use super::Encoder as Super; |
8 | use super::{Comparison, Decision}; |
9 | #[cfg (not(feature = "ffmpeg_5_0" ))] |
10 | use super::{MotionEstimation, Prediction}; |
11 | use codec::{traits, Context}; |
12 | use {color, format, Dictionary, Error, Rational}; |
13 | #[cfg (not(feature = "ffmpeg_5_0" ))] |
14 | use {frame, packet}; |
15 | |
16 | pub struct Video(pub Super); |
17 | |
18 | impl Video { |
19 | #[inline ] |
20 | pub fn open(mut self) -> Result<Encoder, Error> { |
21 | unsafe { |
22 | match avcodec_open2(self.as_mut_ptr(), ptr::null(), ptr::null_mut()) { |
23 | 0 => Ok(Encoder(self)), |
24 | e => Err(Error::from(e)), |
25 | } |
26 | } |
27 | } |
28 | |
29 | #[inline ] |
30 | pub fn open_as<E: traits::Encoder>(mut self, codec: E) -> Result<Encoder, Error> { |
31 | unsafe { |
32 | if let Some(codec) = codec.encoder() { |
33 | match avcodec_open2(self.as_mut_ptr(), codec.as_ptr(), ptr::null_mut()) { |
34 | 0 => Ok(Encoder(self)), |
35 | e => Err(Error::from(e)), |
36 | } |
37 | } else { |
38 | Err(Error::EncoderNotFound) |
39 | } |
40 | } |
41 | } |
42 | |
43 | #[inline ] |
44 | pub fn open_with(mut self, options: Dictionary) -> Result<Encoder, Error> { |
45 | unsafe { |
46 | let mut opts = options.disown(); |
47 | let res = avcodec_open2(self.as_mut_ptr(), ptr::null(), &mut opts); |
48 | |
49 | Dictionary::own(opts); |
50 | |
51 | match res { |
52 | 0 => Ok(Encoder(self)), |
53 | e => Err(Error::from(e)), |
54 | } |
55 | } |
56 | } |
57 | |
58 | #[inline ] |
59 | pub fn open_as_with<E: traits::Encoder>( |
60 | mut self, |
61 | codec: E, |
62 | options: Dictionary, |
63 | ) -> Result<Encoder, Error> { |
64 | unsafe { |
65 | if let Some(codec) = codec.encoder() { |
66 | let mut opts = options.disown(); |
67 | let res = avcodec_open2(self.as_mut_ptr(), codec.as_ptr(), &mut opts); |
68 | |
69 | Dictionary::own(opts); |
70 | |
71 | match res { |
72 | 0 => Ok(Encoder(self)), |
73 | e => Err(Error::from(e)), |
74 | } |
75 | } else { |
76 | Err(Error::EncoderNotFound) |
77 | } |
78 | } |
79 | } |
80 | |
81 | #[inline ] |
82 | pub fn set_width(&mut self, value: u32) { |
83 | unsafe { |
84 | (*self.as_mut_ptr()).width = value as c_int; |
85 | } |
86 | } |
87 | |
88 | #[inline ] |
89 | pub fn width(&self) -> u32 { |
90 | unsafe { (*self.as_ptr()).width as u32 } |
91 | } |
92 | |
93 | #[inline ] |
94 | pub fn set_height(&mut self, value: u32) { |
95 | unsafe { |
96 | (*self.as_mut_ptr()).height = value as c_int; |
97 | } |
98 | } |
99 | |
100 | #[inline ] |
101 | pub fn height(&self) -> u32 { |
102 | unsafe { (*self.as_ptr()).height as u32 } |
103 | } |
104 | |
105 | #[inline ] |
106 | pub fn set_gop(&mut self, value: u32) { |
107 | unsafe { |
108 | (*self.as_mut_ptr()).gop_size = value as c_int; |
109 | } |
110 | } |
111 | |
112 | #[inline ] |
113 | pub fn set_format(&mut self, value: format::Pixel) { |
114 | unsafe { |
115 | (*self.as_mut_ptr()).pix_fmt = value.into(); |
116 | } |
117 | } |
118 | |
119 | #[inline ] |
120 | pub fn format(&self) -> format::Pixel { |
121 | unsafe { format::Pixel::from((*self.as_ptr()).pix_fmt) } |
122 | } |
123 | |
124 | #[inline ] |
125 | #[cfg (feature = "ff_api_motion_est" )] |
126 | pub fn set_motion_estimation(&mut self, value: MotionEstimation) { |
127 | unsafe { |
128 | (*self.as_mut_ptr()).me_method = value.into(); |
129 | } |
130 | } |
131 | |
132 | #[inline ] |
133 | pub fn set_max_b_frames(&mut self, value: usize) { |
134 | unsafe { |
135 | (*self.as_mut_ptr()).max_b_frames = value as c_int; |
136 | } |
137 | } |
138 | |
139 | #[inline ] |
140 | pub fn set_b_quant_factor(&mut self, value: f32) { |
141 | unsafe { |
142 | (*self.as_mut_ptr()).b_quant_factor = value as c_float; |
143 | } |
144 | } |
145 | |
146 | #[inline ] |
147 | pub fn set_b_quant_offset(&mut self, value: f32) { |
148 | unsafe { |
149 | (*self.as_mut_ptr()).b_quant_offset = value as c_float; |
150 | } |
151 | } |
152 | |
153 | #[inline ] |
154 | pub fn set_i_quant_factor(&mut self, value: f32) { |
155 | unsafe { |
156 | (*self.as_mut_ptr()).i_quant_factor = value as c_float; |
157 | } |
158 | } |
159 | |
160 | #[inline ] |
161 | pub fn set_i_quant_offset(&mut self, value: f32) { |
162 | unsafe { |
163 | (*self.as_mut_ptr()).i_quant_offset = value as c_float; |
164 | } |
165 | } |
166 | |
167 | #[inline ] |
168 | pub fn set_lumi_masking(&mut self, value: f32) { |
169 | unsafe { |
170 | (*self.as_mut_ptr()).lumi_masking = value as c_float; |
171 | } |
172 | } |
173 | |
174 | #[inline ] |
175 | pub fn set_temporal_cplx_masking(&mut self, value: f32) { |
176 | unsafe { |
177 | (*self.as_mut_ptr()).temporal_cplx_masking = value as c_float; |
178 | } |
179 | } |
180 | |
181 | #[inline ] |
182 | pub fn set_spatial_cplx_masking(&mut self, value: f32) { |
183 | unsafe { |
184 | (*self.as_mut_ptr()).spatial_cplx_masking = value as c_float; |
185 | } |
186 | } |
187 | |
188 | #[inline ] |
189 | pub fn set_p_masking(&mut self, value: f32) { |
190 | unsafe { |
191 | (*self.as_mut_ptr()).p_masking = value as c_float; |
192 | } |
193 | } |
194 | |
195 | #[inline ] |
196 | pub fn set_dark_masking(&mut self, value: f32) { |
197 | unsafe { |
198 | (*self.as_mut_ptr()).dark_masking = value as c_float; |
199 | } |
200 | } |
201 | |
202 | #[inline ] |
203 | #[cfg (not(feature = "ffmpeg_5_0" ))] |
204 | pub fn set_prediction(&mut self, value: Prediction) { |
205 | unsafe { |
206 | (*self.as_mut_ptr()).prediction_method = value.into(); |
207 | } |
208 | } |
209 | |
210 | #[inline ] |
211 | pub fn set_aspect_ratio<R: Into<Rational>>(&mut self, value: R) { |
212 | unsafe { |
213 | (*self.as_mut_ptr()).sample_aspect_ratio = value.into().into(); |
214 | } |
215 | } |
216 | |
217 | #[inline ] |
218 | pub fn set_me_comparison(&mut self, value: Comparison) { |
219 | unsafe { |
220 | (*self.as_mut_ptr()).me_cmp = value.into(); |
221 | } |
222 | } |
223 | |
224 | #[inline ] |
225 | pub fn set_me_sub_comparison(&mut self, value: Comparison) { |
226 | unsafe { |
227 | (*self.as_mut_ptr()).me_sub_cmp = value.into(); |
228 | } |
229 | } |
230 | |
231 | #[inline ] |
232 | pub fn set_mb_comparison(&mut self, value: Comparison) { |
233 | unsafe { |
234 | (*self.as_mut_ptr()).mb_cmp = value.into(); |
235 | } |
236 | } |
237 | |
238 | #[inline ] |
239 | pub fn set_ildct_comparison(&mut self, value: Comparison) { |
240 | unsafe { |
241 | (*self.as_mut_ptr()).ildct_cmp = value.into(); |
242 | } |
243 | } |
244 | |
245 | #[inline ] |
246 | pub fn set_dia_size(&mut self, value: usize) { |
247 | unsafe { |
248 | (*self.as_mut_ptr()).dia_size = value as c_int; |
249 | } |
250 | } |
251 | |
252 | #[inline ] |
253 | pub fn set_last_predictors(&mut self, value: usize) { |
254 | unsafe { |
255 | (*self.as_mut_ptr()).last_predictor_count = value as c_int; |
256 | } |
257 | } |
258 | |
259 | #[inline ] |
260 | #[cfg (not(feature = "ffmpeg_5_0" ))] |
261 | pub fn set_pre_me(&mut self, value: MotionEstimation) { |
262 | unsafe { |
263 | (*self.as_mut_ptr()).pre_me = value.into(); |
264 | } |
265 | } |
266 | |
267 | #[inline ] |
268 | pub fn set_me_pre_comparison(&mut self, value: Comparison) { |
269 | unsafe { |
270 | (*self.as_mut_ptr()).me_pre_cmp = value.into(); |
271 | } |
272 | } |
273 | |
274 | #[inline ] |
275 | pub fn set_pre_dia_size(&mut self, value: usize) { |
276 | unsafe { |
277 | (*self.as_mut_ptr()).pre_dia_size = value as c_int; |
278 | } |
279 | } |
280 | |
281 | #[inline ] |
282 | pub fn set_me_subpel_quality(&mut self, value: usize) { |
283 | unsafe { |
284 | (*self.as_mut_ptr()).me_subpel_quality = value as c_int; |
285 | } |
286 | } |
287 | |
288 | #[inline ] |
289 | pub fn set_me_range(&mut self, value: usize) { |
290 | unsafe { |
291 | (*self.as_mut_ptr()).me_range = value as c_int; |
292 | } |
293 | } |
294 | |
295 | #[inline ] |
296 | #[cfg (feature = "ff_api_quant_bias" )] |
297 | pub fn set_intra_quant_bias(&mut self, value: Option<usize>) { |
298 | unsafe { |
299 | if let Some(value) = value { |
300 | (*self.as_mut_ptr()).intra_quant_bias = value as c_int; |
301 | } else { |
302 | (*self.as_mut_ptr()).intra_quant_bias = FF_DEFAULT_QUANT_BIAS; |
303 | } |
304 | } |
305 | } |
306 | |
307 | #[inline ] |
308 | #[cfg (feature = "ff_api_quant_bias" )] |
309 | pub fn set_inter_quant_bias(&mut self, value: Option<usize>) { |
310 | unsafe { |
311 | if let Some(value) = value { |
312 | (*self.as_mut_ptr()).inter_quant_bias = value as c_int; |
313 | } else { |
314 | (*self.as_mut_ptr()).inter_quant_bias = FF_DEFAULT_QUANT_BIAS; |
315 | } |
316 | } |
317 | } |
318 | |
319 | #[inline ] |
320 | pub fn set_mb_decision(&mut self, value: Decision) { |
321 | unsafe { |
322 | (*self.as_mut_ptr()).mb_decision = value.into(); |
323 | } |
324 | } |
325 | |
326 | #[inline ] |
327 | pub fn set_mb_lmin(&mut self, value: i32) { |
328 | unsafe { |
329 | (*self.as_mut_ptr()).mb_lmin = value as c_int; |
330 | } |
331 | } |
332 | |
333 | #[inline ] |
334 | pub fn set_mb_lmax(&mut self, value: i32) { |
335 | unsafe { |
336 | (*self.as_mut_ptr()).mb_lmax = value as c_int; |
337 | } |
338 | } |
339 | |
340 | #[inline ] |
341 | pub fn set_intra_dc_precision(&mut self, value: u8) { |
342 | unsafe { |
343 | (*self.as_mut_ptr()).intra_dc_precision = i32::from(value); |
344 | } |
345 | } |
346 | |
347 | #[inline ] |
348 | pub fn set_qmin(&mut self, value: i32) { |
349 | unsafe { |
350 | (*self.as_mut_ptr()).qmin = value as c_int; |
351 | } |
352 | } |
353 | |
354 | #[inline ] |
355 | pub fn set_qmax(&mut self, value: i32) { |
356 | unsafe { |
357 | (*self.as_mut_ptr()).qmax = value as c_int; |
358 | } |
359 | } |
360 | |
361 | #[inline ] |
362 | pub fn set_global_quality(&mut self, value: i32) { |
363 | unsafe { |
364 | (*self.as_mut_ptr()).global_quality = value as c_int; |
365 | } |
366 | } |
367 | |
368 | #[inline ] |
369 | pub fn set_colorspace(&mut self, value: color::Space) { |
370 | unsafe { |
371 | (*self.as_mut_ptr()).colorspace = value.into(); |
372 | } |
373 | } |
374 | |
375 | #[inline ] |
376 | pub fn colorspace(&self) -> color::Space { |
377 | unsafe { (*self.as_ptr()).colorspace.into() } |
378 | } |
379 | |
380 | #[inline ] |
381 | pub fn set_color_range(&mut self, value: color::Range) { |
382 | unsafe { |
383 | (*self.as_mut_ptr()).color_range = value.into(); |
384 | } |
385 | } |
386 | |
387 | #[inline ] |
388 | pub fn color_range(&self) -> color::Range { |
389 | unsafe { (*self.as_ptr()).color_range.into() } |
390 | } |
391 | } |
392 | |
393 | impl Deref for Video { |
394 | type Target = Super; |
395 | |
396 | #[inline (always)] |
397 | fn deref(&self) -> &<Self as Deref>::Target { |
398 | &self.0 |
399 | } |
400 | } |
401 | |
402 | impl DerefMut for Video { |
403 | #[inline (always)] |
404 | fn deref_mut(&mut self) -> &mut <Self as Deref>::Target { |
405 | &mut self.0 |
406 | } |
407 | } |
408 | |
409 | impl AsRef<Context> for Video { |
410 | fn as_ref(&self) -> &Context { |
411 | self |
412 | } |
413 | } |
414 | |
415 | impl AsMut<Context> for Video { |
416 | fn as_mut(&mut self) -> &mut Context { |
417 | &mut self.0 |
418 | } |
419 | } |
420 | |
421 | pub struct Encoder(pub Video); |
422 | |
423 | impl Encoder { |
424 | #[deprecated ( |
425 | since = "4.4.0" , |
426 | note = "Underlying API avcodec_encode_video2 has been deprecated since FFmpeg 3.1; \ |
427 | consider switching to send_frame() and receive_packet()" |
428 | )] |
429 | #[inline ] |
430 | #[cfg (not(feature = "ffmpeg_5_0" ))] |
431 | pub fn encode<P: packet::Mut>( |
432 | &mut self, |
433 | frame: &frame::Video, |
434 | out: &mut P, |
435 | ) -> Result<bool, Error> { |
436 | unsafe { |
437 | if self.format() != frame.format() |
438 | || self.width() != frame.width() |
439 | || self.height() != frame.height() |
440 | { |
441 | return Err(Error::InvalidData); |
442 | } |
443 | |
444 | let mut got: c_int = 0; |
445 | |
446 | match avcodec_encode_video2( |
447 | self.0.as_mut_ptr(), |
448 | out.as_mut_ptr(), |
449 | frame.as_ptr(), |
450 | &mut got, |
451 | ) { |
452 | e if e < 0 => Err(Error::from(e)), |
453 | _ => Ok(got != 0), |
454 | } |
455 | } |
456 | } |
457 | |
458 | #[deprecated ( |
459 | since = "4.4.0" , |
460 | note = "Underlying API avcodec_encode_video2 has been deprecated since FFmpeg 3.1; \ |
461 | consider switching to send_frame() and receive_packet()" |
462 | )] |
463 | #[inline ] |
464 | #[cfg (not(feature = "ffmpeg_5_0" ))] |
465 | pub fn flush<P: packet::Mut>(&mut self, out: &mut P) -> Result<bool, Error> { |
466 | unsafe { |
467 | let mut got: c_int = 0; |
468 | |
469 | match avcodec_encode_video2( |
470 | self.0.as_mut_ptr(), |
471 | out.as_mut_ptr(), |
472 | ptr::null(), |
473 | &mut got, |
474 | ) { |
475 | e if e < 0 => Err(Error::from(e)), |
476 | _ => Ok(got != 0), |
477 | } |
478 | } |
479 | } |
480 | |
481 | #[inline ] |
482 | pub fn frame_size(&self) -> u32 { |
483 | unsafe { (*self.as_ptr()).frame_size as u32 } |
484 | } |
485 | } |
486 | |
487 | impl Deref for Encoder { |
488 | type Target = Video; |
489 | |
490 | #[inline ] |
491 | fn deref(&self) -> &<Self as Deref>::Target { |
492 | &self.0 |
493 | } |
494 | } |
495 | |
496 | impl DerefMut for Encoder { |
497 | #[inline ] |
498 | fn deref_mut(&mut self) -> &mut <Self as Deref>::Target { |
499 | &mut self.0 |
500 | } |
501 | } |
502 | |
503 | impl AsRef<Context> for Encoder { |
504 | fn as_ref(&self) -> &Context { |
505 | self |
506 | } |
507 | } |
508 | |
509 | impl AsMut<Context> for Encoder { |
510 | fn as_mut(&mut self) -> &mut Context { |
511 | &mut self.0 |
512 | } |
513 | } |
514 | |