View Full Version : AviSynth+ thread Vol.2
Dogway
4th November 2021, 13:12
I also saw it as 'SMPTE range', whether 'legal' or not. Sounds more technical. Some read here (https://nick-shaw.github.io/cinematiccolor/full-and-legal-ranges.html) by Nick Shaw, a fellow from ACES Central.
DTL
4th November 2021, 14:00
Also for colour video data properties the 'Primaries' property required. For colour conversions for example between SDR ('standard' colour gamut) and WCG (and more precise SD colour conversions between PAL and NTSC).
johnmeyer
4th November 2021, 15:00
@johnmeyer
I think you may be doing some things wrong. I have 64-bit AviSynth+ installed on my Windows 7 PC and also on a 11 year old MacBook Pro running Windows 7 and both work flawlessly. And if I'm not mistaken there are some users using 64-bit AVS+ even on Windows XP.
With that being said, based on the information you provided it seems you are trying to use some 32-bit plugins on a 64-bit environment. I'm sure I'm using 32-bit plugins, since my main, useful but old, system in WinXP 32-bit, and I just copied over all those plugins.
This will get me through the trip and let me do some work. When I get back, I'll be using my old trusty XP computer that may not be modern, but it works every time (except for browsing which is getting tougher, since no XP-compatible browser supports modern scripts, etc.). Even the latest Firefox spinoff is no longer being developed.
FranceBB
4th November 2021, 16:39
(except for browsing which is getting tougher, since no XP-compatible browser supports modern scripts, etc.). Even the latest Firefox spinoff is no longer being developed.
Updated XP Compatible Browser from the Windows XP Forever community I'm part of in MSFN ;)
http://rtfreesoft.blogspot.com/search/label/browser
pinterf
4th November 2021, 17:06
Also for colour video data properties the 'Primaries' property required. For colour conversions for example between SDR ('standard' colour gamut) and WCG (and more precise SD colour conversions between PAL and NTSC).
As for _Primaries and _Transfer: they are well known and used. I'm on halfway with frameprops integration, I'm not there at the moment. I see how they are used in z_ConvertFormat but in Avisynth core they have zero history.
pinterf
4th November 2021, 17:44
Fresh daily stuff (still not on git, your feedback and cleanup needed)
Avisynth+ 3.7.1 test build 24 (20211104) (https://drive.google.com/uc?export=download&id=1LtBvg0gR6KLtdwzO1lquZvLzszL0_sFS)
20211104 WIP
------------
- frame property support: _ChromaLocation in various filters (e.g. ConvertToYUV422)
New location parameter values: "top", "bottom_left", "bottom", "auto"
"ChromaInLocation" rules:
- if source has _ChromaLocation frame property it will be used else the default is "mpeg2" ("left")
- if parameter is "auto" or not given at all, ChromaInLocation will be set to the above mentioned default value
- if parameter is explicitely given, it will be used
"ChromaOutLocation" rules:
- default is "mpeg2" ("left")
- if parameter is "auto" or not given at all, ChromaOutLocation will be set to the above mentioned default value
- if parameter is explicitely given, it will be used
Accepted values for "ChromaInLocation" and "ChromaOutLocation" (when source/target is a chroma subsampled format)
(full list):
- "left" or "mpeg2"
- "center" or "jpeg" or "mpeg1"
- "top_left"
- "dv"
- "top"
- "bottom_left"
- "bottom"
_ChromaLocation constants - as seen in propShow()
AVS_CHROMA_LEFT = 0
AVS_CHROMA_CENTER = 1
AVS_CHROMA_TOP_LEFT = 2 (4:2:0 only)
AVS_CHROMA_TOP = 3 (4:2:0 only)
AVS_CHROMA_BOTTOM_LEFT = 4 (4:2:0 only)
AVS_CHROMA_BOTTOM = 5 (4:2:0 only)
AVS_CHROMA_DV = 6 Special to Avisynth
_ChromaLocation property will be cleared when the result clip is not a chroma subsampled format (4:4:4 or RGB)
gispos
4th November 2021, 18:21
Probably you made it right, seeing your last results.
Anyway, I refreshed my memories about AvsPMod development, reinstalled everything, so here is my working version. (I see the project is still on 2.7, Microsoft has silently removed their VcPython27 compiler, you can find only on some peoples' github repo.)
The code was try-except-pass guarded so it hid all internal errors e.g. using things which 2.7 did not know about.
Excellent!
Thank you for the effort.
I hardly dare to ask:), what about RGB.
pinterf
4th November 2021, 18:31
Excellent!
Thank you for the effort.
I hardly dare to ask:), what about RGB.
Planar rgb is the very same logic.
Then there remains rgb48 and 64 which follows the two-byte logic as well. But we pisition with X*8 (rgb64) and x*6 (rgb48) instead of x*4 and x*3 then access bgr(a) with +0 +2 +4 +6 instead of +1 +2 +3 inside the 3 or 4 pixel blocks
gispos
4th November 2021, 19:17
Planar rgb is the very same logic.
Then there remains rgb48 and 64 which follows the two-byte logic as well. But we pisition with X*8 (rgb64) and x*6 (rgb48) instead of x*4 and x*3 then access bgr(a) with +0 +2 +4 +6 instead of +1 +2 +3 inside the 3 or 4 pixel blocks
Ok, thanks, 16bit seems to be returning the correct values.
bytes = self.vi.bytes_from_pixels(1)
if self.bits_per_component == 16:
if BGR:
indexB = (x * bytes) + (self.Height - 1 - y) * self.pitch
bufferB = [self.ptrY[indexB], self.ptrY[indexB + 1]]
valB = struct.unpack('=H', bytearray(bufferB))[0]
bufferG = [self.ptrY[indexB+1], self.ptrY[indexB + 2]]
valG = struct.unpack('=H', bytearray(bufferG))[0]
bufferR = [self.ptrY[indexB+2], self.ptrY[indexB + 3]]
valR = struct.unpack('=H', bytearray(bufferR))[0]
return (valR, valG, valB)
else:
indexR = (x * bytes) + y * self.pitch
bufferR = [self.ptrY[indexR], self.ptrY[indexR + 1]]
valR = struct.unpack('=H', bytearray(bufferR))[0]
bufferG = [self.ptrY[indexR+1], self.ptrY[indexR + 2]]
valG = struct.unpack('=H', bytearray(bufferG))[0]
bufferB = [self.ptrY[indexR+2], self.ptrY[indexR + 3]]
valB = struct.unpack('=H', bytearray(bufferB))[0]
return (valR, valG, valB)
Edit: It's not right, I have to sleep on it first.
pinterf
4th November 2021, 19:52
IndexB+2 indexB+3
indexB+4 indexB+5
The 2nd and 3rd pixel
Dogway
5th November 2021, 08:32
Is there a way for the next to don't crash? maybe something along RequestLinear(), Prefetch, optSingleMode or some trick?
for (i=1,48,1) {
Expr("x[0,1] x[-1,0] min x[1,0] min x[0,-1] min","")
}
pinterf
5th November 2021, 08:37
Is there a way for the next to don't crash? maybe something along RequestLinear(), Prefetch, optSingleMode or some trick?
for (i=1,48,1) {
Expr("x[0,1] x[-1,0] min x[1,0] min x[0,-1] min","")
}
"Stack overflow". Interesting.
EDIT: stopped using local variables for large arrays, dynamic std::vector is better for them. Many ~1-2kbytes per Expr on stack chained for 48 Expr calls consumed available stack area.
Fix appears in next build.
Dogway
5th November 2021, 11:29
Thanks for the update pinterf!
I'm giving the last touches for the latest update of TransformsPack that is setting all the frameprops values and let me tell you (rant coming), what a disaster!
So for primaries or matrix constants they are mixing color models with color spaces, going to the extent of (check table E.5 of ITU H.265 page 429) defining '1' for xvYCC -and a small 709 subscript- and defining '5' for xvYCC -and a small 601 subscript-, rhetorical? Then sYCC (the 's' comes from sRGB) is defined along Rec601 and 470BG, that is '5' again when it should be '1' (check table E.1 at value 1 entry)!
To be honest and this is my opinion, the "matrix" concept is outdated as it tries to fit constants into a model (YCbCr) that is flawed and outdated. So you see 0, 8, 11, 12, 13, 14 (and what is not listed) as 'see equations' because some models don't rely on the YCbCr's Kr,Kb,Kg typical constant system. I think if something should be valuable is to set 'models', where matrix constants are a subset of the YCbCr model which can hold several color spaces (with color primaries).
gispos
5th November 2021, 18:48
IndexB+2 indexB+3
indexB+4 indexB+5
The 2nd and 3rd pixel
Hadn't read your posting and just pressed Quote.
So I tried without reading your posting with the two-byte logic... and of course without success. :o
This is how it now works for RGB 48,64 16bit
Thanks again for your help.
If I still have to pay attention to something then out with it.:)
def GetPixelRGB(self, x, y, BGR=True):
if self.IsRGB:
# if a resize filter used in the preview filter. CRASH if not check here
if self.DisplayWidth != self.Width or self.DisplayHeight != self.Height:
return (-1,-1,-1)
bytes = self.vi.bytes_from_pixels(1)
if self.bits_per_component == 16:
if BGR:
indexB = (x * bytes) + (self.Height - 1 - y) * self.pitch
bufferB = [self.ptrY[indexB], self.ptrY[indexB+1]]
valB = struct.unpack('=H', bytearray(bufferB))[0]
bufferG = [self.ptrY[indexB+2], self.ptrY[indexB+3]]
valG = struct.unpack('=H', bytearray(bufferG))[0]
bufferR = [self.ptrY[indexB+4], self.ptrY[indexB+5]]
valR = struct.unpack('=H', bytearray(bufferR))[0]
return (valR, valG, valB)
else:
indexR = (x * bytes) + y * self.pitch
bufferR = [self.ptrY[indexR], self.ptrY[indexR+1]]
valR = struct.unpack('=H', bytearray(bufferR))[0]
bufferG = [self.ptrY[indexR+2], self.ptrY[indexR+3]]
valG = struct.unpack('=H', bytearray(bufferG))[0]
bufferB = [self.ptrY[indexR+4], self.ptrY[indexR+5]]
valB = struct.unpack('=H', bytearray(bufferB))[0]
return (valR, valG, valB)
if self.bits_per_component > 8:
return (-1,-1,-1)
if BGR:
indexB = (x * bytes) + (self.Height - 1 - y) * self.pitch
indexG = indexB + 1
indexR = indexB + 2
else:
indexR = (x * bytes) + y * self.pitch
indexG = indexR + 1
indexB = indexR + 2
return (self.ptrY[indexR], self.ptrY[indexG], self.ptrY[indexB])
else:
return (-1,-1,-1)
Edit:
Is there an alpha channel even with 16 bit?
Is there a function like IsRGBA for testing?
Edit2: found
HasAlpha and IsPlanarRGBA or num_components
pinterf
5th November 2021, 23:11
Happy Friday!
Avisynth+ 3.7.1 test build 25 (20211105) (https://drive.google.com/uc?export=download&id=1xQGN9i3ecJqzwZTfDFNCQ_F1efZfekc-)
20211105 WIP
------------
- ConvertBits: allow dither from 32 bits to 8-16 bits (through an internal 16 bit immediate clip)
- ConvertBits: allow different fulls fulld when converting between integer bit depths
- ConvertBits: allow 32 bit to 32 bit conversion
ColorbarsHD()
# another method for converting to full range
ConvertToRGB(matrix="709:l")
ConvertToYUV444(matrix="709:f")
# 8 to 32 bits
ConvertBits(32, fulls=true, fulld=false)
ConvertBits(32, fulld=true) # fulls=false: auto from frame prop _ColorRange
ConvertBits(8, fulld=false, dither = 1, dither_bits=1) # low dither_bits just for fun :)
Histogram("levels")
- Expr: consume less bytes on stack. 48x Expr call in sequence caused stack overflow
I've just found again this dither = 1, dither_bits=1 (2, 3, ...) option, which I made for curiousity. Apply to your favorite video clip and forget this high-bit-depth hype :)
Dogway
6th November 2021, 12:36
Awesome! I can barely keep up with all the changes.
The dither_bits can come useful for posterization which I have some ideas for.
FranceBB
6th November 2021, 15:35
Awesome, Ferenc!
Have a lovely thoughts-free/stress-free weekend, you deserve it! :D
cretindesalpes
6th November 2021, 17:30
I've just found again this dither = 1, dither_bits=1 (2, 3, ...) option, which I made for curiousity. Apply to your favorite video clip and forget this high-bit-depth hype :)
Funnily a few days ago I found a formula to fix the EOTF effect (gamma thing) when dithering with a low bitdepth:
# Gamma-aware color quantization
# https://www.desmos.com/calculator/qyyjugcbbt
b = 2
q = Int (Pow (2, b))
source ()
ref = ConvertBits (8, fulls=true, fulld=true)
x = " x 0.000001 max "
f = " 2.2 ^ " # EOTF transfer function (expects input value on the stack)
flr = " 0.5 - round "
u = x + String (q) + " * " + flr + String (q) + " / "
v = x + String (q) + " * " + flr + " 1 + " + String (q) + " / "
remap = x + f + u + f + " - " + v + f + u + f + " - / " + v + u + " - * " + u + " + "
fixed = mt_lut (remap, u=3, v=3)
Interleave (last, fixed)
ConvertBits(8, fulls=true, fulld=true, dither=1, dither_bits=b)
StackVertical (SelectEvery (2, 0), SelectEvery (2, 1), ref)
Function source ()
{
BlankClip (pixel_type="RGB24", width=1280, height=64)
ConvertToPlanarRGB ().ConvertToFloat ()
mt_lutspa (mode="relative", expr="x", u=3, v=3)
}
https://i.postimg.cc/Y9zQ2wBf/dithering-gamma.png
wonkey_monkey
7th November 2021, 19:40
I'm writing a plugin and accidently did the following:
env->AddFunction("TrackingReduce", "c[bool]translate[bool]scale[bool]rotate", Create_TrackingReduce, 0);
The parameter string is completely the wrong format. Instead of getting a useful error, this instead causes a System Violation, but only if you try to use any of the functions of the plugin in question. Otherwise it's silent (initialisation of that plugin DLL just aborts).
Obviously it was my silly error, but is it worth considering some validation for parameter strings that could throw a warning instead of leading to a somewhat confusing System Violation?
StainlessS
7th November 2021, 20:48
In my experience [I think], many errors in parameter string produce error exception,
if problem in calling constructor [ie before frameserving starts], then good idea to check params string [first].
however, this error did not seem to produce any problems:- https://forum.doom9.org/showthread.php?p=1954448#post1954448
And Plugins [just a few in Plugins dir] : NOTE, it actually found a bug in ApparentFPS params list (top line, used '[' instead of closing ']', does not seem to cause problems though)
EDIT: Actually 46 plugins auto loaded, only 2 of which cause errors (AssumeFPS, Grunt).
00001704 1.30285561 RT_DebugF: ApparentFPS "c[DupeThresh]f[FrameRate]f[Samples]i[ChromaWeight]f[Prefix]s[Show]b[Verbose]b[Debug]b[Mode]i[Matrix]i[BlkW]i[BlkH[i[oLapX]i[oLapY]i"
Dogway
7th November 2021, 23:52
pinterf, I noticed a few inconsistencies with color related frame props.
-Matrix string Rec601 in test23 defaults to ID 5 (470BG), that's PAL Rec601 which is much less common than NTSC Rec601 (170M).
-FCC corresponds to 470M in ITU to keep the naming convention (170M, 240M, 470BG)
-YCgCo seems to be also much less used than YCoCg (86K versus 16K in Google search), YCoCg is also the preferred term in the Wikipedia and in the Colour python module.
-Also noticed that Rec2020 and 2020 are supported as 2020CL and 2020NCL, but not Rec2020CL or Rec2020NCL.
-I couldn't use the "auto" matrix type. From YCbCr, ConvertToPlanarRGB("auto:auto") or ConvertToPlanarRGB("auto") triggers an "Unknown matrix" error.
-Quote (https://forum.doom9.org/showthread.php?p=1956500#post1956500): "When converting to RGB the _Matrix parameter is set to 0 ("rgb")". Yet for internal RGB clips _Matrix is set to 1(?)
- BlankClip: frame property support:
RGB: _ColorRange = 0 ("full"), _Matrix = 1 ("709")
-Also just tested the new dither_bits arg, too bad it doesn't work with dither=-1 for posterization, not sure if it uses the same code path as it can be very useful.
-Found another issue, how do you correct the bitdepth scale of source without changing the range? Example, load a sample image which by nature is PC range (ie with JPEGSource which has a great builtin deblocker), render the YPlaneMax, it reads 65280. How do we fix this with internal filters? Currently it's only possible with Expr("x 257 256 / *")
vcmohan
9th November 2021, 13:52
I am testing for speed my plugin functions for avs+ using run video analysis on vdub. I am using vseditor benchmark for testing my vapoursynth functions. I find that speed of functions on avs+ are about a third of what they are for vapoursynth. In my script I am not using filter MT_NICE_FILTER and prefetch commands as I presume it will use the type declared in the function itself. I have specified in cacheHints MT_NICE_FILTER.
On checking performance of computer I find for avs+ about 25% usage, while for vapoursynth I get 90+% usage. Looks only one cpu is being used out of 4 on my Intel i5 11th gen computer with windows 10.
Is this a problem in scripting or vdub video analysis?
If this question was already dealt with, I am sorry to have posted this, but would like to get a link to it.
VoodooFX
9th November 2021, 15:25
Is this a problem in scripting or vdub video analysis?
Try benchmarking with AVSMeter (https://forum.doom9.org/showthread.php?t=174797).
gispos
9th November 2021, 17:36
Hello Ferenc, can you please look over there again. With 10 to 16 bit color depth, the correct values seem to be returned only with YUV444.
And please take another look at 32bit.
Thanks in advance.
Edit:
The fact that only 0 is displayed at 32bit is my fault (everything is formatted as an integer), but I also get negative values after float formatting.
Probably you made it right, seeing your last results.
Anyway, I refreshed my memories about AvsPMod development, reinstalled everything, so here is my working version. (I see the project is still on 2.7, Microsoft has silently removed their VcPython27 compiler, you can find only on some peoples' github repo.)
The code was try-except-pass guarded so it hid all internal errors e.g. using things which 2.7 did not know about.
import struct
def GetPixelYUV(self, x, y):
if self.bits_per_component > 8:
if self.bits_per_component == 32:
x = x * 4 # 32 bit float
else:
x = x * 2 # 10-16 bits
# if a resize filter used in the preview filter. CRASH if not check here
if self.DisplayWidth != self.Width or self.DisplayHeight != self.Height:
return (-1,-1,-1)
if self.IsPlanar:
indexY = x + y * self.pitch
if self.IsY8:
return (self.ptrY[indexY], -1, -1)
x = x >> self.WidthSubsampling
y = y >> self.HeightSubsampling
indexU = indexV = x + y * self.pitchUV
elif self.IsYUY2:
indexY = (x*2) + y * self.pitch
indexU = 4*(x/2) + 1 + y * self.pitch
indexV = 4*(x/2) + 3 + y * self.pitch
else:
return (-1,-1,-1)
if self.bits_per_component == 8:
return (self.ptrY[indexY], self.ptrU[indexU], self.ptrV[indexV])
if self.bits_per_component <= 16:
# struct.unpack needs import struct, and returns a single element tuple
# =H: unsigned short (2 bytes), native byte order
bufferY = [self.ptrY[indexY], self.ptrY[indexY + 1]]
valY = struct.unpack('=H', bytearray(bufferY))[0]
bufferU = [self.ptrU[indexU], self.ptrU[indexU + 1]]
valU = struct.unpack('=H', bytearray(bufferU))[0]
bufferV = [self.ptrV[indexV], self.ptrV[indexV + 1]]
valV = struct.unpack('=H', bytearray(bufferV))[0]
return (valY, valU, valV)
#float # =f: float (4 bytes), native byte order
bufferY = [self.ptrY[indexY], self.ptrY[indexY + 1], self.ptrY[indexY + 2], self.ptrY[indexY + 3]]
valY = struct.unpack('=f', bytearray(bufferY))[0]
bufferU = [self.ptrU[indexU], self.ptrU[indexU + 1], self.ptrU[indexU + 2], self.ptrU[indexU + 3]]
valU = struct.unpack('=f', bytearray(bufferU))[0]
bufferV = [self.ptrV[indexV], self.ptrV[indexV + 1], self.ptrV[indexV + 2], self.ptrV[indexV + 3]]
valV = struct.unpack('=f', bytearray(bufferV))[0]
return (valY, valU, valV)
And the calling/test part in avsp.py
avsYUV = script.AVI.GetPixelYUV(x, y)
if avsYUV != (-1,-1,-1):
Y,U,V = avsYUV
cY = ''
if script.AVI.bits_per_component == 8:
hexcolor = '$%02x%02x%02x' % (Y,U,V)
elif script.AVI.bits_per_component <= 16:
hexcolor = '$%04x,%04x,%04x' % (Y,U,V) # comma separated is more visible
else: # 32 bit
hexcolor = '%.5f,%.5f,%.5f' % (Y,U,V) # no reason for 32 bit float in hex
johnmeyer
9th November 2021, 17:48
Updated XP Compatible Browser from the Windows XP Forever community I'm part of in MSFN ;)
http://rtfreesoft.blogspot.com/search/label/browserI'm late in replying, but thank you for that link. Very useful.
pinterf
9th November 2021, 19:23
pinterf, I noticed a few inconsistencies with color related frame props.
-Matrix string Rec601 in test23 defaults to ID 5 (470BG), that's PAL Rec601 which is much less common than NTSC Rec601 (170M).
-FCC corresponds to 470M in ITU to keep the naming convention (170M, 240M, 470BG)
-YCgCo seems to be also much less used than YCoCg (86K versus 16K in Google search), YCoCg is also the preferred term in the Wikipedia and in the Colour python module.
-Also noticed that Rec2020 and 2020 are supported as 2020CL and 2020NCL, but not Rec2020CL or Rec2020NCL.
-I couldn't use the "auto" matrix type. From YCbCr, ConvertToPlanarRGB("auto:auto") or ConvertToPlanarRGB("auto") triggers an "Unknown matrix" error.
-Quote (https://forum.doom9.org/showthread.php?p=1956500#post1956500): "When converting to RGB the _Matrix parameter is set to 0 ("rgb")". Yet for internal RGB clips _Matrix is set to 1(?)
-Also just tested the new dither_bits arg, too bad it doesn't work with dither=-1 for posterization, not sure if it uses the same code path as it can be very useful.
-Found another issue, how do you correct the bitdepth scale of source without changing the range? Example, load a sample image which by nature is PC range (ie with JPEGSource which has a great builtin deblocker), render the YPlaneMax, it reads 65280. How do we fix this with internal filters? Currently it's only possible with Expr("x 257 256 / *")
Thanks for the feedback, I'm looking into them.
pinterf
9th November 2021, 19:27
I am testing for speed my plugin functions for avs+ using run video analysis on vdub. I am using vseditor benchmark for testing my vapoursynth functions. I find that speed of functions on avs+ are about a third of what they are for vapoursynth. In my script I am not using filter MT_NICE_FILTER and prefetch commands as I presume it will use the type declared in the function itself. I have specified in cacheHints MT_NICE_FILTER.
You have to set Prefetch(4) (for example) manually, usually at the end of the script. Or else the whole script runs is single threaded. When a plugin does not specify the default is MT_MULTI_INSTANCE. Even if your filter is totally reentrant and does not have internal states so it is a nice filter, you could test whether MT_MULTI_INSTANCE is better or not speedwise.
pinterf
9th November 2021, 19:32
Hello Ferenc, can you please look over there again. With 10 to 16 bit color depth, the correct values seem to be returned only with YUV444.
And please take another look at 32bit.
Thanks in advance.
Edit:
The fact that only 0 is displayed at 32bit is my fault (everything is formatted as an integer), but I also get negative values after float formatting.
Full float chroma range is -0.5 .. 0.5 so negative values are normal.
EDIT: Ohh, my bad, did not try on a subsampled clip.
- Fix offset for chroma subsampling
- Fix 10+ bit greyscale
In class AvsClipBase you must uncomment two fields:
self.num_components = None # PF 20211109 go live
self.component_size = None # PF 20211109 go live
def GetPixelYUV(self, x, y):
if self.bits_per_component == 8:
component_size = 1;
elif self.bits_per_component == 32:
component_size = 4 # 32 bit float
else:
component_size = 2 # 10-16 bits
# if a resize filter used in the preview filter. CRASH if not check here
if self.DisplayWidth != self.Width or self.DisplayHeight != self.Height:
return (-1,-1,-1)
if self.IsPlanar:
indexY = x * component_size + y * self.pitch
# IsY8 does not detect Y10..Y16,Y32
# Probably IsY is not implemented, so we use num_components
if self.num_components == 1:
if self.bits_per_component == 8:
return (self.ptrY[indexY], -1, -1)
elif self.bits_per_component <= 16:
bufferY = [self.ptrY[indexY], self.ptrY[indexY + 1]]
valY = struct.unpack('=H', bytearray(bufferY))[0]
return (valY, -1, -1)
else:
bufferY = [self.ptrY[indexY], self.ptrY[indexY + 1], self.ptrY[indexY + 2], self.ptrY[indexY + 3]]
valY = struct.unpack('=f', bytearray(bufferY))[0]
return (valY, -1, -1)
x = x >> self.WidthSubsampling
y = y >> self.HeightSubsampling
indexU = indexV = x * component_size + y * self.pitchUV
elif self.IsYUY2:
indexY = (x*2) + y * self.pitch
... rest is the same
pinterf
9th November 2021, 20:42
pinterf, I noticed a few inconsistencies with color related frame props.
Thank you.
As a reference, I'm using z_ConvertFormat.
Avsresize wiki: http://avisynth.nl/index.php/Avsresize
VapourSynth doc: http://www.vapoursynth.com/doc/functions/video/resize.html
But I think I must check VapourSynth resizer behaviour as well, they have a bit longer history.
-Matrix string Rec601 in test23 defaults to ID 5 (470BG), that's PAL Rec601 which is much less common than NTSC Rec601 (170M).
testing z/avs parallel:
ColorBars(pixel_type="RGBP8")
clip1=z_convertformat(pixel_type="yuv420p8").SubTitle("z_conv",y=120)
clip2=ConvertToYUV420().SubTitle("Avs",y=120)
Interleave(clip1, clip2)
propShow()
z_ConvertFormat defaults _Matrix=6 (170M) while I implemented 5 (470BG)
I like when there is a consent, so I'm gonna change it to 6.
FCC corresponds to 470M in ITU to keep the naming convention (170M, 240M, 470BG)
Both avsresize and VapourSynth is using "fcc". The "470m" appears only in transfer characteristic and color primaries.
-YCgCo seems to be also much less used than YCoCg (86K versus 16K in Google search), YCoCg is also the preferred term in the Wikipedia and in the Colour python module.
The base examples are using YCgCo terminology, so I kept it.
(in my opinion when we - here at doom9 or at github - agree on a change then it would be welcomed if everybody change/extend it in their plugin/system.)
-Also noticed that Rec2020 and 2020 are supported as 2020CL and 2020NCL, but not Rec2020CL or Rec2020NCL.
Old matrix constants are kept, but there is no a "rec" or PC" prefix one for every new one.
The preferred strings are the new one, which do not implicitely define full/limited range, but has to specify it after them 2020:f or 2020:full or 2020ncl:l or 2020ncl::limited.
As avsresize wiki says, "2020" is a compatibility alias for "2020ncl", I have implemented the very same convention.
-I couldn't use the "auto" matrix type. From YCbCr, ConvertToPlanarRGB("auto:auto") or ConvertToPlanarRGB("auto") triggers an "Unknown matrix" error.
Thanks, I'm gonna check it.
-Quote (https://forum.doom9.org/showthread.php?p=1956500#post1956500): "When converting to RGB the _Matrix parameter is set to 0 ("rgb")". Yet for internal RGB clips _Matrix is set to 1(?)
What is "internal RGB clips"? Value of "1" is surely wrong for them.
-Also just tested the new dither_bits arg, too bad it doesn't work with dither=-1 for posterization, not sure if it uses the same code path as it can be very useful.
Yes, this dither code has limits.
-Found another issue, how do you correct the bitdepth scale of source without changing the range? Example, load a sample image which by nature is PC range (ie with JPEGSource which has a great builtin deblocker), render the YPlaneMax, it reads 65280. How do we fix this with internal filters? Currently it's only possible with Expr("x 257 256 / *")
JPEGSource return 65280 which is FF00, lower byte is simply zero. This is not a range-question, rather than how JPEGsource is returning you this 16 bit data. (If I understand correctly)
Dogway
9th November 2021, 21:31
FCC is the very old term before ITU standardized it, it's like calling 470BG as EBU Tech. I don't think avsresize should be the golden book for reference on color matters, the colour (https://github.com/colour-science/colour)module or other color science projects are more reliable if you don't take my word for it. But I don't have anything against if still you decide to keep it.
Thanks also for the standard matrix naming convention, I will adhere to them.
What is "internal RGB clips"? Value of "1" is surely wrong for them.
I quoted your example in the test23 release post (https://forum.doom9.org/showthread.php?p=1956500#post1956500)where you post BlankClip in RGB with _Matrix set to 1
JPEGSource return 65280 which is FF00, lower byte is simply zero. This is not a range-question, rather than how JPEGsource is returning you this 16 bit data. (If I understand correctly)
Yes, it can be seen in two ways, a source loader flaw or a lack of options in avs+. I will try to check what loaders fail, unfortunately I think JPEGSource is closed source.
pinterf
10th November 2021, 08:20
FCC is the very old term before ITU standardized it, it's like calling 470BG as EBU Tech. I don't think avsresize should be the golden book for reference on color matters, the colour (https://github.com/colour-science/colour)module or other color science projects are more reliable if you don't take my word for it. But I don't have anything against if still you decide to keep it.
VapourSynth and avsresize both are based on zimg library, and since I'm much less familiar in this area than the creators I rely on them, and learn and read.
I quoted your example in the test23 release post (https://forum.doom9.org/showthread.php?p=1956500#post1956500)where you post BlankClip in RGB with _Matrix set to 1
Ah, I see, it is a typo in docs. Fixed it in original post as well.
EDIT:
FCC is the very old term before ITU standardized it, it's like calling 470BG as EBU Tech. I don't think avsresize should be the golden book for reference on color matters, the colour module or other color science projects are more reliable if you don't take my word for it. But I don't have anything against if still you decide to keep it.
Golden standard because their official constants (matrix, primaries, transfer, chroma location) are from ITU-T H.265, download from here: https://www.itu.int/rec/T-REC-H.265-202108-I
See Table E.5, at value 4 I cannot see any better hint why we not to keep there "fcc". (Unlike transfer and primary)
Dogway
10th November 2021, 19:31
I see, well I won't be taking the zimg route but colour science reference and terms. I have all ITU papers I could find and more but for example the linked Colour repo disregards FCC in favour of 470-525 also called 470M by ITU which is an international standard while FCC is an USA only committe.
I already ranted before of inconsistencies on those papers and many color scientists seem to agree for a reason.
On another note related to image loading:
What is the recommended procedure to convert an image (usually PC range) into HBD?
Expr("255","128") # PC range YUV image
ConvertBits(16,fulls=false,fulld=false) # Now we have PC range but with bitshift scale and _ColorRange of 1 (limited?)
or
ConvertBits(16,fulls=false,fulld=true) # it does a TV range to PC range conversion
Another option is true,true, but then look at this:
Expr("255","128")
ConvertBits(16,fulls=true,fulld=true)
ConvertBits(16,fulls=true,fulld=false)
scriptclip("subtitle(string(UPlaneMax),x=30,y=10)") # output is 32880 instead of 32768
pinterf
10th November 2021, 19:41
Pc range = full range. Both fulls and fulld is true. Like rgb
qyot27
10th November 2021, 20:33
For consistency's sake, using the same names that FFmpeg uses internally makes sense, considering that the two main general-purpose source filters that would be setting frame properties both use FFmpeg's libraries, and that it would also be the thing most likely to be used to playback/encode from a script with those properties set.
pinterf
10th November 2021, 20:34
Another option is true,true, but then look at this:
Expr("255","128")
ConvertBits(16,fulls=true,fulld=true)
ConvertBits(16,fulls=true,fulld=false)
scriptclip("subtitle(string(UPlaneMax),x=30,y=10)") # output is 32880 instead of 32768
But this works:
Expr("255","128")
ConvertBits(32,fulls=true,fulld=true) # 8->32 bits: OK
ConvertBits(16,fulls=true,fulld=false) # 32->16 bits: OK: 32768
This is because when converting to and from 32 bit float the chroma channel is handled specially because of the 0 chroma center at 32 bit float formats.
While in your example
ConvertBits(16,fulls=true,fulld=true)
the internal Avisynth code has no special chroma handling case. The range 0-255 is multiplied by 65535/255 (=257) to stretch the range. :(
It is not correct, because 128 is not the real center of the 0-255 range. Cb Cr is a signed quantity and it is only a technical thing that they are biased and stuffed into an unsigned byte (or 16 bit word) 16-240 is -112..+112 in reality, and its full range equivalent must be -127..+127.
I was thinking earlier that a correct method would be good to implement.
Integer-to-Integer full-full range originated chroma conversion must first subtract 128 (8 bit case) from source, then upscale by a factor then add the new bitdepth's center.
U8 to U16: (U-128) / 127 * 32767 + 32768
1 -> 1
128 -> 32768 (center is O.K.!)
255 -> 65535
In general:
half_src = 2^(M-1) where M is src bit depth
half_dest = 2^(N-1) where N is target bit depth
U_dest = (U_src - half_src) / (half_src-1) * (half_target - 1) + half_target
Note: theoretically a full range 8 bit chroma must have in the range of 1-255 (128 center is kept) 0 is invalid value in any bit depth.
Yes. I have to go this way.
Dogway
10th November 2021, 21:19
This issue propagates into internal RGB conversion with:
ConvertBits(16,fulls=true,fulld=true)
ConverttoplanarRGB("PC.709")
scriptclip("subtitle(string(GPlaneMax),x=30,y=10)") # outputs 65451
The same happens with z_ConvertFormat and fmtc_matrix. My current (not uploaded yet) ConvertFormat version converts to RGB correctly without this happening in 16-bit (grey gradient ramp is achromatic), but still there are other issues I have to iron out before saying I got a solution, also I did the YUV to RGB implementation months ago so I have to revisit it.
The described formula looks right, I tested over other bitdepths, they don't match my HBD constants so I might have a second look to them.
This is 12-bit:
U=240
(U-128) / 127 * 2047 + 2048
Output: 3853,228
gispos
10th November 2021, 21:25
EDIT: Ohh, my bad, did not try on a subsampled clip.
- Fix offset for chroma subsampling
- Fix 10+ bit greyscale
Thanks again, seems to be working.:)
In class AvsClipBase you must uncomment two fields:
IsY, component_size, num_components
It is available in the newer versions and is only set to None during initialization.
Just for my better understanding IsY would then replace num_components?
IsY recognizes all color depths with a single Y component and IsY8 only recognizes 8-bit single Y components?
pinterf
10th November 2021, 21:28
I see, well I won't be taking the zimg route but colour science reference and terms. I have all ITU papers I could find and more but for example the linked Colour repo disregards FCC in favour of 470-525 also called 470M by ITU which is an international standard while FCC is an USA only committe.
I already ranted before of inconsistencies on those papers and many color scientists seem to agree for a reason.
You are argueing on how we should call the conversion filter parameter string which would select "Table E.5 Matrix code 4", which has KR = 0.30; KB = 0.11 and we cannot call it neither 470M nor any other because they have different coefficients?
Perhaps let we name it "fcc_title_47_code_2003" instead of simple "fcc" named after its informative remark
"FCC Title 47 Code of Federal Regulations (2003) 73.682 (a) (20)"?
pinterf
10th November 2021, 21:31
IsY recognizes all color depths with a single Y component and IsY8 only recognizes 8-bit single Y components?
Yes. I was not sure that IsY was implemented at the Python C interface, this is why I didn't use.
pinterf
10th November 2021, 21:40
This issue propagates into internal RGB conversion with:
ConvertBits(16,fulls=true,fulld=true)
ConverttoplanarRGB("PC.709")
scriptclip("subtitle(string(GPlaneMax),x=30,y=10)") # outputs 65451
Yes, and when conversion is OK (going through 32 bit - which is correct), then you get 65535.
ColorbarsHD() # just for YV24 format
Expr("255","128")
ConvertBits(32,fulls=true,fulld=true)
ConvertBits(16,fulls=true,fulld=true)
ConverttoplanarRGB("PC.709")
scriptclip("subtitle(string(GPlaneMax),x=30,y=10)") # outputs 65535 Yeah
I'm gonna do it right for direct 8-16 conversions.
Dogway
10th November 2021, 21:41
You are argueing on how we should call the conversion filter parameter string which would select "Table E.5 Matrix code 4", which has KR = 0.30; KB = 0.11 and we cannot call it neither 470M nor any other because they have different coefficients?
Perhaps let we name it "fcc_title_47_code_2003" instead of simple "fcc" named after its informative remark
"FCC Title 47 Code of Federal Regulations (2003) 73.682 (a) (20)"?
All of a sudden ^^ I don't care how you call it, it was an educated suggestion. I will do my own thing.
pinterf
11th November 2021, 18:43
All of a sudden ^^ I don't care how you call it, it was an educated suggestion. I will do my own thing.
Dear Dogway, you were right.
I read that pdf for the Nth time, and did not recognize the zillion sub-option letters after BT.470-6. I've changed the Avisynth code accordingly. I'm gonna thank you with a glass of red wine in the evening (Kadarka) :)
Dogway
11th November 2021, 19:49
Last recommendation (https://www.itu.int/rec/R-REC-BT.1701-1-200508-I/en) in 2005 (in force). 1701-M anyone? NTSC-M also seems legit.
pinterf
12th November 2021, 11:42
Last recommendation (https://www.itu.int/rec/R-REC-BT.1701-1-200508-I/en) in 2005 (in force). 1701-M anyone? NTSC-M also seems legit.
I'm lost and not seeing in this document the relevant info.
Plenty of papers.
However this paper from 2015 (Report ITU-R BT.2380-0 07/2015 Television colorimetry elements) is the most detailed one I found so far.
https://www.itu.int/dms_pub/itu-r/opb/rep/R-REP-BT.2380-2015-PDF-E.pdf
In TABLE 2.8 matrix_coefficient=4 says:
- US NTSC 1953 Recommendation for transmission standards for colour television (only MPEG-2 Video, MPEG-4 Visual, MPEG HEVC)
- US FCC Title 47 Code of Federal Regulations (2004) 73.682 (a) (20) (only MPEG-4/AVC)
- Recommendation ITU-R BT.470-6 system M (only MPEG-H HEVC)
As a shortcut both bt470m, fcc or fcc47 and probably ntsc1953 or ntsc-m would be valid, when we want to hint [0.30, 0.59, 0.11] matrix.
For historical reasons we had "fcc" for that, then now there is a "bt470m".
I'd like to make propShow to write a human-friendly short descriptions when displaying _Matrix (_ColorRange, ...)
Other topic:
I'm undereducated on these areas: primaries and transfer characteristics, O.K., I can look into the sources of zimg and fmtconv.
Is there any good and clean documentation I can learn from or google is my friend?
Dogway
12th November 2021, 15:03
ITU-R BT.2380-0 07/2015 seems to focus on digital television (SD and HD) except for the tables where it mentions some analogue formats. The tables repeat in several papers, also in T-REC-H.265-201911 and T-REC-H.273-201612. These are codec specific papers whereas BT.2380 looks like a typical standard recommendation.
The current paper (in effect) for analogue formats is R-REC-BT.1701-1-200508 where you can find the specifications for the different types of PAL and NTSC, which some of them we have to deal with. I don't know why they still refer to R-REC-BT.470-6-199811 in these newer papers. I'm not going to make a fuss about cosmetics calling a matrix x or y. 470 or PAL/NTSC with the hyphen+letter seems the most common, shorter and logic to follow, but x265 still uses 'fcc' some whatever pleases you.
The current digital NTSC matrix/primaries (they call it simply 525) is based on 170M, aka SMPTE-C aka Rec601 in Doom9.
As I understand the difference of the matrix naming for the different codecs is because the codec spec is not updated to latest recommendations, so in AVC it's called what fcc, in MPEG2 NTSC 1953 and in HEVC 470M. We are newer so we can call it 1701M ^^
EDIT: Last year I made a project for legacy formats (where I have some knowledge but barely for newer HDR formats), and besides these recommendations and some random papers and books I found a very valuable one called "Video Demystified" by Keith Jack. You can find excerpts and PDFs on google.
jpsdr
12th November 2021, 17:40
@pinterf
This is an "old" version, two updates has been made since.
Last is : https://www.itu.int/pub/R-REP-BT.2380-2-2018
You can read the PDF i've made with my HDRTools, i've tried to explain some things. I don't know if i've succed...
FranceBB
13th November 2021, 14:35
I don't know if i've succed...
You have. That document has been translated in Italian by me and has been in our intranet ever since you made it years ago (with your credits of course) eheheheh
Dogway
15th November 2021, 15:08
Is the 'neg' operator working in Expr? I tried several combinations without success.
pinterf
16th November 2021, 18:55
Well, this build took a longer time to develop.
A _lot_of ConvertBits tweaks (almost a total rewrite in the background), another Dogway wish in Expr, adventures with Intel C++ compiler.
What I enjoyed most was playing with the low dither_bit option both in ordered and in Floyd type of dithering.
Avisynth+ 3.7.1 test build 26 (20211116) (https://drive.google.com/uc?export=download&id=13_UFB4KL_KKFi4pC_G5HBVCRixeEvBqL)
20211116 WIP
------------
- Expr: add "neg": negates stack top: a = -a
- Floyd dither ("dither"=1)
- add native fulls-fulld support, add special chroma handling when full-range = true involved
- valid "dither_bits" parameter 1 to 16 (similar to ordered dither)
- special handling of low (1-7 bits) "dither_bits" => result looks nice, same as at ordered dither
- more optimized to frequently used source and dither target bits differences: 2,4,6 and 8
(covers typical 16->8, 10->8, 16->10 bit conversions; others have ~-10% speed, less than 8 bit targets are -20-25% )
- (fix YV411 to and from conversion - regression since recent chroma placement addition)
- ConvertBits: Support YUY2 (by autoconverting to and from YV16), support YV411
- ConvertBits: "bits" parameter is not compulsory, since the dit depths can stay as it was before. One can call like ConvertBits(fulld=true)
- ConvertBits: "dither" parameter: type changed to integer. Why was it float? :) valid values were 0 and 1
- ConvertBits: source: dither almost full refactor
- ConvertBits: allow dithering down from 8 bit sources (use case: specify parameter "dither_bits" less than 8)
Example: My8bitVideo.ConvertBits(8, fulls=true, fulld=true, dither = 0, dither_bits=1)
- ConvertBits: ordered dither (dither_type=0) new features
- add AVX2
- allow odd dither_bits values, 1-16 bits (was: 2,4,6,8,..). The difference is still maximum 8, so dither_bits=1 is available
only for 8 bit sources. (memo: for Floyd (dither=1) the minimum remained 1, allowed range is 1-16)
- correct conversion of full-range chroma at 8-16 bits, keeping center
- fulls-fulld mix support (conversion - if any - happens before dithering)
- when dither target bitdepth is less than 8, then special measures are taken in order to show 'nice' output;
using dither_bits=1 would be especially ugly without this. (dither table is treated as signed float, autocorrect levels)
Why autocorrect? Ordered dither produces (2^dither_bits) different pixel values.
e.g. dither_bits=1 results in pixel values 0 and 1; dither_bits=2 => 0 to 3, and so on, dither_bits=7 => 0 to 127
When these dithered pixel values are scaled back to 8 bits, Avisynth stretches the upper extremes to 255 (8 bit case).
At dither_bits=1 instead of 0, 128 we get 0 and 255. Or at dither_bits=2 the values 0, 64, 128, 192 are translated to 0, 85, 170, 255.
Note: for low dither targets RGB definitely looks better.
- Use _Matrix name "bt470m" for value=4 ("fcc" is still kept)
Source: Rename AVS_MATRIX_FCC to AVS_MATRIX_BT470_M
- ConvertBits: Correct conversion of full-range chroma at 8-16 bits, keeping center (32 bit float was O.K.) (ditherless case)
- ConvertBits: Direct, much quicker conversions between 8-16 bit formats when either source or target is full range, avx2 support (ditherless case)
Special even quicker case: 8->16 bit fulls=true, fulld=true (simply *257)
- ConvertBits: Fix: fulls=true->fulld=true 16->8 bit missing rounding
- CMake/source: Intel C++ Compiler 2021 and Intel C++ Compiler 19.2 support
With the help of CMake GUI:
- Generator: "Visual Studio 16 2019"
- Optional toolset to use (-T option): (type to the editbox)
For LLVM based icx: Intel C++ Compiler 2021
For classic 19.2 icl: Intel C++ Compiler 19.2
- Specify native compilers (choose radiobutton),
then browse for the appropriate compiler executable path. For example:
icx: C:\Program Files (x86)\Intel\oneAPI\compiler\latest\windows\bin\icx.exe
icl: C:\Program Files (x86)\Intel\oneAPI\compiler\latest\windows\bin\intel64\icl.exe
There are some bugs in the Intel-VS integration:
If you have errors like "xilink: : error : Assertion failed (shared/driver/drvutils.c, line 312" then
as a workaround you must copy clang.exe (by default it is located in C:\Program Files (x86)\Intel\oneAPI\compiler\latest\windows\bin)
to the folder beside xilink (for x64 configuration it is in C:\Program Files (x86)\Intel\oneAPI\compiler\latest\windows\bin\intel64).
- CMake/source: Intel C++ Compiler 2021 and Intel C++ Compiler 19.2 support
tormento
16th November 2021, 19:32
What I enjoyed most was playing with the low dither_bit option both in ordered and in Floyd type of dithering.
Thank you so much!
Would it be difficult to implement the dithering modes of fmtconv? At least dmode=8, i.e. Void and cluster halftone dithering. I find it really effective and compression efficient.
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.