Log in

View Full Version : fmtconv: resize, bitdepth and colorspace conversions


Pages : 1 2 3 4 5 6 [7] 8

feisty2
24th July 2020, 19:24
Found out the solution myself, if an alpha channel is present two clips will be returned.


fun fact: python has language level support for functions with multiple return values, so this works even better (for the sake of readability)


c, alpha = core.ffms2.Source("prores4444.mov")

Cary Knoop
24th July 2020, 19:50
fun fact: python has language level support for functions with multiple return values, so this works even better (for the sake of readability)


c, alpha = core.ffms2.Source("prores4444.mov")

Cooool!

Blue_MiSfit
13th October 2020, 23:25
THANK YOU for making this tool and the impeccable documentation. I've been remastering some old SD content recently into HD and this has been extremely helpful for doing the transfer and primaries conversion!

Selur
2nd November 2020, 20:39
A Hybrid user reported this issue to me and I can reproduce it on my system.
using https://github.com/EleonoreMizo/fmtconv/releases/tag/r22
with
# Imports
import vapoursynth as vs
core = vs.get_core()
# Loading Plugins
core.std.LoadPlugin(path="I:/Hybrid/64bit/vsfilters/Support/fmtconv.dll")
core.std.LoadPlugin(path="I:/Hybrid/64bit/vsfilters/SourceFilter/LSmashSource/vslsmashsource.dll")
# source: 'F:\TestClips&Co\files\YUV\yuv422_16bitBitEndianStereo.mov'
# current color space: YUV422P8, bit depth: 0, resolution: 848x352, fps: 23.976, color matrix: 709, yuv luminance scale: limited, scanorder: progressive
# Loading F:\TestClips&Co\files\YUV\yuv422_16bitBitEndianStereo.mov using LWLibavSource
clip = core.lsmas.LWLibavSource(source="F:/TestClips&Co/files/YUV/yuv422_16bitBitEndianStereo.mov", format="YUV422P8", cache=0, prefer_hw=0)
# making sure input color matrix is set as 709
clip = core.resize.Point(clip, matrix_in_s="709",range_s="limited")
# making sure frame rate is set to 23.976
clip = core.std.AssumeFPS(clip=clip, fpsnum=24000, fpsden=1001)
# Setting color range to TV (limited) range.
clip = core.std.SetFrameProp(clip=clip, prop="_ColorRange", intval=1)
original = clip
# cropping the video to 842x348
clip = core.std.CropRel(clip=clip, left=0, right=6, top=2, bottom=2)
# cropping the video to 842x348
original = core.std.CropRel(clip=original, left=0, right=6, top=2, bottom=2)
clip = core.fmtc.resample(clip=clip, kernel="spline16", w=1280, h=530, interlaced=False, interlacedd=False)
original = core.fmtc.resample(clip=original, kernel="spline16", w=1280, h=530, interlaced=False, interlacedd=False)
# adjusting output color from: YUV422P16 to YUV420P8 for x264Model (i420@8-bit)
clip = core.resize.Bicubic(clip=clip, format=vs.YUV420P8, range_s="limited")
# adjusting for FilterView
#if original.format.id != clip.format.id:
# if (original.format.color_family == vs.RGB and clip.format.color_family != vs.RGB):
#original = core.resize.Bicubic(original, format=clip.format.id, matrix_s="470bg", range_s="limited")
#elif (original.format.color_family == clip.format.color_family):
# original = core.resize.Bicubic(original, format=clip.format.id, range_s="limited")
# else:
# original = core.resize.Bicubic(original, format=clip.format.id, matrix_in_s="470bg", range_s="limited")
stacked = core.std.StackHorizontal([original,clip])
# set output frame rate to 23.976fps
stacked = core.std.AssumeFPS(clip=stacked, fpsnum=24000, fpsden=1001)
# Output
stacked.set_output()
and
I:\Hybrid\64bit\Vapoursynth>VSPipe.exe c:\Users\Selur\Desktop\test.vpy e:\Test.avi


I:\Hybrid\64bit\Vapoursynth>VSPipe.exe c:\Users\Selur\Desktop\test.vpy e:\Test.raw


I:\Hybrid\64bit\Vapoursynth>VSPipe.exe c:\Users\Selur\Desktop\test.vpy e:\Test.raw

Output 80 frames in 0.29 seconds (274.31 fps)

I:\Hybrid\64bit\Vapoursynth>VSPipe.exe c:\Users\Selur\Desktop\test.vpy e:\Test.raw

