『漫游』酷论坛>『影音数码技术学习交流』>[讨论]利用多进程组流 ..
[讨论]利用多进程组流水线提高AVS处理速度
linuxyouxia@2011-10-12 17:38
AVS很多滤镜没做多线程数据保护,MT版本的AVS很容易出现各种莫名奇妙的问题并且32版本容易爆内存
可以多开AVS,通过TCP协议通讯组建流水线,将某些滤镜放到单独的一个进程中去处理(甚至不同电脑上)
AVS脚本通过解析最终会组成一条filter chain(可以带有分支、多个起点),理论上都可以拆成多进程来处理
例如
脚本1:
- xxxSource("xxx")
- TCPServer(22050)
脚本2:
- TCPSource("127.0.0.1",22050,"None")#如果是在不同电脑上处理,最后一个参数根据网络状况选择
- xxxfilter()
- TCPServer(22051)
脚本3:
- TCPSource("127.0.0.1",22051,"None")
- xxxfilter()
- TCPServer(22052)
。。。。。。
脚本X:
- TCPSource("127.0.0.1",xxxx,"None")
- xxxfilter()
然后在诸如VirtualDub之类的程序中分别依次打开上述除最后一个脚本以外的所有脚本,x264压制时输入最后一个脚本
关于TCPServer/TCPSource请参考:
http://avisynth.org/mediawiki/TCPServer
这样还是会有一个问题,当某个滤镜速度极其慢的时候,整个流水线处理速度会受到影响
解决办法之一是实现这个滤镜的多线程版本,也可以尝试通过多进程提高这个滤镜处理速度(需要自己写程序)
嘛,各位大大可以通过自行编写程序自动实现上述过程
急着吃饭,写得比较简略
[ 此帖被linuxyouxia在2011-10-12 18:21重新编辑 ]
linuxyouxia@2011-10-12 18:08
= =嘛,突然想到基于AVS的构架,这样效率也不会很高,只能解决32位下爆内存问题,并不能有效实现多进程同时处理
还是要自己写程序
比如
http://forum.doom9.org/showthread.php?t=139629
http://forum.doom9.org/showthread.php?p=1405205
把ThreadRequest()放到每个进程中去
希望各位大大一起来开发,顺便改下标题
看了一下AVS的TCPServer的代码,当没有收到请求的时候会提前fetch下一帧,我在想能不能改成提前fetch多帧
这样在收到TCPClient请求的时候,可以直接从Cache中取出来
TCP通讯还有一个问题,需要将整一帧数据发送过去,如果仅在一台电脑上处理,帧数据复制会占用额外的资源,如果滤镜处理速度不是很慢的话,可能用共享内存更好一些
[ 此帖被linuxyouxia在2011-10-12 20:59重新编辑 ]
roozhou@2011-10-12 21:15
AVS爆内存主要是脑残的缓存机制造成的。比较好的方法是每个滤镜必须在初始化完成后告诉AVS需要上游最多缓存多少帧,不然多了爆内存,少了影响效率。
linuxyouxia@2011-10-12 21:55
avs确实令人感到很讨厌,最令人讨厌的地方是往往没有合适的替代品(我不能放弃avs社区积累到现在的那些脚本和滤镜),不得不用
roozhou@2011-10-12 22:32
引用
引用第3楼linuxyouxia于2011-10-12 21:55发表的 :
avs确实令人感到很讨厌,最令人讨厌的地方是往往没有合适的替代品(我不能放弃avs社区积累到现在的那些脚本和滤镜),不得不用
你要只是会用,不会开发,那真是没办法。但如果会开发,那第一选择就是去改AVS,第二选择就是去移植。很多AVS的滤镜被移植到了ffmpeg和x264的filter system里去了。修改AVS也有可能使老的脚本或滤镜不兼容,但如果你的新版本真的能解决一些AVS的顽疾,那么那些滤镜或者脚本的作者自然也会来兼容你的新系统,不需要你自己动手的。
linuxyouxia@2011-10-13 08:34
我之前看过avisynth 3.0的遗留代码,无从下手
和新版Boost库有很多不兼容的地方,C++没怎么学过
也有人尝试过将avisynth滤镜移植到gstreamer上面
https://github.com/LRN/gst-avsynth
= =感觉这几年大家都在对老旧的avisynth修修补补(毕竟比起再造轮子节省时间精力),没人真的去开发新版本
还有一个问题就是人的精力总归是有限的,如果没什么动力,还真未必能完成一项开发,avisynth 3.0估计就是这么死掉的
我给字幕组压片第一选择就是avisynth,这在短期内还没办法改变
最近又在折腾写个avs编辑器,已经搞定了OpenGL显示YUV数据 和 基于Scintilla代码高亮(Avs词法分析器从VirtualDubMod残留代码里挖出来改了一下)[ 此帖被linuxyouxia在2011-10-13 08:54重新编辑 ]
linuxyouxia@2011-10-13 09:29
嘛,发现扯远了,我想回到主题上,至少从我粗略测试来看这样的方法确实有效(除非我哪里弄错了),不过需要合理地将avs脚本切割成多分
06_taro@2011-10-13 10:20
https://github.com/nielsmh/vsynth
linuxyouxia@2011-10-13 10:40
引用
引用第7楼06_taro于2011-10-13 10:20发表的 :
https://github.com/nielsmh/vsynth
期待逐步完善,不要像Avisynth 3.0那样通过Boost库自行实现一种脚本语言,bind到ruby、lua之类的脚本语言就行了
到时候来移植avisynth滤镜
[ 此帖被linuxyouxia在2011-10-13 11:09重新编辑 ]
linuxyouxia@2011-10-13 16:14
写了一个简单的小程序用来载入运行TCPServer的avs脚本,支持文件拖放
http://dl.dbank.com/c0n1r9sisk
嘛,有需要的话,我可以加入关于TCPServer和TCPSource的选项和avisynth编辑文本框[ 此帖被linuxyouxia在2011-10-13 16:35重新编辑 ]
roozhou@2011-10-13 21:18
要是连修修补补都不愿意,那就的确没救了。现在确实连修avs的人都没有。
avs 2.x里的buffer问题完全是可以改的,可以参考ffdshow的做法。给每一个滤镜增加一组参数指定需要前后buffer多少帧(可以在脚本中手工指定),这样avs就不会去额外的保存那么多buffer了。
linuxyouxia@2011-10-14 00:58
- ---------------------------------- cache.cpp ----------------------------------
- index 87cc346..f813ae4 100644
- @@ -54,6 +54,7 @@ struct {
- extern const AVSFunction Cache_filters[] = {
- { "Cache", "c", Cache::Create_Cache },
- { "InternalCache", "c", Cache::Create_Cache },
- + { "SetCache", "c[range]i", Cache::Create_Cache2 },
- { 0 }
- };
-
- @@ -81,7 +82,10 @@ Cache::Cache(PClip _child, IScriptEnvironment* env)
- // InitializeCriticalSectionAndSpinCount(&cs_cache_V, 4000);
- // InitializeCriticalSectionAndSpinCount(&cs_cache_A, 4000);
-
- - h_policy = CACHE_ALL; // Since hints are not used per default, this is to describe the lowest default cache mode.
- + max_tracked_frame = 30;
- + max_tracked_vf_scaled = max_tracked_frame << CACHE_SCALE_SHIFT;
- + max_tracked_misses = max_tracked_frame/2;
- + h_policy = CACHE_NOTHING; // Since hints are not used per default, this is to describe the lowest default cache mode.
- h_audiopolicy = CACHE_NOTHING; // Don't cache audio per default.
-
- cache_limit = CACHE_SCALE_FACTOR / 2; // Start half way towards 1 buffer
- @@ -411,14 +415,14 @@ PVideoFrame __stdcall Cache::GetFrame(int n, IScriptEnvironment* env)
- minframe = iminframe;
- }
-
- - if (cache_limit > MAX_CACHED_VF_SCALED) cache_limit = MAX_CACHED_VF_SCALED;
- + if (cache_limit > max_tracked_vf_scaled) cache_limit = max_tracked_vf_scaled;
-
- _RPT4(0, "Cache:%x: size %d, limit %d, fault %d\n", this, c, cache_limit, fault_rate);
-
- } // if (n>=minframe
- else { // This frame is not in the range we are currently tracking
- InterlockedIncrement(&g_Cache_stats.vfb_never);
- - if (InterlockedIncrement(&miss_count) > MAX_CACHE_MISSES) {
- + if (InterlockedIncrement(&miss_count) > max_tracked_misses) {
- ResetCache(env); // The cache isn't being accessed, reset it!
- miss_count = 0x80000000; // Hugh negative
- }
- @@ -535,7 +539,7 @@ Cache::CachedVideoFrame* Cache::GetACachedVideoFrame(const PVideoFrame& frame, I
- ReturnVideoFrameBuffer(j, env); // Return out of range vfb to vfb pool for early reuse
- }
-
- - if (count >= MAX_CACHED_VIDEO_FRAMES) return video_frames.prev; // to many entries just steal the oldest CachedVideoFrame
- + if (count >= max_tracked_frame) return video_frames.prev; // to many entries just steal the oldest CachedVideoFrame
-
- return new CachedVideoFrame; // need a new one
- }
- @@ -833,7 +837,7 @@ int __stdcall Cache::SetCacheHints(int cachehints, int frame_range) {
-
-
- if (cachehints == CACHE_ALL) {
- - int _cache_init = min(MAX_CACHED_VIDEO_FRAMES, frame_range);
- + int _cache_init = min(max_tracked_frame, frame_range);
-
- if (_cache_init > cache_init) // The max of all requests
- cache_init = _cache_init;
- @@ -852,14 +856,14 @@ int __stdcall Cache::SetCacheHints(int cachehints, int frame_range) {
-
- }
- else if (cachehints == CACHE_RANGE) {
- -
- + max_tracked_frame = frame_range*2+1;
- + max_tracked_vf_scaled = max_tracked_frame << CACHE_SCALE_SHIFT;
- + max_tracked_misses = max_tracked_frame/2;
- if (frame_range > h_span) // Use the largest size when we have multiple clients
- - h_span = min(MAX_CACHE_RANGE, frame_range);
- + h_span = min(max_tracked_frame, frame_range);
-
- h_policy = CACHE_RANGE; // An explicit cache of radius "frame_range" around the current frame, n.
- -
- }
- -
- return 0;
- }
-
- @@ -912,3 +916,27 @@ AVSValue __cdecl Cache::Create_Cache(AVSValue args, void*, IScriptEnvironment* e
- return p;
- }
-
- +AVSValue __cdecl Cache::Create_Cache2(AVSValue args, void*, IScriptEnvironment* env)
- +{
- + PClip p=0;
- + PClip r=0;
- + int _framerange;
- +
- + p = args[0].AsClip();
- + _framerange = args[1].AsInt(1);
- +
- + if (p) {
- + int q = 0;
- +
- + if (p->GetVersion() >= 5) // AVISYNTH_INTERFACE_VERSION which supports this
- + q = p->SetCacheHints(GetMyThis, 0); // Check if "p" is a cache instance
- +
- + // Do not cache another cache!
- + if (q != (int)(void *)p) {
- + r = new Cache(p, env);
- + r->SetCacheHints(CACHE_RANGE, _framerange);
- + return r;
- + }
- + }
- + return p;
- +}
- \ No newline at end of file
- ----------------------------------- cache.h -----------------------------------
- index 2f02bed..8c0f989 100644
- @@ -55,6 +55,7 @@ public:
- PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env);
- int __stdcall SetCacheHints(int cachehints,int frame_range);
- static AVSValue __cdecl Create_Cache(AVSValue args, void*, IScriptEnvironment* env);
- + static AVSValue __cdecl Create_Cache2(AVSValue args, void*, IScriptEnvironment* env);
- void __stdcall GetAudio(void* buf, __int64 start, __int64 count, IScriptEnvironment* env);
-
- protected:
- @@ -131,6 +132,9 @@ private:
-
- // Cached range limits
- int minframe, maxframe;
- + int max_tracked_frame;
- + int max_tracked_vf_scaled;
- + int max_tracked_misses;
- int cache_init; // The Initial cache size
- long cache_limit; // 16 time the current maximum number of CachedVideoFrame entries
- long fault_rate; // A decaying average of 100 times the peak fault count, used to control vfb auto-locking
- ----------------------------------- main.cpp -----------------------------------
- index 1b82226..2324e60 100644
- @@ -648,10 +648,10 @@ bool CAVIFileSynth::DelayInit2() {
- if (!AllowFloatAudio) // Ensure samples are int
- filter_graph = ConvertAudio::Create(filter_graph, SAMPLE_INT8|SAMPLE_INT16|SAMPLE_INT24|SAMPLE_INT32, SAMPLE_INT16);
-
- - filter_graph = Cache::Create_Cache(AVSValue(filter_graph), 0, env).AsClip();
- + /*filter_graph = Cache::Create_Cache(AVSValue(filter_graph), 0, env).AsClip();
-
- - filter_graph->SetCacheHints(CACHE_ALL, 999); // Give the top level cache a big head start!!
- - }
- + filter_graph->SetCacheHints(CACHE_ALL, 999); // Give the top level cache a big head start!!*/
- + }
- else
- throw AvisynthError("The script's return value was not a video clip");
-
- ---------------------------- parser/expression.cpp ----------------------------
- index 07e212f..b7b86cd 100644
- @@ -508,9 +508,9 @@ AVSValue ExpVariableReference::Evaluate(IScriptEnvironment* env)
- }
- }
- // Add cache to Bracketless call of argless function
- - if (result.IsClip()) { // Tritical Jan 2006
- +/* if (result.IsClip()) { // Tritical Jan 2006
- return Cache::Create_Cache(result, 0, env);
- - }
- + }*/
- return result;
- }
-
- @@ -603,9 +603,9 @@ AVSValue ExpFunctionCall::Evaluate(IScriptEnvironment* env)
- {
- AVSValue result = Call(env);
-
- - if (result.IsClip()) {
- +/* if (result.IsClip()) {
- return Cache::Create_Cache(result, 0, env);
- - }
- + }*/
-
- return result;
- }
懒得检查有没有问题,不会自动插入cache,可以用SetCache(int range)在脚本里手动插入,每个Cache最大存range*2+1帧
MeteorRain@2011-10-15 01:26
字幕组压片,不内嵌字幕的话最近还真没怎么用avs了……
linuxyouxia@2011-10-15 01:31
= =内嵌我可以不用avs,很多时候我就是这么做的(拿720p raw压PSP 480p)
avs的ConditionalFilter分段处理和TIVTC手动指定pattern,我暂时没实现更好的办法
并且我拿到的ts往往存在锯齿、halo之类的问题,我需要用avs的那些脚本和滤镜处理下
别吐槽avisynth了,我也不喜欢
[ 此帖被linuxyouxia在2011-10-15 02:05重新编辑 ]
06_taro@2011-10-16 00:40
- xxxSource
- xxxFilter()
- SelectEvery(3, 0)
- TCPServer(22050)
- xxxSource
- xxxFilter()
- SelectEvery(3, 1)
- TCPServer(22051)
- xxxSource
- xxxFilter()
- SelectEvery(3, 2)
- TCPServer(22052)
開上面三個,然後跑下面這個:
- Interleave(
- \ TCPSource("127.0.0.1",22050,"None"),
- \ TCPSource("127.0.0.1",22051,"None"),
- \ TCPSource("127.0.0.1",22052,"None") )
對單線程濾鏡能有非常好的提速效果
所以希望AVSTCP能增加同時多開的功能……
«12»共2页
| TOP