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}
174