AvsTimer 0.8.1

An Avisynth 2.5x plugin for measuring speed and performance of Avisynth plugins

By Rainer Wittmann gorw@gmx.de

The binary and the source code are subject to the GNU General Public License. Last change September 15, 2005.

Installation

Beginning with version 0.8 AvsTimer uses the recursion DLL AvsRecursion. In particular, Avisynth can only load the AvsTimer plugin, if  AvsRecursion is installed (goto the AvsRecursion web site for more details). Because AvsRecursion.dll requires msvcr71.dll anyway, a statically linked version of this plugin no more makes sense. Question, comments etc. should be addressed to the support forum. Though registration is appreciated, you can post to this forum without registration. Thus there is no need to send me email. Because of enormous spam, you must put somewhere in the title the word "Avisynth", if you want to send me email. However, I only check for such email once every two weeks.

Usage

AvsTimer  is an Avisynth filter (for Avisynth 2.5 or higher), which actually doesnīt make any changes to a clip. In fact, it even doesnīt make a simple bitblt operation. Thus its overhead is virtually zero. Rather it is a utility to measure the performance of various filters, decoders etc. and should be particular useful for filter writers who want to tweak their filters for maximum speed. To use it one needs the debugview utility or any other program which can catch and display debug messages. Debugview is also used by various other Avisynth filters. Thus it is a utility which a serious Avisynth user should have anyway. Letīs begin with a simple Avisynth script:  
LoadPlugin("C:\Programme\avisynth\plugins\MPEG2Dec3.dll") 
LoadPlugin("C:\Programme\avisynth\plugins\decomb.dll")
MPEG2Source("input.d2v")
crop(16,4,692,568)
FieldDeinterlace()
If we now insert the two lines,
LoadPlugin("C:\Programme\avisynth\plugins\MPEG2Dec3.dll") 
LoadPlugin("C:\Programme\avisynth\plugins\decomb.dll")
LoadPlugin("C:\Programme\avisynth\plugins\AvsTimer.dll") 
MPEG2Source("input.d2v")
AvsTimer() 
crop(16,4,692,568)
FieldDeinterlace()
load the script into VirtualDubMod and start preview, debugview displays the following output:
[1748] AvsTimer 0.3
[1748] AvsTimer 0.3
[1748] AvsTimer 0.3
[1748] [1999] Timer1 = 69 fps
[1748] [3999] Timer1 = 67 fps
[1748] [5999] Timer1 = 66 fps
[1748] [7999] Timer1 = 65 fps
[1748] [9999] Timer1 = 69 fps
The first number in brackets is the process number of VirtualDubMod. This number is useful, if more than one program is sending debug messages. The second number in brackets is the frame number, at which AvsTimer displays the information. In our example, AvsTimer displays the timer results every two thousand frames. This is the default. We can change the default by using AvsTimer with the option frames. If we insert AvsTimer(frames= 1000) into the script, then the results are displayed every thousand frames. The larger the number of frames the more accurate are the results. Thus it is not a good idea at all to use AvsTimer(frames=1). Perhaps one may then get the error message "zero or negative ticks", because the time was too short to be measurable. If a number <=0 is specified for the frames variable, then frames is simply set to the number of frames of the entire clip. Thus in this case the frame rate is only displayed once after the entire clip has been processed. The first string "Timer1" is the name of the timer. If AvsTimer is inserted three times into the script, then one gets also results from "Timer2" and "Timer3". Instead of these default names, one my specify arbitrary names as an option. If we replace AvsTimer() by AvsTimer(frames=1000, name="mpeg2dec"), then we get the following output from debugview:
[1864] AvsTimer 0.3
[1864] AvsTimer 0.3
[1864] AvsTimer 0.3
[1864] [999] mpeg2dec = 68 fps
[1864] [1999] mpeg2dec = 68 fps
[1864] [2999] mpeg2dec = 68 fps
[1864] [3999] mpeg2dec = 67 fps
[1864] [4999] mpeg2dec = 66 fps
[1864] [5999] mpeg2dec = 67 fps
The value after = is the number of frames per seconds which the filter chain before "mpeg2dec" in the Avisynth script would have, if it would run without the filter chain after "mpeg2dec" and VirtualDubMod. All frame rates are averaged over the last 2000 frames (or the the number specified with the option frames ) and are always rounded up or downwards to the next integer. For instance, the script
LoadPlugin("C:\Programme\avisynth\plugins\MPEG2Dec3.dll") 
LoadPlugin("C:\Programme\avisynth\plugins\decomb.dll")
LoadPlugin("C:\Programme\avisynth\plugins\AvsTimer.dll") 
MPEG2Source("input.d2v")
AvsTimer(frames=1000, name="mpeg2dec") 
crop(16,4,692,568)
FieldDeinterlace()
AvsTimer(frames=1500)
gives the following output:
[1908] AvsTimer 0.3
[1908] AvsTimer 0.3
[1908] AvsTimer 0.3
[1908] [999] mpeg2dec = 68 fps
[1908] [1499] Timer2 = 27 fps
[1908] [1999] mpeg2dec = 69 fps
[1908] [2999] mpeg2dec = 66 fps
[1908] [2999] Timer2 = 27 fps
[1908] [3999] mpeg2dec = 69 fps
[1908] [4499] Timer2 = 27 fps
[1908] [4999] mpeg2dec = 67 fps
[1908] [5999] mpeg2dec = 65 fps
[1908] [5999] Timer2 = 27 fps
Unlike "mpeg2dec" "Timer2" now includes the deinterlacer FieldDeinterlace. Thatīs why the frame rate is now much smaller. One can also measure the frame rate of the filter chain between two calls of AvsTimer. For this purpose we have the "difference" and the "quiet" option. Changing the script as follows: 
LoadPlugin("C:\Programme\avisynth\plugins\MPEG2Dec3.dll") 
LoadPlugin("C:\Programme\avisynth\plugins\decomb.dll")
LoadPlugin("C:\Programme\avisynth\plugins\AvsTimer.dll") 
MPEG2Source("input.d2v")
AvsTimer(frames=1000, name="mpeg2dec", quiet=true) 
crop(16,4,692,568)
FieldDeinterlace()
AvsTimer(frames=1500, name="decomb", difference=1)
we get the following output
[1952] AvsTimer 0.3
[1952] AvsTimer 0.3
[1952] AvsTimer 0.3
[1952] [1499] decomb = 45 fps
[1952] [2999] decomb = 46 fps
[1952] [4499] decomb = 46 fps
[1952] [5999] decomb = 45 fps
[1952] [7499] decomb = 45 fps
[1952] [8999] decomb = 46 fps
The displayed frame rate  is now just the frame rate of the filter chain from crop(...) to FieldDeinterlace() (crop really doesnīt matter as it is a "zero cost" filter). Replacing Decomb with TomsMoComp we get the following results:
[432] AvsTimer 0.3
[432] AvsTimer 0.3
[432] AvsTimer 0.3
[432] [1499] TomsMoComp = 97 fps
[432] [2999] TomsMoComp = 98 fps
[432] [4499] TomsMoComp = 98 fps
[432] [5999] TomsMoComp = 98 fps
[432] [7499] TomsMoComp = 98 fps
[432] [8999] TomsMoComp = 97 fps
If  difference=k is specified for the m-th timer then the filter chain between the m-th and the (m-k)-th timer is taken. If m-k<= 0 then Avisynth terminates with an error message. In the above example we have suppressed the output of "mpeg2dec" with the option "quiet= true". Without this option we would have gotten the same "mpeg2dec" output as before. Instead of taking the average only over the last 2000 frames or whatever has been specified with the frames option, one may average over all frames, which have been processed so far, by setting the boolean variable accumulate  to true. Thus the script
LoadPlugin("C:\Programme\avisynth\plugins\MPEG2Dec3.dll") 
LoadPlugin("C:\Programme\avisynth\plugins\TomsMoComp.dll")
LoadPlugin("C:\Programme\avisynth\plugins\AvsTimer.dll") 
MPEG2Source("input.d2v")
AvsTimer(frames=1000, name="mpeg2dec", accumulate=true) 
crop(16,4,692,568)
TomsMoComp(1, 5, 0)
AvsTimer(frames=1500, name="TomsMoComp" , difference=1)
gives the following results
[652] AvsTimer 0.3
[652] AvsTimer 0.3
[652] AvsTimer 0.3
[652] [999] mpeg2dec = 68 fps
[652] [1499] TomsMoComp = 96 fps
[652] [1999] mpeg2dec = 69 fps
[652] [2999] mpeg2dec = 68 fps
[652] [2999] TomsMoComp = 97 fps
[652] [3999] mpeg2dec = 68 fps
[652] [4499] TomsMoComp = 97 fps
[652] [4999] mpeg2dec = 68 fps
[652] [5999] mpeg2dec = 68 fps
[652] [5999] TomsMoComp = 98 fps
[652] [6999] mpeg2dec = 67 fps
[652] [7499] TomsMoComp = 98 fps
[652] [7999] mpeg2dec = 67 fps
[652] [8999] mpeg2dec = 68 fps
[652] [8999] TomsMoComp = 98 fps
[652] [9999] mpeg2dec = 68 fps
[652] [10499] TomsMoComp = 98 fps
[652] [10999] mpeg2dec = 68 fps
[652] [11999] mpeg2dec = 68 fps
[652] [11999] TomsMoComp = 98 fps
[652] [12999] mpeg2dec = 68 fps
[652] [13499] TomsMoComp = 97 fps
[652] [13999] mpeg2dec = 68 fps
[652] [14999] mpeg2dec = 68 fps
[652] [14999] TomsMoComp = 97 fps
In this example the "mpeg2dec" timer averages over all previous frames while "TomsMoComp" timer averages only over the last 1500 frames. Consequently the frame rates for "mpeg2dec" stabilise with more and more frames processed, while the frame rates for "TomsMoComp" continue to fluctuate. AvsTimer comes with four methods for measuring time. The default method type=2 is based on the windows functions GetThreadTimes, which measures the time the filter chain spends within the thread, by which is it is called. This is the most accurate method as long as no other threads are used by the filter chain. Currently I know of no example which violates this assumption. However, as hyperthreading becomes more and more fashionable times may change. If one uses the option type=1, then time is measured with GetProcessTimes. Then the time of the process, which runs the Avisynth script, is measured, while the process is executing the filter chain. However, some threads of this process, which have nothing to do with the filters, but run parallel may artificially reduce the frame rate. If type=0 or type=3 is used, then instead of process or thread time the absolute time is taken. Then also other processes may influence the frame rates to the downside. If  type=0 then the function QueryPerformaceCounter is used, if type=3 then the cpu instruction RDTSC is used. type=3 has certainly the smallest overhead, but during initialisation 1 second is necessary to determine the cpu frequency and on some notebooks the cpu frequency may change over time obliterating all the results. To avoid the delay one may also specify the cpu frequency with the frequency option. This must happen with the first type=3 timer or any other timer befor the first type=3 timer otherwise the frequency option is ignored. Thus AvsTimer(type=3, frequency= 1300) defines a type= 3 timer for a cpu with 1300 MHZ. One can get the exact cpu frequency by running a type= 3 timer without the frequency option. Then the exact cpu frequency is displayed in the debugview window. Timers, which are paired together by the difference option, shouldbe of the same type, otherwise the results do not make sense and may even yield negative frame rates. Timers of type!= 2 have an additional advantage. With such timers the frame rate of the entire process running the script  - we call this the total frame rate - can be measured and is displayed by default. Thus the script
LoadPlugin("C:\Programme\avisynth\plugins\MPEG2Dec3.dll") 
LoadPlugin("C:\Programme\avisynth\plugins\decomb.dll")
LoadPlugin("C:\Programme\avisynth\plugins\AvsTimer.dll") 
MPEG2Source("input.d2v")
AvsTimer(frames=1000, name="mpeg2dec", type=3) 
crop(16,4,692,568)
FieldDeinterlace()
AvsTimer(frames=1500, name="decomb", type=3, difference=1)
gives following output
[1252] AvsTimer 0.3
[1252] AvsTimer 0.3
[1252] AvsTimer 0.3
[1252] CPU frequency = 1312 MHZ
[1252] [999] mpeg2dec = 68 fps, total = 17 fps
[1252] [1499] decomb = 45 fps, total = 19 fps
[1252] [1999] mpeg2dec = 68 fps, total = 26 fps
[1252] [2999] mpeg2dec = 67 fps, total = 26 fps
[1252] [2999] decomb = 46 fps, total = 25 fps
[1252] [3999] mpeg2dec = 67 fps, total = 26 fps
[1252] [4499] decomb = 46 fps, total = 25 fps
[1252] [4999] mpeg2dec = 67 fps, total = 25 fps
[1252] [5999] mpeg2dec = 65 fps, total = 25 fps
[1252] [5999] decomb = 45 fps, total = 25 fps
[1252] [6999] mpeg2dec = 66 fps, total = 25 fps
[1252] [7499] decomb = 46 fps, total = 25 fps
The output of the total frame rate can be disabled by using the total= false option. It is notable from the above output, that the first total frame rate of each timer is substantially lower than the subsequent ones. This is because the "total" clock of each timer is started, when the filter is created by Avisynth. Because the timers are of type=3 even the time until preview is started in VirtualDubMod is counted. Thus the first total frame rates should be ignored if timers of type=0 or 3 are used or one should use GetAll, which is described below. From the above tests we see that TomsMoComp with 98 fps is much faster than FieldDeinterlace with 45 fps which  is even significantly slower than the hard working mpeg2dec3 with 66 fps. All the above tests were run on a 1.3 GHZ Celeron (Tualatin P3 design) with AvsTimer 0.3 .

