initial commit

master
kageru 4 years ago
commit cf9c084cba
Signed by: kageru
GPG Key ID: 8282A2BEA4ADA3D2

@ -0,0 +1,12 @@
[package]
name = "adaptivegrain-rs"
version = "0.1.0"
authors = ["kageru"]
edition = "2018"
[dependencies]
failure = "0.1"
vapoursynth = { path = "vapoursynth" }
[lib]
crate-type = ["cdylib"]

@ -0,0 +1,95 @@
#[macro_use]
extern crate failure;
#[macro_use]
extern crate vapoursynth;
use vapoursynth::core::CoreRef;
use vapoursynth::map::Map;
use vapoursynth::video_info::VideoInfo;
use failure::Error;
use vapoursynth::node::Node;
use vapoursynth::plugins::{Filter, FilterArgument, FrameContext, Metadata};
use vapoursynth::api::API;
use vapoursynth::frame::{FrameRef, FrameRefMut};
const PLUGIN_NAME: &str = "adaptivegrain";
const PLUGIN_IDENTIFIER: &str = "moe.kageru.adaptivegrain";
struct AdaptiveGrain<'core> {
source: Node<'core>
}
impl<'core> Filter<'core> for AdaptiveGrain<'core> {
fn video_info(&self, _api: API, _core: CoreRef<'core>) -> Vec<VideoInfo<'core>> {
vec![self.source.info()]
}
fn get_frame_initial(
&self,
_api: API,
_core: CoreRef<'core>,
context: FrameContext,
n: usize,
) -> Result<Option<FrameRef<'core>>, Error> {
self.source.request_frame_filter(context, n);
Ok(None)
}
fn get_frame(
&self,
_api: API,
core: CoreRef<'core>,
context: FrameContext,
n: usize,
) -> Result<FrameRef<'core>, Error> {
let frame = self.source
.get_frame_filter(context, n)
.ok_or_else(|| format_err!("Could not retrieve source frame. This shouldnt happen."))?;
let average = match frame.props().get::<f64>("PlaneStatsAverage") {
Ok(average) => (average * 256.0) as u8,
Err(_) => panic!(PLUGIN_NAME.to_owned() + ": You need to run std.PlaneStats on the clip before calling this function.")
};
let mut frame = FrameRefMut::copy_of(core, &frame);
for plane in 0..frame.format().plane_count() {
for row in 0..frame.height(plane) {
for pixel in frame.plane_row_mut::<u8>(plane, row) {
*pixel = average;
}
}
}
Ok(frame.into())
}
}
make_filter_function! {
AdaptiveGrainFunction, "AdaptiveGrain"
fn create_adaptivegrain<'core>(
_api: API,
_core: CoreRef<'core>,
clip: Node<'core>,
) -> Result<Option<Box<Filter<'core> + 'core>>, Error> {
Ok(Some(Box::new(AdaptiveGrain { source: clip })))
}
}
export_vapoursynth_plugin! {
Metadata {
identifier: PLUGIN_IDENTIFIER,
namespace: "adg",
name: "Adaptive grain",
read_only: false,
},
[
AdaptiveGrainFunction::new()
]
}
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}

@ -0,0 +1,3 @@
[submodule "source-files/vapoursynth"]
path = source-files/vapoursynth
url = https://github.com/vapoursynth/vapoursynth.git

@ -0,0 +1,24 @@
### v0.2.1 (16th Jun 2018)
- Added missing plugin-related types
- Silenced some clippy warnings
## v0.2.0 (24th Mar 2018)
- Added support for targetting 32-bit Windows
- Added automatic detection of common Windows VapourSynth library dirs
### v0.1.4 (11th Mar 2018)
- Added an AppVeyor badge
- Added a link to vapoursynth-rs in the README
### v0.1.3 (18th Feb 2018)
- Added a docs.rs badge to the README
- Added CHANGELOG.md
### v0.1.2 (18th Feb 2018)
- Changed the documentation to be hosted at docs.rs
### v0.1.1 (2nd Feb 2018)
- Added new bindings from VSScript API 3.2
## v0.1.0
- Initial release

@ -0,0 +1,59 @@
[package]
name = "vapoursynth-sys"
version = "0.2.2" # remember to update html_root_url
authors = ["Ivan Molodetskikh <yalterz@gmail.com>"]
description = "Rust bindings for vapoursynth and vsscript."
license = "MIT/Apache-2.0"
build = "build.rs"
readme = "README.md"
documentation = "https://docs.rs/vapoursynth-sys"
repository = "https://github.com/YaLTeR/vapoursynth-rs"
keywords = ["vapoursynth", "vsscript", "video", "bindings"]
categories = ["api-bindings", "external-ffi-bindings", "multimedia::video"]
[badges]
travis-ci = { repository = "YaLTeR/vapoursynth-rs" }
appveyor = { repository = "YaLTeR/vapoursynth-rs" }
[dependencies]
cfg-if = "0.1"
[features]
# Features for enabling higher API versions.
vapoursynth-api-31 = ["gte-vapoursynth-api-31"]
vapoursynth-api-32 = ["gte-vapoursynth-api-31", "gte-vapoursynth-api-32"]
vapoursynth-api-33 = ["gte-vapoursynth-api-31", "gte-vapoursynth-api-32", "gte-vapoursynth-api-33"]
vapoursynth-api-34 = [
"gte-vapoursynth-api-31",
"gte-vapoursynth-api-32",
"gte-vapoursynth-api-33",
"gte-vapoursynth-api-34"
]
vapoursynth-api-35 = [
"gte-vapoursynth-api-31",
"gte-vapoursynth-api-32",
"gte-vapoursynth-api-33",
"gte-vapoursynth-api-34",
"gte-vapoursynth-api-35"
]
vsscript-api-31 = ["gte-vsscript-api-31"]
vsscript-api-32 = ["gte-vsscript-api-31", "gte-vsscript-api-32"]
# Features for linking to certain functions.
vapoursynth-functions = []
vsscript-functions = []
# Utility features, not for outside use.
gte-vapoursynth-api-31 = []
gte-vapoursynth-api-32 = []
gte-vapoursynth-api-33 = []
gte-vapoursynth-api-34 = []
gte-vapoursynth-api-35 = []
gte-vsscript-api-31 = []
gte-vsscript-api-32 = []
[package.metadata.docs.rs]
features = ["vapoursynth-api-35", "vsscript-api-32", "vapoursynth-functions", "vsscript-functions"]

