Log in

View Full Version : SOLVED :) Compiler Bug ??? (VS 2010)


StainlessS
13th November 2016, 22:32
SOLVED :) Problem disappears with mvtools2 v2.7.1.22.


Hi Guys, having a bit of a problem with below code (VS2010), there dont seem to be similar problem in VS98 or VS2003 ToolKit 3.

Produces -1.IND000000000000 condition (but only on very first frame [EDIT: RT_AverageLuma will not access frame -1]).
Code producing error is during conversion of __int64 value of 255 to double.

Script

FN="LowBitrateAnime.AVI"
Avisource(FN)

Function StartOfSceneClip(clip c,Int "thSCD1",Int "thSCD2") {
c
thSCD1=Default(thSCD1,400)
thSCD2=Default(thSCD2,130)
sup=c.MSuper(pel=1,sharp=0,rfilter=2,hpad=16, vpad=16)
I_fv=sup.MAnalyse(isb=false,delta=1,blksize=16,overlap=8)
Return c.MSCDetection(I_fv,thSCD1=thSCD1,thSCD2=thSCD2)
}

SC=StartOfSceneClip

SSS="""
n=current_frame
f=SC.RT_AverageLuma(n=n,W=1,H=1) # Sample single pixel
RT_Subtitle("%d] F=%f",n,f) # Shows '0] F=-1.#IND00' on first frame
return last
"""

Scriptclip(SSS)



Code fragment

// Roughly What happens earlier in source
// __int64 acc = 0;
// unsigned int sum = 0;
// sum = sum + 255
// unsigned int Pixels=1; // EDIT: Added


// floating point error flags (eg 1.0/3.0 gives _EM_INEXACT)
unsigned int e = (_clearfp());
if(e) {
dprintf("RT_AverageLuma2: ***ERROR*** E=%X\n",e);
}

acc += sum; // acc = 255
double dacc = double(acc); // -1.#IND000000000000 ... SHOCK HORROR
double result = dacc / Pixels;

// e = (_clearfp() & ~_EM_INEXACT);
e = (_clearfp());
if(e) {
dprintf("RT_AverageLuma3: ***ERROR*** E=$%X dacc=%f($%I64X) Pixels=%d",e,dacc,acc,Pixels);
}

return result;
}


Debugview Output, prints 2nd Error only (ie RT_AverageLuma3: error [EDIT: Below E=$10 is _EM_INEXACT])

00000006 1.73375964 RT_AverageLuma3: ***ERROR*** E=$10 dacc=-1.#IND00($FF) Pixels=1



Disassembly

// floating point error flags (eg 1.0/3.0 gives _EM_INEXACT)
// unsigned int e = (_clearfp() & ~_EM_INEXACT);
unsigned int e = (_clearfp());
04DEBFBA call @ILT+1620(__clearfp) (4DE3659h)
04DEBFBF mov dword ptr [e],eax
if(e) {
04DEBFC5 cmp dword ptr [e],0
04DEBFCC je $LN7+183h (4DEBFE2h)
dprintf("RT_AverageLuma2: ***ERROR*** E=%X\n",e);
04DEBFCE mov eax,dword ptr [e]
04DEBFD4 push eax
04DEBFD5 push offset string "RT_AverageLuma2: ***ERROR*** E=%"... (4ECF1ACh)
04DEBFDA call dprintf (4DE31DBh)
04DEBFDF add esp,8
}

acc += sum;
04DEBFE2 mov eax,dword ptr [sum]
04DEBFE5 xor ecx,ecx
04DEBFE7 add eax,dword ptr [acc]
04DEBFEA adc ecx,dword ptr [ebp-38h]
04DEBFED mov dword ptr [acc],eax
04DEBFF0 mov dword ptr [ebp-38h],ecx
double dacc = double(acc);
04DEBFF3 fild qword ptr [acc]
04DEBFF6 fstp qword ptr [dacc]
double result = dacc / Pixels;
04DEBFFC mov eax,dword ptr [Pixels]
04DEBFFF mov dword ptr [ebp-1A0h],eax
04DEC005 mov dword ptr [ebp-19Ch],0
04DEC00F fild qword ptr [ebp-1A0h]
04DEC015 fdivr qword ptr [dacc]
04DEC01B fstp qword ptr [result]