Benchmarking filters with two or three input clips

To measure the performance of a filter with one input clip, two instances of AvsTimer are neccessary. One immediately after the filter and the input clip should be created by  an earlier instance of AvsTimer, i.e.
AvsTimer(filter(AvsTimer(input, quiet=true)), difference=1, frames=1000)
measures the performance of filter(clip input). If the filter to be benchmarked requires two input clips, three instances of AvsTimer are necessary. One for the filter itself and the other two for the two input clips.
AvsTimer(filter(AvsTimer(input1, quiet=true), AvsTimer(input2, quiet=true)), difference=1, difference2=2, frames=1000)
measures the performance of filter(clip input1, clip input2).
AvsTimer(filter(AvsTimer(input1, quiet=true), AvsTimer(input2, quiet=true)), difference=2, difference2=1, frames=1000)
works equally well. Similarily filter(clip input1, clip input2, clip input3) can be benchmarked with
AvsTimer(filter(AvsTimer(input1, quiet=true), AvsTimer(input2, quiet=true), AvsTimer(input3, quiet=true)) \
					          , difference=1, difference2=2, difference3=3, frames=1000)

 

AvsTimer and the Avisynth Cache and the SetCache function

In order to avoid reprocessing of frames, Avisynth has a cache for each instance of a filter in a script. This cache clearly enhances performance, if time consuming filters which operate on multiple frames are used. AvsTimer allows you to monitor the efficiency of these caches. In fact, in most cases, is able to replace the  cache of the filter immediately before AvsTimer and replaces it by its own cache without any measurable performance penalty. For instance in the script
LoadPlugin("C:\Programme\avisynth\plugins\MPEG2Dec3.dll") 
LoadPlugin("C:\Programme\avisynth\plugins\decomb.dll")
LoadPlugin("C:\Programme\avisynth\plugins\AvsTimer.dll")
MPEG2Source("input.d2v")
AvsTimer(frames=1000, name="mpeg2dec", type=3)
crop(16,4,692,568)
FieldDeinterlace()
AvsTimer(frames=1500, name="decomb", type=3, difference=1)
the first AvsTimer instance takes over the cache of MPEG2Source and the second instance takes over the cache of  FieldDeinterlace. What is this taking over good for? If the frame difference between two output lines of an AvsTimer instance is exactly the value of the frames variable, then there was no cache miss for the filter taken over by this instance of AvsTimer. More precisely we have the formula

