Log in

View Full Version : AviSynth+ thread Vol.2


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

jpsdr
31st March 2021, 20:41
If i do

filter 1
filter 2
SetCPUMax
filter 3
filter 4

will SetCPUMax affect only filter 3 and filter 4 or all the filters ?

wonkey_monkey
2nd April 2021, 14:23
Providing proper zeroified-samples for negative sample points is handled however when GetAudio is passing through "audio cache", so ColorBars is seeing only n>=0 audio sample requests.



Sorry, I'm not quite clear on this... is it a bug of GetAudio, or a quirk of ColorBars?

real.finder
2nd April 2021, 19:46
at least in x64 and Spline36Resize

Spline36Resize inside ScriptClip case small memory leak https://forum.doom9.org/showthread.php?p=1939780#post1939780

jpsdr, it's also happen in Spline36ResizeMT

edit: seems happen in any kernel, also z.lib resize has the problem

ColorBars(width=640, height=480, pixel_type="yv12")
Interleave(last,last,last,last,last)
ScriptClip("""
z_BilinearResize(Width(),Height()*2).z_BilinearResize(Width(),Height())
""")

and Dither_resize16 is the worst of them! memory increases dramatically!

ColorBars(width=640, height=480, pixel_type="yv12")
ScriptClip("""
ConvertBits(16).ConvertToStacked.Dither_resize16(Width(),Height()*2).Dither_resize16(Width(),Height()).ConvertfromStacked.ConvertBits(8)
""")

jpsdr
3rd April 2021, 08:51
Maybe it's a ScriptClip issue ?
Read the Warning of the 1rst post of my Internaly multi-threaded desampling functions (DeBilinear, DeBicubic,...) thread, there is maybe some clue of the "why", even if theoricaly all resources are freed in the destructor, so there souldn't be anything left... unless... Destructor is not called anymore...? (I doubt)
My guess it affects only filters allocating ressources on constructor... :D

pinterf
5th April 2021, 09:15
Sorry, I'm not quite clear on this... is it a bug of GetAudio, or a quirk of ColorBars?
Not a bug, at least not that I am aware of, because - quite annoyingly - I'm unable to reproduce your crash issue. All I can see that at the very first frame ResampleAudio can request negative sample indexes from the child clip, but it is handled in a mid-layer (audio-cache) properly, thus protecting the child filter from that. So - in theory - Colorbars will never get a negative sample request.
When I am able to see the crash I'd immediately tell you its reason.

pinterf
5th April 2021, 09:17
If i do

filter 1
filter 2
SetCPUMax
filter 3
filter 4

will SetCPUMax affect only filter 3 and filter 4 or all the filters ?
Good question, I'm unsure when it gets executed.

pinterf
5th April 2021, 09:34
at least in x64 and Spline36Resize

Spline36Resize inside ScriptClip case small memory leak https://forum.doom9.org/showthread.php?p=1939780#post1939780

jpsdr, it's also happen in Spline36ResizeMT

edit: seems happen in any kernel, also z.lib resize has the problem

ColorBars(width=640, height=480, pixel_type="yv12")
Interleave(last,last,last,last,last)
ScriptClip("""
z_BilinearResize(Width(),Height()*2).z_BilinearResize(Width(),Height())
""")

and Dither_resize16 is the worst of them! memory increases dramatically!

ColorBars(width=640, height=480, pixel_type="yv12")
ScriptClip("""
ConvertBits(16).ConvertToStacked.Dither_resize16(Width(),Height()*2).Dither_resize16(Width(),Height()).ConvertfromStacked.ConvertBits(8)
""")
I'm unsure in this as well, just a tip, but Avisynth "string" heap is a thing that can only grow and never be reset. (Avisynth have to make "static" and store string references internally. Strings which are put into an AVSValue Avisynth variable, should be saved in order to prevent them disappearing. (devs: see env->SaveString)
If it happens in a runtime environment, called multiple times, I can imagine that the memory consumption is growing.

wonkey_monkey
5th April 2021, 15:43
When I am able to see the crash I'd immediately tell you its reason.

I don't know if it helps, but adding a call to any filter between ColorsBars and ResampleAudio seems to fix it - Amplify, PointResize, Blur, FlipVertical, even my own debugging filter which does nothing but send debug messages when GetAudio or GetFrame is called.

Without an intervening filter, the error I get is

Avisynth read error: CAVIStreamSynth: System exception - Access violation at 0x00007FFCBF0982C7

I've checked another computer and still get a crash. Does anyone else out there get a crash with


ColorBars
ResampleAudio(36000)


when playing back (including audio) in VirtualDub or ffplay?

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

Regarding the glitching audio since 3.7.0, I've found no difference in the sample values generated by Tone/ColorBars between 3.6.1 and 3.7.0. Maybe something has changed with whatever the interface is to pass audio out to the playing program?

poisondeathray
5th April 2021, 17:04
Does anyone else out there get a crash with


ColorBars
ResampleAudio(36000)


