View Full Version : How do I open a script with the AviSynth C API, and is this a typo?
nonoitall
10th November 2007, 06:52
Two questions, the first one (and perhaps the second as well) a bit noobish. :D Neither the documentation nor the comments made it obvious to me how one would go about opening a script with the functions in avisynth_c.h and reading frames from it. Soooo... say I had a script at the path, C:\script.avs - how would one turn that script into an AVS_Clip?
My second question: I was looking through the inline functions in avisynth_c.h and I was confused by this one (the part in bold):
AVSC_INLINE int avs_is_parity_known(const AVS_VideoInfo * p)
{ return ((p->image_type & AVS_IT_FIELDBASED)&&(p->image_type & (AVS_IT_BFF||AVS_IT_TFF))); }Is there really supposed to be an || operator there, or is it a typo and is it supposed to be the | operator? Because it seems to me that if it's not a typo the operation would be pointless - those are constants and as long as one or both is non-zero, the operation will return non-zero (and they're both non-zero).
Anyway, answer one, both or none of my questions if you please. :)
Fizick
10th November 2007, 09:25
the second is bug. compare with avisynth.h.
avisynth_c is not maintained by author.
IanB
10th November 2007, 09:27
Yes the || is supposed to be an |, it was fixed recently in CVS.
Quickly, to parse a script you need to
1. AVS_ScriptEnvironment *env = avs_create_script_environment(2);
2. AVS_Value Args=avs_new_value_string("C:\script.avs");
3. AVS_Value val=avs_invoke(env, "Import", Args, 0);
4. AVS_Clip *clip=avs_take_clip(val, env);
5. AVS_VideoFrame *frame=avs_get_frame(clip, n);
6a. const BYTE *data=avs_get_read_ptr(frame);
6b. int rowsize=avs_get_row_size(frame);
6c. int pitch=avs_get_pitch(frame);
6d. int height=avs_get_height(frame);
7. do something with data
8. avs_release_frame(frame);
9. avs_release_clip(clip);
10. avs_delete_script_environment(env);
Fizick
10th November 2007, 09:45
So, the bug is fixed in Avisynth 2.5.8 alpha distribution package
nonoitall
11th November 2007, 00:01
Okay, great! Thanks guys!
bigboss97
30th July 2008, 05:21
I want to write a C++ program (using SDL http://www.libsdl.org/) which displays the output (result) of avisynth and I found this (see below).
Does that mean I can do my stuff in step 7?
Do I have to read the pixels and paint them in my SDL surface one by one?
Is there a better way?
Anyone has experience in that?
Also, how to read the pixels in Avisynth API?
thanks in advance
Phuoc Can HUA
Yes the || is supposed to be an |, it was fixed recently in CVS.
Quickly, to parse a script you need to
1. AVS_ScriptEnvironment *env = avs_create_script_environment(2);
2. AVS_Value Args=avs_new_value_string("C:\script.avs");
3. AVS_Value val=avs_invoke(env, "Import", Args, 0);
4. AVS_Clip *clip=avs_take_clip(val, env);
5. AVS_VideoFrame *frame=avs_get_frame(clip, n);
6a. const BYTE *data=avs_get_read_ptr(frame);
6b. int rowsize=avs_get_row_size(frame);
6c. int pitch=avs_get_pitch(frame);
6d. int height=avs_get_height(frame);
7. do something with data
8. avs_release_frame(frame);
9. avs_release_clip(clip);
10. avs_delete_script_environment(env);
IanB
31st July 2008, 00:04
@bigboss97,6a. const BYTE *data=avs_get_read_ptr(frame);
6b. int rowsize=avs_get_row_size(frame);
6c. int pitch=avs_get_pitch(frame);
6d. int height=avs_get_height(frame);
7. do something with data[]Data is a byte array of the raw pixel data. It has dimensions of pitch * height, of which the first rowsize bytes of each row of pitch bytes is active picture the remainder is alignment filler trash.
We export the internal routine BitBlt which is a fast rectangular memory to memory copy. You give it source and destination pointers with rowsize and height along with source pitch and destination pitch. By making the source pitch value negative and adjusting the source pointer you can invert the image during the copy.
For programming techniques look at the sample code and FilterSDK documentation optionally installed (under Select Extra Files) on your hard disk.
bigboss97
10th August 2008, 13:46
http://avisynth.org/mediawiki/Filter_SDK/SDK_necessaries
In my case, I'm not writing a filter which will be used by AviSynth.
Do I still have to use the compiler as the guide suggested?
Besides that, I can just follow the instruction as writing a filter, right?
For programming techniques look at the sample code and FilterSDK documentation optionally installed (under Select Extra Files) on your hard disk.
IanB
11th August 2008, 01:16
If you want an easy ride ;) use the environment as suggested in the guide.
If you want to use the GNU C/C++ compilers you will need to use the AviSynth C API.
The in memory data ordering for C++ differs for the M$ compilers. Maybe with sufficient whips, chains and boiling oil you might convince a GCC environment to successfully use the C++ API, but to date nobody has bothered.
bigboss97
11th August 2008, 04:43
I'm a Borland user and will try my luck with:
http://kevin.atkinson.dhs.org/avisynth_c/api.html
They look quite old. Is there a more recent solution?
thanks
Phuoc Can HUA
If you want an easy ride ;) use the environment as suggested in the guide.
If you want to use the GNU C/C++ compilers you will need to use the AviSynth C API.
IanB
11th August 2008, 09:41
Kevin Atkinson's Avisynth_c API has been included in the main Avisynth.dll
His document is still close to current, with the following exceptions :-
* The internal implementation uses the StdCall calling convention.
* Use Load_Stdcall_Plugin() to load any plugins you write, no extra Avisynth_C.dll is required.
* Link with Avisynth.lib
* Copies of the current files will be on your hard disk in your Avisynth directory if you selected them during the install, FilterSDK\include\avisynth_c.h, Extras\avisynth.lib and Extras\avisynth.exp
bigboss97
22nd August 2008, 15:36
Not much luck :-(
I didn't manage to link the avisynth_c.lib. So I recompile avisynth_c. When I ran my test program it crashed in p->env->Invoke:
extern "C"
AVS_Value AVSC_CC avs_invoke(AVS_ScriptEnvironment * p, const char * name, AVS_Value args, const char * * arg_names)
{
AVS_Value v = {0,0};
p->error = 0;
try {
AVSValue v0 = p->env->Invoke(name, *(AVSValue *)&args, arg_names);
Looks like it's not pointing to anywhere. My debugger says:
p->env->Invoke = E2027 Must take address of a memory location
Anyone can help?
I'm a Borland user and will try my luck with:
http://kevin.atkinson.dhs.org/avisynth_c/api.html
Gavino
22nd August 2008, 16:42
What does your program do before this point?
Have you followed the steps outlined by IanB in post#3?
IanB
22nd August 2008, 17:33
Link with Avisynth.libDo not use any of Kevins old files apart from the documentation.
Did you call avs_create_script_environment(2) to initialise p? You cannot use C++ constructs unless you have M$ compatible linkage. This is why the C interface exists.
So I recompile avisynth_c.If you can compile this and get it working, then you will be using the C++ interface, so you will not need to use the C interface. But I somehow doubt this. You almost certainly need to compile this with the M$ compiler to get the linkage to the main avisynth.dll correct.
bigboss97
24th August 2008, 01:56
I think, now I understand. If I use C++ I don't need avisynth_c, right? In the source codes, no wonder I saw avisynth_c is doing almost the same thing as avisynth.
Okay, I'll try to compile my program with avisynth (C++).
Sorry about my silly confusion :) and thank you for the quick response.
This is why the C interface exists.
Myrsloik
24th August 2008, 09:41
No. If you use microsoft's c++ compilers you don't need to use avisynth_c. All other compilers (including the c++ ones) have to use avisynth_c.
bigboss97
6th September 2008, 15:28
My existing program is compiled with Borland C++. If I swap to M$ I've to do a lot of changes in my program :-(
I'm reading something about AviSynth30. Will I be able to get away without M$ compiler?
You almost certainly need to compile this with the M$ compiler to get the linkage to the main avisynth.dll correct.
TheFluff
6th September 2008, 17:06
Will I be able to get away without M$ compiler?
Yes, but you will only be able to compile vaporware for a few months until you give up and either use avisynth_c or a MS compiler.
bigboss97
23rd November 2008, 13:17
Now I've got my codes compiled in VC++ 2005 Express. But I'm using avisynth_c. My understanding, avisynth_c is sitting on top of avisynth. When I tried to use avisynth.h and changed my codes accordingly. Somehow I couldn't get it compiled and it was just a mess.
Can anyone help me to convert following codes in using avisynth.h? or should I keep it although I'm using MS compiler?
#include "stdafx.h"
#include "windows.h"
#include "avisynth_c.h"
int main(int argc, char* argv[])
{
AVS_ScriptEnvironment *Env = avs_create_script_environment( AVISYNTH_INTERFACE_VERSION);
AVS_Value Arg0= avs_new_value_string( argv[1]);
AVS_Value Args = avs_new_value_array(&Arg0, 1);
AVS_Value Val= avs_invoke( Env, "Import", Args, 0);
AVS_Clip *Clip= avs_take_clip( Val, Env);
AVS_VideoFrame *Frame= avs_get_frame( Clip, 1);
const BYTE *Data= avs_get_read_ptr( Frame);
int RowSize= avs_get_row_size( Frame);
int Pitch= avs_get_pitch( Frame);
int Height= avs_get_height( Frame);
...
No. If you use microsoft's c++ compilers you don't need to use avisynth_c. All other compilers (including the c++ ones) have to use avisynth_c.
Gavino
23rd November 2008, 17:14
Can anyone help me to convert following codes in using avisynth.h? or should I keep it although I'm using MS compiler?
If it works (which I think it should), there's no need to change and you can continue using the C interface. However, if you know C++ (or are prepared to learn), you will find the standard API much more programmer-friendly to use.
The SDK documentation and sample code shows how to write it - start there. If you have specific problems, ask again and we will help you out.
bigboss97
24th November 2008, 13:15
This is my converted code. It seems to be working as expected. Only the delete Frame & Clip causing exceptions. How should they be released?
Are there more things I have to release?
IScriptEnvironment *Env = CreateScriptEnvironment( AVISYNTH_INTERFACE_VERSION);
AVSValue Arg0= AVSValue( argv[1]);
AVSValue Args= AVSValue(&Arg0, 1);
AVSValue Val= Env->Invoke( "Import", Args, 0);
PClip Clip= Val.AsClip();
PVideoFrame Frame= Clip->GetFrame( 1, Env);
int RowSize= Frame->GetRowSize();
int Pitch= Frame->GetPitch();
int Height= Frame->GetHeight();
const unsigned char* BmpLine= Frame->GetReadPtr();
for( int Y= 0; Y < Height; Y++)
{
for( int X= 0; X < RowSize; X+=3)
{ printf("%02x", *(BmpLine +X));
}
printf("\n");
BmpLine+= Pitch;
}
delete Frame;
delete Clip;
delete Env;
If you have specific problems, ask again and we will help you out.
Gavino
24th November 2008, 14:29
This is my converted code. It seems to be working as expected. Only the delete Frame & Clip causing exceptions. How should they be released?
You should do:
Frame = 0;
Clip = 0;
The 'smart pointer' code behind the scenes will do the rest.
You should also put the Invoke inside a try/catch in case the file does not exist or contains errors. Also check the return Val actually is a clip.
Fizick
24th November 2008, 17:34
you may do not release smart pointer. it will be auto-released at program finish.
bigboss97
24th November 2008, 23:12
I'm a horrible quick & dirty coder :-)
My programs always start as a minimal test program and it gets bigger and bigger, at the end out of control hahaha...
Thank you for the very important advice.
You should also put the Invoke inside a try/catch in case the file does not exist or contains errors. Also check the return Val actually is a clip.
bigboss97
27th November 2008, 06:26
Now I've extended my program to show the entire video frame-by-frame. I'm trying the transition plugin:
# Source: http://forum.videohelp.com/topic339076.html
LoadPlugin("TransAll.dll")
A= ImageSource("img01.jpg").trim(1,75)
B= ImageSource("img02.jpg").trim(1,75)
#Transitions
AB00=TransAccord(A,B, 50,"hor")
Vid= AB00
#Vid= A+B
# Change the framerate
#newvid=vid.ChangeFPS(30000.0/1001.0).Spline36Resize(320,240)
NewVid= Vid.ChangeFPS( 25)
NewVid
My program crashes at the end on delete Env;
But if I use Vid= A+B (no transition) then it's fine.
Is that an issue with the plugin or I'm not supposed to call delete Env?
Phuoc
You should do:
Frame = 0;
Clip = 0;
The 'smart pointer' code behind the scenes will do the rest.
Gavino
27th November 2008, 20:09
My program crashes at the end on delete Env;
But if I use Vid= A+B (no transition) then it's fine.
Is that an issue with the plugin or I'm not supposed to call delete Env?
It's generally not a good idea to use 'delete' on something you haven't got yourself from 'new', unless you are told explicitly that it is OK.
I think you can get away with doing nothing here as I think the exit hooks within Avisynth will clear up when the DLL is unloaded. (IanB, is this right?)
BTW To add to my earlier point on error checking, it may also be worth checking that the clip has video (it might be audio only). And remember frames are numbered from zero.
IanB
28th November 2008, 01:41
@bigboss97,
Crashes when deleting Env are usually caused when you have smart pointer object still in scope that need IScriptEnvironment resources during their exit code execution.
Post your full, unabridged source code if you need specific help.
I think you can get away with doing nothing here as I think the exit hooks within Avisynth will clear up when the DLL is unloaded. (IanB, is this right?)No!
bigboss97
28th November 2008, 12:42
Thanks for that. I wasn't sure.
Here is the complete code with crash:
// avitest_ms.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include "avisynth.h"
#include "SDL.h"
//int _tmain(int argc, _TCHAR* argv[])
int main(int argc, char* argv[])
{
IScriptEnvironment *Env = CreateScriptEnvironment( AVISYNTH_INTERFACE_VERSION);
AVSValue Arg0= AVSValue( argv[1]);
//AVSValue Arg0= AVSValue("C:\\work\\cpp\\avitest_ms\\script.avs");
AVSValue Args= AVSValue(&Arg0, 1);
AVSValue Val;
PClip Clip;
PVideoFrame Frame;
VideoInfo VidInfo;
int RowSize, Pitch, Height;
const unsigned char* BmpLine;
try
{ Val= Env->Invoke("Import", Args, 0);
Clip= Val.AsClip();
VidInfo= Clip->GetVideoInfo();
Frame= Clip->GetFrame( 1, Env);
}
catch( AvisynthError err)
{ printf("%s\n", err);
return 1;
}
SDL_Init (SDL_INIT_VIDEO);
SDL_Surface *Screen= SDL_SetVideoMode (640, 480, 24, SDL_HWSURFACE|SDL_DOUBLEBUF);
RowSize= Frame->GetRowSize();
Pitch= Frame->GetPitch();
Height= Frame->GetHeight();
SDL_Event Evt;
for( int I= 0; I < VidInfo.num_frames; I++)
{
if( SDL_PollEvent(&Evt) > 0 )
if ( Evt.type == SDL_KEYDOWN )
break;
Uint8 *CurPix;
BmpLine= Frame->GetReadPtr();
for( int Y= Height-1; Y >= 0; Y--)
{ CurPix= (Uint8*)Screen->pixels +Y *Screen->pitch;
memcpy((void*)CurPix,(const void*)BmpLine, RowSize);
BmpLine+= Pitch;
}
SDL_Flip(Screen);
SDL_Delay( 1000/25);
Frame= Clip->GetFrame( I, Env);
}
//delete Env; ////////////// Crash!
SDL_Quit();
return 0;
}
And remember frames are numbered from zero.
IanB
28th November 2008, 22:22
You should do:Frame = 0;
Clip = 0;The 'smart pointer' code behind the scenes will do the rest.You will also need to Val=0; as well.
bigboss97
29th November 2008, 12:15
Thanks for that. After adding this before delete Env, now it doesn't crash any more.
You will also need to Val=0; as well.
vBulletin® v3.8.5, Copyright ©2000-2012, Jelsoft Enterprises Ltd.