number of cache misses = frames - (frame difference of two subsequent output lines)

To be more concrete we look at the output of this script in the previous section. The frame counts of the instant of AvsTimer with name "mpeg2dec" are 999,1999,2999, 3999,4999,5999,6999. Thus the frame difference is always 1000, which is exactly the value of the frames variable. Thus there was no cache miss for the important clip generator MPEG2Source. Similarily, The frame counts of the instant of AvsTimer with name "decomb" are 1499,2999,4499,5999,7499. Thus the frame difference is always 1500, which is exactly the value of the frames variable of this AvsTimer instance. Hence there was also no cache miss for the filter FieldDeinterlace. Though the cache resources are quite limited (they depend on the resolution and the color space of the frame) and the Avisynth is far from optimal it works perfectly for small scripts like the above. However, in scripts with many sophisticated filters substantial cache misses are inevitable and AvsTimer should measure these accurately. To get optimal throughput of scripts with many filter, each filter should have an option to disable its cache. In this way caching could be restricted to the most important filters in order to maximise performance, which can be monitored by AvsTimers. Unfortunately the Avisynth filter API does not provide such a function. Fortunately James D. Lin invented a trick to manipulate the cache of a clip. This trick is embodied in the function SetCache of this plugin. SetCache(input, value) sets the cache of the clip input to value. If value < 0 then the cache of this clip is simply disabled. If value > 50 then the cache is set to CACHE_ALL and if 0 <= value <= 50, then the range of the cache is set to value.

