View Full Version : Need help with AVISyth C API
LessThanJake
7th October 2008, 00:38
Hi,
need a little help with the AVS C API (http://kevin.atkinson.dhs.org/avisynth_c/api.html).
Here is a simple testcase:
#include <iostream>
#include <avisynth_c.h>
using namespace std;
void testcase(){
// Creates a pointer to an scriptenvironment object
AVS_ScriptEnvironment *scriptenv;
// function to create the scriptenvironment
// AVS_ScriptEnvironment * avs_create_script_environment(int version);
// here is already an compilererror
scriptenv = avs_create_script_environment(AVISYNTH_INTERFACE_VERSION);
// function to check if AVS-Function is available
// int avs_function_exists(AVS_ScriptEnvironment *, const char * name)
// in this case for example "mpeg2source()".
if (avs_function_exists(scriptenv, "mpeg2source"))
cout << "mpeg2source available";
cout << "mpeg2source not available";
}
int main() {
testcase();
return 0;
}
}
With this testcase I try to create an avs_scriptenvironment.
After that the existence of mpeg2source() should be checked but the compiler already throws an error when allocating the environment to the pointer.
-------------- Build: Debug in AVS_Interface ---------------
Compiling: main.cpp
Linking console executable: bin\Debug\AVS_Interface.exe
c:/mingw/bin/../lib/gcc/mingw32/4.2.4/../../../crt2.o:crt1.c:(.text+0x2f): undefined reference to `_SetUnhandledExceptionFilter@4'
c:/mingw/bin/../lib/gcc/mingw32/4.2.4/../../../crt2.o:crt1.c:(.text+0xc1): undefined reference to `_ExitProcess@4'
obj\Debug\main.o: In function `_Z8testcasev':
C:/dev/CodeBlocks/_Projects/AVS_Interface/main.cpp:14: undefined reference to `__imp__avs_create_script_environment@4'
C:/dev/CodeBlocks/_Projects/AVS_Interface/main.cpp:19: undefined reference to `__imp__avs_function_exists@8'
c:/mingw/bin/../lib/gcc/mingw32/4.2.4/libgcc.a(unwind-sjlj.o): In function `fc_key_init_once':
D:/crossdev/gcc/b4.2.4-tdm-1/gcc/../../gcc-4.2.4/gcc/gthr-win32.h:541: undefined reference to `_InterlockedIncrement@4'
D:/crossdev/gcc/b4.2.4-tdm-1/gcc/../../gcc-4.2.4/gcc/gthr-win32.h:554: undefined reference to `_Sleep@4'
c:/mingw/bin/../lib/gcc/mingw32/4.2.4/libgcc.a(unwind-sjlj.o): In function `fc_key_init':
...
I use Code::Blocks as IDE together with MinGW+gcc v4.2.4
Linklibrary: avisynth.dll
Search directory for compiler: "..\AviSynth 2.5\FilterSDK\include"
Search directory for linker: "c:\windows\system32"
AVISynth Version: 2.5.8.
OS: Win XP Prof.
Thanks.
LTJ
Fizick
7th October 2008, 07:20
Linklibrary: avisynth.dll
?
I use avisynth.lib
Leak
7th October 2008, 09:27
I use avisynth.lib
Right - DLLs are for runtime linking, LIBs are for compile time linking... :)
LessThanJake
7th October 2008, 09:58
Should this really be the stupid mistake which costed me 5 hours of time? :o
Will check this tonight after work.
Thank you so far.
greets
LTJ
LoRd_MuldeR
7th October 2008, 13:28
Sometimes the solution is so obvious that you can't see it :D
LessThanJake
7th October 2008, 19:11
Houston reporting: User is too stupid.
Everythingīs fine now.
Thank you. :o
greets
LTJ
LessThanJake
8th October 2008, 01:37
Hi,
Iīve got another problem.
short: Ich want to rebuild AVCSource("testfile.dga") and convert this into a clip to do something with it.
#include <iostream>
#include <avisynth_c.h>
using namespace std;
void showframe(){
// Creates a pointer to an scriptenvironment object
AVS_ScriptEnvironment *scriptenv;
// function to create the scriptenvironment
scriptenv = avs_create_script_environment(AVISYNTH_INTERFACE_VERSION);
// check if "avcsource()" is available
if (!avs_function_exists(scriptenv, "avcsource"))
{cout << "Canīt find dgavcdecode.dll" << endl;}
// Create "AVCSource("testfile.dga")
AVS_Value param0 = avs_new_value_string("testfile.dga");
AVS_Value params = avs_new_value_array(¶m0, 1);
AVS_Value AVCSource = avs_invoke(scriptenv, "avcsource", params, 0);
avs_release_value(AVCSource); // What does this? It doesnīt change anything wether itīs called or not
cout << avs_function_exists(scriptenv, "avcsource"); // --> 1 OK
cout << avs_is_string(param0); // --> 1 OK
cout << avs_is_array(params); // -->1 OK
cout << avs_is_clip(AVCSource); // --> 0 why?
cout << avs_is_error(AVCSource); // --> 1 why?
AVS_Clip *srcclip;
avs_set_to_clip(&AVCSource, srcclip); // compiles with 0 errors, but crash when File is executed
}
int main() {
showframe();
return 0;
}
Three Questions:
AVS_Value AVCSource is not type=clip, but throws an errorflag, why?
What does avs_release_value(AVCSource)? Nothing changes when this function is called.
Donīt understand the Programm Crash when executing file (after avs_set_to_clip), but I guess ist has something to do with the thrown error in avs_is_error(AVCSource);
(Want to show the frames in a GUI Panel-object or staticbitmap-object or something like that, similar to MeGUIsī Preview Window, but donīt how to do this, yet )
Thanks again, guys :)
greets
LTJ
LessThanJake
8th October 2008, 21:47
I found this example
http://forum.doom9.org/showthread.php?p=778825#post778825
and changed "Eval" --> "avcsource"
and string --> "testfile.dga"
everything compiled fine, but the result is the same as above.
AVS_Value res -> not a clip.
Testfile.264 / testfile.dga / (testfile.avs for testing with VD) / testfile.log are all in the same directory together with the compiled executable.
Same thing with directshowsource / avisource+AVI / mpeg2source+d2v.
I cannot "see" the mistake. :(
Would someone be so kind as to compile and verify this short sample code?
greets
LTJ
IanB
9th October 2008, 04:15
You are deleting the underlying PClip backing your AVCSource result.
Try this way ...void showframe(){
// Creates a pointer to an scriptenvironment object
AVS_ScriptEnvironment *scriptenv;
// function to create the scriptenvironment
scriptenv = avs_create_script_environment(AVISYNTH_INTERFACE_VERSION);
// check if "avcsource()" is available
if (!avs_function_exists(scriptenv, "avcsource"))
{
cout << "Canīt find dgavcdecode.dll" << endl;
return; // No point proceeding
}
// Create "AVCSource("testfile.dga")
AVS_Value param0 = avs_new_value_string("testfile.dga");
AVS_Value params = avs_new_value_array(¶m0, 1);
AVS_Value AVCSource = avs_invoke(scriptenv, "avcsource", params, 0); // Returns a PClip inside an AVS_Value
AVS_Clip *srcclip = avs_take_clip(AVCSource, scriptenv); // Recover the PClip for further use
avs_release_value(AVCSource); // Decrement use count of the underlying PClip smart pointer!
AVS_VideoFrame *frame = avs_get_frame(srclip, 0); // Retrieve frame 0
const BYTE data* = avs_get_read_ptr(frame); // Retrieve frame data bytes
...
avs_release_video_frame(frame); // Decrement use count of the underlying PVideoFrame smart pointer!
avs_release_clip(srcclip); // Decrement use count of the underlying PClip smart pointer!
avs_delete_script_environment(scriptenv); // Release the underlying IScriptEnvironment!
}
LessThanJake
9th October 2008, 20:10
Thank you.
Everything compiles fine, but thatīs not the thing. :)
AVS_Value AVCSource = avs_invoke(scriptenv, "avcsource", params, 0); // Returns a PClip inside an AVS_Value
AVCSource should hold a pclip inside, but it does not!
calling
avs_is_clip(AVCSource);
immediately after this line, it returns 0!
It holds the errorflag instead
so
AVS_Clip *srcclip = avs_take_clip(AVCSource, scriptenv);
cannot take the clip
This fact beats me. :confused:
geets
LTJ
Fizick
9th October 2008, 20:21
Are you sure, that default path to testfile.dga file is correct?
LessThanJake
9th October 2008, 20:39
What is meant with "default"-path?
All files are in the same directory.
http://img3.imagebanana.com/img/bw36a9ie/files.png
greets
LTJ
EDIT//
Iīve got it!
If I run the programm from inside Code::Blocks, using the "Run-Button" for testing, "avs_is_clip(AVCSource);" throws 0 and the programm crashes.
Running the compiled executabe directly from the commandline it works.
Very strange.
Might this be a bug in Code::Blocks and should be reported?
SledgeHammer_999
9th October 2008, 21:12
Maybe code::blocks doesn't set correctly the working dir?
LoRd_MuldeR
9th October 2008, 21:20
You better work with full paths, so your app doesn't depend on CurrentDirectory to work/fail...
LessThanJake
9th October 2008, 21:57
You better work with full paths, so your app doesn't depend on CurrentDirectory to work/fail...
Small things - big trouble.
Yes, thatīs the solution.
So, for everyone using code::blocks:
Go to
"Project" --> "Properties" --> "Build targets" and set "Execution working dir" to full path (both Debug/Release).
I guess this will not be my last question.
greets
LTJ
IanB
9th October 2008, 22:50
Of course this is the "C" api environment, there is no "throw/catch", so you must explicitly test to see if a script syntax error occured....
AVS_Value AVCSource = avs_invoke(scriptenv, "avcsource", params, 0); // Returns a PClip inside an AVS_Value
if (avs_is_error(AVCSource)) { // Did we get a script error
cout << avs_as_error(AVCSource); // Output the error mesage text
return;
}
...
Fizick
9th October 2008, 23:23
LessThanJake,
I scored 2 points :)
LessThanJake
10th October 2008, 12:49
Here is the next chance to raise your score.
Slowly but surely I understand the API, please stay patient with a newbie ;).
Two questions for now:
Now I set up the next line in the script
// Create lanczosresize(360, 270) to match size of the preview window
// Everything have to be done with the AVS_Value "fat pointer" struct
AVS_Value lr_param0 = avs_new_value_int(360); // set width
AVS_Value lr_param1 = avs_new_value_int(270); // set height
AVS_Value lr_param_array[2] = {lr_param0, lr_param1}; // create parameter array
AVS_Value lr = avs_new_value_array(lr_param_array, 2); // set up new var with the parameter array
AVS_Value lanczosresize = avs_invoke(scriptenv, "lanczosresize", lr, 0); // build function with parameters and set to new var
How can "lanczosresize" be applied to "srcclip" correctly?
I tried
avs_set_to_clip(&lanczosresize, srcclip);
const AVS_VideoInfo *vi = avs_get_video_info(srcclip);
cout << avs_row_size(vi); // returns 640 (=src) but not 360 as wished
What kind of data (jpeg, png, bmp, or something completely different) is
const BYTE *data = avs_get_read_ptr(frame); // Retrieve frame data bytes
?
I dont know how to treat this and how to form the actual picture.
greets
LTJ
Myrsloik
10th October 2008, 14:39
The first argument in your avs_value array should be the clip to operate on. So try something like:
AVS_Value lr_param0 = AVCSource; // set clip
AVS_Value lr_param1 = avs_new_value_int(360); // set width
AVS_Value lr_param2 = avs_new_value_int(270); // set height
LessThanJake
10th October 2008, 16:13
This works.
---------
I think I have to read something about colorspaces.
avs_is_yv12() returns 1 so probably the *data pointer shows to a buffer that contains yv12 data as well.
greets
LTJ
SledgeHammer_999
11th October 2008, 18:11
Just a noob question from me. Why do you use C api with C++?
IanB
12th October 2008, 05:26
Just a noob question from me. Why do you use C api with C++?Generally because you want to use a non M$ C++ compiler, i.e. GCC or Borland or ...
SledgeHammer_999
12th October 2008, 11:46
So you're saying that the normal C++ api of avisynth is bound to the MS compiler, aren't you?
LessThanJake
12th October 2008, 16:46
Yes.
I use GCC and cannot compile the code, when using the API from avisynth.h, so I have to use avisynth_c.h, but the functionality is the same as far as I can judge.
greets
LTJ
LoRd_MuldeR
12th October 2008, 17:19
So you're saying that the normal C++ api of avisynth is bound to the MS compiler, aren't you?Yes.
Why is that? Shouldn't C++ compliant code compile an all C++ compilers? :confused:
Guest
12th October 2008, 18:48
"The C++ language does not define a standard decoration scheme, so each compiler uses its own. Combined with the fact that C++ decoration can become fairly complex (storing information about classes, templates, namespaces, operator overloading, etc), this means that object code produced by different compilers is not usually linkable."
http://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B_Name_Mangling
http://www.kegel.com/mangle.html
LoRd_MuldeR
12th October 2008, 18:53
Well, linking Objectcode from different compilers is one thing. But why you can't use MinGW to compile all of the C++ code?
It sounds more like the Avisynth header files, which should be plain C++ code, work with MSVC but not with MinGW/GCC :confused:
(Mixing DLL's compiled/linked with different compilers/linkers does work for sure, like ffdshow does for example)
Leak
12th October 2008, 20:45
Well, linking Objectcode from different compilers is one thing. But why you can't use MinGW to compile all of the C++ code?
It sounds more like the Avisynth header files, which should be plain C++ code, work with MSVC but not with MinGW/GCC :confused:
Sure they'll work, but only when you compile both AviSynth and your plugin with either MSVC or GCC. And since AviSynth releases are usually MSVC based you'll have to stick with that, or use the AviSynth C API.
All symbol names in the LIBs/DLLs produced are different depending on the compiler, so you can't just mix and match them. Using C exports only works fine, though...
np: T.Raumschmiere - I Tank U (I Tank U)
LoRd_MuldeR
13th October 2008, 04:31
I see.
However ffdshow mixes MSVC/ICL-compiled DLL's (e.g. "ffdshow.ax") with MinGW/GCC-compiled DLL's (e.g. "libavcodec.dll") :confused:
Why can't it work with Avisynth in the same way? Use the MSVC-compiled "avisynth.dll" with my own MinGW/GCC-compiled C++ executable?
Is mixing binaries from different compilers only possible with C, but inherently impossible with C++ ???
squid_80
13th October 2008, 06:49
C++ classes have virtual function tables. When I was studying I was taught that the vftable would have the same order as the declarations, but apparently that's not always true. So when your gcc compiled plugin receives an *IScriptEnvironment and calls a virtual member function, it may end up calling a completely different function than the one that was intended.
Gavino
13th October 2008, 09:32
It's not just the vftable. Because of name overloading, each compiler has its own scheme for naming individual functions, etc. ('name mangling' - eg see neuron2's post above).
LoRd_MuldeR
13th October 2008, 15:24
Thanks for clarification. So it's less a problem with C++ itself, but more a problem with compiler developers to agree on a common naming scheme.
Well, if the C++ standard had clearly defined a naming scheme, there would be no problem, I guess ;)
squid_80
13th October 2008, 18:05
It's not just the vftable. Because of name overloading, each compiler has its own scheme for naming individual functions, etc. ('name mangling' - eg see neuron2's post above).When you build a plugin/program you typically don't link directly with avisynth at all. Name mangling doesn't matter squat. Last time I looked avisynth.dll doesn't even expose any name mangled functions (and if you link with the .lib you're asking for trouble).
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.