1 | use std::ptr; |
2 | |
3 | use super::Flags; |
4 | use ffi::*; |
5 | use libc::c_int; |
6 | use util::format; |
7 | use {frame, Error}; |
8 | |
9 | #[derive (Eq, PartialEq, Copy, Clone, Debug)] |
10 | pub struct Definition { |
11 | pub format: format::Pixel, |
12 | pub width: u32, |
13 | pub height: u32, |
14 | } |
15 | |
16 | pub struct Context { |
17 | ptr: *mut SwsContext, |
18 | |
19 | input: Definition, |
20 | output: Definition, |
21 | } |
22 | |
23 | impl 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 | |
35 | impl 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 | |
167 | impl Drop for Context { |
168 | fn drop(&mut self) { |
169 | unsafe { |
170 | sws_freeContext(self.as_mut_ptr()); |
171 | } |
172 | } |
173 | } |
174 | |