You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

153 lines
4.0 KiB
Rust

use crate::av::as_ptr::{AsMutPtr, AsPtr};
use crate::av::decoder::Decoder;
use crate::av::encoder::Encoder;
use crate::av::frame::Frame;
use crate::av::verify_response;
use crate::av::xcoder::XCoder;
use ffmpeg_sys_next::{sws_getContext, sws_scale, AVPixelFormat, SwsContext};
use std::os::raw::c_int;
use std::ptr::null_mut;
#[derive(Debug)]
pub struct Scaler {
pub ctx: *mut SwsContext,
flags: c_int,
input: VideoInfo,
output: VideoInfo,
pass_through: bool,
}
#[derive(Eq, PartialEq, Debug)]
struct VideoInfo {
width: i32,
height: i32,
pixel_format: AVPixelFormat,
}
impl Scaler {
pub fn new(
from_pixel_format: AVPixelFormat,
from_width: i32,
from_height: i32,
to_pixel_format: AVPixelFormat,
to_width: i32,
to_height: i32,
flags: c_int,
) -> Scaler {
unsafe {
let ptr = sws_getContext(
from_width,
from_height,
from_pixel_format,
to_width,
to_height,
to_pixel_format,
flags,
null_mut(),
null_mut(),
null_mut(),
);
let input = VideoInfo {
width: from_width,
height: from_height,
pixel_format: from_pixel_format,
};
let output = VideoInfo {
width: to_width,
height: to_height,
pixel_format: to_pixel_format,
};
Scaler {
ctx: ptr,
pass_through: input.eq(&output),
flags,
input,
output,
}
}
}
pub fn from_coder(decoder: &Decoder, encoder: &Encoder, flags: i32) -> Scaler {
Scaler::new(
decoder.pixel_format(),
decoder.width(),
decoder.height(),
encoder.pixel_format(),
encoder.width(),
encoder.height(),
flags,
)
}
pub fn scale(&mut self, input: Frame) -> Result<Frame, String> {
if self.input.pixel_format != input.pixel_format()
|| self.input.width != input.width()
|| self.input.height != input.height()
{
self.input = VideoInfo {
pixel_format: input.pixel_format(),
width: input.width(),
height: input.height(),
};
self.pass_through = self.input == self.output;
if !self.pass_through {
unsafe {
self.ctx = sws_getContext(
self.input.width,
self.input.height,
self.input.pixel_format,
self.output.width,
self.output.height,
self.output.pixel_format,
self.flags,
null_mut(),
null_mut(),
null_mut(),
);
}
}
}
if self.pass_through {
return Ok(input);
}
let mut frame = Frame::alloc();
frame.allocate_video(
self.output.pixel_format,
self.output.width,
self.output.height,
)?;
verify_response("Failed to scale frame", unsafe {
sws_scale(
self.as_mut_ptr(),
(*input.as_ptr()).data.as_ptr() as *const *const _,
(*input.as_mut_ptr()).linesize.as_ptr() as *const _,
0,
self.input.height,
(*frame.as_mut_ptr()).data.as_ptr() as *const *mut _,
(*frame.as_mut_ptr()).linesize.as_ptr() as *mut _,
)
})?;
Ok(frame)
}
}
impl AsPtr<SwsContext> for Scaler {
fn as_ptr(&self) -> *const SwsContext {
self.ctx
}
}
impl AsMutPtr<SwsContext> for Scaler {
fn as_mut_ptr(&self) -> *mut SwsContext {
self.ctx
}
}