ffmpeg_the_third/software/scaling/
context.rs1use std::ptr;
2
3use super::Flags;
4use crate::ffi::*;
5use crate::util::format;
6use crate::{frame, Error};
7use libc::c_int;
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 #[allow(clippy::too_many_arguments)]
82 pub fn cached(
83 &mut self,
84 src_format: format::Pixel,
85 src_w: u32,
86 src_h: u32,
87 dst_format: format::Pixel,
88 dst_w: u32,
89 dst_h: u32,
90 flags: Flags,
91 ) {
92 self.input = Definition {
93 format: src_format,
94 width: src_w,
95 height: src_h,
96 };
97
98 self.output = Definition {
99 format: dst_format,
100 width: dst_w,
101 height: dst_h,
102 };
103
104 unsafe {
105 self.ptr = sws_getCachedContext(
106 self.as_mut_ptr(),
107 src_w as c_int,
108 src_h as c_int,
109 src_format.into(),
110 dst_w as c_int,
111 dst_h as c_int,
112 dst_format.into(),
113 flags.bits(),
114 ptr::null_mut(),
115 ptr::null_mut(),
116 ptr::null(),
117 );
118 }
119 }
120
121 #[inline]
122 pub fn input(&self) -> &Definition {
123 &self.input
124 }
125
126 #[inline]
127 pub fn output(&self) -> &Definition {
128 &self.output
129 }
130
131 pub fn run(&mut self, input: &frame::Video, output: &mut frame::Video) -> Result<(), Error> {
132 if input.format() != self.input.format
133 || input.width() != self.input.width
134 || input.height() != self.input.height
135 {
136 return Err(Error::InputChanged);
137 }
138
139 unsafe {
140 if output.is_empty() {
141 output.alloc(self.output.format, self.output.width, self.output.height);
142 }
143 }
144
145 if output.format() != self.output.format
146 || output.width() != self.output.width
147 || output.height() != self.output.height
148 {
149 return Err(Error::OutputChanged);
150 }
151
152 unsafe {
153 sws_scale(
154 self.as_mut_ptr(),
155 (*input.as_ptr()).data.as_ptr() as *const *const _,
156 (*input.as_ptr()).linesize.as_ptr() as *const _,
157 0,
158 self.input.height as c_int,
159 (*output.as_mut_ptr()).data.as_ptr() as *const *mut _,
160 (*output.as_mut_ptr()).linesize.as_ptr() as *mut _,
161 );
162 }
163
164 Ok(())
165 }
166}
167
168impl Drop for Context {
169 fn drop(&mut self) {
170 unsafe {
171 sws_freeContext(self.as_mut_ptr());
172 }
173 }
174}