// e = (_clearfp() & ~_EM_INEXACT);
e = (_clearfp());
04DEC021 call @ILT+1620(__clearfp) (4DE3659h)
04DEC026 mov dword ptr [e],eax
if(e) {
04DEC02C cmp dword ptr [e],0
04DEC033 je $LN7+202h (4DEC061h)
dprintf("RT_AverageLuma3: ***ERROR*** E=%X dacc=%f($%I64X) Pixels=%d",e,dacc,acc,Pixels);
04DEC035 mov eax,dword ptr [Pixels]
04DEC038 push eax
04DEC039 mov ecx,dword ptr [ebp-38h]
04DEC03C push ecx
04DEC03D mov edx,dword ptr [acc]
04DEC040 push edx
04DEC041 sub esp,8
04DEC044 fld qword ptr [dacc]
04DEC04A fstp qword ptr [esp]
04DEC04D mov eax,dword ptr [e]
04DEC053 push eax
04DEC054 push offset string "RT_AverageLuma3: ***ERROR*** E=%"... (4ECF164h)
04DEC059 call dprintf (4DE31DBh)
04DEC05E add esp,1Ch
}

return result;
04DEC061 fld qword ptr [result]
}


Is it possible that the problem resides earlier in code ? if so how can one detect it ?

Perhaps MvTools2 (v2.5.11.20) problem in trying to access first frame-1 ie frame -1, and somehow propagated into my function ?

Any clues anybody ?

Groucho2004
13th November 2016, 22:44
Did you compile with "/Od"? "_clearfp()" doesn't work properly if you don't disable compiler optimizations.

StainlessS
13th November 2016, 22:49
Debug dll compiled with /Od (as above).

EDIT: Exact same results in release with Maximise Speed /O2.

EDIT: Also occurs if script line mod

f=SC.RT_AverageLuma # Use current_frame and full frame sample

But this has no error

f=SC.AverageLuma


I have stepped though the function and spotted no weirdness, everything as expected (not difficult for single pixel sample).

EDIT:
Swapping

SC=StartOfSceneClip

to

SC=Last

No problems.

StainlessS
13th November 2016, 23:56
Its beginning to taste a lot like a problem in MvTool2 v2.5.11.20.

This has a problem at both ends of the clip, Error on SOS (Start of Scene) at frame 0, and at EOS (End Of Scene) on last frame
(if you in VDMod jump directly to last frame, And also if you jump to last but one, then step forward to last frame.
Strangely not if you jump to last but two and step forward to last frame).

FN="LowBitrateAnime.AVI"
Avisource(FN)

Function EndOfSceneClip(clip c,Int "thSCD1",Int "thSCD2") {
thSCD1=Default(thSCD1,400)
thSCD2=Default(thSCD2,130)
sup=c.MSuper(pel=1,sharp=0,rfilter=2,hpad=16, vpad=16)
I_bv=sup.MAnalyse(isb=true, delta=1,blksize=16,overlap=8)
Return c.MSCDetection(I_bv,thSCD1=thSCD1,thSCD2=thSCD2)
}

Function StartOfSceneClip(clip c,Int "thSCD1",Int "thSCD2") {
thSCD1=Default(thSCD1,400)
thSCD2=Default(thSCD2,130)
sup=c.MSuper(pel=1,sharp=0,rfilter=2,hpad=16, vpad=16)
I_fv=sup.MAnalyse(isb=false,delta=1,blksize=16,overlap=8)
Return c.MSCDetection(I_fv,thSCD1=thSCD1,thSCD2=thSCD2)
}

EOS = EndOfSceneClip
SOS = StartOfSceneClip

SSS="""
e = EOS.RT_AverageLuma(n=current_frame,W=1,H=1)
s = SOS.RT_AverageLuma(n=current_frame,W=1,H=1)
RT_Subtitle("%d] EOS=%f SOS=%f",current_frame,e,s)
return last
"""
Scriptclip(SSS)


EDIT: I dont think AverageLuma() uses a 64 bit accumulator (which RT_ does) and so that could be reason for not being affected
on convert to double.

