Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion.

Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules.

 

Go Back   Doom9's Forum > Capturing and Editing Video > Avisynth Development

Reply
 
Thread Tools Search this Thread Display Modes
Old 3rd June 2023, 16:11   #2541  |  Link
poisondeathray
Registered User
 
Join Date: Sep 2007
Posts: 5,377
Quote:
Originally Posted by DTL View Post
As practice show the YUV to RGB decoder may have its own Transfer Function. Even if it is linear it can do range remapping. So for AVS core the rec709 is range expanding Transfer Function embedded in transform. For PC.709 it is range no change ? So if narrow/limited at input - it will also output narrow/limited (but looks not completely and not match other plugins).
That's why I like zimg better. You can specify input/output ranges, matrix, transfer, primaries. fmtc is slower but has additional transfer curve options


Quote:
I not sure if fixed Y-16 internal will make best RGB for full-YUV input. So it looks the YUV to RGB need to have adjustable proc-amps at input and at output. I will add Ybias and UVbias as new params in next builds. So Ybias will be -16 and UVbias -128 default. For full-YUV input it may be better to set Ybias=0 (and output offset to 0) ? The gains (for Y and UV) may be also important - but most easier to use without performance lost is UVgain only (it is additional multiplier to all UV coefficients). So may be UVgain (float) of 1.0 default better to add too.

Some full-YUV may use not 224 gain and not 128 offset for Digital UVs ?
I think it's better to have options . There are different valid usage scenarios


For reference, this is what vegas is doing with the studio RGB interpretation of the grey ramp. The R channel was extracted and waveform plotted with histogram (on colorbars it gets 180 and 16 for primaries +/-2 for 8bit bars, perfect for 10bit bars) .

So there appears to be a discrepancy in the low and high values and the slope. Vegas' studio RGB interpretation appears linear, with some repeats/gaps. The internal levels(0,1,255,16,125,false) + ConvertToRGB appears close approximation, but with more gaps than vegas'


Last edited by poisondeathray; 3rd June 2023 at 19:28.
poisondeathray is offline   Reply With Quote
Old 3rd June 2023, 22:07   #2542  |  Link
DTL
Registered User
 
Join Date: Jul 2018
Posts: 1,070
New version - https://github.com/DTL2020/ConvertYU...ases/tag/0.4.1

Defaut params values for input YUV proc-amp (Ybias=-16, UVbias=-128, UVgain=1.0) selected to make things unchanged for 'standard narrow YUV' input.

For full-YUV you can now test Ybias=0, gain=64, offset=0. It expected to decode colours in case of full-YUV input more precisely. But I not have full-YUV test charts to test it. Also user may try to tweak UVgain for either some saturation tweaking or for better dematrix if full-YUV source uses non-224 scale for Digital UV. UVgain may be as low as 0.0 - no colour (black and white equal RGB - copy of Y to RGB channels). Too high UVgain values may cause 16bit processing overflows and severe distortions. It is expected to be some fine tuning. For the case some source may use 219 scale for Digital UV for example. So UVgain may be in about 0.9..1.1f range.

All these adjustments should be no change in performance (no changes to processing core).

The shape of the computing errors of different engines with linear ramp input may be interesting.

I tried to use HistogramRGBParade script from http://avisynth.nl/images/Histograms...B_%26_CMY.avsi to display such graphs - but it cause VirtualDub crash with AVS+ 3.7.3 (some build) and 3.6.1 and masktools latest (?) 2.2.30. With both my plugin and ConvertToRGB32 conversion with script:

Code:
LoadPlugin("masktools2.dll")


function HistogramRGBLevels( clip input, bool "range", float "factor" )
{
    return HistogramRGBLevelsType( input, input.ConvertToRGB(), $800000, $008000, $000080, range, factor )
}

function HistogramCMYLevels( clip input, bool "range", float "factor" )
{
    return HistogramRGBLevelsType( input, input.ConvertToRGB().Invert(), $008080, $800080, $808000, range, factor )
}

function HistogramRGBParade( clip input, float "width" )
{
    return HistogramRGBParadeType( input, input.ConvertToRGB(), $800000, $008000, $000080, width )
}

#---

