Log in

View Full Version : Caveats of using Trim in functions


stickboy
27th July 2003, 09:04
I was looking through some of the shared functions (http://www.avisynth.org/index.php?page=ShareFunctions), and I saw a few cases where Trim isn't used very carefully. IMO, Trim's syntax--intended for editing convenience--is tricky to use robustly for general-purpose, user-defined functions.

For example, let's say we wanted to write our own version of ApplyRange. Here's the naive approach:# ApplyRange2
#
# A version of ApplyRange that works with Avisynth 2.0x and that allows
# named arguments and filters that take no arguments.
#
# USAGE:
# c.ApplyRange2(123, 456, "Tweak(sat=1.1)")
#
function ApplyRange2(clip c, int start, int end, string thunk)
{
# NOTE: this version isn't very safe!

seg1 = c.Trim(0, start - 1)
seg2 = c.Trim(start, end) # filter will be applied to frames in the
# range [start, end]
seg3 = c.Trim(end + 1, 0)

seg2 = Eval("seg2." + thunk)
return seg1 + seg2 + seg3
}At first glance, there doesn't appear to be anything wrong. But wait! What happens if: start == 0
start == 1
start == c.FrameCount() - 1
start == c.FrameCount()
start > c.FrameCount()
end < 0
end == 0
end == c.FrameCount() - 1
end == c.FrameCount()
end > c.FrameCount()Not all of those cases necessarily lead to unwanted behavior, and some of them don't make sense in the context of ApplyRange. Nevertheless, they still are things you generally need to watch out for when using Trim. Ugh! Who wants to waste time thinking about all that?

(I'm not sure why, but c.Trim(c.FrameCount() + N, 0) returns the last frame of c instead of an error or instead of a 0-frame clip.)

Okay, so what can we do? We can simplify Trim a lot by: using the interval [start, end) instead of [start, end]
disallowing end=0
disallowing out-of-bounds start/end values
allowing generation of null (0 frame) clips
Here are a couple versions of Trim that I use in my functions:

[Edit: code moved to <http://www.avisynth.org/stickboy/>]

Now we safely can define ApplyRange2 as:function ApplyRange2(clip c, int start, int end, string thunk)
{
seg1 = c.Trim2(0, start)
seg2 = c.Trim2(start, end + 1) # filter will be applied to frames in the
# range [start, end]
seg3 = c.Trim2(end + 1)

seg2 = Eval("seg2." + thunk)
return seg1 + seg2 + seg3
}

Edit (2003-08-13):
Greatly relaxed the bounds-checking for Trim2; now allows start/end values that go past the end of the clip.

Edit: (2003-08-20):
Oops, I broke Trim2's support for negative values of end. Should be fixed now, hopefully without breaking anything else.

Isochroma
10th January 2007, 22:21
I'm having some trouble with your JDL_ApplyRange function. First, I'd like to thank you for making it in the first place, because it is needed due to the named parameters taken by hdragc().

The problem is my script has two lines, like this:

JDL_ApplyRange(0,710,"hdragc(coef_gain=1.5,freezer=1)")

JDL_ApplyRange(1410,180975,"hdragc(coef_gain=1.5,freezer=1)")

The area between frames 710-1410 is where I don't want the hdragc() filter to be active. However, when I open this script, the first section (0-710) works as expected, and of course the hdragc() filter doesn't work in 710-1409, but it doesn't show up in 1410+ either.

When I comment # the first line, the hdragc() function then activates for frames 1410+

Can you help me figure out what's going on here? Thanks.

Isochroma
10th January 2007, 22:34
After some experimentation, I've found a way to make it work... all JDL_ApplyRange() lines must be in reverse frame order:

JDL_ApplyRange(1410,180975,"hdragc(coef_gain=1.5,freezer=1)")

JDL_ApplyRange(0,710,"hdragc(coef_gain=1.5,freezer=1)")

This arrangement works fine... I wonder why the former doesn't?

stickboy
14th January 2007, 11:23
Hm, that doesn't make any sense.

I'm not familiar with hdragc, but maybe there's a bug in that filter that affects its behavior when called multiple times. Does it happen with other filters? Does the following work?

a = hdragc(coef_gain=1.5, freezer=1)
b = hdragc(coef_gain=1.5, freezer=1)
c1 = a.Trim(0, 710)
c2 = Trim(711, 1409)
c3 = b.Trim(1410, 180975)
c4 = Trim(180976, 0)
c1 + c2 + c3 + c4

or how about:

c1 = Trim(0, 710).hdragc(coef_gain=1.5, freezer=1)
c2 = Trim(711, 1409)
c3 = Trim(1410, 180975).hdragc(coef_gain=1.5, freezer=1)
c4 = Trim(180976, 0)
c1 + c2 + c3 + c4

Incidentally, discussion of JDL_ApplyRange isn't really relevant to this thread.