vapoursynth-mvuscale 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- vapoursynth_mvuscale-0.1.0/CMakeLists.txt +28 -0
- vapoursynth_mvuscale-0.1.0/PKG-INFO +51 -0
- vapoursynth_mvuscale-0.1.0/README.md +36 -0
- vapoursynth_mvuscale-0.1.0/build.sh +17 -0
- vapoursynth_mvuscale-0.1.0/include/NOTICE +13 -0
- vapoursynth_mvuscale-0.1.0/include/VSConstants4.h +105 -0
- vapoursynth_mvuscale-0.1.0/include/VSHelper4.h +217 -0
- vapoursynth_mvuscale-0.1.0/include/VapourSynth4.h +534 -0
- vapoursynth_mvuscale-0.1.0/mvuscale.cpp +149 -0
- vapoursynth_mvuscale-0.1.0/pyproject.toml +54 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.18)
|
|
2
|
+
project(mvuscale LANGUAGES CXX)
|
|
3
|
+
|
|
4
|
+
# mvuscale — a native VapourSynth (API4) filter that scales mvutensils motion
|
|
5
|
+
# vectors for the smdegrain_bis UHDhalf path (the manipmv.ScaleVect replacement).
|
|
6
|
+
# It links no libpython and no libvapoursynth (VS resolves the API through the
|
|
7
|
+
# plugin entry point), so the binary is Python-version-independent: one build
|
|
8
|
+
# per (OS, arch) covers all Python 3.x.
|
|
9
|
+
|
|
10
|
+
set(CMAKE_CXX_STANDARD 17)
|
|
11
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
12
|
+
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
|
|
13
|
+
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
|
14
|
+
|
|
15
|
+
add_library(mvuscale SHARED mvuscale.cpp)
|
|
16
|
+
target_include_directories(mvuscale PRIVATE include) # vendored VS API4 headers
|
|
17
|
+
|
|
18
|
+
if(NOT MSVC)
|
|
19
|
+
target_compile_options(mvuscale PRIVATE -O3 -Wall)
|
|
20
|
+
endif()
|
|
21
|
+
|
|
22
|
+
# Install under <site-packages>/vapoursynth/plugins/mvuscale/ — the same payload
|
|
23
|
+
# layout the PyPI VS-plugin wheels (manipmv, nlm_ispc, …) use, so a host that
|
|
24
|
+
# relocates that tree into its own plugins dir finds the .so unchanged, and a
|
|
25
|
+
# plain pip user gets it on sys.path for smdegrain_bis to load.
|
|
26
|
+
install(TARGETS mvuscale
|
|
27
|
+
LIBRARY DESTINATION vapoursynth/plugins/mvuscale
|
|
28
|
+
RUNTIME DESTINATION vapoursynth/plugins/mvuscale)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: vapoursynth-mvuscale
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Native VapourSynth (API4) filter that scales mvutensils motion vectors for smdegrain_bis UHDhalf
|
|
5
|
+
Keywords: vapoursynth,mvutensils,motion-vectors,denoise,smdegrain
|
|
6
|
+
Author: Florian Gamper
|
|
7
|
+
License-Expression: GPL-3.0-or-later
|
|
8
|
+
Classifier: Topic :: Multimedia :: Video
|
|
9
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
10
|
+
Classifier: Operating System :: MacOS
|
|
11
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
12
|
+
Project-URL: Homepage, https://github.com/FlorianGamper/vs-smdegrain-bis
|
|
13
|
+
Requires-Python: >=3.8
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
# vapoursynth-mvuscale
|
|
17
|
+
|
|
18
|
+
A tiny native **VapourSynth (API4)** filter that scales
|
|
19
|
+
[mvutensils](https://github.com/myrsloik/mvutensils) motion vectors between
|
|
20
|
+
resolutions — the `manipmv.ScaleVect` replacement used by the
|
|
21
|
+
[`smdegrain-bis`](https://github.com/FlorianGamper/vs-smdegrain-bis) `UHDhalf` path, where
|
|
22
|
+
motion is searched at half resolution and the vectors are multiplied back up to
|
|
23
|
+
full resolution before `Degrain`.
|
|
24
|
+
|
|
25
|
+
It registers `core.mvuscale.ScaleVect(clip, scale=<int>)`, operating on
|
|
26
|
+
mvutensils' vector frame-props (geometry ×s, packed vectors ×s, SAD ×s²). It
|
|
27
|
+
links no libpython and no libvapoursynth, so one build per platform serves every
|
|
28
|
+
Python 3.x.
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install vapoursynth-mvuscale # drops the plugin under vapoursynth/plugins/mvuscale/
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`smdegrain-bis` loads it automatically when `UHDhalf=True`. A host that manages
|
|
37
|
+
its own plugin directory can instead relocate the wheel payload (or the
|
|
38
|
+
`native/build.sh` output) into that directory, where it autoloads.
|
|
39
|
+
|
|
40
|
+
## Build from source
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip wheel native/ -w dist/ # scikit-build-core + CMake
|
|
44
|
+
# or, just the .so:
|
|
45
|
+
CXX=g++ bash native/build.sh # -> tests/_plugins/mvuscale/libmvuscale.so
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The VapourSynth API4 headers are vendored under `native/include/` (see its
|
|
49
|
+
`NOTICE`), so no VapourSynth SDK is required to build.
|
|
50
|
+
|
|
51
|
+
**Licence:** GPL-3.0-or-later.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# vapoursynth-mvuscale
|
|
2
|
+
|
|
3
|
+
A tiny native **VapourSynth (API4)** filter that scales
|
|
4
|
+
[mvutensils](https://github.com/myrsloik/mvutensils) motion vectors between
|
|
5
|
+
resolutions — the `manipmv.ScaleVect` replacement used by the
|
|
6
|
+
[`smdegrain-bis`](https://github.com/FlorianGamper/vs-smdegrain-bis) `UHDhalf` path, where
|
|
7
|
+
motion is searched at half resolution and the vectors are multiplied back up to
|
|
8
|
+
full resolution before `Degrain`.
|
|
9
|
+
|
|
10
|
+
It registers `core.mvuscale.ScaleVect(clip, scale=<int>)`, operating on
|
|
11
|
+
mvutensils' vector frame-props (geometry ×s, packed vectors ×s, SAD ×s²). It
|
|
12
|
+
links no libpython and no libvapoursynth, so one build per platform serves every
|
|
13
|
+
Python 3.x.
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install vapoursynth-mvuscale # drops the plugin under vapoursynth/plugins/mvuscale/
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`smdegrain-bis` loads it automatically when `UHDhalf=True`. A host that manages
|
|
22
|
+
its own plugin directory can instead relocate the wheel payload (or the
|
|
23
|
+
`native/build.sh` output) into that directory, where it autoloads.
|
|
24
|
+
|
|
25
|
+
## Build from source
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pip wheel native/ -w dist/ # scikit-build-core + CMake
|
|
29
|
+
# or, just the .so:
|
|
30
|
+
CXX=g++ bash native/build.sh # -> tests/_plugins/mvuscale/libmvuscale.so
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The VapourSynth API4 headers are vendored under `native/include/` (see its
|
|
34
|
+
`NOTICE`), so no VapourSynth SDK is required to build.
|
|
35
|
+
|
|
36
|
+
**Licence:** GPL-3.0-or-later.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Build the optional mvuscale native filter (fast UHDhalf vector scaler).
|
|
3
|
+
# Portable x86-64 baseline (SSE2) — no AVX runtime requirement.
|
|
4
|
+
#
|
|
5
|
+
# VS_INCLUDE=/path/to/vapoursynth/headers OUT=/dest/dir native/build.sh
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
8
|
+
# VapourSynth API4 headers (VapourSynth4.h, VSHelper4.h) — vendored under
|
|
9
|
+
# native/include/ so this builds with no VapourSynth SDK installed. Override
|
|
10
|
+
# VS_INCLUDE to point at a system copy if you prefer.
|
|
11
|
+
VS_INCLUDE="${VS_INCLUDE:-$HERE/include}"
|
|
12
|
+
OUT="${OUT:-$HERE/../tests/_plugins/mvuscale}"
|
|
13
|
+
CXX="${CXX:-g++}"
|
|
14
|
+
mkdir -p "$OUT"
|
|
15
|
+
set -x
|
|
16
|
+
"$CXX" -std=c++17 -O3 -fPIC -shared -Wall -fvisibility=hidden \
|
|
17
|
+
-I"$VS_INCLUDE" "$HERE/mvuscale.cpp" -o "$OUT/libmvuscale.so"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
VapourSynth API4 headers — vendored verbatim so the mvuscale native filter
|
|
2
|
+
builds without a VapourSynth SDK installed (self-contained CI).
|
|
3
|
+
|
|
4
|
+
Source: the `vapoursynth` distribution's `vapoursynth/include/` directory.
|
|
5
|
+
Copyright (c) 2012-2026 Fredrik Mellbin.
|
|
6
|
+
|
|
7
|
+
VapourSynth4.h LGPL-2.1-or-later
|
|
8
|
+
VSConstants4.h LGPL-2.1-or-later
|
|
9
|
+
VSHelper4.h WTFPL (Do What The Fuck You Want To Public License, v2)
|
|
10
|
+
|
|
11
|
+
Both licences are compatible with this project's GPL-3.0-or-later, and merely
|
|
12
|
+
#including these API headers to build a plugin is their intended use. They are
|
|
13
|
+
not modified. To refresh, copy them from a current `vapoursynth` install.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2021 Fredrik Mellbin
|
|
3
|
+
*
|
|
4
|
+
* This file is part of VapourSynth.
|
|
5
|
+
*
|
|
6
|
+
* VapourSynth is free software; you can redistribute it and/or
|
|
7
|
+
* modify it under the terms of the GNU Lesser General Public
|
|
8
|
+
* License as published by the Free Software Foundation; either
|
|
9
|
+
* version 2.1 of the License, or (at your option) any later version.
|
|
10
|
+
*
|
|
11
|
+
* VapourSynth is distributed in the hope that it will be useful,
|
|
12
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
14
|
+
* Lesser General Public License for more details.
|
|
15
|
+
*
|
|
16
|
+
* You should have received a copy of the GNU Lesser General Public
|
|
17
|
+
* License along with VapourSynth; if not, write to the Free Software
|
|
18
|
+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
#ifndef VSCONSTANTS4_H
|
|
22
|
+
#define VSCONSTANTS4_H
|
|
23
|
+
|
|
24
|
+
#if defined(VS_USE_LATEST_API) || defined(VS_USE_API_42)
|
|
25
|
+
|
|
26
|
+
typedef enum VSRange {
|
|
27
|
+
VSC_RANGE_FULL = 1,
|
|
28
|
+
VSC_RANGE_LIMITED = 0
|
|
29
|
+
} VSRange;
|
|
30
|
+
|
|
31
|
+
#else
|
|
32
|
+
|
|
33
|
+
typedef enum VSColorRange {
|
|
34
|
+
VSC_RANGE_FULL = 0,
|
|
35
|
+
VSC_RANGE_LIMITED = 1
|
|
36
|
+
} VSColorRange;
|
|
37
|
+
|
|
38
|
+
#endif
|
|
39
|
+
|
|
40
|
+
typedef enum VSChromaLocation {
|
|
41
|
+
VSC_CHROMA_LEFT = 0,
|
|
42
|
+
VSC_CHROMA_CENTER = 1,
|
|
43
|
+
VSC_CHROMA_TOP_LEFT = 2,
|
|
44
|
+
VSC_CHROMA_TOP = 3,
|
|
45
|
+
VSC_CHROMA_BOTTOM_LEFT = 4,
|
|
46
|
+
VSC_CHROMA_BOTTOM = 5
|
|
47
|
+
} VSChromaLocation;
|
|
48
|
+
|
|
49
|
+
typedef enum VSFieldBased {
|
|
50
|
+
VSC_FIELD_PROGRESSIVE = 0,
|
|
51
|
+
VSC_FIELD_BOTTOM = 1,
|
|
52
|
+
VSC_FIELD_TOP = 2
|
|
53
|
+
} VSFieldBased;
|
|
54
|
+
|
|
55
|
+
typedef enum VSMatrixCoefficients {
|
|
56
|
+
VSC_MATRIX_RGB = 0,
|
|
57
|
+
VSC_MATRIX_BT709 = 1,
|
|
58
|
+
VSC_MATRIX_UNSPECIFIED = 2,
|
|
59
|
+
VSC_MATRIX_FCC = 4,
|
|
60
|
+
VSC_MATRIX_BT470_BG = 5,
|
|
61
|
+
VSC_MATRIX_ST170_M = 6, /* Equivalent to 5. */
|
|
62
|
+
VSC_MATRIX_ST240_M = 7,
|
|
63
|
+
VSC_MATRIX_YCGCO = 8,
|
|
64
|
+
VSC_MATRIX_BT2020_NCL = 9,
|
|
65
|
+
VSC_MATRIX_BT2020_CL = 10,
|
|
66
|
+
VSC_MATRIX_CHROMATICITY_DERIVED_NCL = 12,
|
|
67
|
+
VSC_MATRIX_CHROMATICITY_DERIVED_CL = 13,
|
|
68
|
+
VSC_MATRIX_ICTCP = 14
|
|
69
|
+
} VSMatrixCoefficients;
|
|
70
|
+
|
|
71
|
+
typedef enum VSTransferCharacteristics {
|
|
72
|
+
VSC_TRANSFER_BT709 = 1,
|
|
73
|
+
VSC_TRANSFER_UNSPECIFIED = 2,
|
|
74
|
+
VSC_TRANSFER_BT470_M = 4,
|
|
75
|
+
VSC_TRANSFER_BT470_BG = 5,
|
|
76
|
+
VSC_TRANSFER_BT601 = 6, /* Equivalent to 1. */
|
|
77
|
+
VSC_TRANSFER_ST240_M = 7,
|
|
78
|
+
VSC_TRANSFER_LINEAR = 8,
|
|
79
|
+
VSC_TRANSFER_LOG_100 = 9,
|
|
80
|
+
VSC_TRANSFER_LOG_316 = 10,
|
|
81
|
+
VSC_TRANSFER_IEC_61966_2_4 = 11,
|
|
82
|
+
VSC_TRANSFER_IEC_61966_2_1 = 13,
|
|
83
|
+
VSC_TRANSFER_BT2020_10 = 14, /* Equivalent to 1. */
|
|
84
|
+
VSC_TRANSFER_BT2020_12 = 15, /* Equivalent to 1. */
|
|
85
|
+
VSC_TRANSFER_ST2084 = 16,
|
|
86
|
+
VSC_TRANSFER_ST428 = 17,
|
|
87
|
+
VSC_TRANSFER_ARIB_B67 = 18
|
|
88
|
+
} VSTransferCharacteristics;
|
|
89
|
+
|
|
90
|
+
typedef enum VSColorPrimaries {
|
|
91
|
+
VSC_PRIMARIES_BT709 = 1,
|
|
92
|
+
VSC_PRIMARIES_UNSPECIFIED = 2,
|
|
93
|
+
VSC_PRIMARIES_BT470_M = 4,
|
|
94
|
+
VSC_PRIMARIES_BT470_BG = 5,
|
|
95
|
+
VSC_PRIMARIES_ST170_M = 6,
|
|
96
|
+
VSC_PRIMARIES_ST240_M = 7, /* Equivalent to 6. */
|
|
97
|
+
VSC_PRIMARIES_FILM = 8,
|
|
98
|
+
VSC_PRIMARIES_BT2020 = 9,
|
|
99
|
+
VSC_PRIMARIES_ST428 = 10,
|
|
100
|
+
VSC_PRIMARIES_ST431_2 = 11,
|
|
101
|
+
VSC_PRIMARIES_ST432_1 = 12,
|
|
102
|
+
VSC_PRIMARIES_EBU3213_E = 22
|
|
103
|
+
} VSColorPrimaries;
|
|
104
|
+
|
|
105
|
+
#endif /* VSCONSTANTS4_H */
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/*****************************************************************************
|
|
2
|
+
* Copyright (c) 2012-2020 Fredrik Mellbin
|
|
3
|
+
* --- Legal stuff ---
|
|
4
|
+
* This program is free software. It comes without any warranty, to
|
|
5
|
+
* the extent permitted by applicable law. You can redistribute it
|
|
6
|
+
* and/or modify it under the terms of the Do What The Fuck You Want
|
|
7
|
+
* To Public License, Version 2, as published by Sam Hocevar. See
|
|
8
|
+
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
|
9
|
+
*****************************************************************************/
|
|
10
|
+
|
|
11
|
+
#ifndef VSHELPER4_H
|
|
12
|
+
#define VSHELPER4_H
|
|
13
|
+
|
|
14
|
+
#include <limits.h>
|
|
15
|
+
#include <stdint.h>
|
|
16
|
+
#include <stdlib.h>
|
|
17
|
+
#include <string.h>
|
|
18
|
+
#include <assert.h>
|
|
19
|
+
#include <math.h>
|
|
20
|
+
#include <float.h>
|
|
21
|
+
#ifdef _WIN32
|
|
22
|
+
#include <malloc.h>
|
|
23
|
+
#endif
|
|
24
|
+
#include "VapourSynth4.h"
|
|
25
|
+
|
|
26
|
+
#define VSH_STD_PLUGIN_ID "com.vapoursynth.std"
|
|
27
|
+
#define VSH_RESIZE_PLUGIN_ID "com.vapoursynth.resize"
|
|
28
|
+
#define VSH_TEXT_PLUGIN_ID "com.vapoursynth.text"
|
|
29
|
+
|
|
30
|
+
#ifdef __cplusplus
|
|
31
|
+
namespace vsh {
|
|
32
|
+
#define VSH4_MANGLE_FUNCTION_NAME(name) name
|
|
33
|
+
#define VSH4_BOOLEAN_TYPE bool
|
|
34
|
+
#else
|
|
35
|
+
#define VSH4_MANGLE_FUNCTION_NAME(name) vsh_##name
|
|
36
|
+
#define VSH4_BOOLEAN_TYPE int
|
|
37
|
+
#endif
|
|
38
|
+
|
|
39
|
+
/* Visual Studio doesn't recognize inline in c mode */
|
|
40
|
+
#if defined(_MSC_VER) && !defined(__cplusplus)
|
|
41
|
+
#define inline _inline
|
|
42
|
+
#endif
|
|
43
|
+
|
|
44
|
+
/* A kinda portable definition of the C99 restrict keyword (or its unofficial C++ equivalent) */
|
|
45
|
+
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* Available in C99 */
|
|
46
|
+
#define VS_RESTRICT restrict
|
|
47
|
+
#elif defined(__cplusplus) || defined(_MSC_VER) /* Almost all relevant C++ compilers support it so just assume it works */
|
|
48
|
+
#define VS_RESTRICT __restrict
|
|
49
|
+
#else /* Not supported */
|
|
50
|
+
#define VS_RESTRICT
|
|
51
|
+
#endif
|
|
52
|
+
|
|
53
|
+
#ifdef _WIN32
|
|
54
|
+
#define VSH_ALIGNED_MALLOC(pptr, size, alignment) do { *(pptr) = _aligned_malloc((size), (alignment)); } while (0)
|
|
55
|
+
#define VSH_ALIGNED_FREE(ptr) do { _aligned_free((ptr)); } while (0)
|
|
56
|
+
#else
|
|
57
|
+
#define VSH_ALIGNED_MALLOC(pptr, size, alignment) do { if(posix_memalign((void**)(pptr), (alignment), (size))) *((void**)pptr) = NULL; } while (0)
|
|
58
|
+
#define VSH_ALIGNED_FREE(ptr) do { free((ptr)); } while (0)
|
|
59
|
+
#endif
|
|
60
|
+
|
|
61
|
+
#define VSMAX(a,b) ((a) > (b) ? (a) : (b))
|
|
62
|
+
#define VSMIN(a,b) ((a) > (b) ? (b) : (a))
|
|
63
|
+
|
|
64
|
+
#ifdef __cplusplus
|
|
65
|
+
/* A nicer templated malloc for all the C++ users out there */
|
|
66
|
+
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900)
|
|
67
|
+
template<typename T = void>
|
|
68
|
+
#else
|
|
69
|
+
template<typename T>
|
|
70
|
+
#endif
|
|
71
|
+
static inline T *vsh_aligned_malloc(size_t size, size_t alignment) {
|
|
72
|
+
#ifdef _WIN32
|
|
73
|
+
return (T *)_aligned_malloc(size, alignment);
|
|
74
|
+
#else
|
|
75
|
+
void *tmp = NULL;
|
|
76
|
+
if (posix_memalign(&tmp, alignment, size))
|
|
77
|
+
tmp = 0;
|
|
78
|
+
return (T *)tmp;
|
|
79
|
+
#endif
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
static inline void vsh_aligned_free(void *ptr) {
|
|
83
|
+
VSH_ALIGNED_FREE(ptr);
|
|
84
|
+
}
|
|
85
|
+
#endif /* __cplusplus */
|
|
86
|
+
|
|
87
|
+
/* convenience function for checking if the format never changes between frames */
|
|
88
|
+
static inline VSH4_BOOLEAN_TYPE VSH4_MANGLE_FUNCTION_NAME(isConstantVideoFormat)(const VSVideoInfo *vi) {
|
|
89
|
+
return vi->height > 0 && vi->width > 0 && vi->format.colorFamily != cfUndefined;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/* convenience function to check if two clips have the same format (unknown/changeable will be considered the same too) */
|
|
93
|
+
static inline VSH4_BOOLEAN_TYPE VSH4_MANGLE_FUNCTION_NAME(isSameVideoFormat)(const VSVideoFormat *v1, const VSVideoFormat *v2) {
|
|
94
|
+
return v1->colorFamily == v2->colorFamily && v1->sampleType == v2->sampleType && v1->bitsPerSample == v2->bitsPerSample && v1->subSamplingW == v2->subSamplingW && v1->subSamplingH == v2->subSamplingH;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/* convenience function to check if a clip has the same format as a format id */
|
|
98
|
+
static inline VSH4_BOOLEAN_TYPE VSH4_MANGLE_FUNCTION_NAME(isSameVideoPresetFormat)(unsigned presetFormat, const VSVideoFormat *v, VSCore *core, const VSAPI *vsapi) {
|
|
99
|
+
return vsapi->queryVideoFormatID(v->colorFamily, v->sampleType, v->bitsPerSample, v->subSamplingW, v->subSamplingH, core) == presetFormat;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* convenience function to check for if two clips have the same format (but not framerate) while also including width and height (unknown/changeable will be considered the same too) */
|
|
103
|
+
static inline VSH4_BOOLEAN_TYPE VSH4_MANGLE_FUNCTION_NAME(isSameVideoInfo)(const VSVideoInfo *v1, const VSVideoInfo *v2) {
|
|
104
|
+
return v1->height == v2->height && v1->width == v2->width && VSH4_MANGLE_FUNCTION_NAME(isSameVideoFormat)(&v1->format, &v2->format);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/* convenience function to check for if two clips have the same format while also including samplerate (unknown/changeable will be considered the same too) */
|
|
108
|
+
static inline VSH4_BOOLEAN_TYPE VSH4_MANGLE_FUNCTION_NAME(isSameAudioFormat)(const VSAudioFormat *a1, const VSAudioFormat *a2) {
|
|
109
|
+
return a1->bitsPerSample == a2->bitsPerSample && a1->sampleType == a2->sampleType && a1->channelLayout == a2->channelLayout;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/* convenience function to check for if two clips have the same format while also including samplerate (unknown/changeable will be considered the same too) */
|
|
113
|
+
static inline VSH4_BOOLEAN_TYPE VSH4_MANGLE_FUNCTION_NAME(isSameAudioInfo)(const VSAudioInfo *a1, const VSAudioInfo *a2) {
|
|
114
|
+
return a1->sampleRate == a2->sampleRate && VSH4_MANGLE_FUNCTION_NAME(isSameAudioFormat)(&a1->format, &a2->format);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/* multiplies and divides a rational number, such as a frame duration, in place and reduces the result */
|
|
118
|
+
static inline void VSH4_MANGLE_FUNCTION_NAME(muldivRational)(int64_t *num, int64_t *den, int64_t mul, int64_t div) {
|
|
119
|
+
/* do nothing if the rational number is invalid */
|
|
120
|
+
if (!*den)
|
|
121
|
+
return;
|
|
122
|
+
|
|
123
|
+
/* nobody wants to accidentally divide by zero */
|
|
124
|
+
assert(div);
|
|
125
|
+
|
|
126
|
+
int64_t a, b;
|
|
127
|
+
*num *= mul;
|
|
128
|
+
*den *= div;
|
|
129
|
+
a = *num;
|
|
130
|
+
b = *den;
|
|
131
|
+
while (b != 0) {
|
|
132
|
+
int64_t t = a;
|
|
133
|
+
a = b;
|
|
134
|
+
b = t % b;
|
|
135
|
+
}
|
|
136
|
+
if (a < 0)
|
|
137
|
+
a = -a;
|
|
138
|
+
*num /= a;
|
|
139
|
+
*den /= a;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/* reduces a rational number */
|
|
143
|
+
static inline void VSH4_MANGLE_FUNCTION_NAME(reduceRational)(int64_t *num, int64_t *den) {
|
|
144
|
+
VSH4_MANGLE_FUNCTION_NAME(muldivRational)(num, den, 1, 1);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/* add two rational numbers and reduces the result */
|
|
148
|
+
static inline void VSH4_MANGLE_FUNCTION_NAME(addRational)(int64_t *num, int64_t *den, int64_t addnum, int64_t addden) {
|
|
149
|
+
/* do nothing if the rational number is invalid */
|
|
150
|
+
if (!*den)
|
|
151
|
+
return;
|
|
152
|
+
|
|
153
|
+
/* nobody wants to accidentally add an invalid rational number */
|
|
154
|
+
assert(addden);
|
|
155
|
+
|
|
156
|
+
if (*den == addden) {
|
|
157
|
+
*num += addnum;
|
|
158
|
+
} else {
|
|
159
|
+
int64_t temp = addden;
|
|
160
|
+
addnum *= *den;
|
|
161
|
+
addden *= *den;
|
|
162
|
+
*num *= temp;
|
|
163
|
+
*den *= temp;
|
|
164
|
+
|
|
165
|
+
*num += addnum;
|
|
166
|
+
|
|
167
|
+
VSH4_MANGLE_FUNCTION_NAME(reduceRational)(num, den);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/* converts an int64 to int with saturation, useful to silence warnings when reading int properties among other things */
|
|
172
|
+
static inline int VSH4_MANGLE_FUNCTION_NAME(int64ToIntS)(int64_t i) {
|
|
173
|
+
if (i > INT_MAX)
|
|
174
|
+
return INT_MAX;
|
|
175
|
+
else if (i < INT_MIN)
|
|
176
|
+
return INT_MIN;
|
|
177
|
+
else return (int)i;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/* converts a double to float with saturation, useful to silence warnings when reading float properties among other things */
|
|
181
|
+
static inline float VSH4_MANGLE_FUNCTION_NAME(doubleToFloatS)(double d) {
|
|
182
|
+
return (float)d;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
static inline void VSH4_MANGLE_FUNCTION_NAME(bitblt)(void *dstp, ptrdiff_t dst_stride, const void *srcp, ptrdiff_t src_stride, size_t row_size, size_t height) {
|
|
186
|
+
if (height) {
|
|
187
|
+
if (src_stride == dst_stride && src_stride == (ptrdiff_t)row_size) {
|
|
188
|
+
memcpy(dstp, srcp, row_size * height);
|
|
189
|
+
} else {
|
|
190
|
+
const uint8_t *srcp8 = (const uint8_t *)srcp;
|
|
191
|
+
uint8_t *dstp8 = (uint8_t *)dstp;
|
|
192
|
+
size_t i;
|
|
193
|
+
for (i = 0; i < height; i++) {
|
|
194
|
+
memcpy(dstp8, srcp8, row_size);
|
|
195
|
+
srcp8 += src_stride;
|
|
196
|
+
dstp8 += dst_stride;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/* check if the frame dimensions are valid for a given format */
|
|
203
|
+
/* returns non-zero for valid width and height */
|
|
204
|
+
static inline VSH4_BOOLEAN_TYPE VSH4_MANGLE_FUNCTION_NAME(areValidDimensions)(const VSVideoFormat *fi, int width, int height) {
|
|
205
|
+
return !(width % (1 << fi->subSamplingW) || height % (1 << fi->subSamplingH));
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/* Visual Studio doesn't recognize inline in c mode */
|
|
209
|
+
#if defined(_MSC_VER) && !defined(__cplusplus)
|
|
210
|
+
#undef inline
|
|
211
|
+
#endif
|
|
212
|
+
|
|
213
|
+
#ifdef __cplusplus
|
|
214
|
+
}
|
|
215
|
+
#endif
|
|
216
|
+
|
|
217
|
+
#endif
|
|
@@ -0,0 +1,534 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2012-2026 Fredrik Mellbin
|
|
3
|
+
*
|
|
4
|
+
* This file is part of VapourSynth.
|
|
5
|
+
*
|
|
6
|
+
* VapourSynth is free software; you can redistribute it and/or
|
|
7
|
+
* modify it under the terms of the GNU Lesser General Public
|
|
8
|
+
* License as published by the Free Software Foundation; either
|
|
9
|
+
* version 2.1 of the License, or (at your option) any later version.
|
|
10
|
+
*
|
|
11
|
+
* VapourSynth is distributed in the hope that it will be useful,
|
|
12
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
14
|
+
* Lesser General Public License for more details.
|
|
15
|
+
*
|
|
16
|
+
* You should have received a copy of the GNU Lesser General Public
|
|
17
|
+
* License along with VapourSynth; if not, write to the Free Software
|
|
18
|
+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
#ifndef VAPOURSYNTH4_H
|
|
22
|
+
#define VAPOURSYNTH4_H
|
|
23
|
+
|
|
24
|
+
#include <stdint.h>
|
|
25
|
+
#include <stddef.h>
|
|
26
|
+
|
|
27
|
+
#define VS_MAKE_VERSION(major, minor) (((major) << 16) | (minor))
|
|
28
|
+
#define VAPOURSYNTH_API_MAJOR 4
|
|
29
|
+
#if defined(VS_USE_LATEST_API) || defined(VS_USE_API_42)
|
|
30
|
+
#define VAPOURSYNTH_API_MINOR 2
|
|
31
|
+
#elif defined(VS_USE_API_41)
|
|
32
|
+
#define VAPOURSYNTH_API_MINOR 1
|
|
33
|
+
#else
|
|
34
|
+
#define VAPOURSYNTH_API_MINOR 0
|
|
35
|
+
#endif
|
|
36
|
+
#define VAPOURSYNTH_API_VERSION VS_MAKE_VERSION(VAPOURSYNTH_API_MAJOR, VAPOURSYNTH_API_MINOR)
|
|
37
|
+
|
|
38
|
+
#define VS_AUDIO_FRAME_SAMPLES 3072
|
|
39
|
+
|
|
40
|
+
/* Convenience for C++ users. */
|
|
41
|
+
#ifdef __cplusplus
|
|
42
|
+
# define VS_EXTERN_C extern "C"
|
|
43
|
+
# if __cplusplus >= 201103L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201103L)
|
|
44
|
+
# define VS_NOEXCEPT noexcept
|
|
45
|
+
# else
|
|
46
|
+
# define VS_NOEXCEPT
|
|
47
|
+
# endif
|
|
48
|
+
#else
|
|
49
|
+
# define VS_EXTERN_C
|
|
50
|
+
# define VS_NOEXCEPT
|
|
51
|
+
#endif
|
|
52
|
+
|
|
53
|
+
#if defined(_WIN32) && !defined(_WIN64)
|
|
54
|
+
# define VS_CC __stdcall
|
|
55
|
+
#else
|
|
56
|
+
# define VS_CC
|
|
57
|
+
#endif
|
|
58
|
+
|
|
59
|
+
/* And now for some symbol hide-and-seek... */
|
|
60
|
+
#if defined(_WIN32) /* Windows being special */
|
|
61
|
+
# define VS_EXTERNAL_API(ret) VS_EXTERN_C __declspec(dllexport) ret VS_CC
|
|
62
|
+
#elif defined(__GNUC__) && __GNUC__ >= 4
|
|
63
|
+
# define VS_EXTERNAL_API(ret) VS_EXTERN_C __attribute__((visibility("default"))) ret VS_CC
|
|
64
|
+
#else
|
|
65
|
+
# define VS_EXTERNAL_API(ret) VS_EXTERN_C ret VS_CC
|
|
66
|
+
#endif
|
|
67
|
+
|
|
68
|
+
#if !defined(VS_CORE_EXPORTS) && defined(_WIN32)
|
|
69
|
+
# define VS_API(ret) VS_EXTERN_C __declspec(dllimport) ret VS_CC
|
|
70
|
+
#else
|
|
71
|
+
# define VS_API(ret) VS_EXTERNAL_API(ret)
|
|
72
|
+
#endif
|
|
73
|
+
|
|
74
|
+
typedef struct VSFrame VSFrame;
|
|
75
|
+
typedef struct VSNode VSNode;
|
|
76
|
+
typedef struct VSCore VSCore;
|
|
77
|
+
typedef struct VSPlugin VSPlugin;
|
|
78
|
+
typedef struct VSPluginFunction VSPluginFunction;
|
|
79
|
+
typedef struct VSFunction VSFunction;
|
|
80
|
+
typedef struct VSMap VSMap;
|
|
81
|
+
typedef struct VSLogHandle VSLogHandle;
|
|
82
|
+
typedef struct VSFrameContext VSFrameContext;
|
|
83
|
+
typedef struct VSPLUGINAPI VSPLUGINAPI;
|
|
84
|
+
typedef struct VSAPI VSAPI;
|
|
85
|
+
|
|
86
|
+
typedef enum VSColorFamily {
|
|
87
|
+
cfUndefined = 0,
|
|
88
|
+
cfGray = 1,
|
|
89
|
+
cfRGB = 2,
|
|
90
|
+
cfYUV = 3
|
|
91
|
+
} VSColorFamily;
|
|
92
|
+
|
|
93
|
+
typedef enum VSSampleType {
|
|
94
|
+
stInteger = 0,
|
|
95
|
+
stFloat = 1
|
|
96
|
+
} VSSampleType;
|
|
97
|
+
|
|
98
|
+
#define VS_MAKE_VIDEO_ID(colorFamily, sampleType, bitsPerSample, subSamplingW, subSamplingH) ((colorFamily << 28) | (sampleType << 24) | (bitsPerSample << 16) | (subSamplingW << 8) | (subSamplingH << 0))
|
|
99
|
+
|
|
100
|
+
typedef enum VSPresetVideoFormat {
|
|
101
|
+
pfNone = 0,
|
|
102
|
+
|
|
103
|
+
pfGray8 = VS_MAKE_VIDEO_ID(cfGray, stInteger, 8, 0, 0),
|
|
104
|
+
pfGray9 = VS_MAKE_VIDEO_ID(cfGray, stInteger, 9, 0, 0),
|
|
105
|
+
pfGray10 = VS_MAKE_VIDEO_ID(cfGray, stInteger, 10, 0, 0),
|
|
106
|
+
pfGray12 = VS_MAKE_VIDEO_ID(cfGray, stInteger, 12, 0, 0),
|
|
107
|
+
pfGray14 = VS_MAKE_VIDEO_ID(cfGray, stInteger, 14, 0, 0),
|
|
108
|
+
pfGray16 = VS_MAKE_VIDEO_ID(cfGray, stInteger, 16, 0, 0),
|
|
109
|
+
pfGray32 = VS_MAKE_VIDEO_ID(cfGray, stInteger, 32, 0, 0),
|
|
110
|
+
|
|
111
|
+
pfGrayH = VS_MAKE_VIDEO_ID(cfGray, stFloat, 16, 0, 0),
|
|
112
|
+
pfGrayS = VS_MAKE_VIDEO_ID(cfGray, stFloat, 32, 0, 0),
|
|
113
|
+
|
|
114
|
+
pfYUV410P8 = VS_MAKE_VIDEO_ID(cfYUV, stInteger, 8, 2, 2),
|
|
115
|
+
pfYUV411P8 = VS_MAKE_VIDEO_ID(cfYUV, stInteger, 8, 2, 0),
|
|
116
|
+
pfYUV440P8 = VS_MAKE_VIDEO_ID(cfYUV, stInteger, 8, 0, 1),
|
|
117
|
+
|
|
118
|
+
pfYUV420P8 = VS_MAKE_VIDEO_ID(cfYUV, stInteger, 8, 1, 1),
|
|
119
|
+
pfYUV422P8 = VS_MAKE_VIDEO_ID(cfYUV, stInteger, 8, 1, 0),
|
|
120
|
+
pfYUV444P8 = VS_MAKE_VIDEO_ID(cfYUV, stInteger, 8, 0, 0),
|
|
121
|
+
|
|
122
|
+
pfYUV420P9 = VS_MAKE_VIDEO_ID(cfYUV, stInteger, 9, 1, 1),
|
|
123
|
+
pfYUV422P9 = VS_MAKE_VIDEO_ID(cfYUV, stInteger, 9, 1, 0),
|
|
124
|
+
pfYUV444P9 = VS_MAKE_VIDEO_ID(cfYUV, stInteger, 9, 0, 0),
|
|
125
|
+
|
|
126
|
+
pfYUV420P10 = VS_MAKE_VIDEO_ID(cfYUV, stInteger, 10, 1, 1),
|
|
127
|
+
pfYUV422P10 = VS_MAKE_VIDEO_ID(cfYUV, stInteger, 10, 1, 0),
|
|
128
|
+
pfYUV444P10 = VS_MAKE_VIDEO_ID(cfYUV, stInteger, 10, 0, 0),
|
|
129
|
+
|
|
130
|
+
pfYUV420P12 = VS_MAKE_VIDEO_ID(cfYUV, stInteger, 12, 1, 1),
|
|
131
|
+
pfYUV422P12 = VS_MAKE_VIDEO_ID(cfYUV, stInteger, 12, 1, 0),
|
|
132
|
+
pfYUV444P12 = VS_MAKE_VIDEO_ID(cfYUV, stInteger, 12, 0, 0),
|
|
133
|
+
|
|
134
|
+
pfYUV420P14 = VS_MAKE_VIDEO_ID(cfYUV, stInteger, 14, 1, 1),
|
|
135
|
+
pfYUV422P14 = VS_MAKE_VIDEO_ID(cfYUV, stInteger, 14, 1, 0),
|
|
136
|
+
pfYUV444P14 = VS_MAKE_VIDEO_ID(cfYUV, stInteger, 14, 0, 0),
|
|
137
|
+
|
|
138
|
+
pfYUV420P16 = VS_MAKE_VIDEO_ID(cfYUV, stInteger, 16, 1, 1),
|
|
139
|
+
pfYUV422P16 = VS_MAKE_VIDEO_ID(cfYUV, stInteger, 16, 1, 0),
|
|
140
|
+
pfYUV444P16 = VS_MAKE_VIDEO_ID(cfYUV, stInteger, 16, 0, 0),
|
|
141
|
+
|
|
142
|
+
pfYUV420PH = VS_MAKE_VIDEO_ID(cfYUV, stFloat, 16, 1, 1),
|
|
143
|
+
pfYUV420PS = VS_MAKE_VIDEO_ID(cfYUV, stFloat, 32, 1, 1),
|
|
144
|
+
pfYUV422PH = VS_MAKE_VIDEO_ID(cfYUV, stFloat, 16, 1, 0),
|
|
145
|
+
pfYUV422PS = VS_MAKE_VIDEO_ID(cfYUV, stFloat, 32, 1, 0),
|
|
146
|
+
pfYUV444PH = VS_MAKE_VIDEO_ID(cfYUV, stFloat, 16, 0, 0),
|
|
147
|
+
pfYUV444PS = VS_MAKE_VIDEO_ID(cfYUV, stFloat, 32, 0, 0),
|
|
148
|
+
|
|
149
|
+
pfRGB24 = VS_MAKE_VIDEO_ID(cfRGB, stInteger, 8, 0, 0),
|
|
150
|
+
pfRGB27 = VS_MAKE_VIDEO_ID(cfRGB, stInteger, 9, 0, 0),
|
|
151
|
+
pfRGB30 = VS_MAKE_VIDEO_ID(cfRGB, stInteger, 10, 0, 0),
|
|
152
|
+
pfRGB36 = VS_MAKE_VIDEO_ID(cfRGB, stInteger, 12, 0, 0),
|
|
153
|
+
pfRGB42 = VS_MAKE_VIDEO_ID(cfRGB, stInteger, 14, 0, 0),
|
|
154
|
+
pfRGB48 = VS_MAKE_VIDEO_ID(cfRGB, stInteger, 16, 0, 0),
|
|
155
|
+
|
|
156
|
+
pfRGBH = VS_MAKE_VIDEO_ID(cfRGB, stFloat, 16, 0, 0),
|
|
157
|
+
pfRGBS = VS_MAKE_VIDEO_ID(cfRGB, stFloat, 32, 0, 0),
|
|
158
|
+
} VSPresetVideoFormat;
|
|
159
|
+
|
|
160
|
+
#undef VS_MAKE_VIDEO_ID
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
typedef enum VSFilterMode {
|
|
164
|
+
fmParallel = 0, /* completely parallel execution */
|
|
165
|
+
fmParallelRequests = 1, /* for filters that are single-threaded in nature but can request one or more frames they need in advance */
|
|
166
|
+
fmUnordered = 2, /* for filters that modify their internal state every request like source filters that read a file */
|
|
167
|
+
fmFrameState = 3 /* DO NOT USE UNLESS ABSOLUTELY NECESSARY, for compatibility with external code that can only keep the processing state of a single frame at a time */
|
|
168
|
+
} VSFilterMode;
|
|
169
|
+
|
|
170
|
+
typedef enum VSMediaType {
|
|
171
|
+
mtVideo = 1,
|
|
172
|
+
mtAudio = 2
|
|
173
|
+
} VSMediaType;
|
|
174
|
+
|
|
175
|
+
typedef struct VSVideoFormat {
|
|
176
|
+
int colorFamily; /* see VSColorFamily */
|
|
177
|
+
int sampleType; /* see VSSampleType */
|
|
178
|
+
int bitsPerSample; /* number of significant bits */
|
|
179
|
+
int bytesPerSample; /* actual storage is always in a power of 2 and the smallest possible that can fit the number of bits used per sample */
|
|
180
|
+
|
|
181
|
+
int subSamplingW; /* log2 subsampling factor, applied to second and third plane */
|
|
182
|
+
int subSamplingH; /* log2 subsampling factor, applied to second and third plane */
|
|
183
|
+
|
|
184
|
+
int numPlanes; /* implicit from colorFamily */
|
|
185
|
+
} VSVideoFormat;
|
|
186
|
+
|
|
187
|
+
typedef enum VSAudioChannels {
|
|
188
|
+
acFrontLeft = 0,
|
|
189
|
+
acFrontRight = 1,
|
|
190
|
+
acFrontCenter = 2,
|
|
191
|
+
acLowFrequency = 3,
|
|
192
|
+
acBackLeft = 4,
|
|
193
|
+
acBackRight = 5,
|
|
194
|
+
acFrontLeftOFCenter = 6,
|
|
195
|
+
acFrontRightOFCenter = 7,
|
|
196
|
+
acBackCenter = 8,
|
|
197
|
+
acSideLeft = 9,
|
|
198
|
+
acSideRight = 10,
|
|
199
|
+
acTopCenter = 11,
|
|
200
|
+
acTopFrontLeft = 12,
|
|
201
|
+
acTopFrontCenter = 13,
|
|
202
|
+
acTopFrontRight = 14,
|
|
203
|
+
acTopBackLeft = 15,
|
|
204
|
+
acTopBackCenter = 16,
|
|
205
|
+
acTopBackRight = 17,
|
|
206
|
+
acStereoLeft = 29,
|
|
207
|
+
acStereoRight = 30,
|
|
208
|
+
acWideLeft = 31,
|
|
209
|
+
acWideRight = 32,
|
|
210
|
+
acSurroundDirectLeft = 33,
|
|
211
|
+
acSurroundDirectRight = 34,
|
|
212
|
+
acLowFrequency2 = 35
|
|
213
|
+
} VSAudioChannels;
|
|
214
|
+
|
|
215
|
+
typedef struct VSAudioFormat {
|
|
216
|
+
int sampleType;
|
|
217
|
+
int bitsPerSample;
|
|
218
|
+
int bytesPerSample; /* implicit from bitsPerSample */
|
|
219
|
+
int numChannels; /* implicit from channelLayout */
|
|
220
|
+
uint64_t channelLayout;
|
|
221
|
+
} VSAudioFormat;
|
|
222
|
+
|
|
223
|
+
typedef enum VSPropertyType {
|
|
224
|
+
ptUnset = 0,
|
|
225
|
+
ptInt = 1,
|
|
226
|
+
ptFloat = 2,
|
|
227
|
+
ptData = 3,
|
|
228
|
+
ptFunction = 4,
|
|
229
|
+
ptVideoNode = 5,
|
|
230
|
+
ptAudioNode = 6,
|
|
231
|
+
ptVideoFrame = 7,
|
|
232
|
+
ptAudioFrame = 8
|
|
233
|
+
} VSPropertyType;
|
|
234
|
+
|
|
235
|
+
typedef enum VSMapPropertyError {
|
|
236
|
+
peSuccess = 0,
|
|
237
|
+
peUnset = 1, /* no key exists */
|
|
238
|
+
peType = 2, /* key exists but not of a compatible type */
|
|
239
|
+
peIndex = 4, /* index out of bounds */
|
|
240
|
+
peError = 3 /* map has error state set */
|
|
241
|
+
} VSMapPropertyError;
|
|
242
|
+
|
|
243
|
+
typedef enum VSMapAppendMode {
|
|
244
|
+
maReplace = 0,
|
|
245
|
+
maAppend = 1
|
|
246
|
+
} VSMapAppendMode;
|
|
247
|
+
|
|
248
|
+
typedef struct VSCoreInfo {
|
|
249
|
+
const char *versionString;
|
|
250
|
+
int core;
|
|
251
|
+
int api;
|
|
252
|
+
int numThreads;
|
|
253
|
+
int64_t maxFramebufferSize;
|
|
254
|
+
int64_t usedFramebufferSize;
|
|
255
|
+
} VSCoreInfo;
|
|
256
|
+
|
|
257
|
+
typedef struct VSCoreInfo2 {
|
|
258
|
+
const char *versionString;
|
|
259
|
+
int coreVersion;
|
|
260
|
+
int apiVersion;
|
|
261
|
+
int creationFlags;
|
|
262
|
+
int numThreads;
|
|
263
|
+
int64_t maxFramebufferSize;
|
|
264
|
+
int64_t usedFramebufferSize;
|
|
265
|
+
} VSCoreInfo2;
|
|
266
|
+
|
|
267
|
+
typedef struct VSVideoInfo {
|
|
268
|
+
VSVideoFormat format;
|
|
269
|
+
int64_t fpsNum;
|
|
270
|
+
int64_t fpsDen;
|
|
271
|
+
int width;
|
|
272
|
+
int height;
|
|
273
|
+
int numFrames;
|
|
274
|
+
} VSVideoInfo;
|
|
275
|
+
|
|
276
|
+
typedef struct VSAudioInfo {
|
|
277
|
+
VSAudioFormat format;
|
|
278
|
+
int sampleRate;
|
|
279
|
+
int64_t numSamples;
|
|
280
|
+
int numFrames; /* the total number of audio frames needed to hold numSamples, implicit from numSamples when calling createAudioFilter */
|
|
281
|
+
} VSAudioInfo;
|
|
282
|
+
|
|
283
|
+
typedef enum VSActivationReason {
|
|
284
|
+
arInitial = 0,
|
|
285
|
+
arAllFramesReady = 1,
|
|
286
|
+
arError = -1
|
|
287
|
+
} VSActivationReason;
|
|
288
|
+
|
|
289
|
+
typedef enum VSMessageType {
|
|
290
|
+
mtDebug = 0,
|
|
291
|
+
mtInformation = 1,
|
|
292
|
+
mtWarning = 2,
|
|
293
|
+
mtCritical = 3,
|
|
294
|
+
mtFatal = 4 /* also terminates the process, should generally not be used by normal filters */
|
|
295
|
+
} VSMessageType;
|
|
296
|
+
|
|
297
|
+
typedef enum VSCoreCreationFlags {
|
|
298
|
+
ccfEnableGraphInspection = 1,
|
|
299
|
+
ccfDisableAutoLoading = 2,
|
|
300
|
+
ccfDisableLibraryUnloading = 4,
|
|
301
|
+
ccfEnableFrameRefDebug = 8
|
|
302
|
+
} VSCoreCreationFlags;
|
|
303
|
+
|
|
304
|
+
typedef enum VSPluginConfigFlags {
|
|
305
|
+
pcModifiable = 1
|
|
306
|
+
} VSPluginConfigFlags;
|
|
307
|
+
|
|
308
|
+
typedef enum VSDataTypeHint {
|
|
309
|
+
dtUnknown = -1,
|
|
310
|
+
dtBinary = 0,
|
|
311
|
+
dtUtf8 = 1
|
|
312
|
+
} VSDataTypeHint;
|
|
313
|
+
|
|
314
|
+
typedef enum VSRequestPattern {
|
|
315
|
+
rpGeneral = 0, /* General pattern */
|
|
316
|
+
rpNoFrameReuse = 1, /* When requesting all output frames from the filter no frame will be requested more than once from this input clip, never requests frames beyond the end of the clip */
|
|
317
|
+
rpStrictSpatial = 2 /* Always (and only) requests frame n from the input clip when generating output frame n, never requests frames beyond the end of the clip */
|
|
318
|
+
#if VAPOURSYNTH_API_MINOR >= 1
|
|
319
|
+
,
|
|
320
|
+
rpFrameReuseLastOnly = 3 /* Added in API 4.1, This modes is basically identical rpNoFrameReuse except that it hints the last frame may be requested multiple times */
|
|
321
|
+
#endif
|
|
322
|
+
} VSRequestPattern;
|
|
323
|
+
|
|
324
|
+
typedef enum VSCacheMode {
|
|
325
|
+
cmAuto = -1,
|
|
326
|
+
cmForceDisable = 0,
|
|
327
|
+
cmForceEnable = 1
|
|
328
|
+
} VSCacheMode;
|
|
329
|
+
|
|
330
|
+
/* Core entry point */
|
|
331
|
+
typedef const VSAPI *(VS_CC *VSGetVapourSynthAPI)(int version);
|
|
332
|
+
|
|
333
|
+
/* Plugin, function and filter related */
|
|
334
|
+
typedef void (VS_CC *VSPublicFunction)(const VSMap *in, VSMap *out, void *userData, VSCore *core, const VSAPI *vsapi);
|
|
335
|
+
typedef void (VS_CC *VSInitPlugin)(VSPlugin *plugin, const VSPLUGINAPI *vspapi);
|
|
336
|
+
typedef void (VS_CC *VSFreeFunctionData)(void *userData);
|
|
337
|
+
typedef const VSFrame *(VS_CC *VSFilterGetFrame)(int n, int activationReason, void *instanceData, void **frameData, VSFrameContext *frameCtx, VSCore *core, const VSAPI *vsapi);
|
|
338
|
+
typedef void (VS_CC *VSFilterFree)(void *instanceData, VSCore *core, const VSAPI *vsapi);
|
|
339
|
+
|
|
340
|
+
/* Other */
|
|
341
|
+
typedef void (VS_CC *VSFrameDoneCallback)(void *userData, const VSFrame *f, int n, VSNode *node, const char *errorMsg);
|
|
342
|
+
typedef void (VS_CC *VSLogHandler)(int msgType, const char *msg, void *userData);
|
|
343
|
+
typedef void (VS_CC *VSLogHandlerFree)(void *userData);
|
|
344
|
+
|
|
345
|
+
typedef struct VSPLUGINAPI {
|
|
346
|
+
int (VS_CC *getAPIVersion)(void) VS_NOEXCEPT; /* returns VAPOURSYNTH_API_VERSION of the library */
|
|
347
|
+
int (VS_CC *configPlugin)(const char *identifier, const char *pluginNamespace, const char *name, int pluginVersion, int apiVersion, int flags, VSPlugin *plugin) VS_NOEXCEPT; /* use the VS_MAKE_VERSION macro for pluginVersion */
|
|
348
|
+
int (VS_CC *registerFunction)(const char *name, const char *args, const char *returnType, VSPublicFunction argsFunc, void *functionData, VSPlugin *plugin) VS_NOEXCEPT; /* non-zero return value on success */
|
|
349
|
+
} VSPLUGINAPI;
|
|
350
|
+
|
|
351
|
+
typedef struct VSFilterDependency {
|
|
352
|
+
VSNode *source;
|
|
353
|
+
int requestPattern; /* VSRequestPattern */
|
|
354
|
+
} VSFilterDependency;
|
|
355
|
+
|
|
356
|
+
struct VSAPI {
|
|
357
|
+
/* Audio and video filter related including nodes */
|
|
358
|
+
void (VS_CC *createVideoFilter)(VSMap *out, const char *name, const VSVideoInfo *vi, VSFilterGetFrame getFrame, VSFilterFree free, int filterMode, const VSFilterDependency *dependencies, int numDeps, void *instanceData, VSCore *core) VS_NOEXCEPT; /* output nodes are appended to the clip key in the out map */
|
|
359
|
+
VSNode *(VS_CC *createVideoFilter2)(const char *name, const VSVideoInfo *vi, VSFilterGetFrame getFrame, VSFilterFree free, int filterMode, const VSFilterDependency *dependencies, int numDeps, void *instanceData, VSCore *core) VS_NOEXCEPT; /* same as createVideoFilter but returns a pointer to the VSNode directly or NULL on failure */
|
|
360
|
+
void (VS_CC *createAudioFilter)(VSMap *out, const char *name, const VSAudioInfo *ai, VSFilterGetFrame getFrame, VSFilterFree free, int filterMode, const VSFilterDependency *dependencies, int numDeps, void *instanceData, VSCore *core) VS_NOEXCEPT; /* output nodes are appended to the clip key in the out map */
|
|
361
|
+
VSNode *(VS_CC *createAudioFilter2)(const char *name, const VSAudioInfo *ai, VSFilterGetFrame getFrame, VSFilterFree free, int filterMode, const VSFilterDependency *dependencies, int numDeps, void *instanceData, VSCore *core) VS_NOEXCEPT; /* same as createAudioFilter but returns a pointer to the VSNode directly or NULL on failure */
|
|
362
|
+
int (VS_CC *setLinearFilter)(VSNode *node) VS_NOEXCEPT; /* Use right after create*Filter*, sets the correct cache mode for using the cacheFrame API and returns the recommended upper number of additional frames to cache per request */
|
|
363
|
+
void (VS_CC *setCacheMode)(VSNode *node, int mode) VS_NOEXCEPT; /* VSCacheMode, changing the cache mode also resets all options to their default */
|
|
364
|
+
void (VS_CC *setCacheOptions)(VSNode *node, int fixedSize, int maxSize, int maxHistorySize) VS_NOEXCEPT; /* passing -1 means no change */
|
|
365
|
+
|
|
366
|
+
void (VS_CC *freeNode)(VSNode *node) VS_NOEXCEPT;
|
|
367
|
+
VSNode *(VS_CC *addNodeRef)(VSNode *node) VS_NOEXCEPT;
|
|
368
|
+
int (VS_CC *getNodeType)(VSNode *node) VS_NOEXCEPT; /* returns VSMediaType */
|
|
369
|
+
const VSVideoInfo *(VS_CC *getVideoInfo)(VSNode *node) VS_NOEXCEPT;
|
|
370
|
+
const VSAudioInfo *(VS_CC *getAudioInfo)(VSNode *node) VS_NOEXCEPT;
|
|
371
|
+
|
|
372
|
+
/* Frame related functions */
|
|
373
|
+
VSFrame *(VS_CC *newVideoFrame)(const VSVideoFormat *format, int width, int height, const VSFrame *propSrc, VSCore *core) VS_NOEXCEPT;
|
|
374
|
+
VSFrame *(VS_CC *newVideoFrame2)(const VSVideoFormat *format, int width, int height, const VSFrame **planeSrc, const int *planes, const VSFrame *propSrc, VSCore *core) VS_NOEXCEPT; /* same as newVideoFrame but allows the specified planes to be effectively copied from the source frames */
|
|
375
|
+
VSFrame *(VS_CC *newAudioFrame)(const VSAudioFormat *format, int numSamples, const VSFrame *propSrc, VSCore *core) VS_NOEXCEPT;
|
|
376
|
+
VSFrame *(VS_CC *newAudioFrame2)(const VSAudioFormat *format, int numSamples, const VSFrame **channelSrc, const int *channels, const VSFrame *propSrc, VSCore *core) VS_NOEXCEPT; /* same as newAudioFrame but allows the specified channels to be effectively copied from the source frames */
|
|
377
|
+
void (VS_CC *freeFrame)(const VSFrame *f) VS_NOEXCEPT;
|
|
378
|
+
const VSFrame *(VS_CC *addFrameRef)(const VSFrame *f) VS_NOEXCEPT;
|
|
379
|
+
VSFrame *(VS_CC *copyFrame)(const VSFrame *f, VSCore *core) VS_NOEXCEPT;
|
|
380
|
+
const VSMap *(VS_CC *getFramePropertiesRO)(const VSFrame *f) VS_NOEXCEPT;
|
|
381
|
+
VSMap *(VS_CC *getFramePropertiesRW)(VSFrame *f) VS_NOEXCEPT;
|
|
382
|
+
|
|
383
|
+
ptrdiff_t (VS_CC *getStride)(const VSFrame *f, int plane) VS_NOEXCEPT;
|
|
384
|
+
const uint8_t *(VS_CC *getReadPtr)(const VSFrame *f, int plane) VS_NOEXCEPT;
|
|
385
|
+
uint8_t *(VS_CC *getWritePtr)(VSFrame *f, int plane) VS_NOEXCEPT; /* calling this function invalidates previously gotten read pointers to the same frame */
|
|
386
|
+
|
|
387
|
+
const VSVideoFormat *(VS_CC *getVideoFrameFormat)(const VSFrame *f) VS_NOEXCEPT;
|
|
388
|
+
const VSAudioFormat *(VS_CC *getAudioFrameFormat)(const VSFrame *f) VS_NOEXCEPT;
|
|
389
|
+
int (VS_CC *getFrameType)(const VSFrame *f) VS_NOEXCEPT; /* returns VSMediaType */
|
|
390
|
+
int (VS_CC *getFrameWidth)(const VSFrame *f, int plane) VS_NOEXCEPT;
|
|
391
|
+
int (VS_CC *getFrameHeight)(const VSFrame *f, int plane) VS_NOEXCEPT;
|
|
392
|
+
int (VS_CC *getFrameLength)(const VSFrame *f) VS_NOEXCEPT; /* returns the number of samples for audio frames */
|
|
393
|
+
|
|
394
|
+
/* General format functions */
|
|
395
|
+
int (VS_CC *getVideoFormatName)(const VSVideoFormat *format, char *buffer) VS_NOEXCEPT; /* up to 32 characters including terminating null may be written to the buffer, non-zero return value on success */
|
|
396
|
+
int (VS_CC *getAudioFormatName)(const VSAudioFormat *format, char *buffer) VS_NOEXCEPT; /* up to 32 characters including terminating null may be written to the buffer, non-zero return value on success */
|
|
397
|
+
int (VS_CC *queryVideoFormat)(VSVideoFormat *format, int colorFamily, int sampleType, int bitsPerSample, int subSamplingW, int subSamplingH, VSCore *core) VS_NOEXCEPT; /* non-zero return value on success */
|
|
398
|
+
int (VS_CC *queryAudioFormat)(VSAudioFormat *format, int sampleType, int bitsPerSample, uint64_t channelLayout, VSCore *core) VS_NOEXCEPT; /* non-zero return value on success */
|
|
399
|
+
uint32_t (VS_CC *queryVideoFormatID)(int colorFamily, int sampleType, int bitsPerSample, int subSamplingW, int subSamplingH, VSCore *core) VS_NOEXCEPT; /* returns 0 on failure */
|
|
400
|
+
int (VS_CC *getVideoFormatByID)(VSVideoFormat *format, uint32_t id, VSCore *core) VS_NOEXCEPT; /* non-zero return value on success */
|
|
401
|
+
|
|
402
|
+
/* Frame request and filter getframe functions */
|
|
403
|
+
const VSFrame *(VS_CC *getFrame)(int n, VSNode *node, char *errorMsg, int bufSize) VS_NOEXCEPT; /* only for external applications using the core as a library or for requesting frames in a filter constructor, do not use inside a filter's getframe function */
|
|
404
|
+
void (VS_CC *getFrameAsync)(int n, VSNode *node, VSFrameDoneCallback callback, void *userData) VS_NOEXCEPT; /* only for external applications using the core as a library or for requesting frames in a filter constructor, do not use inside a filter's getframe function */
|
|
405
|
+
const VSFrame *(VS_CC *getFrameFilter)(int n, VSNode *node, VSFrameContext *frameCtx) VS_NOEXCEPT; /* only use inside a filter's getframe function */
|
|
406
|
+
void (VS_CC *requestFrameFilter)(int n, VSNode *node, VSFrameContext *frameCtx) VS_NOEXCEPT; /* only use inside a filter's getframe function */
|
|
407
|
+
void (VS_CC *releaseFrameEarly)(VSNode *node, int n, VSFrameContext *frameCtx) VS_NOEXCEPT; /* only use inside a filter's getframe function, unless this function is called a requested frame is kept in memory until the end of processing the current frame */
|
|
408
|
+
void (VS_CC *cacheFrame)(const VSFrame *frame, int n, VSFrameContext *frameCtx) VS_NOEXCEPT; /* used to store intermediate frames in cache, useful for filters where random access is slow, must call setLinearFilter on the node before using or the result is undefined */
|
|
409
|
+
void (VS_CC *setFilterError)(const char *errorMessage, VSFrameContext *frameCtx) VS_NOEXCEPT; /* used to signal errors in the filter getframe function */
|
|
410
|
+
|
|
411
|
+
/* External functions */
|
|
412
|
+
VSFunction *(VS_CC *createFunction)(VSPublicFunction func, void *userData, VSFreeFunctionData free, VSCore *core) VS_NOEXCEPT;
|
|
413
|
+
void (VS_CC *freeFunction)(VSFunction *f) VS_NOEXCEPT;
|
|
414
|
+
VSFunction *(VS_CC *addFunctionRef)(VSFunction *f) VS_NOEXCEPT;
|
|
415
|
+
void (VS_CC *callFunction)(VSFunction *func, const VSMap *in, VSMap *out) VS_NOEXCEPT;
|
|
416
|
+
|
|
417
|
+
/* Map and property access functions */
|
|
418
|
+
VSMap *(VS_CC *createMap)(void) VS_NOEXCEPT;
|
|
419
|
+
void (VS_CC *freeMap)(VSMap *map) VS_NOEXCEPT;
|
|
420
|
+
void (VS_CC *clearMap)(VSMap *map) VS_NOEXCEPT;
|
|
421
|
+
void (VS_CC *copyMap)(const VSMap *src, VSMap *dst) VS_NOEXCEPT; /* copies all values in src to dst, if a key already exists in dst it's replaced */
|
|
422
|
+
|
|
423
|
+
void (VS_CC *mapSetError)(VSMap *map, const char *errorMessage) VS_NOEXCEPT; /* used to signal errors outside filter getframe function */
|
|
424
|
+
const char *(VS_CC *mapGetError)(const VSMap *map) VS_NOEXCEPT; /* used to query errors, returns 0 if no error */
|
|
425
|
+
|
|
426
|
+
int (VS_CC *mapNumKeys)(const VSMap *map) VS_NOEXCEPT;
|
|
427
|
+
const char *(VS_CC *mapGetKey)(const VSMap *map, int index) VS_NOEXCEPT;
|
|
428
|
+
int (VS_CC *mapDeleteKey)(VSMap *map, const char *key) VS_NOEXCEPT;
|
|
429
|
+
int (VS_CC *mapNumElements)(const VSMap *map, const char *key) VS_NOEXCEPT; /* returns -1 if a key doesn't exist */
|
|
430
|
+
int (VS_CC *mapGetType)(const VSMap *map, const char *key) VS_NOEXCEPT; /* returns VSPropertyType */
|
|
431
|
+
int (VS_CC *mapSetEmpty)(VSMap *map, const char *key, int type) VS_NOEXCEPT;
|
|
432
|
+
|
|
433
|
+
int64_t (VS_CC *mapGetInt)(const VSMap *map, const char *key, int index, int *error) VS_NOEXCEPT;
|
|
434
|
+
int (VS_CC *mapGetIntSaturated)(const VSMap *map, const char *key, int index, int *error) VS_NOEXCEPT;
|
|
435
|
+
const int64_t *(VS_CC *mapGetIntArray)(const VSMap *map, const char *key, int *error) VS_NOEXCEPT;
|
|
436
|
+
int (VS_CC *mapSetInt)(VSMap *map, const char *key, int64_t i, int append) VS_NOEXCEPT;
|
|
437
|
+
int (VS_CC *mapSetIntArray)(VSMap *map, const char *key, const int64_t *i, int size) VS_NOEXCEPT;
|
|
438
|
+
|
|
439
|
+
double (VS_CC *mapGetFloat)(const VSMap *map, const char *key, int index, int *error) VS_NOEXCEPT;
|
|
440
|
+
float (VS_CC *mapGetFloatSaturated)(const VSMap *map, const char *key, int index, int *error) VS_NOEXCEPT;
|
|
441
|
+
const double *(VS_CC *mapGetFloatArray)(const VSMap *map, const char *key, int *error) VS_NOEXCEPT;
|
|
442
|
+
int (VS_CC *mapSetFloat)(VSMap *map, const char *key, double d, int append) VS_NOEXCEPT;
|
|
443
|
+
int (VS_CC *mapSetFloatArray)(VSMap *map, const char *key, const double *d, int size) VS_NOEXCEPT;
|
|
444
|
+
|
|
445
|
+
const char *(VS_CC *mapGetData)(const VSMap *map, const char *key, int index, int *error) VS_NOEXCEPT;
|
|
446
|
+
int (VS_CC *mapGetDataSize)(const VSMap *map, const char *key, int index, int *error) VS_NOEXCEPT;
|
|
447
|
+
int (VS_CC *mapGetDataTypeHint)(const VSMap *map, const char *key, int index, int *error) VS_NOEXCEPT; /* returns VSDataTypeHint */
|
|
448
|
+
int (VS_CC *mapSetData)(VSMap *map, const char *key, const char *data, int size, int type, int append) VS_NOEXCEPT;
|
|
449
|
+
|
|
450
|
+
VSNode *(VS_CC *mapGetNode)(const VSMap *map, const char *key, int index, int *error) VS_NOEXCEPT;
|
|
451
|
+
int (VS_CC *mapSetNode)(VSMap *map, const char *key, VSNode *node, int append) VS_NOEXCEPT; /* returns 0 on success */
|
|
452
|
+
int (VS_CC *mapConsumeNode)(VSMap *map, const char *key, VSNode *node, int append) VS_NOEXCEPT; /* always consumes the reference, even on error */
|
|
453
|
+
|
|
454
|
+
const VSFrame *(VS_CC *mapGetFrame)(const VSMap *map, const char *key, int index, int *error) VS_NOEXCEPT;
|
|
455
|
+
int (VS_CC *mapSetFrame)(VSMap *map, const char *key, const VSFrame *f, int append) VS_NOEXCEPT; /* returns 0 on success */
|
|
456
|
+
int (VS_CC *mapConsumeFrame)(VSMap *map, const char *key, const VSFrame *f, int append) VS_NOEXCEPT; /* always consumes the reference, even on error */
|
|
457
|
+
|
|
458
|
+
VSFunction *(VS_CC *mapGetFunction)(const VSMap *map, const char *key, int index, int *error) VS_NOEXCEPT;
|
|
459
|
+
int (VS_CC *mapSetFunction)(VSMap *map, const char *key, VSFunction *func, int append) VS_NOEXCEPT; /* returns 0 on success */
|
|
460
|
+
int (VS_CC *mapConsumeFunction)(VSMap *map, const char *key, VSFunction *func, int append) VS_NOEXCEPT; /* always consumes the reference, even on error */
|
|
461
|
+
|
|
462
|
+
/* Plugin and plugin function related */
|
|
463
|
+
int (VS_CC *registerFunction)(const char *name, const char *args, const char *returnType, VSPublicFunction argsFunc, void *functionData, VSPlugin *plugin) VS_NOEXCEPT; /* non-zero return value on success */
|
|
464
|
+
VSPlugin *(VS_CC *getPluginByID)(const char *identifier, VSCore *core) VS_NOEXCEPT;
|
|
465
|
+
VSPlugin *(VS_CC *getPluginByNamespace)(const char *ns, VSCore *core) VS_NOEXCEPT;
|
|
466
|
+
VSPlugin *(VS_CC *getNextPlugin)(VSPlugin *plugin, VSCore *core) VS_NOEXCEPT; /* pass NULL to get the first plugin */
|
|
467
|
+
const char *(VS_CC *getPluginName)(VSPlugin *plugin) VS_NOEXCEPT;
|
|
468
|
+
const char *(VS_CC *getPluginID)(VSPlugin *plugin) VS_NOEXCEPT;
|
|
469
|
+
const char *(VS_CC *getPluginNamespace)(VSPlugin *plugin) VS_NOEXCEPT;
|
|
470
|
+
VSPluginFunction *(VS_CC *getNextPluginFunction)(VSPluginFunction *func, VSPlugin *plugin) VS_NOEXCEPT; /* pass NULL to get the first plugin function */
|
|
471
|
+
VSPluginFunction *(VS_CC *getPluginFunctionByName)(const char *name, VSPlugin *plugin) VS_NOEXCEPT;
|
|
472
|
+
const char *(VS_CC *getPluginFunctionName)(VSPluginFunction *func) VS_NOEXCEPT;
|
|
473
|
+
const char *(VS_CC *getPluginFunctionArguments)(VSPluginFunction *func) VS_NOEXCEPT; /* returns an argument format string */
|
|
474
|
+
const char *(VS_CC *getPluginFunctionReturnType)(VSPluginFunction *func) VS_NOEXCEPT; /* returns an argument format string */
|
|
475
|
+
const char *(VS_CC *getPluginPath)(const VSPlugin *plugin) VS_NOEXCEPT; /* the full path to the loaded library file containing the plugin entry point */
|
|
476
|
+
int (VS_CC *getPluginVersion)(const VSPlugin *plugin) VS_NOEXCEPT;
|
|
477
|
+
VSMap *(VS_CC *invoke)(VSPlugin *plugin, const char *name, const VSMap *args) VS_NOEXCEPT; /* user must free the returned VSMap */
|
|
478
|
+
|
|
479
|
+
/* Core and information */
|
|
480
|
+
VSCore *(VS_CC *createCore)(int flags) VS_NOEXCEPT; /* flags uses the VSCoreCreationFlags enum */
|
|
481
|
+
void (VS_CC *freeCore)(VSCore *core) VS_NOEXCEPT; /* only call this function after all node, frame and function references belonging to the core have been freed */
|
|
482
|
+
int64_t (VS_CC *setMaxCacheSize)(int64_t bytes, VSCore *core) VS_NOEXCEPT; /* the total cache size at which vapoursynth more aggressively tries to reclaim memory, it is not a hard limit */
|
|
483
|
+
int (VS_CC *setThreadCount)(int threads, VSCore *core) VS_NOEXCEPT; /* setting threads to 0 means automatic detection */
|
|
484
|
+
void (VS_CC *getCoreInfo)(VSCore *core, VSCoreInfo *info) VS_NOEXCEPT;
|
|
485
|
+
int (VS_CC *getAPIVersion)(void) VS_NOEXCEPT;
|
|
486
|
+
|
|
487
|
+
/* Message handler */
|
|
488
|
+
void (VS_CC *logMessage)(int msgType, const char *msg, VSCore *core) VS_NOEXCEPT;
|
|
489
|
+
VSLogHandle *(VS_CC *addLogHandler)(VSLogHandler handler, VSLogHandlerFree free, void *userData, VSCore *core) VS_NOEXCEPT; /* free and userData can be NULL, returns a handle that can be passed to removeLogHandler */
|
|
490
|
+
int (VS_CC *removeLogHandler)(VSLogHandle *handle, VSCore *core) VS_NOEXCEPT; /* returns non-zero if successfully removed */
|
|
491
|
+
|
|
492
|
+
/* Added in API 4.1, mostly graph and node inspection, PLEASE DON'T USE INSIDE FILTERS */
|
|
493
|
+
#if VAPOURSYNTH_API_MINOR >= 1
|
|
494
|
+
/* Additional cache management to free memory */
|
|
495
|
+
void (VS_CC *clearNodeCache)(VSNode *node) VS_NOEXCEPT; /* clears the cache of the specified node */
|
|
496
|
+
void (VS_CC *clearCoreCaches)(VSCore *core) VS_NOEXCEPT; /* clears all caches belonging to the specified core */
|
|
497
|
+
|
|
498
|
+
/* Basic node information */
|
|
499
|
+
const char *(VS_CC *getNodeName)(VSNode *node) VS_NOEXCEPT; /* the name passed to create*Filter */
|
|
500
|
+
int (VS_CC *getNodeFilterMode)(VSNode *node) VS_NOEXCEPT; /* returns VSFilterMode */
|
|
501
|
+
int (VS_CC *getNumNodeDependencies)(VSNode *node) VS_NOEXCEPT;
|
|
502
|
+
const VSFilterDependency *(VS_CC *getNodeDependency)(VSNode *node, int index) VS_NOEXCEPT;
|
|
503
|
+
|
|
504
|
+
/* Node timing functions */
|
|
505
|
+
int (VS_CC *getCoreNodeTiming)(VSCore *core) VS_NOEXCEPT; /* non-zero when filter timing is enabled */
|
|
506
|
+
void (VS_CC *setCoreNodeTiming)(VSCore *core, int enable) VS_NOEXCEPT; /* non-zero enables filter timing, note that disabling simply stops the counters from incrementing */
|
|
507
|
+
int64_t (VS_CC *getNodeProcessingTime)(VSNode *node, int reset) VS_NOEXCEPT; /* time spent processing frames in nanoseconds, reset sets the counter to 0 again */
|
|
508
|
+
int64_t (VS_CC *getFreedNodeProcessingTime)(VSCore *core, int reset) VS_NOEXCEPT; /* time spent processing frames in nanoseconds in all destroyed nodes, reset sets the counter to 0 again */
|
|
509
|
+
|
|
510
|
+
/* Added in API 4.2 */
|
|
511
|
+
#if VAPOURSYNTH_API_MINOR >= 2
|
|
512
|
+
void (VS_CC *getCoreInfo2)(VSCore *core, VSCoreInfo2 *info) VS_NOEXCEPT;
|
|
513
|
+
|
|
514
|
+
#if defined(VS_GRAPH_API)
|
|
515
|
+
/* !!! Experimental/expensive graph information, these function require both the major and minor version to match exactly when using them !!!
|
|
516
|
+
*
|
|
517
|
+
* These functions only exist to retrieve internal details for debug purposes and graph visualization
|
|
518
|
+
* They will only only work properly when used on a core created with ccfEnableGraphInspection and are
|
|
519
|
+
* not safe to use concurrently with frame requests or other API functions. Because of this they are
|
|
520
|
+
* unsuitable for use in plugins and filters.
|
|
521
|
+
*/
|
|
522
|
+
|
|
523
|
+
const char *(VS_CC *getNodeCreationFunctionName)(VSNode *node, int level) VS_NOEXCEPT; /* level=0 returns the name of the function that created the filter, specifying a higher level will retrieve the function above that invoked it or NULL if a non-existent level is requested */
|
|
524
|
+
const char *(VS_CC *getNodeCreationPluginID)(VSNode *node, int level) VS_NOEXCEPT; /* level=0 returns the name of the function that created the filter, specifying a higher level will retrieve the function above that invoked it or NULL if a non-existent level is requested */
|
|
525
|
+
const char *(VS_CC *getNodeCreationPluginNS)(VSNode *node, int level) VS_NOEXCEPT; /* level=0 returns the name of the function that created the filter, specifying a higher level will retrieve the function above that invoked it or NULL if a non-existent level is requested */
|
|
526
|
+
const VSMap *(VS_CC *getNodeCreationFunctionArguments)(VSNode *node, int level) VS_NOEXCEPT; /* level=0 returns a copy of the arguments passed to the function that created the filter, returns NULL if a non-existent level is requested */
|
|
527
|
+
#endif
|
|
528
|
+
#endif
|
|
529
|
+
#endif
|
|
530
|
+
};
|
|
531
|
+
|
|
532
|
+
VS_API(const VSAPI *) getVapourSynthAPI(int version) VS_NOEXCEPT;
|
|
533
|
+
|
|
534
|
+
#endif /* VAPOURSYNTH4_H */
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// mvuscale — a native replacement for the pure-Python scale_vect() used by
|
|
2
|
+
// smdegrain_bis' UHDhalf path (SMDEGRAIN_BIS_IMPROVEMENTS.md §5/§6).
|
|
3
|
+
//
|
|
4
|
+
// manipmv.ScaleVect cannot read mvutensils' vectors, and mvu ships no scaling
|
|
5
|
+
// op, so the port scales the vectors in Python. That marshals ~96k int64 props
|
|
6
|
+
// per frame through the GIL and is ~4x slower than the mvtools+manipmv UHDhalf
|
|
7
|
+
// path. This filter does the same work in C++: it reads mvu's plain-int frame
|
|
8
|
+
// props, scales geometry by s, packed vectors (low32=x, high32=y) by s, and
|
|
9
|
+
// per-block SAD by s*s, releasing the GIL so frames process in parallel.
|
|
10
|
+
//
|
|
11
|
+
// The operation is memory-bound (array I/O + the unavoidable frame copy), so
|
|
12
|
+
// it is deliberately scalar; -O3 auto-vectorises the trivial loops with the
|
|
13
|
+
// x86-64 baseline (SSE2), keeping the .so portable (no AVX runtime requirement).
|
|
14
|
+
//
|
|
15
|
+
// Boundary frames carry geometry but no Vectors/SAD (§6.1); those are simply
|
|
16
|
+
// left untouched.
|
|
17
|
+
|
|
18
|
+
#include <cstdint>
|
|
19
|
+
#include <string>
|
|
20
|
+
#include <vector>
|
|
21
|
+
|
|
22
|
+
#include "VapourSynth4.h"
|
|
23
|
+
#include "VSHelper4.h"
|
|
24
|
+
|
|
25
|
+
namespace {
|
|
26
|
+
|
|
27
|
+
struct ScaleVectData {
|
|
28
|
+
VSNode *node;
|
|
29
|
+
int scale;
|
|
30
|
+
std::string prefix;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// Geometry props that describe a resolution and therefore scale by `s`.
|
|
34
|
+
const char *const kGeomSuffix[] = {
|
|
35
|
+
"BlkSizeX", "BlkSizeY", "OverlapX", "OverlapY",
|
|
36
|
+
"Width", "Height", "RealWidth", "RealHeight", "HPad", "VPad",
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
void scaleProps(VSMap *props, const ScaleVectData *d, const VSAPI *vsapi) {
|
|
40
|
+
const int64_t s = d->scale;
|
|
41
|
+
const int64_t s2 = s * s;
|
|
42
|
+
const std::string &pfx = d->prefix;
|
|
43
|
+
|
|
44
|
+
// Scalar geometry props: present on every frame, always scaled.
|
|
45
|
+
for (const char *suffix : kGeomSuffix) {
|
|
46
|
+
const std::string key = pfx + "Analysis" + suffix;
|
|
47
|
+
int err = 0;
|
|
48
|
+
int64_t v = vsapi->mapGetInt(props, key.c_str(), 0, &err);
|
|
49
|
+
if (!err)
|
|
50
|
+
vsapi->mapSetInt(props, key.c_str(), v * s, maReplace);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Packed motion vectors: low 32 bits = x, high 32 bits = y (two's
|
|
54
|
+
// complement). Absent on sequence-boundary frames — skip if so.
|
|
55
|
+
const std::string vkey = pfx + "AnalysisVectors";
|
|
56
|
+
int verr = 0;
|
|
57
|
+
const int64_t *vec = vsapi->mapGetIntArray(props, vkey.c_str(), &verr);
|
|
58
|
+
if (verr || !vec)
|
|
59
|
+
return;
|
|
60
|
+
const int vcount = vsapi->mapNumElements(props, vkey.c_str());
|
|
61
|
+
|
|
62
|
+
// Copy the SAD array out before we overwrite any keys (mapSet* may
|
|
63
|
+
// reallocate the map's storage and invalidate `vec`/`sad`).
|
|
64
|
+
const std::string skey = pfx + "AnalysisSAD";
|
|
65
|
+
int serr = 0;
|
|
66
|
+
const int64_t *sad = vsapi->mapGetIntArray(props, skey.c_str(), &serr);
|
|
67
|
+
const int scount = (!serr && sad) ? vsapi->mapNumElements(props, skey.c_str()) : 0;
|
|
68
|
+
|
|
69
|
+
std::vector<int64_t> vout(vcount);
|
|
70
|
+
for (int i = 0; i < vcount; ++i) {
|
|
71
|
+
// Scaling a two's-complement value is a masked multiply: the low 32
|
|
72
|
+
// bits of (signed_half * s) are correct for either sign (multiplication
|
|
73
|
+
// is well-defined mod 2^32). Vectors are small, so no 32-bit overflow.
|
|
74
|
+
const uint64_t packed = static_cast<uint64_t>(vec[i]);
|
|
75
|
+
const int32_t x = static_cast<int32_t>(packed & 0xFFFFFFFFu);
|
|
76
|
+
const int32_t y = static_cast<int32_t>(packed >> 32);
|
|
77
|
+
const uint32_t nx = static_cast<uint32_t>(static_cast<int64_t>(x) * s);
|
|
78
|
+
const uint32_t ny = static_cast<uint32_t>(static_cast<int64_t>(y) * s);
|
|
79
|
+
vout[i] = static_cast<int64_t>(static_cast<uint64_t>(nx) |
|
|
80
|
+
(static_cast<uint64_t>(ny) << 32));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
std::vector<int64_t> sout(scount);
|
|
84
|
+
for (int i = 0; i < scount; ++i)
|
|
85
|
+
sout[i] = sad[i] * s2; // SAD scales with block area (s*s)
|
|
86
|
+
|
|
87
|
+
vsapi->mapSetIntArray(props, vkey.c_str(), vout.data(), vcount);
|
|
88
|
+
if (scount)
|
|
89
|
+
vsapi->mapSetIntArray(props, skey.c_str(), sout.data(), scount);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const VSFrame *VS_CC scaleVectGetFrame(int n, int activationReason, void *instanceData,
|
|
93
|
+
void **frameData, VSFrameContext *frameCtx, VSCore *core, const VSAPI *vsapi) {
|
|
94
|
+
ScaleVectData *d = static_cast<ScaleVectData *>(instanceData);
|
|
95
|
+
if (activationReason == arInitial) {
|
|
96
|
+
vsapi->requestFrameFilter(n, d->node, frameCtx);
|
|
97
|
+
} else if (activationReason == arAllFramesReady) {
|
|
98
|
+
const VSFrame *src = vsapi->getFrameFilter(n, d->node, frameCtx);
|
|
99
|
+
VSFrame *dst = vsapi->copyFrame(src, core);
|
|
100
|
+
vsapi->freeFrame(src);
|
|
101
|
+
scaleProps(vsapi->getFramePropertiesRW(dst), d, vsapi);
|
|
102
|
+
return dst;
|
|
103
|
+
}
|
|
104
|
+
return nullptr;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
void VS_CC scaleVectFree(void *instanceData, VSCore *core, const VSAPI *vsapi) {
|
|
108
|
+
ScaleVectData *d = static_cast<ScaleVectData *>(instanceData);
|
|
109
|
+
vsapi->freeNode(d->node);
|
|
110
|
+
delete d;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
void VS_CC scaleVectCreate(const VSMap *in, VSMap *out, void *userData,
|
|
114
|
+
VSCore *core, const VSAPI *vsapi) {
|
|
115
|
+
ScaleVectData d{};
|
|
116
|
+
d.node = vsapi->mapGetNode(in, "clip", 0, nullptr);
|
|
117
|
+
|
|
118
|
+
int err = 0;
|
|
119
|
+
d.scale = vsapi->mapGetIntSaturated(in, "scale", 0, &err);
|
|
120
|
+
if (err)
|
|
121
|
+
d.scale = 2;
|
|
122
|
+
|
|
123
|
+
const char *pfx = vsapi->mapGetData(in, "prefix", 0, &err);
|
|
124
|
+
d.prefix = err ? "MVUtensils" : pfx;
|
|
125
|
+
|
|
126
|
+
if (d.scale < 1) {
|
|
127
|
+
vsapi->mapSetError(out, "ScaleVect: scale must be >= 1");
|
|
128
|
+
vsapi->freeNode(d.node);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const VSVideoInfo *vi = vsapi->getVideoInfo(d.node);
|
|
133
|
+
ScaleVectData *data = new ScaleVectData(std::move(d));
|
|
134
|
+
VSFilterDependency deps[] = {{data->node, rpStrictSpatial}};
|
|
135
|
+
vsapi->createVideoFilter(out, "ScaleVect", vi, scaleVectGetFrame, scaleVectFree,
|
|
136
|
+
fmParallel, deps, 1, data, core);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
} // namespace
|
|
140
|
+
|
|
141
|
+
VS_EXTERNAL_API(void) VapourSynthPluginInit2(VSPlugin *plugin, const VSPLUGINAPI *vspapi) {
|
|
142
|
+
vspapi->configPlugin("com.smdegrainbis.mvuscale", "mvuscale",
|
|
143
|
+
"Scale mvutensils vector clips (manipmv.ScaleVect replacement)",
|
|
144
|
+
VS_MAKE_VERSION(1, 0), VAPOURSYNTH_API_VERSION, 0, plugin);
|
|
145
|
+
vspapi->registerFunction("ScaleVect",
|
|
146
|
+
"clip:vnode;scale:int:opt;prefix:data:opt;",
|
|
147
|
+
"clip:vnode;",
|
|
148
|
+
scaleVectCreate, nullptr, plugin);
|
|
149
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# vapoursynth-mvuscale — the compiled UHDhalf vector scaler for smdegrain_bis,
|
|
2
|
+
# distributed as a per-platform wheel whose payload is a bare VS plugin under
|
|
3
|
+
# vapoursynth/plugins/mvuscale/ (identical layout to vapoursynth-manipmv et al.).
|
|
4
|
+
# This is a SEPARATE distribution from the pure-Python `smdegrain-bis` package.
|
|
5
|
+
#
|
|
6
|
+
# Build one wheel: pip wheel native/ -w dist/
|
|
7
|
+
# Build the matrix: cibuildwheel native/ (see [tool.cibuildwheel] below)
|
|
8
|
+
|
|
9
|
+
[build-system]
|
|
10
|
+
requires = ["scikit-build-core>=0.10"]
|
|
11
|
+
build-backend = "scikit_build_core.build"
|
|
12
|
+
|
|
13
|
+
[project]
|
|
14
|
+
name = "vapoursynth-mvuscale"
|
|
15
|
+
version = "0.1.0"
|
|
16
|
+
description = "Native VapourSynth (API4) filter that scales mvutensils motion vectors for smdegrain_bis UHDhalf"
|
|
17
|
+
readme = "README.md"
|
|
18
|
+
requires-python = ">=3.8"
|
|
19
|
+
license = "GPL-3.0-or-later"
|
|
20
|
+
authors = [{ name = "Florian Gamper" }]
|
|
21
|
+
keywords = ["vapoursynth", "mvutensils", "motion-vectors", "denoise", "smdegrain"]
|
|
22
|
+
classifiers = [
|
|
23
|
+
"Topic :: Multimedia :: Video",
|
|
24
|
+
"Operating System :: POSIX :: Linux",
|
|
25
|
+
"Operating System :: MacOS",
|
|
26
|
+
"Operating System :: Microsoft :: Windows",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[project.urls]
|
|
30
|
+
Homepage = "https://github.com/FlorianGamper/vs-smdegrain-bis"
|
|
31
|
+
|
|
32
|
+
[tool.scikit-build]
|
|
33
|
+
minimum-version = "0.10"
|
|
34
|
+
# The payload has no CPython extension (no libpython link), so one wheel serves
|
|
35
|
+
# all Python 3.x on a platform. py-api = "py3" tags it none-ABI accordingly.
|
|
36
|
+
wheel.py-api = "py3"
|
|
37
|
+
build-dir = "build/{wheel_tag}"
|
|
38
|
+
|
|
39
|
+
[tool.cibuildwheel]
|
|
40
|
+
# The .so is Python-version-independent, so build with a single interpreter per
|
|
41
|
+
# platform rather than the full cpXX matrix.
|
|
42
|
+
build = "cp312-*"
|
|
43
|
+
skip = "*_i686 *-musllinux_i686"
|
|
44
|
+
build-frontend = "build"
|
|
45
|
+
# The .so links only libstdc++/gcc/c/m — all present in the 2_28 image, so
|
|
46
|
+
# auditwheel repair is effectively a no-op (no bundled sidecar libs).
|
|
47
|
+
manylinux-x86_64-image = "manylinux_2_28"
|
|
48
|
+
manylinux-aarch64-image = "manylinux_2_28"
|
|
49
|
+
|
|
50
|
+
# Build BOTH macOS arches on one (arm64) runner — clang cross-compiles the x86_64
|
|
51
|
+
# .dylib via CMAKE_OSX_ARCHITECTURES, so we don't depend on the scarce/deprecated
|
|
52
|
+
# Intel `macos-13` runner. (No tests in the wheel build, so cross-arch is fine.)
|
|
53
|
+
[tool.cibuildwheel.macos]
|
|
54
|
+
archs = ["x86_64", "arm64"]
|