Log in

View Full Version : weird dfttest error


feisty2
16th November 2014, 10:23
I was tryna test the "nfile/nstring" functions of dfttest, did everything as it's written in readme.txt

LWLibAVVideoSource("yv12 video")
dfttest (f0beta=0.5,U=false,V=false,nstring="a:4.0 2,0,45,68 2,0,23,87")

and got an error
http://i.imgur.com/nO70WWD.png
what did I do wrong?

StainlessS
16th November 2014, 11:30
I dont usually use this function but looked it up in doc and source.

dfttest.cpp

void dfttest::getNoiseSpectrum(const char *fname, const char *nstring,
float *dest, const float wscale, IScriptEnvironment *env)
{
PS_INFO *pss = pssInfo[0];
PlanarFrame *prf = new PlanarFrame(vi_src);
memset(dest,0,ccnt*2*sizeof(float));
float *hw2 = (float*)_aligned_malloc(bvolume*sizeof(float),16);
createWindow(hw2,0,tbsize,tosize,twin,tbeta,0,sbsize,sosize,swin,sbeta);
fftwf_complex *dftgc2 = (fftwf_complex*)_aligned_malloc(sizeof(fftwf_complex)*(ccnt+11),16);
float wscale2 = 0.0f, alpha = ftype == 0 ? 5.0f : 7.0f, *dftr = pss->dftr;
int w = 0;
for (int s=0; s<tbsize; ++s)
{
for (int i=0; i<sbsize; ++i)
{
for (int k=0; k<sbsize; ++k, ++w)
{
dftr[w] = 255.0f*hw2[w];
wscale2 += hw2[w]*hw2[w];
}
}
}
wscale2 = 1.0f/wscale2;
fftwf_execute_dft_r2c(ftg,dftr,dftgc2);
int nnpoints = 0;
char buf[512];
NPINFO *npts = (NPINFO*)malloc(500*sizeof(NPINFO));
if (nstring[0]) // read points from nstring
{
const char *q = nstring;
if (q[0] == 'a' || q[0] == 'A')
{
float alphat;
if (sscanf(q,"%*c:%f",&alphat) != 1)
env->ThrowError("dfttest: error reading alpha value from nstring!\n");
if (alphat <= 0.0f)
env->ThrowError("dfttest: nstring - invalid alpha factor!\n");
alpha = alphat;
while (q[0] != ' ' && q[0] != 0) ++q;
}
while (true)
{
while ((q[0] < '0' || q[0] > '9') && q[0] != 0)
++q;
int fn, b, y, x;
if (q[0] == 0 || sscanf(q,"%d,%d,%d,%d",&fn,&b,&y,&x) != 4)
break;
if (fn < 0 || fn > vi_src.num_frames-tbsize)
env->ThrowError("dfttest: invalid frame number in nstring (%d)!\n", fn);
if (b < 0 || b > 2)
env->ThrowError("dfttest: invalid plane number in nstring (%d)!\n", b);
const int height = proc_height >> vi.GetPlaneHeightSubsampling (b);
if (y < 0 || y > height-sbsize)
env->ThrowError("dfttest: invalid y pos in nstring (%d)!\n", y);
const int width = vi_src.width >> vi.GetPlaneWidthSubsampling (b);
if (x < 0 || x > width-sbsize)
env->ThrowError("dfttest: invalid x pos in nstring (%d)!\n", x);
if (nnpoints >= 300)
env->ThrowError("dfttest: maximum number of entries in nstring is 500!\n");
npts[nnpoints].fn = fn;
npts[nnpoints].b = b;
npts[nnpoints].y = y;
npts[nnpoints].x = x;
++nnpoints;
while (q[0] != ' ' && q[0] != 0) ++q;
}
}


Modified VERSION 3, Avisynth.h

int GetPlaneHeightSubsampling(int plane) const { // Subsampling in bitshifts!
if (plane == PLANAR_Y) // No subsampling
return 0;
if (IsY8())
throw AvisynthError("Filter error: GetPlaneHeightSubsampling not available on Y8 pixel type.");
if (plane == PLANAR_U || plane == PLANAR_V) {
if (IsYUY2())
return 0;
else if (IsPlanar())
return ((pixel_type>>CS_Shift_Sub_Height)+1) & 3;
else
throw AvisynthError("Filter error: GetPlaneHeightSubsampling called with unsupported pixel type.");
}
throw AvisynthError("Filter error: GetPlaneHeightSubsampling called with unsupported plane.");
}


I dont really see where the error is.

EDIT: Think this is the problem but I dont understand why I was convinced that PLANAR_Y==0, and PLANAR_U==1 and PLANAR_V==2,
but from Avisynth.h

enum {
PLANAR_Y=1<<0, // 1
PLANAR_U=1<<1, // 2
PLANAR_V=1<<2, // 4
PLANAR_ALIGNED=1<<3,
PLANAR_Y_ALIGNED=PLANAR_Y|PLANAR_ALIGNED,
PLANAR_U_ALIGNED=PLANAR_U|PLANAR_ALIGNED,
PLANAR_V_ALIGNED=PLANAR_V|PLANAR_ALIGNED,
};


plane is given to GetPlaneHeightSubsampling range 0-2 but is compared with 1, or 2, or 4.

when did PLANAR_Y etc change ?
EDIT: Looks like PLANAR_Y was always 1 << 0, dont know why I thought it was 0 (kicks oneself).

EDIT: So perhaps it should be (in dfttest.cpp:getNoiseSpectrum)

const int height = proc_height >> vi.GetPlaneHeightSubsampling (1 << b);

GetPlaneWidthSubsampling() calls would also need change.

or, alternatively change GetPlaneHeightSubsampling/width functions to compare with (1<< plane), [probably better bet].

I guess we wait for Cretindesalpes or Firesledge (two equally nice guys).

EDIT:

Taking same info from file seems OK

if (fn < 0 || fn > vi.num_frames-tbsize)
env->ThrowError("dfttest: invalid frame number in nfile (%d)!\n", fn);
if (b < 0 || b > 2)
env->ThrowError("dfttest: invalid plane number in nfile (%d)!\n", b);
const int height = b == 0 ? vi.height : (vi.height>>1);
if (y < 0 || y > height-sbsize)
env->ThrowError("dfttest: invalid y pos in nfile (%d)!\n", y);
const int width = (vi.IsYV12() && b > 0) ? (vi.width>>1) : vi.width;
if (x < 0 || x > width-sbsize)
env->ThrowError("dfttest: invalid x pos in nfile (%d)!\n", x);
if (nnpoints >= 300)
env->ThrowError("dfttest: maximum number of entries in nfile is 500!\n");

But found another [not really too problematic] bug in RED. Should be 500 (bug in both string and file)

NPINFO *npts = (NPINFO*)malloc(500*sizeof(NPINFO));


EDIT: Also, Internal.h should not be necessary now VERSION 3 Avisynth.h is used, should (I think) be able to delete from source.
Also, if same modified VERSION 3 Avisynth.h used in other Cretindesalpes mods, then will likely suffer from similar problems. (ignore this line)

feisty2
16th November 2014, 13:37
thx for ur reply
guess I'll sneak around other stuff and wait for support
:)

