Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion.

Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules.

 

Go Back   Doom9's Forum > Capturing and Editing Video > Avisynth Usage

Reply
 
Thread Tools Search this Thread Display Modes
Old 5th December 2008, 15:59   #1  |  Link
JonE
Registered User
 
JonE's Avatar
 
Join Date: Sep 2008
Location: Birmingham (UK)
Posts: 69
AviSynth Efficiency

There are often many different ways to write code, each producing identical results but some more efficiently than others.

Are there any general "efficiency" tips for AviSynth scripts, be that processing speed or resource usage ?

One example : I have a project with many bitmaps which are displayed one after another (a slideshow). Once an image has been displayed it is no longer needed but seems to remain in memory. Is there any way to "release" the memory ?

Now, before you all say "buy some more RAM you cheapskate", there could be 600+ images of 5-10MB each so thats 3GB-6GB !

TTFN,
Jon
JonE is offline   Reply With Quote
Old 5th December 2008, 16:11   #2  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,431
Are you saying you have a script with 600+ instances of ImageSource?

Better would be to name your image files in such a way that a single ImageSource call could be used, then use Trim and Loop to construct your slideshow sequence.
Gavino is offline   Reply With Quote
Old 5th December 2008, 17:41   #3  |  Link
cogman
The Crazy Idahoan
 
Join Date: Jun 2007
Location: Idaho
Posts: 249
Perhaps he means tips like this.

Deinterlacing/Telicide (and consequently decimation / any fps modification) stuff should always go first.