when playing back (including audio) in VirtualDub or ffplay?


Crashes in both for me

avs+ 3.7 (r3382) x64

StainlessS
5th April 2021, 17:17
OK x86 [no crash] on VDub2 and PotPlayer, [nasty audio interference VD2 only, not Potplayer]
x64 VD2, on load Avs OK [not constructor prob], on play Crash " Access violation at 0x00007FFCBF0982C7".
PotPlayer x64 Freeze.
Current v3.70.

pinterf
5th April 2021, 19:49
OK x86 [no crash] on VDub2 and PotPlayer, [nasty audio interference VD2 only, not Potplayer]
x64 VD2, on load Avs OK [not constructor prob], on play Crash " Access violation at 0x00007FFCBF0982C7".
PotPlayer x64 Freeze.
Current v3.70.
I'll give it a next try then.
EDIT: yeah, with ffplay it finally crashed!

StainlessS
5th April 2021, 20:17
VDub2 x86
Save to Crash.avi

ColorBars
ResampleAudio(36000)
Trim(0,-100)
#WaveForm_Filmstrip() # does not show any problem in waveform_filmstrip
return last




Avisource(".\crash.avi")
WaveForm_Filmstrip()
return last

result [audio spikes]
https://i.postimg.cc/QMzYcdL9/crash-Copy-00.jpg (https://postimages.org/)

EDIT: Even spikes [noise] in x86 potplayer with the avi

pinterf
5th April 2021, 20:53
I'll give it a next try then.
EDIT: yeah, with ffplay it finally crashed!
O.K. this one is fixed. Colorbars did not tolerate negative sample index requests which can happen at the very first frame of ResampleAudio.

wonkey_monkey
5th April 2021, 21:59
Thanks pinterf! Good to know it's only a ColorBars problem so not going to cause any "real" crashes.

The glitch problem is in convertFLTTo32 (avs_core/convert/convert_audio_c.cpp), convertFLTTo32_SSE2 (avs_core/convert/intel/convert_audio_sse.cpp) and convertFLTTo32_AVX2 (avs_core/convert/intel/convert_audio_avx2.cpp) which are used as the first step in conversion from float to any of the integer formats, and it's with this:

const float max32 = 2147483647.0f;

That number can't be represented by a float (they only have 7-8 decimal digits of precision, roughly an error of +/- 60 around that high value) so it's rounded up to 2147483648.0f, which is just beyond the range of a 32-bit integer. Visual Studio shows its true value:

https://i.imgur.com/ttmzVEZ.png

Suggestion: Single-precision conversion to 24 bit integers (float can accurately represent any integer from -2^23 to +2^23) as a first step for conversion to 24, 16, or 8-bit, plus specialised double-precision routines for conversion from float to 32-bit.

StainlessS
6th April 2021, 01:46
Are RowSize, and Pitch, guaranteed the same sizes for all channels of Planar RGB ?
[EDIT: all rowsize's same, and all pitch's same]

pinterf
6th April 2021, 07:14
Thanks pinterf! Good to know it's only a ColorBars problem so not going to cause any "real" crashes.

The glitch problem is in convertFLTTo32 (avs_core/convert/convert_audio_c.cpp), convertFLTTo32_SSE2 (avs_core/convert/intel/convert_audio_sse.cpp) and convertFLTTo32_AVX2 (avs_core/convert/intel/convert_audio_avx2.cpp) which are used as the first step in conversion from float to any of the integer formats, and it's with this:

const float max32 = 2147483647.0f;

That number can't be represented by a float (they only have 7-8 decimal digits of precision, roughly an error of +/- 60 around that high value) so it's rounded up to 2147483648.0f, which is just beyond the range of a 32-bit integer. Visual Studio shows its true value:

https://i.imgur.com/ttmzVEZ.png

Suggestion: Single-precision conversion to 24 bit integers (float can accurately represent any integer from -2^23 to +2^23) as a first step for conversion to 24, 16, or 8-bit, plus specialised double-precision routines for conversion from float to 32-bit.
Great, thank you for finding those glitches.

jpsdr
6th April 2021, 12:48
For investigating purpose, i've done the followig :

