ac_ffmpeg/codec/video/
mod.rs

1//! Video decoder/encoder.
2
3#[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
23/// Builder for the video decoder.
24pub struct VideoDecoderBuilder {
25    ptr: *mut c_void,
26    time_base: TimeBase,
27}
28
29impl VideoDecoderBuilder {
30    /// Create a new decoder builder from a given raw representation.
31    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    /// Create a new builder for a given codec.
40    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    /// Create a new builder from given codec parameters.
53    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    /// Set a decoder option.
64    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    /// Set decoder time base (all input packets will be rescaled into this
83    /// time base). The default time base is in microseconds.
84    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    /// Set codec extradata.
99    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    /// Build the decoder.
126    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
155/// Video decoder.
156pub struct VideoDecoder {
157    ptr: *mut c_void,
158    time_base: TimeBase,
159}
160
161impl VideoDecoder {
162    /// Create a new video decoder for a given codec.
163    pub fn new(codec: &str) -> Result<Self, Error> {
164        VideoDecoderBuilder::new(codec).and_then(|builder| builder.build())
165    }
166
167    /// Create a new video decoder builder from given codec parameters.
168    pub fn from_codec_parameters(
169        codec_parameters: &VideoCodecParameters,
170    ) -> Result<VideoDecoderBuilder, Error> {
171        VideoDecoderBuilder::from_codec_parameters(codec_parameters)
172    }
173
174    /// Create a new decoder for a given stream.
175    ///
176    /// # Panics
177    /// The method panics if the stream is not a video stream.
178    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    /// Get decoder builder for a given codec.
191    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
266/// Builder for the video encoder.
267pub 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    /// Create a new encoder builder for a given codec.
279    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    /// Create a new encoder builder from given codec parameters.
306    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    /// Set an encoder option.
337    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    /// Set encoder bit rate. The default is 0 (i.e. automatic).
356    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    /// Set encoder time base. The default time base is in microseconds.
365    #[inline]
366    pub fn time_base(mut self, time_base: TimeBase) -> Self {
367        self.time_base = time_base;
368        self
369    }
370
371    /// Set encoder pixel format.
372    #[inline]
373    pub fn pixel_format(mut self, format: PixelFormat) -> Self {
374        self.format = Some(format);
375        self
376    }
377
378    /// Set frame width.
379    #[inline]
380    pub fn width(mut self, width: usize) -> Self {
381        self.width = Some(width);
382        self
383    }
384
385    /// Set frame height.
386    #[inline]
387    pub fn height(mut self, height: usize) -> Self {
388        self.height = Some(height);
389        self
390    }
391
392    /// Set codec tag.
393    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    /// Build the encoder.
402    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
442/// Video encoder.
443pub struct VideoEncoder {
444    ptr: *mut c_void,
445    time_base: TimeBase,
446}
447
448impl VideoEncoder {
449    /// Create a new encoder from given codec parameters.
450    pub fn from_codec_parameters(
451        codec_parameters: &VideoCodecParameters,
452    ) -> Result<VideoEncoderBuilder, Error> {
453        VideoEncoderBuilder::from_codec_parameters(codec_parameters)
454    }
455
456    /// Get encoder builder for a given codec.
457    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 {}