Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VapourSynth API Integration #24

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ rfd = "0.11.0" # open file dialog
which = "4.4.0" # Get-Command / where.exe / which alternative
# rustsynth = "0.2.1" # wrapper for VapourSynth.dll
rustsynth = {git = "https://github.com/animafps/rustsynth"}
rustsynth-derive = {git = "https://github.com/animafps/rustsynth"}

# json stuff
serde = "1.0.152"
Expand Down
4 changes: 4 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ pub struct Arguments {
/// Override recipe setting(s), e.g: --ov "flowblur;amount;40" "misc;container;MKV"
#[clap(visible_alias="ov", visible_alias="overide", long, num_args=1..)]
pub r#override: Option<Vec<String>>,

/// Specify a recipe path
#[clap(visible_alias = "rs_exp", long, default_value_t = false)]
pub render_experimental: bool,
}

pub fn setup_args() -> Arguments {
Expand Down
2 changes: 1 addition & 1 deletion src/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::video::Payload;
use crate::verb;
use std::env;

#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct SmCommand {
pub vs_path: String,
pub vs_args: Vec<String>,
Expand Down
17 changes: 15 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ fn main() {
|| env::var("NO_SMOOTHIE_WIN32").is_ok();
// user is neither running Windows Terminal and alacritty, OR has NO_SMOOTHIE_WIN32 defined

#[cfg(target_os = "windows")]
if args.tui
&& is_conhost
&& cfg!(target_os = "windows")
&& !recipe.get_bool("miscellaneous", "always verbose")
&& !args.verbose
{
Expand All @@ -65,7 +65,20 @@ fn main() {

let payloads: Vec<Payload> = video::resolve_input(&mut args, &recipe);

let experimental = args.render_experimental;

let vpy = args.vpy.exists();
let vpy_path = args.vpy.clone();

let commands: Vec<SmCommand> = cmd::build_commands(args, payloads, recipe);

render::_vpipe_render2(commands);
if experimental {
if vpy {
render::api_vpy_render(commands, vpy_path);
} else {
render::api_render(commands);
}
} else {
render::_vpipe_render2(commands);
}
}
66 changes: 65 additions & 1 deletion src/render.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
use std::io::prelude::*;
use std::io::BufReader;
use std::path::PathBuf;

use crate::cmd::SmCommand;

use crate::vapoursynth::output::{output, OutputParameters};
use regex::Regex;
use rustsynth::core::CoreCreationFlags;
use rustsynth::core::CoreRef;
use rustsynth::node::Node;
use rustsynth::vsscript::Environment;
use rustsynth_derive::init_plugins;
use std::process::{ChildStderr, Command, Stdio};

use crate::{ffpb2, verb};
Expand Down Expand Up @@ -219,3 +225,61 @@ pub fn _vpipe_render2(commands: Vec<SmCommand>) {
}
}
}

pub fn api_vpy_render(commands: Vec<SmCommand>, path: PathBuf) {
let core = CoreRef::new(CoreCreationFlags::NONE);
for cmd in commands {
let mut env = Environment::new(&core).unwrap();
env.eval_file(&path).unwrap();
let clip = env.get_output(0).unwrap();
render_node(cmd, clip, &core)
}
}

pub fn api_render(commands: Vec<SmCommand>) {
let core = CoreRef::new(CoreCreationFlags::NONE);

init_plugins!();

for cmd in commands {

let clip =
Plugins::ffms2::Source(&core, cmd.payload.in_path.to_str().unwrap().to_owned())
.get_node("clip")
.unwrap();

render_node(cmd, clip, &core);
}
}

pub fn render_node(cmd: SmCommand, clip: Node, core: &CoreRef) {
let num_frames = clip.video_info().unwrap().num_frames as usize;

let mut ffmpeg = Command::new(cmd.ff_path)
.args(cmd.ff_args)
.stdin(std::process::Stdio::piped())
.stdout(Stdio::inherit())
.stderr(std::process::Stdio::piped())
.spawn()
.expect("Failed in spawning FFmpeg child");
let ffpipe = ffmpeg.stdin.take().unwrap();

let ff_stats = ffmpeg.stderr.take().expect("Failed capturing FFmpeg");

output(
ffpipe,
None,
OutputParameters {
y4m: true,
node: clip,
start_frame: 0,
end_frame: num_frames - 1,
requests: core.info().num_threads,
},
)
.expect("Failed outputting with output");

ffpb2::ffmpeg2(ff_stats).expect("Failed rendering ffmpeg");

ffmpeg.wait().unwrap();
}
1 change: 1 addition & 0 deletions src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::recipe::Recipe;
use std::env;
#[cfg(windows)]
use std::ffi::c_int;

#[cfg(windows)]
Expand Down
88 changes: 71 additions & 17 deletions src/vapoursynth/havsfunc.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
use rustsynth::{
core::CoreRef,
function::Function,
node::Node,
owned_map,
prelude::{Map, API},
core::CoreRef, format::SampleType, function::Function, node::Node, owned_map, prelude::Map,
};

pub fn _change_fps<'elem, 'core: 'elem>(
api: API,
core: CoreRef<'core>,
clip: Node<'core>,
fpsnum: f64,
Expand All @@ -17,31 +12,90 @@ pub fn _change_fps<'elem, 'core: 'elem>(
* (clip.video_info().unwrap().fps_den as f64 / clip.video_info().unwrap().fps_num as f64);

let length = (clip.video_info().unwrap().num_frames as f64 * factor).floor();
let adjust_frame = move |api: API,
core: CoreRef<'core>,
in_map: &Map<'core>,
out: &mut Map<'core>| {
let adjust_frame = move |core: CoreRef<'core>, in_map: &Map<'core>, out: &mut Map<'core>| {
let n = in_map.get_int("n").unwrap();
let real_n = (n as f64 / factor).floor();
let std = core.plugin_by_namespace("std").unwrap();
let in_args = owned_map!(api, { "clip": &clip }, { "first": &real_n }, {
"last": &real_n
});
let in_args = owned_map!({ "clip": &clip }, { "first": &real_n }, { "last": &real_n });
let trim = std.invoke("Trim", &in_args);
let one_frame_clip: Node = trim.get("clip").unwrap();
let in_args = owned_map!(api, {"clip": &one_frame_clip}, {"factor": &(clip.video_info().unwrap().num_frames as i64 + 100)});
let in_args = owned_map!({"clip": &one_frame_clip}, {"factor": &(clip.video_info().unwrap().num_frames as i64 + 100)});
let one_frame_clip = std.invoke("Loop", &in_args);
let node = one_frame_clip.get_node("clip").unwrap();
out.set_node("clip", &node).unwrap();
};
let adjust_frame = Function::new(core, adjust_frame);
let std = core.plugin_by_namespace("std").unwrap();
let in_args = owned_map!(api, { "length": &length }, { "fpsnum": &fpsnum }, {
let in_args = owned_map!({ "length": &length }, { "fpsnum": &fpsnum }, {
"fpsden": &fpsden
});
let blank = std.invoke("BlankClip", &in_args);
let in_args =
owned_map!(api, {"eval": &adjust_frame}, {"clip": &blank.get_node("clip").unwrap()});
let in_args = owned_map!({"eval": &adjust_frame}, {"clip": &blank.get_node("clip").unwrap()});
let eval = std.invoke("FrameEval", &in_args);
eval.get_node("clip").unwrap()
}

pub fn inter_frame<'elem, 'core: 'elem>(
core: CoreRef<'core>,
clip: Node<'core>,
params: InterFrameParams,
) -> Result<Node<'elem>, &'static str> {
let info = clip.video_info().unwrap();

let sw = info.format.sub_sampling_w;
let sh = info.format.sub_sampling_h;
let depth = info.format.bits_per_sample;
if sw != 1 && sh != 1 && !vec![8, 10].contains(&depth) {
return Err("InterFrame: This is not a clip");
}
let oInput = clip;
// let clip = vsdepth(clip, 8);
// Validate inputs
let preset = params.Preset.to_lowercase();
let tuning = params.Tuning.to_lowercase();
if !["medium", "fast", "faster", "fastest"].contains(&preset.as_str()) {
return Err("");
}
if !["film", "smooth", "animation", "weak"].contains(&tuning.as_str()) {
return Err("");
}
todo!()
}

