diff --git a/Cargo.lock b/Cargo.lock index 7b663f38e5fa0d923cfe42c53cdcb47044a2d4b4..fc4140e1fcaa11658a1a81d720942bf3969b5e98 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 65a703f36548e46fce3931c01432328c975274b5..b446c7f895ef390a9f5ff6ab3dff94fc2f4ccecd 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 51df241ebe23ef36abe9890d205fe4678e1fa906..d2a973197abc4f4de4a7b71aaacd97f4ab7a69cd 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 4cd29652ec25ee10a20de9fa5df99865352acc0d..e2b108e6c0a9e363d49cd9b441ab59c48dc28d6a 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 0c29b0c982c5ca0f5db52bfd8cb852a9c672b2d4..658cf09636d7a2cb79eb0e986c24a3395cc92ca3 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 5771668fd0dfa74bb2784141f23e7f3a36d5dcf1..6fa28539d5947c145b21994ea89ace4ede139d28 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 788a78b97b87fc79992f29b4d6aa7fa95556f0fc..60af827fd69eb5c77fc26e2476eca57524b46423 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(())