# Generic levels form, not very useful as a standalone function
function HistogramRGBLevelsType( clip input, clip rgb, int color1, int color2, int color3, bool "range", float "factor" )
{
    range = default(range,true)
    ChannelHeight = 64
    Gap = 8  # divisible by 4

    r = rgb.ShowRed  ("YV12").HistogramChannel("Levels", color1, "add", ChannelHeight, range, factor)
    g = rgb.ShowGreen("YV12").HistogramChannel("Levels", color2, "add", ChannelHeight, range, factor)
    b = rgb.ShowBlue ("YV12").HistogramChannel("Levels", color3, "add", ChannelHeight, range, factor)
    gap = BlankClip(r, height=Gap)
    hist = StackVertical(r,gap,g,gap,b).ConvertToMatch(input)
    return input.Height() > hist.Height() ? \ 
           StackHorizontal(input, hist.AddBorders(0,0,0,input.Height() - hist.Height())) : \
           StackHorizontal(input.AddBorders(0,0,0,hist.Height() - input.Height()), hist)
}

# Generic parade form, not very useful as a standalone function
function HistogramRGBParadeType( clip input, clip rgb, int color1, int color2, int color3, float "width" )
{
    width = default(width,0.25)
    Gap = 8  # divisible by 4

    rgb = rgb.PointResize( m4(rgb.Width()*width), m4(rgb.Height()) ).TurnRight()
    r = rgb.ShowRed  ("YV12").HistogramChannel("Classic", color1, "chroma", 0, true)
    g = rgb.ShowGreen("YV12").HistogramChannel("Classic", color2, "chroma", 0, true)
    b = rgb.ShowBlue ("YV12").HistogramChannel("Classic", color3, "chroma", 0, true)
    gap = BlankClip(r, height=Gap)
    hist = StackVertical(r,gap,g,gap,b).TurnLeft().ConvertToMatch(input)
    return input.Height() > hist.Height() ? \ 
           StackHorizontal(input, hist.AddBorders(0,0,0,input.Height() - hist.Height())) : \
           StackHorizontal(input.AddBorders(0,0,0,hist.Height() - input.Height()), hist)
}

# Used by functions above, not a standalone function
function HistogramChannel( clip input, string type, int color, string colorMode, int height, bool range, float "factor" )
{
    input.Histogram(type, factor).Crop(input.Width(),0,0,height).Greyscale()
    range ? last : Levels(128,1.0,255,0,255,false)
    return Overlay(BlankClip(color=color), mode=colorMode)
}

# Returns "input" converted to same colorspace as "ref"
function ConvertToMatch( clip input, clip ref )
{
    return ref.IsYV12()  ? input.IsYV12()  ? input : input.ConvertToYV12()  : \
           ref.IsRGB32() ? input.IsRGB32() ? input : input.ConvertToRGB32() : \
           ref.IsRGB24() ? input.IsRGB24() ? input : input.ConvertToRGB24() : \
           ref.IsYUY2()  ? input.IsYUY2()  ? input : input.ConvertToYUY2()  : \
           ref.IsYV16()  ? input.IsYV16()  ? input : input.ConvertToYV16()  : \
           ref.IsYV24()  ? input.IsYV24()  ? input : input.ConvertToYV24()  : \
           ref.IsY8()    ? input.IsY8()    ? input : input.ConvertToY8()    : \
           ref.IsYV411() ? input.IsYV411() ? input : input.ConvertToYV411() : \
           input
}

# Convert value to multiple of 4 which is  >= 16
function m4( float x ) { return (x < 16 ? 16 : int(round(x / 4.0) * 4)) }


BlankClip(length=1, width=256, height=256, pixel_type="Y8")
mt_lutspa(mode="relative closed", expr="x 255 *")

ConvertToRGB32()
#DecodeYUVtoRGB(matrix=1, threads=1, cl=true, cs=false, gain=64, offset=16, ib=16, Ybias=-16, UVbias=-128, UVgain=0.0)

