Log in

View Full Version : ScriptClip (once again...)


WarpEnterprises
23rd March 2004, 22:21
I still don't understand fully how AviSynth works internally between script parsing and delivering frames. This gets very pronounces when using (or programming) conditional filters (functions that modify variables at runtime and/or call a script in the GetFrame).
So I asked sh0dan a question...and he gave some explanation - which is well suited for the public too BUT was not fully covered IMO.

Q
Why exactly do you temp. save "last" in ScriptClip?
I noticed I have to make the same code in my Write, else there is a heap overflow due to recursive calls, but only when using implicit last. What is different between "last" and an explicit variable?

A
To avoid strangeness. If a filter should request frames when they are constructed, a conditional filter could mess up the implicit last.

--> well, this I understand, I think.


Q
I now found the way to put the codec name and the frametype in AviSource.
As we have no per-frame properties I simply use SetVar in AviSource::GetFrame to return a string "current_frametype" I create there.
So far it works ok, if I use e.g.

AviSource("droppedframes.avi")
ScriptClip(""" subtitle(current_frametype) """)

BUT when I use:

AviSource("droppedframes.avi")
ScriptClip(""" subtitle(" " + current_frametype) """)

the display lags one frame behind. Why that? Why does Subtitle alone work, but if I use ANY function it lags?

A
ok - When the filter runs, this happends:

- ScriptClip gets asked to deliver a frame.
- ScriptClip Evaluates the subtitle string.
- A PClip is returned with the newly created subtitle filter.
*
- Subtitle is asked to deliver a frame.
- AviSource delivers a frame to Subtitle.
- Subtitle returns the frame to ScriptClip after processing.

* This is where the funny stuff happends. Since the subtitle is created before AviSource is called, the variable will not have been updated yet.

It could be changed, by also requesting a frame before evaluating, but it will make inconsistencies, since the filter above will be called twice (give and take a cache hit). But in principle it could make it work.

--> OK, this explains the general "lag" - but why is there no lag when I use a pure Subtitle (inside ScriptClip of course) WITHOUT an extra function?

Manao
23rd March 2004, 22:44
Because current_frame is defined inside scriptclip ( third line of ScriptClip::GetFrame() ) and hence is defined before the creation of the Subtitle filter.

WarpEnterprises
23rd March 2004, 22:47
stop, once again:
- current_frametype is created in MY AviSource-hack
- the behaviour gets different by using a simple

" " +

Manao
23rd March 2004, 22:56
Ooops, my bad, I misunderstood your question.

Manao
23rd March 2004, 23:34
I made the same test you did, with one of my filter which I modified to make it create a variable current_frametype. I can't reproduce the behavior you're encountering. For me, there is always the one frame lag.

Is there a chance you would have mistyped current_frametype by current_frame ?

sh0dan
24th March 2004, 10:02
(I realize the context of this post is somewhat hard to get).

The conclusion is: It is possible to add an "after_frame=true/false". It will however result in two GetFrame calls, and the result of the first will be discarded.

The reason ConditionalReader and XstatImport (Xvid stat importer) works is because they are to be placed _after_ the scriptclip filter.

WarpEnterprises
24th March 2004, 11:35
:confused: you soon make me give up...

1) I made an AviSource which sets in its GetFrame a variable "current_frametype" (which is filled with e.g. "D 34" meaning DroppedFrame, frame 34.

2) When I then use

ScriptClip(""" subtitle(current_frametype) """)

there is NO lag. On frame 34 there is the string "D 34" printed - there is no lag, Subtitle gets called AFTER AviSource has set the variable.

3) BUT when I use a function as here the string addition

ScriptClip(""" subtitle(" " + current_frametype) """)

or ANY OTHER scriptfunction inside the Subtitle command, there is the lag you described and explained.


Of course I can upload my DLL/source somewhere to test, but it's a mere
env->SetVar(...) in the AviSource::GetFrame

Manao
24th March 2004, 12:05
I understood you : What I said last was that I made a modification in one of my filter to do a env->SetVar(...) inside its GetFrame function. I used the following scripts : source = mpeg2source("foo.d2v")
return source.thefilter().ScriptClip("""Subtitle(current_frametype)""")

and

source = mpeg2source("foo.d2v")
return source.thefilter().ScriptClip("""Subtitle( " " + current_frametype)""")And I always got the one frame lag, with both the previous scripts.

Can you make your dll available ( and the modification of the avisource.cpp ), so I can test ( I can't compile right now avisynth, I'll be able soon )

WarpEnterprises
29th March 2004, 21:31
OK, no need to post code, I solved the riddle.

When using env->SetVar("myvar", buf) AviSynth passes ONLY THE POINTER OF BUF !! (and does not copy the string to some internal location - yes, I'm coming from VB-land).

So when there is no other function, a change in buf is directly passed through no matter where or when the variable is used in the script, even Subtitle does not use additional buffers, so it punches through down to the final video.

If there is a function in between (no matter which) this function generates a new buffer for its result, which is then evaluated with exactly the lag as you described.

Nevertheless this is an important "discovery":
it implies that you use only vars with a scope high enough (define it public in the filter class) for use with SetVar.
E.g. defining a buf in GetFrame will cause no compiler error but produce garbage or crashes because buf may be not available the whole time!

Have I gotten all correct?

Bidoche
31st March 2004, 23:06
When using env->SetVar("myvar", buf) AviSynth passes ONLY THE POINTER OF BUF !! (and does not copy the string to some internal locationSince avisynth (2.X) is using char *, that's where the SaveString env method should come into play.