JasinChen
帖子: 43
注册时间: 2017-06-10 22:14

请教如何使用c制作vs滤镜

我用vapoursynth很多年了,同时用python写过一些滤镜。近期想用c语言写一个滤镜,刚学习c语言入门的教程,但是官方的文档看的云里雾里,参考别的开源滤镜发现看不懂他们如何使用api 。

请问有没有类似的简单的教程,谢谢!!!
头像
Sakura2020
帖子: 15
注册时间: 2020-03-19 15:22

Re: 请教如何使用c制作vs滤镜

抛砖引玉胡乱说两句
(以下涉及了c++)


零、官方模板

有份官方模板,不知道楼主看没看过。模板在 VapourSynth 本体或源码下的 sdk/filter_skeleton.c 文件。

https://github.com/vapoursynth/vapoursy ... skeleton.c


一、基本的框架

接着上面的模板说。

一份 vs 滤镜代码至少要有一个结构体/类,4 个基本函数,以及 python 接口。

结构体里定义了必要的指针,而 4 个函数的功能从名字就能看出来。
  1. Init() 用来初始化
  2. GetFrame() 用来读取帧的内容并进行滤镜的核心处理
  3. Free() 释放内存
  4. 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..
上次由 Sakura2020 在 2021-09-24 18:01,总共编辑 5 次。
JasinChen
帖子: 43
注册时间: 2017-06-10 22:14

Re: 请教如何使用c制作vs滤镜

感谢分享!

回到 “VapourSynth”