@ -0,0 +1 @@
../LICENSE-APACHE

@ -0,0 +1 @@
../LICENSE-MIT

@ -0,0 +1,43 @@
# vapoursynth-sys
[![crates.io](https://img.shields.io/crates/v/vapoursynth-sys.svg)](https://crates.io/crates/vapoursynth-sys)
[![Documentation](https://docs.rs/vapoursynth-sys/badge.svg)](https://docs.rs/vapoursynth-sys)
[ChangeLog](https://github.com/YaLTeR/vapoursynth-rs/blob/master/vapoursynth-sys/CHANGELOG.md)
Raw bindings to [VapourSynth](https://github.com/vapoursynth/vapoursynth).
Check out [vapoursynth-rs](https://crates.io/crates/vapoursynth) for a safe Rust wrapper.
## Supported Versions
All VapourSynth and VSScript API versions starting with 3.0 are supported. By default the crates use the 3.0 feature set. To enable higher API version support, enable one of the following Cargo features:
* `vapoursynth-api-31` for VapourSynth API 3.1
* `vapoursynth-api-32` for VapourSynth API 3.2
* `vapoursynth-api-33` for VapourSynth API 3.3
* `vapoursynth-api-34` for VapourSynth API 3.4
* `vapoursynth-api-35` for VapourSynth API 3.5
* `vsscript-api-31` for VSScript API 3.1
* `vsscript-api-32` for VSScript API 3.2
To enable linking to VapourSynth or VSScript functions, enable the following Cargo features:
* `vapoursynth-functions` for VapourSynth functions (`getVapourSynthAPI()`)
* `vsscript-functions` for VSScript functions (`vsscript_*()`)
## Building
Make sure you have the corresponding libraries available if you enable the linking features. You can use the `VAPOURSYNTH_LIB_DIR` environment variable to specify a custom directory with the library files.
On Windows the easiest way is to use the VapourSynth installer (make sure the VapourSynth SDK is checked). The crate should pick up the library directory automatically. If it doesn't or if you're cross-compiling, set `VAPOURSYNTH_LIB_DIR` to `<path to the VapourSynth installation>\sdk\lib64` or `<...>\lib32`, depending on the target bitness.
## License
Licensed under either of
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.

@ -0,0 +1,67 @@
use std::env;
use std::path::PathBuf;
const LIBRARY_DIR_VARIABLE: &str = "VAPOURSYNTH_LIB_DIR";
fn main() {
// Make sure the build script is re-run if our env variable is changed.
println!("cargo:rerun-if-env-changed={}", LIBRARY_DIR_VARIABLE);
let windows = env::var("TARGET").unwrap().contains("windows");
// Get the default library dir on Windows.
let default_library_dir = if windows {
get_default_library_dir()
} else {
None
};
// Library directory override or the default dir on windows.
if let Some(dir) = env::var(LIBRARY_DIR_VARIABLE).ok().or(default_library_dir) {
println!("cargo:rustc-link-search=native={}", dir);
}
// Handle linking to VapourSynth libs.
if env::var("CARGO_FEATURE_VAPOURSYNTH_FUNCTIONS").is_ok() {
println!("cargo:rustc-link-lib=vapoursynth");
}
if env::var("CARGO_FEATURE_VSSCRIPT_FUNCTIONS").is_ok() {
let vsscript_lib_name = if windows {
"vsscript"
} else {
"vapoursynth-script"
};
println!("cargo:rustc-link-lib={}", vsscript_lib_name);
}
}
// Returns the default library dir on Windows.
// The default dir is where the VapourSynth installer puts the libraries.
fn get_default_library_dir() -> Option<String> {
let host = env::var("HOST").ok()?;
// If the host isn't Windows we don't have %programfiles%.
if !host.contains("windows") {
return None;
}
let programfiles = if host.starts_with("i686") {
env::var("programfiles")
} else {
env::var("programfiles(x86)")
};
let suffix = if env::var("TARGET").ok()?.starts_with("i686") {
"lib32"
} else {
"lib64"
};
let mut path = PathBuf::from(programfiles.ok()?);
path.push("VapourSynth");
path.push("sdk");
path.push(suffix);
path.to_str().map(|s| s.to_owned())
}

@ -0,0 +1,24 @@
#!/bin/sh
bindgen --whitelist-function 'getVapourSynthAPI' \
--whitelist-function 'vsscript.*' \
--whitelist-type 'VSColorFamily' \
--whitelist-type 'VSSampleType' \
--whitelist-type 'VSPresetFormat' \
--whitelist-type 'VSFilterMode' \
--whitelist-type 'VSNodeFlags' \
--whitelist-type 'VSPropTypes' \
--whitelist-type 'VSGetPropErrors' \
--whitelist-type 'VSPropAppendMode' \
--whitelist-type 'VSActivationReason' \
--whitelist-type 'VSMessageType' \
--whitelist-type 'VSEvalFlags' \
--whitelist-type 'VSInitPlugin' \
--blacklist-type '__int64_t' \
--blacklist-type '__uint8_t' \
--bitfield-enum 'VSNodeFlags' \
--rustified-enum 'VS[^N].*' \
--no-layout-tests \
-o bindings.rs \
vapoursynth/include/VSScript.h \
-- -target x86_64-unknown-windows-unknown

@ -0,0 +1 @@
#include "vapoursynth/include/VSScript.h"

@ -0,0 +1,564 @@
use std::os::raw::*;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct VSFrameRef {
_unused: [u8; 0],
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct VSNodeRef {
_unused: [u8; 0],
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct VSCore {
_unused: [u8; 0],
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct VSPlugin {
_unused: [u8; 0],
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct VSNode {
_unused: [u8; 0],
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct VSFuncRef {
_unused: [u8; 0],
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct VSMap {
_unused: [u8; 0],
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct VSFrameContext {
_unused: [u8; 0],
}
#[cfg_attr(feature = "cargo-clippy", allow(unreadable_literal))]
#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum VSColorFamily {
cmGray = 1000000,
cmRGB = 2000000,
cmYUV = 3000000,
cmYCoCg = 4000000,
cmCompat = 9000000,
}
#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum VSSampleType {
stInteger = 0,
stFloat = 1,
}
#[cfg_attr(feature = "cargo-clippy", allow(unreadable_literal))]
#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum VSPresetFormat {
pfNone = 0,
pfGray8 = 1000010,
pfGray16 = 1000011,
pfGrayH = 1000012,
pfGrayS = 1000013,
pfYUV420P8 = 3000010,
pfYUV422P8 = 3000011,
pfYUV444P8 = 3000012,
pfYUV410P8 = 3000013,
pfYUV411P8 = 3000014,
pfYUV440P8 = 3000015,
pfYUV420P9 = 3000016,
pfYUV422P9 = 3000017,
pfYUV444P9 = 3000018,
pfYUV420P10 = 3000019,
pfYUV422P10 = 3000020,
pfYUV444P10 = 3000021,
pfYUV420P16 = 3000022,
pfYUV422P16 = 3000023,
pfYUV444P16 = 3000024,
pfYUV444PH = 3000025,
pfYUV444PS = 3000026,
pfYUV420P12 = 3000027,
pfYUV422P12 = 3000028,
pfYUV444P12 = 3000029,
pfYUV420P14 = 3000030,
pfYUV422P14 = 3000031,
pfYUV444P14 = 3000032,
pfRGB24 = 2000010,
pfRGB27 = 2000011,
pfRGB30 = 2000012,
pfRGB48 = 2000013,
pfRGBH = 2000014,
pfRGBS = 2000015,
pfCompatBGR32 = 9000010,
pfCompatYUY2 = 9000011,
}
#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum VSFilterMode {
fmParallel = 100,
fmParallelRequests = 200,
fmUnordered = 300,
fmSerial = 400,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct VSFormat {
pub name: [c_char; 32usize],
pub id: c_int,
pub colorFamily: c_int,
pub sampleType: c_int,
pub bitsPerSample: c_int,
pub bytesPerSample: c_int,
pub subSamplingW: c_int,
pub subSamplingH: c_int,
pub numPlanes: c_int,
}
pub const VSNodeFlags_nfNoCache: VSNodeFlags = VSNodeFlags(1);
pub const VSNodeFlags_nfIsCache: VSNodeFlags = VSNodeFlags(2);
#[cfg(feature = "gte-vapoursynth-api-33")]
pub const VSNodeFlags_nfMakeLinear: VSNodeFlags = VSNodeFlags(4);
impl ::std::ops::BitOr<VSNodeFlags> for VSNodeFlags {
type Output = Self;
#[inline]
fn bitor(self, other: Self) -> Self {
VSNodeFlags(self.0 | other.0)
}
}
impl ::std::ops::BitOrAssign for VSNodeFlags {
#[inline]
fn bitor_assign(&mut self, rhs: VSNodeFlags) {
self.0 |= rhs.0;
}
}
impl ::std::ops::BitAnd<VSNodeFlags> for VSNodeFlags {
type Output = Self;
#[inline]
fn bitand(self, other: Self) -> Self {
VSNodeFlags(self.0 & other.0)
}
}
impl ::std::ops::BitAndAssign for VSNodeFlags {
#[inline]
fn bitand_assign(&mut self, rhs: VSNodeFlags) {
self.0 &= rhs.0;
}
}
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct VSNodeFlags(pub c_int);
#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum VSPropTypes {
ptUnset = 117,
ptInt = 105,
ptFloat = 102,
ptData = 115,
ptNode = 99,
ptFrame = 118,
ptFunction = 109,
}
#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum VSGetPropErrors {
peUnset = 1,
peType = 2,
peIndex = 4,
}
#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum VSPropAppendMode {
paReplace = 0,
paAppend = 1,
paTouch = 2,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct VSCoreInfo {
pub versionString: *const c_char,
pub core: c_int,
pub api: c_int,
pub numThreads: c_int,
pub maxFramebufferSize: i64,
pub usedFramebufferSize: i64,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct VSVideoInfo {
pub format: *const VSFormat,
pub fpsNum: i64,
pub fpsDen: i64,
pub width: c_int,
pub height: c_int,
pub numFrames: c_int,
pub flags: c_int,
}
#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum VSActivationReason {
arInitial = 0,
arFrameReady = 1,
arAllFramesReady = 2,
arError = -1,
}
#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum VSMessageType {
mtDebug = 0,
mtWarning = 1,
mtCritical = 2,
mtFatal = 3,
}
pub type VSPublicFunction = unsafe extern "system" fn(
in_: *const VSMap,
out: *mut VSMap,
userData: *mut c_void,
core: *mut VSCore,
vsapi: *const VSAPI,
);
pub type VSRegisterFunction = unsafe extern "system" fn(
name: *const c_char,
args: *const c_char,
argsFunc: VSPublicFunction,
functionData: *mut c_void,
plugin: *mut VSPlugin,
);
pub type VSConfigPlugin = unsafe extern "system" fn(
identifier: *const c_char,
defaultNamespace: *const c_char,
name: *const c_char,
apiVersion: c_int,
readonly: c_int,
plugin: *mut VSPlugin,
);
pub type VSInitPlugin = Option<
unsafe extern "system" fn(
configFunc: VSConfigPlugin,
registerFunc: VSRegisterFunction,
plugin: *mut VSPlugin,
),
>;
pub type VSFreeFuncData = Option<unsafe extern "system" fn(userData: *mut c_void)>;
pub type VSFilterInit = unsafe extern "system" fn(
in_: *mut VSMap,
out: *mut VSMap,
instanceData: *mut *mut c_void,
node: *mut VSNode,
core: *mut VSCore,
vsapi: *const VSAPI,
);
pub type VSFilterGetFrame = unsafe extern "system" fn(
n: c_int,
activationReason: c_int,
instanceData: *mut *mut c_void,
frameData: *mut *mut c_void,
frameCtx: *mut VSFrameContext,
core: *mut VSCore,
vsapi: *const VSAPI,
) -> *const VSFrameRef;
pub type VSFilterFree = Option<
unsafe extern "system" fn(instanceData: *mut c_void, core: *mut VSCore, vsapi: *const VSAPI),
>;
pub type VSFrameDoneCallback = Option<
unsafe extern "system" fn(
userData: *mut c_void,
f: *const VSFrameRef,
n: c_int,
arg1: *mut VSNodeRef,
errorMsg: *const c_char,
),
>;
pub type VSMessageHandler =
Option<unsafe extern "system" fn(msgType: c_int, msg: *const c_char, userData: *mut c_void)>;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct VSAPI {
pub createCore: unsafe extern "system" fn(threads: c_int) -> *mut VSCore,
pub freeCore: unsafe extern "system" fn(core: *mut VSCore),
pub getCoreInfo: unsafe extern "system" fn(core: *mut VSCore) -> *const VSCoreInfo,
pub cloneFrameRef: unsafe extern "system" fn(f: *const VSFrameRef) -> *const VSFrameRef,
pub cloneNodeRef: unsafe extern "system" fn(node: *mut VSNodeRef) -> *mut VSNodeRef,
pub cloneFuncRef: unsafe extern "system" fn(f: *mut VSFuncRef) -> *mut VSFuncRef,
pub freeFrame: unsafe extern "system" fn(f: *const VSFrameRef),
pub freeNode: unsafe extern "system" fn(node: *mut VSNodeRef),
pub freeFunc: unsafe extern "system" fn(f: *mut VSFuncRef),
pub newVideoFrame: unsafe extern "system" fn(
format: *const VSFormat,
width: c_int,
height: c_int,
propSrc: *const VSFrameRef,
core: *mut VSCore,
) -> *mut VSFrameRef,
pub copyFrame:
unsafe extern "system" fn(f: *const VSFrameRef, core: *mut VSCore) -> *mut VSFrameRef,
pub copyFrameProps:
unsafe extern "system" fn(src: *const VSFrameRef, dst: *mut VSFrameRef, core: *mut VSCore),
pub registerFunction: unsafe extern "system" fn(
name: *const c_char,
args: *const c_char,
argsFunc: VSPublicFunction,
functionData: *mut c_void,
plugin: *mut VSPlugin,
),
pub getPluginById:
unsafe extern "system" fn(identifier: *const c_char, core: *mut VSCore) -> *mut VSPlugin,
pub getPluginByNs:
unsafe extern "system" fn(ns: *const c_char, core: *mut VSCore) -> *mut VSPlugin,
pub getPlugins: unsafe extern "system" fn(core: *mut VSCore) -> *mut VSMap,
pub getFunctions: unsafe extern "system" fn(plugin: *mut VSPlugin) -> *mut VSMap,
#[cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
pub createFilter: unsafe extern "system" fn(
in_: *const VSMap,
out: *mut VSMap,
name: *const c_char,
init: VSFilterInit,
getFrame: VSFilterGetFrame,
free: VSFilterFree,
filterMode: c_int,
flags: c_int,
instanceData: *mut c_void,
core: *mut VSCore,
),
pub setError: unsafe extern "system" fn(map: *mut VSMap, errorMessage: *const c_char),
pub getError: unsafe extern "system" fn(map: *const VSMap) -> *const c_char,
pub setFilterError:
unsafe extern "system" fn(errorMessage: *const c_char, frameCtx: *mut VSFrameContext),
pub invoke:
unsafe extern "system" fn(plugin: *mut VSPlugin, name: *const c_char, args: *const VSMap)
-> *mut VSMap,
pub getFormatPreset: unsafe extern "system" fn(id: c_int, core: *mut VSCore) -> *const VSFormat,
pub registerFormat: unsafe extern "system" fn(
colorFamily: c_int,
sampleType: c_int,
bitsPerSample: c_int,
subSamplingW: c_int,
subSamplingH: c_int,
core: *mut VSCore,
) -> *const VSFormat,
pub getFrame: unsafe extern "system" fn(
n: c_int,
node: *mut VSNodeRef,
errorMsg: *mut c_char,
bufSize: c_int,
) -> *const VSFrameRef,
pub getFrameAsync: unsafe extern "system" fn(
n: c_int,
node: *mut VSNodeRef,
callback: VSFrameDoneCallback,
userData: *mut c_void,
),
pub getFrameFilter:
unsafe extern "system" fn(n: c_int, node: *mut VSNodeRef, frameCtx: *mut VSFrameContext)
-> *const VSFrameRef,
pub requestFrameFilter:
unsafe extern "system" fn(n: c_int, node: *mut VSNodeRef, frameCtx: *mut VSFrameContext),
pub queryCompletedFrame: unsafe extern "system" fn(
node: *mut *mut VSNodeRef,
n: *mut c_int,
frameCtx: *mut VSFrameContext,
),
pub releaseFrameEarly:
unsafe extern "system" fn(node: *mut VSNodeRef, n: c_int, frameCtx: *mut VSFrameContext),
pub getStride: unsafe extern "system" fn(f: *const VSFrameRef, plane: c_int) -> c_int,
pub getReadPtr: unsafe extern "system" fn(f: *const VSFrameRef, plane: c_int) -> *const u8,
pub getWritePtr: unsafe extern "system" fn(f: *mut VSFrameRef, plane: c_int) -> *mut u8,
pub createFunc: unsafe extern "system" fn(
func: VSPublicFunction,
userData: *mut c_void,
free: VSFreeFuncData,
core: *mut VSCore,
vsapi: *const VSAPI,
) -> *mut VSFuncRef,
pub callFunc: unsafe extern "system" fn(
func: *mut VSFuncRef,
in_: *const VSMap,
out: *mut VSMap,
core: *mut VSCore,
vsapi: *const VSAPI,
),
pub createMap: unsafe extern "system" fn() -> *mut VSMap,
pub freeMap: unsafe extern "system" fn(map: *mut VSMap),
pub clearMap: unsafe extern "system" fn(map: *mut VSMap),
pub getVideoInfo: unsafe extern "system" fn(node: *mut VSNodeRef) -> *const VSVideoInfo,
pub setVideoInfo:
unsafe extern "system" fn(vi: *const VSVideoInfo, numOutputs: c_int, node: *mut VSNode),
pub getFrameFormat: unsafe extern "system" fn(f: *const VSFrameRef) -> *const VSFormat,
pub getFrameWidth: unsafe extern "system" fn(f: *const VSFrameRef, plane: c_int) -> c_int,
pub getFrameHeight: unsafe extern "system" fn(f: *const VSFrameRef, plane: c_int) -> c_int,
pub getFramePropsRO: unsafe extern "system" fn(f: *const VSFrameRef) -> *const VSMap,
pub getFramePropsRW: unsafe extern "system" fn(f: *mut VSFrameRef) -> *mut VSMap,
pub propNumKeys: unsafe extern "system" fn(map: *const VSMap) -> c_int,
pub propGetKey: unsafe extern "system" fn(map: *const VSMap, index: c_int) -> *const c_char,
pub propNumElements: unsafe extern "system" fn(map: *const VSMap, key: *const c_char) -> c_int,
pub propGetType: unsafe extern "system" fn(map: *const VSMap, key: *const c_char) -> c_char,
pub propGetInt: unsafe extern "system" fn(
map: *const VSMap,
key: *const c_char,
index: c_int,
error: *mut c_int,
) -> i64,
pub propGetFloat: unsafe extern "system" fn(
map: *const VSMap,
key: *const c_char,
index: c_int,
error: *mut c_int,
) -> f64,
pub propGetData: unsafe extern "system" fn(
map: *const VSMap,
key: *const c_char,
index: c_int,
error: *mut c_int,
) -> *const c_char,
pub propGetDataSize: unsafe extern "system" fn(
map: *const VSMap,
key: *const c_char,
index: c_int,
error: *mut c_int,
) -> c_int,
pub propGetNode: unsafe extern "system" fn(
map: *const VSMap,
key: *const c_char,
index: c_int,
error: *mut c_int,
) -> *mut VSNodeRef,
pub propGetFrame: unsafe extern "system" fn(
map: *const VSMap,
key: *const c_char,
index: c_int,
error: *mut c_int,
) -> *const VSFrameRef,
pub propGetFunc: unsafe extern "system" fn(
map: *const VSMap,
key: *const c_char,
index: c_int,
error: *mut c_int,
) -> *mut VSFuncRef,
pub propDeleteKey: unsafe extern "system" fn(map: *mut VSMap, key: *const c_char) -> c_int,
pub propSetInt:
unsafe extern "system" fn(map: *mut VSMap, key: *const c_char, i: i64, append: c_int)
-> c_int,
pub propSetFloat:
unsafe extern "system" fn(map: *mut VSMap, key: *const c_char, d: f64, append: c_int)
-> c_int,
pub propSetData: unsafe extern "system" fn(
map: *mut VSMap,
key: *const c_char,
data: *const c_char,
size: c_int,
append: c_int,
) -> c_int,
pub propSetNode: unsafe extern "system" fn(
map: *mut VSMap,
key: *const c_char,
node: *mut VSNodeRef,
append: c_int,
) -> c_int,
pub propSetFrame: unsafe extern "system" fn(
map: *mut VSMap,
key: *const c_char,
f: *const VSFrameRef,
append: c_int,
) -> c_int,
pub propSetFunc: unsafe extern "system" fn(
map: *mut VSMap,
key: *const c_char,
func: *mut VSFuncRef,
append: c_int,
) -> c_int,
pub setMaxCacheSize: unsafe extern "system" fn(bytes: i64, core: *mut VSCore) -> i64,
pub getOutputIndex: unsafe extern "system" fn(frameCtx: *mut VSFrameContext) -> c_int,
pub newVideoFrame2: unsafe extern "system" fn(
format: *const VSFormat,
width: c_int,
height: c_int,
planeSrc: *mut *const VSFrameRef,
planes: *const c_int,
propSrc: *const VSFrameRef,
core: *mut VSCore,
) -> *mut VSFrameRef,
pub setMessageHandler:
unsafe extern "system" fn(handler: VSMessageHandler, userData: *mut c_void),
pub setThreadCount: unsafe extern "system" fn(threads: c_int, core: *mut VSCore) -> c_int,
pub getPluginPath: unsafe extern "system" fn(plugin: *const VSPlugin) -> *const c_char,
#[cfg(feature = "gte-vapoursynth-api-31")]
pub propGetIntArray:
unsafe extern "system" fn(map: *const VSMap, key: *const c_char, error: *mut c_int)
-> *const i64,
#[cfg(feature = "gte-vapoursynth-api-31")]
pub propGetFloatArray:
unsafe extern "system" fn(map: *const VSMap, key: *const c_char, error: *mut c_int)
-> *const f64,
#[cfg(feature = "gte-vapoursynth-api-31")]
pub propSetIntArray:
unsafe extern "system" fn(map: *mut VSMap, key: *const c_char, i: *const i64, size: c_int)
-> c_int,
#[cfg(feature = "gte-vapoursynth-api-31")]
pub propSetFloatArray:
unsafe extern "system" fn(map: *mut VSMap, key: *const c_char, d: *const f64, size: c_int)
-> c_int,
#[cfg(feature = "gte-vapoursynth-api-34")]
pub logMessage: unsafe extern "system" fn(msgType: c_int, msg: *const c_char),
}
#[cfg(feature = "vapoursynth-functions")]
extern "system" {
pub fn getVapourSynthAPI(version: c_int) -> *const VSAPI;
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct VSScript {
_unused: [u8; 0],
}
#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum VSEvalFlags {
efSetWorkingDir = 1,
}
#[cfg(feature = "vsscript-functions")]
extern "system" {
#[cfg(feature = "gte-vsscript-api-31")]
pub fn vsscript_getApiVersion() -> c_int;
pub fn vsscript_init() -> c_int;
pub fn vsscript_finalize() -> c_int;
pub fn vsscript_evaluateScript(
handle: *mut *mut VSScript,
script: *const c_char,
scriptFilename: *const c_char,
flags: c_int,
) -> c_int;
pub fn vsscript_evaluateFile(
handle: *mut *mut VSScript,
scriptFilename: *const c_char,
flags: c_int,
) -> c_int;
pub fn vsscript_createScript(handle: *mut *mut VSScript) -> c_int;
pub fn vsscript_freeScript(handle: *mut VSScript);
pub fn vsscript_getError(handle: *mut VSScript) -> *const c_char;
pub fn vsscript_getOutput(handle: *mut VSScript, index: c_int) -> *mut VSNodeRef;
#[cfg(feature = "gte-vsscript-api-31")]
pub fn vsscript_getOutput2(
handle: *mut VSScript,
index: c_int,
alpha: *mut *mut VSNodeRef,
) -> *mut VSNodeRef;
pub fn vsscript_clearOutput(handle: *mut VSScript, index: c_int) -> c_int;
pub fn vsscript_getCore(handle: *mut VSScript) -> *mut VSCore;
pub fn vsscript_getVSApi() -> *const VSAPI;
#[cfg(feature = "gte-vsscript-api-32")]
pub fn vsscript_getVSApi2(version: c_int) -> *const VSAPI;
pub fn vsscript_getVariable(
handle: *mut VSScript,
name: *const c_char,
dst: *mut VSMap,
) -> c_int;
pub fn vsscript_setVariable(handle: *mut VSScript, vars: *const VSMap) -> c_int;
pub fn vsscript_clearVariable(handle: *mut VSScript, name: *const c_char) -> c_int;
pub fn vsscript_clearEnvironment(handle: *mut VSScript);
}

@ -0,0 +1,43 @@
//! Raw bindings to [VapourSynth](https://github.com/vapoursynth/vapoursynth).
#![doc(html_root_url = "https://docs.rs/vapoursynth-sys/0.2.2")]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#[macro_use]
extern crate cfg_if;
mod bindings;
pub use bindings::*;
macro_rules! api_version {
($major:expr, $minor:expr) => {
($major << 16) | $minor
};
}
cfg_if! {
if #[cfg(feature="vapoursynth-api-35")] {
pub const VAPOURSYNTH_API_VERSION: i32 = api_version!(3, 5);
} else if #[cfg(feature="vapoursynth-api-34")] {
pub const VAPOURSYNTH_API_VERSION: i32 = api_version!(3, 4);
} else if #[cfg(feature="vapoursynth-api-33")] {
pub const VAPOURSYNTH_API_VERSION: i32 = api_version!(3, 3);
} else if #[cfg(feature="vapoursynth-api-32")] {
pub const VAPOURSYNTH_API_VERSION: i32 = api_version!(3, 2);
} else if #[cfg(feature="vapoursynth-api-31")] {
pub const VAPOURSYNTH_API_VERSION: i32 = api_version!(3, 1);
} else {
pub const VAPOURSYNTH_API_VERSION: i32 = api_version!(3, 0);
}
}
cfg_if! {
if #[cfg(feature="vsscript-api-32")] {
pub const VSSCRIPT_API_VERSION: i32 = api_version!(3, 2);
} else if #[cfg(feature="vsscript-api-31")] {
pub const VSSCRIPT_API_VERSION: i32 = api_version!(3, 1);
} else {
pub const VSSCRIPT_API_VERSION: i32 = api_version!(3, 0);
}
}

@ -0,0 +1,24 @@
## v0.2 (16th Jun 2018)
- Added plugin support! That includes:
- `plugins::{Metadata,Filter,FilterFunction}` types and traits for making plugins;
- `export_vapoursynth_plugin!` macro for exporting a VapourSynth plugin;
- `make_filter_function!` macro for making filters without much boilerplate.
- Added a sample plugin in the `sample-filter` folder.
- Added the `component::Component` trait and `Frame::plane*()` accessors for safely working with the pixel data without having to manually transmute slices, including an optional half-precision float support using the `half` crate.
- Added `plugin::Plugin` and other relevant APIs for enumerating plugins and invoking their functions.
- Added lifetime parameters to many types to fix soundness issues.
- Split `Frame` into `Frame`, `FrameRef`, `FrameRefMut`.
- Added the `map::Value` trait and generic `Map::{get,get_iter,set,append}()` functions.
- Added format caching in `Frame` to reduce the number of API calls needed.
- Added some convenience `From` impls.
### v0.1.2 (2nd Apr 2018)
- Fixed `Frame::data_row()` returning slices of incorrect rows (using the `plane` value instead of the `row` value).
### v0.1.1 (24th Mar 2018)
- Added support for targetting 32-bit Windows
- Added automatic detection of common Windows VapourSynth library dirs
- Fixed `Frame::data()` and `Frame::data_row()` returning slices of incorrect sizes (too short) for pixel formats with more than 1 byte per pixel
## v0.1.0
- Initial release

@ -0,0 +1,101 @@
[package]
name = "vapoursynth"
version = "0.2.0" # remember to update html_root_url
authors = ["Ivan Molodetskikh <yalterz@gmail.com>"]
description = "Safe Rust wrapper for VapourSynth and VSScript."
license = "MIT/Apache-2.0"
readme = "README.md"
documentation = "https://docs.rs/vapoursynth"
repository = "https://github.com/YaLTeR/vapoursynth-rs"
keywords = ["vapoursynth", "vsscript", "video", "bindings"]
categories = ["api-bindings", "external-ffi-bindings", "multimedia::video"]
[badges]
travis-ci = { repository = "YaLTeR/vapoursynth-rs" }
appveyor = { repository = "YaLTeR/vapoursynth-rs" }
[dependencies]
bitflags = "1"
failure = "0.1"
failure_derive = "0.1"
half = { version = "1", optional = true }
lazy_static = "1"
vapoursynth-sys = { version = "0.2", path = "../vapoursynth-sys" }
[dev-dependencies]
clap = "2"
lazy_static = "1"
num-rational = { version = "0.1", default-features = false }
[features]
# Enable the half::f16 type to be used for frame pixel data.
f16-pixel-type = ["half"]
# Features for enabling higher API versions.
vapoursynth-api-31 = [
"vapoursynth-sys/vapoursynth-api-31",
"gte-vapoursynth-api-31"
]
vapoursynth-api-32 = [
"vapoursynth-sys/vapoursynth-api-32",
"gte-vapoursynth-api-31",
"gte-vapoursynth-api-32"
]
vapoursynth-api-33 = [
"vapoursynth-sys/vapoursynth-api-33",
"gte-vapoursynth-api-31",
"gte-vapoursynth-api-32",
"gte-vapoursynth-api-33"
]
vapoursynth-api-34 = [
"vapoursynth-sys/vapoursynth-api-34",
"gte-vapoursynth-api-31",
"gte-vapoursynth-api-32",
"gte-vapoursynth-api-33",
"gte-vapoursynth-api-34"
]
vapoursynth-api-35 = [
"vapoursynth-sys/vapoursynth-api-35",
"gte-vapoursynth-api-31",
"gte-vapoursynth-api-32",
"gte-vapoursynth-api-33",
"gte-vapoursynth-api-34",
"gte-vapoursynth-api-35"
]
vsscript-api-31 = [
"vapoursynth-sys/vsscript-api-31",
"gte-vsscript-api-31"
]
vsscript-api-32 = [
"vapoursynth-sys/vsscript-api-32",
"gte-vsscript-api-31",
"gte-vsscript-api-32"
]
# Features for linking to certain functions.
vapoursynth-functions = ["vapoursynth-sys/vapoursynth-functions"]
vsscript-functions = ["vapoursynth-sys/vsscript-functions"]
# Utility features, not for outside use.
gte-vapoursynth-api-31 = []
gte-vapoursynth-api-32 = []
gte-vapoursynth-api-33 = []
gte-vapoursynth-api-34 = []
gte-vapoursynth-api-35 = []
gte-vsscript-api-31 = []
gte-vsscript-api-32 = []
# For development.
#default = ["vapoursynth-api-35", "vsscript-api-32", "vapoursynth-functions", "vsscript-functions"]
[package.metadata.docs.rs]
features = [
"vapoursynth-api-35",
"vsscript-api-32",
"vapoursynth-functions",
"vsscript-functions",
"f16-pixel-type"
]

@ -0,0 +1 @@
../LICENSE-APACHE

@ -0,0 +1 @@
../LICENSE-MIT

@ -0,0 +1 @@
../README.md

@ -0,0 +1,202 @@
#![allow(unused)]
#[macro_use]
extern crate failure;
extern crate vapoursynth;
use failure::{err_msg, Error, ResultExt};
use std::env;
use vapoursynth::prelude::*;
fn usage() {
println!(
"Usage:\n\t{} <script.vpy> [frame number]",
env::current_exe()
.ok()
.and_then(|p| p.file_name().map(|n| n.to_string_lossy().into_owned()))
.unwrap_or_else(|| "vpy-info".to_owned())
);
}
#[cfg(all(
feature = "vsscript-functions",
any(
feature = "vapoursynth-functions",
feature = "gte-vsscript-api-32"
)
))]
fn print_node_info(node: &Node) {
use std::fmt::Debug;
// Helper function for printing properties.
fn map_or_variable<T, F>(x: &Property<T>, f: F) -> String
where
T: Debug + Clone + Copy + Eq + PartialEq,
F: FnOnce(&T) -> String,
{
match *x {
Property::Variable => "variable".to_owned(),
Property::Constant(ref x) => f(x),
}
}
let info = node.info();
println!(
"Format: {}",
map_or_variable(&info.format, |x| x.name().to_owned())
);
println!(
"Resolution: {}",
map_or_variable(&info.resolution, |x| format!("{}×{}", x.width, x.height))
);
println!(
"Framerate: {}",
map_or_variable(&info.framerate, |x| format!(
"{}/{} ({})",
x.numerator,
x.denominator,
x.numerator as f64 / x.denominator as f64
))
);
#[cfg(feature = "gte-vapoursynth-api-32")]
println!("Frame count: {}", info.num_frames);
#[cfg(not(feature = "gte-vapoursynth-api-32"))]
println!(
"Frame count: {}",
map_or_variable(&info.num_frames, |x| format!("{}", x))
);
}
#[cfg(all(
feature = "vsscript-functions",
any(
feature = "vapoursynth-functions",
feature = "gte-vsscript-api-32"
)
))]
fn run() -> Result<(), Error> {
let filename = env::args()
.nth(1)
.ok_or_else(|| err_msg("The filename argument is missing"))?;
let environment =
vsscript::Environment::from_file(filename, vsscript::EvalFlags::SetWorkingDir)
.context("Couldn't create the VSScript environment")?;
let core = environment
.get_core()
.context("Couldn't get the VapourSynth core")?;
println!("{}", core.info());
#[cfg(feature = "gte-vsscript-api-31")]
let (node, alpha_node) = environment
.get_output(0)
.context("Couldn't get the output at index 0")?;
#[cfg(not(feature = "gte-vsscript-api-31"))]
let (node, alpha_node) = (
environment
.get_output(0)
.context("Couldn't get the output at index 0")?,
None::<Node>,
);
print_node_info(&node);
println!();
if let Some(alpha_node) = alpha_node {
println!("Alpha:");
print_node_info(&alpha_node);
} else {
println!("Alpha: No");
}
if let Some(n) = env::args().nth(2) {
let n = n
.parse::<usize>()
.context("Couldn't parse the frame number")?;
if n > i32::max_value() as usize {
bail!("Frame number is too big");
}
let frame = node.get_frame(n).context("Couldn't get the frame")?;
println!();
println!("Frame #{}", n);
let format = frame.format();
println!("Format: {}", format.name());
println!("Plane count: {}", format.plane_count());
let props = frame.props();
let count = props.key_count();
if count > 0 {
println!();
}
for k in 0..count {
let key = props.key(k);
macro_rules! print_value {
($func:ident) => {
println!(
"Property: {} => {:?}",
key,
props.$func(key).unwrap().collect::<Vec<_>>()
)
};
}
match props.value_type(key).unwrap() {
ValueType::Int => print_value!(get_int_iter),
ValueType::Float => print_value!(get_float_iter),
ValueType::Data => print_value!(get_data_iter),
ValueType::Node => print_value!(get_node_iter),
ValueType::Frame => print_value!(get_frame_iter),
ValueType::Function => print_value!(get_function_iter),
}
}
for plane in 0..format.plane_count() {
println!();
println!("Plane #{}", plane);
println!(
"Resolution: {}×{}",
frame.width(plane),
frame.height(plane)
);
println!("Stride: {}", frame.stride(plane));
}
}
Ok(())
}
#[cfg(not(all(
feature = "vsscript-functions",
any(
feature = "vapoursynth-functions",
feature = "gte-vsscript-api-32"
)
)))]
fn run() -> Result<(), Error> {
bail!(
"This example requires the `vsscript-functions` and either `vapoursynth-functions` or \
`vsscript-api-32` features."
)
}
fn main() {
if let Err(err) = run() {
eprintln!("Error: {}", err.cause());
for cause in err.causes().skip(1) {
eprintln!("Caused by: {}", cause);
}
eprintln!("{}", err.backtrace());
usage();
}
}

