Log in

View Full Version : Multiple concurrent avisynth threads causes access violation


bwkahle
9th August 2011, 22:49
I'm running 2 STA threads each with its own instance of a WMV VC-1 encoder. The encoders are using an Avisynth script as the input file and opened using the AVIFile functions.

The encoders will run in tandem just fine for some variable period of time before causing an access violation. I've traced the problem to avisynth trying to use the same VideoFrame object for both threads

Below are the truncated stack traces for both threads.


avisynth.dll!FilteredResizeH::GetFrame(int n=428, IScriptEnvironment * env=0x0860a7d0) Line 1108 C++
> avisynth.dll!Cache::childGetFrame(int n=428, IScriptEnvironment * env=0x0860a7d0) Line 236 + 0x33 bytes C++
avisynth.dll!Cache::GetFrame(int n=428, IScriptEnvironment * env=0x0860a7d0) Line 399 + 0x15 bytes C++
avisynth.dll!ConvertToYV12::GetFrame(int n=428, IScriptEnvironment * env=0x0860a7d0) Line 233 + 0x33 bytes C++
avisynth.dll!Cache::childGetFrame(int n=428, IScriptEnvironment * env=0x0860a7d0) Line 236 + 0x33 bytes C++
avisynth.dll!Cache::GetFrame(int n=428, IScriptEnvironment * env=0x0860a7d0) Line 399 + 0x15 bytes C++
avisynth.dll!CAVIStreamSynth::ReadFrame(void * lpBuffer=0x0f840020, int n=428) Line 995 + 0x3c bytes C++
avisynth.dll!CAVIStreamSynth::ReadHelper(void * lpBuffer=0x0f840020, int lStart=428, int lSamples=-1, unsigned int * code=0x078dece0) Line 1063 C++
avisynth.dll!CAVIStreamSynth::Read2(long lStart=428, long lSamples=-1, void * lpBuffer=0x0f840020, long cbBuffer=613440, long * plBytes=0x078defe0, long * plSamples=0x00000000) Line 1289 C++
avisynth.dll!CAVIStreamSynth::Read(long lStart=428, long lSamples=-1, void * lpBuffer=0x0f840020, long cbBuffer=613440, long * plBytes=0x078defe0, long * plSamples=0x00000000) Line 1180 + 0x20 bytes C++
avifil32.dll!_AVIStreamRead@28() + 0x20 bytes




avisynth.dll!FilteredResizeH::GetFrame(int n=110, IScriptEnvironment * env=0x085e41f8) Line 1108 C++
avisynth.dll!Cache::childGetFrame(int n=110, IScriptEnvironment * env=0x085e41f8) Line 236 + 0x33 bytes C++
avisynth.dll!Cache::GetFrame(int n=110, IScriptEnvironment * env=0x085e41f8) Line 399 + 0x15 bytes C++
avisynth.dll!ConvertToYV12::GetFrame(int n=110, IScriptEnvironment * env=0x085e41f8) Line 233 + 0x33 bytes C++
avisynth.dll!Cache::childGetFrame(int n=110, IScriptEnvironment * env=0x085e41f8) Line 236 + 0x33 bytes C++
avisynth.dll!Cache::GetFrame(int n=110, IScriptEnvironment * env=0x085e41f8) Line 399 + 0x15 bytes C++
avisynth.dll!CAVIStreamSynth::ReadFrame(void * lpBuffer=0x0c4c0020, int n=110) Line 995 + 0x3c bytes C++
avisynth.dll!CAVIStreamSynth::ReadHelper(void * lpBuffer=0x0c4c0020, int lStart=110, int lSamples=-1, unsigned int * code=0x076fe720) Line 1063 C++
avisynth.dll!CAVIStreamSynth::Read2(long lStart=110, long lSamples=-1, void * lpBuffer=0x0c4c0020, long cbBuffer=613440, long * plBytes=0x076fea20, long * plSamples=0x00000000) Line 1289 C++
avisynth.dll!CAVIStreamSynth::Read(long lStart=110, long lSamples=-1, void * lpBuffer=0x0c4c0020, long cbBuffer=613440, long * plBytes=0x076fea20, long * plSamples=0x00000000) Line 1180 + 0x20 bytes C++
avifil32.dll!_AVIStreamRead@28() + 0x20 bytes


Inside FilteredResizeH::GetFrame dst->GetWritePtr() is returning a null pointer because VideoFrame::refcount == 2

Both threads are referencing the same VideoFrame object at 0x085e40cc. This object is returned from IScriptEnvironment::NewVideoFrame on the 2nd line of FilteredResizeH::GetFrame.

How is it possible both threads get the same VideoFrame object back from NewVideoFrame()? Is this a bug or intended behavior?

I have a full debug environment setup if more information is needed.

bwkahle
12th August 2011, 15:32
This is pretty important for us to get working. My company would be willing to setup a consulting deal with whoever can help us get this fixed.

IanB
12th August 2011, 23:28
The standard Avisynth releases are not at all thread safe. The most recent alpha 3 now has a fair amount of thread safety code included but the effort is not complete.

There are experimental 3rd party MT builds which may help. See the wiki Main Page (http://avisynth.org/mediawiki/Main_Page) for detail.

TheFluff
13th August 2011, 02:58
How can thread safety issues affect two completely different processes? At least that's what I assume the OP is using, but I don't know what "STA" refers to in this context.

I've done something similar myself many times, running multiple Avisynth instances in different encoder processes and never had any problems.

SEt
13th August 2011, 21:01
Try using my newest build of Avisynth 2.6 (not 2.5) in MTMode and rebuild any filters you need that have sources and you see in their avisynth.h expressions like refcount++ with avisynth.h you can find in thread about Avisynth 2.5 MT with expressions like InterlockedIncrement().

bwkahle
30th August 2011, 00:12
How can thread safety issues affect two completely different processes? At least that's what I assume the OP is using, but I don't know what "STA" refers to in this context.

I've done something similar myself many times, running multiple Avisynth instances in different encoder processes and never had any problems.

They are not separate processes. STA refers to Single Thread Apartment. I've found that accessing Avisynth from MTA threads causes issues.

I will probably go the separate process route since it seems like this could be a doozy of an issue.

PhrostByte
30th August 2011, 20:21
They are not separate processes. STA refers to Single Thread Apartment. I've found that accessing Avisynth from MTA threads causes issues.

I will probably go the separate process route since it seems like this could be a doozy of an issue.

As far as I know Avisynth does not use any COM, so STA/MTA should not affect it.

bwkahle
30th August 2011, 20:32
As far as I know Avisynth does not use any COM, so STA/MTA should not affect it.

I'm using DirectShowSource in my scripts, and DirectShow uses COM. Thats why it affects me.

Gavino
30th August 2011, 21:48
As far as I know Avisynth does not use any COM, so STA/MTA should not affect it.
One of the first things Avisynth does on startup (in the ScriptEnvironment constructor) is call CoInitialize(NULL).

patrick_
1st September 2011, 16:53
bwkahle, don't use multiple threads. Consider using child processes.