-
Notifications
You must be signed in to change notification settings - Fork 2
/
invert_example.zig
124 lines (99 loc) · 4.43 KB
/
invert_example.zig
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
//! https://github.com/vapoursynth/vapoursynth/blob/master/sdk/invert_example.c
const std = @import("std");
const vapoursynth = @import("vapoursynth");
const math = std.math;
const vs = vapoursynth.vapoursynth4;
const vsh = vapoursynth.vshelper;
// https://ziglang.org/documentation/master/#Choosing-an-Allocator
const allocator = std.heap.c_allocator;
const InvertData = struct {
node: ?*vs.Node,
enabled: bool,
string_bufs: [2]?[]u8,
};
export fn invertGetFrame(n: c_int, activation_reason: vs.ActivationReason, instance_data: ?*anyopaque, frame_data: ?*?*anyopaque, frame_ctx: ?*vs.FrameContext, core: ?*vs.Core, vsapi: ?*const vs.API) callconv(.C) ?*const vs.Frame {
_ = frame_data;
const d: *InvertData = @ptrCast(@alignCast(instance_data));
if (activation_reason == .Initial) {
vsapi.?.requestFrameFilter.?(n, d.node, frame_ctx);
} else if (activation_reason == .AllFramesReady) {
const src = vsapi.?.getFrameFilter.?(n, d.node, frame_ctx);
// https://ziglang.org/documentation/master/#defer
defer vsapi.?.freeFrame.?(src);
const fi = vsapi.?.getVideoFrameFormat.?(src);
const height = vsapi.?.getFrameHeight.?(src, 0);
const width = vsapi.?.getFrameWidth.?(src, 0);
const dst = vsapi.?.newVideoFrame.?(fi, width, height, src, core);
var plane: c_int = 0;
while (plane < fi.numPlanes) : (plane += 1) {
var srcp: [*]const u8 = vsapi.?.getReadPtr.?(src, plane);
var dstp: [*]u8 = vsapi.?.getWritePtr.?(dst, plane);
const stride: usize = @intCast(vsapi.?.getStride.?(src, plane));
const h: usize = @intCast(vsapi.?.getFrameHeight.?(src, plane));
const w: usize = @intCast(vsapi.?.getFrameWidth.?(src, plane));
var y: usize = 0;
while (y < h) : (y += 1) {
var x: usize = 0;
while (x < w) : (x += 1) {
dstp[x] = if (d.enabled) ~(srcp[x]) else srcp[x];
}
dstp += stride;
srcp += stride;
}
}
return dst;
}
return null;
}
export fn invertFree(instance_data: ?*anyopaque, core: ?*vs.Core, vsapi: ?*const vs.API) callconv(.C) void {
_ = core;
const d: *InvertData = @ptrCast(@alignCast(instance_data));
vsapi.?.freeNode.?(d.node);
for (d.string_bufs) |buf| {
if (buf) |b| allocator.free(b);
}
allocator.destroy(d);
}
export fn invertCreate(in: ?*const vs.Map, out: ?*vs.Map, user_data: ?*anyopaque, core: ?*vs.Core, vsapi: ?*const vs.API) callconv(.C) void {
_ = user_data;
var d: InvertData = undefined;
var err: vs.MapPropertyError = undefined;
d.node = vsapi.?.mapGetNode.?(in, "clip", 0, &err).?;
const vi: *const vs.VideoInfo = vsapi.?.getVideoInfo.?(d.node);
if (!vsh.isConstantVideoFormat(vi) or (vi.format.sampleType != .Integer) or (vi.format.bitsPerSample != @as(c_int, 8))) {
vsapi.?.mapSetError.?(out, vsh.printf(
allocator,
&d.string_bufs[0],
"Invert: only constant format 8bit integer input supported. Input clip is {}x{} {}-bits",
.{ vi.width, vi.height, vi.format.bitsPerSample },
).ptr);
vsapi.?.freeNode.?(d.node);
return;
}
// https://ziglang.org/documentation/master/#Optionals
const enabled = vsh.mapGetN(i32, in, "enabled", 0, vsapi) orelse 1;
if ((enabled < 0) or (enabled > 1)) {
vsapi.?.mapSetError.?(out, vsh.printf(
allocator,
&d.string_bufs[1],
"Invert: enabled must be 0 or 1. Passed: {}",
.{enabled},
).ptr);
vsapi.?.freeNode.?(d.node);
return;
}
d.enabled = enabled == 1;
const data: *InvertData = allocator.create(InvertData) catch unreachable;
data.* = d;
var deps = [_]vs.FilterDependency{
vs.FilterDependency{
.source = d.node,
.requestPattern = .StrictSpatial,
},
};
vsapi.?.createVideoFilter.?(out, "Invert", vi, invertGetFrame, invertFree, .Parallel, &deps, deps.len, data, core);
}
export fn VapourSynthPluginInit2(plugin: *vs.Plugin, vspapi: *const vs.PLUGINAPI) void {
_ = vspapi.configPlugin.?("com.example.invert", "invert", "VapourSynth Invert Example", vs.makeVersion(1, 0), vs.VAPOURSYNTH_API_VERSION, 0, plugin);
_ = vspapi.registerFunction.?("Filter", "clip:vnode;enabled:int:opt;", "clip:vnode;", invertCreate, null, plugin);
}