HistogramRGBParade()
Debugger shows
Code:
Exception thrown at 0x00007FFA5458CF19 in Veedub64.exe: Microsoft C++ exception: ReturnExprException at memory location 0x000000000014D070.
Exception thrown at 0x00007FFA5458CF19 in Veedub64.exe: Microsoft C++ exception: [rethrow] at memory location 0x0000000000000000.
Exception thrown at 0x00007FFA5458CF19 in Veedub64.exe: Microsoft C++ exception: ReturnExprException at memory location 0x000000000014D070.
Exception thrown at 0x00007FFA5458CF19 in Veedub64.exe: Microsoft C++ exception: ReturnExprException at memory location 0x000000000014D070.
Exception thrown at 0x00007FFA5458CF19 in Veedub64.exe: Microsoft C++ exception: [rethrow] at memory location 0x0000000000000000.
Exception thrown at 0x00007FFA5458CF19 in Veedub64.exe: Microsoft C++ exception: ReturnExprException at memory location 0x000000000014D070.
Exception thrown at 0x00007FFA5458CF19 in Veedub64.exe: Microsoft C++ exception: ReturnExprException at memory location 0x000000000014D240.
Exception thrown at 0x00007FFA5458CF19 in Veedub64.exe: Microsoft C++ exception: [rethrow] at memory location 0x0000000000000000.
Exception thrown at 0x00007FFA5458CF19 in Veedub64.exe: Microsoft C++ exception: ReturnExprException at memory location 0x000000000014D240.
Exception thrown at 0x00007FFA5458CF19 in Veedub64.exe: Microsoft C++ exception: ReturnExprException at memory location 0x000000000014D240.
Exception thrown at 0x00007FFA5458CF19 in Veedub64.exe: Microsoft C++ exception: [rethrow] at memory location 0x0000000000000000.
Exception thrown at 0x00007FFA5458CF19 in Veedub64.exe: Microsoft C++ exception: ReturnExprException at memory location 0x000000000014D240.
Exception thrown at 0x00007FFA5458CF19 in Veedub64.exe: Microsoft C++ exception: ReturnExprException at memory location 0x000000000014D240.
Exception thrown at 0x00007FFA5458CF19 in Veedub64.exe: Microsoft C++ exception: [rethrow] at memory location 0x0000000000000000.
Exception thrown at 0x00007FFA5458CF19 in Veedub64.exe: Microsoft C++ exception: ReturnExprException at memory location 0x000000000014D240.
Exception thrown at 0x00007FFA5458CF19 in Veedub64.exe: Microsoft C++ exception: ReturnExprException at memory location 0x000000000014D290.
Exception thrown at 0x00007FFA5458CF19 in Veedub64.exe: Microsoft C++ exception: [rethrow] at memory location 0x0000000000000000.
Exception thrown at 0x00007FFA5458CF19 in Veedub64.exe: Microsoft C++ exception: ReturnExprException at memory location 0x000000000014D290.
Exception thrown at 0x00007FFA5458CF19 in Veedub64.exe: Microsoft C++ exception: ReturnExprException at memory location 0x000000000014D9C0.
Exception thrown at 0x00007FFA5458CF19 in Veedub64.exe: Microsoft C++ exception: [rethrow] at memory location 0x0000000000000000.
Exception thrown at 0x00007FFA5458CF19 in Veedub64.exe: Microsoft C++ exception: ReturnExprException at memory location 0x000000000014D9C0.
Exception thrown at 0x00007FFA5458CF19 in Veedub64.exe: Microsoft C++ exception: ReturnExprException at memory location 0x000000000014E030.
Exception thrown at 0x00007FFA5458CF19 in Veedub64.exe: Microsoft C++ exception: [rethrow] at memory location 0x0000000000000000.
Exception thrown at 0x00007FFA5458CF19 in Veedub64.exe: Microsoft C++ exception: ReturnExprException at memory location 0x000000000014E030.
Critical error detected c0000374
Veedub64.exe has triggered a breakpoint.
Not sure where is the bug - AVS or masktools or VirtualDub 1.10.4 ? The HistogramRGBParade is simply script for AVS and should not cause crashes ? AVSmeter looks like also crashes at startup (exit without error at F0 / T0.00), so it is not VirtualDub crash ?

The
mt_lutspa(mode="relative closed", expr="x 255 *")
produced some ramp without crash. Only call to HistogramRGBParade start crash. Is it some AVS+ core new crash ?

Last edited by DTL; 3rd June 2023 at 22:53.
DTL is offline   Reply With Quote
Old 3rd June 2023, 22:52   #2543  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
DTL,
Have you tried VirtualDub2 (VDub 1.10.4 Oct 2013, is pretty much abandoned).

