From 8de5580d1ab219451616592a59805d91e367ea0d Mon Sep 17 00:00:00 2001 From: Janne Mareike Koschinski <janne@kuschku.de> Date: Mon, 9 Mar 2020 22:12:21 +0100 Subject: [PATCH] add more exact scaling options --- Cargo.lock | 1 + Cargo.toml | 1 + src/ffmpeg_api/api.rs | 3 ++- src/ffmpeg_api/enums.rs | 12 ++++++++++++ src/ingest/extract.rs | 5 +++-- src/ingest/spritesheet.rs | 2 +- src/main.rs | 22 ++++++++++++++++++++-- 7 files changed, 40 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7b663f3..fc4140e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -454,6 +454,7 @@ checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" name = "media-ingestion" version = "0.1.0" dependencies = [ + "bitflags", "enum_primitive", "failure", "ffmpeg-dev", diff --git a/Cargo.toml b/Cargo.toml index 65a703f..b446c7f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +bitflags = "1.2.1" enum_primitive = "0.1.1" failure = "0.1.6" ffmpeg-dev = "0.3.8" diff --git a/src/ffmpeg_api/api.rs b/src/ffmpeg_api/api.rs index 51df241..d2a9731 100644 --- a/src/ffmpeg_api/api.rs +++ b/src/ffmpeg_api/api.rs @@ -533,6 +533,7 @@ impl SwsContext { source: &AVFrame, target: &AVFrame, scaler: SwsScaler, + flags: SwsFlags, ) -> Result<(), Error> { let base = unsafe { ffi::sws_getCachedContext( @@ -543,7 +544,7 @@ impl SwsContext { target.width(), target.height(), target.format() as ffi::AVPixelFormat, - scaler as i32, + scaler as std::os::raw::c_int | flags.bits() as std::os::raw::c_int, std::ptr::null_mut(), std::ptr::null_mut(), std::ptr::null(), diff --git a/src/ffmpeg_api/enums.rs b/src/ffmpeg_api/enums.rs index 4cd2965..e2b108e 100644 --- a/src/ffmpeg_api/enums.rs +++ b/src/ffmpeg_api/enums.rs @@ -1,6 +1,18 @@ +use bitflags::*; use enum_primitive::*; use ffmpeg_dev::sys as ffi; +bitflags! { + #[derive(Default)] + pub struct SwsFlags: u32 { + const PRINT_INFO = ffi::SWS_PRINT_INFO; + const FULL_CHROMA_INTERPOLATION = ffi::SWS_FULL_CHR_H_INT; + const FULL_CHROMA_INPUT = ffi::SWS_FULL_CHR_H_INP; + const ACCURATE_ROUNDING = ffi::SWS_ACCURATE_RND; + const BIT_EXACT_SCALING = ffi::SWS_BITEXACT; + } +} + enum_from_primitive! { #[doc = " Pixel format."] #[doc = ""] diff --git a/src/ingest/extract.rs b/src/ingest/extract.rs index 0c29b0c..658cf09 100644 --- a/src/ingest/extract.rs +++ b/src/ingest/extract.rs @@ -17,6 +17,7 @@ pub fn extract( output_folder: &Path, format: impl AsRef<str>, scaler: SwsScaler, + flags: SwsFlags, ) -> Result<(), Error> { let mut avformat_context = AVFormatContext::new() .map_err(|error| format_err!("Could not open video input: {}", error))?; @@ -34,7 +35,7 @@ pub fn extract( frame_interval, spritesheet_path, "preview", - format + format, ); let mut stream: AVStream = avformat_context @@ -120,7 +121,7 @@ pub fn extract( format_err!("Could not init output frame: {}", error) })?; scale_context - .reinit(&frame, &output_frame, scaler) + .reinit(&frame, &output_frame, scaler, flags) .map_err(|error| { format_err!("Could not reinit scale context: {}", error) })?; diff --git a/src/ingest/spritesheet.rs b/src/ingest/spritesheet.rs index 5771668..6fa2853 100644 --- a/src/ingest/spritesheet.rs +++ b/src/ingest/spritesheet.rs @@ -31,7 +31,7 @@ impl SpritesheetManager { frame_interval: MediaTime, output_path: impl Into<PathBuf>, name: impl AsRef<str>, - format: impl AsRef<str> + format: impl AsRef<str>, ) -> SpritesheetManager { SpritesheetManager { num_horizontal, diff --git a/src/main.rs b/src/main.rs index 788a78b..60af827 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,8 +9,8 @@ use std::path::Path; use failure::Error; use structopt::StructOpt; +use crate::ffmpeg_api::enums::{SwsFlags, SwsScaler}; use crate::util::media_time::MediaTime; -use crate::ffmpeg_api::enums::SwsScaler; fn parse_scaler(src: &str) -> Result<SwsScaler, String> { match src { @@ -25,7 +25,7 @@ fn parse_scaler(src: &str) -> Result<SwsScaler, String> { "sinc" => Ok(SwsScaler::Sinc), "lanczos" => Ok(SwsScaler::Lanczos), "spline" => Ok(SwsScaler::Spline), - _ => Err(format!("Invalid scaler: {}", src)) + _ => Err(format!("Invalid scaler: {}", src)), } } @@ -46,11 +46,28 @@ struct Options { format: String, #[structopt(long = "scaler", default_value = "bilinear", parse(try_from_str = parse_scaler))] scaler: SwsScaler, + #[structopt(long = "accurate-chroma")] + accurate_chroma: bool, + #[structopt(long = "accurate-rounding")] + accurate_rounding: bool, + #[structopt(long = "accurate-scaling")] + accurate_scaling: bool, } fn main() -> Result<(), Error> { let options = Options::from_args(); + let mut flags = SwsFlags::empty(); + if options.accurate_chroma { + flags |= SwsFlags::FULL_CHROMA_INTERPOLATION | SwsFlags::FULL_CHROMA_INPUT; + } + if options.accurate_rounding { + flags |= SwsFlags::ACCURATE_ROUNDING; + } + if options.accurate_scaling { + flags |= SwsFlags::BIT_EXACT_SCALING; + } + ingest::extract::extract( options.max_size, options.num_horizontal, @@ -60,6 +77,7 @@ fn main() -> Result<(), Error> { Path::new(&options.output), options.format, options.scaler, + flags, )?; Ok(()) -- GitLab