pub struct InterFrameParams {
Preset: String,
Tuning: String,
NewNum: Option<i64>,
NewDen: i64,
GPU: bool,
gpuid: i64,
OverrideAlgo: Option<String>,
OverrideArea: Option<String>,
FrameDouble: bool,
}

impl Default for InterFrameParams {
fn default() -> Self {
Self {
Preset: String::from("Medium"),
Tuning: String::from("Film"),
NewNum: None,
NewDen: 1,
GPU: true,
gpuid: 1,
OverrideAlgo: None,
OverrideArea: None,
FrameDouble: false,
}
}
}

pub fn vsdepth(clip: Node, bitdepth: i64) -> Node {
let info = clip.video_info().unwrap();
let curr_depth = info.format.bits_per_sample as i64;
let sample_type = SampleType::Integer;
if (curr_depth, info.format.sample_type) == (bitdepth, sample_type) {
return clip;
}
todo!()
}
1 change: 0 additions & 1 deletion src/vapoursynth/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
pub mod havsfunc;
#[allow(unused)]
pub mod output;
8 changes: 4 additions & 4 deletions src/vapoursynth/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use std::{
cmp,
collections::HashMap,
fs::File,
io::Write,
process::ChildStdin,
io::{Cursor, Write},
process::{ChildStdin, Stdio},
sync::{Arc, Condvar, Mutex},
time::Instant,
};
Expand Down Expand Up @@ -303,8 +303,8 @@ fn frame_done_callback<'core, T: Write + Send + 'core>(
}
}

pub fn output(
mut output_target: ChildStdin,
pub fn output<T: std::io::Write + std::marker::Send>(
mut output_target: T,
mut timecodes_file: Option<File>,
parameters: OutputParameters,
) -> Result<(), Error> {
Expand Down