The Delay Filter and AssignRecursionClip

The delay filter is the first filter at all, which features script recursion. It is used as follows:

Delay(clip input, int "recursive", int "delay", int recdelay)
If AssignRecursionClip is not applied later, then Delay(input) behaves as trim(1, input). More generally, Delay(input, delay =  -n) behaves as trim(n,0). The situation changes dramatically, if a recursion slot is allocated with the variable recursive and if the recursion slot is filled later with AssignRecursionClip. To illustrate this, we look at the following script function:
function DR(clip input, int "repmode")
{
	repmode = default(repmode, 16)
	delayed = Delay(input, recursive=0)
	setcache(delayed, -1) # the cache of zero cost filters should always be disabled
	rep = Repair(delayed, input, mode=repmode)
	AssignRecursionClip(rep, 0)
	return rep
}
Here the filter Delay creates the clip "delayed" and allocates the recursion slot 0 (there are currently 10 recursion slots with numbers ranging from 0 to 9). Without AssignRecursionClip(rep, 0), the clip "delayed" would behave as trim(input,1,0). Somewhat later  the clip "rep" is assigned to the recursion slot 0 with AssignRecursionClip(rep, 0).  Consequently, when frames are requested sequentially, then the clip "delayed" delivers the frames from trim(rep,1,0) instead of the frames from trim(1,0). Thus if frames are requested sequentially, then the above script function would behave as
function DR(clip input, int "repmode")
{
	repmode = default(repmode, 16)
	rep = Repair(trim(rep,1,0), input, mode=repmode)
	AssignRecursionClip(rep, 0)
	return rep
}
However, this is not a valid Avisynth script function, because the clip "rep" is used before it is defined. In other words, it is used recursively and this is not allowed in Avisynth scripts. If frames are requested randomly from the clip "delayed", then delayed cannot deliver frames from trim(rep,1,0) because these frames are not in the cache of the clip rep, whence "delayed" delivers frames from trim(input,1,0) in random access mode. However, during encoding always the sequential access mode is used. Thus the filter Delay combined with AssignRecursionClip makes robust recursion possible for Avisynth. Clips created with Delay are always protected against infinite recursion. After assigning a clip to a recursion slot, the recursion slot is released and can be allocated again by Delay or other forthcoming recursive filters. This is important, when a script function is applied more than once. If AssignRecursionClip assigns a clip to a recursion slot, which has not been allocated before, the script terminates with an error message. The variable "recdelay" (default value = -1) is similar to the variable "delay" (also with default value -1), but is used only in sequential mode. For instance
function DR(clip input, int "repmode")
{
	repmode = default(repmode, 16)
	delayed = Delay(input, recursive=7, recdelay=-n)
	setcache(delayed, -1) # the cache of zero cost filters should always be disabled
	rep = Repair(delayed, input, mode=repmode)
	AssignRecursionClip(rep, 7)
	return rep
}
behaves as
function DR(clip input, int "repmode")
{
	repmode = default(repmode, 16)
	rep = Repair(trim(rep,n,0), input, mode=repmode)
	AssignRecursionClip(rep, 0)
	return rep
}
if it would be a valid Avisynth script function. Note, that this time we have used the recursion slot 7. Using positive values for the "delay" variable makes perfect sense. On the other hand, positive values for "recdelay" do not make much sense, because hte requested frames cannot be in the cache of the clip "rep", if recdelay >= 0. Consequently, the clip "delayed" will stop the recursion and will usually deliver frames from trim(input,-delay,0).  By the way, the above script function DR is a quite fast filter for improving compression. The filters "Clense" (from the RemoveGrain plugin), "DupBlocks" (from the RemoveDirt plugin) and ReduceFluctuations (from the ReduceFlicker plugin) will support recursion directly. The filter Delay is no more neccessary, but AssignRecursionClip has to be used as before.