VirtualDub2:- https://forum.doom9.org/showthread.php?t=172021
[SourceForge: Latest, March 2020, Version 20, VirtualDub_Pack: VirtualDub2_44282.zip]:- https://sourceforge.net/projects/vdfiltermod/files/

VirtualDub 1.10.4 is out (Oct 2013) :- https://forum.doom9.org/showthread.php?t=169640
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 3rd June 2023 at 23:01.
StainlessS is offline   Reply With Quote
Old 3rd June 2023, 23:02   #2544  |  Link
DTL
Registered User
 
Join Date: Jul 2018
Posts: 1,070
Got VirtualDub2_44282 - also crashes. It draw wide frame (so got frame width/height from AVS OK) but next disappear-crash.

Debugger shows same errors -
Exception thrown at 0x00007FFA5458CF19 in VirtualDub64.exe: Microsoft C++ exception: ReturnExprException at memory location 0x0000000000CFCD20.
Exception thrown at 0x00007FFA5458CF19 in VirtualDub64.exe: Microsoft C++ exception: [rethrow] at memory location 0x0000000000000000.
and so on.

So it is some AVS+masktools or AVS+ only crash ?

Without masktools it also crashes:
Code:
function HistogramRGBLevels( clip input, bool "range", float "factor" )
{
    return HistogramRGBLevelsType( input, input.ConvertToRGB(), $800000, $008000, $000080, range, factor )
}

function HistogramCMYLevels( clip input, bool "range", float "factor" )
{
    return HistogramRGBLevelsType( input, input.ConvertToRGB().Invert(), $008080, $800080, $808000, range, factor )
}

function HistogramRGBParade( clip input, float "width" )
{
    return HistogramRGBParadeType( input, input.ConvertToRGB(), $800000, $008000, $000080, width )
}

#---

# Generic levels form, not very useful as a standalone function
function HistogramRGBLevelsType( clip input, clip rgb, int color1, int color2, int color3, bool "range", float "factor" )
{
    range = default(range,true)
    ChannelHeight = 64
    Gap = 8  # divisible by 4

    r = rgb.ShowRed  ("YV12").HistogramChannel("Levels", color1, "add", ChannelHeight, range, factor)
    g = rgb.ShowGreen("YV12").HistogramChannel("Levels", color2, "add", ChannelHeight, range, factor)
    b = rgb.ShowBlue ("YV12").HistogramChannel("Levels", color3, "add", ChannelHeight, range, factor)
    gap = BlankClip(r, height=Gap)
    hist = StackVertical(r,gap,g,gap,b).ConvertToMatch(input)
    return input.Height() > hist.Height() ? \ 
           StackHorizontal(input, hist.AddBorders(0,0,0,input.Height() - hist.Height())) : \
           StackHorizontal(input.AddBorders(0,0,0,hist.Height() - input.Height()), hist)
}

# Generic parade form, not very useful as a standalone function
function HistogramRGBParadeType( clip input, clip rgb, int color1, int color2, int color3, float "width" )
{
    width = default(width,0.25)
    Gap = 8  # divisible by 4

    rgb = rgb.PointResize( m4(rgb.Width()*width), m4(rgb.Height()) ).TurnRight()
    r = rgb.ShowRed  ("YV12").HistogramChannel("Classic", color1, "chroma", 0, true)
    g = rgb.ShowGreen("YV12").HistogramChannel("Classic", color2, "chroma", 0, true)
    b = rgb.ShowBlue ("YV12").HistogramChannel("Classic", color3, "chroma", 0, true)
    gap = BlankClip(r, height=Gap)
    hist = StackVertical(r,gap,g,gap,b).TurnLeft().ConvertToMatch(input)
    return input.Height() > hist.Height() ? \ 
           StackHorizontal(input, hist.AddBorders(0,0,0,input.Height() - hist.Height())) : \
           StackHorizontal(input.AddBorders(0,0,0,hist.Height() - input.Height()), hist)
}