@ -0,0 +1,893 @@
// This is a mostly drop-in reimplementation of vspipe.
// The main difference is what the errors look like.
#![allow(unused)]
#[macro_use]
extern crate failure;
use failure::{err_msg, Error, ResultExt};
#[cfg(all(
feature = "vsscript-functions",
any(
feature = "vapoursynth-functions",
feature = "gte-vsscript-api-32"
)
))]
mod inner {
#![cfg_attr(feature = "cargo-clippy", allow(cast_lossless))]
#![cfg_attr(feature = "cargo-clippy", allow(mutex_atomic))]
extern crate clap;
extern crate num_rational;
extern crate vapoursynth;
use std::cmp;
use std::collections::HashMap;
use std::ffi::OsStr;
use std::fmt::Debug;
use std::fs::File;
use std::io::{self, stdout, Stdout, Write};
use std::ops::Deref;
use std::sync::{Arc, Condvar, Mutex};
use std::time::Instant;
use self::clap::{App, Arg};
use self::num_rational::Ratio;
use self::vapoursynth::prelude::*;
use super::*;
enum OutputTarget {
File(File),
Stdout(Stdout),
Empty,
}
struct OutputParameters<'core> {
node: Node<'core>,
alpha_node: Option<Node<'core>>,
start_frame: usize,
end_frame: usize,
requests: usize,
y4m: bool,
progress: bool,
}
struct OutputState<'core> {
output_target: OutputTarget,
timecodes_file: Option<File>,
error: Option<(usize, Error)>,
reorder_map: HashMap<usize, (Option<FrameRef<'core>>, Option<FrameRef<'core>>)>,
last_requested_frame: usize,
next_output_frame: usize,
current_timecode: Ratio<i64>,
callbacks_fired: usize,
callbacks_fired_alpha: usize,
last_fps_report_time: Instant,
last_fps_report_frames: usize,
fps: Option<f64>,
}
struct SharedData<'core> {
output_done_pair: (Mutex<bool>, Condvar),
output_parameters: OutputParameters<'core>,
output_state: Mutex<OutputState<'core>>,
}
impl Write for OutputTarget {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
match *self {
OutputTarget::File(ref mut file) => file.write(buf),
OutputTarget::Stdout(ref mut out) => out.write(buf),
OutputTarget::Empty => Ok(buf.len()),
}
}
fn flush(&mut self) -> io::Result<()> {
match *self {
OutputTarget::File(ref mut file) => file.flush(),
OutputTarget::Stdout(ref mut out) => out.flush(),
OutputTarget::Empty => Ok(()),
}
}
}
fn print_version() -> Result<(), Error> {
let environment = Environment::new().context("Couldn't create the VSScript environment")?;
let core = environment
.get_core()
.context("Couldn't create the VapourSynth core")?;
print!("{}", core.info().version_string);
Ok(())
}
// Parses the --arg arguments in form of key=value.
fn parse_arg(arg: &str) -> Result<(&str, &str), Error> {
arg.find('=')
.map(|index| arg.split_at(index))
.map(|(k, v)| (k, &v[1..]))
.ok_or_else(|| format_err!("No value specified for argument: {}", arg))
}
// Returns "Variable" or the value of the property passed through a function.
fn map_or_variable<T, F>(x: &Property<T>, f: F) -> String