Output 80 frames in 0.29 seconds (272.45 fps)

I:\Hybrid\64bit\Vapoursynth>VSPipe.exe c:\Users\Selur\Desktop\test.vpy e:\Test.raw


I:\Hybrid\64bit\Vapoursynth>VSPipe.exe c:\Users\Selur\Desktop\test.vpy e:\Test.raw

Output 80 frames in 0.29 seconds (272.80 fps)

I:\Hybrid\64bit\Vapoursynth>VSPipe.exe c:\Users\Selur\Desktop\test.vpy e:\Test.raw


I:\Hybrid\64bit\Vapoursynth>
it randomly crashes,... every few times,..
Changing the source filter from LWLibavSource to FFMS2

core.std.LoadPlugin(path="I:/Hybrid/64bit/vsfilters/SourceFilter/FFMS2/ffms2.dll")
clip = core.ffms2.Source(source="F:/TestClips&Co/files/YUV/yuv422_16bitBitEndianStereo.mov",cachefile="E:/Temp/mov_f1203bb1621d87009c15418dab3b00fb_853323747.ffindex",format=vs.YUV422P8,alpha=False)

doesn't help, it even seems that it crashed more often with ffms2.

removing:
clip = core.fmtc.resample(clip=clip, kernel="spline16", w=1280, h=530, interlaced=False, interlacedd=False)
original = core.fmtc.resample(clip=original, kernel="spline16", w=1280, h=530, interlaced=False, interlacedd=False)
and everything works.
Changing "spline16" to "spline64" same thing happens, but it seems to happen less frequently.
(same for spline36)
When using 'cubic' is seems to always crash.

Cu Selur

