1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
//!  A safe wrapper for [VapourSynth](https://github.com/vapoursynth/vapoursynth), written in Rust.
//!
//! The primary goal is safety (that is, safe Rust code should not trigger undefined behavior), and
//! secondary goals include performance and ease of use.
//!
//! ## Functionality
//!
//! Most of the VapourSynth API is covered. It's possible to evaluate `.vpy` scripts, access their
//! properties and output, retrieve frames; enumerate loaded plugins and invoke their functions as
//! well as create VapourSynth filters.
//!
//! For an example usage see
//! [examples/vspipe.rs](https://github.com/YaLTeR/vapoursynth-rs/blob/master/vapoursynth/examples/vspipe.rs),
//! a complete reimplementation of VapourSynth's
//! [vspipe](https://github.com/vapoursynth/vapoursynth/blob/master/src/vspipe/vspipe.cpp) in safe
//! Rust utilizing this crate.
//!
//! For a VapourSynth plugin example see
//! [sample-plugin](https://github.com/YaLTeR/vapoursynth-rs/blob/master/sample-plugin) which
//! implements some simple filters.
//!
//! ## Short example
//!
//! ```no_run
//! # extern crate vapoursynth;
//! # use anyhow::Error;
//! # #[cfg(all(feature = "vsscript-functions",
//! #           feature = "gte-vsscript-api-31",
//! #           any(feature = "vapoursynth-functions", feature = "gte-vsscript-api-32")))]
//! # fn foo() -> Result<(), Error> {
//! use vapoursynth::prelude::*;
//!
//! let env = Environment::from_file("test.vpy", EvalFlags::SetWorkingDir)?;
//! let node = env.get_output(0)?.0; // Without `.0` for VSScript API 3.0
//! let frame = node.get_frame(0)?;
//!
//! println!("Resolution: {}×{}", frame.width(0), frame.height(0));
//! # Ok(())
//! # }
//! # fn main() {
//! # }
//! ```
//!
//! ## Plugins
//!
//! To make a VapourSynth plugin, start by creating a new Rust library with
//! `crate-type = ["cdylib"]`. Then add filters by implementing the `plugins::Filter` trait. Bind
//! them to functions by implementing `plugins::FilterFunction`, which is much more easily done via
//! the `make_filter_function!` macro. Finally, put `export_vapoursynth_plugin!` at the top level
//! of `src/lib.rs` to export the functionality.
//!
//! **Important note:** due to what seems to be a
//! [bug](https://github.com/rust-lang/rust/issues/50176) in rustc, it's impossible to make plugins
//! on the `i686-pc-windows-gnu` target (all other variations of `x86_64` and `i686` do work).
//! Please use `i686-pc-windows-msvc` for an i686 Windows plugin.
//!
//! ## Short plugin example
//!
//! ```no_run
//! #[macro_use]
//! extern crate vapoursynth;
//!
//! use anyhow::{anyhow, Error};
//! use vapoursynth::prelude::*;
//! use vapoursynth::core::CoreRef;
//! use vapoursynth::plugins::{Filter, FilterArgument, FrameContext, Metadata};
//! use vapoursynth::video_info::VideoInfo;
//!
//! // A simple filter that passes the frames through unchanged.
//! struct Passthrough<'core> {
//!     source: Node<'core>,
//! }
//!
//! impl<'core> Filter<'core> for Passthrough<'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> {
//!         self.source
//!             .get_frame_filter(context, n)
//!             .ok_or(anyhow!("Couldn't get the source frame"))
//!     }
//! }
//!
//! make_filter_function! {
//!     PassthroughFunction, "Passthrough"
//!
//!     fn create_passthrough<'core>(
//!         _api: API,
//!         _core: CoreRef<'core>,
//!         clip: Node<'core>,
//!     ) -> Result<Option<Box<dyn Filter<'core> + 'core>>, Error> {
//!         Ok(Some(Box::new(Passthrough { source: clip })))
//!     }
//! }
//!
//! export_vapoursynth_plugin! {
//!     Metadata {
//!         identifier: "com.example.passthrough",
//!         namespace: "passthrough",
//!         name: "Example Plugin",
//!         read_only: true,
//!     },
//!     [PassthroughFunction::new()]
//! }
//! # fn main() {
//! # }
//! ```
//!
//! Check [sample-plugin](https://github.com/YaLTeR/vapoursynth-rs/blob/master/sample-plugin) for
//! an example plugin which exports some simple filters.
//!
//! ## 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.

#![doc(html_root_url = "https://docs.rs/vapoursynth/0.4.0")]
// Preventing all those warnings with #[cfg] directives would be really diffucult.
#![allow(unused, dead_code)]
#![allow(clippy::trivially_copy_pass_by_ref)]

#[macro_use]
extern crate bitflags;
#[cfg(feature = "f16-pixel-type")]
extern crate half;
#[cfg(any(not(feature = "gte-vsscript-api-32"), test))]
#[macro_use]
extern crate lazy_static;
extern crate vapoursynth_sys;

#[cfg(feature = "vsscript-functions")]
pub mod vsscript;

pub mod api;
pub mod component;
pub mod core;
pub mod format;
pub mod frame;
pub mod function;
pub mod map;
pub mod node;
pub mod plugin;
pub mod plugins;
pub mod video_info;

pub mod prelude {
    //! The VapourSynth prelude.
    //!
    //! Contains the types you most likely want to import anyway.
    pub use super::api::{MessageType, API};
    pub use super::component::Component;
    pub use super::format::{ColorFamily, PresetFormat, SampleType};
    pub use super::frame::{Frame, FrameRef, FrameRefMut};
    pub use super::map::{Map, OwnedMap, ValueType};
    pub use super::node::{GetFrameError, Node};
    pub use super::plugin::Plugin;
    pub use super::video_info::Property;

    #[cfg(feature = "vsscript-functions")]
    pub use super::vsscript::{self, Environment, EvalFlags};
}

mod tests;