PDA

View Full Version : memory leak w. Helix producer or DirectShow?


karl_lillevold
6th March 2003, 02:39
I wanted to mention this problem in this forum where all the Avisynth experts are, in case someone has run into something similar when an Avisynth file is read via DirectShow's AVI reader.

I have filed a problem for Helix Producer on
https://bugs.helixcommunity.org/show_bug.cgi?id=148

EDIT 27 Jul 2004 (fixed link to bug)

Since you need sign up with Helix Community to access this, I better repeat the description here:

I noticed that when I use an Avisynth script as
input to producer for 2-pass encoding, memory
usage almost doubles during the 2nd pass, even
though producer completely shuts down the
DirectShow reader before starting the 2nd pass.

So I ran another test, where I asked producer to
encode a directory with five AVS files. Producer
will then batch encode all the files in the
directory individually. What happened was that for
the last file,
producer's memory use was at 300 MB!

I have seen this with many previous versions of
Avisynth, but this specific example is with 2.5.

Could it be something about how producer shuts
down the DirectShow reader, or a problem with how
DirectShow interacts with Avisynth? The reason I
ask this, is because doing a 2-pass XviD encode in
VirtualDub with the exact same AVS input, memory
usage does /not/ increase.


My AVS scripts generally look something like
LoadPlugin
("C:\avisynth\mpeg2dec\mpeg2dec.dll")
stream=MPEG2Source("L:\source.d2v")
audiofile=WAVSource("L:\source.wav")
stream=AudioDub(stream,audiofile)
stream=BilinearResize(stream,720,480)
stream=Trim(stream,0,2000)
return(stream)

sh0dan
6th March 2003, 19:37
Yes - it seems to have been the case for quite some time.

Do you know any good (preferably free) tools to detect leaks, or dumping the heap, showing where stuff was allocated.

Memory is deallocated when the IAVIFile::Release() is called.

zettai
6th March 2003, 20:42
I can't help locate the leak, but I can confirm that this is not the only situation where these memory overloads then crashes occur.

If you use the premiere import plugin and import many avisynth files the memory usage goes through the roof when you start using them, causing avisynth to crash and kill any project you are trying to render.

karl_lillevold
12th March 2003, 08:50
I finally got around to compiling the AviSynth source code, and now I just have to find some time to debug it when used by producer. Not sure I'll be able to find anything useful though, but at least I get to learn about how Avisynth works, which I have always been curious about.

sh0dan
12th March 2003, 10:15
Feel free to post any observations or questions you have! :)

karl_lillevold
13th March 2003, 03:24
I had some time today, and here's what I found so far:
It seems that if I comment out the parent->AddRef() in


CAVIStreamSynth::CAVIStreamSynth(CAVIFileSynth *parentPtr, bool isAudio) {
_RPT2(0,"%p->CAVIStreamSynth(%s)\n", this, isAudio ? "audio" : "video");
m_refs = 0; AddRef();

parent = parentPtr;
fAudio = isAudio;

parent->AddRef();
}


