View Full Version : how to handle external clips in avisynth plugin
Ceppo
2nd February 2021, 21:51
I'm making a plugin and it uses an edeint clip to take the deinterlaced frames from. I'd like to know how to handle the case in which no edeint clip is given because of forgetfulness (like the thr parameter is set but no edeint is given) and when is not given because the user wants not to use it and skip the code block (the thr parameter is set to saturation). I'd like also to know if it is possible to set it to a dummy clip that works with getframe and so on and if not, would be possible to set it to default a bob(last) clip? I hope I'm clear.
If you want to look at the code let me know.
StainlessS
2nd February 2021, 23:30
env->AddFunction("GamMac" ,
"c[LockChan]i[Scale]i[RedMul]f[GrnMul]f[BluMul]f"
"[Th]f[loTh]f[hiTh]f[LockVal]f[RngLim]i[GamMax]f"
"[dc]c"
"[x]i[y]i[w]i[h]i[omin]i[omax]i"
"[Show]b[Verbosity]i[Coords]b[Dither]b"
,Create_GamMac , 0);
// ...
AVSValue __cdecl Create_GamMac(AVSValue args, void* user_data, IScriptEnvironment* env) {
char *myName="GamMac: ";
PClip child = args[0].AsClip();
const VideoInfo &vi=child->GetVideoInfo();
if(!vi.IsRGB()) env->ThrowError("%sRGB Only",myName);
if(vi.width==0||vi.num_frames<=0) env->ThrowError("%sClip has no video",myName);
int LockChan = args[1 ].AsInt(1);
int Scale = args[2 ].AsInt(1);
double RedMul = args[3 ].AsFloat(1.0);
double GrnMul = args[4 ].AsFloat(1.0);
double BluMul = args[5 ].AsFloat(1.0);
float Th = (float)args[6 ].AsFloat(0.00);
double loTh = args[7 ].AsFloat(Th);
double hiTh = args[8 ].AsFloat(Th);
double LockVal = args[9 ].AsFloat(128.0);
int RngLim = args[10].AsInt(11);
double GamMax = args[11].AsFloat(10.0);
PClip dc = (args[12].IsClip()) ? args[12].AsClip() : child;
// ...
Above, we made same as child clip, to avoid separate usage of dc,
you could just as easily set it to NULL and alter behaviour based on that.
Does that solve your problem.
EDIT:
class GamMac : public GenericVideoFilter {
private:
PClip dc;
const int LockChan;
const int Scale;
// ...
GamMac::GamMac(PClip _child,PClip _dc,
int _LockChan,int _Scale,double _RedMul,double _GrnMul,double _BluMul,
double _loTh,double _hiTh,double _LockVal,
int _RngLim,double _GamMax,
int _xx,int _yy,int _ww,int _hh,int _omin,int _omax,
bool _Show,int _Verbosity,bool _dither,
IScriptEnvironment* env) :
GenericVideoFilter(_child),
dc(_dc),
LockChan(_LockChan),Scale(_Scale),RedMul(_RedMul),GrnMul(_GrnMul),BluMul(_BluMul),
loTh(_loTh),hiTh(_hiTh),LockVal(_LockVal),
RngLim(_RngLim),GamMax(_GamMax),
xx(_xx),yy(_yy),ww(_ww),hh(_hh),omin(_omin),omax(_omax),
Show(_Show),Verbosity(_Verbosity),Dither(_dither) {
// ...
Sort of similar usage to in GetFrame
void GamMac::CountDcRGB(int n,IScriptEnvironment* env) {
// vi and vi2 are same colorspace and number of frames, so can use vi for n and ColorSpace.
n = (n<0) ? 0 : (n>= vi.num_frames) ? vi.num_frames - 1 : n;
unsigned int *R=cnt[0],*G=cnt[1],*B=cnt[2];
memset(R,0,sizeof(R[0])*256); memset(G,0,sizeof(G[0])*256); memset(B,0,sizeof(B[0])*256);
PVideoFrame src = dc->GetFrame(n, env);
int height = src->GetHeight();
int pitch = src->GetPitch();
const int step = (vi.IsRGB32()) ? 4 : 3;
// ...
And use something like this if necessary in GetFrame.
const VideoInfo &vi2=dc->GetVideoInfo();
Ceppo
3rd February 2021, 11:04
Thank you for your help. Just wondering if it was still possible to set a default bob/QTGMC clip.
StainlessS
3rd February 2021, 16:39
If I understand you correctly, then maybe do something like
// In Create_GamMac()
PClip dc;
if(args[12].IsClip()) {
dc = args[12].AsClip();
} else {
// do invoke bob/QTGMC on child, or whatever in here, assign to dc
}
EDIT: Defo need try/catch on invoke.
I don't like using non builtin filters in CPP plugin, also,
QTGMC() has [I think] a few different versions, with different args probably, have to use Named Invoke arguments
and only use args common in all versions of QTGMC().
Probably easier to demand user supply bobbed dc, and complain if not supplied.
Can still specify as optional, but detect not supplied in the Create_GamMac thing, and ThrowError.
Also gives user control over bobber used.
EDIT:
Although you could also use some bobber Eval() string instead of dc, again with try/catch and
so user has control of bob, but that aint much different to the user having to provide a pre-bobbed dc clip.
Ceppo
3rd February 2021, 19:57
I see thank you.
StainlessS
3rd February 2021, 20:22
Maybe also of use, demos optional named args for invoke, from Uglarm() plug.
if(ShowMode >= 2) {
DPRINTF("ShowMode=%d",ShowMode)
ret = new Uglarm(ret,Pat_X,Pat_Y,Pat_W,Pat_H,SAR,BlurPower,Msk,xmod,ymod,hasChroma,ShowMode,env);
DPRINTF("Returned from Uglarm constructor")
// Blank Border
if(Blank) {
DPRINTF("Showing BLANK LetterBox")
// Letterbox (clip, int top, int bottom, [int left], [int right], int "color")
// un-named args NULL names
AVSValue LetterBox_Args[6] = { ret, ClipY, vi.height-ClipY-ClipH, ClipX, vi.width-ClipX-ClipW, 0x000000 };
const char* LetterBox_Names[6] = { NULL, NULL, NULL, NULL, NULL, "color" };
try {
DPRINTF("Calling Invoke LetterBox (Blank)")
ret = env->Invoke("LetterBox", AVSValue(LetterBox_Args,6),LetterBox_Names).AsClip();
DPRINTF("Invoke LetterBox Succeeds (Blank)")
} catch (IScriptEnvironment::NotFound) {
DPRINTF("Invoke LetterBox Fails (Blank)")
env->ThrowError("%sWhoa! Could not Invoke LetterBox! (Blank)",myName);
}
DPRINTF("Done Uglarm Blank")
}
Using only optional named arg "color" for Letterbox().
DPRINTF stuff just some of my debug code.
EDIT: When I wrote above, I could find little info on named args, in particular the NULL (un-named) ones prior to using named arg,
I tried using "", which failed, and found NULL is required.
EDIT:
Here code of the DPRINTF() thing, is handy for debugging which is easily switched off in final.
Part of my compilier.h
#ifndef __COMPILER_H__
#define BUG
#define __COMPILER_H__
#ifdef BUG
#if _MSC_VER >= 1500 // VS 2008+
// Call as eg DPRINTF("Forty Two = %d",42) // No Semi colon
// C99 Compiler (eg VS2008)
#define DPRINTF(fmt, ...) dprintf(fmt, ##__VA_ARGS__); // No Semi colon needed
#else
// OLD C89 Compiler: (eg VS6)
// Call as eg DPRINTF(("Forty Two = %d",42)) // Enclosed in double parentethis, No Semi colon
#define DPRINTF(x) dprintf x;
#endif
#else
#if _MSC_VER >= 1500 // VS 2008+
// C99 Compiler (eg VS2008)
#define DPRINTF(fmt,...) /* fmt */
#else
// OLD C89 Compiler: (eg VS6)
#define DPRINTF(x) /* x */
#endif
#endif
extern int __cdecl dprintf(char* fmt, ...);
#endif // __COMPILER_H__
can set #define BUG inside compiler.h or remove it and set before including compiler.h,
if BUG defined, will print debugging stuff else not.
and then somewhere else in source [View debug in DebugView, below outputs eg "Uglarm: Some message" ]
#ifdef BUG
int __cdecl dprintf(char* fmt, ...) {
char printString[2048]="Uglarm: "; // Must be nul Termed, eg "Test: " or ""
char *p=printString;
for(;*p++;);
--p; // @ null term
va_list argp;
va_start(argp, fmt);
vsprintf(p, fmt, argp);
va_end(argp);
for(;*p++;);
--p; // @ null term
if(printString == p || p[-1] != '\n') {
p[0]='\n'; // append n/l if not there already
p[1]='\0';
}
OutputDebugString(printString);
return int(p-printString); // strlen printString
}
#endif // BUG
Can use like
DPRINTF("Forty two = %d",42) // No ending semi-colon, "Uglarm: Forty two = 42" # Use DebugView to view output.
DebugView from SysInternals [ie M$]:- https://docs.microsoft.com/en-us/sysinternals/downloads/debugview
Ceppo
5th February 2021, 11:46
if(ShowMode >= 2) {
DPRINTF("ShowMode=%d",ShowMode)
ret = new Uglarm(ret,Pat_X,Pat_Y,Pat_W,Pat_H,SAR,BlurPower,Msk,xmod,ymod,hasChroma,ShowMode,env);
DPRINTF("Returned from Uglarm constructor")
// Blank Border
if(Blank) {
DPRINTF("Showing BLANK LetterBox")
// Letterbox (clip, int top, int bottom, [int left], [int right], int "color")
// un-named args NULL names
AVSValue LetterBox_Args[6] = { ret, ClipY, vi.height-ClipY-ClipH, ClipX, vi.width-ClipX-ClipW, 0x000000 };
const char* LetterBox_Names[6] = { NULL, NULL, NULL, NULL, NULL, "color" };
try {
DPRINTF("Calling Invoke LetterBox (Blank)")
ret = env->Invoke("LetterBox", AVSValue(LetterBox_Args,6),LetterBox_Names).AsClip();
DPRINTF("Invoke LetterBox Succeeds (Blank)")
} catch (IScriptEnvironment::NotFound) {
DPRINTF("Invoke LetterBox Fails (Blank)")
env->ThrowError("%sWhoa! Could not Invoke LetterBox! (Blank)",myName);
}
DPRINTF("Done Uglarm Blank")
}
Thanks, is good to know. I will keep the link saved for future reference. About DebugView, I started C++ after Christmas so at the moment is a bit hard for me, but I will keep it in mind.
StainlessS
5th February 2021, 16:16
OK,
You can just use instead eg,
OutputDebugString("Hello"); // Single entire string ONLY, needs include stdio.h [I think]
DebugView allows you to see your debug messages, its maybe harder Not-To-Use it.
Any kind of debugging makes life easier, especially if learning, you can see where it went wrong, or where it got to before it went wrong.
I use debugview even with avs script, RT_Stats RT_DebugF() for output.
EDIT: DPRINTF() [or dprintf() which dont switch off when you dont define BUG], uses the same style as standard C printf()
or sprintf().
Ceppo
7th February 2021, 14:04
I see, thank you.
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.