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