Log in

View Full Version : AviSynthShader + SuperRes


Pages : 1 2 3 [4] 5 6 7 8 9 10 11 12 13

foxyshadis
30th November 2015, 07:29
I should point out that rgb 255*16 and yuv 235*16 is defined to be white in 16-bit mode, specifically so you don't have to compensate for 255.9 or anything like that. So it should be divided by 255.0 to get 0-1.0 and then multiplied back by 255. Using anything else probably won't really hurt, it's float after all, but using different constants will cause a slight shift.

MysteryX
30th November 2015, 16:47
OK I've done more testing on it after getting some sleep.

The distortion shown in the last screenshots happens when PrecisionIn=1. v1.2.1 should have fixed that already. Something got mixed up somewhere.

There's a slight difference between doing the internal processing with Precision=2 (UINT16) or Precision=3 (half-float). Doing processing with Precision=2 causes a slight darkening! That's where the slight darkening is coming from. Computing with half-float fixes it. So what works best is to use PrecisionIn=2 (1 causes image distortion), Precision=3 (2 causes slight darkening) and PrecisionOut=1.

v1.2.1 'should' be fine.

Which means, HLSL Bicubic is working. It still would be nice to add the performance optimization mentioned earlier.

As for doing Bicubic downscaling in HLSL or converting and doing it in AviSynth (rounded to 8-bit), there's no quality difference whatsoever. Or perhaps 10% of the pixels would have a difference of 1? Nothing visible.

There's still an issue with Super-xBR: a distortion line on the right and at the bottom. I'm still investigating how to fix this.

sqrt(9801)
30th November 2015, 18:44
sqrt(9801), Shiandow also said this about your Bicubic code

The funny thing is that it shouldn't work, if we follow the theory as it is explained by the author of ImageWorsener, (http://entropymine.com/imageworsener/resample/) and this has me on suicide watch right now.
I am also working on separating the resizer into two passes/shaders (and adding a shift parameter for NEDI), which makes compilation much faster (<1 second on my box), so [fastopt] isn't necessary here.
I am still trying to figure out why I am getting an incorrect output with the right formula though.

There's still an issue with Super-xBR: a distortion line on the right and at the bottom. I'm still investigating how to fix this.
I'm suspecting this is because the shader clamps textures coordinates between 0 and 1.
I've only recently found out that the input images are shifted by half a pixel when mapped to a texture, so the texture coordinates should be clamped between 0 and 1-pixel_size or 1-.5*pixel_size (?) to get a correct output. I'm not too sure about that, to be honest.

MysteryX
30th November 2015, 18:55
I'm suspecting this is because the shader clamps textures coordinates between 0 and 1.
I've only recently found out that the input images are shifted by half a pixel when mapped to a texture, so the texture coordinates should be clamped between 0 and 1-pixel_size or 1-.5*pixel_size (?) to get a correct output. I'm not too sure about that, to be honest.
There's a 0.5 shift that has to be added when rendering textures, which is done already.

It does seem to be related to the clamping of overflow values. I tried changing it but haven't yet been successful.

Btw, I tried re-encoding videos with YUV conversion disabled. In that case, the colors appeared washed out. I'm really not sure why it worked with the still image with ConvertToYV12, but I guess at this point it doesn't matter if it's not working on live footage.

Here's the reason why Precision must be 3 to process SuperRes: the Diff requires negative values, which means half-float data is required. Otherwise these get cropped and the image gets darker.

loneboyz
1st December 2015, 03:12
it's seem ok but have little different color of output

v1.2.1 'should' be fine.

The colors of the output's nearly correct than source when I edited script


ConverttoRGB24(matrix="Rec601")

SuperRes(2, .43, 0, """edi_rpow2(2, nns=4, cshift="Spline16Resize")""") # srcMatrix601=true
SuperRes(2, .43, 0, """edi_rpow2(2, nns=4, cshift="Spline36Resize", fwidth=708, fheight=576)""") # srcMatrix601=true

ConverttoYV12(matrix="Rec601")


I've also tweaked x264 command, adjust ps-trellis set 0.0 to 0.05, last result is fine and smoother

MysteryX
1st December 2015, 03:48
I've also tweaked x264 command, adjust ps-trellis set 0.0 to 0.05, last result is fine and smoother
I had never heard of ps-trellis; looking at it. Default is --psy-rd 1.0:0.0, and some recommend --psy-rd 1.0:1.0

I use encoding preset 'veryslow', do you know if that's set to 0 by default on that preset?

Would you recommend me to set that value to 1.0 or to 0.05?

Btw, I just tested SuperRes with Softness; that's corrupt right now, no idea why. When Softness=0 (the way I always use it), it works.

I'll also add that with the full script I posted earlier, encoding the full video took just over an hour with the previous method of EEDI3+NNEDI with various passes of light sharpening. With SuperRes, not only is the result better and requires less fine-tuning per video, but it also encodes in just 45-50 minutes.

MysteryX
1st December 2015, 04:00
Here's a sample noisy 288p MPEG video re-encoded with this script.