static void Warp2_8(const unsigned char *psrc,const unsigned char *pedg,unsigned char *pdst,const int32_t src_pitch,
const int32_t edg_pitch,const int32_t dst_pitch,const int32_t dst_row_size,const int32_t dst_height,int32_t depthH,
int32_t depthV)
{
const int32_t i = -((dst_row_size+3)&~3);
const int32_t c = dst_row_size + i - 1;
const int32_t src_pitch4=src_pitch<<2;

/* psrc -= (i << 2);
pedg -= i;
pdst -= i;

depthH <<= 8;
depthV <<= 8;*/

const short x_limit_min[8] = {(short)(i<<2),(short)((i-1)<<2),(short)((i-2)<<2),(short)((i-3)<<2),(short)((i-4)<<2),
(short)((i-5)<<2),(short)((i-6)<<2),(short)((i-7)<<2)};
const short x_limit_max[8] = {(short)(c<<2),(short)((c-1)<<2),(short)((c-2)<<2),(short)((c-3)<<2),(short)((c-4)<<2),
(short)((c-5)<<2),(short)((c-6)<<2),(short)((c-7)<<2)};

if (aWarpSharp_Enable_AVX)
{

psrc -= (i << 2);
pedg -= i;
pdst -= i;

depthH <<= 8;
depthV <<= 8;

for (int32_t y=0; y<dst_height; y++)
{
int32_t y_limit_min = -y * 0x80;
int32_t y_limit_max = (dst_height - y) * 0x80 - 0x81;
int32_t edg_pitchp = -(y ? edg_pitch : 0);
int32_t edg_pitchn = y != dst_height - 1 ? edg_pitch : 0;

JPSDR_Warp2_8_AVX(psrc,pedg,pdst,src_pitch,edg_pitchp,edg_pitchn,y_limit_min,y_limit_max,
x_limit_min,x_limit_max,i,depthH,depthV);

psrc += src_pitch4;
pedg += edg_pitch;
pdst += dst_pitch;
}
}
else
{
warp_c<2,uint8_t>(psrc,pedg,pdst,src_pitch,edg_pitch,dst_pitch,dst_row_size,dst_height,depthH,depthV,8);
/*
for (int32_t y=0; y<dst_height; y++)
{
int32_t y_limit_min = -y * 0x80;
int32_t y_limit_max = (dst_height - y) * 0x80 - 0x81;
int32_t edg_pitchp = -(y ? edg_pitch : 0);
int32_t edg_pitchn = y != dst_height - 1 ? edg_pitch : 0;

JPSDR_Warp2_8_SSE2(psrc,pedg,pdst,src_pitch,edg_pitchp,edg_pitchn,y_limit_min,y_limit_max,
x_limit_min,x_limit_max,i,depthH,depthV);

psrc += src_pitch4;
pedg += edg_pitch;
pdst += dst_pitch;
}*/
}
}

And using the following :

#SetMaxCPU("SSE2")
SetMaxCPU("AVX2")
ColorBars(width=640, height=480, pixel_type="yv12").PlaneToY("Y")
#convertbits(16)
awarp4(Spline36Resize(640*4,480*4),asobel(thresh=255).ablur(),depth=6,threads=1,cplace="MPEG2")
convertbits(8)


So, first, with AVX2, i have expected good display.
Then, switch to SSE2, i have different improper display. Meaning there is directly something wrong with the C code and SMALG=2 should it be 8 or 16 bits. Right now, that's not the issue.
Then, i switch back to AVX2 and... still have improper display. It's like i'm stuck to SSE2, and can't go up again to AVX2.
I think there is an issue with SetMaxCPU, or i'm doing something wrong ?
Script is loaded with VirtualDub, avs is 3.7.0.

pinterf
6th April 2021, 12:59
For investigating purpose, i've done the following :

I think there is an issue with SetMaxCPU, or i'm doing something wrong ?
Script is loaded with VirtualDub, avs is 3.7.0.
It can be that in order to take SetMaxCPU in effect, you have to exit VirtualDub to release Avisynth environment fully? I've just run into this problem today that it's not enough to F2-reload after a script edit after I changed SetMaxCPU line.

pinterf
6th April 2021, 13:06
@wonkey_monkey or others
Why is it that the float-integer conversions are using 2^N factor instead of (2^N)-1? E.g. to get a 16 bit signed integer value the original 32 bit float sample is multiplied by 32768 and not 32767? Looking around the net (WAV float-int conversions) I can see mostly (2^N) - 1 examples. The 32 bit floating point range -1.0 to 1.0 is not symmetric in a strict sense.
The other thing I found that the float-int conversions now omit the +0.5 rounding before goint into the integer domain - at least the C code
(the whole audio format conversion was rewritten last year)

wonkey_monkey
6th April 2021, 13:56
No idea I'm afraid. Whatever way you choose there will always be an argument that it's "wrong" - if you multiply by 32768 you (very slightly) clip the positive, if you multiply by 32767 you don't reach the negative maximum. If you expand to fit [-32768,32767] exactly, you move your 0 point.

The other thing I found that the float-int conversions now omit the +0.5 rounding before goint into the integer domain - at least the C code
(the whole audio format conversion was rewritten last year)

I think the SSE/AVX2 instructions do this automatically, though it may use banker's rounding (round x.5 to the nearest even number, up or down) instead of rounding up (I'm not sure if you can change the default but you can explicitly do the rounding yourself first before converting). It's another tricky one - banker's rounding is statistically fairer (no overall upward bias), but could potentially lead to aliasing, if every sample happened to fall on a 0.5 (e.g. [1.5, 2.5, 3.5, 4.5, 5.5] would round to [2.0, 2.0, 4.0, 4.0, 6.0]. I've been using it in all my video filters of late and I just treat as a sort of built-in dithering (if I'm not already doing my own dithering).