Wilbert
16th November 2014, 17:08
I don't know anything about this plugin, but i guess you can set the plane which should be processed/analyzed as input parameter (by setting the nstring value).
If the values of PLANAR_Y, PLANAR_U, PLANAR_V were to change one day you would run into problems with this plugin. So it's not a good way of doing this. You should use something like the following:


int fn, b, y, x, plane;
if (q[0] == 0 || sscanf(q,"%d,%d,%d,%d",&fn,&b,&y,&x) != 4)
break;
...
if (b == 0) plane = PLANAR_Y;
if (b == 1) plane = PLANAR_U;
if (b == 2) plane = PLANAR_V;
if (b <= 0 || b > 2)
env->ThrowError("dfttest: invalid plane number in nstring (%d)!\n", b);
const int height = proc_height >> vi.GetPlaneHeightSubsampling (plane);
if (y < 0 || y > height-sbsize)
env->ThrowError("dfttest: invalid y pos in nstring (%d)!\n", y);
const int width = vi_src.width >> vi.GetPlaneWidthSubsampling (plane);
...

StainlessS
16th November 2014, 20:37
Well blow me, GetPlaneHeightSubsampling() in what I described as Modified VERSION 3, Avisynth.h is taken from
v2.6a5 Interface.cpp (exactly), I would have immediately assumed that the 'plane' arg was in range 0 -> 2 and not the
PLANAR_Y type flags.
I'm glad I've never used those functions before, I usually roll my own and so valid in v2.5 or v2.6.