PluginPath=""
LoadPlugin(PluginPath+"Shader.dll")
LoadPlugin(PluginPath+"KNLMeansCL.dll")
LoadPlugin(PluginPath+"nnedi3.dll")
Import(PluginPath+"edi_rpow2.avsi")
Import(PluginPath+"ResizeX.avsi")
Import(PluginPath+"SuperRes.avsi")
LoadPlugin(PluginPath+"svpflow1.dll")
LoadPlugin(PluginPath+"svpflow2.dll")
Import(PluginPath+"InterFrame2.avsi")

SetMTMode(3,8)
AviSource("Preview.avi", audio=true, pixel_type="YV12")
SetMTMode(2)
Crop(0, 0, -8, -0)
SetMTMode(5)
KNLMeansCL(D=2, A=1, h=3, device_type="GPU")
SetMTMode(2)
SuperRes(2, 0.43, 0, """edi_rpow2(2, nns=4, cshift="Spline16Resize", Threads=2)""", srcMatrix601 = true)
InterFrame(Cores=8, Tuning="Smooth", NewNum=60000, NewDen=1001, GPU=true)
SuperRes(2, 0.43, 0, """edi_rpow2(2, nns=4, cshift="Spline36Resize", fwidth=944, fheight=724, Threads=2)""")
Spline36Resize(940, 720, 0, 4, -4, -0)

