View Full Version : Possible MakeWritable bug?
foxyshadis
1st June 2006, 09:07
I'm not familiar enough with the guts of avisynth to even say for sure if this is a bug, but I thought I'd mention it. It's very obvious if you try something like:
blankclip(pixel_type="yv12",color=$808080,width=640,height=320)
addgrain(200,0,0)
t=mipsmooth().pointresize(width*2,height*2)
u=mipsmooth().pointresize(width*2,height*2)
interleave(t,u)
The first two frames should be exactly the same, but instead addgrain is called twice, once for each mipsmooth. When you remove mipsmooth, all is as expected again.
It only seems to occur on the first frame access, after that it works as expected (so far). So it doesn't seem to be a major problem.
AddGrain and such "random" filters are the only ones it would probably show with. Thanks to Didée for pointing it out. It could just be an AddGrain bug, but the code looks normal enough to me (not that I'm any kind of expert).
Testing some more, this code:
blankclip(pixel_type="yv12",color=$808080,width=640,height=320)
o=last
addgrain(200,0,0)
t=mt_makediff(last,o)
u=mt_makediff(last,o)
mt_makediff(t,u).greyscale
Is problematic for the first two frames and occurs at random intervals afterward.
Avisynth is 2.57a3.
squid_80
1st June 2006, 11:07
Thank god I'm not imagining things! I've seen this too, but have never been able to trim it down to a sensible script to report. The full mess looks like this:
cropx=92
cropy=2
source=mpeg2source("new.d2v")
croppedsourcetemp=crop(source, cropx, 0, -cropx, -0)
croppedsource=crop(croppedsourcetemp, 0, cropy, -0, -cropy)
tfmtemp=tfm(source, order=1, mode=3)
tfmsource=crop(tfmtemp, cropx, cropy, -cropx, -cropy)
tenlogo=imagereader(file="C:\temp\wmarks\ten new.bmp", end=source.framecount, fps=25)
tenlogomask=levels(tenlogo, 0, 1, 16, 0, 255, false)
tenlogomask2=levels(tenlogo, 0, 1, 64, 0, 90, false)
tentfmnewsource=overlay(tfmsource, tenlogo, 524-cropx, 462-cropy, tenlogomask, 1, "subtract")
tentfmnewlogosource=crop(tentfmnewsource, 524-cropx, 462-cropy, tenlogomask.width, tenlogomask.height)
tentfmnew2source=overlay(tentfmnewsource, tentfmnewlogosource, 524-cropx, 462-cropy, tenlogomask2, mode="add")
tentfmnew2logosource=crop(tentfmnew2source, 524-cropx, 462-cropy, tenlogomask.width, tenlogomask.height).blur(.3)
tentfmsource=overlay(tentfmnew2source, tentfmnew2logosource, 524-cropx, 462-cropy, tenlogomask, mode="blend")
tennewsource=overlay(croppedsource, tenlogo, 524-cropx, 462-cropy, tenlogomask, 1, "subtract")
tennewlogosource=crop(tennewsource, 524-cropx, 462-cropy, tenlogomask.width, tenlogomask.height)
tennewsource=overlay(tennewsource, tennewlogosource, 524-cropx, 462-cropy, tenlogomask2, mode="add")
tennewlogosource=crop(tennewsource, 524-cropx, 462-cropy, tenlogomask.width, tenlogomask.height).blur(.3)
tensource=overlay(tennewsource, tennewlogosource, 524-cropx, 462-cropy, tenlogomask, mode="blend")
(this is a logo removal script, btw. Maybe not very clean but it does the job pretty well.)
Sometimes I return tentfmsource and the logo is always removed as expected; when I don't need field matching I return tensource and sometimes the logo is too dark from the levels functions being called twice. Pressing F2 in virtualdub to reload sometimes fixes it. Sometimes I start pulling my hair out because it just won't behave.
No bug, but undesirable behaviour!
Filters are expected to return exactly the same output frame every time the same frame number is requested, otherwise you will get unpredicatable behaviour depending on when the cache hits or misses. AddGrain could re-seed it's random number generator with the frame number on each GetFrame call to implement this expectation.
The cache has some learning ability where it notices if vfb's are being modified then re-requested a subsequent time. When it notices this behaviour it will lock the vfb for the first N callers to prevent it being modified and having to regenerate the frame. The last caller receives the vfb unlocked and may modify it. It requires N cache accesses to trigger this protection, N being 2 in foxyshadis case. By thrashing the cache very hard random frames may also experience this problems.
@Squid,
For your script I see no indeterminate filter, ( I assume tfm() is well behaved :confused: ), there may be a bug with some filter not correctly using GetWritePtr(). Can you prune the script down to a simpler case that demonstates the problem.
squid_80
3rd June 2006, 03:20
OK, let's try this.
source=colorbars()
versionclip=version()
logomask=levels(versionclip, 0, 1, 16, 0, 255, false)
#a=overlay(source, versionclip, 0, 0, logomask, 1, "subtract").crop(0,0,logomask.width,logomask.height)
b=overlay(source, versionclip, 0, 0, logomask, 1, "subtract").crop(0,0,logomask.width,logomask.height)
return b
Load into virtualdub, remove the #'s from the script, save and reload. The image should change slightly, if it doesn't hit F2 a few times. Alternatively remove the comments and replace return b with stackvertical(a,b) and note the differences.
@Squid,
It won't go wrong for me :confused:
The vfb from Version is static so the makewritable in Levels always blits a new frame for logomask. Overlay always converts to YV24 on the way in and converts back on the way out so again a and b are always new vfb's, source is only ever read as is versionclip :confused: :confused: :confused:
squid_80
3rd June 2006, 04:48
I knew this would happen.
Here's what it looks like when I replace return b with stackvertical(a,b) (just to prove I'm not making it up):
http://img455.imageshack.us/img455/4349/avserror7dd.png (http://imageshack.us)
Can anyone else reading this thread see this or is it completely isolated to my machine?
Guest
3rd June 2006, 05:06
I can't duplicate your result in 2.56.
Guest
3rd June 2006, 05:13
Whoa! After I hit F2 twice I got your result.
squid_80
3rd June 2006, 05:15
Hooray, I'm not crazy!
Is this specific to Overlay() with operator "Subtract"?
What CPU are you using?
Could it be a static in the MMX code leaking between the 2 instances?
squid_80
3rd June 2006, 06:48
Definitely an overlay bug, not specific to subtract. This simpler script exhibits similar behaviour:
a=overlay(colorbars(), version()).crop(0,0,436,80)
b=overlay(colorbars(), version()).crop(0,0,436,80)
stackvertical(a,b)
Different modes for each overlay call can be used and the problem still shows. CPU is AMD64, but I don't think it matters since when the script ends with return b we're not even running MMX code before the second overlay call.
squid_80
5th July 2006, 11:20
EUREKA!
Found this bug in overlay.cpp:
Overlay::Overlay(PClip _child, AVSValue args, IScriptEnvironment *env) :
GenericVideoFilter(_child) {
// Make copy of the VideoInfo
inputVi = (VideoInfo*)malloc(sizeof(VideoInfo));
memcpy(inputVi, &vi, sizeof(VideoInfo));
mask = 0;
opacity = (int)(256.0*args[ARG_OPACITY].AsFloat(1.0)+0.5);
offset_x = args[ARG_X].AsInt(0);
offset_y = args[ARG_Y].AsInt(0);
overlay = args[ARG_OVERLAY].AsClip();
overlayVi = overlay->GetVideoInfo();
overlayConv = SelectInputCS(&overlayVi, env);
if (!overlayConv) {
env->ThrowError("Overlay: Overlay image colorspace not supported.");
}
greymask = args[ARG_GREYMASK].AsBool(true); // Grey mask, default true
ignore_conditional = args[ARG_IGNORE_CONDITIONAL].AsBool(false); // Don't ignore conditionals by default
full_range = args[ARG_FULL_RANGE].AsBool(false); // Maintain CCIR601 range when converting to/from RGB.
SelectInputCS chooses which RGB->444 function to use (standard or NonCCIR601) based on the full_range variable - which isn't initialised until later.
Edit: Ah, it appears this is already fixed in 2.6 :)
@Squid, Thank's, will also fix for 2.5.7
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.