自立更生 不愁吃穿? AVS filter制作入门…
在21世纪的今天,相信大家都使用或听说过avisynth这个东西吧。这个软件有大量的第三方制作的filter供用户选择。不过,因为其中大部分是个人制作的开源代码的软件,使得质量参差不齐。 有时候会碰到一个很好的filter,但离自己需要的就是差了那么一点,这时候就会想如果这东西能这样改一下就好了。这篇文章就是和大家讨论AVS filter的制作入门的。
当然,要写AVS的filter必然要有基本的C++知识和对视频处理有一定的了解大部分会看这篇文章的人估计都对视频处理有一定的了解了,而对C++不了解的朋友们可以在机器压制的空闲时间内学习一下C++.
下面将借用Avisynth网站上的入门程序范例来讲述AVS的基本结构。
(注:作者对C++的中文词汇不太了解,所以大家看的时候请谅解)
#include "windows.h"
#include "avisynth.h"
class Invert : public GenericVideoFilter {
public:
Invert(PClip _child) : GenericVideoFilter(_child) {}
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env);
};
PVideoFrame __stdcall Invert::GetFrame(int n, IScriptEnvironment* env) {
PVideoFrame src = child->GetFrame(n, env);
PVideoFrame dst = env->NewVideoFrame(vi);
const unsigned char* srcp = src->GetReadPtr();
unsigned char* dstp = dst->GetWritePtr();
const int src_pitch = src->GetPitch();
const int dst_pitch = dst->GetPitch();
const int row_size = dst->GetRowSize();
const int height = dst->GetHeight();
for (int y = 0; y < height; y++) {
for (int x = 0; x < row_size; x++) {
dstp[x] = srcp[x] ^ 255;
}
srcp += src_pitch;
dstp += dst_pitch;
}
return dst;
}
AVSValue __cdecl Create_Invert(AVSValue args, void* user_data, IScriptEnvironment* env) {
return new Invert(args[0].AsClip());
}
extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit2(IScriptEnvironment* env) {
env->AddFunction("Invert", "c", Create_Invert, 0);
return "`Invert' sample plugin";
}
#include "avisynth.h"
这两句的意思很简单,就是让这个软件能使用avs的数据结构和接口,基本上放进去就行了。
class Invert : public GenericVideoFilter {
}
这里是建立Invert这个class,另外把Invert作为GenericVideoFilter这个Class的subclass,这样就可以让Invert使用AVS里面已经建立好的数据结构和接口。
Invert(PClip _child) : GenericVideoFilter(_child) {}
这是Invert的constructor, PClip _child是一个指向一段视频的pointer, 在GetFrame里面就可以对这段视频进行处理。
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env);
GetFrame 就是处理视频的function,每当AVS下游的程序(比如VirtualDub)向AVS要求 帧n 的时候,AVS就会运行这个function,然后把处理完的结果发给下游的程序。IScriptEnvironment* env 是记录和控制整个AVS脚本里面数据和filter流程的class.
下面开始讲如何在GetFrame 里面处理视频。
PVideoFrame src = child->GetFrame(n, env);
这里建立了一个pointer src, 它指向child->GetFrame(n, env) 返回的结果,也就是我们要处理的片源。
PVideoFrame dst = env->NewVideoFrame(vi);
这里又建立一个pointer dst, 并用env->NewVideoFrame(vi) 建立了一个新的帧, 这样我们可以把处理后的结果放在里面然后交给AVS. 这里新建立的帧使用的vi作为输入,vi里面包含了片源帧的数据,所以新建立的帧和片源在大小,格式上都是一样的。
const unsigned char* srcp = src->GetReadPtr();
建立一个pointer指向片源帧的第一个字节。注意这里是只读的pointer。如果用GetReadPtr(PLANAR_Y)的话就可以取得指向灰度plane的pointer.
unsigned char* dstp = dst->GetWritePtr();
这里建立一个可写的pointer到我们前面建立的新的要输出的帧。
const int src_pitch = src->GetPitch();
这里取得片源的pitch, pitch在avs里面的定义就是每一行所占的字节数。注意,如果是 GetPitch(PLANAR_Y)的话就是取得画面灰度plane的pitch, 同样还有PLANAR_U和PLANAR_V, 这在处理YV12等格式的时候需要用到。
const int dst_pitch = dst->GetPitch();
这里取得输出帧的pitch
const int row_size = dst->GetRowSize();
这里取得输出帧的行宽,注意这里还是字节数而不是像素,大部分时候这和pitch是一样的,但是在crop后会有区别。
const int height = dst->GetHeight();
取得输出帧的行数,这里是以像素的单位的。
for (int y = 0; y < height; y++) {
for (int x = 0; x < row_size; x++)
dstp[x] = srcp[x] ^ 255;
srcp += src_pitch;
dstp += dst_pitch;
}
这一段就是真正处理视频的程序。个像素的数值都被倒过来了。注意这里pointer每次移动的是pitch而不是rowsize. 就像上面说的,crop后pitch和rowsize会不一样,实际在内存里每行还是pitch个字节。
return dst;
把dst返回给AVS.
AVSValue __cdecl Create_Invert(AVSValue args, void* user_data, IScriptEnvironment* env) {
return new Invert(args[0].AsClip());
}
这个function是用来在script里面运行filter function的时候使用的。注意里面的
”return new Invert(args[0].AsClip()); “ 这里建立了一个Invert class的 instance. AVS脚本里面filter的argument也是从这里输入到filter里面来的。比如args[0] 就是clip, 要处理的片源。
extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit2(IScriptEnvironment* env)
这个function的功能就是让AVS知道Invert这个filter的存在。在loadplugin的时候AVS就会运行这个function.
env->AddFunction("Invert", "c", Create_Invert, 0);
这里就把这个function的名称,类型等在AVS注册,这样在AVS就可以识别和运行在脚本里面出现的Invert()了。
return "`Invert' sample plugin";
//这里作为loadplugin的返回值,一般被忽略掉。
希望在看完这个后对大家有一些启发.
英文好的可以看下面这个, 比我写的要详细许多.
AVS网站上的入门
http://www.avisynth.org/BensAviSynthDocs暂时完了...........
等我多积累点经验后再继续写.....
可能吧........
大家有什么问题欢迎讨论..........
另外欢迎用中文学习过c++的人帮助我修正一些用词.
Version log:
Version 0.1 2/24 first draft with basic explanations