View Full Version : Trim vs. Select speed
lexor
16th June 2008, 15:43
Hi guys, I was wondering if the following behavior is normal when piping avs to an encoder.
Trim(1,2470) -> encode at ~25fps
SelectEvery(20,0) -> encode at ~5fps (same number of frames as above)
Is the seek involved in selecting frames with a certain step really that expensive to completely destroy encoding speed?
Leak
16th June 2008, 16:21
Trim(1,2470) -> encode at ~25fps
^= Decode 2471 frames of your input, skip the first one.
SelectEvery(20,0) -> encode at ~5fps (same number of frames as above)
^= Decode 49400 frames of your input, skip all frames except for every 20th.
Yes, I would expect that the second script performs a lot worse than the first one...
Of course, if your source supports frame-accurate seeking it might do that in the second case, but that's still a lot more CPU-intensive than just decoding frames continuously.
np: Seabear - Piano Hands (A Number Of Small Things (Disc 1))
lexor
16th June 2008, 16:43
^= Decode 49400 frames of your input, skip all frames except for every 20th.
Yes, I would expect that the second script performs a lot worse than the first one...
I don't buy that. If it was true, then it shouldn't be a lot worse than complete encode, which is decode 49384 frames and encode them all, which it does at ~28fps (actually a bit faster than in Trim's case, I guess it speeds up later on). So the seeking alone is responsible for the horrid slowdown, not decoding or the number of frames. Going ahead 1 frame at a time, until you hit 20th and only encoding that should by the above be faster than seeking.
GodofaGap
16th June 2008, 16:54
It depends on the input format. On a format that is not keyframe-only selectevery will definitely be slower than trim. Except for the first frame trim will then be 'decode 1 frame/display 1 frame'. Selectevery(20,0) will be 'decode 1-20 frames/display 1 frame'.
Gavino
16th June 2008, 17:02
So the seeking alone is responsible for the horrid slowdown, not decoding or the number of frames. Going ahead 1 frame at a time, until you hit 20th and only encoding that should by the above be faster than seeking.
What is your source and what source filter are you using? I suspect the problem lies there.
All that SelectEvery can do is, when it is asked for frame n, ask its predecessor in the filter chain for frame 20*n. If the source implements seeking by starting from frame 0 every time, it will be a lot slower than simply reading frames serially.
lexor
16th June 2008, 17:17
What is your source and what source filter are you using? I suspect the problem lies there.
All that SelectEvery can do is, when it is asked for frame n, ask its predecessor in the filter chain for frame 20*n. If the source implements seeking by starting from frame 0 every time, it will be a lot slower than simply reading frames serially.
Just doing DSS("h264.mkv") + resize. See, if it's the seeking that's the problem, then I don't understand why it was implemented with seeking. Consider this:
To encode the whole movie it does:
decode1 -> avs woodoo -> encode1
decode2 -> avs woodoo -> encode2
...
decode20 -> avs woodoo -> encode20
If SelectEvery did:
decode1 -> avs woodoo
decode2 -> avs woodoo
...
decode20 -> avs woodoo -> encode20
It should at least maintain the 28fps of the full encode and not tank to ~5fps. Is there a way to do that or do all Selects seek?
Leak
16th June 2008, 17:30
It should at least maintain the 28fps of the full encode and not tank to ~5fps. Is there a way to do that or do all Selects seek?
Well, it's totally up to the DirectShow decoder in this case - all DirectShowSource can do is calculate a timestamp for the frame it needs and request that from the decoder.
And skipping frames to return every n-th frame isn't exactly what DirectShow decoders are aimed at, either. Usually it's either do a big seek every now and then or decode a sequence of frames.
DirectShowSource is really meant as a last measure when there's nothing else that will decode some file, as DirectShow doesn't even guarantee being frame-accurate, which is a big no-no for editing.
np: ISAN - No. 2. (Lent Et Triste) (A Number Of Small Things (Disc 2))
GodofaGap
16th June 2008, 17:32
It should at least maintain the 28fps of the full encode and not tank to ~5fps.
No it won't. You are processing a lot more frames than you are outputting. That is where the discrepancy is coming from.
If you process 1000 frames in 10 seconds and output 1000 you have 100 fps. If you process 1000 frames in 10 seconds and output only 200 you get 20 fps.
lexor
16th June 2008, 17:49
No it won't. You are processing a lot more frames than you are outputting. That is where the discrepancy is coming from.
That's what bothers me. It is apparently slower to process N frames, outputting only L (L << N) than it is to process N frames and output all N. Less work = slower, that's my issue.
If you process 1000 frames in 10 seconds and output 1000 you have 100 fps. If you process 1000 frames in 10 seconds and output only 200 you get 20 fps.
Those 1000 and 20 fps are input. I'm pretty sure that x264 counts fps it's encoding at, not input fps.
GodofaGap
16th June 2008, 18:13
That's what bothers me. It is apparently slower to process N frames, outputting only L (L << N) than it is to process N frames and output all N. Less work = slower, that's my issue.
There is no less work. You are still processing N frames. Why the fps is lower I already explained above. If you do this with a keyframe only format you will not see the difference you are experiencing now, as you have to decode only the frames you want.
Those 1000 and 20 fps are input. I'm pretty sure that x264 counts fps it's encoding at, not input fps.
But the encoding fps is naturally dependent on how fast the encoder can get frames.
mikeytown2
16th June 2008, 22:14
If the source implements seeking by starting from frame 0 every time, it will be a lot slower than simply reading frames serially.
Good question... If it does start from 0 every time could the FrameCache (http://niiyan.net/?FrameCache) filter prevent seeking from 0; would it act like it's reading all the frames?
FrameCache(20).SelectEvery(20,0)
squid_80
17th June 2008, 00:43
Did you know avisynth already inserts a cache between all filters automatically?
mikeytown2
17th June 2008, 02:25
Did you know avisynth already inserts a cache between all filters automatically?
I guessed it did since my memory usage goes up with every frame. You are correct, using an xvid avi, FPS is the same between these 2 clips in MPC.
DirectShowSource("file.avi",seekzero=true)
SelectEvery(20,0)
DirectShowSource("file.avi",seekzero=true)
FrameCache(20).SelectEvery(20,0)
So AviSynth is smart enough to read all frames so that it doesn't start back at zero every time. Cool!
Edit: just verified in VirtualDub. FPS is the same!
Edit2: Guess it doesn't matter since i'm not going backwards in the timeline. Experimenting with trim would be interesting...
IanB
17th June 2008, 08:58
As you have probably found, cacheing does not help here, the caches only hold every 20th frame. You need to linearize your stream accesses thru the codec.
The SeekZero=True option for DirectShowSource does this as a side effect. It forces when accessing forward all the intervening frames are skip-read. When accessing backwards a seek to frame zero is done followed by skip-reading all the intervening frames. Skip-reading does not transfer data into a PVideoFrame, it just has the video codec decode the next delta frame so as to advance the internal current frame state.
In normal operation the source filters will skip-read forwards up to 10 frames, beyond that they do a direct seek to the desired frame. Delta frame codecs need to implement this as an internal seek to the prior key frame followed by skip-reading upto the desired frame.
If you are processing a delta frame type source with low keyframe frequency then you can be a bit screwed doing sparse access.
E.g. XViD encode, keyframes every 300 frames, accessing every 20th frame. The codec must decode as follows, PVideoFrame copies are Underlined, 0 1 2 3 ... 19 20 0 1 2 ... 39 40 0 1 2 ... 59 60 ... 0 1 2 ... 259 260 300 301 302 ... 339 340 300 301 302 ... 359 360 .... As you can see the poor XViD codec has to really work it's poor little behind off.
For keyframe only formats the opposite occurs if stepping less than 10 frames, i.e. all intervening frames are skip-read even though it is not required. This slowdown is however linear unlike the above which is exponential.
I might make the amount of skip reading tuneable in a future revision.
Note 1:- FrameCache, unlike the internal Avisynth cache, is a hard cache! If you tell it to cache 50 frames it will hold on to an inuse reference to the last 50 PVideoFrame objects fetched no matter what. This can be a very bad thing in low memory situations. It also screws with MakeWriteable, because it holds an inuse reference MakeWriteable must always create a copy and blit the data.
The internal cache is a soft cache, it merely tracks old PVideoFrames without keeping any inuse reference, if they need to be used for other purposes then the cacheing of that frame is lost. To prevent loss of required frames increase the SetMemoryMax setting.
Note 2:- Caches only work when a PVideoFrame is required more than once. Temporal filters and filters that scan back and forwards looking for matches benefit from the cache. Filters that simply plod along always accessing the next frame once only never benefit from a cache.
mikeytown2
17th June 2008, 09:31
As you have probably found, cacheing does not help here, the caches only hold every 20th frame. You need to linearize your stream accesses thru the codec.
The SeekZero=True option for DirectShowSource does this as a side effect. It forces when accessing forward all the intervening frames are skip-read.
Interesting! In Vdub get 5fps with this script
DirectShowSource("D:\file.avi", audio=false)
#FrameCache(50)
SelectEvery(50,0)
AssumeFPS(100)
Where as i get 15fps with this script
DirectShowSource("D:\file.avi",seekzero=true, audio=false)
#FrameCache(50)
SelectEvery(50,0)
AssumeFPS(100)
This is good to know. IanB Thanks for pointing that out! FrameCache does nothing in both scripts. Keyframes were set to every 300 frames.
Ouch.... I get 1.5FPS by using this
AviSource("D:\bestline_mlt-640x640.avi",audio=false)
#FrameCache(50)
SelectEvery(50,0)
AssumeFPS(100)
Temporal filters and filters that scan back and forwards looking for matches benefit from the cache
Speaking of FrameCache, when would a Hard cache be better then a Soft cache (MVTools (http://forum.doom9.org/showthread.php?p=1141506#post1141506)?)? Because as you said, the SetMemoryMax "indirectly" sets the cache size, so just wondering if their could be an advantage by having a Hard cache.
IanB
17th June 2008, 15:23
@mikeytown2,
I cannot think of any case to use FrameCache.
And with SetMemoryMax, there is no "indirectly", it does set the upper limit for the Video Frame Cache.
Caches only work when a PVideoFrame is required more than once!
And MVTools gets into trouble because it manages it's own hard cache (IDX param).
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.