pinterf
6th April 2021, 14:03
I think the SSE/AVX2 instructions do this automatically, though it may use banker's rounding (round x.5 to the nearest even number, up or down) instead of rounding up (I'm not sure if you can change the default but you can explicitly do the rounding yourself first before converting).
SSE routines are using cvttps (double t: truncate, same as the int typecast in C). Former code was using integer_value = (int)(floating_pt + 0.5f) (after saturation check), now the plus 0.5 is gone.

wonkey_monkey
6th April 2021, 19:58
Well it certainly won't make an audible difference. Personally I'd go for cvtps - the tiny bias towards even numbers is statistically fair, and is not going to be audible (how often are two neighbouring .5 float samples likely to crop up? And even if they do, it's parts-in-billions), particularly if you're using it (as is currently done but with doubles) as the first step for converting to the lower bit-depths.

Edit: that missing 0.5 is causing a slight "visible" bias to waveforms when converting to 8-bit compared to 3.6.1. Not sure about 16-, 24-, and 32-bit yet as I'm having other problems of my own with those.

PS Does anyone know the logic behind this behaviour of Amplify():

8bit and 24bit audio is converted to float; the other audio formats are kept as they are.

?

pinterf
7th April 2021, 08:42
PS Does anyone know the logic behind this behaviour of Amplify():
"8bit and 24bit audio is converted to float; the other audio formats are kept as they are."
?
The Amplify routines were written only for int16, int32 and float. The rest two formats (8 and 24 bits) are converted to float (better than nothing)

tebasuna51
7th April 2021, 09:50
The Amplify routines were written only for int16, int32 and float. The rest two formats (8 and 24 bits) are converted to float (better than nothing)

One more time: All Avisynth audio internal or external filters than involve volume changes must operate only in float format.

It is not "better than nothing" is the correct way.

Amplify, ConvertToMono, MixAudio, MonoToStereo, Normalize, ResampleAudio, SuperEQ, SSRC and TimeStretch must work always in float format.
The user is free to use the ConvertAudioTo any int format if desired, most the times unnecesary because players or encoders accept float samples without problems.

Preserve int format is usefull for lossless manipulation, but when a volume change is done the audio is lossy now, and does not make sense preserve int format.

pinterf
7th April 2021, 10:35
Then it's the user's (bad) choice when he is using integer audio formats?

tebasuna51
7th April 2021, 11:21
Maybe the user don't know than is a bad choice (lose precission, risk of clip) manipulate the volume with int formats.

Is always better operate with float samples and recover the int format at end if is necesary ( I can't imagine for what).

wonkey_monkey
7th April 2021, 11:32
Well either they should all preserve the input format, or they should all convert to float - although the latter would, in my opinion, violate the Principle of Least Astonishment (https://en.wikipedia.org/wiki/Principle_of_least_astonishment). I spent a little while last night tracking down what I thought was a bug in my filter that only seemed to affect 8-bit and 24-bit audio, but it was actually a problem with float audio because I had used an Amplify().

After all, the levels video filter doesn't convert to high bit depth, and nor would anyone expect it to. If users want higher resolution they should convert explicitly first. Most of my recent video filters convert to float internally but always convert back to the input format (with dithering) - except for YUY2, aka the Freak Colourspace.

tebasuna51
7th April 2021, 12:53
Well either they should all preserve the input format...

In audio there are some input classes:

- lossy formats (MP3, AC3, DTS, AAC,... ). The decoders always output float samples, if aren't requested to downsample the output.
There are users than don't know that, and ask about AC3 16 bits or DTS 24 bits when lossy formats don't have bitdepth, and doesn't make sense convert that float samples to int.

- 8 bits int (PCM or equivalent, rare cases): can be converted to float, manipulate it and reconvert to 8 bits int without lose that poor quality.

- 32 bits int: I never see a real sample, only useless experiments (the human ear can distinguise only until a 20 bit precission).

- 16/24 bits int PCM or lossless encoded (FLAC,TrueHD,DTS-MA,...) only functions than remain the volume unchanged (AudioTrim,DelayAudio, Get/MergeChannels) must preserve the input format, other functions deceive the user, than can think have still a lossless audio when is already lossy or even distorted by clip.

Only that last case is relevant for the discussion, we can lie the user with the Principle of least astonishment, or follow the correct way already used in AviSynth (http://avisynth.nl/index.php/Internal_filters#Audio_processing_filters): "Audio samples will be automatically converted if any filters requires a special type of sample."

And include Amplify, ConvertToMono, MixAudio, MonoToStereo, Normalize, ResampleAudio to only manage Float samples.

My 5 cent. for Avs+ audio development.
If you want other 5 cent. include ChannelMask like audio property instead NumChannels.

Boulder
7th April 2021, 15:11
Any ideas why Asd-g's GMSD and MDSI functions don't get any benefit from multithreading? I just tested one clip with AVSMeter and without Prefetch, got avg 6.81 fps and with Prefetch(24,1), 6.66 fps. Average CPU usage 23,3% / 26,1% respectively.

https://github.com/Asd-g/AviSynthPlus-Scripts/blob/master/GMSD.avsi
https://github.com/Asd-g/AviSynthPlus-Scripts/blob/master/MDSI.avsi

EDIT: with Prefetch(threads=24, frames=10), 2.37 fps / 34,1% :(

StvG
7th April 2021, 16:04
Any ideas why Asd-g's GMSD and MDSI functions don't get any benefit from multithreading? I just tested one clip with AVSMeter and without Prefetch, got avg 6.81 fps and with Prefetch(24,1), 6.66 fps. Average CPU usage 23,3% / 26,1% respectively.

https://github.com/Asd-g/AviSynthPlus-Scripts/blob/master/GMSD.avsi
https://github.com/Asd-g/AviSynthPlus-Scripts/blob/master/MDSI.avsi

EDIT: with Prefetch(threads=24, frames=10), 2.37 fps / 34,1% :(

Without prefetch:
Frames processed: 442 (0 - 441)
FPS (min | max | average): 10.76 | 50.43 | 43.85
Process memory usage (max): 321 MiB
Thread count: 66
CPU usage (average): 7.4%

Time (elapsed): 00:00:10.081

With prefetch(8):
Frames processed: 1750 (0 - 1749)
FPS (min | max | average): 47.45 | 987.9 | 172.3
Process memory usage (max): 580 MiB
Thread count: 74
CPU usage (average): 65.9%

Time (elapsed): 00:00:10.156

Boulder
7th April 2021, 16:24
Script based on my Zopti script:
SetCacheMode(0)
orig = FFVideoSource("c:\zopti\lotr_fotr.avi").AssumeFPS(24000./1001)

b = -75/100.0 # optimize b = _n_/100.0 | -150..50 | b
c = 15/100.0 # optimize c = _n_/100.0 | -100..100 | c

downscaled_width = 1920
downscaled_height = 808

alternate = BicubicResize(orig, downscaled_width, downscaled_height, b=b, c=c).Lanczos4Resize(orig.width(),orig.height())

GMSD(alternate, orig, show=true)

#prefetch(24)

AVSMeter 3.0.6.0 (x64), (c) Groucho2004, 2012-2020
AviSynth+ 3.7.0 (r3382, 3.7, x86_64) (3.7.0.0)

Number of frames: 400
Length (hh:mm:ss.ms): 00:00:16.683
Frame width: 3840
Frame height: 1608
Framerate: 23.976 (24000/1001)
Colorspace: YUV420P16

Frames processed: 400 (0 - 399)
FPS (min | max | average): 0.980 | 8.501 | 7.318
Process memory usage (max): 865 MiB
Thread count: 41
CPU usage (average): 25.0%

Time (elapsed): 00:00:54.661

With Prefetch(threads=24, frames=1):
AviSynth+ 3.7.0 (r3382, 3.7, x86_64) (3.7.0.0)

Number of frames: 400
Length (hh:mm:ss.ms): 00:00:16.683
Frame width: 3840
Frame height: 1608
Framerate: 23.976 (24000/1001)
Colorspace: YUV420P16

Frames processed: 400 (0 - 399)
FPS (min | max | average): 0.116 | 30.55 | 6.887
Process memory usage (max): 1044 MiB
Thread count: 65
CPU usage (average): 27.0%

Time (elapsed): 00:00:58.078

The testclip is FFV1 encoded.

StvG
7th April 2021, 16:57
To use prefetch efficiently you should start with prefetch(x) where x is 2 and increase by 2 until find the most efficient value.
Here quick example with similar to your script:

Without prefetch:
orig=ffvideosource("001.mkv").ConvertBits(16) #source is 10-bit HEVC
downscaled_width = 1920
downscaled_height = 1080
b=1/3.0
c=1/3.0
b=BicubicResize(orig, downscaled_width, downscaled_height, b=b, c=c).Lanczos4Resize(orig.width(),orig.height())
gmsd(b, orig)
Number of frames: 1350
Length (hh:mm:ss.ms): 00:00:56.306
Frame width: 3840
Frame height: 2160
Framerate: 23.976 (24000/1001)
Colorspace: YUV420P16

Frames processed: 28 (0 - 27)
FPS (min | max | average): 2.269 | 3.377 | 2.797
Process memory usage (max): 1639 MiB
Thread count: 46
CPU usage (average): 5.9%

Time (elapsed): 00:00:10.009

With prefetch:

orig=ffvideosource("001.mkv").ConvertBits(16) #source is 10-bit HEVC
downscaled_width = 1920
downscaled_height = 1080
b=1/3.0
c=1/3.0
b=BicubicResize(orig, downscaled_width, downscaled_height, b=b, c=c).Lanczos4Resize(orig.width(),orig.height())
gmsd(b, orig)
prefetch(4)
Number of frames: 1350
Length (hh:mm:ss.ms): 00:00:56.306
Frame width: 3840
Frame height: 2160
Framerate: 23.976 (24000/1001)
Colorspace: YUV420P16

Frames processed: 73 (0 - 72)
FPS (min | max | average): 1.091 | 256416 | 7.141
Process memory usage (max): 1961 MiB
Thread count: 50
CPU usage (average): 38.9%

Time (elapsed): 00:00:10.223

pinterf
7th April 2021, 17:26
I think with the frames=1 you have just serialized the process. Default value for frames is threads*2, see Avisynth wiki on Prefetch

Boulder
7th April 2021, 17:47
To use prefetch efficiently you should start with prefetch(x) where x is 2 and increase by 2 until find the most efficient value.
Yes, I know how it works, having tested it quite a lot when I switched back to Avisynth from VapourSynth. It works just fine in my normal encoding cases but this Zopti issue has got me baffled.

I think with the frames=1 you have just serialized the process. Default value for frames is threads*2, see Avisynth wiki on Prefetch

With my go-to settings of Prefetch(threads=24, frames=10) (fastest when encoding with x265), it gets just ridiculously slow. 2.35 fps / 32,1% this time.

Boulder
7th April 2021, 18:07
I think I may have found the problem. My test clip is produced by using these:

SelectEvery(920, 1)
Trim(3, 202)

When encoded with ffmpeg, it gives the clip a very strange framerate instead of the original one.

If the clip is decoded with orig = FFVideoSource("c:\zopti\silverado.avi"), it's slow as molasses but opens normally in VDub.
If it's decoded with orig = FFVideoSource("c:\zopti\silverado.avi",fpsnum=24000,fpsden=1001), it's very fast but it keeps on processing beyond the clip length, which is 200 frames. I checked the output in VDub, and it's actually repeating the same frame for the amount of frames that was in the original SelectEvery call :D

So where is the actual problem? I tested LWLibavVideoSource as well, same problem there.

You can find a testclip here:
https://drive.google.com/file/d/1fuVEx4bNDA6UFISaDFxAX7u0f_I0tQ2U/view?usp=sharing

StvG
7th April 2021, 18:12
Yes, I know how it works, having tested it quite a lot when I switched back to Avisynth from VapourSynth. It works just fine in my normal encoding cases but this Zopti issue has got me baffled.

You wrote in the first post:
Any ideas why Asd-g's GMSD and MDSI functions don't get any benefit from multithreading? I just tested one clip with AVSMeter and without Prefetch, got avg 6.81 fps and with Prefetch(24,1), 6.66 fps. Average CPU usage 23,3% / 26,1% respectively.

https://github.com/Asd-g/AviSynthPlus-Scripts/blob/master/GMSD.avsi
https://github.com/Asd-g/AviSynthPlus-Scripts/blob/master/MDSI.avsi

EDIT: with Prefetch(threads=24, frames=10), 2.37 fps / 34,1% :(

I was curious and tested.
Those scripts benefit of mt.
It seems you have additional filters/processing in the script?
Did you try with prefetch(4):
SetCacheMode(0)
orig = FFVideoSource("c:\zopti\lotr_fotr.avi").AssumeFPS(24000./1001)

b = -75/100.0 # optimize b = _n_/100.0 | -150..50 | b
c = 15/100.0 # optimize c = _n_/100.0 | -100..100 | c

downscaled_width = 1920
downscaled_height = 808

alternate = BicubicResize(orig, downscaled_width, downscaled_height, b=b, c=c).Lanczos4Resize(orig.width(),orig.height())

GMSD(alternate, orig, show=true)

prefetch(4)

Boulder
7th April 2021, 18:16
I was curious and tested.
Those scripts benefit of mt.
It seems you have additional filters/processing in the script?

Please see the previous post, it's definitely an issue caused by the source clip confusing the decoder. I don't know how it gets worse with multithreading because source decoding should be serialized anyway.

Richard1485
7th April 2021, 19:58
If you want other 5 cent. include ChannelMask like audio property instead NumChannels.

That would be very useful.

StvG
8th April 2021, 15:05
Please see the previous post, it's definitely an issue caused by the source clip confusing the decoder. I don't know how it gets worse with multithreading because source decoding should be serialized anyway.

Yes, I can reproduce the issue with your sample.

kedautinh12
12th April 2021, 01:25
New hqdn3d support HBD
https://github.com/Asd-g/hqdn3d

tebasuna51
12th April 2021, 12:16
4 post not related with Avs+ moved to why MP2 files are decoded as s16? (https://forum.doom9.org/showthread.php?t=182724)

They are related with audio decoders plugins behaviour also with standard AviSynth.

vcmohan
26th April 2021, 07:23
Fieldbased vs Framebased:-
If I go through avisynth+ documentation ( assumeFieldbased(), assumeFramebased, seperateFields() , get impression that a frame of clip will consist of 2 fields. If seperateFied() was used it becomes fieldbased. For progressive input possibly assumefieldbased need to be used. In the plugin code vi.IsFieldBased() will give true. But when I querry each frame property then _FieldBased will be 0. Some confusing notation.
I looked into code of avsresize to understand how frame properties could be accessed. Then I noticed this code:
// TODO: support interlaced video through dual filter graphs.
if (v8 && env->propNumElements(props, "_FieldBased") > 0 && env->propGetInt(props, "_FieldBased", 0, nullptr) > 0)
throw_error("clip must be frame-based");
if (vi.IsFieldBased())
throw_error("clip must be frame-based"); The message one will get is not in line with the documentation I cited above. If one uses assumeFrameBased() script call how does this change?
I have also some problem of coding for getting frame properties in GetFrame section.. I had to use following which I thought as strange
PVideoFrame src = child->GetFrame(in, env);
// did not compile
//AVSMap * srcprop = src->getProperties();
AVSMap& srcprop = src->getProperties();
if (v8 && env->propNumElements(srcprop&, "_FieldBased") > 0 && env->propGetInt(srcprop&, "_FieldBased", 0, nullptr) > 0)
env->ThrowError("clip must be frame-based");
Is it the correct way to get frame properties?
On going through the avsresize code I found the following code
for (int p = 0; p < planes; ++p)
env->BitBlt(ret->GetWritePtr(p), ret->GetPitch(p), frame->GetReadPtr(p), frame->GetPitch(p), frame->GetRowSize(p), vi.height);
As the height of a plane can also change why v.height was used?

pinterf
27th April 2021, 09:53
On going through the avsresize code I found the following code
for (int p = 0; p < planes; ++p)
env->BitBlt(ret->GetWritePtr(p), ret->GetPitch(p), frame->GetReadPtr(p), frame->GetPitch(p), frame->GetRowSize(p), vi.height);
As the height of a plane can also change why v.height was used?
Good catch. It won't work properly but fortunately in Avisynth+ the alignment is always O.K., so it will never run.

pinterf
27th April 2021, 10:05
I have also some problem of coding for getting frame properties in GetFrame section.. I had to use following which I thought as strange
PVideoFrame src = child->GetFrame(in, env);
// did not compile
//AVSMap * srcprop = src->getProperties();
AVSMap& srcprop = src->getProperties();
if (v8 && env->propNumElements(srcprop&, "_FieldBased") > 0 && env->propGetInt(srcprop&, "_FieldBased", 0, nullptr) > 0)
env->ThrowError("clip must be frame-based");
Is it the correct way to get frame properties?


Did not try but you have to implement something like this.
We are using variable 'error' which can flag success (frame property with index==0 exists)


PVideoFrame src = child->GetFrame(n, env);
if(v8) { // use frameprop calls only when supported
const AVSMap* avsmap = env->getFramePropsRO(src);
int error = 0;
int64_t result = env->propGetInt(avsmap, "_FieldBased", 0, &error);
if(error != 0 || result > 0) // not exists or >0
env->ThrowError("clip must be frame-based");
}

vcmohan
27th April 2021, 13:10
Thanks. I want a progressive or a field separated input frame. In the script I querry isfieldseparated() or use assumefieldbased(). Framebased will mean the clip has interleaved fields. The error message in script is Frame based input is not allowed. But in coding for each frame the message will be input is fieldbased not allowed, or input must be framebased. These two are contradictory. Can the property _Fieldbased be altered to _Progressive or some such?

wonkey_monkey
3rd May 2021, 22:32
Is there any way for a filter to get information about other filters, for example their AddFunction parameter strings, or the short description that is returned at the end of AvisynthPluginInit3?

It occured to me that there's no built-in help for filters. I thought about writing a "Help" filter which you could call and would then tell you - either by throwing an error or generating a clip with text - about the filter you've asked it about, e.g.:

Help("FlipVertical")

...would return the short description plus a description of its parameters.

Another idea I had is that it could check for a filter called, according to a convention, something like "_help_[filtername]" (to be implemented by filter authors) which could return longer help text.

StainlessS
4th May 2021, 02:07
AvisynthPluginInit3(), I thought that it should return some info on filter name, however, some dll's return a string, some an int (0),
and not sure but think some may return void. [so basically not of much use for anything].

The Help() thing is a real good idea.
These functions from RT_Stats,

RT_InternalFunctions()
Returns String, SPACE separated list of internal filter and function names.
Returns "", if cannot find InternalFunctions.
If you like a good read try this:-
S=RT_StrReplace(RT_InternalFunctions," ",Chr(10))
ColorBars.ScriptClip("""RT_Subtitle("%s",S,align=5,y=height+100-current_frame,expx=true,expy=true)""").killaudio

***
***
***

RT_PluginFunctions()
Returns String, SPACE separated list of external filter and function names.
Returns "", if cannot find PluginFunctions.
If you like a good read try this:-
S=RT_StrReplace(RT_PluginFunctions," ",Chr(10))
ColorBars.ScriptClip("""RT_Subtitle("%s",S,align=5,y=height+100-current_frame,expx=true,expy=true)""").killaudio

***
***
***

RT_PluginParam(String FunctionName)
FunctionName, String, name of Avisynth built-in or Plugin filter or function name.
Returns "", if FunctionName Parameter string not found.
Returns String, the Avisynth CPP Interface style argument specifier string used by Avisynth to determine argument types and optional names.
Optional arguments have square brackets surrounding their name as in [name] and are followed by a type specifier character that gives
the type. Unnamed arguments are not optional. eg "cc[arg1]b[arg2]i" would be two compulsory unnamed clip args, followed by optional
'arg1' of type bool and optional 'arg2' of type int.
# Argument type specifier strings.
c - Video Clip
i - Integer number
f - Float number
s - String
b - boolean
. - Any type (dot)
# Array Specifiers
i* - Integer Array, zero or more
i+ - Integer Array, one or more
.* - Any type Array, zero or more
.+ - Any type Array, one or more
# Etc
To show params:-
colorbars().Killaudio()
S=RT_PluginParam("RT_YStats")
S=RT_StrReplace(S,"[",Chr(10)+"[")
RT_Subtitle(s)


Also, 3 functions in RT_Stats AVS/FunctionLists/ folder for extracting
1] All builtin function prototypes,
2] All RT_Stats prototypes,
3] Prototypes for a dll in plugins directory. [dll is selected via FileSelector dialog box]

See source of RT_Stats, and the AVS scripts too.

however, where multiple alternative prototypes, we can only extract the first one, others dont seem to be exposed.
So, a Help() whotsit with mutliple alternatve prototypes extractable, would be a real good idea.
[eg AvsPMod (and others) could interogate valid prototypes to give user assistance, in them little yellow floating text box thingies. EDIT: Tooltips]

vcmohan
6th May 2021, 14:34
I think I asked about the MT nomeneclature and meanings long time back. But I am repeating as it is somewhat confusing to me. As I understand:
MT_SERIALIZED ensures that input and output from plugin is in serial order of frames. No multi threading whatsoever.
MT_MULTI_INSTANCE ensures that only one instance of plugin operates at any time. Therefore buffers created by constructor with pointers in class, can be safely used as temporary work to read and written by GetFrame method. The input and output can be in any order.
MT_NICE_FILTER input/ output can be in any order. several instances of GetFrame may be present simultaneously. Dangerous to use Class variables for writing.
My freq domain functions use FFTW dll which is not thread safe. While for those requiring visual inspection of output frame, I am using MT_SERIALIZED. For rest I am using MT_MULTI_INSTANCE. Is this correct way?
Instead of late binding of the DLL at run time, I have created the lib file using the def and dll. By including this in additional dependencies in link section of VC++ 2019, I am able to compile. Whether this can be thread safe?

vcmohan
8th May 2021, 13:42
I read through avisynth wiki on the multi threading nomeneclature. I think it needs some editing. There are comments like "a bad programmer keeps in class' for MT_SERIALIZED and "large buffer space required" for MT_MULTI_INSTANCE and not much explanation for MT_NICE_FILTER. I am forced to use MT_SERIALIZED for my freq domain functions as the fft dll does not support multi threading. In that case I use buffers created by constructor. In other cases for large memory requirements can request env->Allocate. I do not see much problem. I am sure a MT_NICE_FILTER can also use large memory through env->Allocate.

Morku
8th May 2021, 19:23
Someone experience something similiar?
When processing a videofile with AviSynth, it starts fine, but stops at a completely random moment without error. The processed frames won't rise anymore, the remaining time goes up forever, HDD usage stops, no CPU workload anymore. It just stops, without any error but going 'further'. As my PC got tired to do.

First I thought, it's maybe my HDD Dock, so I copied the file on my internal SSD, but same issue. Maybe I thought it's MeGUI, so I processed the file with VirtualDub2, but same issue...
So my best guess is the Avisynth/Plug-ins I use. I try to have anything up to date.
For example encode som BD content always works fine and finish.
LoadPlugin("D:\Sonstiges\Videotools\MeGUI\tools\dgindexnv\DGDecodeNV.dll")
DGSource("E:\video.dgi")
ConvertBits(8)

And thats the script with the "sporadic issue":
global MeGUI_darx = 160
global MeGUI_dary = 117

AVISource("a.avi", audio=true).AssumeFPS(25,1)

AssumeTFF()
top = Crop(0,0,-0,288)
bot = Crop(0,289,-0,-0).AddBorders(0,0,0,1)

StackVertical(top,bot)

QTGMC(Denoiser="dfttest", Preset="slow", EdiMode="NNEDI3", EdiThreads=8, Sharpness=1.0)

ConvertToYV12()

__film = last
__t0 = __film.trim(134, 281048)
__t0


This is my Avisynth Info Tool Logfile:
https://pastebin.com/C3qSz3RU

Every AVSI Script should be up to date from realfinder GitHub repo.
The source file is UT video avi 720x576 25fps YUV 4:2:2, PCM 48.0kHz stereo

I don't know how to specify and analyze any further. Since I am rarely encoding this way (but update frequently), I can't tell when it started to happen. Any idea what I could do is appreciated.