The GetAll Filter

As already  mentioned in the preceding section other programs or threads may influence the results if type!= 2.  Thus for performance tests a simple program, which would only request one frame after the other from Avisynth and do nothing else, would be ideal. It would even be better as far as accuracy is concerned to have a filter with such a property. Thatīs what GetAll is all about.  If VirtualDubMod or any other program running the Avisynth script is requesting the trigger frame (by default this is the first frame and has the frame number 0) from Avisynth and GetAll is in the filter chain, then GetAll request all other frames before it returns the trigger frame to the calling program which then has to wait for quite a while. All frames may be a little to much. With GetAll(frames=10000) GetAll will only request the first 10000 frames. Modifying our example script as follows
LoadPlugin("C:\Programme\avisynth\plugins\MPEG2Dec3.dll") 
LoadPlugin("C:\Programme\avisynth\plugins\decomb.dll")
LoadPlugin("C:\Programme\avisynth\plugins\AvsTimer.dll") 
MPEG2Source("input.d2v")
AvsTimer(frames=1000, name="mpeg2dec", type=0) 
crop(16,4,692,568)
FieldDeinterlace()
AvsTimer(frames=1500, name="decomb", difference=1, type=0)
GetAll(frames=10000)
we get the following output
[2000] AvsTimer 0.3
[2000] AvsTimer 0.3
[2000] AvsTimer 0.3
[2000] [999] mpeg2dec = 66 fps, total = 25 fps
[2000] [1499] decomb = 44 fps, total = 26 fps
[2000] [1999] mpeg2dec = 67 fps, total = 27 fps
[2000] [2999] mpeg2dec = 66 fps, total = 27 fps
[2000] [2999] decomb = 46 fps, total = 27 fps
[2000] [3999] mpeg2dec = 63 fps, total = 26 fps
[2000] [4499] decomb = 45 fps, total = 26 fps
[2000] [4999] mpeg2dec = 65 fps, total = 26 fps
[2000] [5999] mpeg2dec = 64 fps, total = 26 fps
[2000] [5999] decomb = 45 fps, total = 26 fps
[2000] [6999] mpeg2dec = 65 fps, total = 26 fps
[2000] [7499] decomb = 45 fps, total = 26 fps
[2000] [7999] mpeg2dec = 65 fps, total = 27 fps
[2000] [8999] mpeg2dec = 68 fps, total = 27 fps
[2000] [8999] decomb = 46 fps, total = 27 fps
[2000] [9999] mpeg2dec = 67 fps, total = 27 fps
Now it is no more necessary to start preview, because by requesting frame 0, VirtualDubMod triggers GetAll to request the first 10000 frames. Only after it has completed these 10000 frames the frame 0 is delivered to VirtualDubMod. The disadvantage of GetAll, of course, is that it cannot be used during a normal encoding process.  To get trustworthy frame rates with timers of type!=2 insert GetAll immediately after the last AvsTimer call, shut down all cpu intensive processes and run the script in VirtualDubMod to trigger GetAll.