Next, any cropping that makes the image smaller. (so if you are adding black bars, don't put cropping first)

Resizing also goes ether before or after denoising. If you are resizing to make the image smaller, it should go before (unless you want a cleaner film). If it is making the image bigger it should always go after the denoising stuff.

And finally do any denoising stuff.

Other then that, order is somewhat unimportant. Just remember that you want the fastest speed, run denoising when you have the smallest resolution, and the slowest FPS. Effectively reducing the amount of denoising that has to be done.
cogman is offline   Reply With Quote
Old 12th December 2008, 10:17   #4  |  Link
JonE
Registered User
 
JonE's Avatar
 
Join Date: Sep 2008
Location: Birmingham (UK)
Posts: 69
Sorry for being slow to get back on this one.

Quote:
Are you saying you have a script with 600+ instances of ImageSource?
Not yet - but eventually yes. This example is of converting some scanned family albumn slides into a DVD movie (the slides themselves are restored in a seperate graphics package).

When playing back slides as a movie, it can be a bit dull unless you zoom the images - doesn't have to be a massive zoom, even a slow zoom from 100% to 110% is ok. However, zooming is done on individual frames so yes, it is 600 potential instances of ImageSource.

Initial testing indicates that once loaded images remain in memory. So, when rendering frame 600, frame 1 is still in memory even though it could have long been discarded (this based on test of ~20 images).

So, was wondering if there were any efficiency differences in different methods. For example, a basic script:-

a = ImageSource(...#1...)
b = ImageSource(...#2...)
c = ImageSource(...#3...)
d = ImageSource(...#4...)
e = ImageSource(...#5...)
....
return a+b+c+d+e+....

Could be written as
a = ImageSource(...#1...)
b = ImageSource(...#2...)
c = ImageSource(...#3...)
d = ImageSource(...#4...)
e = ImageSource(...#5...)
...
part1=a+b+c
part2=d+e+f
...
return part1+part2+...

which in some other scripting based programs would be more efficient structure.

With my programmers hat on,
a = ImageSource(...#1...)
a = a+ ImageSource(...#2...)
a = a+ ImageSource(...#3...)
a = a+ ImageSource(...#4...)
a = a+ ImageSource(...#5...)
...etc

might be more efficient.

Tests show there are no differences between these.

However, I don't want to get to bogged down on this spcific image source case. Rather, in general are there different ways of (re)structuring an AviSynth script such that it produces exactly the same video but more efficiently ? "Efficient" may mean memory usage or rendering speed.

TTFN,
Jon
JonE is offline   Reply With Quote
Old 12th December 2008, 11:41   #5  |  Link
weaker
Registered User
 
Join Date: Feb 2008
Posts: 26
Also have a look at DVDslideshowGUI http://download.videohelp.com/tin2tin/index.html if you think of creating a DVD. It is made especially for that purpose. On the site it says that it has avs as file export option.
weaker is offline   Reply With Quote
Old 12th December 2008, 14:05   #6  |  Link
JonE
Registered User
 
JonE's Avatar
 
Join Date: Sep 2008
Location: Birmingham (UK)
Posts: 69
Thanks for the link, the intro on the website looks quite impressive so I shall investigate further.

However slideshows are only part of the question - I was just wondering whether, in general, there are ways to structure scripts such that they are more efficient.

TTFN,
Jon
JonE is offline   Reply With Quote
Old 12th December 2008, 14:19   #7  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,431
Quote:
Originally Posted by JonE View Post
Tests show there are no differences between these.
That's what I would expect, since each version has the same number of ImageSource instances, and produces exactly the same filter graph.

If instead, you could do what I was suggesting (name your image files in such a way that a single ImageSource call could be used), you would reduce the memory usage. You can still make individual clips out of the images (using Trim and Loop) for separate zooming, etc. For example,
Code:
images = ImageSource(...) # all images in sequence
a = images.Trim(0, -1).Loop(aLength)
b = images.Trim(1, -1).Loop(bLength)
c = images.Trim(2, -1).Loop(cLength)
...
Editing-type filters like Trim and Loop cost virtually nothing in time or memory.
Quote:
in general are there different ways of (re)structuring an AviSynth script such that it produces exactly the same video but more efficiently ? "Efficient" may mean memory usage or rendering speed.
It's difficult to give general advice but cogman's post above is a good starting point. It helps to consider the final filter graph and the work done by each filter, even sketching this out on a piece of paper for complex scripts. Changing the processing order can often help to avoid unncecessary work.

Having the right mental picture of how Avisynth works is also indispensable. See here in general and the performance section in particular.

Last edited by Gavino; 12th December 2008 at 16:07. Reason: Reference to wiki
Gavino is offline   Reply With Quote
Old 13th December 2008, 16:13   #8  |  Link
NerdWithNoLife
Registered User
 
NerdWithNoLife's Avatar
 
Join Date: Jul 2007
Posts: 157
From Fauskes.net:
Code:
# Load image sequence with filenames 0001.png, 0002.png, ..., 1999.png
video = ImageSource("%04d.png", start=1, end=1999, fps=25,pixel_type = "rgb32")
Then you could trim/loop the individual images and use them as separate clips for KenBurnsEffect or something like that.
__________________
f=33
NerdWithNoLife is offline   Reply With Quote
Old 14th December 2008, 04:40   #9  |  Link
IanB
Avisynth Developer
 
Join Date: Jan 2003
Location: Melbourne, Australia
Posts: 3,167
@JonE,

Yes lots of instances of ImageSource() is a big problem. If the images are all the same size and orientation then you can use the "%04d.png" style, but often they are not.

I have used the following style to get around these problem :-
Code:
# List of filenames
Function FileNames(int N) {
  return select(n, \
    "F:\DCIM\100MSDCF\DSC00013.JPG", \
    "F:\DCIM\100MSDCF\DSC00010.JPG", \
    "F:\DCIM\100MSDCF\DSC00011.JPG", \
    "F:\DCIM\100MSDCF\DSC00012.JPG", \
    "F:\DCIM\100MSDCF\DSC00004.JPG")
}

# Prototype clip
BlankClip(5, pixel_type="rgb24")

# Resized ImageSource, single instance per frame
ScriptClip("ImageSource(FileNames(current_frame)).Spline16Resize(Width(), Height())")
This results in each frame being a fresh instance of ImageSource and matching Spline16Resize, so there are no problems with 100's of instances of ImageSource or unique resizers.

Normally I council against this style of script, exactly because of the fresh instance per frame issue, but in this case it is a positive attribute.

Getting the structure right is a bit tricky. You need a prototype BlankClip at the start to keep ScriptClip happy (It wants the input and output frames to be compatible)
IanB is offline   Reply With Quote
Old 14th December 2008, 11:40   #10  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,431
Quote:
Originally Posted by IanB View Post
You need a prototype BlankClip at the start to keep ScriptClip happy
And to define the number of frames (as Ian has shown - that's where the 5 comes from).

This is a really neat solution. As well as solving the specific problem, it shows how to simulate an array with a function and a Select. And gives an example of when it makes sense to use current_frame.

And of course, it can also be extended with the Trim and Loop approach to make subclips out of the original images.
Gavino is offline   Reply With Quote
Old 15th December 2008, 09:34   #11  |  Link
JonE
Registered User
 
JonE's Avatar
 
Join Date: Sep 2008
Location: Birmingham (UK)
Posts: 69
Thanks all,

@InnB : Yes, that works well ; after the first ~10 images, memory usage (running script in Monogram GraphStudio and looking in Program Manager) hits ~80-90MB and then stops rising.

@Gavino : So, the rule seems to be to make one "stream" (e.g. images = ImageSource(...) in your example) and then extract sections from it. I applied the same logic to video files; for example instead of say:-

Code:
a = AviSource(..).Trim(0,100)
b = AviSource(..).Trim(1000,100)
c = AviSource(..).Trim(2000,100)
return a+b+c
it is more efficient to do

Code:
video=AviSource(..)
a = video.Trim(0,100)
b = video.Trim(1000,100)
c = video.Trim(2000,100)
return a+b+c
(The latter also plays back smoothly without pauses at the start of each section).

Quote:
Having the right mental picture of how Avisynth works is also indispensable.
Yes, I think I need to delve a little further.

Thanks for the help,

TTFN,
Jon
JonE is offline   Reply With Quote
Old 15th December 2008, 11:10   #12  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,431
Quote:
Originally Posted by JonE View Post
So, the rule seems to be to make one "stream" (e.g. images = ImageSource(...) in your example) and then extract sections from it. I applied the same logic to video files...
Yes, that's right, generally speaking, since the 'extracting' costs virtually nothing.

However, as with all things in life, there can be exceptions. Suppose you were constructing a clip that jumped backwards and forwards in a source that did not support fast seeking. Then it might make sense to have two instances of the source filter.
Eg instead of
Code:
s = DirectShowSource(...)
a = s.Trim(...)
b = s.Trim(...)
Interleave(a, b)
do
Code:
a = DirectShowSource(...).Trim(...)
b = DirectShowSource(...).Trim(...)
Interleave(a, b)
This is an invented example, but it shows why it's hard to give rigid 'rules'. Because Avisynth is so flexible, and you can do just about anything, the surest way is to think your script through from first principles, armed with a good understanding of the way Avisynth works.
Gavino is offline   Reply With Quote
Old 17th December 2008, 09:37   #13  |  Link
JonE
Registered User
 
JonE's Avatar
 
Join Date: Sep 2008
Location: Birmingham (UK)
Posts: 69
Thanks Gavino,

Yes, I hadn't considered effect of efficiency drive on actual playback. Your latter example plays back more efficiently, but initial graph rendering time can get a bit nasty - not an issue when only dealing with a few clips / clip sections but another project I'm contemplating could end up chopping a clip into a considerable number pieces (using a homebrew editor) so rendering time becomes an issue.

Anyhow, I think I've now got a better picture of whats going on, thanks for the help.

TTFN,
Jon
JonE is offline   Reply With Quote
Old 25th March 2009, 16:46   #14  |  Link
tin3tin
Registered User
 
tin3tin's Avatar
 
Join Date: Mar 2005
Posts: 366
I've tried this concept:
Code:
# List of filenames
Function FileNames(int N) {
  return select(n, \
    "F:\DCIM\100MSDCF\DSC00013.JPG", \
    "F:\DCIM\100MSDCF\DSC00010.JPG", \
    "F:\DCIM\100MSDCF\DSC00011.JPG", \
    "F:\DCIM\100MSDCF\DSC00012.JPG", \
    "F:\DCIM\100MSDCF\DSC00004.JPG")
}

# Prototype clip
BlankClip(5, pixel_type="rgb24")

# Resized ImageSource, single instance per frame
ScriptClip("ImageSource(FileNames(current_frame)).Spline16Resize(Width(), Height())")
It seems like a RAM friendly way to import a lot of big images, but it kills the playback speed even with a few images.

Are there any other ways to load a lot of big images, downscale them and then release the original images from the memory? I imagine something like... what if 'Imagesource' had width and height parameters?
__________________
DVD slideshow GUI(Freeware).
tin3tin is offline   Reply With Quote
Old 25th March 2009, 19:24   #15  |  Link
Wilbert
Moderator
 
Join Date: Nov 2001
Location: Netherlands
Posts: 6,364
Quote:
Are there any other ways to load a lot of big images, downscale them and then release the original images from the memory? I imagine something like... what if 'Imagesource' had width and height parameters?
Immaavs has this functionality.
Wilbert is offline   Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 08:35.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.