Log in

View Full Version : Obscure avisynth 2.5.6 error (possibly cache bug)


foxyshadis
23rd October 2005, 16:26
I'm sorry about how long this will be, I cut it down as much as possible. I found that it only occurs when these four function calls in a row are made, removing any of them leaves a working script.


SetMemoryMax(280)
#x=directshowSource("cb_cache.avi")
x=aviSource("cb_cache.avi")

x=x.fx_unblend(16,43).fx_unblend(127,189)\
.fx_unblend(258,275).fx_unblend2(311,316)

return x


# call with frame1 being 3 before first double-blend
function fx_unblend(clip c, int frame1, int frame2) {
clip1 = c.trim(0,frame1-1)
clip2 = c.trim(frame2+1,0)
main = c.trim(frame1,frame2)
keep = main.selectevery(5,0,1,2)
tomask = main.selectevery(5,0,2).deleteframe(0)
deblend = main.selectevery(5,3,4)

# refers to where in the cycle frame falls,
#first is 1, 4 & 5 are the blends
frame4 = deblend
frame5 = deblend.trim(1,0)
sframe3 = tomask
sframe6 = tomask.trim(1,0)

# experimental crap
subframe1 = yv12subtract(sframe3,frame4,u=3,v=3) \
.coloryuv(off_y=2,off_u=0,off_v=0)
subframe2 = yv12subtract(sframe6,frame5,u=3,v=3) \
.coloryuv(off_y=2,off_u=0,off_v=0)
frame1add = frame4.yv12subtract(subframe1,u=3,v=3)
frame2add = frame5.yv12subtract(subframe2,u=3,v=3)

# ERROR Uncomment last "deblended" to see strange
# behavior, comment it out to go back to normal
deblended = sxs(frame1add,frame2add,2).selectevery(2)
deblended = sxs(frame1add,subframe2,2).selectevery(2)
deblended = sxs(frame1add,subframe1,2).selectevery(2)

final = interleave(keep.selectevery(3,0), \
keep.selectevery(3,1),keep.selectevery(3,2), \
deblended,deblended)
return clip1 + final + clip2
}

# Added ONLY for ease of debugging, call can be \
replaced with fx_unblend() and artifacts still show.
function fx_unblend2(clip c, int frame1, int frame2) {
clip1 = c.trim(0,310)
clip2 = c.trim(317,0)
main = c.trim(311,316)
keep = main.selectevery(5,0,1,2)
tomask = main.selectevery(5,0,2).deleteframe(0)
deblend = main.selectevery(5,3,4)

# refers to where in the cycle frame falls,
#first is 1, 4 & 5 are the blends
frame4 = deblend
frame5 = deblend.trim(1,0)
sframe3 = tomask
sframe6 = tomask.trim(1,0)

# experimental crap
subframe1 = yv12subtract(sframe3,frame4,u=3,v=3) \
.coloryuv(off_y=2,off_u=0,off_v=0)
subframe2 = yv12subtract(sframe6,frame5,u=3,v=3) \
.coloryuv(off_y=2,off_u=0,off_v=0)
frame1add = frame4.yv12subtract(subframe1,u=3,v=3)
frame2add = frame5.yv12subtract(subframe2,u=3,v=3)

# ERROR Uncomment last "deblended" to see strange behavior,
#comment it out to go back to normal
deblended = sxs(frame1add,frame2add,2).selectevery(2)
deblended = sxs(frame1add,subframe2,2).selectevery(2)
deblended = sxs(frame1add,subframe1,2).selectevery(2)

final = interleave(keep.selectevery(3,0), \
keep.selectevery(3,1),keep.selectevery(3,2), \
deblended,deblended)
# final shows errors, clip2 includes frames it should not when
# first fn's deblended is uncommented (this one's does change it)
return final
return clip2
#return clip1 + final + clip2
}

# view two clips side-by-side, 3rd parameter defines window:
# 0: left 1: center (default) 2: right
function SXS (clip "_c1", clip "_c2", int "_scale") {
_scale = default(_scale,1)
_w1 = select(_scale,0,Width(_c1)/4,Width(_c1)/2)
_w2 = width(_c1) / 2
return Stackhorizontal(_c1.crop(_w1,0,_w2,0), \
_c2.crop(_w1,0,_w2,0))
}