the memory leak is gone (see this screen capture (http://www.lillevold.com/files/png/memleak.png), where I encoded five .avs files ing a batch encode with 2-pass - the spike is before, the saw-toot after)

Since the corresponding parent->Release() happens in CAVIStreamSynth::~CAVIStreamSynth() which is called after all Streams are Released, it would seem someone is not calling the appropriate Release, which I also verified in the debugger. I don't yet know if this is producer or the DirectShow AVI reader. The producer code that interacts with Directshow to read AVI files, is somewhat complex (at least for me who does not know DirectShow too well).

Does anyone know of another app that uses DirectShow to read .avs files so I can test if this has the same behavior?

When AviSynth is used in a little AVI test app that simply opens, converts all frames to raw, and then closes the AVI, there is no problem, and I can also see the right Release() is called. And, the above work-around leads to a crash, since CAVIFileSynth is deleted prematurely.

(On a different topic, while working on this, I ran into a problem with mplayer2 and mplayerc in that .avs files do not show any video, and a dead process is left on exit ;; since this happens with the released Avisynth binary, both 2.0.7 and 2.5, so I won't worry about that for now).

sh0dan
13th March 2003, 10:21
Seems like a rather hard problem to solve. Unfortunately all open source video apps that open AVS-files are using VFW to open them, and not DirectShow. AviSynth itself is AFAIK the only OpenSource app. that even knows how to read images from DirectShow.

If Release() isn't being called I can see no way to know when to release the memory, if the dll isn't being unloaded. Is the filter graph completely recreated for each pass? Is the old one being destroyed?
But you probably much better know where to look.

Bidoche
13th March 2003, 16:34
@karl_lillevold

More likely it is simply that the parent->AddRef() is redundant with a call done before construction.
Generally it is done this way when you pass refcounted params, you pass them with an updated refcount.

karl_lillevold
14th March 2003, 00:16
I think the AddRef is needed because AVIStreams use the originating AVIFile, even this AVIFile's own refcount (not counting the refcount added by AVIStream) has gone to zero.

There may not be any open source apps, but at least I can use the binary graphedit.exe, which appears to be behaving nicely with .avs files. Memory use does not increase when repeatedly playing and stopping, and when deleting the graph, gRefCnt in AviSynth goes to zero (which it does not with producer). So this seems to indicate it is producer that has a problem with not releasing or shutting down its graph.

I could have spent a day to learn the producer code handling DirectShow graphs, but for now I will update the initial bug report with what I have found. Unless someone in the producer team picks it up soon, I may look into it some more.

P.S. In case you are wondering why producer is not using the AVI interface to read AVI files, which would probably have not had this memory leak... In order to be able to read uncompressed AVI files (RGB + most of the YUV formats) on Linux, it has its own AVI parser code, that unfortunately does not understand how to read .avs files.

sh0dan
14th March 2003, 18:21
In theory, passing the AVS files to the "uncompressed VFW reader" should be ok - I could imagine you caould gain a slight speedimprovement here (probably a few memory transfers would go away, and some filters would not be used).

A question: If ffdshow is enabled to accept "Raw Video" - is the video then being brought through ffdshow (and processed) - or does the Helix Producer always build the simplest possible graph - without risking any colorspace conversions or filtering?

karl_lillevold
14th March 2003, 19:12
Originally posted by sh0dan
In theory, passing the AVS files to the "uncompressed VFW reader" should be ok - I could imagine you caould gain a slight speedimprovement here (probably a few memory transfers would go away, and some filters would not be used).
I wish, but not when it does its own raw AVI file format parsing.
A question: If ffdshow is enabled to accept "Raw Video" - is the video then being brought through ffdshow (and processed) - or does the Helix Producer always build the simplest possible graph - without risking any colorspace conversions or filtering?
No, it is not brought through ffdshow. It works just like you suggest: try to avoid any color conversions or filtering, which is why AviSynth 2.5 with YV12, which is (almost) the native format of RV9, is very efficient. The native format is I420.

As it happens, we also found that using the simplest possible DS graph to read true uncompressed YUV files, is faster than producer's own AVI parsing code as well. DS is pretty good at avoiding unnecessary memcpy's This is why DS is the AVI reading method chosen first on Windows.

On the memory leak problem again: I did go over the DS reader code in producer quickly. Everything appears to be handled correctly, without including all the details: Create instance of a filter graph. graph->Render (which when traced in AviSynth causes gRefCnt to go to 15). ->Run, ->StopWhenReady. Ending with graph->Release (which when traced in AviSynth does 'not' release all the instances of streams, gRefCnt ends up at 3 I think).

summary, not incl the format selection setup:
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,
IID_IGraphBuilder, (LPVOID *)&m_pGraphBuilder);
m_pGraphBuilder->RenderFile( wPath, NULL );
run, stop;
m_pGraphBuilder->Release();
where I have checked that this Release returns 0;

Sirber
20th July 2004, 00:51
Big leaking with 2.5.5 :(

http://www.webernic.com/sites/sirber/Leak.png

sh0dan
20th July 2004, 09:42
Could you post the date displayed in version()?

Sirber
22nd July 2004, 01:12
AviSynth 2.55, buikd: Jun 17 2004 [17:51:49]
(c) 2000-2004 Ben Rudiak-Goulkd, et al.
http://www.avisynth.org

karl_lillevold
16th October 2004, 19:27
This bug is still alive and well, and presently making it virtually impossible to batch encode Avisynth scripts in RealProducer SDK. This is because the SDK does not shut down completely like the Producer cmd line in between each encode. Thus, several hundred MB is leaked for each file. We were starting to look into a work-around in Producer, but got side-tracked.

I was curious if anyone know of any other encoding tool that
1) uses DirectShow to read input files
2) supports Avisynth scripts as input
3) can do 2-pass or batch encode multiple files
?

I am asking because I would like to try to see if the memory leak behavior is the same there as in RealProducer...

Thanks!