ffmpeg_rs/software/scaling/
context.rs1use 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}