Log in

View Full Version : Behavior when reading past the end of a clip... bug or feature?


stickboy
14th August 2003, 09:08
A number of internal Avisynth functions (notably Trim, SelectEvery and its ilk) don't behave quite how I'd expect when going past the end of a clip. (Of course, I don't presume my expectations are quite in line with everyone else's.)

For example:# 5-frame clip
sourceClip = ColorBars(640, 480).ShowFrameNumber().Trim(0, 4)

c1 = sourceClip.Trim(1000, 2000)
c2 = sourceClip.SelectEvery(10, 7, 8, 9)
This results in c1 being a 1-frame clip and c2 being a 3-frame clip, each composed entirely of copies of the last frame (4).

If I set sourceClip as a 0-frame clip, Trim generates a 1-frame clip containing a blank frame, and SelectEvery generates a 2-frame clip of blank frames. (Yes, two, not three.)

Is this the intended behavior?

Bidoche
15th August 2003, 14:49
Personally, I think Trim should throw an error when dealing with out of bounds input.

stickboy
15th August 2003, 17:11
That's fine with me too.

WarpEnterprises
16th August 2003, 22:39
So a 0-frame-clip does or should not exist, am I right?

stickboy
17th August 2003, 00:18
No, IMO 0-frame clips definitely should be allowed (every system ought to have a concept of "zero"). You can create one with BlankClip, and 0-frame clips can simplify writing of some user-defined functions.

Here's an example, borrowed from my Caveats of using Trim in functions (http://forum.doom9.org/showthread.php?s=&threadid=58358) thread (with some additional comments):
# ApplyRange2
#
# A version of ApplyRange that works with Avisynth 2.0x and that allows
# named arguments and filters that take no arguments.
#
# PARAMETERS:
# start, end - the filter will be applied to all frames in the range
# [start, end]
# thunk - the action to perform on the specified frames
#
# USAGE:
# c.ApplyRange2(123, 456, "Tweak(sat=1.1)")
#
function ApplyRange2(clip c, int start, int end, string thunk)
{
seg1 = c.Trim2(0, start) # Trim2(a, b) trims frames the in
# range [a, b) and allows generation
# of 0-frame clips
seg2 = c.Trim2(start, end + 1) # we want to apply the filter to the range
# range [start, end]
seg3 = c.Trim2(end + 1)

seg2 = Eval("seg2." + thunk)
return seg1 + seg2 + seg3
}If 0-frame clips were disallowed, you'd have to check if start is 0, if end is c.FrameCount() - 1, and then you'd have figure out what combination of segments to splice together at the end. It wouldn't be impossible, but it would be quite a bit more work, more error-prone, and less readable.

Bidoche
17th August 2003, 18:36
zero frames clips definitely have to exist to simplify things.

stickboy
19th August 2003, 20:16
Okay, so back to my original question:
Is the automatic generation of blank frames in out-of-bounds conditions a bug or a feature? Is there anyone who thinks it's useful and who depends on that behavior? Is it behavior that can or should be changed in Avisynth 2.5.x?

sh0dan
20th August 2003, 08:17
In 2.5 the following was inserted into the cache to avoid filters requesting frames outside the valid range:

PVideoFrame __stdcall Cache::GetFrame(int n, IScriptEnvironment* env)
{
n = min(vi.num_frames-1, max(0,n)); // Inserted to avoid requests beyond framerange.
[...]


Most filters do similar clamping, but this is just another safety precaution. This is the only "policy" in 2.5. Otherwise filters are free to choose what to do, but I believe last frame duplication is the most useful.

Edit: Checked trim - it also clamps ranges to valid values. Selectevery does no checks, but relies on the cache check.

Should I have them throw an error if any invalid framenumber is given as argument? I'm not throwing in loads of time on this one.

WarpEnterprises
20th August 2003, 10:03
I now don't understand if a 0-frame-clip is a thing AviSynth can actually handle. Frame 0 is the first frame, so what number is requested if a 0-frame-clip is fed into a function? Or what is the mechanism that prevents such a request?

sh0dan
20th August 2003, 15:40
vi.HasVideo() should perhaps also return false, if vi.num_frames <= 0.