1#[cfg(feature = "filters")]
4pub mod filter;
5pub mod frame;
6pub mod scaler;
7
8use std::{ffi::CString, os::raw::c_void, ptr};
9
10use crate::{
11 codec::{CodecError, CodecParameters, CodecTag, Decoder, Encoder, VideoCodecParameters},
12 format::stream::Stream,
13 packet::Packet,
14 time::TimeBase,
15 Error,
16};
17
18pub use self::{
19 frame::{PixelFormat, VideoFrame, VideoFrameMut},
20 scaler::{VideoFrameScaler, VideoFrameScalerBuilder},
21};
22
23pub struct VideoDecoderBuilder {
25 ptr: *mut c_void,
26 time_base: TimeBase,
27}
28
29impl VideoDecoderBuilder {
30 unsafe fn from_raw_ptr(ptr: *mut c_void) -> Self {
32 let time_base = TimeBase::MICROSECONDS;
33
34 super::ffw_decoder_set_pkt_timebase(ptr, time_base.num() as _, time_base.den() as _);
35
36 Self { ptr, time_base }
37 }
38
39 fn new(codec: &str) -> Result<Self, Error> {
41 let codec = CString::new(codec).expect("invalid codec name");
42
43 let ptr = unsafe { super::ffw_decoder_new(codec.as_ptr() as _) };
44
45 if ptr.is_null() {
46 return Err(Error::new("unknown codec"));
47 }
48
49 unsafe { Ok(Self::from_raw_ptr(ptr)) }
50 }
51
52 fn from_codec_parameters(codec_parameters: &VideoCodecParameters) -> Result<Self, Error> {
54 let ptr = unsafe { super::ffw_decoder_from_codec_parameters(codec_parameters.as_ptr()) };
55
56 if ptr.is_null() {
57 return Err(Error::new("unable to create a decoder"));
58 }
59
60 unsafe { Ok(Self::from_raw_ptr(ptr)) }
61 }
62
63 pub fn set_option<V>(self, name: &str, value: V) -> Self
65 where
66 V: ToString,
67 {
68 let name = CString::new(name).expect("invalid option name");
69 let value = CString::new(value.to_string()).expect("invalid option value");
70
71 let ret = unsafe {
72 super::ffw_decoder_set_initial_option(self.ptr, name.as_ptr() as _, value.as_ptr() as _)
73 };
74
75 if ret < 0 {
76 panic!("unable to allocate an option");
77 }
78
79 self
80 }
81
82 pub fn time_base(mut self, time_base: TimeBase) -> Self {
85 self.time_base = time_base;
86
87 unsafe {
88 super::ffw_decoder_set_pkt_timebase(
89 self.ptr,
90 time_base.num() as _,
91 time_base.den() as _,
92 );
93 }
94
95 self
96 }
97
98 pub fn extradata<T>(self, data: Option<T>) -> Self
100 where
101 T: AsRef<[u8]>,
102 {
103 let data = data.as_ref().map(|d| d.as_ref());
104
105 let ptr;
106 let size;
107
108 if let Some(data) = data {
109 ptr = data.as_ptr();
110 size = data.len();
111 } else {
112 ptr = ptr::null();
113 size = 0;
114 }
115
116 let res = unsafe { super::ffw_decoder_set_extradata(self.ptr, ptr, size as _) };
117
118 if res < 0 {
119 panic!("unable to allocate extradata");
120 }
121
122 self
123 }
124
125 pub fn build(mut self) -> Result<VideoDecoder, Error> {
127 unsafe {
128 if super::ffw_decoder_open(self.ptr) != 0 {
129 return Err(Error::new("unable to build the decoder"));
130 }
131 }
132
133 let ptr = self.ptr;
134
135 self.ptr = ptr::null_mut();
136
137 let res = VideoDecoder {
138 ptr,
139 time_base: self.time_base,
140 };
141
142 Ok(res)
143 }
144}
145
146impl Drop for VideoDecoderBuilder {
147 fn drop(&mut self) {
148 unsafe { super::ffw_decoder_free(self.ptr) }
149 }
150}
151
152unsafe impl Send for VideoDecoderBuilder {}
153unsafe impl Sync for VideoDecoderBuilder {}
154
155pub struct VideoDecoder {
157 ptr: *mut c_void,
158 time_base: TimeBase,
159}
160
161impl VideoDecoder {
162 pub fn new(codec: &str) -> Result<Self, Error> {
164 VideoDecoderBuilder::new(codec).and_then(|builder| builder.build())
165 }
166
167 pub fn from_codec_parameters(
169 codec_parameters: &VideoCodecParameters,
170 ) -> Result<VideoDecoderBuilder, Error> {
171 VideoDecoderBuilder::from_codec_parameters(codec_parameters)
172 }
173
174 pub fn from_stream(stream: &Stream) -> Result<VideoDecoderBuilder, Error> {
179 let codec_parameters = stream
180 .codec_parameters()
181 .into_video_codec_parameters()
182 .unwrap();
183
184 let builder = VideoDecoderBuilder::from_codec_parameters(&codec_parameters)?
185 .time_base(stream.time_base());
186
187 Ok(builder)
188 }
189
190 pub fn builder(codec: &str) -> Result<VideoDecoderBuilder, Error> {
192 VideoDecoderBuilder::new(codec)
193 }
194}
195
196impl Decoder for VideoDecoder {
197 type CodecParameters = VideoCodecParameters;
198 type Frame = VideoFrame;
199
200 fn codec_parameters(&self) -> VideoCodecParameters {
201 let ptr = unsafe { super::ffw_decoder_get_codec_parameters(self.ptr) };
202
203 if ptr.is_null() {
204 panic!("unable to allocate codec parameters");
205 }
206
207 let params = unsafe { CodecParameters::from_raw_ptr(ptr) };
208
209 params.into_video_codec_parameters().unwrap()
210 }
211
212 fn try_push(&mut self, packet: Packet) -> Result<(), CodecError> {
213 let packet = packet.with_time_base(self.time_base);
214
215 unsafe {
216 match super::ffw_decoder_push_packet(self.ptr, packet.as_ptr()) {
217 1 => Ok(()),
218 0 => Err(CodecError::again(
219 "all frames must be consumed before pushing a new packet",
220 )),
221 e => Err(CodecError::from_raw_error_code(e)),
222 }
223 }
224 }
225
226 fn try_flush(&mut self) -> Result<(), CodecError> {
227 unsafe {
228 match super::ffw_decoder_push_packet(self.ptr, ptr::null()) {
229 1 => Ok(()),
230 0 => Err(CodecError::again(
231 "all frames must be consumed before flushing",
232 )),
233 e => Err(CodecError::from_raw_error_code(e)),
234 }
235 }
236 }
237
238 fn take(&mut self) -> Result<Option<VideoFrame>, Error> {
239 let mut fptr = ptr::null_mut();
240
241 unsafe {
242 match super::ffw_decoder_take_frame(self.ptr, &mut fptr) {
243 1 => {
244 if fptr.is_null() {
245 panic!("no frame received")
246 } else {
247 Ok(Some(VideoFrame::from_raw_ptr(fptr, self.time_base)))
248 }
249 }
250 0 => Ok(None),
251 e => Err(Error::from_raw_error_code(e)),
252 }
253 }
254 }
255}
256
257impl Drop for VideoDecoder {
258 fn drop(&mut self) {
259 unsafe { super::ffw_decoder_free(self.ptr) }
260 }
261}
262
263unsafe impl Send for VideoDecoder {}
264unsafe impl Sync for VideoDecoder {}
265
266pub struct VideoEncoderBuilder {
268 ptr: *mut c_void,
269
270 time_base: TimeBase,
271
272 format: Option<PixelFormat>,
273 width: Option<usize>,
274 height: Option<usize>,
275}
276
277impl VideoEncoderBuilder {
278 fn new(codec: &str) -> Result<Self, Error> {
280 let codec = CString::new(codec).expect("invalid codec name");
281
282 let ptr = unsafe { super::ffw_encoder_new(codec.as_ptr() as _) };
283
284 if ptr.is_null() {
285 return Err(Error::new("unknown codec"));
286 }
287
288 unsafe {
289 super::ffw_encoder_set_bit_rate(ptr, 0);
290 }
291
292 let res = Self {
293 ptr,
294
295 time_base: TimeBase::MICROSECONDS,
296
297 format: None,
298 width: None,
299 height: None,
300 };
301
302 Ok(res)
303 }
304
305 fn from_codec_parameters(codec_parameters: &VideoCodecParameters) -> Result<Self, Error> {
307 let ptr = unsafe { super::ffw_encoder_from_codec_parameters(codec_parameters.as_ptr()) };
308
309 if ptr.is_null() {
310 return Err(Error::new("unable to create an encoder"));
311 }
312
313 let pixel_format;
314 let width;
315 let height;
316
317 unsafe {
318 pixel_format = PixelFormat::from_raw(super::ffw_encoder_get_pixel_format(ptr));
319 width = super::ffw_encoder_get_width(ptr) as _;
320 height = super::ffw_encoder_get_height(ptr) as _;
321 }
322
323 let res = Self {
324 ptr,
325
326 time_base: TimeBase::MICROSECONDS,
327
328 format: Some(pixel_format),
329 width: Some(width),
330 height: Some(height),
331 };
332
333 Ok(res)
334 }
335
336 pub fn set_option<V>(self, name: &str, value: V) -> Self
338 where
339 V: ToString,
340 {
341 let name = CString::new(name).expect("invalid option name");
342 let value = CString::new(value.to_string()).expect("invalid option value");
343
344 let ret = unsafe {
345 super::ffw_encoder_set_initial_option(self.ptr, name.as_ptr() as _, value.as_ptr() as _)
346 };
347
348 if ret < 0 {
349 panic!("unable to allocate an option");
350 }
351
352 self
353 }
354
355 pub fn bit_rate(self, bit_rate: u64) -> Self {
357 unsafe {
358 super::ffw_encoder_set_bit_rate(self.ptr, bit_rate as _);
359 }
360
361 self
362 }
363
364 #[inline]
366 pub fn time_base(mut self, time_base: TimeBase) -> Self {
367 self.time_base = time_base;
368 self
369 }
370
371 #[inline]
373 pub fn pixel_format(mut self, format: PixelFormat) -> Self {
374 self.format = Some(format);
375 self
376 }
377
378 #[inline]
380 pub fn width(mut self, width: usize) -> Self {
381 self.width = Some(width);
382 self
383 }
384
385 #[inline]
387 pub fn height(mut self, height: usize) -> Self {
388 self.height = Some(height);
389 self
390 }
391
392 pub fn codec_tag(self, codec_tag: impl Into<CodecTag>) -> Self {
394 unsafe {
395 super::ffw_encoder_set_codec_tag(self.ptr, codec_tag.into().into());
396 }
397
398 self
399 }
400
401 pub fn build(mut self) -> Result<VideoEncoder, Error> {
403 let format = self
404 .format
405 .ok_or_else(|| Error::new("pixel format not set"))?;
406
407 let width = self.width.ok_or_else(|| Error::new("width not set"))?;
408 let height = self.height.ok_or_else(|| Error::new("height not set"))?;
409
410 let tb = self.time_base;
411
412 unsafe {
413 super::ffw_encoder_set_time_base(self.ptr, tb.num() as _, tb.den() as _);
414 super::ffw_encoder_set_pixel_format(self.ptr, format.into_raw());
415 super::ffw_encoder_set_width(self.ptr, width as _);
416 super::ffw_encoder_set_height(self.ptr, height as _);
417
418 if super::ffw_encoder_open(self.ptr) != 0 {
419 return Err(Error::new("unable to build the encoder"));
420 }
421 }
422
423 let ptr = self.ptr;
424
425 self.ptr = ptr::null_mut();
426
427 let res = VideoEncoder { ptr, time_base: tb };
428
429 Ok(res)
430 }
431}
432
433impl Drop for VideoEncoderBuilder {
434 fn drop(&mut self) {
435 unsafe { super::ffw_encoder_free(self.ptr) }
436 }
437}
438
439unsafe impl Send for VideoEncoderBuilder {}
440unsafe impl Sync for VideoEncoderBuilder {}
441
442pub struct VideoEncoder {
444 ptr: *mut c_void,
445 time_base: TimeBase,
446}
447
448impl VideoEncoder {
449 pub fn from_codec_parameters(
451 codec_parameters: &VideoCodecParameters,
452 ) -> Result<VideoEncoderBuilder, Error> {
453 VideoEncoderBuilder::from_codec_parameters(codec_parameters)
454 }
455
456 pub fn builder(codec: &str) -> Result<VideoEncoderBuilder, Error> {
458 VideoEncoderBuilder::new(codec)
459 }
460}
461
462impl Encoder for VideoEncoder {
463 type CodecParameters = VideoCodecParameters;
464 type Frame = VideoFrame;
465
466 fn codec_parameters(&self) -> VideoCodecParameters {
467 let ptr = unsafe { super::ffw_encoder_get_codec_parameters(self.ptr) };
468
469 if ptr.is_null() {
470 panic!("unable to allocate codec parameters");
471 }
472
473 let params = unsafe { CodecParameters::from_raw_ptr(ptr) };
474
475 params.into_video_codec_parameters().unwrap()
476 }
477
478 fn try_push(&mut self, frame: VideoFrame) -> Result<(), CodecError> {
479 let frame = frame.with_time_base(self.time_base);
480
481 unsafe {
482 match super::ffw_encoder_push_frame(self.ptr, frame.as_ptr()) {
483 1 => Ok(()),
484 0 => Err(CodecError::again(
485 "all packets must be consumed before pushing a new frame",
486 )),
487 e => Err(CodecError::from_raw_error_code(e)),
488 }
489 }
490 }
491
492 fn try_flush(&mut self) -> Result<(), CodecError> {
493 unsafe {
494 match super::ffw_encoder_push_frame(self.ptr, ptr::null()) {
495 1 => Ok(()),
496 0 => Err(CodecError::again(
497 "all packets must be consumed before flushing",
498 )),
499 e => Err(CodecError::from_raw_error_code(e)),
500 }
501 }
502 }
503
504 fn take(&mut self) -> Result<Option<Packet>, Error> {
505 let mut pptr = ptr::null_mut();
506
507 unsafe {
508 match super::ffw_encoder_take_packet(self.ptr, &mut pptr) {
509 1 => {
510 if pptr.is_null() {
511 panic!("no packet received")
512 } else {
513 Ok(Some(Packet::from_raw_ptr(pptr, self.time_base)))
514 }
515 }
516 0 => Ok(None),
517 e => Err(Error::from_raw_error_code(e)),
518 }
519 }
520 }
521}
522
523impl Drop for VideoEncoder {
524 fn drop(&mut self) {
525 unsafe { super::ffw_encoder_free(self.ptr) }
526 }
527}
528
529unsafe impl Send for VideoEncoder {}
530unsafe impl Sync for VideoEncoder {}