Skip to main content

ffmpeg_pipeline/
scaler.rs

1use super::*;
2use ffmpeg_next::{
3    format::Pixel,
4    software::scaling::{context::Context as ScalerContext, flag::Flags as ScalerFlags},
5    Stream,
6};
7
8pub struct Scaler {
9    scaler: ScalerContext,
10}
11
12#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
13pub enum ScalingAlgorithm {
14    Bilinear,
15    Bicubic,
16    #[default]
17    Spline,
18    Lanczos,
19}
20
21impl Scaler {
22    pub fn new(size: &FrameSize, src_format: Pixel, dst_format: Pixel) -> FFmpegResult<Self> {
23        Self::with_algorithm(size, src_format, dst_format, ScalingAlgorithm::default())
24    }
25
26    pub fn with_algorithm(
27        size: &FrameSize,
28        src_format: Pixel,
29        dst_format: Pixel,
30        algorithm: ScalingAlgorithm,
31    ) -> FFmpegResult<Self> {
32        let flags = match algorithm {
33            ScalingAlgorithm::Bilinear => ScalerFlags::BILINEAR,
34            ScalingAlgorithm::Bicubic => ScalerFlags::BICUBIC,
35            ScalingAlgorithm::Spline => ScalerFlags::SPLINE,
36            ScalingAlgorithm::Lanczos => ScalerFlags::LANCZOS,
37        };
38        Ok(Self {
39            scaler: ScalerContext::get(
40                src_format,
41                size.width as u32,
42                size.height as u32,
43                dst_format,
44                size.width as u32,
45                size.height as u32,
46                flags,
47            )?,
48        })
49    }
50
51    pub fn from_info(info: &VideoInfo, dst_format: Pixel) -> FFmpegResult<Self> {
52        Self::new(&info.size, info.pixel, dst_format)
53    }
54
55    pub fn from_stream(stream: &Stream, dst_format: Pixel) -> FFmpegResult<Self> {
56        let info = parse::parse_stream_info(stream)?;
57        debug!(
58            "stream: {}, size: {} x {}, pixel: {:?}",
59            info.stream, info.size.width, info.size.height, info.pixel
60        );
61        Self::from_info(&info, dst_format)
62    }
63
64    pub fn from_path(path: &Path, index: usize, dst_format: Pixel) -> FFmpegResult<Self> {
65        let input = input_file(path)?;
66        let stream = input
67            .stream(index)
68            .ok_or(FFmpegError::StreamNotFound(index))?;
69        Self::from_stream(&stream, dst_format)
70    }
71
72    pub fn scale_frame(&mut self, frame: &VideoFrame) -> FFmpegResult<VideoFrame> {
73        let mut rgb_frame = VideoFrame::empty();
74        self.scaler.run(frame, &mut rgb_frame)?;
75        Ok(rgb_frame)
76    }
77}