ffmpeg_rs/software/scaling/
context.rs

1use std::ptr;
2
3use super::Flags;
4use ffi::*;
5use libc::c_int;
6use util::format;
7use {frame, Error};
8
9#[derive(Eq, PartialEq, Copy, Clone, Debug)]
10pub struct Definition {
11    pub format: format::Pixel,
12    pub width: u32,
13    pub height: u32,
14}
15
16pub struct Context {
17    ptr: *mut SwsContext,
18
19    input: Definition,
20    output: Definition,
21}
22
23unsafe impl Send for Context {}
24
25impl Context {
26    #[inline(always)]
27    pub unsafe fn as_ptr(&self) -> *const SwsContext {
28        self.ptr as *const _
29    }
30
31    #[inline(always)]
32    pub unsafe fn as_mut_ptr(&mut self) -> *mut SwsContext {
33        self.ptr
34    }
35}
36
37impl Context {
38    pub fn get(
39        src_format: format::Pixel,
40        src_w: u32,
41        src_h: u32,
42        dst_format: format::Pixel,
43        dst_w: u32,
44        dst_h: u32,
45        flags: Flags,
46    ) -> Result<Self, Error> {
47        unsafe {
48            let ptr = sws_getContext(
49                src_w as c_int,
50                src_h as c_int,
51                src_format.into(),
52                dst_w as c_int,
53                dst_h as c_int,
54                dst_format.into(),
55                flags.bits(),
56                ptr::null_mut(),
57                ptr::null_mut(),
58                ptr::null_mut(),
59            );
60
61            if !ptr.is_null() {
62                Ok(Context {
63                    ptr,
64
65                    input: Definition {
66                        format: src_format,
67                        width: src_w,
68                        height: src_h,
69                    },
70
71                    output: Definition {
72                        format: dst_format,
73                        width: dst_w,
74                        height: dst_h,
75                    },
76                })
77            } else {
78                Err(Error::InvalidData)
79            }
80        }
81    }
82
83    pub fn cached(
84        &mut self,
85        src_format: format::Pixel,
86        src_w: u32,
87        src_h: u32,
88        dst_format: format::Pixel,
89        dst_w: u32,
90        dst_h: u32,
91        flags: Flags,
92    ) {
93        self.input = Definition {
94            format: src_format,
95            width: src_w,
96            height: src_h,
97        };
98
99        self.output = Definition {
100            format: dst_format,
101            width: dst_w,
102            height: dst_h,
103        };
104
105        unsafe {
106            self.ptr = sws_getCachedContext(
107                self.as_mut_ptr(),
108                src_w as c_int,
109                src_h as c_int,
110                src_format.into(),
111                dst_w as c_int,
112                dst_h as c_int,
113                dst_format.into(),
114                flags.bits(),
115                ptr::null_mut(),
116                ptr::null_mut(),
117                ptr::null(),
118            );
119        }
120    }
121
122    #[inline]
123    pub fn input(&self) -> &Definition {
124        &self.input
125    }
126
127    #[inline]
128    pub fn output(&self) -> &Definition {
129        &self.output
130    }
131
132    pub fn run(&mut self, input: &frame::Video, output: &mut frame::Video) -> Result<(), Error> {
133        if input.format() != self.input.format
134            || input.width() != self.input.width
135            || input.height() != self.input.height
136        {
137            return Err(Error::InputChanged);
138        }
139
140        unsafe {
141            if output.is_empty() {
142                output.alloc(self.output.format, self.output.width, self.output.height);
143            }
144        }
145
146        if output.format() != self.output.format
147            || output.width() != self.output.width
148            || output.height() != self.output.height
149        {
150            return Err(Error::OutputChanged);
151        }
152
153        unsafe {
154            sws_scale(
155                self.as_mut_ptr(),
156                (*input.as_ptr()).data.as_ptr() as *const *const _,
157                (*input.as_ptr()).linesize.as_ptr() as *const _,
158                0,
159                self.input.height as c_int,
160                (*output.as_mut_ptr()).data.as_ptr() as *const *mut _,
161                (*output.as_mut_ptr()).linesize.as_ptr() as *mut _,
162            );
163        }
164
165        Ok(())
166    }
167}
168
169impl Drop for Context {
170    fn drop(&mut self) {
171        unsafe {
172            sws_freeContext(self.as_mut_ptr());
173        }
174    }
175}