PDA

View Full Version : Applying filter to a frame range


moviefan
28th February 2009, 23:06
Hi guys,

I would like to apply a filter to certain frame ranges. Therefore I have written a small function:


function applyFilter(clip clp, int "start", int "end", string "filter")
{
return clp.trim(0,start-1) + Eval("""clp.trim(start,end).filter""") + clp.trim(end+1,0)
}

Does it cause performance issues, when I use this filter several times in a row to specify different frame ranges and apply a filter for each? I would only like to have slower rendering speed when the encoder encodes these ranges.

Regards
moviefan

kemuri-_9
28th February 2009, 23:52
what's wrong with

ApplyRange (clip, int start_frame, int end_frame, string filtername, args)

which is built into avisynth?

the documentation already mentions this as well:

In cases where a large number of ranges need similar processing using many ApplyRange calls may cause resourse issues. An alternative can be to use ConditionalReader with ConditionalFilter to select between the unprocessed and processed version of a source.

Gavino
28th February 2009, 23:53
There are no performance problems, but note that
- your function will not work properly if start is 0 or 1, or end is frameCount-1 (see here);
- the Eval part should be Eval("clp.trim(start,end)."+filter)

There is already an internal filter ApplyRange (http://avisynth.org/mediawiki/ApplyRange).

moviefan
1st March 2009, 11:15
If I did it with conditional filter to check whether I am in a certain frame range, would I be able to apply filters that use reference frames, e.g. MVTools?

MadRat
1st March 2009, 11:39
You might want to avoid using trim functions. Trim will work but I tried it once and ended up taking 19 hours to encode 24 minutes of video.

Gavino
1st March 2009, 12:16
If I did it with conditional filter to check whether I am in a certain frame range, would I be able to apply filters that use reference frames, e.g. MVTools?
You don't want to use ConditionalFilter for something like that - it will be slower as the condition is parsed and evaluated on every frame. Trim is fine as long as you take the special cases into account in coding your function.
You might want to avoid using trim functions. Trim will work but I tried it once and ended up taking 19 hours to encode 24 minutes of video.
Trim itself costs virtually nothing. But of course, with any video in Avisynth, you are necessarily re-encoding every output frame.

MadRat
1st March 2009, 22:18
Trim itself costs virtually nothing. But of course, with any video in Avisynth, you are necessarily re-encoding every output frame.

Yes I understand that. Here's an example of what I did using mostly random filters. I haven't tested this script so I'm not sure it would work but just so everyone understands what I'm referring to here it is.


function FilterChain1(clip c) {
c
Tweak(sat=1.5)
LSFMod(strength=100)
gradfunkmirror()
return last
}

function FilterChain2(clip c) {
c
LSFMod(strength=50)
return last
}

Mpeg2Source("E:\MyVideos\videoclip.d2v")

FilterChainClip2=FilterChain2()
FilterChainClip1=FilterChain1()

FilterChainClip1.Trim(0,1497)+FilterChainClip2.Trim(1498,2038)+FilterChainClip1.Trim(2039,2157)+FilterChainClip2.Trim(2158,4538)

ColorMatrix(mode="Rec.709->Rec.601")
Deblock(quant=25)
Crop(0, 56, -0, -60)


If I were to use ApplyRange or ConditionalReader with ConditionalFilter as mentioned by kemuri-_9 would the script be more effecient and what would it look like?

Gavino
2nd March 2009, 00:24
ApplyRange(0, 1497, "FilterChain1")
ApplyRange(1498, 2038, "FilterChain2")
ApplyRange(2039, 2157, "FilterChain1")
ApplyRange(2158, 4538, "FilterChain2")
would use more memory because all the filters in FilterChain1 and FilterChain2 would be instantiated twice. (That's what the docs are referring to when they talk about resource usage with many calls to ApplyRange.) It probably wouldn't be much slower though unless one of the filters has a significant instantiation time overhead, because each instance only processes its own range of frames.

The ConditionalReader approach (see the docs for an example) would only instantiate each filter once and should be comparable in speed to using Trim manually as in your script (probably slightly slower) - but for a large number of ranges, it is probably a more convenient way to write it.

MadRat
2nd March 2009, 05:37
So other than using moviefan's script, I see three options for applying a range (these scripts have been tested and all work the same).

#1 Functions, Trim and +

function FilterChain1(clip c) {
c
Tweak(sat=1.5)
LSFMod(strength=100)
gradfunkmirror()
return last
}

function FilterChain2(clip c) {
c
LSFMod(strength=50)
return last
}

Colorbars(512,512).Trim(0,4538).ConvertToYV12() # A substitute for Mpeg2Source("E:\MyVideos\videoclip.d2v")

FilterChainClip2=FilterChain2()
FilterChainClip1=FilterChain1()

FilterChainClip1.Trim(0,1497)+FilterChainClip2.Trim(1498,2038)+FilterChainClip1.Trim(2039,2157)+FilterChainClip2.Trim(2158,4538)

# ColorMatrix(mode="Rec.709->Rec.601") # This line commented out because I'm using Colorbars instead of Mpeg2Source
Deblock(quant=25)
Crop(0, 56, -0, -60)


#2 Functions and ApplyRange

function FilterChain1(clip c) {
c
Tweak(sat=1.5)
LSFMod(strength=100)
gradfunkmirror()
return last
}

function FilterChain2(clip c) {
c
LSFMod(strength=50)
return last
}

Colorbars(512,512).Trim(0,4538).ConvertToYV12() # A substitute for Mpeg2Source("E:\MyVideos\videoclip.d2v")

FilterChainClip2=FilterChain2()
FilterChainClip1=FilterChain1()

ApplyRange(0, 1497, "FilterChain1")
ApplyRange(1498, 2038, "FilterChain2")
ApplyRange(2039, 2157, "FilterChain1")
ApplyRange(2158, 4538, "FilterChain2")

# ColorMatrix(mode="Rec.709->Rec.601") # This line commented out because I'm using Colorbars instead of Mpeg2Source
Deblock(quant=25)
Crop(0, 56, -0, -60)


#3 ConditionalFilter and ConditionalReader and an external text file

Colorbars(512,512).Trim(0,4538).ConvertToYV12() # A substitute for Mpeg2Source("E:\MyVideos\videoclip.d2v")

FilterChain1 = Last.Tweak(sat=1.5).LSFMod(strength=100).gradfunkmirror()
FilterChain2 = Last.LSFMod(strength=50)

ConditionalFilter(FilterChain1, FilterChain2, "MyVar", "==", "False", false)
ConditionalReader("frameranges.txt", "MyVar", false)

# ColorMatrix(mode="Rec.709->Rec.601") # This line commented out because I'm using Colorbars instead of Mpeg2Source
Deblock(quant=25)
Crop(0, 56, -0, -60)

frameranges.txt

Type Bool
Default False

R 1498 2038 True
R 2158 4538 True


The first two options can have as many different filter chains as your computer system can handle but as it's written the third script can only deal with an either/or. Either FilterChain1 or FilterChain2. There should be a way to add more and I'll be working on that.

Can someone find out which one encodes the fastest? Is there a way to make them more efficient or is that as good as it gets? How can this be used with moviefan's script to make the whole process of segmenting video easier?

Gavino
2nd March 2009, 10:53
Yes, that's a good summary of the three possible approaches (except that in #2, the lines
FilterChainClip2=FilterChain2()
FilterChainClip1=FilterChain1()
can be removed, since FilterChainClip1 and FilterChainClip2 are not used here).

I haven't tried timing them, but I would not expect a big difference between the three.
Most of the time in Avisynth goes in processing pixels - the rest is mainly just keeping track of which frame to process and is trivial by comparison. In all three cases, the same pixels are processed in the same way to give the same result, so you can't really do any better than that.

So I think mainly it's a choice of which version you find easier to write and understand, with the caveat that using a large number of ApplyRange calls may end up hitting memory limits.
as it's written the third script can only deal with an either/or. Either FilterChain1 or FilterChain2. There should be a way to add more and I'll be working on that.
The ConditionalReader approach can be extended to cover more choices by making the variable an int instead of a bool.

ScriptClip("
Select(MyVar, last, FilterChain1, FilterChain2, FilterChain3)
")
ConditionalReader("frameranges.txt", "MyVar", false)

with frameranges.txt containing something like
Type int
Default 0

R 1498 2038 1
R 2158 4538 2
R 5432 6289 3
This also allows for the possibility of some frame ranges not being processed at all.

stickboy
3rd March 2009, 09:31
In my (not so humble) opinion, using my RemapFrames plug-in (http://www.avisynth.org/stickboy/) is slightly simpler (at the very least, it doesn't require a separate text file) and is more AviSynth-like than the ConditionalReader approach.