Wilbert
16th November 2014, 20:56
Well blow me, GetPlaneHeightSubsampling() in what I described as Modified VERSION 3, Avisynth.h is taken from
v2.6a5 Interface.cpp (exactly), I would have immediately assumed that the 'plane' arg was in range 0 -> 2 and not the
PLANAR_Y type flags.
I'm glad I've never used those functions before, I usually roll my own and so valid in v2.5 or v2.6.
I don't get your response. If you define your own for v2.58, you need to deal with the same issue. You need to add them in the following way: http://avisynth.nl/index.php/Filter_SDK/DualPlugins#The_SimpleSample_example

You should always use the flags and never their values!

StainlessS
16th November 2014, 21:59
I should have said something like, "and so valid in v2.6 or for Y8 in v2.58 plugins, and not dependant upon whether implemented in both avisynth headers",
I dont actually use those funcs (implemented only in Standard VERSION 5 Avisynth v2.6 header API),
here sample from RoboCrop constructor, a number of the variables are not usually necessary, but RoboCrop constructor is a bit heavy duty and better to have available (I dont like calling even inline member functions a gazillion times).


# ifdef AVISYNTH_PLUGIN_25
if(vi.IsPlanar() && vi.pixel_type != 0xA0000008) {
// Here Planar but NOT YV12, If v2.5 Plugin Does NOT support ANY v2.6+ ColorSpaces
env->ThrowError("%sColorSpace unsupported in v2.5 plugin",myName);
}
# endif

bool isyuv=false,isplanar=false,isyuy2=false,isrgb=false,isy8=false;
xmod=1,ymod=1;

if(isyuv=vi.IsYUV()) {
if(isplanar=vi.IsPlanar()) {
PVideoFrame src = child->GetFrame(0, env); // get frame 0, have already checked HasVideo and FrameCount
int rowsizeUV=src->GetRowSize(PLANAR_U);
if(rowsizeUV!=0) { // Not Y8
const int ywid=src->GetRowSize(PLANAR_Y);
const int yhit=src->GetHeight(PLANAR_Y);
const int uhit=src->GetHeight(PLANAR_U);
xmod=ywid/rowsizeUV;
ymod=yhit/uhit;
} else {
isy8=true;
}
} else {
isyuy2=true;
xmod=2;
}
} else {
isrgb=true;
}

xSubS=xmod; // for Planar GetFrame
ySubS=ymod;

laced = args[3].AsBool(true);
ymod = (laced)? ymod*2 : ymod;



You can usually cope with Y8 in Avisynth v2.58 plugin or,
with other planar if only sampling Luma or using env->MakeWritable when only changing Luma 'In-Place'
(not where using env->NewVideoFrame or where rendering metrics text using Info.h or DDigit [as both affect chroma]).
I have chosen above to not support Y8 in 2.5 plugin in RoboCrop, even though I probably could have done.

PS, I usually do assign eg PLANAR_Y if using int range 0->2 to index plane, as suggested (although I had thought I was being a little over cautious in doing so, the fact that I remained convinced that PLANAR_Y was 0 etc is testament that I do use those defined values).

And, CS_YV12 = 0xA0000008, is cast in stone in Avisynth v2.5 header baked API for YV12 or other planar (v2.5 plugin),
but vi.pixel_type gives true colorspace (set by Avisynth/Sourcefilter) whether v2.5 plugin in v2.5/2.6 Avisynth, or v2.6 plugin in v2.6 Avisynth
(recent v2.6 plugin in v2.5 Avisynth no longer function, so, I guess that CS_YV12 = 0xA0000008 is no longer cast in stone for future 2.6 headers but where I used 0xA0000008 at head of snippet, it is for v2.5 plug and so will remain cast in stone. NOPE, Avisynth v2.6 would likely need to keep CS_YV12 = 0xA0000008 for v2.5 plugs, so cast in stone 4e4 [for a long time]).
From current v2.6a5 VERSION 5 Avisynth.h

// YV12 must be 0xA000008 2.5 Baked API will see all new planar as YV12
// I420 must be 0xA000010


EDITED:

EDIT: And here what I use where v2.5 plug supports v2.6 colorspaces as only luma processed, BUT NOT if showing metrics.

const char *myName="Chronos: ";

# ifdef AVISYNTH_PLUGIN_25
if(show && vi.IsPlanar()) {
if( vi.pixel_type!=0xA0000008 && // YV12
vi.pixel_type!=0xE0000000 // Y8
) { // v2.5 plug supports v2.6 colorspaces as only luma processed, BUT NOT if showing metrics
env->ThrowError("%sColorSpace unsupported for Show metrics in v2.5 dll\n",myName);
}
}
# endif