playa_ffmpeg/software/scaling/
context.rs1use std::ptr;
2
3use super::Flags;
4use crate::{Error, ffi::*, frame, util::format};
5use libc::c_int;
6
7#[derive(Eq, PartialEq, Copy, Clone, Debug)]
8pub struct Definition {
9 pub format: format::Pixel,
10 pub width: u32,
11 pub height: u32,
12}
13
14pub struct Context {
15 ptr: *mut SwsContext,
16
17 input: Definition,
18 output: Definition,
19}
20
21impl Context {
22 #[inline(always)]
23 pub unsafe fn as_ptr(&self) -> *const SwsContext {
24 self.ptr as *const _
25 }
26
27 #[inline(always)]
28 pub unsafe fn as_mut_ptr(&mut self) -> *mut SwsContext {
29 self.ptr
30 }
31}
32
33impl Context {
34 pub fn get(src_format: format::Pixel, src_w: u32, src_h: u32, dst_format: format::Pixel, dst_w: u32, dst_h: u32, flags: Flags) -> Result<Self, Error> {
35 unsafe {
36 let ptr = sws_getContext(src_w as c_int, src_h as c_int, src_format.into(), dst_w as c_int, dst_h as c_int, dst_format.into(), flags.bits(), ptr::null_mut(), ptr::null_mut(), ptr::null_mut());
37
38 if !ptr.is_null() { Ok(Context { ptr, input: Definition { format: src_format, width: src_w, height: src_h }, output: Definition { format: dst_format, width: dst_w, height: dst_h } }) } else { Err(Error::InvalidData) }
39 }
40 }
41
42 pub fn cached(&mut self, src_format: format::Pixel, src_w: u32, src_h: u32, dst_format: format::Pixel, dst_w: u32, dst_h: u32, flags: Flags) {
43 self.input = Definition { format: src_format, width: src_w, height: src_h };
44
45 self.output = Definition { format: dst_format, width: dst_w, height: dst_h };
46
47 unsafe {
48 self.ptr = sws_getCachedContext(self.as_mut_ptr(), src_w as c_int, src_h as c_int, src_format.into(), dst_w as c_int, dst_h as c_int, dst_format.into(), flags.bits(), ptr::null_mut(), ptr::null_mut(), ptr::null());
49 }
50 }
51
52 #[inline]
53 pub fn input(&self) -> &Definition {
54 &self.input
55 }
56
57 #[inline]
58 pub fn output(&self) -> &Definition {
59 &self.output
60 }
61
62 pub fn run(&mut self, input: &frame::Video, output: &mut frame::Video) -> Result<(), Error> {
63 if input.format() != self.input.format || input.width() != self.input.width || input.height() != self.input.height {
64 return Err(Error::InputChanged);
65 }
66
67 unsafe {
68 if output.is_empty() {
69 output.alloc(self.output.format, self.output.width, self.output.height);
70 }
71 }
72
73 if output.format() != self.output.format || output.width() != self.output.width || output.height() != self.output.height {
74 return Err(Error::OutputChanged);
75 }
76
77 unsafe {
78 sws_scale(
79 self.as_mut_ptr(),
80 (*input.as_ptr()).data.as_ptr() as *const *const _,
81 (*input.as_ptr()).linesize.as_ptr() as *const _,
82 0,
83 self.input.height as c_int,
84 (*output.as_mut_ptr()).data.as_ptr(),
85 (*output.as_mut_ptr()).linesize.as_ptr() as *mut _,
86 );
87 }
88
89 Ok(())
90 }
91}
92
93impl Drop for Context {
94 fn drop(&mut self) {
95 unsafe {
96 sws_freeContext(self.as_mut_ptr());
97 }
98 }
99}