Log in

View Full Version : Avisynth+


Pages : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 [79] 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112

wonkey_monkey
23rd January 2018, 00:02
resample? rescale? I think in general true/false parameters like that should be verbs, not nouns, since it indicates what it will do (or not do).

raffriff42
23rd January 2018, 07:22
Well I did some tests ...results are not exactly what I was expecting
(I was expecting truerange=true to be left-shifted and truerange=false to be left-padded)

baseline --
https://www.dropbox.com/s/xv7o4sosomxahqf/avsplus-convertbits-truerange-test-00.png?raw=1

8bit in, convert to 10bit, back to 8bit:
https://www.dropbox.com/s/v9imv1acge27068/avsplus-convertbits-truerange-test-01.png?raw=1

https://www.dropbox.com/s/lhrgtqkxo2f1epk/avsplus-convertbits-truerange-test-02.png?raw=1

https://www.dropbox.com/s/1al0h996s6g5lt9/avsplus-convertbits-truerange-test-03.png?raw=1

...any ideas?

Here's the script; requires Utils-r41.avsi (http://avisynth.nl/images/Utils-r41.avsi) for EvalShow functionColorbarsHD(width=480, height=320, pixel_type="YUV444P8")
Subtitle("Source PixelType = '" + PixelType + "'", y=24)

#[[ choose one (or none) - convert bit depth
#EvalShow("ConvertBits(10, truerange=true)")
#EvalShow("ConvertBits(10, truerange=false)")
#]]

Subtitle("Converted PixelType = '" + PixelType + "'", y=48)

ScriptClip("""
Subtitle(
\ "Y min = " + String(YPlaneMin, "%0.2f") + ", max = " + String(YPlaneMax, "%0.2f") + "\n"
\+"U min = " + String(UPlaneMin, "%0.2f") + ", max = " + String(UPlaneMax, "%0.2f") + "\n"
\+"V min = " + String(VPlaneMin, "%0.2f") + ", max = " + String(VPlaneMax, "%0.2f"),
\ lsp=0, y=80)
""")

#[[ choose one (or none) - downconvert for viewing purposes
#EvalShow("ConvertBits(8, truerange=true)", align=1)
#EvalShow("ConvertBits(8, truerange=false)", align=1)
#]]

poisondeathray
23rd January 2018, 08:06
@rr42 - Maybe that's only for "10bit in 16bit" ? and might not apply to "8bit in 10bit" ?

I'm just trying to think of what usage scenarios would you NOT want to scale the values for 8 to 10bit? I can't think of any

The docs (which obviously could be wrong at this point) say "convert 10-16 bit formats without re-scaling underlying pixel data." I think that means source 10 to 16 . The example given is ConvertBits(16, truerange=false)

But for the 10bit case, "10bit in 16bit code words" is still used by some people using dither tools workflows

wonkey_monkey
23rd January 2018, 10:39
The docs (which obviously could be wrong at this point) say "convert 10-16 bit formats without re-scaling underlying pixel data." I think that means source 10 to 16 .

I think it means "convert to/from formats with between 10 and 16 bits without rescaling."

When converting up, should there be an option to rescale and copy in the upper bits to the new lower bits? So that full white remains full white? E.g, from 8 to 12 bits:


11111111 => 111111111111
11010011 => 110100111101
01101111 => 011011110110


This can be shifted back down and still return to the original value.

raffriff42
23rd January 2018, 16:01
poisondeathray,
>The docs (which obviously could be wrong at this point)

"The docs" were typed in by me, using whatever information I could gather at the time. :) :o

Note the big red TODO which is my way of saying I don't have a frickin clue here.

If you scroll down to scale, fulls and fulld you will see more confusion. Fact-finding assistance is welcome.

Your mention of 10bit in 16bit data sounds plausible.

pinterf
23rd January 2018, 17:13
This parameter, whatever stupid name it has, was introduced at the very beginning of the high bit depth project. Its only purpose was to 'typecast' a 16 bit video format over an existing 10 bit content.
Probably in those times native 10 bit support by plugins or external applications was practically non-existing, some external programs could handle 16 bits or one could use stacked 16 bit format.
I guess these were the reasons.

raffriff42
25th January 2018, 15:27
pinterf, it's okay to take a wrong turn or two in such an undertaking. Overall, AVS+ is a huge step forward, and thanks again for the work you've done.

Maybe truerange, scale, fulls and fulld can be left undocumented - labeled "deprecated/experimental" (or something) for the time being?

pinterf
26th January 2018, 07:10
Yes, truerange and scale should surely die silently.

pinterf
26th January 2018, 18:21
Meanwhile I accidentally observed a bug, which appeared on the right-side of a clip as random color blocks/lines.
It was appearing only in 32bit float test clips and only at specific sequence of resizing.

Check and encode this script and look at the right side of the bottom right clip (32 bit float)

x=ColorBarsHD.ConvertToYUV444().Trim(0,100)
Function Resize(clip c)
{
Return c.Spline64Resize(2802,1501).\
Spline16Resize(904,487).\
BilinearResize(402,500).\
Spline36Resize(200,489).\
LanczosResize(400,300).ConvertBits(8)
}
a8 = x.ConvertBits(8).Resize()
a10 = x.ConvertBits(10).Resize()
a16 = x.ConvertBits(16).Resize()
a32 = x.ConvertBits(32).Resize()
Stackvertical(StackHorizontal(a8,a10),StackHorizontal(a16,a32))


Unfortunately it was perfect when I encoded float-only clips. The uglyness in the reproduction was that there had to be a 8-16 bit clip in the script (I usually do the tests for 8-10-16-32 bits then stack it together in 8 bits to see any difference) Obviously there had to be something that had left other patterns in memory than a 32bit float format clip.

Narrowing the problem down, it turned out that the SIMD code that handles the pixels in 4/8 units was run into some garbage at the right side, where not all the 4/8 units are visible pixels, depending of the clip width (modulo 4 or 8).

During the resizing process, the unused pixels are masked out with a zero multiplier - existing 8-16 bit code worked fine like that -, but it was not enough for 32 bit float pixels. When such a pixel is undefined, the processor would report it NaN (Not a Number), and multiplying it by 0 would still result in NaN.
Thus such pixel in the resized clip turned into undefined (garbage)

So I had to fix the float resizer code - uhh, it was old, one of my early attempts.
Since the 10-16 bit resizer parts were affected as well, they had to be touched, too.
Finally whe whole 10-16 and float resizer code got rewritten - unfortunately I couldn't see the time that the bug chasing needed, sure, with less effort I could port Zimg resizers into avs+.

Btw zimg.
Since I had to benchmark the new code if it is any better than the one in r2580, I have included the z_XXX resizers.
https://forum.doom9.org/showthread.php?t=173986

Results are interesting.
Look at the 400x2800 -> 900x400 case (16 bit)

Resizing always happens in one horizontal and one vertical pass. Or first vertical resizing, then horizontal. it depends.

In Avisynth - probably for quality reasons - there is a strategy: "// ensure that the intermediate area is maximal"

Avs resizer gave a 103 fps, while zimg had 402 fps. What?

Then it was made clear that Avs chose the 400x2800->900x2800->900x400 sequence,
while zimg chose
400x2800->400x400->900x400.

When I turned the resizing command into two resizing (first V then H), avisynth+ gave a quite comparable result of 427 fps.
First three columns (AVX2, SSE4, noSSE4 contains results of the new resizers) Code was run on an i7-7700, Avs+ x64. I built specific avs+ versions for the test to ignore AVX2..SSE4.1 CPU flags.

EDIT: this benchmark data contains the comparison of a current "under construction" version avs+ and the z-lib resizer I had access (r1a, from 2016).
They both have faster variants since then.

