Ceppo
4th February 2021, 14:44
I have a strange bug in my filter and I was able to pinpoint the source function but I don't understand what's the problem. VS Project (https://www.mediafire.com/file/0fqalan7ylmjfge/InvertNeg.zip/file)
I will try to also copy here the main code parts so that maybe you don't have to download the project.
This is GetFrame:
PVideoFrame __stdcall InvertNeg::GetFrame(int m, IScriptEnvironment* env) {
int n = m / 2;
int order = child->GetParity(0) ? 1 : 0;
PVideoFrame dst = env->NewVideoFrame(vi);
PVideoFrame src = child->GetFrame(n, env);
PVideoFrame prv = child->GetFrame(n == 0 ? n : n - 1, env);
PVideoFrame nxt = child->GetFrame(n == vi.num_frames - 1 ? n : n + 1, env);
if ( m & 1 )
{
std::int64_t diffC = get_diff(src, src, mode, order, nt, sse);
std::int64_t diffN = get_diff(src, nxt, mode, !order, nt, sse);
field_match(dst, src, nxt, diffC, diffN, !order);
}
else
{
std::int64_t diffC = get_diff(src, src, mode, order, nt, sse);
std::int64_t diffP = get_diff(src, prv, mode, order, nt, sse);
field_match(dst, src, prv, diffC, diffP, order);
}
PVideoFrame met;
bool check = true;
if (m & 1)
{
if (thr < 255 || thr2 < 255)
{
PVideoFrame met = env->NewVideoFrame(vi);
check = calc_combed(dst, met, metric, !order, thr, thr2, src_width, src_height);
}
}
else
{
if (thr < 255 || thr2 < 255)
{
PVideoFrame met = env->NewVideoFrame(vi);
check = calc_combed(dst, met, metric, order, thr, thr2, src_width, src_height);
}
}
if (check && thr2 < 255 && edeint2)
{
PVideoFrame edtb = edeint2->GetFrame(m, env);
copy_frame(dst, edtb);
}
else if (thr < 255 && edeint)
{
if (is_combed(met, metric, order, 4))
{
PVideoFrame edta = edeint->GetFrame(m, env);
copy_frame(dst, edta);
}
}
return dst;
}
Now the bug shows up when this line is executed: if (is_combed(met, metric, order, 4))
The problem with it is the "met" clip as a PVideoframe argument. If I change "met" with another random clip like "src" the bug doesn't show up and all frames are detected as combed as expected.
Now I make another change in the calc_combed() lines and I replace "met" with "src" here as well. The bug shows up again so I'm guessing that calc_combed() does something evil. Here the function:
bool calc_combed(PVideoFrame& dst, PVideoFrame& met, int metric, int order, int thr, int thr2, int src_width, int src_height)
{
unsigned char* metp;
const unsigned char* dstp;
const unsigned char* dstpp;
const unsigned char* dstppp;
const unsigned char* dstpn;
const unsigned char* dstpnn;
int height;
int row_size;
int dst_pitch;
int met_pitch;
double sum = 0;
int p, x, y, c, c1, c2;
int planes[] = { PLANAR_Y, PLANAR_U, PLANAR_V };
if (metric == 0)
{
for (p = 0; p < 3; p++)
{
dstp = dst->GetReadPtr(planes[p]);
metp = met->GetWritePtr(planes[p]);
dst_pitch = dst->GetPitch(planes[p]);
met_pitch = met->GetPitch(planes[p]);
height = dst->GetHeight(planes[p]);
row_size = dst->GetRowSize(planes[p]);
dstp += dst_pitch * static_cast<int64_t>(2);
metp += met_pitch * static_cast<int64_t>(2);
dstpp = dstp - dst_pitch;
dstpn = dstp + dst_pitch;
dstppp = dstpp - dst_pitch;
dstpnn = dstpn + dst_pitch;
if (order == 1)
{
metp += met_pitch;
dstp += dst_pitch;
dstpp += dst_pitch;
dstpn += dst_pitch;
dstppp += dst_pitch;
dstpnn += dst_pitch;
}
for (y = 0; y < (height - 4); y += 2)
{
for (x = 0; x < row_size; x++)
{
c1 = (dstp[x] - dstpp[x]);
c2 = (dstp[x] - dstpn[x]);
c = std::abs((dstppp[x] + (dstp[x] << 2) + dstpnn[x]) - 3 * (dstpp[x] + dstpn[x]));
sum += c;
if ((c1 > thr && c2 > thr) || (c1 < -thr && c2 < -thr))
{
metp[x] = c > thr * 6 ? 1 : 0;
}
else
{
metp[x] = 0;
}
}
metp += met_pitch * static_cast<int64_t>(2);
dstp += dst_pitch * static_cast<int64_t>(2);
dstpp += dst_pitch * static_cast<int64_t>(2);
dstppp += dst_pitch * static_cast<int64_t>(2);
dstpn += dst_pitch * static_cast<int64_t>(2);
dstpnn += dst_pitch * static_cast<int64_t>(2);
}
}
}
else
{
for (p = 0; p < 3; p++)
{
dstp = dst->GetReadPtr(planes[p]);
metp = met->GetWritePtr(planes[p]);
dst_pitch = dst->GetPitch(planes[p]);
met_pitch = met->GetPitch(planes[p]);
height = dst->GetHeight(planes[p]);
row_size = dst->GetRowSize(planes[p]);
dstp += dst_pitch;
metp += met_pitch;
dstpp = dstp - dst_pitch;
dstpn = dstp + dst_pitch;
if (order == 0)
{
metp += met_pitch;
dstp += dst_pitch;
dstpp += dst_pitch;
dstpn += dst_pitch;
}
for (y = 0; y < (height - 2); y += 2)
{
for (x = 0; x < row_size; x++)
{
c = (dstpp[x] - dstp[x]) * (dstpn[x] - dstp[x]);
sum += c;
metp[x] = c > thr * thr ? 1 : 0;
}
metp += met_pitch * static_cast<int64_t>(2);
dstp += dst_pitch * static_cast<int64_t>(2);
dstpp += dst_pitch * static_cast<int64_t>(2);
dstpn += dst_pitch * static_cast<int64_t>(2);
}
}
}
sum /= (2.0 * static_cast<double>(src_width)
* static_cast<double>(metric == 0 ? src_height - 6 : src_height - 3));
return metric == 0 ? sum > static_cast<double>(thr2) * 6.0
: sum > static_cast<double>(thr2) * static_cast<double>(thr2);
}
Now for easy reading, I will explain what it does:
1) Calculates the combed values from "dst" pixels.
2) Keeps track of the combed values and returns a check on the average.
3) Stores in "met" pixels the result of the combed detection as 1 if combed and 0 if not for later use.
Probably is something stupid, but I passed already 2 days without luck. Also I tried to attach avspmod to visual studio debugger and when it gets to the point in which avspmod crashes it says that avisynth.dll throws an exception because of an error while trying to access an address.
The script lines that makes it crash is the following:
InvertNeg(edeint=bob().invert(),thr=6)
I will try to also copy here the main code parts so that maybe you don't have to download the project.
This is GetFrame:
PVideoFrame __stdcall InvertNeg::GetFrame(int m, IScriptEnvironment* env) {
int n = m / 2;
int order = child->GetParity(0) ? 1 : 0;
PVideoFrame dst = env->NewVideoFrame(vi);
PVideoFrame src = child->GetFrame(n, env);
PVideoFrame prv = child->GetFrame(n == 0 ? n : n - 1, env);
PVideoFrame nxt = child->GetFrame(n == vi.num_frames - 1 ? n : n + 1, env);
if ( m & 1 )
{
std::int64_t diffC = get_diff(src, src, mode, order, nt, sse);
std::int64_t diffN = get_diff(src, nxt, mode, !order, nt, sse);
field_match(dst, src, nxt, diffC, diffN, !order);
}
else
{
std::int64_t diffC = get_diff(src, src, mode, order, nt, sse);
std::int64_t diffP = get_diff(src, prv, mode, order, nt, sse);
field_match(dst, src, prv, diffC, diffP, order);
}
PVideoFrame met;
bool check = true;
if (m & 1)
{
if (thr < 255 || thr2 < 255)
{
PVideoFrame met = env->NewVideoFrame(vi);
check = calc_combed(dst, met, metric, !order, thr, thr2, src_width, src_height);
}
}
else
{
if (thr < 255 || thr2 < 255)
{
PVideoFrame met = env->NewVideoFrame(vi);
check = calc_combed(dst, met, metric, order, thr, thr2, src_width, src_height);
}
}
if (check && thr2 < 255 && edeint2)
{
PVideoFrame edtb = edeint2->GetFrame(m, env);
copy_frame(dst, edtb);
}
else if (thr < 255 && edeint)
{
if (is_combed(met, metric, order, 4))
{
PVideoFrame edta = edeint->GetFrame(m, env);
copy_frame(dst, edta);
}
}
return dst;
}
Now the bug shows up when this line is executed: if (is_combed(met, metric, order, 4))
The problem with it is the "met" clip as a PVideoframe argument. If I change "met" with another random clip like "src" the bug doesn't show up and all frames are detected as combed as expected.
Now I make another change in the calc_combed() lines and I replace "met" with "src" here as well. The bug shows up again so I'm guessing that calc_combed() does something evil. Here the function:
bool calc_combed(PVideoFrame& dst, PVideoFrame& met, int metric, int order, int thr, int thr2, int src_width, int src_height)
{
unsigned char* metp;
const unsigned char* dstp;
const unsigned char* dstpp;
const unsigned char* dstppp;
const unsigned char* dstpn;
const unsigned char* dstpnn;
int height;
int row_size;
int dst_pitch;
int met_pitch;
double sum = 0;
int p, x, y, c, c1, c2;
int planes[] = { PLANAR_Y, PLANAR_U, PLANAR_V };
if (metric == 0)
{
for (p = 0; p < 3; p++)
{
dstp = dst->GetReadPtr(planes[p]);
metp = met->GetWritePtr(planes[p]);
dst_pitch = dst->GetPitch(planes[p]);
met_pitch = met->GetPitch(planes[p]);
height = dst->GetHeight(planes[p]);
row_size = dst->GetRowSize(planes[p]);
dstp += dst_pitch * static_cast<int64_t>(2);
metp += met_pitch * static_cast<int64_t>(2);
dstpp = dstp - dst_pitch;
dstpn = dstp + dst_pitch;
dstppp = dstpp - dst_pitch;
dstpnn = dstpn + dst_pitch;
if (order == 1)
{
metp += met_pitch;
dstp += dst_pitch;
dstpp += dst_pitch;
dstpn += dst_pitch;
dstppp += dst_pitch;
dstpnn += dst_pitch;
}
for (y = 0; y < (height - 4); y += 2)
{
for (x = 0; x < row_size; x++)
{
c1 = (dstp[x] - dstpp[x]);
c2 = (dstp[x] - dstpn[x]);
c = std::abs((dstppp[x] + (dstp[x] << 2) + dstpnn[x]) - 3 * (dstpp[x] + dstpn[x]));
sum += c;
if ((c1 > thr && c2 > thr) || (c1 < -thr && c2 < -thr))
{
metp[x] = c > thr * 6 ? 1 : 0;
}
else
{
metp[x] = 0;
}
}
metp += met_pitch * static_cast<int64_t>(2);
dstp += dst_pitch * static_cast<int64_t>(2);
dstpp += dst_pitch * static_cast<int64_t>(2);
dstppp += dst_pitch * static_cast<int64_t>(2);
dstpn += dst_pitch * static_cast<int64_t>(2);
dstpnn += dst_pitch * static_cast<int64_t>(2);
}
}
}
else
{
for (p = 0; p < 3; p++)
{
dstp = dst->GetReadPtr(planes[p]);
metp = met->GetWritePtr(planes[p]);
dst_pitch = dst->GetPitch(planes[p]);
met_pitch = met->GetPitch(planes[p]);
height = dst->GetHeight(planes[p]);
row_size = dst->GetRowSize(planes[p]);
dstp += dst_pitch;
metp += met_pitch;
dstpp = dstp - dst_pitch;
dstpn = dstp + dst_pitch;
if (order == 0)
{
metp += met_pitch;
dstp += dst_pitch;
dstpp += dst_pitch;
dstpn += dst_pitch;
}
for (y = 0; y < (height - 2); y += 2)
{
for (x = 0; x < row_size; x++)
{
c = (dstpp[x] - dstp[x]) * (dstpn[x] - dstp[x]);
sum += c;
metp[x] = c > thr * thr ? 1 : 0;
}
metp += met_pitch * static_cast<int64_t>(2);
dstp += dst_pitch * static_cast<int64_t>(2);
dstpp += dst_pitch * static_cast<int64_t>(2);
dstpn += dst_pitch * static_cast<int64_t>(2);
}
}
}
sum /= (2.0 * static_cast<double>(src_width)
* static_cast<double>(metric == 0 ? src_height - 6 : src_height - 3));
return metric == 0 ? sum > static_cast<double>(thr2) * 6.0
: sum > static_cast<double>(thr2) * static_cast<double>(thr2);
}
Now for easy reading, I will explain what it does:
1) Calculates the combed values from "dst" pixels.
2) Keeps track of the combed values and returns a check on the average.
3) Stores in "met" pixels the result of the combed detection as 1 if combed and 0 if not for later use.
Probably is something stupid, but I passed already 2 days without luck. Also I tried to attach avspmod to visual studio debugger and when it gets to the point in which avspmod crashes it says that avisynth.dll throws an exception because of an error while trying to access an address.
The script lines that makes it crash is the following:
InvertNeg(edeint=bob().invert(),thr=6)