-
Notifications
You must be signed in to change notification settings - Fork 14
videofilt_scriptingsupport
VirtualDub Plugin SDK 1.2
Scripting support
Video filters can expose a Config()
method that allows scripts to
control filter configuration values, without requiring user
intervention. This is also required for your filter to work in batch
mode (job control). It is highly recommended that any filter offering
configurable parameters implement scripting/batch support.
To expose the script method, the script_obj
field of the filter
definition must be filled. This points to a script object definition,
which describes the Config()
method group exposed by the filter.
Typically this just points to a function list:
VDXScriptObject script_obj = { NULL, script_functions, NULL };
The function list, in turn, describes all of the methods exposed in terms of a C/C++ handler function, name, and argument list:
VDXScriptFunctionDef script_functions[] = {
{ (VDXScriptFunctionPtr)configScriptFunc, "Config", "0i" },
{ NULL, NULL, NULL },
};
Normally, the function list only consists of one function entry and the
NULL sentinel. The third argument describes the argument list to the
script function, and consists of the first character, which describes
the return type, and subsequent characters, which correspond to
arguments. The return value should always be a zero (0
) for void
,
while the argument characters can be i
for integer or s
for string.
V11+ only: Function parameters can also be of type 64-bit long (l
)
or double (d
).
The function callback is called with a pointer to the script interpreter, filter activation context, arguments, and argument count:
static void configScriptFunc(IVDXScriptInterpreter *isi, void *lpVoid, VDXScriptValue *argv, int argc) {
VDXFilterActivation *fa = (VDXFilterActivation *)lpVoid;
MyData *mfd = (MyData *)fa->filter_data;
mfd->width = argv[0].asDouble();
mfd->height = atoi(*argv[1].asString());
if (argc >= 3 && argv[2].isInt())
mfd->mode = argv[2].asInt();
}
Note: Due to the cast when initializing the VDXScriptFunctionDef
structure, it is possible to accidentally supply the wrong function
prototype when declaring the function. Make sure that the prototype is
correct, including the calling convention (__cdecl
). The return value
will vary depending on the return type specified in the function
signature -- it should be void
for a 0
.
Once the script method has been declared, an additional fssProc
function must be supplied to emit the Config()
script call describing
the current configuration. This generally simply calls a printf()
style function to generate the script line:
bool fssProc(VDXFilterActivation *fa, const VDXFilterFunctions *ff, char *buf, int bufsize) {
MyData *mfd = (MyData *)fa->filter_data;
if ((unsigned)_snprintf(buf, buflen, "Config(%g, \"%d\", %d)"
, mfd->width
, mfd->height
, mfd->mode) >= (unsigned)(bufsize - 1))
return false;
return true;
}
Note: Bounded versions of sprintf(), such as the VC++-specific
_snprintf()
call above, should be used to avoid a buffer overflow in
case the script string is too large to fit.
The script interpreter checks argument types against the method
prototypes specified in the function list, so it is not normally
required for the handler function to check types manually. If the
handler function does detect an error, it can raise the error by using
the EXT_SCRIPT_ERROR()
macro, which in turns calls the
IVDXScriptInterpreter::ScriptError()
method. This method throws a C++
exception and thus does not return.
In general, however, it is better to store the invalid parameters and
flag the error on the startProc
method. This allows for more friendly
reporting and consolidates error handling logic in the filter.
Once a filter has been released, it may be necessary to update the
filter's script interface in a way that is backwards compatible. This is
done by overloading the Config()
method with multiple argument lists:
VDXScriptFunctionDef script_functions[] = {
{ (VDXScriptFunctionPtr)configScriptFunc, "Config", "0i" },
{ (VDXScriptFunctionPtr)configScriptFunc, NULL, "0iis" },
{ NULL, NULL, NULL },
};
The Config
name should only be specified for the first entry, with
subsequent entries using NULL
for the name. The handler function can
be the same or different for each entry; if it is the same, the function
must determine which prototype was used by checking the argument count
and parameter types.
Once overloads have been declared, the script engine chooses the best match based on the arguments provided and the argument lists of each overload. If multiple methods match and no match is clearly better than the rest, an ambiguity error is raised and script execution fails.
Tip: Avoid declaring overloads that differ only in argument types of
int
, double
, or long
. This can produce unexpected ambiguities when
the config string is emitted with numbers that are valid int
values,
such as zero. It is safest to extend the method list by adding
parameters or by swapping numbers and strings.
Copyright (C) 2007-2012 Avery Lee.
Setting up your development environment
Conventions
Plugin initialization
Dynamic loading
Reference counting
Using CPU extensions
Introduction
What's new
Breaking changes
Gotchas
Deprecated features
Migrating from the old Filter SDK
Programming model
Handling bitmaps
Creating a video filter
Setting filter parameters
Processing video frames
Managing filter data
Creating time-varying filters
Handling aspect ratio
Prefetching multiple source frames
Handling multiple sources
Making a filter configurable
Scripting support
CPU dependent optimization
VDXA index omitted
Getting started
Writing the module entry point
Creating a video filter
Adding configurability
Adding script support
Introduction
What's new
Autodetect
Direct mode
Video frames vs. samples
Video decodint model
Video decoder