Original video (https://www.spiritualselftransformation.com/files/media-encoder-old.mpg)

New video (https://www.spiritualselftransformation.com/files/media-encoder-new2.mkv)

Previously, the best approach was to use EEDI3+NNEDI3 which gave a more blurry result. Afterwards, I improved with 2-3 passes of fine-tuned sharpening at various stages of the scaling. The SuperRes version looks better and I can go without EEDI3 and without sharpening.
I re-uploaded the new video after fixing SuperRes distortion issues.

loneboyz
1st December 2015, 04:51
I had never heard of ps-trellis; looking at it.

Typing wrong. Ok, exact PsyRD & PsyTrellis with default --psy-rd 1.0:0.0

Nothing at all that only by experience and in fact, i tried PsyTrellis set other many values, from 0.0 to 1.0 and finally choose the best result

MysteryX
1st December 2015, 04:58
Typing wrong. Ok, exact PsyRD & PsyTrellis with default --psy-rd 1.0:0.0

Nothing at all that only by experience and in fact, i tried PsyTrellis set other many values, from 0.0 to 1.0 and finally choose the best result
For a general-purpose encoder, I'm wondering whether I should leave it to 0.0 or set it to something else. Apparently it was 1.0 before and then they changed the default to 0.0, probably because it could cause slight artifacts. 0.05 does sound like close to the default while getting "some" benefits from it.

MysteryX
2nd December 2015, 00:40
I've fixed a bunch of issues with SuperRes and Super-xBR, such as a distortion line at the right and bottom of Super-xBR and a sub-pixel shift when ThirdPass=false. It now works with Precision=1 which gives a nice 10% performance boost and reduces memory usage. There's one last detail I want to fix before releasing the next version. I get 45-50fps with SuperRes(1, .85, 0, """nnedi3_rpow2(2, cshift="Spline16Resize", threads=2)""") with MT=8 threads

Meanwhile, now that SuperRes is implemented right, here's a comparison of its Softness argument
First picture is Passes=2, Strength=.5, Softness=0
Other pictures are Passes=3, Strength=1, Softness = 0,.2, .4, .6, .8 and 1

http://s20.postimg.org/d5zbz17mh/Strength50.png (http://postimg.org/image/d5zbz17mh/) http://s20.postimg.org/n20eyodeh/Softness00.png (http://postimg.org/image/n20eyodeh/) http://s20.postimg.org/qhnxuhl95/Softness20.png (http://postimg.org/image/qhnxuhl95/) http://s20.postimg.org/qrvgdtzvd/Softness40.png (http://postimg.org/image/qrvgdtzvd/) http://s20.postimg.org/eeim6xa6x/Softness60.png (http://postimg.org/image/eeim6xa6x/) http://s20.postimg.org/ufb7jw82h/Softness80.png (http://postimg.org/image/ufb7jw82h/) http://s20.postimg.org/o2w2a2509/Softness100.png (http://postimg.org/image/o2w2a2509/)

I have to say that Softness=.6 is looking pretty good. The white bars are much better defined.

MysteryX
2nd December 2015, 04:38
Released v1.3 (https://github.com/mysteryx93/AviSynthShader/releases/tag/v1.3)

What's new:
- SuperRes distortion problems fixed. Colors should now be accurate.
- Shaders now use PrecisionIn=1 and convert frames to 16-bit on the GPU
- 10% performance increase and lowered memory usage
- Fixed SuperRes when using Softness parameter
- Overflow coordinates now use 'clamp'
- Fixed distortion line at the right and bottom of Super-xBR
- Fixed sub-pixel shift with Super-xBR when ThirdPass=false
- Super-xBR 'weight' argument renamed to 'sharpness'
- ConvertToFloat renamed to ConvertToShader, ConvertFromFloat renamed to ConvertFromShader
- ConvertToShader/ConvertFromShader, removed convertYuv argument
- ConvertToShader/ConvertFromShader, precision default is now 1
- All arguments now start with a uppercase letter
- Added PrecisionIn argument to SuperRes and Super-xBR. Set to 0 to call ConvertToShader within the shader; set to 1-3 if it is already converted.

There is a restriction with Super-xBR where you cannot disable the third pass unless PrecisionIn = 0. The reason is that when using only 2 passes, a sub-pixel shift must be applied. It is currently being done in AviSynth after converting back. Perhaps we could recompile the HLSL code for the 2nd pass to include the sub-pixel shift for when the 3rd pass is disabled.

MysteryX
2nd December 2015, 08:08
After doing some more tests with SuperRes's softness parameter, it still doesn't work well on noisy material, in which case I get the best result with Passes=2 and Strength=.43

For quality material, however, there are other options:
1. Using higher sharpness with softness
2. Using Super with Super-xBR (which gives an artificial look on noisy material but looks sharp on some quality material)

Also, the performance gain with the new version is higher than I expected. Perhaps the reason is that the bottleneck is the memory transfer between the CPU and GPU, and it reduces that memory transfer.

Bloax
2nd December 2015, 22:46
Perhaps the reason is that the bottleneck is the memory transfer between the CPU and GPU, and it reduces that memory transfer.
Yes - memory transfers between the CPU and the GPU are actually one of the biggest performance issues when it comes to making use of the GPU for calculations in a non-rendering setup.

MysteryX
2nd December 2015, 23:47
I've also tweaked x264 command, adjust ps-trellis set 0.0 to 0.05, last result is fine and smoother
I've made encoding tests. Adding "-psy-rd 1:0.05" does make a big difference! Otherwise the encoded image is slightly blurry (with -crf 24). With psy-trellis=0.05, the image is considerably clearer and it preserves better the shape of the details. Encoded file went from 90.1MB to 92.0MB, to give an idea of the extra details. With psi-trellis=1, encoded file was 97.5MB, the encoding took considerably longer and the noises are too sharp.

Considering how much of a difference 0.05 makes, and considering how close it still is to the default value, I think it's safe to use it as the default. I haven't tested it on all types of contents, but I don't think it will hurt.

I also tested encoding to 768p with crf=25, and it's losing more details at a similar file size.

Encoding to 720p with crf=25 and psy-trellis=0.05 is what works best.

loneboyz
3rd December 2015, 03:09
Encoding to 720p with crf=25 and psy-trellis=0.05 is what works best.

Thanks for your advice! It should be set to the default value, is 0.0. Cause maybe, I've used earlỉer SuperRes version and taken the result compare with the result of eedi3+nnedi3 that generate too blurry.

I've just edited scipt, add mt_lutxy before call SuperRes twice, and the result image is considerably clearer


source fillter: with TFM + DeHalo_alpha + KNLMeansCL + GradFun3
http://1.t.imgbox.com/kQmqgbu0.jpg (http://imgbox.com/kQmqgbu0)

eedi3 + sclip nnedi3:
http://1.t.imgbox.com/l1jHVLC3.jpg (http://imgbox.com/l1jHVLC3)

SuperRes 1.3
http://2.t.imgbox.com/kTCabWB8.jpg (http://imgbox.com/kTCabWB8)

Mt_lutxy + SuperRes 1.3
http://2.t.imgbox.com/GhATEQLS.jpg (http://imgbox.com/GhATEQLS)

MysteryX
3rd December 2015, 05:39
Interesting. How do you use mt_lutxy and what does it do exactly? Can you post you exact command? I'm not familiar with that command.

Are you saying psy-trellis should be left to 0.0 instead of 0.05? What are your thoughts on that?

bxyhxyh
3rd December 2015, 07:20
mt_lut and others are from masktool plugin.
For mt_lut you can apply specific expression on pixels.
For example mt_lut("x 10 +") you're brightening it with 10 value. It also can work on chroma channels.
I think you should read about it from its documentation.

I was planning to ask what formula are you using on ConvertToFloat and ConvertFromFloat, If you weren't going to fix that darkening issue so I can fix manually with mt_lut().

Edit:
Oh it was about mt_lutxy(). It is the same as mt_lut(). But takes two clip's pixel value.
mt_lutxy(a,b,"x y + 7 /") you're adding a, b clips then dividing it by 7

loneboyz
3rd December 2015, 08:50
How do you use mt_lutxy and what does it do exactly?

I'm only learn and try to follow this (http://forum.doom9.org/showthread.php?t=171526&page=4)

what does it do exactly or not? I'm not sure. Please correct me if I did something wrong.

This's script that I used


LoadPlugin("F:\Setup\Encode\MeGUI\tools\dgindex\DGDecode.dll")
DGDecode_mpeg2source("F:\Setup\Encode\Work\partner.d2v")
LoadPlugin("F:\Setup\Encode\MeGUI\tools\avisynth_plugin\TIVTC.dll")

tfm(order=1).tdecimate()
Vinverse(sstr=2.7, amnt=255, uv=3, scl=0.25)
Trim(1190, 0).crop(6, 64, -6, -52)

#denoise
DeHalo_alpha(ss=2,rx=2.0,ry=2.0,darkstr=0,highsens=80)

KNLMeansCL(d=1, a=1, h=2, device_type="GPU")
#~ dfttest(sigma=16)

GradFun3 (smode=2)

#~ sharpen(0,0.25)
mt_lutxy(last,last.RemoveGrain(20,-1),\
"x y == x x x y - abs 0.25 ^ 4.0 * x y - 2 ^ x y - 2 ^ 5 + / * x y - x y - abs / * 1 x y - abs 32 / 4 ^ + / + ?",U=2,V=2)

SR_Path = "F:\Setup\Encode\Tools\Avisynth.Plugin\AviSynthShader-1.3\"
LoadPlugin(SR_Path + "Shader.dll")
Import(SR_Path + "ColorMatrix\ColorMatrix.avsi")
Import(SR_Path + "SuperRes\SuperRes.avsi")
Import(SR_Path + "Super-xBR\super-xbr.avsi")

#~ ConverttoRGB24(matrix="Rec601")
ColorMatrix601to709()
SuperRes(2, .43, 0, """edi_rpow2(2, nns=4, cshift="Spline16Resize")""") # srcMatrix601=false

#~ mt_lutxy(last,last.RemoveGrain(20,-1),\
#~ "x y == x x x y - abs 0.25 ^ 4.0 * x y - 2 ^ x y - 2 ^ 5 + / * x y - x y - abs / * 1 x y - abs 32 / 4 ^ + / + ?",U=2,V=2)

SuperRes(2, .43, 0, """edi_rpow2(2, nns=4, cshift="Spline36Resize", fwidth=708, fheight=576)""") # , srcMatrix601=false

ColorMatrix709to601()

#~ Spline36Resize(708, 576)

Twarp2()
#~ LimitedSharpenfaster(edgemode=1,strength=20,ss_x=1.5,ss_y=1.5)
#~ AutoAdjust(output_tv=false,high_quality=true,auto_balance=true)
SmoothLevels(gamma=1, Ecenter=64, Lmode=1, dither=100, darkSTR=50, brightSTR=100, Ecurve=0) #Ecenter =32,darkSTR=50,brightSTR=50


Trim(20775, 28398)


Are you saying psy-trellis should be left to 0.0 instead of 0.05? What are your thoughts on that?

What I known, Psy-trellis useful in case source grainy and it also depends on your eyes

MysteryX
3rd December 2015, 18:06
mt_lutxy(last,last.RemoveGrain(20,-1),\
"x y == x x x y - abs 0.25 ^ 4.0 * x y - 2 ^ x y - 2 ^ 5 + / * x y - x y - abs / * 1 x y - abs 32 / 4 ^ + / + ?",U=2,V=2)
mt_lutxy doesn't do anything on its own. It simply makes it easy to implement other algorithms without creating a brand new filter. Heck, HLSL with AviSynthShader also makes it easy to implement new algorithms without creating brand new filters, and I suspect that the HLSL way will be considerably faster (would have to be tested).

So basically, you're applying sharpening before upscaling. It can work in some cases but it's something to be very careful about, and it needs to be fine-tuned for each video. Have you tried other sharpeners, such as FF3DFilter's sharpening? That's what I was using before to sharpen the source before upscaling.


ColorMatrix601to709()
By using this outside of SuperRes, you're adding an extra unecessary chroma conversion and you're losing color data. You're better to bundle it into other operations.

Or perhaps convert it to YV24 first, call ColorMatrix601to709, SuperRes, and then convert back to YV12. This way you won't lose chroma data between these two. YV24, however, is much heavier for AviSynth standard filters, but lighter for when it needs to be converted to perform HLSL operations.

By the way, I haven't done any tests on videos that are sensitive to banding. In those cases, should I add a deband such as GradFun3 at the beginning and a dither at the end to create some random noise? And then I suppose those should be left disabled for videos that don't have banding. My 288p videos have too much noise to have banding.

MysteryX
3rd December 2015, 18:54
Could you try with FF3DFilter's sharpening, or simply increase SuperRes's strength, to compare?

I just tried applying FF3DFilter sharpening before upscaling and it's worsening the noise in the images. Before when I used FF3DFilter to denoise, its sharpening was necessary, but with KNLMeans the result is already sharp so I don't need it anymore.

And by the way, SmoothLevels is depreciated; see SmoothAdjust (http://forum.doom9.org/showthread.php?t=137479).

loneboyz
4th December 2015, 05:30
mt_lutxy doesn't do anything on its own.
So basically, you're applying sharpening before upscaling. It can work in some cases but it's something to be very careful about, and it needs to be fine-tuned for each video.

Yes, mt_lutxy doesn't give much but I only want to instead of Sharpen
I had to increase the strength of KNLMeans, from h=1.45 to 2 and then 2.2 after add mt_lutxy

Have you tried other sharpeners, such as FF3DFilter's sharpening?
I have not tried it in this script, FF3DFilter or Dftest, perhaps they're too strong but too slowly. Follow me, KNLMeans would be enough.

Or perhaps convert it to YV24 first, call ColorMatrix601to709, SuperRes, and then convert back to YV12
I'll try your way


And by the way, SmoothLevels is depreciated; see SmoothAdjust (http://forum.doom9.org/showthread.php?t=137479).

SmoothAdjust, it seems slow when I called it in my scrip

#SmoothLevels(gamma=1, Ecenter=64, Lmode=1, dither=100, darkSTR=50, brightSTR=100, Ecurve=0) #Ecenter =32,darkSTR=50,brightSTR=50
AutoAdjust(output_tv=false,high_quality=true,auto_balance=true)
Can you give me any advice on this?

MysteryX
4th December 2015, 17:58
If you really want to process Rec601 videos with SuperRes, then the best way would be to recompile SuperResFinal709.cso with compiler flags making it Rec601. Shaders\SuperRes\CompileHLSL.bat has all the command-lines to compile the script. I'll compile this one for you. We need to add "/DKb=0.114 /DKr=0.299" at the end.

"C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Utilities\bin\x86\fxc.exe" /T ps_3_0 /Fo "SuperResFinal601.cso" "src\SuperRes\SuperRes709.hlsl" /DFinalPass=1 /DKb=0.114 /DKr=0.299

Attached is the compiled CSO file (once approved by the admin)

Just edit the SuperRes.avsi to use that one for the final pass instead of the 601 one. Then you won't need to convert color space back and forth.

I never tried AutoAdjust or SmoothAdjust so I can't comment on that.

luquinhas0021
4th December 2015, 18:27
Really is an amazing work the your improvements in this plug-in. There`s way of you implement it, includding color space conversion, in double precision floating point? Only curiosity: if you made this plug-in turn a stand-alone software, includding some resizers versions, would stand-alone be faster than plug-in? The development of stand-alone would be more laborious than the development of plug-in?

MysteryX
4th December 2015, 18:31
What do you mean by stand-alone? It has to take its data somewhere and output it somewhere. What would be the use if it's not part of a chain of scripts?

The bottleneck is the memory transfer between the CPU and GPU. Graphic cards aren't designed to read from the GPU so the bandwidth to transfer back is limited.

madVR doesn't have this limitation because it's processing series of filters on the GPU and then rendering to the screen, which allows it to use the full GPU power.

luquinhas0021
4th December 2015, 18:36
"Stand-alone" is the same of "software". Like you transform nnedi3 plug-in in a software that only makes resize using nnedi3 core,with a GUY.

MysteryX
4th December 2015, 18:46
I have a GUI within the Natural Grounding Player, in Tools | Media Encoder

I'll be releasing the next version soon, which will have considerable upgrades to the Media Encoder, including adding SuperRes into it. This new version encodes faster, gives much better quality and produces smaller files.

luquinhas0021
4th December 2015, 19:09
I saw your player. It requires MadVR, but the computer I use (Intel Core i3 1st generation without dedicated GPU) doesn't run it well. There's a way of emulate FP 32/64 processing, in CPU?

MysteryX
4th December 2015, 19:31
It supports and facilitates the use of madVR, but it is in no way required. That's only useful for video playback.

When it comes to the Media Encoder, madVR has nothing to do with it.

Although I'm not exactly sure about the requirements for it to work properly. AviSynth needs to be installed, which comes with SVP. Then I'm not sure whether it works just like that, or if LAV Filters must be installed, or if K-Lite Codec Pack must be installed. Perhaps someone could test that and let me know. What is touchy is for the Media Encoder "Preview" button to work, loading the AVS script in Windows Media Player without complaining that it is an unrecognized format. After upgrading to Windows 10, it started complaining again that it didn't recognize the format and clicking "Yes" would still open it. Re-installing K-Lite Codec Pack (with LAV Filters) solved the issue for me.

Although if your CPU is old with no decent GPU, encoding might be very slow.

At the end of the day, this software is only a wrapper that takes a list of 39 files (DLL, AVSI, EXE, CSO) and makes them work together to streamline the encoding process via AviSynth and FFMPEG.

MysteryX
5th December 2015, 06:10
mt_lutxy(last,last.RemoveGrain(20,-1),\
"x y == x x x y - abs 0.25 ^ 4.0 * x y - 2 ^ x y - 2 ^ 5 + / * x y - x y - abs / * 1 x y - abs 32 / 4 ^ + / + ?",U=2,V=2)
OK I tried your method of sharpening. It does somehow mix very well with SuperRes to make the resulting image much sharper. With noisy material, however it amplifies the noise so it doesn't work. But then, for quality material, does adding sharpening first give anything better than simply increasing the strength of SuperRes?

I also did some testing about other Cubic downscaling configurations here (http://forum.doom9.org/showthread.php?p=1748689#post1748689), and the conclusion is that although Cubic(-.6,0) appears to give better result than the default Cubic(1/3,1/3) on the Lighthouse, after testing on a real video, it lost some of the textures and details, so the current implementation still works best.

Then about running 3 passes instead of 2, I could see slight differences on the colors when running it on the Lighthouse in RGB24, but when testing on a real video in YV12, I really can't see any difference except very subtle details here and there. It seems the color precision benefits are lost in the chroma conversion to YV12, so it has benefits in the RGB24 space but not in the YV12 space.

MysteryX
6th December 2015, 09:29
There's a way of emulate FP 32/64 processing, in CPU?
If you're asking whether it's possible to process pixel shaders on the CPU, I don't know of any way to do it; and it would be very slow.

I'm implementing conversion to/from DitherTools for 16-bit resize, and I'm testing with it. It can be used as the NNEDI3 subpixel shift.

Here are some images of subpixel shift

Upscale="""edi_rpow2(2, nns=4, cshift="Spline16Resize", lsb=true, threads=2)"""
SuperRes(2, .43, 0, Upscale, lsb_in=true)


1. Standard (lsb=false)
2. Subpixel shift with lsb=true, then convert to 8-bit and run SuperRes
3. Subpixel shift with lsb=true, feeding SuperRes with 16-bit data

http://s20.postimg.org/nlztqn6qh/Subpixel_Shift.png (http://postimg.org/image/nlztqn6qh/) http://s20.postimg.org/xym4cq09l/Subpixel_Shift_Dither1.png (http://postimg.org/image/xym4cq09l/) http://s20.postimg.org/7etjakzq1/Subpixel_Shift_Dither2.png (http://postimg.org/image/7etjakzq1/)

The difference is very minimal. It's not worth using for subpixel shift.

Here are sample images with dither resize


Upscale="""edi_rpow2(2, nns=4, cshift="Spline16Resize", lsb=false, threads=2)"""
SuperRes(2, .43, 0, Upscale, lsb_in=false)
Upscale="""edi_rpow2(2, nns=4, cshift="BicubicResize", a1=-.6, a2=0, fwidth=""" + \
string(int(width*1.77)) + ", fheight=" + string(int(height*1.77)) + ", lsb=true, threads=2)"
SuperRes(2, .43, 0, Upscale, lsb_in=true)


1. Standard (lsb=false)
2. Resize with lsb=true, then convert to 8-bit and run SuperRes
3. Resize with lsb=true, feeding SuperRes with 16-bit data

http://s20.postimg.org/9prlerahl/Resize.png (http://postimg.org/image/9prlerahl/) http://s20.postimg.org/kdvcdlkgp/Resize_Dither1.png (http://postimg.org/image/kdvcdlkgp/) http://s20.postimg.org/3snpxxtcp/Resize_Dither2.png (http://postimg.org/image/3snpxxtcp/)

http://s20.postimg.org/xoj774b15/Clown_Resize.png (http://postimg.org/image/xoj774b15/) http://s20.postimg.org/5cxna2r4p/Clown_Resize_Dither1.png (http://postimg.org/image/5cxna2r4p/) http://s20.postimg.org/e98fe0hqx/Clown_Resize_Dither2.png (http://postimg.org/image/e98fe0hqx/)

The difference is subtle but it's there. The difference between 1 and 2 is about the same as the difference between 2 and 3. The difference is more visible on the clown image. It's also worth nothing that since the CPU-GPU memory transfer is the bottleneck, using more of the CPU won't lower the overall performance so we can do 16-bit processing on the CPU while the GPU is busy.

As for downsizing, Cubic(-.6,0) is giving a more accurate image than the default Bicubic. For SuperRes's internal downscaling, however, the default Bicubic gives a sharper image while Cubic(-.6,0) causes it to lose some details and get softer.

MysteryX
6th December 2015, 19:07
I accidentally made those tests with SuperRes using Cubic(-.6,0) as a downscaler, which causes the image to be softer.

Here's the clown again with standard Bicubic

http://s20.postimg.org/d1uhlsrmh/Clown_Resize.png (http://postimg.org/image/d1uhlsrmh/) http://s20.postimg.org/phr7fjkyh/Clown_Resize_Dither1.png (http://postimg.org/image/phr7fjkyh/) http://s20.postimg.org/h0waid5nd/Clown_Resize_Dither2.png (http://postimg.org/image/h0waid5nd/)

MysteryX
6th December 2015, 21:06
The next version with DitherTools support is almost ready.

Here's a comparison on a noisy video. It is the full script I posted earlier. I do the encoding with crf=24. Note that there are slight variances in the way InterFrame generates the frames.

1. Bicubic downscaling at the end (86.6MB file)
2. Cubic(-.6,0) downscaling at the end (87.7MB file)
3. Cubic(-.6,0) downscaling with DitherTools and passing 16-bit data into SuperRes (87.4MB file)

http://s20.postimg.org/w6ok42rix/Bicubic.png (http://postimg.org/image/w6ok42rix/) http://s20.postimg.org/ee2zw7aah/Cubic.png (http://postimg.org/image/ee2zw7aah/) http://s20.postimg.org/9gpfb38bd/Cubic_Dither.png (http://postimg.org/image/9gpfb38bd/)

MysteryX
6th December 2015, 22:39
Version 1.3.1 released (https://github.com/mysteryx93/AviSynthShader/releases/tag/v1.3.1)

What's new:
- Added support to convert to/from DitherTools' Stack16 format
- All Precision parameters are now 2 by default to avoid confusion
- ConvertToShader/ConvertFromShader: now have 'lsb' argument. When true, it converts to/from Stack16 format. Only YV12 and YV24 are supported.
- ExecuteShader: Added Clip1Precision-Clip9Precision instead of PrecisionIn, allowing input clips with various precisions
- ExecuteShader: PrecisionOut is now OutputPrecision
- SuperRes: Added MatrixIn and MatrixOut arguments instead of srcMatrix601 which gives more flexibility for color matrix conversion
- SuperRes and Super-xBR: Added lsb_in, lsb_upscale and lsb_out to convert to/from Stack16 format
- SuperRes and Super-xBR: PrecisionIn replaced with Convert. When true, the source must be precision=2
- ColorMatrix601to709 is now ColorMatrixShader
- ColorMatrixShader: Added MatrixIn and MatrixOut arguments giving more flexibility for color matrix conversion

MysteryX
7th December 2015, 01:30
Here's my updated best script to upscale SD content to HD. I'm testing it on the worse-case 288p noisy VCDs, so that if it works with that, it will work for most content.


PluginPath=""
LoadPlugin(PluginPath+"KNLMeansCL.dll")
LoadPlugin(PluginPath+"Shader.dll")
LoadPlugin(PluginPath+"nnedi3.dll")
LoadPlugin(PluginPath+"FTurn.dll")
Import(PluginPath+"edi_rpow2.avsi")
Import(PluginPath+"ResizeX.avsi")
Import(PluginPath+"SuperRes.avsi")
LoadPlugin(PluginPath+"dither.dll")
Import(PluginPath+"dither.avsi")
LoadPlugin(PluginPath+"svpflow1.dll")
LoadPlugin(PluginPath+"svpflow2.dll")
Import(PluginPath+"InterFrame2.avsi")

SetMTMode(3,8)
file = "Preview.avi"
AviSource(file, audio=true, pixel_type="YV12")
SetMTMode(5)
KNLMeansCL(D=2, A=1, h=3, device_type="GPU")
SetMTMode(2)
Double="""edi_rpow2(2, nns=4, cshift="Spline16Resize", Threads=2)"""
SuperRes(2, 0.43, 0, Double, MatrixIn="601")
InterFrame(Cores=8, Tuning="Smooth", NewNum=60000, NewDen=1001, GPU=true)
Double="""edi_rpow2(2, nns=4, cshift="BicubicResize", a1=-.6, a2=0, lsb=true, fwidth=960, fheight=720, Threads=2)"""
SuperRes(2, 0.43, 0, Double, lsb_upscale=true)


Original (https://www.spiritualselftransformation.com/files/media-encoder-old.mpg)

Encoded with x264 --preset "veryslow" --crf 24 -psy-rd 1:0.05 (https://www.spiritualselftransformation.com/files/media-encoder-new2.mkv)

loneboyz
8th December 2015, 05:47
MysteryX, your job is great. Finally, I felt satisfied with the result that lastest SuperRes give out.

I removed Mt_luxy and some color tweak in script because they can cause loss of precision while upscaling. I also tested with LimitedSharpenFaster insert at the end of script, its result very impressive, has no difference than the result of original encode (no upscale).

The last thing remain, I'm considering that has too small spots on this source, I can use Despot filter or the same as Clense, but before or after upscale?

MysteryX
8th December 2015, 15:21
The last thing remain, I'm considering that has too small spots on this source, I can use Despot filter or the same as Clense, but before or after upscale?
Liquid paper on the screen?

MysteryX
9th December 2015, 04:08
I experimented with 10-bit encoding.

If I simply use x264-10bit.exe with the same script posted above on 288p VCD content, encoding time is about 10-20% longer and file size is very slightly smaller, while I'm not quite such whether the 8-bit or 10-bit files have best quality. It's pretty much equal. Not worth the overhead and lack of compatibility.

However, I can feed 10-bit data to the encoder by replacing the last part of the script with this. The final resize and SuperRes will be performed with 16-bit precision and output that to x264-10bit.exe


Double="""edi_rpow2(2, nns=4, cshift="BicubicResize", a1=-.6, a2=0, lsb=true, fwidth=960, fheight=720, Threads=2)"""
SuperRes(2, 0.43, 0, Double, lsb_upscale=true, lsb_out=true)
Dither_out()


Note: there is a small bug in the last release of SuperRes. Edit SuperRes.avsi, and replace "ConvertFromShader(1" with "ConvertFromShader(PrecisionOut". Otherwise, lsb_out won't work.

Then, I encode with this command. The latest version of avs2yuv support --input-depth 16 which can make this command simpler by avoiding to provide all the metadata, but the latest version of avs2yuv is freezing for me. The previous version I had is working; not sure which version I have, but it works.

avs2yuv.exe -raw "Script.avs" -o - | x264-10bit.exe --demuxer raw --input-depth 16 --input-res 940x720 --fps 59.94
--preset veryslow --crf 24 --psy-rd 1:0.05 --output ""output.264"" --frames 10000 -


Here's the comparison
10-bit encoding result (https://www.spiritualselftransformation.com/files/media-encoder-new-10bit.mkv) (90.9 MB)
8-bit encoding result (https://www.spiritualselftransformation.com/files/media-encoder-new2.mkv) (92.2 MB)

The 10-bit encoding chain took about 40% longer, but the quality is better. However, it won't be compatible with all devices.

There is one weird difference between the 8-bit and 10-bit versions, which I'd like to have your feedback on. Both files have the same size (940x720) and the cropping of the original file is the same. However, there is a small difference in the vertical stretching where the 8-bit video is missing a line at the bottom compared to the 10-bit video. This is a plus for the 10-bit encoding chain, and... why is there such a distortion on the 8-bit video?

SSH4
9th December 2015, 05:27
On such sources, 10bit... no 8bit is a huge overhead. 4 or 6bit for High-end quality for VCR rips is more than enough :) (1/2 joke)

10 bit can help with videos with smooth gradients. And if this gradients take most part of video frame...
For example like in some latest computer only made anime. 10 bit will help you avoid bandings on average encoding settings.

So i think you don't need 10bit h264 here.

MysteryX
9th December 2015, 05:42
I got curious when I searched online and read that 10-bit encoding gives 10-20% higher quality (or 10-20% smaller file) with any video source, even 8-bit sources.

With this test, however, a 10-bit video source is required to see such benefit. It still is a 10% quality gain for 40% performance cost.

Now this got me even more curious about something else: why is the 8-bit encoding distorted?

SSH4
10th December 2015, 03:27
mod16?

loneboyz
11th December 2015, 18:29
Liquid paper on the screen?

Yes. After google with doom9, bla bla and this problem (http://forum.doom9.org/showthread.php?p=1749506#post1749506)

bxyhxyh
12th December 2015, 06:31
What does strength argument affect? Only sharpness?
I'm asking this since you always choose 0.43 in your test scripts.

MysteryX
12th December 2015, 06:42
What does strength argument affect? Only sharpness?
I'm asking this since you always choose 0.43 in your test scripts.
Strength affects the sharpness yes. The reason I use 0.43 is because that's the value that is working the best with my noisy 288p VCDs. The Lighthouse picture can take a higher value.

bxyhxyh
12th December 2015, 07:04
So nothing to do with details except sharpness?

MysteryX
14th December 2015, 06:34
It has the *result* of sharpness, except that it *recovers* details instead of *creating* details.

bcn_246
18th December 2015, 10:43
v1.2 released (https://github.com/mysteryx93/AviSynthShader/releases/tag/v1.2)

What's new:
- Added precisionIn and precisionOut arguments to ExecuteShader, allowing converting data on the GPU
- SuperRes, Super-sBR and ColorMatrix scripts adapted to convert with precision=1 while doing the processing with precision=2
- Removed D3DCREATE_DISABLE_PSGP_THREADING flag from DirectX9 device
- Performance is similar, memory usage is slightly lower and CPU usage is considerably lower

Here's a benchmark comparison while running SuperRes
SuperRes(2, .42, 0, """nnedi3_rpow2(2, cshift="Spline16Resize", Threads=2)""")

Before
FPS (min | max | average): 1.882 | 1000000 | 28.72
Memory usage (phys | virt): 598 | 679 MB
Thread count: 158
CPU usage (average): 57%

With data conversion on the GPU
FPS (min | max | average): 1.778 | 1000000 | 27.33
Memory usage (phys | virt): 590 | 662 MB
Thread count: 158
CPU usage (average): 51%

Without the D3DCREATE_DISABLE_PSGP_THREADING flag
FPS (min | max | average): 1.882 | 1000000 | 27.38
Memory usage (phys | virt): 595 | 666 MB
Thread count: 166
CPU usage (average): 45%

The performance isn't better. In fact it is 'slightly' slower. However, memory usage is slightly lower (679 to 666), and CPU usage is considerably lower (57% to 45%).

EDIT: This update now makes it possible to do the processing with half-float data (precision=3) since the conversion doesn't need to be done on the CPU. This results in higher performance. This change will be in the next release, and for now you can apply this fix by replacing precision=2 with precision=3 in SuperRes.avsi on ExecuteShader.

FPS (min | max | average): 2.667 | 1000000 | 29.09
Memory usage (phys | virt): 594 | 666 MB
Thread count: 169
CPU usage (average): 45%

Can I ask what your system specs are, and the resolution/frame rate/source type of the video you tested it on?

Peace :)

MysteryX
20th December 2015, 19:27
Can I ask what your system specs are, and the resolution/frame rate/source type of the video you tested it on?

Peace :)
Intel Quad-Core i7 3630QM with Radeon HD 7670M

I'm testing on a 288p video

bxyhxyh
27th December 2015, 08:44
How does lsb_out=true work?
It always returns me the double width clip.
If it's how supposed to work, how can I convert it to normal 16bit stacked clip after superres call?

MysteryX
28th December 2015, 01:24
There's a bug and I haven't yet made an official release with the fix. In SuperRes.avsi, replace "ConvertFromShader(1" with "ConvertFromShader(PrecisionOut"

MysteryX
28th December 2015, 04:06
After doing some testing, the AviSynthShader approach has a serious advantage over OpenCL implementations.

The bottleneck is the memory transfers between the CPU and GPU.

With KNLMeansCL, using A=2 instead of A=1 has a massive impact on performance.

With SuperRes, however, using 2 passes instead of 1 pass is giving me the exact same performance even though it works twice harder.

Why?

Because shader chains allow running as many operations as you want before returning the output, and since the GPU processing power is limited by the memory transfers, using twice more GPU processing has 0 impact on memory transfers.

This means this approach is excellent for heavy-processing operations, especially those requiring YV24 or RGB data. For singular light operations, however, the transfer bandwidth can get wasted fast.

If you want to run several HLSL operations in a row, you could easily edit the scripts to suit your needs and chain it all up in a single call.