抛砖引玉胡乱说两句
(以下涉及了c++)
零、官方模板
有份官方模板,不知道楼主看没看过。模板在 VapourSynth 本体或源码下的 sdk/filter_skeleton.c 文件。
https://github.com/vapoursynth/vapoursy ... skeleton.c
一、基本的框架
接着上面的模板说。
一份 vs 滤镜代码至少要有一个结构体/类,4 个基本函数,以及 python 接口。
结构体里定义了必要的指针,而 4 个函数的功能从名字就能看出来。
- Init() 用来初始化
- GetFrame() 用来读取帧的内容并进行滤镜的核心处理
- Free() 释放内存
- Create() 接收 python 前端传递过来的参数、抛出异常,并调用前面的函数
代码: 全选
static void VS_CC FunctionInit(VSMap* in, VSMap* out, void** instanceData, VSNode* node,
VSCore* core, const VSAPI* vsapi){}
static const VSFrameRef* VS_CC FunctionGetFrame(int n, int activationReason, void** instanceData,
void** frameData, VSFrameContext* frameCtx, VSCore* core, const VSAPI* vsapi){}
static void VS_CC FunctionFree(void* instanceData, VSCore* core, const VSAPI* vsapi){}
static void VS_CC FunctionCreate(const VSMap* in, VSMap* out, void* userData, VSCore* core,
const VSAPI* vsapi){}
以及留给 python 接口设定参数的
代码: 全选
VS_EXTERNAL_API(void) VapourSynthPluginInit(VSConfigPlugin configFunc,
VSRegisterFunction registerFunc, VSPlugin* plugin){}
二、如何抄代码
前面提到,读取帧内容和核心处理都放在 GetFrame() 函数中,而习惯上会写一个或者一系列 process() 函数,把核心处理单独拿出来。
这样一来,除了 process() 函数外,开头的结构体/类、四个核心函数外加 python 接口,基本都是固定的套路,具体每一行代码的写法可以照抄现有滤镜。至于 process() 函数本身,就看个人移植/实现算法的能力了,到这里已经和 vs api 关系不大了。
比如下面这个
AreaResize。(自卖自夸地拿自己迁移后满是 bug 的滤镜当例子)
这是一个只有一个 .cpp 文件的相对简短的滤镜,用简单的计算邻近像素均值的方法缩小画面,代码见下。
https://github.com/Kiyamou/VapourSynth- ... Resize.cpp
三、稍微一点进阶,支持不同的格式
上面举例的这个滤镜,虽然思路和功能很简单,但由于支持了 8-16 bit + 32 bit,灰度、RGB、YUV,所以代码也稍微有点长。
3.1 在 8 bit 基础上支持 9-16 bit 和 32 bit
从整型 8 bit 到整型 9 - 16 bit,由于都是整型运算,简单情况下不需要改动核心代码,添加一个函数模板(template)即可。
进一步支持浮点 32 bit 可能会有一些具体的变化。比如上面的 AreaResize,在 8-16 bit RGB 下用了查表,32bit RGB 没用(因为表太大了查表得不偿失)。又比如浮点数运算可以使用 avx 指令集做优化。
当然,更现实的原因是,有的算法在设计思路上就给支持 32 bit 增加了难度,比如
DehazingCE,算法中为弥补像素越界提出了一个损失值作为迭代的指标,至少我自己没想出来这部分在浮点数下怎么写...
3.2 支持更多的色彩空间
灰度和 YUV 通常只是增加一个判断的区别(如果算法层面没有特殊要求),这部分看官方教程是没问题的。
从 YUV 到 RGB 还需要再做 Interleaved 格式的转换,并调整指针读取像素的顺序(同样,仅为算法层面没有特殊要求的简单情况)。Interleaved 的相关内容在学写脚本的时候都遇见过。Interleaved 格式转换也是照现有代码抄即可。像素读取顺序,如果我没记错,YUV 是一个 plane 一个 plane 地读,RGB 是读完一个像素点的三个值再移动到下一个像素点。
PS:以上针对 VapourSynth R54 及之前的版本,新出来的 API 还没有研究,不知道哪里变没变 Orz..