Download clip. (http://foxyshadis.slightlydark.com/random/cb_cache.avi)

You go to frame 3 (614 without the trim), you'll see the white artifacts, and if you output clip2 instead of final, it has extra frames that it shouldn't. Add hashes in front of the last 'deblended' definition in the first function, and the output of the second is then entirely as it should be. All it's doing is changing what gets viewed. I feel like I'm working with Schrodinger's Cat trying to debug this, I don't have the tools to go any further.

Of interest: You can add function calls with other random frame ranges in between the ones in there, doesn't seem to make a difference. (Unless you hit one that does.) You can delete any of the calls, and the last one will be perfect. You can take the second function (fx_deblend2) out if you want to see all frames. It happens somewhat randomly, mostly I notice it happen just like this, sometimes it's with frame2add/subframe2, and sometimes frame1add/frame2add (=the output, thus broken function).

Oh yeah: I can't get the most obvious artifact to show with directshowsource. Probably shifts frames around a bit. But the extra clip2 frames are there. I originally hit it with dgdecode so it's likely input agnostic.

I'm going to go take some advil now.

IanB
23rd October 2005, 16:56
Please EDIT you code block to wrap all the really long lines. (This vBulletin 3.0.7 sucks)

Please confess the contents of your pluggin directory.

Elic
23rd October 2005, 17:17
Hmm... Can you please also upload (or give links to) functions: InterleaveEvery(), repeateveryframe(), yv12subtract() and trim2()? Without them, I cannot run your script :(
I use Avisynth 2.5.6 from yesterday and I'm interesting on its new features and new bugs/incompatibilities also :)

Elic
23rd October 2005, 20:11
Oh, I'm so sorry. I forgot about magical "search" word :(
InterleaveEvery(), repeateveryframe() (http://www.avisynth.org/stickboy/ApplyEvery.zip), trim2() (http://www.avisynth.org/stickboy/jdl-util.avsi), yv12subtract() (http://jourdan.madism.org/~manao/MaskTools-v1.5.4.zip) - are they OK?

Edit:
foxyshadis
I have repeated experience with script, and I got damaged frames even if 5th line of above script is looking likex=x.fx_unblend(16,43) #.fx_unblend(127,189).fx_unblend(258,275).fx_unblend2(311,316)Maybe this happens because I have relatively low amount of physical memory (256 Megs)?
I got clip looking like this in attachment - see frames 19-20, 24-25 and so on. Is it the same damage you are talking about?

foxyshadis
23rd October 2005, 23:53
I'm so sorry, Elic, I was too tired to remember to post those. Masktools is actually 1.5.8 (http://manao4.free.fr/MaskTools-v1.5.8.zip).

Ian, edited. Contents of plugin folder: applyevery.dll, jdl-util.avsi, masktools.dll. (ie, removed everything else.) I'm going to try eliminating the applyevery/trim2 dependancies and see what happens, and also use an older version of masktools.

The artifacts will look like really ugly white hotspots around the left image that don't show up using one of the other sxs lines.

Okay, trim2 does affect it. All but the very first trim2 can be taken out and the result isn't affected, but the first does. And Elic, you're right, the artifacts do appear in all the others, they're just not as obvious as the one I highlighted, so I guess I was wrong about all 4 being necessary. Also the first few yv12subtracts can be replaced with:

subframe1 = frame4
subframe2 = frame5
frame1add = sframe3
frame2add = sframe6

And it still affects the final clip but not any of the ones just using that frame.

It does occur in older versions of masktools.

IanB
24th October 2005, 01:44
Thanks for trimming the code lines, much more readable. I wish everyone would do the same when they post.

Please post this minimalist script that still shows the bug. And keep posting each more distilled versions. (Avisynth is a hugh project so narrowing the script helps bigtime)

Also version of applyevery.dll and jdl-util.avsi?

And does converting jdl trim2's to the equivalent fundamental trim's keep showing the problem?

foxyshadis
24th October 2005, 02:38
Actually I edited the first script, didn't want to repost the script each time, if you'd rather I could. Versions are whatever's on his site, I just got the the other day. Only one trim2's left, taking it out leaves normal output. (Or shifts the problem around, I haven't gone looking for it to reappear.) I also figured out how to get rid of applyevery using interleave().

stickboy
24th October 2005, 02:41
and if you output clip2 instead of final, it has extra frames that it shouldn't.It wouldn't surprise me if I screwed up my implementation of InterleaveEvery. I fixed some off-by-one errors a few months ago, but maybe it's still broken.

Edit:
Okay, if you're still getting extra frames after replacing InterleaveEvery with Interleave, then that's relieving. But I doubt Trim2 would be problematic...

stickboy
24th October 2005, 03:04
By the way, what are the extra frames? It'll be easier to debug the extra frame problem if you replace the AVISource call with:
BlankClip(length=321, pixel_type="yv12").ShowFrameNumber()What are the frames you expect clip2 to have, and what are the frames you actually get?

foxyshadis
24th October 2005, 03:05
I've done some more testing and it seems I was incorrect, it only occurs if both yv12subtract and that first trim2 are present. Editing again.

clip2 should have 317-320 ( clip2=c.trim(316+1,0) ), it has 311-321. (Good idea on framenumber, I'll try that.) Also got rid of that extra frame thing.

I replaced the trims in the second part with:
clip1 = c.trim(0,310)
clip2 = c.trim(317,0)
main = c.trim(311,316)
and still get 311-320.

Edit, doh, if the input's bad of course the output range would be wrong, I'll scan the entire clip and see where dups are coming from, since I really doubt trim would cause those problems.

All of the ones that cause an effect seem to be (frame2 - frame1) % 5 = 2. I'm pretty sure it's because of interleave, let me try to sort out why. Wait, maybe not, since commenting out the sxs call still makes proper output. hmm. If the last sxs is uncommented, it causes the two frames after frame2 to get the sxs treatment and get included in final, which is why two extra frames keep getting padded after each call. Commenting that last one out it resumes as it should from frame2.

Since I've sorted out why clip2 has extra and the frame changes, the second copy of the function is probably superfluous now, in fact it only needs the first call. I can remove it if it's just cluttering things up.

Wait, I did remove the last trim2 and now it shows the bad behavior after all. I think I originally converted it to trim incorrectly, very sorry about that.

IanB
29th October 2005, 07:43
Okay,

What H264 VFW codec are you using? Does is support frame exact seeking correctly?

Do you still get the problem withX=BlankClip(321, 352, 240, pixel_type="YV12").ShowFrameNumber()as your clip source?

Can you post the current absolute minimum script that shows the problem. Leave out all the side by side junk and the commented out statments, just the statments that contribute to the problem. For this exact script state exactly what you see and exactly what you expected to see.

foxyshadis
30th October 2005, 02:34
Yes, most of my last comment was based on blankclip+framenumber.

I'll see if I can further pare it down this weekend.

IanB
6th November 2005, 07:09
Any news?

foxyshadis
6th November 2005, 09:10
It seems that 2.56a changed some things, it no longer seems to have that weird different behavior. I guess it must have fixed something related. It's still not doing necessarily what I expect, but that might be caused by a bad assumption about selectevery and interleave, so that aspect might be my fault.

For reference here's the code I was using:

SetMemoryMax(280)
x=BlankClip(length=30, pixel_type="yv12").ShowFrameNumber()

x=x.fx_unblend(16,18)

return x


function fx_unblend(clip c, int frame1, int frame2) {
clip1 = c.trim(0,frame1-1)
clip2 = c.trim(frame2+1,0)
main = c.trim(frame1,frame2)
keep = main.selectevery(5,0,1,2)
tomask = main.selectevery(5,0,2).deleteframe(0)
deblend = main.selectevery(5,3,4)

frame4 = deblend
frame5 = deblend.trim(1,0)
sframe3 = tomask
sframe6 = tomask.trim(1,0)

subframe1 = yv12subtract(sframe3,frame4,u=3,v=3) \
.coloryuv(off_y=2,off_u=0,off_v=0)
subframe2 = yv12subtract(sframe6,frame5,u=3,v=3) \
.coloryuv(off_y=2,off_u=0,off_v=0)
frame1add = frame4.yv12subtract(subframe1,u=3,v=3)
frame2add = frame5.yv12subtract(subframe2,u=3,v=3)

deblended = sxs(frame4,frame5,2).selectevery(2)
#deblended = sxs(frame1add,subframe1,2).selectevery(2) #uncomment

final = interleave(keep.selectevery(3,0), \
keep.selectevery(3,1),keep.selectevery(3,2), \
deblended,deblended)
return clip1 + final + clip2
}

function SXS (clip "_c1", clip "_c2", int "_scale") {
_scale = default(_scale,1)
_w1 = select(_scale,0,Width(_c1)/4,Width(_c1)/2)
_w2 = width(_c1) / 2
return Stackhorizontal(_c1.crop(_w1,0,_w2,0),_c2.crop(_w1,0,_w2,0))
}

IanB
6th November 2005, 12:22
For this exact script state exactly what you see and exactly what you expected to see. :confused:

IanB

foxyshadis
6th November 2005, 15:20
^^; sorry.

I expected written frame numbers to increase identically to the actual frame #. Instead two double-18 are written and continues at 19 on frame 21. (It should have skipped the doubling completely.)

gzarkadas
6th November 2005, 20:00
Hi,

I think I have found what happens. The "deblend.SelectEvery(5,3,4)" returns a two frame-clip (for the specific argument's combination) while it should return a zero frame-clip if a do-not-return-frames-past-the-end behavior was honored.

See the comments on the script below (despite the formatting changes, it is the same logic). Each clip's frames are marked with their original framenumbers inside brackets. Frames from SXS output are marked as {number left|number right}.


LoadPlugin("masktools.dll")

function SXS(clip "_c1", clip "_c2", int "_scale")
{
_scale = Default(_scale, 1)
_w1 = Select(_scale, 0, _c1.Width / 4, _c1.Width / 2)
_w2 = _c1.Width / 2
return StackHorizontal( \
_c1.Crop(_w1, 0, _w2, 0), \
_c2.Crop(_w1, 0, _w2, 0) )
}

function fx_unblend(clip c, int frame1, int frame2)
{
clip1 = c.Trim(0, frame1 - 1) # [ 0..15]
clip2 = c.Trim(frame2 + 1, 0) # [19..29]
main = c.Trim(frame1, frame2) # [16..18]
keep = main.SelectEvery(5, 0, 1, 2) # [16,17,18]
tomask = main.SelectEvery(5, 0, 2).DeleteFrame(0) # {16,}18 - > [18]
deblend = main.SelectEvery(5, 3, 4) # [] ? 2 frames [18,18]

# return deblend (returns the two un-antisipated frames
# Assert(deblend.Framecount == 0, String(deblend.Framecount))

frame4 = deblend # [] ? [18,18]
frame5 = deblend.Trim(1,0) # [] ? [18]
sframe3 = tomask # [18]
sframe6 = tomask.Trim(1,0) # [] ? [18]

subframe1 = YV12Subtract(sframe3, frame4, \
u=3, v=3).ColorYUV(off_y=2, off_u=0, off_v=0) # [18,18]
subframe2 = YV12Subtract(sframe6, frame5, \
u=3, v=3).ColorYUV(off_y=2, off_u=0, off_v=0) # [18]
frame1add = frame4.YV12Subtract(subframe1, u=3, v=3) # [18,18]
frame2add = frame5.YV12Subtract(subframe2, u=3, v=3) # [18]
deblended = SXS(frame4, frame5, 2) # 2 fr.(by frame4) [18|18,18|18]
deblended = deblended.SelectEvery(2) # [18|18], 1 frame
# deblended = sxs(frame1add,subframe1,2).selectevery(2) #uncomment

final = Interleave( \
keep.SelectEvery(3,0), \
keep.SelectEvery(3,1), \
keep.SelectEvery(3,2), \
deblended, \
deblended )
# keep.SelectEvery(3,0) -> 1 frames [16]
# keep.SelectEvery(3,1) -> 1 frames [17]
# keep.SelectEvery(3,2) -> 1 frames [18]
# deblended -> 1 frames [18|18]
# deblended -> 1 frames [18|18]
# final -> 5 frames [16,17,18,18|18,18|18]
return clip1 + final + clip2
# [0..15] + [16,17,18,18|18,18|18] + [19..29] ,ie 16 + 5 + 11 = 32 frames
}

SetMemoryMax(280)
x = BlankClip(length=30, pixel_type="yv12").ShowFrameNumber()
x = x.fx_unblend(16, 18)
return x


I must admit though, that it does not seem to me as Avisynth's error; merely as a need to document better the filter's behavior in end-limits input.

Also, the Trims just below have trouble if they receive a clip with just one frame; IMHO an assertion to dissallow frame2 - frame1 to go below 4 and also coding the end frames of Trims as negative values (say to guard against frame1=1) is necessary to make the function robust.

Hope I have helped.

foxyshadis
7th November 2005, 05:41
Thanks for pointing out my error there, I thought something like that might have been occuring when it happened both ways. In the original, there were a lot more checks; this version is almost useless it's so cut down. I guess I just ran into a corner case I didn't recognize properly (the expansion and contraction of clips when two of different sizes are compared) and thus didn't build checks around. I guess that explains some of the bizarre results I would get.

Apologies for wasting you guys' time then.