PDA

View Full Version : How to determine if "Distributor" call is necessary


Groucho2004
21st June 2011, 00:06
Here is the relevant code snippet:

try
{
AVSValue val;
PClip clip;
PVideoFrame frame;

IScriptEnvironment *env = CreateScriptEnvironment(AVISYNTH_INTERFACE_VERSION);
AVSValue Arg0 = AVSValue(argv[1]); //argv[1] is the script file name
AVSValue Args = AVSValue(&Arg0, 1);
VideoInfo vidinfo;

val = env->Invoke("Import", Args, 0);

clip = val.AsClip();
vidinfo = clip->GetVideoInfo();
int iFrames = (int)vidinfo.num_frames;

for (int iCurFrame = 0; iCurFrame < iFrames; iCurFrame++)
{
frame = clip->GetFrame(iCurFrame, env);

//read frames
//do something with frames
//etc
}

frame = 0;
clip = 0;
val = 0;
}
catch(AvisynthError err)
{
printf("\r%s\n", err);
return FALSE;
}


I'm trying to implement a safe way to determine if the "Distributor" call is necessary, i.e. if this call is already in the script I obviously don't want to invoke it.

I have looked at the implementation in the x264 source code but that uses the C API and it seems that I'm too dumb to port it to C++.

Can anyone help me?

Gavino
21st June 2011, 00:34
I'm trying to implement a safe way to determine if the "Distributor" call is necessary, i.e. if this call is already in the script I obviously don't want to invoke it.
I don't think there is any way of telling if it is already in the script other than parsing the script yourself.

I would adopt a different strategy - assume it is not present (and tell your users not to include it). Then check (after loading the script) for whether you need to add it by seeing whether GetMTMode exists and returns a positive value. (You would need to do this bit anyway - you don't want to call Distributor unless you are running on a multithreaded Avisynth and multithreading is on.)

I have looked at the implementation in the x264 source code but that uses the C API and it seems that I'm too dumb to port it to C++.
Can't you tell roughly what it is doing?
Post the code here if you're not sure.

Incidentally, you can pass a string directly to Invoke if it is the only argument. So instead of:
AVSValue Arg0 = AVSValue(argv[1]); //argv[1] is the script file name
AVSValue Args = AVSValue(&Arg0, 1);
val = env->Invoke("Import", Args, 0);
you can just write
val = env->Invoke("Import", argv[1]);

Groucho2004
21st June 2011, 00:50
Here is the code from x264:

if( !strcasecmp( filename_ext, "avs" ) )
{
res = h->func.avs_invoke( h->env, "Import", arg, NULL );
FAIL_IF_ERROR( avs_is_error( res ), "%s\n", avs_as_string( res ) )
/* check if the user is using a multi-threaded script and apply distributor if necessary.
adapted from avisynth's vfw interface */
AVS_Value mt_test = h->func.avs_invoke( h->env, "GetMTMode", avs_new_value_bool( 0 ), NULL );
int mt_mode = avs_is_int( mt_test ) ? avs_as_int( mt_test ) : 0;
h->func.avs_release_value( mt_test );
if( mt_mode > 0 && mt_mode < 5 )
{
AVS_Value temp = h->func.avs_invoke( h->env, "Distributor", res, NULL );
h->func.avs_release_value( res );
res = temp;
}
}


I understand what it does but maybe I have some blockage today to convert it to C++. :confused:

Gavino
21st June 2011, 01:19
It's basically doing what I suggested (without having seen it :)).
You can add it to your C++ code like this:
...
val = env->Invoke("Import", argv[1]);
try {
AVSValue mt_test = env->Invoke("GetMTMode", false);
const int mt_mode = mt_test.IsInt() ? mt_test.AsInt() : 0;
if (mt_mode > 0 && mt_mode < 5)
val = env->Invoke("Distributor", val);
}
catch(AvisynthError err) { // not multi-threaded Avisynth - do nothing
}
clip = val.AsClip();
vidinfo = clip->GetVideoInfo();
...

Groucho2004
21st June 2011, 01:33
Works, thanks a mil Gavino.
:thanks:

Edit: Hm, it crashes with a non-MT version of Avisynth (2.6 Alpha 3). Once I get past the "Invoke" line I get "Unhandled exception...". Odd.

Edit2: Found it. I have to use
catch(IScriptEnvironment::NotFound) { // not multi-threaded Avisynth - do nothing
}
in order to catch that exception.

Gavino
21st June 2011, 10:05
I have to use
catch(IScriptEnvironment::NotFound) { // not multi-threaded Avisynth - do nothing
}
in order to catch that exception.
Ah, yes, sorry, my mistake.
Glad you got it sorted.