#32bit float AVX2 SSE4 noSSE4 v2580 Zimg
#400x2800 -> 900x400: 103 64.3 64.3 65.9 Lanczos
#1920x1080-> 1280x720 143.1 83.7 83.2 95.7 158.4 Spline64

#16 bit AVX2 SSE4 noSSE4 v2580 Zimg
#400x2800 -> 900x400: 103.9 84 75.8 56.2 402.6 Lanczos **see comment
#400x2800 -> 400x400->
# 900x400: 427.2 315.3 289.9 243.4 405.1 Lanczos

#1920x1080-> 1280x720 152.2 125.0 118.9 80.6 129 Spline64
#1920x1080-> 1280x720 160.6 134.3 129.4 85.9 134.5 Lanczos
#1920x1080-> 1280x1080 240.2 190.6 185.2 113.2 191.8 Lanczos H
#1920x1080-> 1920x720 335.5 320.8 281 272.2 203.0 Lanczos V

#10 bit AVX2 SSE4 noSSE4 v2580 Zimg
#400x2800 -> 900x400: 105.4 77.5 53.5 Lanczos
#1920x1080-> 1280x720 155.2 146.6 120.4 78.9 133 Spline64
#1920x1080-> 1280x720 163.6 156.2 Lanczos

#8 AVX2 SSE4 noSSE4 Old Zimg
#400x2800 -> 900x400: 93.8 93.4 96.2 93.8 402 **see comment
#1920x1080-> 1280x720 104.7 105.1 106.0 105.5 120.2

# ** Avisynth - unlike zimg - always orders H/V resizers for max intermediate area!

(8 bit resizer code is untouched by me, there is no avx2 option there but I included their measurements)

Now it's to be decided that the slower H/V or V/H decision strategy should be kept or not. Is the difference really visible and when?

poisondeathray
26th January 2018, 19:11
Were those tests based on the old zimg , or a recompiled one ? There are quite a few commits to z.lib since that avisynth version posted in Nov 2016, but I don't know offhand if any changes were made to performance (except I think he added AVX-512) or resizing strategies

If there was a noticable qualitative difference, I would imagine it should be more noticable on upscaling. But maybe with some extreme cases , where you have a few pixel width or height src e.g. a 3840x4 strip. There might be some more noticable differences. I guess we can do some tests

But end user can still separate the W, V steps manually if they needed to...



BTW, how are can you load native float formats into avs+ ? (e.g EXR) ? vapoursynth got a bunch of imagemagick updates, but I don't see equivalent method in avs+ ? ffmpeg related options load at 16bit int

jpsdr
27th January 2018, 10:30
@Stephen R. Savage
Have you, like pinterf, turn the resizing command into two resizing (first V then H) to ensure that AVS+ and z.Lib have the same "resize path", to make the benchmark realy accurate ?

@Pinterf
Does it mean there is a new code for resizer, so i have to update my ResizeMT...? :sly: ;)

jpsdr
27th January 2018, 10:35
Now it's to be decided that the slower H/V or V/H decision strategy should be kept or not. Is the difference really visible and when?
You can still add a new parameter at the end, this will keep compatibility with old script, with something like this :
0 : (default) current behavior
1 : Fastest (so will probably result in opposite of current behavior)
2 : Vertical first
3 : Horizontal first

pinterf
27th January 2018, 12:29
Anyway I will rebuild zimg and do the comparison again, at least I have a look at the code and get familiar with a possible integration.

raffriff42
27th January 2018, 13:10
Now it's to be decided that the slower h/v or v/h decision strategy should be kept or not.
Is the difference really visible and when?
Huh! I thought AVS's rationale made sense, but now that I think about it,
how is the visible result of the AVS sequence
400x2800->900x2800 // scale rows, copy columns
900x2800->900x400 // copy rows, scale columns

any different from zimg's
400x2800->400x400 // copy rows, scale columns
400x400->900x400 // scale rows, copy columns