# Used by functions above, not a standalone function
function HistogramChannel( clip input, string type, int color, string colorMode, int height, bool range, float "factor" )
{
    input.Histogram(type, factor).Crop(input.Width(),0,0,height).Greyscale()
    range ? last : Levels(128,1.0,255,0,255,false)
    return Overlay(BlankClip(color=color), mode=colorMode)
}

# Returns "input" converted to same colorspace as "ref"
function ConvertToMatch( clip input, clip ref )
{
    return ref.IsYV12()  ? input.IsYV12()  ? input : input.ConvertToYV12()  : \
           ref.IsRGB32() ? input.IsRGB32() ? input : input.ConvertToRGB32() : \
           ref.IsRGB24() ? input.IsRGB24() ? input : input.ConvertToRGB24() : \
           ref.IsYUY2()  ? input.IsYUY2()  ? input : input.ConvertToYUY2()  : \
           ref.IsYV16()  ? input.IsYV16()  ? input : input.ConvertToYV16()  : \
           ref.IsYV24()  ? input.IsYV24()  ? input : input.ConvertToYV24()  : \
           ref.IsY8()    ? input.IsY8()    ? input : input.ConvertToY8()    : \
           ref.IsYV411() ? input.IsYV411() ? input : input.ConvertToYV411() : \
           input
}

# Convert value to multiple of 4 which is  >= 16
function m4( float x ) { return (x < 16 ? 16 : int(round(x / 4.0) * 4)) }


BlankClip(length=1, width=256, height=256, pixel_type="Y8")

ConvertToRGB32()

HistogramRGBParade()
As a pure AVS script.
So need to be reported as bug at github ?
DTL is offline   Reply With Quote
Old 4th June 2023, 01:22   #2545  |  Link
poisondeathray
Registered User
 
Join Date: Sep 2007
Posts: 5,377
I believe the crash is dimension related (width, height)
No crash if you resize to 640x480, preview , then change to 512x512. But it only works after you run a script first that works (this is in avspmod) . If you start with 512x512, it crashes

It's odd behaviour

Code:
BlankClip(length=1, width=256, height=256, pixel_type="Y8")
mt_lutspa(mode="relative closed", expr="x 255 *")
ConvertToRGB(matrix="PC.601")
#pointresize(640,480) #1st run
pointresize(512,512)
histogramrgbparade
EDIT: actually I can't reproduce it consistently, it sometimes crashes. But resizing to 640x480 always works. It seems height related - you need a certain min height

Last edited by poisondeathray; 4th June 2023 at 01:29.
poisondeathray is offline   Reply With Quote
Old 4th June 2023, 02:11   #2546  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
With PDR script,

Windows Logs/Application: 0xc0000374, Heap Corruption.

Code:
Faulting application name: VirtualDub64.exe, version: 2.0.0.0, time stamp: 0x5e73f48a
Faulting module name: ntdll.dll, version: 10.0.19041.2788, time stamp: 0x2f715b17
Exception code: 0xc0000374
Fault offset: 0x00000000000ff449
Faulting process ID: 0x24f4
Faulting application start time: 0x01d99680ff1cb793
Faulting application path: C:\NON-INSTALL\VDUB\VDUB2\VirtualDub64.exe
Faulting module path: C:\WINDOWS\SYSTEM32\ntdll.dll
Report ID: 3170e74f-582d-40e8-891b-0847f484c03c
Faulting package full name: 
Faulting package-relative application ID:
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???
StainlessS is offline   Reply With Quote
Old 4th June 2023, 07:32   #2547  |  Link
DTL
Registered User
 
Join Date: Jul 2018
Posts: 1,070
It is good to narrow where the initial C++ exception happen - may be in AVS core and passed via SEH stack into VirtualDub module and finally thrown to operating system so debugger point to the .exe module and not to AVS.dll ? Or in calling application ? But debugger point to ntdll.dll and it is Windows part and it may detect heap corruption with initial source in either AVS of VirtualDub ?
DTL is offline   Reply With Quote
Old 4th June 2023, 13:01   #2548  |  Link
flossy_cake
Registered User
 
Join Date: Aug 2016
Posts: 609
Is there any possibility to upgrade DirectShowSource() to support pixel formats greater than 8-bits?




Last edited by flossy_cake; 4th June 2023 at 15:22.
flossy_cake is offline   Reply With Quote
Old 4th June 2023, 16:28   #2549  |  Link
DTL
Registered User
 