EDIT: Problem persists in earlier MvTool2 v2.5.11.2.

StainlessS
14th November 2016, 00:18
Problem disappears with mvtools2 v2.7.1.22.

SOLVED :)

EDIT:
MSCDetection from mvtools2 v2.5.11.2 and v2.5.11.20 must cause some kind of Floating point error that is propagated to the next filter using Floating point.

Only above 3 versions of mvTools2 tested.

EDIT: Wheres the Edit Tags thing gone ? (Wanted to add eg MvTools, MSCDetection, and Floating point error).
EDIT: Found it, on last post, not first.

EDIT: Also broken in v2.5.11.22.
EDIT: V2.6.0.5 unaffected by above problem.

StainlessS
14th November 2016, 23:14
Here is small source that demos the problem even using VS6 (Aka VS 98)


#ifdef UNICODE
#undef UNICODE // Avoid default wide character stuff
#endif
#ifdef _UNICODE
#undef _UNICODE // Avoid default wide character stuff
#endif
#ifdef MBCS
#undef MBCS
#endif
#ifdef _MBCS
#undef _MBCS
#endif
#define _CRT_SECURE_NO_WARNINGS

#include <windows.h>
#include <stdio.h>
#include <float.h>
#include "avisynth.h"

int dprintf(char* fmt, ...) {
char printString[2048]="FloatTest: "; // MUST NUL TERM THIS [at some point before vsprintf(p, fmt, argp)]
char *p=printString;
while(*p++);
--p; // @ nul term
va_list argp;
va_start(argp, fmt);
vsprintf(p, fmt, argp);
va_end(argp);
while(*p++);
--p; // @ nul term
if(printString == p || p[-1] != '\n') { p[0]='\n'; p[1]='\0'; } // append n/l if not there already
OutputDebugString(printString);
return int(p-printString); // strlen printString
}

AVSValue __cdecl FloatTest(AVSValue args, void* user_data, IScriptEnvironment* env) {
PClip child = args[0].AsClip();
const bool test = args[1].AsBool(false); // Should we test video frame 0 ?
const int n = 0; // test frame 0 only
PVideoFrame src;
__int64 acc=255;
int Pixels=1;
double dacc = (double)acc;
double result = dacc / Pixels;
int e;
if(e = _clearfp()) {
dprintf("FloatTest1: ***ERROR*** E=$%X dacc=%f($%I64X) Pixels=%d",e,dacc,acc,Pixels);
}
if(test)src = child->GetFrame(n,env); // Force decoding. MUST assign to PVideoFrame
dacc = (double)acc; // Error Here when test==true
result = dacc / Pixels;
if(e = _clearfp()) {
dprintf("FloatTest2: ***ERROR*** E=$%X dacc=%f($%I64X) Pixels=%d",e,dacc,acc,Pixels);
}
return result;
}

extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit2(IScriptEnvironment* env) {
env->AddFunction("FloatTest","c[test]b", FloatTest, 0);
return "`FloatTest' FloatTest plugin";
}


And test script, errors if TEST=True (where calls GetFrame on frame 0, without doing anything else to it).


FN="LowBitrateAnime.AVI"
Avisource(FN)

Function StartOfSceneClip(clip c,Int "thSCD1",Int "thSCD2") {
thSCD1=Default(thSCD1,400)
thSCD2=Default(thSCD2,130)
sup=c.MSuper(pel=1,sharp=0,rfilter=2,hpad=16, vpad=16)
I_fv=sup.MAnalyse(isb=false,delta=1,blksize=16,overlap=8)
Return c.MSCDetection(I_fv,thSCD1=thSCD1,thSCD2=thSCD2)
}

SOS = StartOfSceneClip

TEST=True

SSS="""
s = SOS.FloatTest(Test=TEST)
RT_Subtitle("%d] SOS=%f",current_frame,s)
return last
"""

Scriptclip(SSS)


EDIT: Test target above was MvTool2 v2.5.11.2, no others tested.

EDIT: Made test a bit better, CPP updated.
Here debug output

00000003 0.80795121 FloatTest: FloatTest2: ***ERROR*** E=$10 dacc=-1.#IND00($FF) Pixels=1