View Full Version : MaskTools2 - pfmod
Pages :
1
2
3
4
[
5]
6
7
8
9
burfadel
15th September 2017, 23:21
Open source means you can use it, as long as you don't charge for borrowed code and you acknowledge the source. Maybe some of the legacy support code can be removed, particularly if it is impinging in any way. The 64 bit avisynth shouldn't have any of the 32 bit compatibility stuff since you can't use those filters. Maybe all the compatibility code that is still valid but not useful for most modern filters can be moved to a plugin, no point limiting Avisynth with unuseful constraints.
real.finder
16th October 2017, 14:57
hi pinterf
check this https://forum.doom9.org/showthread.php?t=174752
and what about adding mt_merge parameter (https://forum.doom9.org/showthread.php?p=1804907#post1804907) for mpeg2 vs mpeg1 in 420 with luma=true?
any news? LSFmod port depends on that
burfadel
9th November 2017, 05:54
It seems that maybe the scaling feature doesn't work as intended. I was using mt_lut with range of 256, with bit depth 12, and the result was as if there was no scaling (all black). If I convert back to 8 bit first, run it, and then convert back to 12 bits it works properly.
pinterf
9th November 2017, 08:47
It seems that maybe the scaling feature doesn't work as intended. I was using mt_lut with range of 256, with bit depth 12, and the result was as if there was no scaling (all black). If I convert back to 8 bit first, run it, and then convert back to 12 bits it works properly.
What was your expression string? Constants inside expressions are scaled only when you specify scaleb or scalef for them.
real.finder
15th November 2017, 18:43
so, since the expr is added to avs+, are you going to make mt_lut* use it with some option (https://github.com/pinterf/masktools/issues/1#issuecomment-340471206) or it's not possible?
pinterf
15th November 2017, 20:49
I was just thinking about it while rideing homeward. Sure, it won't be a default behaviour.
It has performance penalty. Scaling inputs to a common range requires a floating multiplication within the expression, right after reading the source pixels, unless the common bitdepth is the same as source clip bitdepth. I suppose - knowing that this behaviour was requested because of the easy conversion of old scripts - that this common bit depth is in 8 bit scale 0-255. So for 16 bit input clips the multiplier is 1/256. For 8 bit input, there is no performance loss in this scenario.
A second conversion occurs before storing the result back.
Another ambiguity comes on whether the source is a limited range yuv or full scale. Limited range can nicely be scaled by bit shift method, but this method will give wrong results if we use it on a full scale source.
Other.
In Expr not all operators/functions are implemented, there are masktools-only syntax elements. Do you know scripts that are using these operators? Modulo, sin, cos, all kinds of rounding?
edcrfv94
15th November 2017, 21:39
You can try this first, mt_lut at 16bit still faster than Expr 10% speed.
Function kf_expr_x(clip clip1, string "expr", string "yExpr", string "uExpr", string "vExpr", string "aExpr", int "Y", int "U", int "V", int "A", bool "sse2", bool "avx2", bool "optSSE2", bool "optSingleMode", bool "optAvx2")
{
sCSP = clip1.kf_GetCSP()
IsY8 = sCSP == "Y8"
IsRGBA = sCSP == "RGBA"
sBit = clip1.BitsPerComponent()
use_mt_expr = (sBit == 8)
yExpr = Default(yExpr, expr)
uExpr = Default(uExpr, yExpr)
vExpr = Default(vExpr, yExpr)
aExpr = Default(aExpr, yExpr)
optSSE2 = Default(optSSE2, sse2)
optAvx2 = Default(optAvx2, avx2)
Y = Default(Y, 3)
U = Default(U, 1)
V = Default(V, 1)
A = Default(A, 1)
yExpr = (Y == 3) ? yExpr : ""
uExpr = (U == 3) ? uExpr : ""
vExpr = (V == 3) ? vExpr : ""
aExpr = (A == 3) ? aExpr : ""
out = use_mt_expr ? mt_lut(clip1, expr=expr, yExpr=yExpr, uExpr=uExpr, vExpr=vExpr, aExpr=aExpr, Y=Y, U=U, V=V, A=A, sse2=sse2, avx2=avx2)
\ : IsY8 ? Expr(clip1, yExpr, optSSE2=optSSE2, optSingleMode=optSingleMode, optAvx2=optAvx2)
\ : !IsRGBA ? Expr(clip1, yExpr, uExpr, vExpr, optSSE2=optSSE2, optSingleMode=optSingleMode, optAvx2=optAvx2)
\ : Expr(clip1, yExpr, uExpr, vExpr, aExpr, optSSE2=optSSE2, optSingleMode=optSingleMode, optAvx2=optAvx2)
return out
}
Function kf_expr_xy(clip clip1, clip clip2, string "expr", string "yExpr", string "uExpr", string "vExpr", string "aExpr", int "Y", int "U", int "V", int "A", bool "sse2", bool "avx2", bool "optSSE2", bool "optSingleMode", bool "optAvx2")
{
sCSP = clip1.kf_GetCSP()
IsY8 = sCSP == "Y8"
IsRGBA = sCSP == "RGBA"
sBit = clip1.BitsPerComponent()
use_mt_expr = (sBit == 8)
yExpr = Default(yExpr, expr)
uExpr = Default(uExpr, yExpr)
vExpr = Default(vExpr, yExpr)
aExpr = Default(aExpr, yExpr)
optSSE2 = Default(optSSE2, sse2)
optAvx2 = Default(optAvx2, avx2)
Y = Default(Y, 3)
U = Default(U, 1)
V = Default(V, 1)
A = Default(A, 1)
yExpr = (Y == 3) ? yExpr : ""
uExpr = (U == 3) ? uExpr : ""
vExpr = (V == 3) ? vExpr : ""
aExpr = (A == 3) ? aExpr : ""
out = use_mt_expr ? mt_lutxy(clip1, clip2, expr=expr, yExpr=yExpr, uExpr=uExpr, vExpr=vExpr, aExpr=aExpr, Y=Y, U=U, V=V, A=A, sse2=sse2, avx2=avx2)
\ : IsY8 ? Expr(clip1, clip2, yExpr, optSSE2=optSSE2, optSingleMode=optSingleMode, optAvx2=optAvx2)
\ : !IsRGBA ? Expr(clip1, clip2, yExpr, uExpr, vExpr, optSSE2=optSSE2, optSingleMode=optSingleMode, optAvx2=optAvx2)
\ : Expr(clip1, clip2, yExpr, uExpr, vExpr, aExpr, optSSE2=optSSE2, optSingleMode=optSingleMode, optAvx2=optAvx2)
return out
}
Function kf_expr_xyz(clip clip1, clip clip2, clip clip3, string "expr", string "yExpr", string "uExpr", string "vExpr", string "aExpr", int "Y", int "U", int "V", int "A", bool "sse2", bool "avx2", bool "optSSE2", bool "optSingleMode", bool "optAvx2")
{
sCSP = clip1.kf_GetCSP()
IsY8 = sCSP == "Y8"
IsRGBA = sCSP == "RGBA"
sBit = clip1.BitsPerComponent()
use_mt_expr = (sBit == 8)
yExpr = Default(yExpr, expr)
uExpr = Default(uExpr, yExpr)
vExpr = Default(vExpr, yExpr)
aExpr = Default(aExpr, yExpr)
optSSE2 = Default(optSSE2, sse2)
optAvx2 = Default(optAvx2, avx2)
Y = Default(Y, 3)
U = Default(U, 1)
V = Default(V, 1)
A = Default(A, 1)
yExpr = (Y == 3) ? yExpr : ""
uExpr = (U == 3) ? uExpr : ""
vExpr = (V == 3) ? vExpr : ""
aExpr = (A == 3) ? aExpr : ""
out = use_mt_expr ? mt_lutxyz(clip1, clip2, clip3, expr=expr, yExpr=yExpr, uExpr=uExpr, vExpr=vExpr, aExpr=aExpr, Y=Y, U=U, V=V, A=A, sse2=sse2, avx2=avx2)
\ : IsY8 ? Expr(clip1, clip2, clip3, yExpr, optSSE2=optSSE2, optSingleMode=optSingleMode, optAvx2=optAvx2)
\ : !IsRGBA ? Expr(clip1, clip2, clip3, yExpr, uExpr, vExpr, optSSE2=optSSE2, optSingleMode=optSingleMode, optAvx2=optAvx2)
\ : Expr(clip1, clip2, clip3, yExpr, uExpr, vExpr, aExpr, optSSE2=optSSE2, optSingleMode=optSingleMode, optAvx2=optAvx2)
return out
}
Function kf_expr_xyza(clip clip1, clip clip2, clip clip3, clip clip4, string "expr", string "yExpr", string "uExpr", string "vExpr", string "aExpr", int "Y", int "U", int "V", int "A", bool "sse2", bool "avx2", bool "optSSE2", bool "optSingleMode", bool "optAvx2")
{
sCSP = clip1.kf_GetCSP()
IsY8 = sCSP == "Y8"
IsRGBA = sCSP == "RGBA"
sBit = clip1.BitsPerComponent()
use_mt_expr = (sBit == 8)
yExpr = Default(yExpr, expr)
uExpr = Default(uExpr, yExpr)
vExpr = Default(vExpr, yExpr)
aExpr = Default(aExpr, yExpr)
optSSE2 = Default(optSSE2, sse2)
optAvx2 = Default(optAvx2, avx2)
Y = Default(Y, 3)
U = Default(U, 1)
V = Default(V, 1)
A = Default(A, 1)
yExpr = (Y == 3) ? yExpr : ""
uExpr = (U == 3) ? uExpr : ""
vExpr = (V == 3) ? vExpr : ""
aExpr = (A == 3) ? aExpr : ""
out = use_mt_expr ? mt_lutxyza(clip1, clip2, clip3, clip4, expr=expr, yExpr=yExpr, uExpr=uExpr, vExpr=vExpr, aExpr=aExpr, Y=Y, U=U, V=V, A=A, sse2=sse2, avx2=avx2)
\ : IsY8 ? Expr(clip1, clip2, clip3, clip4, yExpr, optSSE2=optSSE2, optSingleMode=optSingleMode, optAvx2=optAvx2)
\ : !IsRGBA ? Expr(clip1, clip2, clip3, clip4, yExpr, uExpr, vExpr, optSSE2=optSSE2, optSingleMode=optSingleMode, optAvx2=optAvx2)
\ : Expr(clip1, clip2, clip3, clip4, yExpr, uExpr, vExpr, aExpr, optSSE2=optSSE2, optSingleMode=optSingleMode, optAvx2=optAvx2)
return out
}
Function kf_GetCSP(clip c)
{
try {
csp = c.kf_GetCSP_avsPlus()
} catch (error_msg) {
csp = c.kf_GetCSP_avs()
}
return csp
}
Function kf_GetCSP_avs(clip c)
{
return c.IsPlanar ? c.IsYV12 ? "YV12" :
\ c.IsYV16 ? "YV16" :
\ c.IsYV24 ? "YV24" : c.kf_GetCSP_Y8_YV411() :
\ c.IsYUY2 ? "YUY2" :
\ c.IsRGB32 ? "RGB32" :
\ c.IsRGB24 ? "RGB24" : "Unknown"
Function kf_GetCSP_Y8_YV411(clip c) {
try {
c.UtoY
csp = "YV411"
} catch (error_msg) {
csp = "Y8"
}
return csp
}
}
Function kf_GetCSP_avsPlus(clip c)
{
return c.Is420 ? "YV12" :
\ c.IsY ? "Y8" :
\ c.Is422 ? "YV16" :
\ c.Is444 ? "YV24" :
\ c.IsYUVA ? "YUVA" :
\ c.IsYV411 ? "YV411" :
\ c.IsYUY2 ? "YUY2" :
\ c.IsRGB32 ? "RGB32" :
\ c.IsRGB24 ? "RGB24" :
\ c.IsPlanarRGB ? "RGB" :
\ c.IsPlanarRGBA ? "RGBA" :
\ c.IsPackedRGB ? "RGBIL" : "Unknown"
}
real.finder
15th November 2017, 21:54
In Expr not all operators/functions are implemented, there are masktools-only syntax elements. Do you know scripts that are using these operators? Modulo, sin, cos, all kinds of rounding?
well, I can't count all scripts, and aside from those in wiki there are many that not listed there, and they are more than these in wiki
so for safe choice, useexpr parameter should be:-
useexpr="internal" or "none" (default)
so anyone update some function that has mt_lut* can make it faster if it possible by set it to "internal", and the "internal" will be "none" automatically if normal avs or old avs+ is used
aside from that now, maybe in future if someone update the clexpr (https://github.com/tp7/CLExpr), then it will be another options with "internal" and "none"
real.finder
15th November 2017, 22:01
You can try this first, mt_lut at 16bit still faster than Expr 10% speed.
didn't try it but what about RAM usage :devil:?
edcrfv94
15th November 2017, 22:08
didn't try it but what about RAM usage :devil:?
Almost no different, mt_lut at 16bit use 1mb ram more than Expr.
pinterf
16th November 2017, 09:43
You can try this first, mt_lut at 16bit still faster than Expr 10% speed.
I think it depends on the expression itself. What expression string did you use for comparison? (and that 10% means that lut is faster by 10% or lut needs only 10% time of Expr?)
And I'd like to ask you (or someone) with AVX2, could you please compare the performance of lut/lutxy with Expr on your machines (for a basic expression like "x x +" for lut and "x y -" for lut_xy, and a more complex one?) with optAvx2=False and optAVX2=true. For 8, 10 and 16 bits. (10 bit lut_xy has not that much memory overhead)
Thanks.
edcrfv94
16th November 2017, 11:39
I think it depends on the expression itself. What expression string did you use for comparison? (and that 10% means that lut is faster by 10% or lut needs only 10% time of Expr?)
And I'd like to ask you (or someone) with AVX2, could you please compare the performance of lut/lutxy with Expr on your machines (for a basic expression like "x x +" for lut and "x y -" for lut_xy, and a more complex one?) with optAvx2=False and optAVX2=true. For 8, 10 and 16 bits. (10 bit lut_xy has not that much memory overhead)
Thanks.
3770k did not support AVX2 only has AVX.(When I9 PC arrivals I can test again maybe need a month.)
mt_lut 8bit-16bit 10%+ faster with complex Expr.
mt_lutxy 8bit faster Expr, other way Expr much faster.
I7 3770k 4.2g
16bit Expr Y8: 201fps 49% cpu 42Mib Memory
SetMemoryMax(3000)
colorbars(width=1920, height=1080, pixel_type="yv12")
ConvertToY8()
trim(0, 5000)
ConvertBits(bits=16)
last.Expr("x x +")
ConvertToStacked().DitherPost(mode=6, ampo=1)
16bit mt_lut Y8: 200fps 45% cpu 43Mib Memory
SetMemoryMax(3000)
colorbars(width=1920, height=1080, pixel_type="yv12")
ConvertToY8()
trim(0, 5000)
ConvertBits(bits=16)
last.mt_lut("x x +", y=3, u=1, v=1)
ConvertToStacked().DitherPost(mode=6, ampo=1)
16bit Expr Y8: 155fps 34% cpu 43Mib Memory
SetMemoryMax(3000)
colorbars(width=1920, height=1080, pixel_type="yv12")
ConvertToY8()
trim(0, 5000)
ConvertBits(bits=16)
last.Expr("x 111 + 3 * 100 - 2 / 2 ^ 0.02 * 4 ^ 11 +")
ConvertToStacked().DitherPost(mode=6, ampo=1)
16bit mt_lut Y8: 201fps 47% cpu 43Mib Memory
SetMemoryMax(3000)
colorbars(width=1920, height=1080, pixel_type="yv12")
ConvertToY8()
trim(0, 5000)
ConvertBits(bits=16)
last.mt_lut("x 111 + 3 * 100 - 2 / 2 ^ 0.02 * 4 ^ 11 +", y=3, u=1, v=1)
ConvertToStacked().DitherPost(mode=6, ampo=1)
16bit Expr Y8: 159fps 34% cpu 50Mib Memory
SetMemoryMax(3000)
colorbars(width=1920, height=1080, pixel_type="yv12")
ConvertToY8()
trim(0, 5000)
ConvertBits(bits=16)
p1 = last
p2 = p1.Invert("Y")
Expr(p1, p2, "x y -")
ConvertToStacked().DitherPost(mode=6, ampo=1)
16bit mt_lutxy Y8: 36fps 16% cpu 50Mib Memory
SetMemoryMax(3000)
colorbars(width=1920, height=1080, pixel_type="yv12")
ConvertToY8()
trim(0, 5000)
ConvertBits(bits=16)
p1 = last
p2 = p1.Invert("Y")
mt_lutxy(p1, p2, "x y -", y=3, u=1, v=1)
ConvertToStacked().DitherPost(mode=6, ampo=1)
8bit Expr Y8: 708fps 12% cpu 35Mib Memory
SetMemoryMax(3000)
colorbars(width=1920, height=1080, pixel_type="yv12")
ConvertToY8()
trim(0, 5000)
#ConvertBits(bits=16)
p1 = last
p2 = p1.Invert("Y")
Expr(p1, p2, "x y -")
#ConvertToStacked().DitherPost(mode=6, ampo=1)
8bit mt_lutxy Y8: 636fps 12% cpu 35Mib Memory
SetMemoryMax(3000)
colorbars(width=1920, height=1080, pixel_type="yv12")
ConvertToY8()
trim(0, 5000)
#ConvertBits(bits=16)
p1 = last
p2 = p1.Invert("Y")
mt_lutxy(p1, p2, "x y -", y=3, u=1, v=1)
#ConvertToStacked().DitherPost(mode=6, ampo=1)
8bit Expr Y8: 276ps 12% cpu 35Mib Memory
SetMemoryMax(3000)
colorbars(width=1920, height=1080, pixel_type="yv12")
ConvertToY8()
trim(0, 5000)
#ConvertBits(bits=16)
p1 = last
p2 = p1.Invert("Y")
Expr(p1, p2, "x y < x x y - 0.8 * - x x y - 0.9 * - ?")
#ConvertToStacked().DitherPost(mode=6, ampo=1)
8bit mt_lutxy Y8: 614fps 12% cpu 35Mib Memory
SetMemoryMax(3000)
colorbars(width=1920, height=1080, pixel_type="yv12")
ConvertToY8()
trim(0, 5000)
#ConvertBits(bits=16)
p1 = last
p2 = p1.Invert("Y")
mt_lutxy(p1, p2, "x y < x x y - 0.8 * - x x y - 0.9 * - ?", y=3, u=1, v=1)
#ConvertToStacked().DitherPost(mode=6, ampo=1)
10bit Expr Y8: 220ps 12% cpu 47Mib Memory
SetMemoryMax(3000)
colorbars(width=1920, height=1080, pixel_type="yv12")
ConvertToY8()
trim(0, 5000)
ConvertBits(bits=10)
p1 = last
p2 = p1.Invert("Y")
Expr(p1, p2, "x y < x x y - 0.8 * - x x y - 0.9 * - ?")
#ConvertToStacked().DitherPost(mode=6, ampo=1)
10bit mt_lutxy Y8: 225fps 12% cpu 48Mib Memory
SetMemoryMax(3000)
colorbars(width=1920, height=1080, pixel_type="yv12")
ConvertToY8()
trim(0, 5000)
ConvertBits(bits=10)
p1 = last
p2 = p1.Invert("Y")
mt_lutxy(p1, p2, "x y < x x y - 0.8 * - x x y - 0.9 * - ?", y=3, u=1, v=1)
#ConvertToStacked().DitherPost(mode=6, ampo=1)
pinterf
16th November 2017, 13:58
3770k did not support AVX2 only has AVX.(When I9 PC arrivals I can test again maybe need a month.)
Many thanks!
Can you check again these two numbers? I feel that the difference is too big between them.
"x y -"
16bit Expr Y8: 159fps 34% cpu 50Mib Memory
8bit Expr Y8: 708fps 12% cpu 35Mib Memory
edit: the difference occured because of the final stacked + dither post conversion
This script eliminates the conversion overhead before the lut/expr (and no conversion occurs after, avsmeter can report the real comparison of the methods)
SetMemoryMax(3000)
bits=16 # set 8, 10, .. 16
lut=true # true:lut, false:expr
clipcount=1 # 1: clip/lut, 2: two clips/lutxy
simpleexpr=false # choose simple (true) or a more complex expression
format="YUV420P"+String(bits)
colorbars(width=1920, height=1080, pixel_type=format)
ConvertToY()
trim(0, 5000)
p1 = last
p2 = p1.Invert("Y").trim(0,-1).loop(p1.framecount()) # all cached, no speed penalty
expr_1d_simple = "x x +"
expr_1d_complex = "x 111 + 3 * 100 - 2 / 2 ^ 0.02 * 4 ^ 11 +"
expr_2d_simple = "x y -"
expr_2d_complex = "x y < x x y - 0.8 * - x x y - 0.9 * - ?"
expr = clipcount==1 ? (simpleexpr ? expr_1d_simple : expr_1d_complex) : (simpleexpr ? expr_2d_simple : expr_2d_complex)
if(clipcount==1) {
result = lut ? mt_lut(p1, expr, y=3, u=1, v=1) : Expr(p1, expr)
} else {
result = lut ? mt_lutxy(p1, p2, expr, y=3, u=1, v=1) : Expr(p1, p2, expr)
}
result
My results for avs+ x86 r2544 and masktools2 2.2.10:
i7-3770 @ 3.40 GHz (No AVX2)
results in [fps] reported by AvsMeter
Bits: 8 Lut/Expr
Simple, 1 Clip 790/700
Complex, 1 Clip 796/306
Simple, 2 Clips 540/684
Complex, 2 Clips 540/219
Bits: 16 Lut/Expr
Simple, 1 Clip 655/713
Complex, 1 Clip 664/300
Simple, 2 Clips 41.2/684 # masktools2 16 bit lutxy is not lookup but realtime calc
Complex, 2 Clips 6.45/224 # masktools2 16 bit lutxy is not lookup but realtime calc
real.finder
16th November 2017, 17:20
the top is Expr, then Expr with optAvx2=False, then mt_lutxy, using this https://ark.intel.com/products/75459/Intel-Core-i5-4200U-Processor-3M-Cache-up-to-2_60-GHz
https://i.imgur.com/x0gDHb1.png
colorbars()
converttoyv12
d=last
Expr(last,d,"x y -")
#Expr(last,d,"x y -",optAvx2=False)
#mt_lutxy(last,d,"x y -")
pinterf
16th November 2017, 19:30
What OS? Not much difference for this kind of expression with or w/o avx2
real.finder
16th November 2017, 19:43
What OS? Not much difference for this kind of expression with or w/o avx2
win7 64 sp1, not my pc btw
edcrfv94
30th November 2017, 09:33
kf_limit_dif8_128_expr_test(src_f, src, thr=1.0, elast=1.0, y=3, u=3, v=3)
expr: Stack unbalanced at end of expression. Need to have exactly one value on the stack to return.
kf_limit_dif8_128_expr_test(src_f, src, thr=1.0, elast=1.0, y=3, u=3, v=3)
mt_lut:Output is garbage
kf_limit_dif8_128_expr_test(src_f, src, thr=1.0, elast=1.01, y=3, u=3, v=3)
kf_limit_dif8_128_mt_test(src_f, src, thr=1.0, elast=1.01, y=3, u=3, v=3)
Work fine.
Maybe "- Expr optimization: eliminate ^1 +0 -0 *1 /1 " cause problems?
SetMemoryMax(3000)
colorbars(width=1920, height=1080, pixel_type="yv12").killaudio().assumefps(25, 1)
#ConvertToY8()
trim(0, 5000)
#Limiter()
#InvertNeg()
#VToY()
src = last
src_f = src.RemoveGrain(11, 11, 11)
kf_limit_dif8_128_expr_test(src_f, src, thr=1.0, elast=1.0, y=3, u=3, v=3)
#kf_limit_dif8_128_mt_test(src_f, src, thr=1.0, elast=1.0, y=3, u=3, v=3)
#kf_limit_dif8_128_expr_test(src_f, src, thr=1.0, elast=1.01, y=3, u=3, v=3)
#kf_limit_dif8_128_mt_test(src_f, src, thr=1.0, elast=1.01, y=3, u=3, v=3)
Function kf_limit_dif8_128_expr_test(clip filtered, clip original, bool "smooth", float "thr", float "elast", float "darkthr", int "Y", int "U", int "V")
{
smooth = Default(smooth, True )
thr = Default(thr, 1.0 )
elast = Default(elast, smooth ? 3.0 : 128./thr)
darkthr = Default(darkthr,thr )
Y = Default(Y, 3 )
U = Default(U, 3 )
V = Default(V, 3 )
Y = min(Y, 4)
U = min(U, 4)
V = min(V, 4)
Yt = Y == 3
Ut = U == 3
Vt = V == 3
Y31 = Yt ? 3 : 1
U31 = Ut ? 3 : 1
V31 = Vt ? 3 : 1
thr = max(min( thr, 128.0), 0.0)
darkthr = max(min(darkthr, 128.0), 0.0)
elast = max(elast, 1.0)
mode = thr == 0 && darkthr == 0 ? 4 : thr == 128 && darkthr == 128 ? 2 : 3
smooth = elast==1 ? False : smooth
diffstr = " x range_half - "
elaststr = " "+string(elast)+" "
thrstr = diffstr+" 0 > "+string(darkthr)+" scalef "+string(thr)+" scalef ? "
alphastr = elaststr+" 1 <= 0 1 "+elaststr+" 1 - "+thrstr+" * / ? "
betastr = thrstr+elaststr+" * "
sexpr = smooth ? alphastr+diffstr+" * "+betastr+diffstr+" abs - * range_half + "
\ : thrstr+diffstr+diffstr" abs / * range_half + "
expr = diffstr+" abs "+thrstr+" <= x "+diffstr+" abs "+betastr+" >= range_half "+sexpr+" ? ? "
thrstrc = " "+string(thr)+" scalef "
alphastrc= elaststr+" 1 <= 0 1 "+elaststr+" 1 - "+thrstrc+" * / ? "
betastrc = thrstrc+elaststr+" * "
sexprc = smooth ? alphastrc+diffstr+" * "+betastrc+diffstr+" abs - * range_half + "
\ : thrstrc+diffstr+diffstr" abs / * range_half + "
exprc = diffstr+" abs "+thrstrc+" <= x "+diffstr+" abs "+betastrc+" >= range_half "+sexprc+" ? ? "
# diff = filtered - original
# alpha = 1 / (thr * (elast - 1))
# beta = elast * thr
# When smooth=True :
# output = diff <= thr ? filtered : \
# diff >= beta ? original : \
# original + alpha * diff * (beta - abs(diff))
# When smooth=False :
# output = diff <= thr ? filtered : \
# diff >= beta ? original : \
# original + thr * (diff / abs(diff))
diff = mt_makediff(filtered, original, y=Y31, u=U31, v=V31)
ldiff = expr(diff, expr, exprc, exprc)
merged = mt_adddiff(original, ldiff, y=Y31, u=U31, v=V31)
merged = Y==2 || U==2 || V==2 || Y==4 || U==4 || V==4 ? mt_lutxyz(filtered, original, merged, Y=Y==3?5:Y, U=U==3?5:U, V=V==3?5:V) : merged
return mode == 4 ? original
\ : mode == 2 ? filtered
\ : merged
}
Function kf_limit_dif8_128_mt_test(clip filtered, clip original, bool "smooth", float "thr", float "elast", float "darkthr", int "Y", int "U", int "V")
{
smooth = Default(smooth, True )
thr = Default(thr, 1.0 )
elast = Default(elast, smooth ? 3.0 : 128./thr)
darkthr = Default(darkthr,thr )
Y = Default(Y, 3 )
U = Default(U, 3 )
V = Default(V, 3 )
Y = min(Y, 4)
U = min(U, 4)
V = min(V, 4)
Yt = Y == 3
Ut = U == 3
Vt = V == 3
Y31 = Yt ? 3 : 1
U31 = Ut ? 3 : 1
V31 = Vt ? 3 : 1
thr = max(min( thr, 128.0), 0.0)
darkthr = max(min(darkthr, 128.0), 0.0)
elast = max(elast, 1.0)
mode = thr == 0 && darkthr == 0 ? 4 : thr == 128 && darkthr == 128 ? 2 : 3
smooth = elast==1 ? False : smooth
diffstr = " x range_half - "
elaststr = " "+string(elast)+" "
thrstr = diffstr+" 0 > "+string(darkthr)+" scalef "+string(thr)+" scalef ? "
alphastr = elaststr+" 1 <= 0 1 "+elaststr+" 1 - "+thrstr+" * / ? "
betastr = thrstr+elaststr+" * "
sexpr = smooth ? alphastr+diffstr+" * "+betastr+diffstr+" abs - * range_half + "
\ : thrstr+diffstr+diffstr" abs / * range_half + "
expr = diffstr+" abs "+thrstr+" <= x "+diffstr+" abs "+betastr+" >= range_half "+sexpr+" ? ? "
thrstrc = " "+string(thr)+" scalef "
alphastrc= elaststr+" 1 <= 0 1 "+elaststr+" 1 - "+thrstrc+" * / ? "
betastrc = thrstrc+elaststr+" * "
sexprc = smooth ? alphastrc+diffstr+" * "+betastrc+diffstr+" abs - * range_half + "
\ : thrstrc+diffstr+diffstr" abs / * range_half + "
exprc = diffstr+" abs "+thrstrc+" <= x "+diffstr+" abs "+betastrc+" >= range_half "+sexprc+" ? ? "
# diff = filtered - original
# alpha = 1 / (thr * (elast - 1))
# beta = elast * thr
# When smooth=True :
# output = diff <= thr ? filtered : \
# diff >= beta ? original : \
# original + alpha * diff * (beta - abs(diff))
# When smooth=False :
# output = diff <= thr ? filtered : \
# diff >= beta ? original : \
# original + thr * (diff / abs(diff))
diff = mt_makediff(filtered, original, y=Y31, u=U31, v=V31)
ldiff = mt_lut(diff, yexpr=expr, uexpr=exprc, vexpr=exprc, y=Y31, u=U31, v=V31)
merged = mt_adddiff(original, ldiff, y=Y31, u=U31, v=V31)
merged = Y==2 || U==2 || V==2 || Y==4 || U==4 || V==4 ? mt_lutxyz(filtered, original, merged, Y=Y==3?5:Y, U=U==3?5:U, V=V==3?5:V) : merged
return mode == 4 ? original
\ : mode == 2 ? filtered
\ : merged
}
pinterf
30th November 2017, 10:38
Missing + sign?
I can see
diffstr+diffstr"
instead of
diffstr+diffstr+"
Edit: elast=1 -> smooth=False, different expressions, syntax error was in the smooth=false branch
edcrfv94
30th November 2017, 11:03
Missing + sign?
I can see
diffstr+diffstr"
instead of
diffstr+diffstr+"
Edit: elast=1 -> smooth=False, different expressions, syntax error was in the smooth=false branch
You are right, thanks! *mt_lut no error message at Stack mistakes?
real.finder
6th December 2017, 21:47
any news on scaling things for both expr and lut?
pinterf
6th December 2017, 22:57
I am still working on Expr but somehow stuck because this version of jit asm used in the ad-hoc assembler code generation is failing and generates false code for the feature I'm experimenting with, resulting in random nice access violation messages. Ordinary expressions are not affected however. I'd like to understand why it fails. It already took a lot of days and I'm not seeing the end of the tunnel. When I'm ready, I can start making the feature list more similar between mt_lut family and Expr. So it's not forgotten just takes more time than expected.
wonkey_monkey
7th December 2017, 11:14
I've been writing an assembler and have looked (briefly) at expr, so if you need another pair eyes on it... got any machine code output to share?
pinterf
7th December 2017, 12:03
I've been writing an assembler and have looked (briefly) at expr, so if you need another pair eyes on it... got any machine code output to share?
Thanks. The problem is that jitasm tries to be smart. When there are not enough working registers, it swaps one to two to a memory slot, use the register(s) for the specific purpose, then restores their previous state. Sometimes jit makes optimization in such a way that it exchanges the appropriate working registers (e.g. xchg esi,ecx). For example let's have a read pointer in esi, frame width in ecx. Normally jitasm generates code that is reading pixel from esi which is our pixel pointer. But if we use labels and jumps, jit may generate register exchanges but forgets about the exchange, and uses ecx for pixel readout, which is obviously not a pointer.
See here (https://github.com/pinterf/AviSynthPlus/commit/4d69a103bc58a5897c960696158a1ce1b488839e)
(Later I found your work, and I am working on similar features, namely x-y offsets and storing current result into a variable slot.)
raffriff42
5th January 2018, 04:32
Consider the following test:function _test(clip C)
{
C
M = BlankClip(Last) [* any old mask *]
\ .Subtitle("TEXT", text_color=color_white, size=Height, align=2)
\ .Tweak(cont=0.5, bright=32)
\ .BilinearResize(Width/8, Height/8)
\ .GaussResize(Width, Height, p=19)
#return M
#[[ pick one
return mt_merge(Grayscale, M, luma=true).Subtitle("mt_merge")
#return Overlay(Grayscale, mask=M).Subtitle("Overlay")
#]]
}
BlankClip(width=512, height=256, pixel_type="YV12", length=1024, color=color_red)
FadeOut(600)
_test
return Last
Here is the expected output:
https://www.dropbox.com/s/x6hsj7k6ju5k78g/mt_merge-bug-00.png?raw=1
Here is mt_merge:
https://www.dropbox.com/s/cdnv4lwj8tyotsl/mt_merge-bug-01.png?raw=1
Tested with YV12, YUV420P10..YUV420PS - all do it (although the pattern changes a bit)
poisondeathray
5th January 2018, 06:44
I can reproduce rr42's bug in avisynth+ x64 with masktools2.dll 2.2.10.0.
But it doesn't seem to affect the same masktools2.dll 2.2.10.0 in x86 flavour in avisynth "classic" . I don't have avisynth+ x86 installed to test right now
Motenai Yoda
5th January 2018, 07:22
it works for me
avs+ v2574 x86 & x86_64
masktools2 v2.2.10.0
pinterf
5th January 2018, 09:18
It's wrong when avx2 is used.
This works:
return mt_merge(Grayscale, M, luma=true, avx2=false).Subtitle("mt_merge")
I'll prioritize the fix.
EDIT: fixed on git, no release yet
real.finder
5th January 2018, 17:54
any news for scale things?
pinterf
5th January 2018, 22:43
Not forgotten. Already have started to rework the internals first to have some of the Expr syntax that is not implemented in masktools. Regarding your old request for mpeg1 chroma option in luma=true, would it really be visibly superior than without it?
real.finder
6th January 2018, 03:16
Not forgotten. Already have started to rework the internals first to have some of the Expr syntax that is not implemented in masktools.
thanks, will wait for that then
Regarding your old request for mpeg1 chroma option in luma=true, would it really be visibly superior than without it?
it will not be a big difference, but it always good to have the right things, similar to chroma resize bug (always center, so it will be technically wrong in most cases) in internal avs resizes, there will be people care about it
pinterf
6th January 2018, 19:26
New build, important fix for AVX2 users for mt_merge, luma=true
Download Masktools2 2.2.11 (https://github.com/pinterf/masktools/releases/tag/2.2.11)
**v2.2.11 (20180105)
- Fix: mt_merge luma=true: broken output when: 8-16 bits AVX2, 32 bit float: SSE2, AVX
- move project to VS2017, vs141_xp toolset
raffriff42
6th January 2018, 22:22
Sorry to say, the test fails with widths that are not mod32 -- a little "crud" (mask image wraparound?) is visible on the right side.
EDIT
1) if you use my test above, BilinearResize will have to be modded to support arbitrary sizes. Of course
2) avx2=false fixes the problem, and it is a little faster for me!
pinterf
7th January 2018, 09:15
Sorry to say, the test fails with widths that are not mod32 -- a little "crud" (mask image wraparound?) is visible on the right side.
EDIT
1) if you use my test above, BilinearResize will have to be modded to support arbitrary sizes. Of course
2) avx2=false fixes the problem, and it is a little faster for me!
Indeed, there are problems with 10-16 bit 420 and 422 sources, when they are not mod8 (SSE2) or mod16 (AVX2) width, on the right side, where no fast SIMD but only the C code works. For 8 bits I can see no artifacts, what is your exact script?
raffriff42
7th January 2018, 12:10
Sorry, I meant to say, not mod64 AND bit depth > 8 && < 32.
Didn't mean to imply there was a new bug where there was none before.
EDIT my script -BlankClip(width=512-4, height=256, pixel_type="YUV420P10", color=color_red)
M = BlankClip(Last)
\ .Subtitle("X", text_color=$ffffff, size=Height, align=2)
#return M
s="""
mt_merge(Grayscale, M, luma=true,
\ sse2=1>0, sse3=1>0, ssse3=1>0,
\ sse4=1>0, avx=1>0, avx2=0>0)
"""
Eval(s)
Subtitle(PixelType
\ +"\n"+"width="+String(Width)
\ +ReplaceStr(s, Chr(10), "\n"),
\ lsp=0)
return Last
https://www.dropbox.com/s/8bxnfy2vu0jrxy0/mt_merge-bug-03.png?raw=1
https://www.dropbox.com/s/bqx134sn3q03wl5/mt_merge-bug-04.png?raw=1
pinterf
7th January 2018, 19:57
Sorry, I meant to say, not mod64 AND bit depth > 8 && < 32.
Thanks, this one is fixed, probably the last one from this group.
Now I have run the speed tests (mt_merge alone), encoding tests (whole script above) to have the exact same files for avx2/nonAvx2 case, and visual tests with all combinations of 420, 422, 444 / 8, 14, 16 bits and float / avx2=false or true / width=512 and 512-4.
(10-14 and 16 bit versions differs a bit internally)
pinterf
7th January 2018, 21:19
New build, fixing an old bug, thank you raffriff42!
Download masktools2 2.2.12 (https://github.com/pinterf/masktools/releases/tag/2.2.12)
**v2.2.12 (20180107)**
- Fix: mt_merge 10-16 bits: right side artifacts when clip has non-mod 8 (non-AVX2) or mod16 (AVX2) width
8day
27th January 2018, 18:27
Either I'm doing something wrong, or MT_LUTxyza doesn't work: it always returns "z"-clip instead of "a"-clip. Tested using 2.2.0 and >=2.2.9 at Windows 7 with AviSynth 2.6 using different filter chains.
MT_LUTxyza(
\ ColorBars(pixel_type="YV12").Subtitle("X"),
\ ColorBars(pixel_type="YV12").Subtitle("Y"),
\ ColorBars(pixel_type="YV12").Subtitle("Z"),
\ ColorBars(pixel_type="YV12").Subtitle("A"),
\ "a"
\ )
poisondeathray
27th January 2018, 18:40
Either I'm doing something wrong, or MT_LUTxyza doesn't work: it always returns "z"-clip instead of "a"-clip. Tested using 2.2.0 and >=2.2.9 at Windows 7 with AviSynth 2.6 using different filter chains.
MT_LUTxyza(
\ ColorBars(pixel_type="YV12").Subtitle("X"),
\ ColorBars(pixel_type="YV12").Subtitle("Y"),
\ ColorBars(pixel_type="YV12").Subtitle("Z"),
\ ColorBars(pixel_type="YV12").Subtitle("A"),
\ "a"
\ )
This works correctly for me
avs+ r2574 x64 , masktools2-v2.2.12, win8.1
8day
28th January 2018, 14:30
This works correctly for me
avs+ r2574 x64 , masktools2-v2.2.12, win8.1
Sorry, my bad. Turns out it works. On the other hand, I figured out what caused the issue -- MT_Polish(). This is the code that doesn't work:
MT_LUTxyza(
\ ColorBars(pixel_type="YV12").Subtitle("X"),
\ ColorBars(pixel_type="YV12").Subtitle("Y"),
\ ColorBars(pixel_type="YV12").Subtitle("Z"),
\ ColorBars(pixel_type="YV12").Subtitle("A"),
\ MT_Polish("a")
\ )
That being said, despite that MT_LUTxyza() returns any of these clips when I use raw string, doing any calculations breaks something pretty heavy. E.g., "a-z", "a+128", "x*1" or even "x+" results in same darkened frame. Thought it may be something wrong with AvsPmod, but VirtualDub shows same image. v2.2.1, the first build with this function, has same issues.
burfadel
1st February 2018, 07:54
There seems to be something wrong with MT_Lut in regards to bit depth handling. For one, even though the docs says 'When not defined, all threshold-like and Y, U, V, A parameter values are treated as 8 bit values and will be autoscaled accordingly to match the clip bit depths. '. It doesn't! You can't use the scaleparams function either, as it says mt_lut doesn't have that function. Not sure if the other lut functions are affected.
This is with the latest 2.2.12
pinterf
1st February 2018, 09:40
Sorry, what you found, is a typo, will fix it.
Search for paramscale
http://avisynth.nl/index.php/MaskTools2
burfadel
1st February 2018, 10:11
Sorry about the second thing, that was my typo :D. The first thing is still valid though, in that it doesn't scale automatically like the other functions.
pinterf
1st February 2018, 11:56
Sorry about the second thing, that was my typo :D. The first thing is still valid though, in that it doesn't scale automatically like the other functions.
Found something. Are you trying with chroma="somenegativevalue"?
burfadel
1st February 2018, 12:34
The colour format is an extracted Luma channel. I use it for a mask using
passmask = mt_lut (cy, "x "+string(32)+" < 0 x "+string(45)+" > "+string(255)+" 0 x "+string(35)+" - "+string(255)+" "+string(32)+" "+string(65)+" - / * - ? ?")
Where cy is a 12 bit Luma extract using ExtractY. If you view the mask as 8 bit extract it works, but in 12 bit it is essentially black due to not being scaled. On the same 12 bit clip functions like mt_binarize(cy, 128) works fine and scales to 12 bit automatically.
pinterf
1st February 2018, 13:07
Ok, then I found a bug that you haven't think of. We can nicely work together :)
ConvertBits(10).mt_lut("x 2 *",chroma="-128")
# sets a YUV clip to greyscale. 8 bit OK, 10-14 and 32 bits fail ("chroma" parameter issue only)
Back to your problem: the expression interpreter cannot decide from a constant whether it is scalable or not (think of a "x y + 2 /", is "2" something to scale or not?).
scaleparam is only for parameter (Y,U,V, thresholds, etc..) scaling, not the expression itself.
So you have to insert manually the scaleb (bitshift scale, usually for YUV) or scalef (full range scale). Like "235 scaleb" which will mean luma max for each bitdepth.
You can use some predefined constants which will have always a properly scaled value, like range_max (255/1023/4095/16383/65535 or 1.0 for float), range_size --> 256/1024...65536, ymin, ymax, cmin, cmax --> the 16/235 and 16/240 limits autoscaled.
Usually you would use range_max instead of 255, and scaleb for the other constants in your sample.
Same rules apply on the Expr filter syntax in Avisynth+.
burfadel
1st February 2018, 13:58
Ah ok, so I can only apply it on the source with chroma, or 8-bit, when not specifically stating to scale in 8-bit?
pinterf
1st February 2018, 14:07
Ah ok, so I can only apply it on the source with chroma, or 8-bit, when not specifically stating to scale in 8-bit?
The sample above should work (and will work in a soon-to-be released 2.2.13) for all bit depths because parameter scaling is from 8 bits (paramscale="i8" default) and it works fine for other parameters that are using negative numbers for pixel-fill.
pinterf
1st February 2018, 16:41
New build
Masktools2 v2.2.13 (https://github.com/pinterf/masktools/releases/tag/2.2.13)
**v2.2.13 (20180201)
- Fix: rare crash in multithreading environment at the very first frames
(keeping XP compatibility with /Z:threadsafeinit- caused troubles!)
- mt_edge: AVX2 (1.4-1.9x speed) for 8 and 10-16 bits
- fix: "chroma" parameter with negative (memset) values were not working properly for 10-14 bits and 32bit float
That stupid crash took me weeks to catch until it turned out that a mysterious access violation is happening right in masktools2.
The original report was: ffdshow x64 crashed with a script using maa2. I have almost completely un-mmx'd ffdshow, and moved it to avs 2.6 interface from v2.5, changed things that existed in boost many years ago but now C++14/17 adopted them, so it finally could be compiled and debugged with VS2017 (with some features disabled). But the crash was still there, pointing to avisynth or one of its filters. Then I succeeded to reproduce the crash w/o ffdshow with a simple script:
c=BlankClip(width=620,height=600,length=1000,pixel_type="YV12")
mt_merge(c,c,c,y=-2,u=-2,v=-2,luma=true)
#Exception 0xC0000005 [STATUS_ACCESS_VIOLATION]
#Module: C:\Windows\System32\KernelBase.dll
#Address: 0x00007FF9A5313FB8
Prefetch(2)
It was the side effect of the /Zthreadsafeinit- switch. This option is used for keeping stupid XP compatibility and caused a static class to be initialized later in one thread than it was used from another thread. Specifically in MT environment GetFrame(0) started the initializing some variables but GetFrame(1) from another thread kicked in too early and couldn't yet see the changes that the first thread was doing.
Of course all this happened only in Release mode because it needed strict timing conditions, maybe sub-milliseconds so it could not be debugged. When will XP die????
TheFluff
1st February 2018, 16:51
When will XP die????
You are as free as a bird. You can kill it whenever you like.
VS_Fan
1st February 2018, 19:21
When will XP die????This can help: According to statcounter's "Desktop Windows Version Market Share Worldwide (http://gs.statcounter.com/windows-version-market-share/desktop/worldwide#monthly-201701-201801)":
Windows XP market share dropped from almost 6% to about 3% during the last year.
Windows XP market share has consistently lost more than 3% market share yearly since January 2015, three years ago, when it had almost 14%.
Windows XP’s big brother, windows 2003, disappeared from those statistics in January 2015, three years ago.
Support for Windows XP has ended (https://www.microsoft.com/en-us/WindowsForBusiness/end-of-xp-support) almost 4 years ago:
After 12 years, support for Windows XP ended April 8, 2014. Microsoft will no longer provide security updates or technical support for the Windows XP operating system
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.