Join Date: Jul 2018
Posts: 1,070
RGB48 is 3x 16bit RGB ? So you can try to force output in RGB48. It will cover 10bit precision too.
DTL is offline   Reply With Quote
Old 4th June 2023, 18:07   #2550  |  Link
flossy_cake
Registered User
 
Join Date: Aug 2016
Posts: 609
Quote:
Originally Posted by DTL View Post
RGB48 is 3x 16bit RGB ? So you can try to force output in RGB48. It will cover 10bit precision too.
Yeah the wiki for DirectShowSource doesn't mention RGB48 as a supported pixel_type but I did try it anyway and it doesn't seem to work - no video frame displayed as if there isn't any video stream present, but audio still plays. RGB24 works though. Converting RGB24 to RGB48 with ConvertToRGB48() works and media player renderer reports pixel format RGB48LE. I don't really want to be converting to RGB in Avisynth as that involves chroma upscaling & matrix that I want to handle elsewhere.

Last edited by flossy_cake; 4th June 2023 at 18:16.
flossy_cake is offline   Reply With Quote
Old 4th June 2023, 20:45   #2551  |  Link
DTL
Registered User
 
Join Date: Jul 2018
Posts: 1,070
Quote:
Originally Posted by StainlessS View Post
With PDR script,

Windows Logs/Application: 0xc0000374, Heap Corruption.

Code:
Faulting application name: VirtualDub64.exe, version: 2.0.0.0, time stamp: 0x5e73f48a
Faulting module name: ntdll.dll, version: 10.0.19041.2788, time stamp: 0x2f715b17
Exception code: 0xc0000374
It looks pinterf fix it now - https://github.com/AviSynth/AviSynth...bf19dbfb06828a . Awaiting next release-build to use. Pinterf found and fix serious memory corruption bug around AVScore/convert and it may cause lots of random crashes with many scripts. It is not known when this bug was introduced ?

Build with VS2019 - https://drive.google.com/file/d/1_tl...ew?usp=sharing . It finally start to draw some waveform without crash at 256x256 size.

Now can see waveforms draw :
"The internal levels(0,1,255,16,125,false) + ConvertToRGB appears close approximation, but with more gaps than vegas' "

It looks the code values duplicating going from Levels() transform. If put simple
ConvertToRGB(matrix="601:f")

It output also completely linear ramp -
Code:
BlankClip(length=1, width=256, height=256, pixel_type="Y8")
mt_lutspa(mode="relative closed", expr="x 255 *")

ConvertToRGB(matrix="601:f")

HistogramRGBParade(width=1.0)


Same as latest 0.4.1 ver - DecodeYUVtoRGB(gain=64, offset=0, Ybias=0, UVbias=-128, UVgain=0.0)

Last edited by DTL; 4th June 2023 at 23:18.
DTL is offline   Reply With Quote
Old 6th June 2023, 14:37   #2552  |  Link
flossy_cake
Registered User
 
Join Date: Aug 2016
Posts: 609
I was reading up on multithreading modes and I would like to use mode 3 to ensure my ScriptClip is evaluated in linear sequential chronological order ("MT_SERIALIZED: If the filter requires sequential access or uses some global storage, then mode 3 is the only way to go"). However I'm not sure how to apply it to my ScriptClip - is it even possible?

I tried:
Code:
SetFilterMTMode("ScriptClip", MT_SERIALIZED)
And/or:
Code:
SetFilterMTMode("MyFunctionWhichMyScriptClipCalls", MT_SERIALIZED)
But I can't see any change in behaviour - I'm still seeing many frames where current_frame inside the ScriptClip is not equal to previous_frame+1. I count these as "desync" frames and print it out with SubTitle, and the behaviour is unpredictable - sometimes I have no desync frames and other times I get them quite a lot and my ScriptClip won't produce the output frame I want because Avisynth is evaluating it in nonlinear frame order. For example if I'm keeping a counter of how many combed frames in a row there were, the decision making logic is slightly broken since the counter can sometimes increment up like 1-2-5-3-4 instead of 1-2-3-4-5.

Single threading of course avoids the issue but performance is in the toilet. For now I'm keeping multithreading and warning the user with SubTitle error message if they get n desync frames within a 30 second period, but it would be nicer to force my ScriptClip to linear access.



