AviSynth Networking & MultiCores in Linux

I have a few boxes around at home, so if i do video-editing i’d like to benefit from that. We can use some avisynth plugins/enhancements to do so. There are two things we might do: a) running filters in parallel b) handing filters to another box (networking). The problem with multiple cores in Linux is that it’s not easily possible to run Avisynth on many cores in fact it’s per default just running on one core.

MT Approach

Let’s first take a look at the multiple cores issue.

 3760 wdp       20   0 1573m  48m 6584 R   99  2.4   0:58.37 avs2yuv                   
 3761 wdp       20   0  104m  57m 1336 S    4  2.8   0:01.40 x264

What you can see here is simple – I’m running avisynth using

wine avs2yuv test.avs - | x264 --demuxer y4m --output output.264 -

avs2yuv has 99% CPU where as it should have 200% (taking both cores into account) and x264 needs only 4% cpu (because the avisynth script is way too slow for x264 to even notice) – And here we got our first problem. Let’s see if we can change that behaviour. So i installed MT() and played around.

  • SetMtMode(2) doesn’t change this behaviour.
  • MT(, threads=2) changes this behaviour
 3928 wdp       20   0 1574m 192m 6736 R  186  9.5   1:30.97 avs2yuv                   
 3929 wdp       20   0  105m  63m 1336 S    8  3.1   0:02.78 x264

The downside of this is, that MT() might be bad for quality, and it might not work for everything. However, let’s put this into real numbers now:

Intel(R) Core(TM)2 Duo CPU T7500 @ 2.20GHz, 1001 frames, FFmpegSource2 + TNLMeans(), 2 threads

  • with MT encoded 1001 frames, 2.51 fps, 279.84 kb/s
  • without MT encoded 1001 frames, 1.47 fps, 278.98 kb/s

AMD Athlon(tm) II X4 645 Processor (3,1 GHz), 1001 frames, FFmpegSource2 + TNLMeans(), 4 threads

  • with MT encoded 1001 frames, 6.96 fps, 279.23 kb/s
  • without MT encoded 1001 frames, 2.05 fps, 279.22 kb/s

AMD Athlon(tm) II X4 630 Processor (2,8 GHz), 1001 frames, FFmpegSource2 + TNLMeans(), 4 threads

  • with MT encoded 1001 frames, 6.96 fps, 279.23 kb/s
  • without MT encoded 1001 frames, 2.05 fps, 279.22 kb/s
  Intel Dualcore 2,2 GHz
mobile cpu, 32bit system
Amd Quad Core 3,1 GHz
32 bit system
AMD Quadcore 2,8 GHz
without MT 1.47 2.05  
with MT 2.51 6.96  
speedup 170%
(ca 2 times)
339%
(ca 3 1/2 times)
 

I’d say that’s a good improvement and worth it.

Networking Approach

The networking approach has some flaws. For example: The Concept in Avisynth works like this: You’re filtering a video, you’re handing the clip to another box using TCPServer – After TCPServer you can’t do anything anymore (thus you can’t do TCPSource to get the clip back). This means, if you want to hand it back you have to run several avisynth instances, like this:

box1 instance 1 box2 box1 instance 2
Blur(1) TCPServer() TCPSource(„box1 instance1“) nnedi3 TCPServer() TCPSource(box2) Sharpen

i.e.: box 1 instance 1 (10.0.0.1 port 7777) » box 2 (10.0.0.2) port 8888 » box 1 instance 2 (10.0.0.1 port 6666)

The next flaw is, this is still only linear processing, so it doesn’t matter how many boxes you add, if your boxes are equal in power a full encode will take just as much time as it would on one box, probably due to the networking a bit more. So this makes only sense, if you have expensive filters on a fast box and the rest on your slow box. However, we can try to work around that using Crop.

box1

FFMpegSource2()
_do_some_fast_filtering_
TCPServer()

box2

TCPSource().Crop() # take the upper half of the frame
do some filtering
TCPServer()

box3

TCPSource().Crop() # take the bottom half of the frame
do some filtering
TCPServer()

box1 instance2

top = TCPSource(box2)
bottom = TCPSource(box3)
StackVertical(top, bottom)

That’d be very basic threading. And it works fine. The problematic part is that some filters aren’t processing the edges – So you might have trouble at the edges where you cropped. Some Way to come around that, would be to crop 16px more and when setting it together, average those 16px or remove them completely.

Alltogether

Now you can use MT() also, of course if you hand your clip to another box. i.e.

TCPSource()
MT("filter", threads=x)
TCPServer()

But let’s see, what do i get when doing both?

Conclusion

Well well, i’m a bit disapointed, because the networking stuff is pretty complicated. Features i’m missing for example are giving filters from one box to another. i.e. some feature like:

TCPRun("Filter1().Filter2().Filter3()", "ip", port, compression)

The way it’s currently done, i have to write scripts and place them onto the specific box. In Linux it’s even more complicated (no idea how the windows guys are doing that) i have to open the .avs in virtualdub in wine first, before i can connect to em using TCPSource. Thus the administrative part behind this magic is quite high.

No Comments

Post a Comment