Ps.: Uploaded the clip I used to my GoogleDrive (https://drive.google.com/file/d/1X8gLxWSXqbsWe4QJPqwCUBcy93zjhfiN/view?usp=sharing) (~46MB)

groucho86
16th April 2021, 22:07
Yes it looks so

import vapoursynth as vs
import muvsfunc
core = vs.get_core()

input_path = 'source_sgamut

c = core.imwri.Read(input_path,float_output=True)
#c = core.std.Expr(clips=[c], expr=" x 0.9 *")
c = core.std.Expr(clips=[c], expr=" x 0.01125000 >= x 0.01 + 0.19 / log 10 log / 261.5 * 420 + 1023 / 171.2102946929 95 - x * 0.01125000 95 + / 1023 / ?")
c.set_output()


Not sure if the resolve result is right either, maybe there is need to scaling from linear to reflection multiply by 0.9

https://github.com/videovillage/Lattice-Issues/issues/17

https://pro.sony/s3/cms-static-content/uploadfile/06/1237494271406.pdf

age, for posterity's sake, I just realized that the second half of the lin to slog3 expression (the one dealing with values below 0.01125000) was not working as expected.

The proper RPN expr for linear to slog3 is:

x 0.01125000 >= x 0.01 + 0.19 / log 10 log / 261.5 * 420.0 + 1023.0 / x 171.2102946929 95.0 - * 0.01125000 / 95.0 + 1023.0 / ?

MysteryX
21st June 2021, 19:54
Running this code in VsEdit gives this error


video = core.resize.Point(video, format=vs.GRAY16)
video = core.fmtc.transfer(video, transs="709", transd="linear", fulls=0, fulld=1)
video = core.resize.Point(video, format=vs.GRAY8)



Error on frame 0 request:
Resize error -1: invalid graph state L910: !m_state.has_chroma() || m_state.plan

Selur
22nd June 2021, 19:36
@MysteryX: I can reproduce the issue unless I set the _ColorRange property beforehand:

# Setting color range to TV (limited) range.
video = core.std.SetFrameProp(clip=video , prop="_ColorRange", intval=1)


# Setting color range to PC (full) range.
video = core.std.SetFrameProp(clip=video , prop="_ColorRange", intval=0)


Cu Selur

cretindesalpes
14th July 2021, 12:53
Running this code in VsEdit gives this error

video = core.resize.Point(video, format=vs.GRAY16)
video = core.fmtc.transfer(video, transs="709", transd="linear", fulls=0, fulld=1)
video = core.resize.Point(video, format=vs.GRAY8)


Can be fixed by removing the _ColorRange property before sending it to output:
video = core.std.SetFrameProp (video, prop="_ColorRange", delete=True)
video.set_output()
The problem exists even without calling fmtconv, just by setting the property manually to 0 (full range). There’s nothing in the VS doc that forbids to attach a _ColorRange property set to 0 to a GRAY8 or GRAY16 clip, so I think it’s probably a bug related to VS Editor.

cretindesalpes
14th July 2021, 14:18
fmtconv r23 (http://forum.doom9.org/showthread.php?t=166504):

transfer: added an Exposure Index (EI) parameter for the Arri Log C Alexa 2.x and 3.x curves.
bitdepth: properly sets the _ColorRange attribute.
Doesn’t output a debug message when AVSTP is not found.
Fixed a concurrency issue by using a more recent toolkit when compiling with MSVC.
Windows XP is not supported any more.

kedautinh12
14th July 2021, 14:49
Please can you port to avisynth??

feisty2
14th July 2021, 15:56
dither is the equivalent toolkit for avisynth.

kedautinh12
14th July 2021, 16:24
dither is the equivalent toolkit for avisynth.

I don't think so
https://forum.doom9.org/showpost.php?p=1943559&postcount=1131

cretindesalpes
10th August 2021, 10:30
I already ported bitdepth, matrix and matrix2020cl to Avisynth+, so we’re halfway now. I’ll start a thread in the Avisynth forum when it is ready.

cretindesalpes
17th August 2021, 07:14
fmtconv r24 (https://forum.doom9.org/showthread.php?t=166504):
bitdepth: added dithering mode 9: quasirandom sequences.
bitdepth: added a triangular probability distribution function (TPDF) for the dithering patterns and noises, along with the associated parameters tpdfo and tpdfn.
bitdepth: added corplane parameter to prevent colored noise in RGB processing.
bitdepth: fixed crash when trying to change the range (full or TV) without reducing the bitdepth.
matrix: deletes the _Matrix and _ColorSpace properties if a non-standard matrix is used.
matrix2020cl: sets the _Matrix and _Transfer frame properties.
matrix2020cl: fixed hideous colors when converting slightly out-of-colorspace values from integer Y’Cb’Cr’ to integer linear RGB.
resample: totalh and totalv are now correctly taken into account, added total parameter too.
resample: added a planes parameter.
transfer: sYCC curve (similar to sRGB) now supports signed values.
transfer: added a planes parameter.
Added support for Avisynth+
Added information on functions reading and writing frame properties.
Added more support for 14-bit data.
Vapoursynth: still uses API v3.6 but can use Python constants from future API v4.0.

I did a lot of internal changes in this release because of the Avisynth+ port so I hope I haven’t broke too many things. The next thing I’ll do is probably adding reference OOTFs (direct and inverse) to transfer to fully support the BT.2100 HDR pipeline and scene- or display-referred linear RGB.

kedautinh12
17th August 2021, 08:54
Thanks

cretindesalpes
26th August 2021, 17:57
I’m very likely to remove the planes parameter from fmtc_transfer introduced in r24. I added it because it was almost free, but with the upcomping addition of OOTFs, planes are no longer independant, and the parameter is making the implementation too complicated for my taste. Any objection?

poisondeathray
4th September 2021, 18:01
Some issue with either transfer or primaries function in r24, that worked ok with r22 in vapoursynth version x64. I didn't test x86 or avs version

When converting ProPhoto (romm) or AdobeRGB to sRGB, it works ok in r22 . But in r24, there is some clipping or some errors in some channels

Best way is to see example:

Demo package ,

https://www.mediafire.com/file/k5rfblwvpi7tkwp/OxbowBoots_AdobeRGB,ProPhoto,sRGB.zip/file

(src photos from https://furbo.org/color/WideGamut/)


srgb = core.imwri.Read(r'Oxbow_Boots_sRGB.jpg')
prophoto = core.imwri.Read(r'Oxbow_Boots_ProPhoto.jpg')
adobe = core.imwri.Read(r'Oxbow_Boots_AdobeRGB.jpg')

atos = core.fmtc.bitdepth (adobe, bits=32)
atos = core.fmtc.transfer (atos, transs="adobergb", transd="linear")
atos = core.fmtc.primaries (atos, prims="adobe98", primd="srgb")
atos = core.fmtc.transfer (atos, transs="linear", transd="srgb")
atos = core.resize.Point(atos, format=vs.RGB24)

ptos = core.fmtc.bitdepth (prophoto, bits=32)
ptos = core.fmtc.transfer (ptos, transs="romm", transd="linear")
ptos = core.fmtc.primaries (ptos, prims="romm", primd="srgb")
ptos = core.fmtc.transfer (ptos, transs="linear", transd="srgb")
ptos = core.resize.Point(ptos, format=vs.RGB24)

i = core.std.Interleave(clips=[srgb, atos, ptos])

i.set_output()

cretindesalpes
5th September 2021, 08:40
Thank you, I can reproduce the issue here (dark tones with transfer). I’m going to check what is wrong.

EDIT: it was the linear part of the sRGB curve that was wrong from r24. Fixed in commit f7cd019, will be available in the next full release or hot fix update.

cretindesalpes
19th September 2021, 18:16
fmtconv r25 (https://forum.doom9.org/showthread.php?t=166504) is mostly a bug-fix release:
bitdepth/Avisynth+: fixed I420 input that couldn’t be converted to higher bitdepth. Thanks to StvG for the report.
matrix: fixed the output colorspace autodetection which failed with specific matrix combinations.
resample/Avisynth+: fixed fulls and fulld parameters which were wrongly defined as int instead of bool.
resample/Avisynth+: fixed cplaced which was wrongly copied from cplaces. Thanks to TbtBI for the report.
transfer: automatically adapts the output format (16-bit integer) if the input is a low-bitdepth clip and nothing is specified in bits nor flt, instead of emitting an error.
transfer: fixed the BT.2100 HLG curve that was inverted.
transfer: fixed the sRGB curve linear part and extended its positive range. Thanks to poisondeathray for the report.
Avisynth+: fixed a crash occuring when using data bitdepths between 9 and 14. Thanks to tormento for the report.

Etroxamin
27th September 2021, 16:15
hey, i have a (hopefully) small problem:

i've converted YUV 8bit 420 to RGB 32bit 444, looks like this:

src = core.fmtc.bitdepth(src, bits=32)
src = core.fmtc.resample (src, css="444")
src = core.fmtc.matrix(src, mat="709", col_fam=vs.RGB, bits=32)

that works without problems.

now change it to YUV 10bit 420:

src = core.fmtc.bitdepth (src, bits=10)
src = core.fmtc.matrix(src, mat="709", col_fam=vs.YUV, bits=10)
src = core.fmtc.resample (src, css="420")

that works, but gives me a brighter picture, perhaps because of full range instead of tv.

i just started with VS scripts and could need some help here. How to do that?
Thanks in advance.

poisondeathray
27th September 2021, 17:41
hey, i have a (hopefully) small problem:

i've converted YUV 8bit 420 to RGB 32bit 444, looks like this:

src = core.fmtc.bitdepth(src, bits=32)
src = core.fmtc.resample (src, css="444")
src = core.fmtc.matrix(src, mat="709", col_fam=vs.RGB, bits=32)

that works without problems.

now change it to YUV 10bit 420:

src = core.fmtc.bitdepth (src, bits=10)
src = core.fmtc.matrix(src, mat="709", col_fam=vs.YUV, bits=10)
src = core.fmtc.resample (src, css="420")

that works, but gives me a brighter picture, perhaps because of full range instead of tv.

i just started with VS scripts and could need some help here. How to do that?
Thanks in advance.



You can specify fulls and fulld (s for source, d for destination) in the fmtc.matrix lines

Etroxamin
28th September 2021, 14:07
You can specify fulls and fulld (s for source, d for destination) in the fmtc.matrix lines

hey, thanks for your help, but i just started with vs scripts and this doesnt't really help me to know what to do, could you eventually provide me with a full example?

thanks in advance.

poisondeathray
28th September 2021, 15:16
hey, thanks for your help, but i just started with vs scripts and this doesnt't really help me to know what to do, could you eventually provide me with a full example?

thanks in advance.


Why are you doing this in that manner ? Why not 8bit420 to 10bit420 directly ?

fmtc.Resample always outputs 16bit int or 32bit float. So it does not make sense to use fmtc.bitdepth to downconvert to 10bit then up, then down again

From the documentation:

Output is always 16-bit integer (default for integer input) or 32-bit float. Use fmtc.bitdepth to convert the result to a lower bitdepth.



eg. if your input is limited range, fulls=False (limited range YUV) to full range RGB. Then the reverse when you go from RGB (full) to YUV (limited)


src = core.fmtc.bitdepth(src, bits=32)
src = core.fmtc.resample (src, css="444")
src = core.fmtc.matrix(src, mats="709", fulls=False, fulld=True, col_fam=vs.RGB)

src = core.fmtc.matrix(src, mat="709", fulls=True, fulld=False, col_fam=vs.YUV)
src = core.fmtc.resample (src, css="420")
src = core.fmtc.bitdepth (src, bits=10) #set your dither mode, default is 3 Sierra-2-4A error diffusion

Etroxamin
28th September 2021, 17:14
Why are you doing this in that manner ? Why not 8bit420 to 10bit420 directly ?

Well, i just try out a few things and see how they work.

The source is 8bit yuv 420, anime with a lot of ugly artefacting, as it has dynamic grain added. I convert it to 16 bit, with hope that certain filters will work better in 16 bit, than convert it to 32bit rgb 444, cause i try with Waifu up/down sampling to remove some grain, but on the other side also to give more sharpness at the same time, I tried to mimic this sharpening, but it looks better with waifu up/down, or else i would need to use dehaloing, but that may will destroy fine white lines that are no halos. But i still need to test if waifu suits for videos ...

btw, someone recommended this:

src = core.resize.Bicubic(src, format=vs.RGBS, matrix_in_s='709')

src = core.resize.Bicubic(src, format=vs.YUV420P10, matrix_s='709', dither_type='none')

when i use this the higher brightness doesn't appear, but i will try your example as well, thanks a lot for that btw.

And ... there seem to be a few more ways to do these conversions, can you recommand a "way" eventually? As said, i am quite new to VS scripts, so any recommendations would be helpful.

poisondeathray
28th September 2021, 17:19
And ... there seem to be a few more ways to do these conversions, can you recommand a "way" eventually? As said, i am quite new to VS scripts, so any recommendations would be helpful.

Yes, more than one way to do the same thing

I prefer internal core.resize , for general use because fewer lines to write.

But there are some functions that fmtc has that resize does not (eg. some transfer functions, some kernels, some different dithering patterns, a few other things)

AMED
11th October 2021, 08:12
Sorry a bit of a stupid question but is there any reason to use core.fmtc.resample over core.resize.Spline36 for resizing the blurays from 1080p to 720p?

Possibly just overkill?

Yomiko
11th October 2021, 09:35
In fmtc you can specify cropping arguments for each plane, so if the source has chroma shift to fix, you will see the convenience.

MysteryX
15th October 2021, 04:31
When using bitdepth, do I need to set fulls and fulld on every call? Or does fulld take fulls by default? Or does it read frame properties?

cretindesalpes
15th October 2021, 08:03
Like other fmtconv functions, bitdepth assumes that the range is full for RGB and YCgCo, and narrow for the others (namely Y with or without UV). So there is no need to set the full* parameters if you know the default values are valid for your use. At the moment, the frame properties are not used to detect the range, I don’t know if there is a need for this.

MysteryX
15th October 2021, 14:37
Like other fmtconv functions, bitdepth assumes that the range is full for RGB and YCgCo, and narrow for the others (namely Y with or without UV). So there is no need to set the full* parameters if you know the default values are valid for your use. At the moment, the frame properties are not used to detect the range, I don’t know if there is a need for this.
When converting bitdepth, it doesn't change the format and shouldn't change the range. After reading the frame property, for YUV conversion, do I need to set BOTH fulls and fulld on every call?

So far it has been converting YUV full-range clips with default fulls=false and fulld=false. Output seems "fine", but what's the impact of that?

poisondeathray
15th October 2021, 14:53
When converting bitdepth, it doesn't change the format and shouldn't change the range. After reading the frame property, for YUV conversion, do I need to set BOTH fulls and fulld on every call?

So far it has been converting YUV full-range clips with default fulls=false and fulld=false. Output seems "fine", but what's the impact of that?

In terms of code values, no problems

But FrameProps for _ColorRange will be changed to "1" (limited range) . So if earlier source was flagged full range "0" for FrameProps, it will now say limited, which might be problematic. You can SetFrameProp to "0" to mark it full, or use fulls=True, fulld=True

MysteryX
15th October 2021, 16:48
Under what authority is it setting frame props if it isn't reading them?

If it's just that, fulld sets it; what is fulls for?

cretindesalpes
15th October 2021, 17:21
You can do a range conversion in the same step as bitdepth change. Or you can even change the range without changing the bitdepth.

Using a TV-range conversion with a full range signal works but the results will be slightly off: code for 100 % white is 255 in 8 bits and 1023 in 10 bits. With a TV-range conversion, 255 becomes 1020. It is generally not a big deal when converting between large bitdepth because the difference is really tiny.

MysteryX
15th October 2021, 18:03
That could explain the very slight luma shift I was seeing; as I'm performing several conversions.

IMO by default it should read and preserve frame properties, and setting fulls should also set fulld's default. Applying TV-PC range conversion should only be done when explicitly said.

cretindesalpes
19th October 2021, 15:59
fmtconv r26 (https://forum.doom9.org/showthread.php?t=166504):
matrix: fixed the output colorspace when using singleout.
matrix: fixed the output colorspace when using a custom matrix. Thanks to vxzms for the report.
matrix/Vapoursynth: _Matrix and _ColorSpace frame properties are actually deleted when a custom matrix is used or the final colorspace is unknown. Thanks to mysteryx93 for the report.
resample: fixed empty custom impulse that could cause a crash.
resample: added top-left chroma location.
resample/Avisynth+: interlacing detection now uses the global stream information when the frame properties are not available.
resample/Avisynth+: fixed the planes parameter.
transfer: Linear light can now be display- or scene-referred. Added sceneref, lw, lws, lwd, lb, ambiant and deprecated blacklvl.
transfer: By default, automatically matches the reference white levels for source and destination transfer curves. This may cause some backward incompatibilities. match parameter added.
transfer: Removed the planes parameter introduced in r24 because planes are no longer independent of each other.
transfer: debug provides information about the transfer operation and levels as a frame property.
transfer: BT.470M characteristic is now a pure power curve, instead of a copy of the sRGB curve.
transfer/Avisynth+: fixed flt + bits combination that was ignored. Thanks to DTL for the report.
transfer/Avisynth+: fixed case sensitivity to transs and transd.
transfer/Vapoursynth: fixed logceis and logceid that were missing from the function registration since their introduction in r23… Thanks to groucho86 for the report.
Fixed compatibility with Avisynth+ 3.7.1.
Avisynth+: fixed "RGBPxx" colorspace values that weren’t correctly interpreted as planar.

cretindesalpes
30th October 2021, 12:01
fmtconv r27 (https://forum.doom9.org/showthread.php?t=166504):
matrix: fixed coefficient errors when using singleout.
primaries: added Sony P22 primaries.
transfer: better selection between linear and logarithmic input for LUTs, LUT size reduced.
transfer: fixed crash with grey colorspace. Thanks to vxzms for the report.

lansing
1st November 2021, 00:29
I got an error trying to convert a GRAY8 to YV12,
"Error: Filter resample didn't set videoinfo", what does it mean?


clip = core.std.ShufflePlanes(clip, 0, colorfamily=vs.GRAY)
clip = core.fmtc.resample(clip, css="420")

cretindesalpes
1st November 2021, 09:44
resample cannot change the format like this. You can change the chroma subsampling using css only for a format which already has chroma channels. I’m going to make the error message more explicit.

MysteryX
7th November 2021, 19:09
For specifying matrix(mat=...), how can I convert INT value from frame property into a string value it will understand?

btw I did a performance test on 5K clip with built-in Bicubic vs FMTC

List of heaviest filters with vspipe --filter-time

Built-in Bicubic:

Script evaluation done in 7.41 seconds
Output 30 frames in 73.84 seconds (0.41 fps)
Filtername Filter mode Time (%) Time (s)
Bicubic parallel 73.07 53.96
Bicubic parallel 57.85 42.72
BM3D parallel 56.85 41.98
KNLMeansCL parreq 53.74 39.68


FMTC

Script evaluation done in 6.83 seconds
Output 30 frames in 63.83 seconds (0.47 fps)
Filtername Filter mode Time (%) Time (s)
resample parallel 64.69 41.29
KNLMeansCL parreq 56.66 36.17
matrix parallel 55.09 35.17
BM3D parallel 55.02 35.12


Considerably better! But still heavy. For 720p videos, resize is way down in the list and not an issue. Any idea what could be causing this performance bottleneck? I posted about the issue here. (https://github.com/vapoursynth/vapoursynth/issues/824)

The only thing that comes to my mind is CPU cache saturation as explained here (https://forum.doom9.org/showthread.php?t=173772).

cretindesalpes
20th November 2021, 10:44
fmtconv r28 (https://forum.doom9.org/showthread.php?t=166504):
bitdepth: Faster void and cluster pattern generation. Larger patterns are allowed.
matrix: Added an alias for "fcc"
primaries: New presets: Free Scale-gamut, DaVinci Wide Gamut, DRAGONcolor, DRAGONcolor2, REDcolor, REDcolor2, REDcolor3, REDcolor4 and REDWideGamutRGB.
primaries: Fixed Sony P22 primaries.
primaries: Removed the deprecated "dcip3" alias for "p3d65".
transfer: Added DaVinci Intermediate, RED Log3G10, REDlog, Cineon and Panalog.
Vapoursynth and Avisynth+ plug-ins are now contained in the same binary file.

asarian
26th January 2022, 16:50
I was wondering whether there's way to convert regular Bluray HD to UHD HDR10, using fmtconv? I saw several attempts here, but in all those examples something went wrong. A clean example would be nice. :)

Blue_MiSfit
18th February 2022, 03:49
I'm struggling a bit with some HDR conversions:

Source:
16 bit full range RGB
PQ, BT. 2020

Target:
12 bit limited range YCbCr 4:4:4
PQ, BT. 2020

(for ProRes XQ encoding)

With this script:


import vapoursynth as vs
core = vs.core

source = core.ffms2.Source("flattened_video.mov")

c = source

c = core.fmtc.matrix(source, mat="2100", bits=16)
c = core.fmtc.bitdepth(c, bits=12)

c.set_output()


I get something that's mostly right, but doesn't fully match the source in Resolve. Suggestions?

cretindesalpes
13th March 2022, 23:47
What kind of difference do you have? How could I reproduce your issue in Resolve?

cretindesalpes
11th April 2022, 17:30
fmtconv r29 (https://forum.doom9.org/showthread.php?t=166504):
Vapoursynth: switched to API v4. Fmtconv now requires Vapoursynth r55 or later, API v3 is not supported anymore.
resample: Fixed degnerated cases with invks causing a crash. Thanks to Dogway for the report.
resample/Avisynth+: fixed frame property writing when only cplaced is defined, thanks to Dogway for the report.
transfer: Added sigmoid curve as a transfer function.
transfer: Fixed the float to integer path.

Blue_MiSfit
27th April 2022, 02:36
Ok, here's a sample frame:

https://drive.google.com/file/d/1vJgzmUQmoAS02TikcwOaar80M-cVSLv3/view?usp=sharing

Again, this is 16 bit full range RGB in HDR with BT. 2020 primaries and ST. 2084 / PQ transfer. Things have evolved a bit since my last post, and now I want to produce two different types of output:

1) Limited range 4:2:0 10 bit (for HDR10 encoding with HEVC)

2) Limited range 4:4:4 12 bit (for ProRes XQ encoding)

Both seem totally fine if I keep full resolution. However, if I downscale (e.g. to 1080p) I'd like to do the scaling in linear light since this is best practice. When I do, a lot of the higher code values are clipped.

Examples: https://imgur.com/a/1K8iKG3

Good (... I think):

import vapoursynth as vs
core = vs.core

a = core.ffms2.Source("HDR_Ramp.tif")

#a = a.fmtc.transfer(transs="pq", transd="linear", fulls=True, fulld=True)
a = a.fmtc.resample(w=1920, h=1080)
#a = a.fmtc.transfer(transs="linear", transd="pq", fulls=True, fulld=True)
a = a.fmtc.matrix(mat="2020", fulls=True, fulld=False)
a = a.fmtc.resample(css="420")
a = a.fmtc.bitdepth(bits=10)

a.set_output()


Bad (clipped):

import vapoursynth as vs
core = vs.core

a = core.ffms2.Source("HDR_Ramp.tif")

a = a.fmtc.transfer(transs="pq", transd="linear", fulls=True, fulld=True)
a = a.fmtc.resample(w=1920, h=1080)
a = a.fmtc.transfer(transs="linear", transd="pq", fulls=True, fulld=True)
a = a.fmtc.matrix(mat="2020", fulls=True, fulld=False)
a = a.fmtc.resample(css="420")
a = a.fmtc.bitdepth(bits=10)

a.set_output()


Am I doing something wrong? The same pattern holds true if I omit the final resample (keeping 4:4:4) and change bitdepth to 12 to make 4:4:4 12 bit for ProRes XQ.

poisondeathray
27th April 2022, 04:48
Bad (clipped):

import vapoursynth as vs
core = vs.core

a = core.ffms2.Source("HDR_Ramp.tif")

a = a.fmtc.transfer(transs="pq", transd="linear", fulls=True, fulld=True)
a = a.fmtc.resample(w=1920, h=1080)
a = a.fmtc.transfer(transs="linear", transd="pq", fulls=True, fulld=True)
a = a.fmtc.matrix(mat="2020", fulls=True, fulld=False)
a = a.fmtc.resample(css="420")
a = a.fmtc.bitdepth(bits=10)

a.set_output()


Am I doing something wrong? The same pattern holds true if I omit the final resample (keeping 4:4:4) and change bitdepth to 12 to make 4:4:4 12 bit for ProRes XQ.

Do calcs in 32bit float
a = core.ffms2.Source...
a = a.fmtc.bitdepth(bits=32)
.
.
.

Blue_MiSfit
27th April 2022, 06:36
Wow, yeah that totally fixed it.

Why is this necessary? I understand how 32 bit float is certainly more precise than 16 bit integer, but I'd have imagined the differences being a whole lot more subtle than this!

On the off-chance, is it possible to reproduce this filter chain in ffmpeg?

poisondeathray
27th April 2022, 18:57
Wow, yeah that totally fixed it.

Why is this necessary? I understand how 32 bit float is certainly more precise than 16 bit integer, but I'd have imagined the differences being a whole lot more subtle than this!




Yes 16bit has higher precision, but 16bit int will still clip to [black,white] or [min,max] , or 0 to 65535 for 16bit code values. "Higher precision" because there are more "steps" described between black to white, but "higher precision" still clips

But the ST2084 PQ to linear transfer function will have values >1 in float ( > 65635 in 16bit) , or "whiter than white"



On the off-chance, is it possible to reproduce this filter chain in ffmpeg?


Yes, using zscale and format=gbrpf32le for float
https://ffmpeg.org/ffmpeg-filters.html#zscale-1


-vf zscale=w=1920:h=1080:transferin=smpte2084:transfer=linear,format=gbrpf32le,zscale=matrix=2020_ncl:transferin=linear:transfer=smpte2084,format=yuv420p10le

Blue_MiSfit
27th April 2022, 20:01
Thanks very much for the ffmpeg filter chain! I'll do some testing with that.

Thanks also for the explanation. After I thought about it a bit more this did indeed occur to me :)

Blue_MiSfit
27th April 2022, 23:12
Hmm ok so I had to add a couple of parameters to

a) Identify the input primaries as bt2020

and

b) Specify limited range output


This worked great for a TIF input. The output matches the source in Resolve perfectly:


ffmpeg -i HDR_Ramp.tif -vf zscale=w=1920:h=1080:pin=bt2020:p=bt2020:tin=smpte2084:t=linear,format=gbrpf32le,zscale=m=2020_ncl:tin=linear:t=smpte2084:r=limited,format=yuv420p10le -c:v libx265 -crf 10 reference2.mp4


However, as soon as I swapped over to using the IMF MXF J2K wrapped version of this (same image, just a lossless compressed version of the full range 16 bit RGB TIF), I get the same clipped whites:


ffmpeg -f imf -i .\CPL_FOX-TPS-1MIN-HDR10-ML7_20181105_OV.xml -map 0:v -vf zscale=w=1920:h=1080:pin=bt2020:p=bt2020:tin=smpte2084:t=linear,format=gbrpf32le,zscale=m=2020_ncl:tin=linear:t=smpte2084:r=limited,format=yuv420p10le -c:v libx265 -crf 10 -preset superfast -x265-params keyint=24 -t 1 scale_linear_08.mp4


That clipped white is visible both in MPC-HC and in Resolve.

Both formats seem to insert the same auto scaler from rgb48le to gbrp16le:


[auto_scale_0 @ 00000157ac51b040] picking gbrp16le out of 48 ref:rgb48le alpha:0
...
[auto_scale_0 @ 00000157ac51b040] w:3840 h:2160 fmt:rgb48le sar:0/1 -> w:3840 h:2160 fmt:gbrp16le sar:0/1 flags:0x0


I tried disabling auto conversion and explicitly adding format=gbrp16le to the head of the filter graph and that errors out:


[format @ 000001f0f4c5ea00] Setting 'pix_fmts' to value 'yuv420p|yuvj420p|yuv422p|yuvj422p|yuv444p|yuvj444p|gbrp|yuv420p10le|yuv422p10le|yuv444p10le|gbrp10le|yuv420p12le|yuv422p12le|yuv444p12le|gbrp12le|gray|gray10le|gray12le'
The filters 'graph 0 input from stream 0:0' and 'Parsed_format_0' do not have a common format and automatic conversion is disabled.
Error reinitializing filters!