edit: also tried GrunT.dll without improvement (tried local=true as well, which works in GRunT for global variable messaging between frames, unlike stock AVS+). It's weird because realtime playback of the .avs in MPC-HC using LAV (which uses ffmpeg) settles down to 0 desync frames after about 10 seconds of playback, but rendering the .avs to mpeg file with ffmpeg.exe at command line just continues to produce desync frames for the entire duration of the video.

edit: I noticed when desync frames cease during realtime MPC-HC playback, this seems to correlate to a drop in CPU usage, which I'm pretty sure is the multithread prefetch buffer becoming full. So maybe when prefetch buffer gets full then Avisynth starts evaluating ScriptClip in linear order. Whereas rendering the script with ffmpeg.exe, Avisynth never fills the prefetch buffer, probably because CPU is pegged at 100% on all cores busy encoding to h264. If true, then as long as you have some CPU headroom the nonthreadsafe issue seems to resolve itself. Although it seems it can crop up again for a few random frames if CPU suddenly gets very busy, like on certain high contrast line patterns when nnedi3 prescreener switches from bicubic to neural net the CPU usage can suddenly spike causing some desync frames.

Last edited by flossy_cake; 6th June 2023 at 17:02.
flossy_cake is offline   Reply With Quote
Old 6th June 2023, 19:18   #2553  |  Link
Boulder
Pig on the wing
 
Boulder's Avatar
 
Join Date: Mar 2002
Location: Finland
Posts: 5,733
Quote:
Originally Posted by flossy_cake View Post
I was reading up on multithreading modes and I would like to use mode 3 to ensure my ScriptClip is evaluated in linear sequential chronological order ("MT_SERIALIZED: If the filter requires sequential access or uses some global storage, then mode 3 is the only way to go"). However I'm not sure how to apply it to my ScriptClip - is it even possible?
You could try placing the RequestLinear function from the TIVTC package after the ScriptClip part.
__________________
And if the band you're in starts playing different tunes
I'll see you on the dark side of the Moon...
Boulder is offline   Reply With Quote
Old 7th June 2023, 02:31   #2554  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
Avs internal filters are already internally set/defaulted to optimium mode,
ScriptClip (and other runtime filters) will already be MT_SERIALIZED.
(Nothing else really makes much sense).
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???
StainlessS is offline   Reply With Quote
Old 7th June 2023, 05:40   #2555  |  Link
kedautinh12
Registered User
 
Join Date: Jan 2018
Posts: 2,156
AviSynthPlus r3993
https://gitlab.com/uvz/AviSynthPlus-Builds/
kedautinh12 is offline   Reply With Quote
Old 7th June 2023, 07:02   #2556  |  Link
TDS
Formally known as .......
 
TDS's Avatar
 
Join Date: Sep 2021
Location: Down Under.
Posts: 998
Quote:
Originally Posted by kedautinh12 View Post
Double up

https://forum.doom9.org/showthread.p...43#post1988143
__________________
Long term RipBot264 user.

RipBot264 modded builds..
TDS is offline   Reply With Quote
Old 7th June 2023, 08:29   #2557  |  Link
pinterf
Registered User
 
Join Date: Jan 2014
Posts: 2,314
Quote:
Originally Posted by StainlessS View Post
Avs internal filters are already internally set/defaulted to optimium mode,
ScriptClip (and other runtime filters) will already be MT_SERIALIZED.
(Nothing else really makes much sense).
MT_SERIALIZED only ensures that the filter instance cannot be accessed more than once at a time (e.g. not multithread friendly at all). It does not mean that the call will be strict sequential.
pinterf is offline   Reply With Quote
Old 7th June 2023, 09:24   #2558  |  Link
kedautinh12
Registered User
 
Join Date: Jan 2018
Posts: 2,156
Quote:
Originally Posted by TDS View Post
Someone won't go to there post, i think up here more people will catch it
kedautinh12 is offline   Reply With Quote
Old 7th June 2023, 10:04   #2559  |  Link
flossy_cake
Registered User
 