Unless the two resize operations are not actually separable (https://en.wikipedia.org/wiki/Separable_filter)?
Does scale row n ever use pixels from the row(s) above or below? I assumed not.

(dumb question?)

VS_Fan
27th January 2018, 17:56
... In Avisynth - probably for quality reasons - there is a strategy: "// ensure that the intermediate area is maximal" ...

Now it's to be decided that the slower H/V or V/H decision strategy should be kept or not. Is the difference really visible and when?... how is the visible result of the AVS sequence ... any different from zimg's ...

One can imagine the larger intermediate resolution would keep more original information for the second stage filtering: The more resolution/information as input would yield a better output from any filter.

An “objective” test could be done to measure the quality of the results of either strategy: Produce the results of both strategies: scale the original to whatever size (up/down), then scale them back to the original size, and finally measure the quality of both strategies, with say SSIM, against the original

poisondeathray
27th January 2018, 18:03
Huh! I thought AVS's rationale made sense, but now that I think about it,
how is the visible result of the AVS sequence
400x2800->900x2800 // scale rows, copy columns
900x2800->900x400 // copy rows, scale columns

any different from zimg's
400x2800->400x400 // copy rows, scale columns
400x400->900x400 // scale rows, copy columns

Unless the two resize operations are not actually separable (https://en.wikipedia.org/wiki/Separable_filter)?
Does scale row n ever use pixels from the row(s) above or below? I assumed not.

(dumb question?)





It would depend on the scaling algorithm. For example, bilinear looks at a 2x2 grid, bicubic 4x4 grid. Bicubic should be more adversely affected if you scale the lower dimension first

Computing width first vs. height or, vice versa are not bitexact, identical operations if image dimensions are not identical to begin with (square) . You can detect differences or visualize with amplified differences in the end result on any test. The question is whether or not they are significant, or under what conditions do they become significant

You can see issues on various test patterns .

(apologies, this was done in vapoursynth with zimg/z.lib, but the example should still apply to resizing order)

eg.
Test source 10bit RGB 2048x960 dpx patttern 0-1023 gradients for R,G,B,greyscale used the other vapoursynth thread .
http://www.mediafire.com/file/71x5rz8feku2bku/RGB_10bit_grad.7z

Convert/resize to YUV420P8, resize (width/2 then height/2) , or (height/2 then width/2)


v = core.imwri.Read(r'F:\_Video Tests\10bit Pattern Tests\RGB_10bit_grad.dpx')

v1 = core.resize.Bicubic(v, width=1024 , height=960, format=vs.YUV420P8, matrix_s="709", range_s="full")
v1 = core.resize.Bicubic(v1, width=1024 , height=480, format=vs.YUV420P8, matrix_s="709", range_s="full")

v2 = core.resize.Bicubic(v, width=2048 , height=480, format=vs.YUV420P8, matrix_s="709", range_s="full")
v2 = core.resize.Bicubic(v2, width=1024 , height=480, format=vs.YUV420P8, matrix_s="709", range_s="full")

i = core.std.Interleave(clips=[v1,v2])
i = core.hist.Luma(i)
i.set_output()


You can use MakeDiff to see the diff but I chose histogram.luma for this exagerrated look, but you can see the issue on the native image as well if you zoom in and have good eyes. You can see the alignment is "off" when resizing height first . The height first strategy will predispose you to more "banding" in post production, encoding later etc...

Quality wise, it makes more sense to me to resize the dimension with more pixels first - better for sampling


This is a 1:1 center crop , nearest neighbor x2 to show the issue
https://s9.postimg.org/40qqq6mdr/stack.png (https://postimages.org/)

poisondeathray
27th January 2018, 20:11
Did you consider that the "issue" goes away if you just do it normally?


core.resize.Bicubic(c, width=1024, height=480, format=vs.YUV420P8, matrix_s="709", range_s="full")



But the problem is... it does not go away


v3 = core.resize.Bicubic(v, width=1024 , height=480, format=vs.YUV420P8, matrix_s="709", range_s="full")

i = core.std.Interleave(clips=[v1,v2,v3])



Here are the full images after the histogram luma

In case it's not clear look at the intersections between the rows
http://www.mediafire.com/file/ehrjjjfigzbulc0/scalingtests.7z


again, a crop , 2x point resize

stackvertical (widthfirst, heightfirst, both)
https://s9.postimg.org/rwygvqlun/stack.png (https://postimages.org/)

poisondeathray
27th January 2018, 20:53
I am sure if you rotated the image, you would see the opposite "finding."


I used transpose, and it's not quite the "opposite" finding

But there are difference between all 3 - why wouldn't v2 and v3 be equivalent ?

For now, let's leave dithering out for a separate discussion. Just evaluate the order of operations on end result


By the way, 1024x960 and 2048x480 are exactly the same "area."

Yes, good point



See how there is no "problem" in "c"? All your observations are the artificial result of rounding.



Your "c" is the same as my "v3" . It's not the same. I even tried ffms2

So you're saying everything here is from rounding ?

poisondeathray
27th January 2018, 22:02
It does not matter if it is the same.


I'm saying horizontal first vs. vertical first is not the same. It's just an observation

You said "See how there is no "problem" in "c"? "

In this example, there is a "problem", or at least a difference. In this specific case, the bars at the intersections don't even line up when you resize height first, or if you do it "normally" . I would expect "doing it normally" in z.lib would be = resize height first, but that isn't the case here either.

ie. there is a difference between resizing horizontal first, vs vertical resizing. They do not produce bit identical results. ie. They are not the same. In this specific case, it happens that resizing horizontal first is clearly better . That might not be true for other cases. But clearly there is a difference.


If you use "core.register_format(vs.YUV, vs.FLOAT, 32, 1, 1)" as the intermediate, everything is bit-exact. But it doesn't matter to begin with.

No difference here. Maybe you're using a different version ?

EDIT: or did you mean just using float as the intermediate e.g. YUV444PS - in that case yes, all 3 cases are identical . Then your point about rounding errors makes more sense

poisondeathray
27th January 2018, 22:13
How can you "leave out" dithering when discussing rounding errors?


Because it's possible dithering can obscure underlying issues


You observe discrepancies in ordering because your image is constant in one direction. After you rotate the image, vertical-first becomes the "better" direction...
resize_h->round->resize_v->round
resize_v->round->resize_h->round
resize_v->resize_h->round

These are not the same operations... You are observing a discrepancy because resizing a constant image produces a constant result. It is not the resizing but the rounding that "moves" the bars in the first pass. The reason they do not move again in the second pass is because the image has been quantized to 8 bits already.


Ok this makes sense to me now, thanks


As for the rotate/transpose test:

vertical first was slightly better in some of the patterns, but the intersections were still bad in all 3.

The premise was resizing the "larger" dimension first would be better because of more information (although as you pointed out same area) so you would expect it to be "better" to resize vertical first in the rotated version, just like you would "expect" it to be "better" the horizontal in the 1st case . But this was just 1 test case, i think it' s just happenstance here and as you say a result of the quantizing/rounding errors

tormento
28th January 2018, 07:48
@pinterf

Do you remember this (https://forum.doom9.org/showthread.php?p=1771397#post1771397) topic about image corruption on pure white and regional settings that you solved?

Well, it happened again.

Yesterday night I was watching an encoded version of Hitman's bodyguard and it showed again, mostly on scene changes. I dunno if it still AviSynth+ fault. Let me grab it again from BD and will provide some raw material to work with and script.

pinterf
28th January 2018, 07:55
It was a decimal point or comma issue? I don't think we have the same problems here.

real.finder
28th January 2018, 09:17
@pinterf

Do you remember this (https://forum.doom9.org/showthread.php?p=1771397#post1771397) topic about image corruption on pure white and regional settings that you solved?

Well, it happened again.

Yesterday night I was watching an encoded version of Hitman's bodyguard and it showed again, mostly on scene changes. I dunno if it still AviSynth+ fault. Let me grab it again from BD and will provide some raw material to work with and script.

what masktools you use?

tormento
28th January 2018, 09:18
It was a decimal point or comma issue? I don't think we have the same problems here.
Here we go.

OS: Windows 10 ent x64 rs4 17083 italian

Environment:

VersionString: AviSynth+ 0.1 (r2580, MT, x86_64)
VersionNumber: 2.60
File / Product version: 0.1.0.0 / 0.1.0.0
Interface Version: 6
Multi-threading support: Yes
Avisynth.dll location: C:\WINDOWS\SYSTEM32\avisynth.dll
Avisynth.dll time stamp: 2017-12-27, 19:55:46 (UTC)
PluginDir2_5 (HKLM, x64): D:\Programmi\Media\AviSynth+\plugins64
PluginDir+ (HKLM, x64): D:\Programmi\Media\AviSynth+\plugins64+


[CPP 2.5 Plugins (64 Bit)]
D:\Programmi\Media\AviSynth+\plugins64\Dither-1.27.2.dll [2015-12-30]
D:\Programmi\Media\AviSynth+\plugins64\f3kdb-2.020140721-SAPikachu.dll [2015-02-19]

[CPP 2.6 Plugins (64 Bit)]
D:\Programmi\Media\AviSynth+\plugins64+\AutoAdjust-2.60.dll [2.6.0.0]
D:\Programmi\Media\AviSynth+\plugins64+\ConvertStacked.dll [2016-10-20]
D:\Programmi\Media\AviSynth+\plugins64+\DCTFilter-0.5.0-chikuzen.dll [0.5.0.0]
D:\Programmi\Media\AviSynth+\plugins64+\DirectShowSource.dll [2016-10-26]
D:\Programmi\Media\AviSynth+\plugins64+\FFT3dFilter-2.4-pinterf.dll [2.4.0.0]
D:\Programmi\Media\AviSynth+\plugins64+\ImageSeq.dll [2016-10-20]
D:\Programmi\Media\AviSynth+\plugins64+\KNLMeansCL-1.1.0.dll [2017-05-04]
D:\Programmi\Media\AviSynth+\plugins64+\MaskTools-2.2.12-pinterf.dll [2.2.12.0]
D:\Programmi\Media\AviSynth+\plugins64+\MedianBlur2-0.94-tp7.dll [2014-02-10]
D:\Programmi\Media\AviSynth+\plugins64+\MVTools-2.7.24-pinterf.dll [2.7.24.0]
D:\Programmi\Media\AviSynth+\plugins64+\RgTools-0.96-pinterf.dll [0.96.0.0]
D:\Programmi\Media\AviSynth+\plugins64+\Shibatch.dll [2016-10-20]
D:\Programmi\Media\AviSynth+\plugins64+\TimeStretch.dll [2016-10-20]
D:\Programmi\Media\AviSynth+\plugins64+\VDubFilter.dll [2016-10-20]

[Scripts (AVSI)]
D:\Programmi\Media\AviSynth+\plugins64+\colors_rgb.avsi [2015-03-21]
D:\Programmi\Media\AviSynth+\plugins64\CompTest.avsi [2010-09-05]
D:\Programmi\Media\AviSynth+\plugins64\DeHalo_alpha-realfinder.avsi [2017-02-26]
D:\Programmi\Media\AviSynth+\plugins64\Dither-1.27.2.avsi [2015-12-30]
D:\Programmi\Media\AviSynth+\plugins64\MT_xxpand_multi.avsi [2010-09-11]
D:\Programmi\Media\AviSynth+\plugins64\SMDegrain-3.1.2ú94-realfinder.avsi [2017-11-15]
D:\Programmi\Media\AviSynth+\plugins64\VHSHaloremover.avsi [2017-02-25]

[Uncategorized files]
D:\Programmi\Media\AviSynth+\plugins64+\AutoAdjust-2.60.txt [2015-11-15]
D:\Programmi\Media\AviSynth+\plugins64+\AviSynth-new.css [2016-03-31]
D:\Programmi\Media\AviSynth+\plugins64+\AviSynth.css [2016-03-31]
D:\Programmi\Media\AviSynth+\plugins64+\colors_rgb.txt [2015-03-21]
D:\Programmi\Media\AviSynth+\plugins64+\DCTFilter-0.5.0-chikuzen.md [2016-08-03]
D:\Programmi\Media\AviSynth+\plugins64+\FFT3dFilter-2.4-pinterf.gif [2005-04-04]
D:\Programmi\Media\AviSynth+\plugins64+\FFT3dFilter-2.4-pinterf.htm [2017-10-31]
D:\Programmi\Media\AviSynth+\plugins64+\FFT3dFilter-2.4-pinterf.txt [2017-06-08]
D:\Programmi\Media\AviSynth+\plugins64+\MaskTools-2.0a48.htm [2010-12-31]
D:\Programmi\Media\AviSynth+\plugins64+\MaskTools-2.2.12-pinterf.md [2018-01-07]
D:\Programmi\Media\AviSynth+\plugins64+\MedianBlur-0.84.txt [2004-12-07]
D:\Programmi\Media\AviSynth+\plugins64+\MVTools-2.7.24-pinterf.htm [2017-12-05]
D:\Programmi\Media\AviSynth+\plugins64+\MVTools-2.7.24-pinterf.md [2017-12-05]
D:\Programmi\Media\AviSynth+\plugins64+\RgTools-0.96-pinterf.md [2017-06-09]
D:\Programmi\Media\AviSynth+\plugins64\AviSynth-new.css [2016-03-31]
D:\Programmi\Media\AviSynth+\plugins64\AviSynth.css [2016-03-31]
D:\Programmi\Media\AviSynth+\plugins64\Dither-1.27.2.htm [2015-12-30]
D:\Programmi\Media\AviSynth+\plugins64\f3kdb-2.020140721-SAPikachu.htm [2015-02-19]
D:\Programmi\Media\AviSynth+\plugins64\SMDegrain-3.1.2ú93-realfinder_avsi [2017-05-05]
D:\Programmi\Media\AviSynth+\plugins64\SMDegrain-3.1.2d.htm [2015-07-21]

Script:
SetMemoryMax(8000)
SetFilterMTMode("DEFAULT_MT_MODE", 2)
SetFilterMTMode("ChangeFPS", 3)

SetFilterMTMode("DGSource", 3)
LoadPlugin("D:\eseguibili\media\DGDecNV\x64\DGDecodeNV.dll")
DGSource("E:\in\1_58 Hitman's bodyguard\hitman01.dgi")

ChangeFPS(last,last,true)

SMDegrain (tr=4,PreFilter=4,thSAD=400,contrasharp=false,refinemotion=false,truemotion=true,plane=4,chroma=true,lsb=true,mode=0)

Prefetch(6)

Hitman's raw.7z (http://www21.zippyshare.com/v/uxocHvV9/file.html)
Hitman's enc.7z (http://www21.zippyshare.com/v/PmudiFm7/file.html)
Hitman's dgi.7z (http://www21.zippyshare.com/v/bLaD6Iz1/file.html)
Hitman's dgi avs.7z (http://www21.zippyshare.com/v/FE0IOf0W/file.html)

Enjoy. ;)

real.finder
28th January 2018, 09:29
Hitman's raw.7z (http://www21.zippyshare.com/v/uxocHvV9/file.html)
Hitman's enc.7z (http://www21.zippyshare.com/v/PmudiFm7/file.html)
Hitman's dgi.7z (http://www21.zippyshare.com/v/bLaD6Iz1/file.html)
Hitman's dgi avs.7z (http://www21.zippyshare.com/v/FE0IOf0W/file.html)

Enjoy. ;)

I just see hitman01.mkv and hitman02.mkv they not same as old bug, I think they are new bug in mvtools or something, try with older versions of mvtools

edit: after see the others, it's kinda like the old one, try with older masktools too, and then try with tv_range=false if even old masktools not work

tormento
28th January 2018, 09:43
I just see hitman01.mkv and hitman02.mkv they not same as old bug, I think they are new bug in mvtools or something, try with older versions of mvtools

edit: after see the others, it's kinda like the old one, try with older masktools too, and then try with tv_range=false if even old masktools not work
Reverting to previous versions of MVTools and MaskTools did not solve, tv_range=false yes.
Something wrong in avisynth again or SMDegrain? Strange 264 input?
Tried also with up to 2 versions of AviSynth back, i.e. up to 2544.

real.finder
28th January 2018, 10:08
if only tv_range=false solve it then yes the old bug is back, try with many avs+ versions until you get the one that work

tormento
28th January 2018, 10:19
if only tv_range=false solve it then yes the old bug is back, try with many avs+ versions until you get the one that work
Using too old AviSynth versions throws no ExtractU function. Can't remember since when it was introduced.

We definitely need Pinterf help :)

EDIT: I have tried every version back to 2420 and got same error. From 2294 and before, I get no ExtractU function and can't test.

raffriff42
28th January 2018, 15:08
In all RGB Planar modes, Subtitle colors appear with R and G swapped
Colorbars
ConvertToPlanarRGBA
tc = $ff00 ## green
Subtitle(Hex(tc), text_color=tc, size=56, align=5)
return ConvertToRGB32 ## for viewing purposes
https://www.dropbox.com/s/nkcx847vfo9mxl9/subtitle-RGPx-2018-01.png?raw=1

pinterf
28th January 2018, 17:41
In all RGB Planar modes, Subtitle colors appear with R and G swapped
Thanks, fixed.

pinterf
28th January 2018, 18:59
Here we go.
OS: Windows 10 ent x64 rs4 17083 italian
Enjoy. ;)
Thanks, almost as enjoyable as the 8th hour in an ultra running race :)
This one is different though.