The Shutdown Filter

As the name indicates,  the sole purpose of the Shutdown filter is to shut down the PC or to log off after the encoding process is finished. If the line "Shutdown()" is placed in an Avisynth script (this can only be done once and should be done on the last line of the script) and if the encoder requests the last frame of the clip for the first time, then the Shutdown filter initiates a shutdown of the PC. Usually the encoder needs some further time to finish the encoding process, after it has requested the last frame. Hence the Shutdown filter waits for a certain time (the default is 60 seconds) before starting the shutdown. Using the wait option the waiting time can be changed. For example if "Shutdown(wait=600)" is used, then it waits for 600 seconds = 10 minutes until shutdown. To avoid unwanted shutdown the Shutdown checks again after the waiting time is over, whether the last requested frame was the last frame of the clip. If not, then the last frame wasprobably only requested by browsing within Virtualdub and the shutdown is not initiated. Instead of a shutdown one may simply log off by using the method option. With "Shutdown(method=0) the user is simply logged off after the encoding process is finished. method=1 is the default and results in a shutdown, method=2 results in a poweroff, which is usually identical to a shutdown, finally method= 3 reboots the PC after finishing the encoding process. All other values for the method option are illegal. Once the shutdown or the logoff is initiated it can no more be stopped. It can however be stopped during the waiting time by simply shutting down the encoder. For this purpose the Shutdown filter signals the start of the waiting period with a short beep tone.The default frequency of this beep tone is 1000Hertz (it can be changed to, say, 2000 Hertz with the option "frequency= 2000") and the default duration is 1000 ms= 1 second (it can be changed to, say, 500 ms with the option "duration= 500"). Sometimes the user changes his opinion and doesn't want a shutdown any more though the encoder is processing an AVS script withthe Shutdown filter.For this purpose there is the stamp option. Using the option "stamp= myfile" the filter only initiates a shutdown if "myfile"exists and it checks the existence before and after the waiting period. Thus by erasing or renaming the stamp file one can avoid a shutdown even if the Shutdown filter is in the script. I always use the Shutdown filter with this option. There is one problem with this stamp file method, though. The next day, after the shutdown, the stamp file is still there. But I have only a very limited number of scripts, which are adjusted to a specific encoding process. Now if I load such an "old" script, it is still triggered for a shutdown, if I accidentally touch the last frame. To avoid such unpleasant shutdown surprises, I have added the rename; variable, to rename the stamp file just before shutdown is started. The following command is at the end of all my scripts: Shutdown(stamp= "c:\video\stamp", rename= "c:\video\stampn", wait = 300). If now the Shutdown filter triggers a shutdown, it renames the stamp file, such that it can no more cause an accidential shutdown. Clearly the Shutdown filter can only work properly if the encoder doesn't terminate after finishing the encoding process. However, for such encoders the Shutdown filter isn't needed, because in this case the shutdown can be achieved by a batch file using one of the many freeware shutdown utilities. The Shutdown filter tries to terminate all processes gracefully by sending them appropriate messages. However, if a process does not respond properly to these messages, it is getting killed which may result in data loss. Use this filter only at your own risk and don't blame me.

Known Problems

Alternative

Kurosu has a similar program called Kronos . In fact, Kronos was first.