Join Date: Aug 2016
Posts: 609
Quote:
Originally Posted by pinterf View Post
MT_SERIALIZED only ensures that the filter instance cannot be accessed more than once at a time (e.g. not multithread friendly at all). It does not mean that the call will be strict sequential.
Am I correct in thinking there is perhaps no such concept as multithreading in which calls would be sequential?

The way I'm imagining it in my mind right now, if calls were sequential, then all other threads would have to wait until the previous call was finished before they could do any work, meaning no work could be done in parallel, thus no multithreading?

If true, then I'm left wondering how the heck Avisynth is seemingly becoming sequential once the prefetch buffer becomes full. Example:

Code:
ColorBarsHD().Killaudio().ConvertToYV12() #HD video to make some more CPU load. ChangeFPS(60) for more if required.

global desyncCounter = 0
global previous_frame = 0

ScriptClip(last, "CheckSync(last, current_frame)", after_frame=true, local=false)

function CheckSync(clip c, int current_frame){

	if (current_frame != 0){
	
		if (previous_frame != current_frame-1){
			
			global desyncCounter = desyncCounter + 1		
			c = c.SubTitle("Desync", text_color=$FF0000)
		}
	
		c = c.SubTitle("\ndesyncCount:" + string(desyncCounter) + "\n" +
		\		"current_frame: " + string(current_frame) + "\n" +
		\		"previous_frame: " + string(previous_frame)
		\		, text_color=$C0C0C0, lsp=10)
	
	}
	
	global previous_frame = current_frame
	
	c
}

Prefetch(8, 8)  # may need to increase this on higher spec systems to generate desync frames.  Try seeking around too.
edit: after some more testing with ChangeFPS(120) and/or loading up the CPU with QTGMC, the number of desync frames can become entirely unpredictable on my system, even after CPU usage settles to a lower level (indicating the prefetch buffer is full). So that theory of mine would seem to be false and perhaps it's just a pure fluke whether ScriptClip will be evaluated in linear order or not, depending on how the CPU is loaded or what other filters are doing. This makes me wonder how QTGMC can be successful with multithreading if that means QTGMC can't make any guarantee that it will be comparing the current frame to previous frame, in relation to how it "temporally smooths over the neighboring frames using a binomial kernel" if the neighbouring frame order can't be guaranteed due to multithreading.

edit: tried a workaround of using 2 ScriptClips - first one to do the decision making math and is set to Prefetch(1,4). Second ScriptClip does the heavy lifting of rendering the output clip based on previous ScriptClip's decision making and is set to Prefetch(7,4). At first it seemed to work and the first ScriptClip would always be chronologically prior to the second one (based on comparing frame counters between the two ScriptClips) but then as soon as I put any load on the first ScriptClip like doing some YDiffToNext or CFrameDiff I start getting desync frames again.

edit: after more testing of the above it seems that splitting the work into multiple ScriptClips with each of them set to "after_frame=true" does seem to be helping to control the order in which ScriptClip code is evaluated. But it's still a crapshoot and can't be guaranteed. It still seems to be a function of how many cores and prefetch frames I specify with Prefetch(), eg:

Code:
# seems to work under all tests - desync frames settle to 0 after n seconds of playback
ScriptClip(last, "GetFrameMetrics()").Prefetch(1, 4)
ScriptClip(last, "ChooseOutputClipBasedOnFrameMetrics()").Prefetch(7, 4)

# works only if CPU is loaded a certain way
ScriptClip(last, "GetMetricsPlusChooseOutputClipBasedOnMetrics()").Prefetch(8, 4)

# works only if CPU is loaded a certain way
ScriptClip(last, "GetMetrics()").Prefetch(1, 8)
ScriptClip(last, "ChooseOutputClipBasedOnMetrics()").Prefetch(7, 8)
edit: it seems this function Preroll can mitigate the issue, eg prerolling 1-2 seconds of video on the ScriptClip which you want to evaluate things in linear order.

Last edited by flossy_cake; 12th June 2023 at 10:36.
flossy_cake is offline   Reply With Quote
Old 7th June 2023, 14:17   #2560  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
Quote:
Originally Posted by pinterf View Post
MT_SERIALIZED only ensures that the filter instance cannot be accessed more than once at a time (e.g. not multithread friendly at all). It does not mean that the call will be strict sequential.
I stand corrected, good sir
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???
StainlessS is offline   Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 00:45.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.