In the old (fixed) problem the String(1.04) yielded "1,04" instead of "1.04" in our windows input local. It was fixed to always using decimal _point_ for separator (input local = "C language"), because dither tools' lut interpreter could not recognize constants with commas as decimal separator. Now it's s different problem since I can see only decimal points in the expression.
Since then I was also moving to Win10 and see the problem (I'm testing with another clip): greyish/burnt out parts in fast moving scenes.

pinterf
28th January 2018, 19:50
if only tv_range=false solve it then yes the old bug is back, try with many avs+ versions until you get the one that work

The old bug is back, but now it's dither_lut16 is the culprit.
It seems that under Win10 (?) configuration it understands only the decimal separator of the current input local.

Just replace the decimal point to commas in yexpr parameter and it will work fine. (the used ReplaceStr is built-in in AVS+)

function Dither_Luma_Rebuild (clip src, float "s0", float "c",int "uv", bool "lsb", bool "lsb_in", bool "lsb_out", int "mode", float "ampn", bool "slice"){
[...]
src
lsb ? (lsb_in ? Dither_lut16 (yexpr=ReplaceStr(e,".",","),expr="x 32768 - 32768 * 28672 / 32768 +",y=3, u=uv, v=uv) : \
Dither_lut8 (yexpr=ReplaceStr(e,".",","),expr="x 128 - 32768 * 112 / 32768 +" ,y=3, u=uv, v=uv)) : \
avs26 ? mt_lut(yexpr=e,expr="x range_half - range_half * 112 scaleb / range_half +",y=3, u=uv, v=uv) : \
mt_lut(yexpr=e,expr="x 128 - 128 * 112 / 128 +" ,y=3, u=uv, v=uv)

[...]
}

And one more remark. When you want to scale the YUV TV range limits 16-235, 16-240, or their difference (like 112 = (240-16)/2), use scaleb instead of scalef. scaleb correctly converts "official" bit-shifted limits (e.g. 16*4, 235*4: 64-940 for 10 bits), while scalef (Scale _F_ull range) is for stretching a range of 0-255,1023,4095,16383,65535 to another bit-depth's full range of 0..255,1023,4095,16383,65535. So 235 in a 8bit world would become 235*1023/255 = 942 in 10 bits, which is not correct.

real.finder
29th January 2018, 00:06
The old bug is back, but now it's dither_lut16 is the culprit.
It seems that under Win10 (?) configuration it understands only the decimal separator of the current input local.

Just replace the decimal point to commas in yexpr parameter and it will work fine. (the used ReplaceStr is built-in in AVS+)

function Dither_Luma_Rebuild (clip src, float "s0", float "c",int "uv", bool "lsb", bool "lsb_in", bool "lsb_out", int "mode", float "ampn", bool "slice"){
[...]
src
lsb ? (lsb_in ? Dither_lut16 (yexpr=ReplaceStr(e,".",","),expr="x 32768 - 32768 * 28672 / 32768 +",y=3, u=uv, v=uv) : \
Dither_lut8 (yexpr=ReplaceStr(e,".",","),expr="x 128 - 32768 * 112 / 32768 +" ,y=3, u=uv, v=uv)) : \
avs26 ? mt_lut(yexpr=e,expr="x range_half - range_half * 112 scaleb / range_half +",y=3, u=uv, v=uv) : \
mt_lut(yexpr=e,expr="x 128 - 128 * 112 / 128 +" ,y=3, u=uv, v=uv)

[...]
}

And one more remark. When you want to scale the YUV TV range limits 16-235, 16-240, or their difference (like 112 = (240-16)/2), use scaleb instead of scalef. scaleb correctly converts "official" bit-shifted limits (e.g. 16*4, 235*4: 64-940 for 10 bits), while scalef (Scale _F_ull range) is for stretching a range of 0-255,1023,4095,16383,65535 to another bit-depth's full range of 0..255,1023,4095,16383,65535. So 235 in a 8bit world would become 235*1023/255 = 942 in 10 bits, which is not correct.

yes that right, will did next time when do update, in fact I stopped updating scripts waiting for the new changes of bit convert, even if SMDegrain don't need those changes, I will do adding some parameters that come with the next update of masktools to make sure that no one will run it with older masktools and get some wrong outputs like https://forum.doom9.org/showthread.php?p=1813270#post1813270

tormento
29th January 2018, 14:01
I stopped updating scripts waiting for the new changes of bit convert
Could you please release an intermediate version to make things usable now? :p

I applied the fix proposed from Pinterf and things are working. Dunno if other mods are needed.

real.finder
29th January 2018, 14:09
Could you please release an intermediate version to make things usable now? :p

I applied the fix proposed from Pinterf and things are working. Dunno if other mods are needed.

find and replace what Pinterf edit in his last post then

Aktan
2nd February 2018, 15:57
I find that these two return different Stack16 clips, am I missing something?

#YV16 Source 8-bit
ConvertBits(bits=32)
ConvertBits(bits=16)
ConvertToStacked()

#YV16 Source 8-bit
ConvertBits(bits=16)
ConvertBits(bits=32)
ConvertBits(bits=16)
ConvertToStacked()

StainlessS
20th February 2018, 17:53
This would be nice addition to +.


RT_BitSetCount(int)
Return an int, the count of the number of set bits (1's) in arg int.
NOTE, Previous Bit functions are similar to the v2.6 bit manipulation functions, however this one has no equivalent in v2.6
[perhaps it should, it is quite handy, as used in the ApparentFPS() script prototype)]

BitClrCount easily calc'd from above.

EDIT: Here, S_ApparentFPS(), ApparentFPS prototype script function, would have been difficult/impossibly_slow without RT_BitSetCount.
https://forum.doom9.org/showthread.php?p=1698788#post1698788
EDIT: This line, about 80% of the way through the script function.

Unique = RT_BitSetCount(BITS0) + RT_BitSetCount(BITS1) + RT_BitSetCount(BITS2) + RT_BitSetCount(BITS3) +
\ RT_BitSetCount(BITS4) + RT_BitSetCount(BITS5) + RT_BitSetCount(BITS6) + RT_BitSetCount(BITS7)

Above script function limited to 256 frame sample spread, was later increased to 1024 frames for plugin only (@ request of Scharfis_Brain, would maybe be a bit much for the script function, even with BitSetCount).

pinterf
21st February 2018, 14:43
This would be nice addition to +.


RT_BitSetCount(int)
Return an int, the count of the number of set bits (1's) in arg int.
NOTE, Previous Bit functions are similar to the v2.6 bit manipulation functions, however this one has no equivalent in v2.6
[perhaps it should, it is quite handy, as used in the ApparentFPS() script prototype)]

BitClrCount easily calc'd from above.


This one?
https://stackoverflow.com/questions/109023/how-to-count-the-number-of-set-bits-in-a-32-bit-integer

RT_xxx collection have quite a few useful function, do you (or others) recommend to cherry-pick some of them, which are worth of integration and futureproof?

Edit:
- New script function: int BitSetCount(int[,int, int, ...])
Function accepts one or more integer parameters
Returns the number of bits set to 1 in the number or the total number of '1' bits in the supplied integers.

real.finder
21st February 2018, 20:54
since the topic now is runtime, pinterf can you have a look at https://forum.doom9.org/showthread.php?t=175212

and any news about fix the old mt problem with runtime?

StainlessS
22nd February 2018, 13:42
This one?
https://stackoverflow.com/questions/109023/how-to-count-the-number-of-set-bits-in-a-32-bit-integer

From StackOverflow: (Looks more efficient than my naive effort).

int numberOfSetBits(int i)
{
// Java: use >>> instead of >>
// C or C++: use uint32_t
i = i - ((i >> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
}


From RT_Logic.cpp (my naive effort)

env->AddFunction("RT_BitSetCount","i",RT_BitSetCount, 0);
AVSValue __cdecl RT_BitSetCount(AVSValue args, void* user_data, IScriptEnvironment* env) {
unsigned int n = (unsigned int)args[0].AsInt();
int cnt=0;
for(int i=0;i<32;n>>=1,++i)
if(n&0x01) ++cnt;
return (int)cnt;
}

I think I recently saw some Intrinsic to count number of set bits, not sure, might have been for 64 bit only.

I dont think avs 2.6 implements Arithmetic Shift Left, just Logical Shift Left, probably not needed but I also
implemented in RT_.


Edit:
- New script function: int BitSetCount(int[,int, int, ...])
Function accepts one or more integer parameters
Returns the number of bits set to 1 in the number or the total number of '1' bits in the supplied integers.
Oh My, I had not even considered multiple args to BitSetCount, very nice :)

This one?
RT_xxx collection have quite a few useful function, do you (or others) recommend to cherry-pick some of them, which are worth of integration and futureproof?


Here, some suggested additions.

From RT_File.cpp

env->AddFunction("RT_FileDelete", "s",RT_FileDelete, 0);

env->AddFunction("RT_WriteFile", "ss.*[Append]b",RT_WriteFile, 0);


From RT_Call.cpp, call external command [EDIT: Most often used to delete a file, prior to RT_FileDelete.]

env->AddFunction("RT_Call", "s[Hide]b[Debug]b", RT_Call, 0);



From RT_Debug.cpp [EDIT: In desparate need of this one, probably the singularly most useful function]

env->AddFunction("RT_DebugF", "s.*[name]s[tabsz]i", RT_DebugF, 0);


From RT_Func.cpp,

# Mod, add width arg.
env->AddFunction("RT_Hex", "i[width]i",RT_Hex, 0);

RT_Hex(int , int "width"=0)
First arg is an integer to convert to a hexadecimal string.
Width, (0, 0 -> 8) is the minimum width of the returned string.
eg RT_Hex(255,4) returns "00FF".

AVSValue __cdecl RT_Hex(AVSValue args, void* user_data, IScriptEnvironment* env) {
int n = args[0].AsInt();
int wid = args[1].AsInt(0);
wid=(wid<0) ? 0 : (wid > 8) ? 8 : wid;
char buf[8+1];
sprintf(buf,"%0*X",wid,n);
return env->SaveString(buf); // Get pointer to Avisynth saved string
}

# Mod, add pos arg.
RT_HexValue(String,"pos"=1)
Returns an int conversion of the supplied hexadecimal string.
Conversion will cease at the first non legal number base digit, without producing an error
Fixes HexValue bug in 2.58 & 2.6a3. eg "FFFFFFFF" returns 2147483647 (0x7FFFFFFF) instead of the correct -1 (As most/all calculators)
Bug is fixed in Avisynth v2.6a4.
v1.14, Added optional pos arg default=1, start position in string of the HexString, 1 denotes the string beginning. Will return 0
if error in 'pos' ie if pos is less than 1 or greater than string length.

env->AddFunction("RT_HexValue", "s[pos]i",RT_HexValue, 0);

AVSValue RT_HexValue(AVSValue args, void*, IScriptEnvironment* env) {
const char *str = args[0].AsString();
int pos = args[1].AsInt(1) - 1;
int sz=strlen(str);
if(pos<0 || pos>=sz)
return 0;
str+=pos;
char *stopstring;
return (int)(strtoul(str,&stopstring,16));
}

# Mod
env->AddFunction("RT_NumberString", "i[base]i[width]i",RT_NumberString, 0);

RT_NumberString(int ,int "base"=10, int "width"=0)
First arg is an integer to convert to a number base/radix string.
Base, (10, 2 -> 36), is the number base or radix, eg 2 == Binary, 8 == Octal, 10 == Denary/Decimal, 16 == Hexadecimal.
The default of 10 (decimal) will just convert a number to its decimal string equivalent possibly with a '-' minus sign.
All number bases with the exception of decimal, will be unsigned form, ie -1 to hexadecimal will produce "FFFFFFFF",
(the sign is in the digits rather than as separate 'sign and magnitude' used in decimal representation).
The digits used for the base are, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ". Binary uses first two; decimal, the first 10;
Hexadecimal the first 16; base 36 all 36 digits.
Width, (0, 0 -> 32) is the minimum width of the returned string.
eg RT_NumberString(255,16,4) returns "00FF".
To convert a Float to a decimal string use Avisynth native "String()" func.

# Mod
env->AddFunction("RT_NumberValue", "s[base]i[pos]i",RT_NumberValue, 0);

RT_NumberValue(String,int "base"=10,int "pos"=1)
Returns an int conversion of the supplied number base string.
Base, (10, 2 -> 36) is the number base that the string uses.
To convert a Decimal string to a Float, use Avisynth native "Value()" func.
Conversion will cease at the first non legal number base digit, without producing an error.
eg RT_NumberValue("1100",2) returns 12 from the binary string.
v1.14, Added optional pos arg default=1, start position in string of the number string, 1 denotes the string beginning. Will return 0
if error in 'pos' ie if pos is less than 1 or greater than string length.



from RT_Odds.cpp

env->AddFunction("RT_VarExist", "s",RT_VarExist, 0);

env->AddFunction("RT_VarType", ".",RT_VarType, 0);

env->AddFunction("RT_Ord", "s[pos]i",RT_Ord, 0);

env->AddFunction("RT_TimerHP", "",RT_TimerHP, 0);

env->AddFunction("RT_GetSystemEnv", "s",RT_GetSystemEnv, 0);

env->AddFunction("RT_GetFileTime", "si",RT_GetFileTime, 0);

env->AddFunction("RT_LocalTimeString", "[file]b",RT_LocalTimeString, 0);


from RT_String.cpp

env->AddFunction("RT_StrReplace", "sss[sig]b",RT_StrReplace, 0);

# Replace multiple strings, not so often used but is very powerful, allows for a sort of macro language where
# strings can replace substrings of already replaced strings.

env->AddFunction("RT_StrReplaceMulti", "sss[sig]b",RT_StrReplaceMulti, 0);

env->AddFunction("RT_StrPad", "si[c]s",RT_StrPad, 0);

# Mod,
env->AddFunction("RT_FindStr", "ss[sig]b[pos]i",RT_FindStr, 0);

# Must have. Although take source from RT_Stats v2.0, with bug fix. Or from StrFmt() plugins, also suggest StrFmt as name.
AVSValue __cdecl RT_String(AVSValue args, void* user_data, IScriptEnvironment* env);

env->AddFunction("RT_String", "s.*[esc]i",RT_String, 0);

StrFmt():- https://forum.doom9.org/showthread.php?t=174649&highlight=StrFmt
EDIT: StrFmt does not support the Esc arg, probably best omitted as StrFmt does (Esc arg, very demanding on script developer).

from RT_Sundry.cpp

env->AddFunction("RT_ColorSpaceXMod", "c",RT_ColorSpaceXMod, 0);

env->AddFunction("RT_ColorSpaceYMod", "c[Laced]b",RT_ColorSpaceYMod, 0);


EDIT: Additional from RT_String.cpp

env->AddFunction("RT_TxtAddStr", "ss+",RT_TxtAddStr, 0);

RT_TxtAddStr(String, String s1, ... , String sn)
Non-clip function.
Function to concatenate (join together) 2 or more strings with Chr(10) line separators.
If the first string is an empty string ("") it will not have a newline [Chr(10)] appended.
All other strings even empty strings will have a newline [Chr(10)] inserted after them
(if they dont already have a trailing newline).
Any source string containing carriage return Chr(13) will have them converted to Chr(10).
X = RT_TxtAddStr("A","B","C") same as X = "A" + Chr(10) + "B" + Chr(10) +"C" + Chr(10)
X = RT_TxtAddStr("","A","B","C") same as X = "" + "A" + Chr(10) + "B" + Chr(10) + "C" + Chr(10)

env->AddFunction("RT_TxtQueryLines", "s",RT_TxtQueryLines, 0);

RT_TxtQueryLines(String)
Non-clip function.
String, the multiline string that you require a line count from.
Returns the number of Newline [Chr(10)] separated lines in a multiline string.
The last line does not have to be Chr(10) terminated, it still counts. [EDIT: awkward/slow to do in script alone]

env->AddFunction("RT_TxtGetLine", "s[Line]i",RT_TxtGetLine, 0);

RT_TxtGetLine(String, Int "Line"=0)
Non-clip function.
Extract a single line from a multiline Newline[Chr(10)] separated string. Default=0 == first line.
The Line index is Zero Relative like frame number versus FrameCount.
The returned string has trailing Newlines and carriage returns stripped from it.
Throws an error if your requested line is >= to the number of lines in the multiline string.

EDIT: Above stuff for use where strings can be used as a sort of simple array.

pinterf
22nd February 2018, 15:08
I think I recently saw some Intrinsic to count number of set bits, not sure, might have been for 64 bit only.


POPCNT, don't think it's our bottleneck if I'm omitting that


I dont think avs 2.6 implements Arithmetic Shift Left, just Logical Shift Left, probably not needed but I also
implemented in RT_.

No difference for left shift. Right is arithmetic because it copies MSB instead of filling in zeros.


RT_Hex(int , int "width"=0)

Done. Did you know that in avs+ the hex string was in lowercase?


# Mod, add pos arg.
RT_HexValue(String,"pos"=1)

Done. -1 bug was not present, probably the fix was pulled from classic avs


from RT_String.cpp
env->AddFunction("RT_StrReplace", "sss[sig]b",RT_StrReplace, 0);

ReplaceStr exists already in avs+, and I was just about adding a 'case insensitive' parameter. Probably I'll keep your parameter naming.

I'll look at the rest later.

StainlessS
22nd February 2018, 15:23
Yep, PopCnt looks familiar.

No difference for left shift. Right is arithmetic because it copies MSB instead of filling in zeros.
Yep, I sort of remembered that, but not sure, long since I've done Z80, M68K assembler.

Done. Did you know that in avs+ the hex string was in lowercase?
Yeh, think I remember that avs uses lower case, I dont like that and would almost always output uppercase (personal prefs).
[EDIT: Almost obligatory to use uppercase for hex on M68K machines]

I'll look at the rest later.
Cool :cool:

raffriff42
22nd February 2018, 15:34
I have been working on some AVS+ enhancement routines for months without promoting it.
http://avisynth.nl/images/Utils-r41.avsi

The more useful ones (they're essential, to me anyway) are listed below.

The single most useful function (if I had to pick one) is MatchColorFormat - match color format to a template clip.
Use this before splicing or stacking two clips when you're not sure of their current color formats.


### MISCELLANEOUS FUNCTIONS

### return true if running in Avisynth+, false otherwise
#@ function IsAvsPlus()

### return AVS+ build number, if present; else 0
#@ function VersionBuildNumber()

### return basic clip properties as a string
## Example | Assert(false, InfoString) ## show info about current Last variable
#@ function InfoString(val C, string "label")

### STRING FUNCTIONS

### count the number of line breaks (for multi-line Subtitle(align=1|2|3)
#@ function CountLines(string s, bool "lsp")

### Split long lines for [[Subtitle]] line wrap
#@ function SplitLines(string s, int "lastcol", bool "reflow")

### trim spaces from both ends of string
#@ function Trim(string s)

### trim spaces from left end of string
#@ function TrimLeft(string s)

### Get part of a full path to right of last '\'
#@ function GetNameFromPath(string path)

### Get part of a full path to left of last '\'
#@ function GetParentFolder(string path)

### format seconds as hh:mm:ss.ddd
#@ function FormatTime(float fsec, int "decimals")

### format hours/minutes/seconds as hh:mm:ss.ddd
#@ function FormatTime(int t_hours, int t_mins, float t_secs, int "decimals")

### for bits==32, return "S", else return String(bits)
#@ function BitsToPixelType(int bits)

### NUMERIC FUNCTIONS

### return argument 'f' as integer and ensure it is modulo 'm'
#@ function modx(int m, float f, int "dir")

### Hex() with leading "0" if less than 2 chars long
#@ function Hex2(int i)

### scale [[ColorYUV]]'s 'gain_x', 'gamma_x' & 'cont_x'
### to more intuitive values (like [[Tweak]]'s)
#@ function f2c(float f)

### calculate new width, given height, for preserving aspect ratio
#@ function CalcWidth(clip C, float fhgt, int "mod", int "lim")

### calculate new height, given width, for preserving aspect ratio
#@ function CalcHeight(clip C, float fwid, int "mod", int "lim")

### DEEP COLOR ARGUMENT SCALING FUNCTIONS

### scale an 8-bit value for target clip 'T'
#@ function sc8f(clip T, float f, bool "cx")

### scale an 8-bit value for target clip 'T'; clamp output
#@ function sc8x(clip T, float f)

### scale an 8-bit value for target clip 'T'; string result
#@ function sc8s(clip T, float f, int "decimals")

### UTILITY FILTERS

### Convert from anything to planar RGB(A)
#@ function ToRGB(clip C, string "matrix", int "bits_out", val "A")

### Convert from anything to YUV(A)444
#@ function To444(clip C, string "matrix", int "bits_out", val "A")

### Convert from anything to YUV(A)422
#@ function To422(clip C, string "matrix", int "bits_out", val "A")

### Convert from anything to YUV(A)420
#@ function To420(clip C, string "matrix", int "bits_out", val "A")

### Convert from anything to best equivalent 16-bit version
#@ function To16bit(clip C, clip "A")

### Convert from anything to best equivalent higher-bit-depth version
#@ function ToHibit(clip C, int bits, clip "A")

### Convert from anything to best equivalent lower-bit-depth version
#@ function ToLobit(clip C, int bits, bool "dither", clip "A")

### Convert from anything to 'best' (v2.6x compatible) equivalent 8-bit version
#@ function To8bit(clip C, bool "dither")

### make changes needed to display on vdubFM (VirtualDub FilterMod)
#@ function ToVdubFM(clip C, bool "dither")

### Match color format of source 'C' to template 'T'
#@ function MatchColorFormat(clip C, clip T, string "matrix", bool "keepbits", bool "dither")

### Match audio properties of source 'C' to template 'T'
#@ function MatchAudioFormat(clip C, clip T, bool "allowresample")

### convert levels from 'TV' (black=16d, white=235d) to 'PC' (black=0, white=255d)
#@ function ToPC(clip C)

### convert levels from 'PC' (black=0, white=255d) to 'TV' (black=16d, white=235d)
#@ function ToTV(clip C)

### 709->601 (less green, more red)
#@ function To601(clip C)

### 601->709 (more green, less red)
#@ function To709(clip C)

### remove sRGB gamma transfer function (if bit depth > 8) for linear-light processing
### ( used in [[#ScaleZoom]], [[#ScaleSize]] )
#@ function remove_gamma(clip C, bool "enable", string "matrix")

### apply standard gamma transfer function (if bit depth > 8)
#@ function restore_gamma(clip C, bool "enable", string "matrix")

### COLOR AND OVERLAY FILTERS

### scale 0-255 [[Levels]] arguments to current bit depth
#@ function Levelsc(clip C,
##\ float input_low, float gamma, float input_high,
##\ float output_low, float output_high, bool "coring",
##\ bool "dither", bool "chroma")

### Enhanced [[SGradation]]; semi-independent control of highlights & lowlights
#@ function SGradation2D(clip C,
##\ float loBoost, float hiCut,
##\ float "bluSat", float "yelSat",
##\ float "redSat", float "grnSat", bool "tvrange")

### [[Layer]] with support for 'mask', 'opacity' and 'align' parameters
#@ function LayerAligned(clip base, clip over, string "op", int "level",
##\ clip "mask", float "opacity", int "align")

### [[Overlay]] with support for 'align' parameter
### supports adding borders to, or letterboxing, inset clip
#@ function OverlayAligned(clip base, clip over,
##\ int "x", int "y", clip "mask", float "opacity", string "mode",
##\ bool "greymask", string "output", bool "ignore_conditional",
##\ bool "pc_range", int "align", int "borderwidth", int "bordercolor")


### CROP, RESIZE AND TRANSFORM FILTERS

### alias for [[#Cropd]] with argument order: Left, Right, Top, Bottom
#@ function CropLRTB(clip C, int left, int right, int top, int bottom, bool "align", int "mod")

### alias for [[#Cropd]] with argument order: Left, Top, Width, Height
#@ function CropLTWH(clip C, int left, int top, int width, int height, bool "align", int "mod")

### show a helpful diagnostic string on [[Crop]] failure; optionally enforce [[Mod]]
#@ function Cropd(clip C, int x, int y, int wid, int hgt, bool "align", int "mod")

### switch (or fade) between three [[Resize]] clips depending on scale factor
### (overridable with user-specified resizers e.g. nnedi3 etc)
### (ScaleZoom sizes by percent; ScaleSize by width and/or height)
#@ function ScaleZoom(clip C, float factor, int mod,
##\ string "sm", string "med", string "lg",
##\ float "thrSm", float "thrLg", bool "fade", bool "ident",
##\ bool "gamma", bool "hibit")

### switch (or fade) between three [[Resize]] clips depending on scale factor
### (overridable with user-specified resizers e.g. nnedi3 etc)
### (ScaleZoom sizes by percent; ScaleSize by width and/or height)
#@ function ScaleSize(clip C, float fwid, float fhgt, int mod,
##\ string "sm", string "med", string "lg",
##\ float "thrSm", float "thrLg", bool "fade", bool "ident",
##\ bool "gamma", bool "hibit")

### crop or expand a clip to ensure it is a certain size (symmetrically by default)
#@ function CropEx(clip C, float wid, float hgt, int "mod",
##\ int "align", int "dx", int "dy", bool "debug")

### quick Gaussian blur
#@ function QGaussBlur(clip C, float radx, float "rady")

### DEBUGGING FILTERS

### [[Eval]] a script snippet; show script & its return value (clip or nonclip)
#@ function EvalShow(clip C, string s, string "font", float "size",
##\ int "text_color", int "halo_color",
##\ float "x", float "y", int "align", string "name")

### return color ramp clip w/ same specs as template clip 'T'
#@ function ColorRampEx(clip T, int "left_color", int "right_color", int "height",
##\ bool "zigs", bool "stack", int "noise")

### return grayscale ramp clip w/ same specs as template clip 'T'
#@ function Grayramp(clip T, int "height", bool "zigs", bool "stack", int "noise")

### YUV/RGB vectorscope (inverted so red is top-left and hue increases counter-clockwise)
#@ function Vector2(clip C, string "matrix", bool "bottom")

### Classic [[Histogram]], waveform on top (or on bottom); supports RGB
### many little enhancements; accepts both YUV & RGB
#@ function HistogramTurn(clip C, bool "parade", bool "shrink", bool "bottom")

### show video waveform + vectorscope; many little enhancements; accepts both YUV & RGB
#@ function ScopeR(clip C, bool "shrink", bool "vector", string "matrix", bool "parade", bool "bottom")

### Simple waveform + vectorscope. Accepts 8-bit, YUV(A) only.
#@ function ScopeY(clip C, bool "shrink", bool "vector", bool "levels", bool "bottom")

### print color channel statistics on the screen
### (auto switch between RGBAdjust(analyze=true) and ColorYUV(analyze=true)
### @ format - optional nicer formatting
#@ function Analyze(clip C, bool "format")

### show original & 3 channels (Y, U, V or R, G, B) in quad split
#@ function ShowChannels(clip C, bool "analyze", bool "uinvert", bool "chroffset")

### [[ShowFrameNumber]] with support for 'opacity' and 'align'
#@ function ShowFrameNumberAligned(
##\ clip C, bool "scroll", int "offset",
##\ float "x", float "y", string "font", int "size",
##\ int "text_color", int "halo_color",
##\ float "font_width", float "font_angle",
##\ float "opacity", int "align")

StainlessS
22nd February 2018, 15:47
### show original & 3 channels (Y, U, V or R, G, B) in quad split
#@ function ShowChannels(clip C, bool "analyze", bool "uinvert", bool "chroffset")

Presumably in honour of my plugin ShowChannels :)

EDIT: https://forum.doom9.org/showthread.php?t=163829&highlight=ShowChannels

ShowChannels:-

Typical output for a YUV clip:-
---------------------------

347 ] Frames Visited = 348

This Frame Accumulated
Y U V Y U V
Ave 77.00 125.52 125.42 70.91 125.87 125.78
Min 4 80 95 0 69 83
Max 255 177 165 255 190 174
~Min 14 95 101 12 92 101
~Max 234 167 148 235 167 151

---------------------------

where
'AVE' shows average for current frame and accumulated average for all visited frames.

'MIN' shows minimum value for a channel, this frame and accumulated.

'MAX' shows maximum value for a channel, this frame and accumulated.

'~MIN' shows loose minimum value for a channel, this frame and accumulated.

'~MAX' shows loose maximum value for a channel, this frame and accumulated.

Loose minimum uses the filter arg float MinPerc, a percentage of total pixels to ignore
when finding the loose minimum, allows to ignore extreme stray pixels (noise).

Loose maximum uses the filter arg float MaxPerc, a percentage of total pixels to ignore
when finding the loose maximum, allows to ignore extreme stray pixels (noise).

The "loose" values are made to filter out very bright
or very dark noise creating an artificially low or high minimum / maximum.

The Accumulated Ave is a "Average of Averages", or "Average Mean" or "Mean Average", take your pick but accumulated seemed more appropriate
considering that it was not restricted to describing just the averages. Accumulated Min is the minimum of all minimums so far, etc.

pinterf
22nd February 2018, 17:05
I have been working on some AVS+ enhancement routines for months without promoting it.
http://avisynth.nl/images/Utils-r41.avsi

Really nice collection.

Note#1
Why do you need to ##HACK in function GBR2YUV(clip C, bool "yuva")? Packed RGB is upside down (unlike planar RGB), but you are flipping not all the three 'planes', why?

Note#2
In restore_gamma (and where luts are used) you can use the Expr function for 32bit float case. Single 8-16bit lut is faster now with mt_lut, but for 32bit float would help (rare use case nowadays). In general I recommend using scalef and scaleb instead of @F @B, Expr supports only the word ones.
Another comment: 255 @F (255 scalef) is better written as 'range_max'

I'm planning to make Expr to automatically recognise fast (8-16 bit mt_lut and 8 bit mt_lutxy-like) cases and automatically turn them into real LUT working mode).

Note#others.. later, too much new stuff for today :)

Atak_Snajpera
22nd February 2018, 17:47
Sorry for interrupting but can somebody tell me why Prefetch does not like my subtitle rendering script on YUV420P10? Image flashes and eventually script crashes my player (MPC-HC).
If I remove video=Prefetch(video,8) then everything is ok.

Test script (video.avs)
http://www.mediafire.com/file/c9n8ml9gr1rby1v/AviSynth%20MT%20Prefetch%20issues.7z

LigH
22nd February 2018, 21:05
@StainlessS:

Would you consider providing a CHM documentation for a recent AviSynth+ state again if collecting all the differences to AviSynth 2.60 doesn't mean too much efforts?

pinterf
22nd February 2018, 21:25
Sorry for interrupting but can somebody tell me why Prefetch does not like my subtitle rendering script on YUV420P10? Image flashes and eventually script crashes my player (MPC-HC).
If I remove video=Prefetch(video,8) then everything is ok.

Test script (video.avs)
http://www.mediafire.com/file/c9n8ml9gr1rby1v/AviSynth%20MT%20Prefetch%20issues.7z
Thanks, good report. For me it crashed after 41-42 seconds: 6399, 6319, 6369 are the frame numbers that avsmeter64 is showing before the crash.
When using Trim(5000,..) the crash occurs at around frame 1400.
I suspect something in the subtitle text around that spot.

EDIT: debugging in avs+ (arrrgh, perhaps because the debug build is slower, it was the 5th run until it gave error, unlike the release build which crashed 100%)

It stopped at
frame = ChildFilters[env2->GetProperty(AEP_THREAD_ID)]->GetFrame(n, env);
with message: Exception thrown at 0x00007FFCBBB6C909 (VSFilter.dll) in AVSMeter64.exe: 0xC0000005: Access violation writing location 0x0000000000000000. occurred

Atak_Snajpera
22nd February 2018, 21:41
Script won't crash if we use SetFilterMTMode("TextSub",MT_SERIALIZED) but this still does not fix flashing (frame corruption) of the whole frame.
It is more noticeable if you put real video instead of BlankClip

http://i.cubeupload.com/TscvHT.png

pinterf
22nd February 2018, 21:47
Does it have a source? Searched on it and there is VsFilter, xy-vsfilter, etc.. I'm not familiar with them.