Log in

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


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

jose1711
25th July 2015, 12:40
jose1711: I fixed something in the git repository, but at this point I’m not sure it fixes everything. Please check it and tell me if it works better, or differently.

thank you, i assume i was supposed to recompile vapoursynth-plugin-fmtconv-git. unfortunately, there was no change or improvement. this is the backtrace:

Program received signal SIGABRT, Aborted.
0xb7fdbbc8 in __kernel_vsyscall ()
(gdb) bt
#0 0xb7fdbbc8 in __kernel_vsyscall ()
#1 0xb7c67d66 in raise () from /usr/lib/libc.so.6
#2 0xb7c69397 in abort () from /usr/lib/libc.so.6
#3 0xb7c60e07 in __assert_fail_base () from /usr/lib/libc.so.6
#4 0xb7c60e8b in __assert_fail () from /usr/lib/libc.so.6
#5 0xb720b8f9 in conc::LockFreeStack<fmtcl::ErrDifBuf*>::push(conc::LockFreeCell<fmtcl::ErrDifBuf*>&) ()
from /usr/lib/vapoursynth/libfmtconv.so
#6 0xb720bade in conc::CellPool<fmtcl::ErrDifBuf*>::allocate_zone(int, unsigned int, conc::AtomicPtr<conc::LockFreeCell<fmtcl::ErrDifBuf*> >&) () from /usr/lib/vapoursynth/libfmtconv.so
#7 0xb720bc4a in conc::CellPool<fmtcl::ErrDifBuf*>::expand_to(unsigned int) () from /usr/lib/vapoursynth/libfmtconv.so
#8 0xb715aa4f in fmtc::Bitdepth::Bitdepth(VSMap const&, VSMap&, void*, VSCore&, VSAPI const&) () from /usr/lib/vapoursynth/libfmtconv.so
#9 0xb714bcf4 in vsutl::Redirect<fmtc::Bitdepth>::create(VSMap const*, VSMap*, void*, VSCore*, VSAPI const*) ()
from /usr/lib/vapoursynth/libfmtconv.so
#10 0xb754734a in VSPlugin::invoke(std::string const&, VSMap const&) () from /usr/lib/libvapoursynth.so
#11 0xb7534bb2 in invoke(VSPlugin*, char const*, VSMap const*) () from /usr/lib/libvapoursynth.so
#12 0xb7605ebe in __pyx_pw_11vapoursynth_8Function_3__call__ () from /usr/lib/python3.4/site-packages/vapoursynth.so
#13 0xb79dc973 in PyObject_Call (func=0xb2aa8874, arg=0xb76ed02c, kw=0xb7645cec) at Objects/abstract.c:2040
#14 0xb7a95905 in do_call (nk=<optimized out>, na=<optimized out>, pp_stack=<optimized out>, func=<optimized out>) at Python/ceval.c:4466
#15 call_function (oparg=<optimized out>, pp_stack=<optimized out>) at Python/ceval.c:4264
#16 PyEval_EvalFrameEx (f=0xb75981cc, throwflag=0) at Python/ceval.c:2838
#17 0xb7a98f9b in PyEval_EvalCodeEx (_co=0xb2a95070, globals=0xb73a9aac, locals=0x0, args=0x82b3ab4, argcount=4, kws=0x82b3ac4, kwcount=0,
defs=0xb2aa8790, defcount=3, kwdefs=0x0, closure=0x0) at Python/ceval.c:3588
#18 0xb7a95f8e in fast_function (nk=<optimized out>, na=<optimized out>, n=<optimized out>, pp_stack=<optimized out>, func=<optimized out>)
at Python/ceval.c:4344
#19 call_function (oparg=<optimized out>, pp_stack=<optimized out>) at Python/ceval.c:4262
#20 PyEval_EvalFrameEx (f=0x82b365c, throwflag=0) at Python/ceval.c:2838
#21 0xb7a98f9b in PyEval_EvalCodeEx (_co=0xb2a98160, globals=0xb73a9aac, locals=0x0, args=0xb7675d6c, argcount=1, kws=0xb7675d70, kwcount=2,
defs=0xb73b0188, defcount=78, kwdefs=0x0, closure=0x0) at Python/ceval.c:3588
#22 0xb7a95f8e in fast_function (nk=<optimized out>, na=<optimized out>, n=<optimized out>, pp_stack=<optimized out>, func=<optimized out>)
at Python/ceval.c:4344
#23 call_function (oparg=<optimized out>, pp_stack=<optimized out>) at Python/ceval.c:4262
#24 PyEval_EvalFrameEx (f=0xb7675c2c, throwflag=0) at Python/ceval.c:2838
#25 0xb7a98f9b in PyEval_EvalCodeEx (_co=0xb76596b0, globals=0xb7687ecc, locals=0xb7687ecc, args=0x0, argcount=0, kws=0x0, kwcount=0,
defs=0x0, defcount=0, kwdefs=0x0, closure=0x0) at Python/ceval.c:3588
#26 0xb7a99070 in PyEval_EvalCode (co=0xb76596b0, globals=0xb7687ecc, locals=0xb7687ecc) at Python/ceval.c:775
#27 0xb75ee9a4 in vpy_evaluateScript () from /usr/lib/python3.4/site-packages/vapoursynth.so
#28 0xb75f0be3 in vpy_evaluateFile () from /usr/lib/python3.4/site-packages/vapoursynth.so
#29 0xb7f8659c in vsscript_evaluateFile () from /usr/lib/libvapoursynth-script.so.0
#30 0x08049fe2 in main ()

cretindesalpes
25th July 2015, 18:13
jose1711: Thanks, the stack trace was really enlightening. I fixed a few other things. Please give it another try now.
Edit: the “official” git I update is here (https://github.com/EleonoreMizo/fmtconv). I don’t know which copy you were checking.

jose1711
25th July 2015, 18:43
jose1711: Thanks, the stack trace was really enlightening. I fixed a few other things. Please give it another try now.
Edit: the “official” git I update is here (https://github.com/EleonoreMizo/fmtconv). I don’t know which copy you were checking.

thank you, i am using the correct git source then. anyway, still the same error but the stacktrace changed a little:

Program received signal SIGABRT, Aborted.
0xb7fdbbc8 in __kernel_vsyscall ()
(gdb) bt
#0 0xb7fdbbc8 in __kernel_vsyscall ()
#1 0xb7c67d66 in raise () from /usr/lib/libc.so.6
#2 0xb7c69397 in abort () from /usr/lib/libc.so.6
#3 0xb7c60e07 in __assert_fail_base () from /usr/lib/libc.so.6
#4 0xb7c60e8b in __assert_fail () from /usr/lib/libc.so.6
#5 0xb71493b7 in conc::LockFreeStack<fmtcl::ErrDifBuf*>::push(conc::LockFreeCell<fmtcl::ErrDifBuf*>&) ()
from /usr/lib/vapoursynth/libfmtconv.so
#6 0xb7209c54 in conc::CellPool<fmtcl::ErrDifBuf*>::allocate_zone(int, unsigned int, conc::AtomicPtr<conc::LockFreeCell<fmtcl::ErrDifBuf*> >&) () from /usr/lib/vapoursynth/libfmtconv.so
#7 0xb7209db2 in conc::CellPool<fmtcl::ErrDifBuf*>::expand_to(unsigned int) () from /usr/lib/vapoursynth/libfmtconv.so
#8 0xb7159799 in fmtc::Bitdepth::Bitdepth(VSMap const&, VSMap&, void*, VSCore&, VSAPI const&) () from /usr/lib/vapoursynth/libfmtconv.so
#9 0xb7149ea4 in vsutl::Redirect<fmtc::Bitdepth>::create(VSMap const*, VSMap*, void*, VSCore*, VSAPI const*) ()
from /usr/lib/vapoursynth/libfmtconv.so
#10 0xb754734a in VSPlugin::invoke(std::string const&, VSMap const&) () from /usr/lib/libvapoursynth.so
#11 0xb7534bb2 in invoke(VSPlugin*, char const*, VSMap const*) () from /usr/lib/libvapoursynth.so
#12 0xb7605ebe in __pyx_pw_11vapoursynth_8Function_3__call__ () from /usr/lib/python3.4/site-packages/vapoursynth.so
#13 0xb79dc973 in PyObject_Call (func=0xb2aa3874, arg=0xb76ed02c, kw=0xb7645cec) at Objects/abstract.c:2040
#14 0xb7a95905 in do_call (nk=<optimized out>, na=<optimized out>, pp_stack=<optimized out>, func=<optimized out>) at Python/ceval.c:4466
#15 call_function (oparg=<optimized out>, pp_stack=<optimized out>) at Python/ceval.c:4264
#16 PyEval_EvalFrameEx (f=0xb75981cc, throwflag=0) at Python/ceval.c:2838
#17 0xb7a98f9b in PyEval_EvalCodeEx (_co=0xb2a90070, globals=0xb73a9aac, locals=0x0, args=0x82b4374, argcount=4, kws=0x82b4384, kwcount=0,
defs=0xb2aa3790, defcount=3, kwdefs=0x0, closure=0x0) at Python/ceval.c:3588
#18 0xb7a95f8e in fast_function (nk=<optimized out>, na=<optimized out>, n=<optimized out>, pp_stack=<optimized out>, func=<optimized out>)
at Python/ceval.c:4344
#19 call_function (oparg=<optimized out>, pp_stack=<optimized out>) at Python/ceval.c:4262
#20 PyEval_EvalFrameEx (f=0x82b3f1c, throwflag=0) at Python/ceval.c:2838
#21 0xb7a98f9b in PyEval_EvalCodeEx (_co=0xb2a93160, globals=0xb73a9aac, locals=0x0, args=0xb7675d6c, argcount=1, kws=0xb7675d70, kwcount=2,
defs=0xb73b1188, defcount=78, kwdefs=0x0, closure=0x0) at Python/ceval.c:3588
#22 0xb7a95f8e in fast_function (nk=<optimized out>, na=<optimized out>, n=<optimized out>, pp_stack=<optimized out>, func=<optimized out>)
at Python/ceval.c:4344
#23 call_function (oparg=<optimized out>, pp_stack=<optimized out>) at Python/ceval.c:4262
#24 PyEval_EvalFrameEx (f=0xb7675c2c, throwflag=0) at Python/ceval.c:2838
#25 0xb7a98f9b in PyEval_EvalCodeEx (_co=0xb76596b0, globals=0xb7687ecc, locals=0xb7687ecc, args=0x0, argcount=0, kws=0x0, kwcount=0,
defs=0x0, defcount=0, kwdefs=0x0, closure=0x0) at Python/ceval.c:3588
#26 0xb7a99070 in PyEval_EvalCode (co=0xb76596b0, globals=0xb7687ecc, locals=0xb7687ecc) at Python/ceval.c:775
#27 0xb75ee9a4 in vpy_evaluateScript () from /usr/lib/python3.4/site-packages/vapoursynth.so
#28 0xb75f0be3 in vpy_evaluateFile () from /usr/lib/python3.4/site-packages/vapoursynth.so
#29 0xb7f8659c in vsscript_evaluateFile () from /usr/lib/libvapoursynth-script.so.0
#30 0x08049fe2 in main ()

cretindesalpes
26th July 2015, 09:30
jose1711: I’m not sure what’s wrong now. I did another modification. If it still doesn’t work, could you do the following?
– Add the -fdump-class-hierarchy option for the compilation. Modify the AM_CXXFLAGS line at the beginning of makefile.am for example.
– Compile fmtconv
– Locate the file beginnig with Bitdepth.cpp and ending with the .class extension. It should be in the same directory as the object files.
– Send me the content (it’s a text file) via a pastebin or something, or compressed on any file host if it’s too big.

jose1711
26th July 2015, 09:56
jose1711: I’m not sure what’s wrong now. I did another modification. If it still doesn’t work, could you do the following?
– Add the -fdump-class-hierarchy option for the compilation. Modify the AM_CXXFLAGS line at the beginning of makefile.am for example.
– Compile fmtconv
– Locate the file beginnig with Bitdepth.cpp and ending with the .class extension. It should be in the same directory as the object files.
– Send me the content (it’s a text file) via a pastebin or something, or compressed on any file host if it’s too big.

different error now:

Python exception: No attribute with the name scd exists. Did you mistype a plugin namespace?
Traceback (most recent call last):
File "src/cython/vapoursynth.pyx", line 1469, in vapoursynth.vpy_evaluateScript (src/cython/vapoursynth.c:24755)
File "test.vpy", line 22, in <module>
ret = haf.QTGMC( ret, Preset='Slow', TFF=True)
File "/usr/lib/python3.4/site-packages/havsfunc.py", line 878, in QTGMC
if TR0 > 0: ts1 = TemporalSoften(bobbed, 1, 255<<shift, CMts<<shift, 28<<shift, 2) # 0.00 0.33 0.33 0.33 0.00
File "/usr/lib/python3.4/site-packages/havsfunc.py", line 3688, in TemporalSoften
clip = set_scenechange(clip, scenechange)
File "/usr/lib/python3.4/site-packages/havsfunc.py", line 3710, in set_scenechange
sc = core.scd.Detect(sc, thresh)
File "src/cython/vapoursynth.pyx", line 1090, in vapoursynth.Core.__getattr__ (src/cython/vapoursynth.c:18950)
AttributeError: No attribute with the name scd exists. Did you mistype a plugin namespace?

Failed to recognize file format.

cretindesalpes
26th July 2015, 10:37
Ah. It looks like it’s not an fmtconv error anymore. Vapoursynth is looking for scd.Detect. Check that you have the scene change detection plug-in (http://forum.doom9.org/showthread.php?t=166769) installed.

jose1711
26th July 2015, 23:18
Ah. It looks like it’s not an fmtconv error anymore. Vapoursynth is looking for scd.Detect. Check that you have the scene change detection plug-in (http://forum.doom9.org/showthread.php?t=166769) installed.

wow, thank you so much. after compiling scene change detection plugin everything just works!

jose1711
5th August 2015, 20:50
and i just came across another problem. while most of the videos work i just stumbled upon a clip that throws a segmentation fault. gdb:

Using host libthread_db library "/usr/lib/libthread_db.so.1".
[New Thread 0xb1001b40 (LWP 11289)]
[New Thread 0xb1802b40 (LWP 11288)]
[New Thread 0xb29b3b40 (LWP 11287)]
[New Thread 0xb2003b40 (LWP 11286)]

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb1001b40 (LWP 11289)]
0xb7d65740 in __memcpy_ssse3 () from /usr/lib/libc.so.6
(gdb) bt
#0 0xb7d65740 in __memcpy_ssse3 () from /usr/lib/libc.so.6
#1 0xb70deeb9 in vs_bitblt(void*, int, void const*, int, int, int) () from /usr/lib/libffms2.so.4.0.0
#2 0xb70e08e6 in VSVideoSource::OutputFrame(FFMS_Frame const*, VSFrameRef*, VSAPI const*) ()
from /usr/lib/libffms2.so.4.0.0
#3 0xb70dfa14 in VSVideoSource::GetFrame(int, int, void**, void**, VSFrameContext*, VSCore*, VSAPI const*) ()
from /usr/lib/libffms2.so.4.0.0
#4 0xb7540d78 in VSNode::getFrameInternal(int, int, VSFrameContext&) () from /usr/lib/libvapoursynth.so
#5 0xb754f72a in VSThreadPool::runTasks(VSThreadPool*, std::atomic<bool>&) () from /usr/lib/libvapoursynth.so
#6 0xb75506d0 in std::thread::_Impl<std::_Bind_simple<void (*(VSThreadPool*, std::reference_wrapper<std::atomic<bool> >))(VSThreadPool*, std::atomic<bool>&)> >::_M_run() () from /usr/lib/libvapoursynth.so
#7 0xb7eadaee in std::(anonymous namespace)::execute_native_thread_routine (__p=0xb2d00544)
at /build/gcc/src/gcc-5.2.0/libstdc++-v3/src/c++11/thread.cc:84
#8 0xb793f1c3 in start_thread () from /usr/lib/libpthread.so.0
#9 0xb7d24e8e in clone () from /usr/lib/libc.so.6


any idea? much obliged, jose

cretindesalpes
6th August 2015, 20:34
I only see Vapoursynth code here. You can post this in the main Vapoursynth thread.

cretindesalpes
23rd September 2015, 20:54
No idea why. What were the changes between test1 and test2?

Myrsloik
23rd September 2015, 20:55
Try other filters and you'll see it's probably a general speed degradation. It's because I've had to temporarily stop using tcmalloc. It will be back some day soon probably. Once it has the weird VS2015 issues fixed.

an3k
16th January 2016, 10:35
Here is another plug-in for Vapoursynth.

>>> fmtconv-r17.zip <<< (http://ldesoras.free.fr/src/vs/fmtconv-r17.zip)

Thank You :)

I just noticed the autogen.sh in the zip-file doesn't has chmod u+x and is additionally in DOS format, thus Linux cannot execute it, only after manual chmod and conversion into "Linux" format. The file in the git repo is fine. However both libraries are installed into $PREFIX/lib/ instead of $PREFIX/lib/vapoursynth/

jackoneill
16th January 2016, 12:55
Thank You :)

I just noticed the autogen.sh in the zip-file doesn't has chmod u+x and is additionally in DOS format, thus Linux cannot execute it, only after manual chmod and conversion into "Linux" format. The file in the git repo is fine. However both libraries are installed into $PREFIX/lib/ instead of $PREFIX/lib/vapoursynth/

Use the --libdir parameter.

mawen1250
22nd January 2016, 16:38
http://i683.photobucket.com/albums/vv197/mawen1250/Madoka_01_test.vpy%20-%200_zps6opssy2k.jpg
I encountered a really weird bug that might relate to fmtc.bitdepth.
In fact it was someone reporting bug about mvf.BM3D then did I go to figure out what's going wrong. After testing for nearly a whole day, finally I found a minimum script to reproduce this issue.

video example and the test script (https://mega.nz/#!xA5BVIrL!zZEjn5KZNoN5WPWIM2WPiON5WtAQesCjH3SOv7XJk4o)

environment:
CPU is Ivy Bridge (no AVX2)
Windows 7
VS R30 64bit
fmtconv-r17
BM3D-r4
L-SMASH-Works-r859-20151231

import vapoursynth as vs

core = vs.get_core(threads=0)
core.max_cache_size = 8000

src_path = r'Madoka_01.mkv'
src = core.lsmas.LWLibavSource(src_path, threads=1)
src = core.fmtc.bitdepth(src, bits=32) # Comment this line will not reproduce the issue
src = core.fmtc.resample(src, kernel='bicubic', a1=0, a2=0.5, css='444') # Catmull-Rom can reproduce the issue
#src = core.fmtc.resample(src, kernel='spline', css='444') # Spline can reproduce the issue
#src = core.fmtc.resample(src, kernel='spline36', css='444') # and some other kernels will not
src = core.fmtc.matrix(src, mat='709', col_fam=vs.RGB)

radius = 1
param = {'sigma':[3,3,3], 'radius':radius, 'profile':'fast', 'matrix':100}
sample = vs.FLOAT # vs.INTEGER will not reproduce the issue
src = core.bm3d.RGB2OPP(src, sample)
flt = core.bm3d.VBasic(src, **param).bm3d.VAggregate(radius, sample)
flt = core.bm3d.VFinal(src, flt, **param).bm3d.VAggregate(radius, vs.FLOAT) # vs.INTEGER will not reproduce the issue
flt = core.bm3d.OPP2RGB(flt, vs.FLOAT) # vs.INTEGER will not reproduce the issue

final = flt
#final = core.fmtc.matrix(final, mat='709', col_fam=vs.YUV) # optionally, uncomment this line will also reproduce the issue
final = core.fmtc.bitdepth(final, bits=8, dmode=3) # with float input, integer output and dmode=3~7, the output is corrupt

out = final # src and flt are OK
out[111:].set_output()
From what I've seen the corrupt result is produced by the last fmtc.bitdepth, and only with float input+integer output+dmode=3~7.

The weird thing is that only under specific circumstance will this issue be reproduced. With a tiny change in the script (e.g. different resample kernel, vs.FLOAT->vs.INTEGER, remove the BM3D part, change dmode to 0~2) the result will be correct. Different environment may also affect it but I'm not sure.
More specific information is written in the comments.
I've tried converting source to lossless format and the result is the same, thus it should not be a problem relates to source filter.

mawen1250
23rd January 2016, 03:05
After more testing, I found out that it's related to the final estimate of BM3D, which can produce very large or even NaN/INF results, and break the error diffusion algorithm of fmtc.bitdepth.

Adding either one like these before fmtc.bitdepth I'll get different black areas:
final = core.std.Expr(final, 'x -4294967296 max')
final = core.std.Expr(final, 'x -16777216 max')
final = core.std.Expr(final, 'x -65536 max')

Anyway, I've fixed this issue in BM3D-r5, but I'm not sure if it's a problem for fmtc.bitdepth.

speedyrazor
7th February 2016, 08:52
Is there a way to reverse the filed order is VapourSynth?

MonoS
7th February 2016, 12:56
Is there a way to reverse the filed order is VapourSynth?

If i've undestood what you're asking, it should be

reversed = core.std.SelectEvery(InterleavedField, 2, [1,0])

speedyrazor
7th February 2016, 13:42
If i've undestood what you're asking, it should be

reversed = core.std.SelectEvery(InterleavedField, 2, [1,0])


Hi, thanks for the suggestion, but this is not what I was after.
Lets say I have some footage which is top field first and I want to convert it to bottom field first. How would I do that in VapoutSynth please?

jackoneill
7th February 2016, 14:29
Hi, thanks for the suggestion, but this is not what I was after.
Lets say I have some footage which is top field first and I want to convert it to bottom field first. How would I do that in VapoutSynth please?

Probably by deinterlacing it and then interlacing it again. If you just take the fields as they are and display them backwards, you'll get jerky motion. Or if you put the top field at the bottom, and the bottom field at the top, it's going to look wrong. Therefore, slow processing (QTGMC) is the way to go.

speedyrazor
7th February 2016, 15:02
Probably by deinterlacing it and then interlacing it again. If you just take the fields as they are and display them backwards, you'll get jerky motion. Or if you put the top field at the bottom, and the bottom field at the top, it's going to look wrong. Therefore, slow processing (QTGMC) is the way to go.

What I am looking for is the equivalent to ffmpeg's filter:

-vf phase=b

Just tested and this works correctly, any equivalent in VapourSynth?

Myrsloik
7th February 2016, 15:22
Simply delete the first field, same as in avisynth as usual...


core.std.DoubleWeave(clip.std.SeparateFields(tff=whatevertheinputis)[1:])[::2]


Untested but it's the general idea at least.

speedyrazor
7th February 2016, 15:37
Simply delete the first field, same as in avisynth as usual...


core.std.DoubleWeave(clip.std.SeparateFields(tff=whatevertheinputis)[1:])[::2]


Untested but it's the general idea at least.
I am using it like this:

ret = core.std.DoubleWeave(ret.std.SeparateFields(tff=True)[1:])[::2]

But am getting the error:

vapoursynth.Error: DoubleWeave: argument tff is required

stax76
29th February 2016, 19:06
can fmtconv convert to the same format used in the code below?

clip.resize.Bicubic(format=vs.COMPATBGR32)

cretindesalpes
29th February 2016, 20:06
fmtconv doesn’t output to COMPAT* formats. However you can convert to RGB24 with fmtconv and output to a COMPAT format with the builtin VS functions.

cretindesalpes
8th March 2016, 21:54
fmtconv r18 (http://forum.doom9.org/showthread.php?t=166504):
Added the primaries function to convert between gamuts.
The “full” range is now closer to what is specified in the standards.
A recent Vapoursynth is now required because API headers were updated to version 3.1.4.
transfer: added the Adobe RGB and ProPhoto / ROMM curves.

benmanw
16th March 2016, 02:44
just forward J1Man's request from GitHub.

https://github.com/EleonoreMizo/fmtconv/issues/7


Feature Request, High Dynamic Range Video Conversion #7


J1Man commented 2 days ago

Dear Laurent,

I would like to request a feature. Can you add the capability to do UHD compliant Standard Dynamic Range (SDR) to High Dynamic Range (HDR) conversion (and also the opposite HDR to SDR conversion) to Fmtconv plugin?

I also sent you a long email with all the technical research that I could find. In summary, the required new features are listed below.

1) A custom HDR-1000 system compatible SMPTE ST 2084 transfer function that maps to "0 cd/m2 to 1000 cd/m2" luminance range. (Note: current 2084 function included in Fmtconv maps to 0 to 10,000 cd/m2)

2) Add DCI-P3 color primaries as a preset to primaries function. This is not very urgent since "gd=[0.265, 0.69], bd=[0.15, 0.06], rd=[0.68, 0.32], wd=[0.3127, 0.329]" command can be used to manually define DCI-P3 primaries in fmtconv r18.

Once these two new features are implemented, the workflow in Fmtconv will be the following for SDR to HDR conversion.
-Convert source video to "Linear light RGB 4:4:4"
-If necessary, change primaries to one of the HDR compatible primaries (BT709, BT2020, or DCI-P3)
-Convert transfer function from Linear to the custom SMPTE ST 2084 that maps to "0 to 1000 cd/m2" luminance range
-Resample to YUV 4:2:0 10 bit using BT2020 or BT709 matrix (which ever matrix is appropriate)
-Send YUV to x265 encoder. Specify the 2084 transfer fuction, appropriate matrix and appropriate primaries in the x265 command line.

The opposite steps can be used to convert HDR to SDR.

Please let me know what you think.

Best Regards

benmanw
16th March 2016, 14:54
One more message from J1Man. He won't be able to post on Doom9 until he has been registered for 5 days (until 3/19/2016).

I attached the source code patch zip file for fmtconv r18 that modifies SMPTE-ST-2084 function to "0 cd/m2 to 1000 cd/m2" luminance range and adds the "dci-p3" preset to primaries function. I also attached a zip file that contains the complete fmtconv r18 source code that is already patched. I would appreciate if somebody with Visual Studio can compile the 64bit fmtconv.dll for Windows 7. No matter how hard I tried in the last 2 days, I could not compile fmtconv.dll on Windows 7 by using MSYS2 and mingw64.

I saw that fmtconv uses the "Dolby Labs recommended version of SMPTE-ST-2084 function" specified on page 17/58 of the following PDF document.

http://www.mediaandbroadcast.bt.com/wp-content/uploads/D2936-UHDTV-final.pdf

I think that was good choice because Dolby Labs version is designed for easy scalability between luminance ranges. Upper bound of the range can be changed by dividing or multiplying the right hand side of the function shown on page 17/58 of the PDF document. That's how I modified lines 78 and 83 of the TransOp2084.cpp file.

I added "dci-p3" primaries preset after line 356 of Primaries.cpp function.

fmtconv-r18-HDR1000-patch-only.zip (https://github.com/EleonoreMizo/fmtconv/files/175990/fmtconv-r18-HDR1000-patch-only.zip)
fmtconv-r18-patched-with-HDR1000features.zip (https://github.com/EleonoreMizo/fmtconv/files/175991/fmtconv-r18-patched-with-HDR1000features.zip)

cretindesalpes
17th March 2016, 13:01
J1Man:

fmtconv does not need any modification to support 1000 cd/m² as HDR peak white. If your 100% light value represents 1000 cd/m², you can divide the components by 10 so they fit in a scale where 100% means 10000 cd/m². For this, reduce the contrast directly in the transfer command by setting cont=0.1.
clip = core.fmtc.transfer (clip, transs="linear", transd="2084", cont=1000.0/10000.0)
BTW in your email you showed me a Vapoursynth code snippet where the transfer functions had fulls=False and fulld=False. This is not right because the R’G’B’ input/output for matrix is full by default.

I added the DCI-P3 colorspace to fmtconv and will release an update in the next few days.

cretindesalpes
19th March 2016, 12:13
fmtconv r19 (http://forum.doom9.org/showthread.php?t=166504):
primaries: refined the values for the Adobe Wide gamut and BT.2020 primaries.
primaries: added DCI-P3, ACES AP0/AP1, S-Gamut, S-Gamut3.Cine, ALEXA and V-Gamut presets.
transfer: added ACEScc, ERIMM, S-Log2, S-Log3 and V-Log curves.

J1Man
19th March 2016, 15:24
Cretindesalpes:

Thanks for your reply and thanks for adding DCI-P3 to the primaries. I will use cont option, as you suggested, to change the luminance range. I will test the videos on my UHD tv and let you know if there are any HDR related issues.


Benmanw:

Thanks for forwarding my messages to the doom forum.

J1Man
20th March 2016, 17:48
Cretindesalpes:

You stated in your message that the RGB input/output for matrix is "full range" by default. I ran some tests with Big Buck Bunny clip (link below).
http://distribution.bbb3d.renderfarming.net/video/mp4/bbb_sunflower_1080p_60fps_normal.mp4

When I use the transfer function (even with only the input clip option), I can not get accurate colors from the output clip unless I manually define clip range conversion from "limited to full" or "limited to limited" either in transfer or matrix functions. I wrote the test scripts below along with their results. Let me know if this is an indication of a bug in fmtconv.

Script 1 (Input and Output look different. Output colors are slightly dull.)
clip = core.fmtc.resample (clip, css="444")
clip = core.fmtc.matrix (clip, mat="709")
clip = core.fmtc.transfer (clip)
clip = core.fmtc.matrix (clip, mat="709")
clip = core.fmtc.resample (clip, css="420")
clip = core.fmtc.bitdepth (clip, bits=10)


Script 2 (Input and Output look different. Output colors are slightly dull.)
clip = core.fmtc.resample (clip, css="444")
clip = core.fmtc.matrix (clip, mat="709")
clip = core.fmtc.transfer (clip, fulls=True, fulld=True)
clip = core.fmtc.matrix (clip, mat="709")
clip = core.fmtc.resample (clip, css="420")
clip = core.fmtc.bitdepth (clip, bits=10)



Script 3 (Input and Output look identical.)
clip = core.fmtc.resample (clip, css="444")
clip = core.fmtc.matrix (clip, mat="709")
clip = core.fmtc.transfer (clip, fulls=False, fulld=False)
clip = core.fmtc.matrix (clip, mat="709")
clip = core.fmtc.resample (clip, css="420")
clip = core.fmtc.bitdepth (clip, bits=10)


Script 4 (Input and Output look identical.)
clip = core.fmtc.resample (clip, css="444")
clip = core.fmtc.matrix (clip, mat="709")
clip = core.fmtc.transfer (clip, fulls=False, fulld=True)
clip = core.fmtc.matrix (clip, mat="709")
clip = core.fmtc.resample (clip, css="420")
clip = core.fmtc.bitdepth (clip, bits=10)



Script 5 (Input and Output look identical.)
clip = core.fmtc.resample (clip, css="444")
clip = core.fmtc.matrix (clip, mat="709",fulls=False, fulld=True)
clip = core.fmtc.transfer (clip)
clip = core.fmtc.matrix (clip, mat="709", fulls=True, fulld=False)
clip = core.fmtc.resample (clip, css="420")
clip = core.fmtc.bitdepth (clip, bits=10)

cretindesalpes
21st March 2016, 09:50
Only Script 4 gave me a different output with a regular TV-range video sample, which was expected. However the Big Buck Bunny clip you linked seems to be BT.601 and not BT.709 (the stream is not even tagged and some red colors are clipped when using a 709 matrix), which would explain why converting back and forth to R’G’B’ generates some differences.

J1Man
21st March 2016, 20:45
Thanks for getting back to me.

How did you understand that the original clip uses BT601 matrix? Does it use BT601-525 primaries? I got BT709 matrix and primaries from MadVR's OSD but it seems like MadVR automatically assumes BT709 matrix/primaries for all HD size clips. Does fmtconv display the original matrix/primaries/transfer_function info for the clip? Or did you use another program?

In order to prevent color clipping, is it safe to use BT2020 matrix for back and forth conversion between RGB and YUV (without primaries gamut conversion), when I am not sure about the source matrix?


I am still getting some unexpected behavior in the output even with BT601 matrix. I generated screenshots for the unprocessed original clip, output for scripts 1-5 with BT601 matrix and output for scripts 1-5 with BT709 matrix. All screenshots are from the same frame that is located approximately at time code 06:22/10:35 of the clip. I used 64bit fmtconv r19, 64bit ffms2 ver 2.20 and 64bit vapoursynth r31 via 64bit Staxrip 1.3.2 to generate these screenshots. The link for the screenshots zip file is shown below:

https://github.com/EleonoreMizo/fmtconv/files/182947/BigBuckBunny_FmtConv_RangeTestScripts_Screenshots.zip

I noticed that Script 4 gives different output in my tests as well. Color of the Bunny is incorrect in the screenshots for Script 4 both with BT601 and BT709 matrices. There is a very small difference in output of Script 4 that I did not notice before I posted my previous message.

When you look at my screenshots, you will see that Scripts 1, 2 and 4 with BT601 matrix give different outputs that are not identical to input. Only Scripts 3 and 5 with BT601 matrix give outputs that are identical to input. (Note: In this particular test frame, BT601 and BT709 did not make a noticeable difference in the screenshots for any of the scripts. That's why it is very difficult to visually notice the incorrect usage of BT709 matrix by looking at the screenshots of this test frame.)

Were you able to replicate my results by using Scripts 1 and 2 with BT601 matrix on the Big Buck Bunny clip near the same frame/scene that I used in my screenshots? What might be the reason for input/output differences caused by Scripts 1 and 2? The results might not be noticeable at some other scenes of the same clip.



Is this Big Buck Bunny clip limited range based on your analysis? Is there a way to tell if a source clip is full range or limited range? MediaInfo does not always show this information. I probably should have asked this question before doing all the work for generating screenshots.

kolak
21st March 2016, 21:21
Cretindesalpes:

You stated in your message that the RGB input/output for matrix is "full range" by default. I ran some tests with Big Buck Bunny clip (link below).
http://distribution.bbb3d.renderfarming.net/video/mp4/bbb_sunflower_1080p_60fps_normal.mp4

When I use the transfer function (even with only the input clip option), I can not get accurate colors from the output clip unless I manually define clip range conversion from "limited to full" or "limited to limited" either in transfer or matrix functions. I wrote the test scripts below along with their results. Let me know if this is an indication of a bug in fmtconv.

Script 1 (Input and Output look different. Output colors are slightly dull.)
clip = core.fmtc.resample (clip, css="444")
clip = core.fmtc.matrix (clip, mat="709")
clip = core.fmtc.transfer (clip)
clip = core.fmtc.matrix (clip, mat="709")
clip = core.fmtc.resample (clip, css="420")
clip = core.fmtc.bitdepth (clip, bits=10)


Script 2 (Input and Output look different. Output colors are slightly dull.)
clip = core.fmtc.resample (clip, css="444")
clip = core.fmtc.matrix (clip, mat="709")
clip = core.fmtc.transfer (clip, fulls=True, fulld=True)
clip = core.fmtc.matrix (clip, mat="709")
clip = core.fmtc.resample (clip, css="420")
clip = core.fmtc.bitdepth (clip, bits=10)



Script 3 (Input and Output look identical.)
clip = core.fmtc.resample (clip, css="444")
clip = core.fmtc.matrix (clip, mat="709")
clip = core.fmtc.transfer (clip, fulls=False, fulld=False)
clip = core.fmtc.matrix (clip, mat="709")
clip = core.fmtc.resample (clip, css="420")
clip = core.fmtc.bitdepth (clip, bits=10)


Script 4 (Input and Output look identical.)
clip = core.fmtc.resample (clip, css="444")
clip = core.fmtc.matrix (clip, mat="709")
clip = core.fmtc.transfer (clip, fulls=False, fulld=True)
clip = core.fmtc.matrix (clip, mat="709")
clip = core.fmtc.resample (clip, css="420")
clip = core.fmtc.bitdepth (clip, bits=10)



Script 5 (Input and Output look identical.)
clip = core.fmtc.resample (clip, css="444")
clip = core.fmtc.matrix (clip, mat="709",fulls=False, fulld=True)
clip = core.fmtc.transfer (clip)
clip = core.fmtc.matrix (clip, mat="709", fulls=True, fulld=False)
clip = core.fmtc.resample (clip, css="420")
clip = core.fmtc.bitdepth (clip, bits=10)

Your source file has no full range flag, so by the default nothing will expect full range.

These files are full range and have proper flagging, so you can try:
http://www.dpreview.com/reviews/canoneos5dmarkii/19

cretindesalpes
21st March 2016, 23:34
How did you understand that the original clip uses BT601 matrix?
By trying to display it with a BT.601 matrix and suddenly seeing flat colors turning into gradients. Look at the fruit hanging on the tree at around 1:45.

Does it use BT601-525 primaries?
No idea. As I said, the stream isn’t tagged at all with color specifications. To be sure, you should ask the people that encoded this movie.

In order to prevent color clipping, is it safe to use BT2020 matrix for back and forth conversion between RGB and YUV (without primaries gamut conversion), when I am not sure about the source matrix?
There is no safe way. If you assume a certain colorspace and if your stream has Y’Cb’Cr’ component out of its legal range, you’ll have a loss when going back to Y’Cb’Cr’. In any case the R’G’B’ representations will be wrong so I can’t see why you would do this.

When you look at my screenshots, you will see that Scripts 1, 2 and 4 with BT601 matrix give different outputs that are not identical to input.
You’re assuming the source is full range whereas it is TV-range.

Is this Big Buck Bunny clip limited range based on your analysis? Is there a way to tell if a source clip is full range or limited range?
Unless specified explicitly in the stream, you can assume TV-range for most Y’Cb’Cr’ signals. To make sure (some streams are wrongly tagged), you can use an histogram. However this is not trivial, a lot of cameras generate TV-range streams but uses levels over 235 to store HDR data. But the black level should be located around 16 anyway.

J1Man
22nd March 2016, 00:44
Kolak:

Thanks for the full range test cases. I ran the tests using the following video from the page that you sent me:
http://download.dpreview.com/canon_eos5dmkii/5D2_Portrait.MOV

This video has Full Range color, BT.601 matrix coefficients, BT.709 primaries and BT.709 transfer function tagged in the stream. No guess work this time. Everything is tagged.

Since this video is full range, I added script 6 shown below.

Script 6 (Input and Output look identical for a full range source video.)
clip = core.fmtc.resample (clip, css="444")
clip = core.fmtc.matrix (clip, mat="601",fulls=True, fulld=True)
clip = core.fmtc.transfer (clip)
clip = core.fmtc.matrix (clip, mat="601", fulls=True, fulld=True)
clip = core.fmtc.resample (clip, css="420")
clip = core.fmtc.bitdepth (clip, bits=10)

I only ran test scripts 1,2 and 6 all with BT.601 matrix on this full range video. It does not make sense to run scripts 3,4 and 5 on this full range video (but in case anybody is wondering, outputs in test scripts 3, 4 and 5 do not look like the input, as expected). Screenshots can be downloaded from the link below. All screenshots are taken from the first frame of the video.

https://github.com/EleonoreMizo/fmtconv/files/183269/Portrait_FmtConv_RangeTestScripts_Screenshots.zip

Only script 6 gives an output that is identical to the input. Scripts 1 and 2 have different outputs. I would have expected Scripts 1 and 2 to have identical inputs & outputs for this full range video, but they don't.


The reason why I am running these tests and bringing this issue to Cretindesalp's attention is because I am trying to figure out if there is a bug in fmtconv or not. Based on Cretindesalp's messages, test scripts 1 and 2 should have identical inputs and outputs. But my screenshots (both for limited range Big Buck Bunny and full range Portrait video) show that this is not the case.


Cretindesalps:

Based on your message, I understand that the tests that I did with Big Buck Bunny clip were not very useful because we do not know for sure what the original specifications of the clip are.

This Portrait clip generated by Canon EOS 5D Mark II camera is a better test case because all information is tagged in the stream. What is your opinion on these results? Shouldn't scripts 1 and 2 give outputs that are identical to the input for this full range clip?

The most important question is, is there any unexpected behavior in these test results that indicate the presence of a bug in fmtconv? If you think that there is no problem, I am good too. I can just use script 5 for limited range clips and script 6 for full range source clips.

If you are in doubt, I can re-run the same test with other clips that you specify. Just send me the links.

cretindesalpes
22nd March 2016, 11:49
If you use a full-range video, you have to indicate to fmtc.matrix that you are using full-range Y’Cb’Cr’. Default is TV-range. That’s why script 1 and 2 don’t give the right result, whereas script 6 works as expected.

J1Man
25th March 2016, 00:37
Cretindesalps:

I am also having trouble with primaries conversion. I ran the test using the same video:
http://download.dpreview.com/canon_eos5dmkii/5D2_Portrait.MOV

This video has Full Range color, BT.601 matrix coefficients, BT.709 primaries and BT.709 transfer function tagged in the stream.

I used the following script to convert it to a 10bit full range clip with BT2020 primaries, BT2020 matrix and BT2020-10 transfer function.

Script 7 (Input and Output look different for a full range source video.)
clip = core.fmtc.resample (clip, css="444")
clip = core.fmtc.matrix (clip, mat="601",fulls=True, fulld=True)
clip = core.fmtc.transfer (clip, transs="709", transd="linear")
clip = core.fmtc.primaries (clip, prims="709", primd="2020")
clip = core.fmtc.transfer (clip, transs="linear", transd="2020_10")
clip = core.fmtc.matrix (clip, mat="2020", fulls=True, fulld=True)
clip = core.fmtc.resample (clip, css="420")
clip = core.fmtc.bitdepth (clip, bits=10)


I encoded the video by 10bit build of x265 and tagged the stream properly with BT2020 info. Screenshots can be downloaded from the link below. I took the screenshots at the first frame using MadVR. The girl's face looks very red. I am getting similar results when I play the clip on my UHD TV.

https://github.com/EleonoreMizo/fmtconv/files/188854/5D2_Portrait_BT2020_conversionTest.zip


Am I doing something wrong? Is there a mistake in my script?

cretindesalpes
25th March 2016, 10:27
Indeed there is a problem in the primaries code. I’m going to check what’s wrong.

cretindesalpes
25th March 2016, 16:14
fmtconv r20 (http://forum.doom9.org/showthread.php?t=166504):
primaries: fixed a bug preventing to set all primaries individually without specifying any preset.
primaries: fixed a bug in the color conversion, thanks to J1Man for having spotted it.

J1Man
26th March 2016, 02:02
Cretindesalpes:

Thanks for quickly releasing the new R20 version of fmtconv. I did more testing (using the same portrait clip) and it seems like the issue is not completely resolved. It seems like a big part of the problem is due to BT2020 matrix conversion. I ran the tests listed below using fmtconv r20. The screenshots can be downloaded from the link shown below.

https://github.com/EleonoreMizo/fmtconv/files/190266/5D2_Portrait_BT2020_StepByStepConversionTest2.zip

I first ran Script 6 to test for regressions. Script 6 converts the clip to RGB and back to 10bit YUV without modifying the matrix, primaries and transfer function. I took screenshots with MadVR and confirmed that input and output look 100% identical. This also proves that there is no distortion introduced by x265 or MadVR.

I also ran a modified version of Script 6 that only changes the transfer function from BT709 to BT2020-10 (keeping Matrix and primaries the same). I confirmed that screenshots taken by MadVR were identical. This rules out transfer function related mistakes.

I ran Script 7, to convert everything to BT2020 colorspace, took screenshots with MadVR and saw that input and output were different. I also ran a modified version of Script 7 to convert everything to BT709. Again there was a noticeable difference. The surprising thing is BT709 and BT2020 conversion screenshots look very very similar. As a result, I decided to run other tests.

I created Script 8 (shown below) that only changes the matrix (keeping primaries and transfer function identical). The input and output were different. There is a very big and noticeable difference.

Script 8 (just changes the matrix, Input and Output look different)
clip = core.fmtc.resample (clip, css="444")
clip = core.fmtc.matrix (clip, mat="601",fulls=True, fulld=True)
clip = core.fmtc.matrix (clip, mat="2020", fulls=True, fulld=True)
clip = core.fmtc.resample (clip, css="420")
clip = core.fmtc.bitdepth (clip, bits=10)


There might be a problem with the matrix conversion function used by fmtconv. Since we are going from the smaller color space of BT601 to much larger color space BT2020, there should not be any clipping. There is a BT2020 matrix defined in the source code of x265. I wrote the links below in case they can be useful to you.

https://bitbucket.org/multicoreware/x265/commits/2860b4d8bd682e8d0fe2a08b1e16198feb696230
https://bitbucket.org/multicoreware/x265/src/2860b4d8bd682e8d0fe2a08b1e16198feb696230/source/common/constants.cpp?at=default&fileviewer=file-view-default




I created Script 9 (shown below) that only changes the primaries (keeping matrix and transfer function identical). The input and output were different. There is a small (but still noticeable) difference visible on girl's face, lips and the ceiling.

script 9 (just change primaries, Input and Output look different)
clip = core.fmtc.resample (clip, css="444")
clip = core.fmtc.matrix (clip, mat="601",fulls=True, fulld=True)
clip = core.fmtc.transfer (clip, transs="709", transd="linear")
clip = core.fmtc.primaries (clip, prims="709", primd="2020")
clip = core.fmtc.transfer (clip, transs="linear", transd="709")
clip = core.fmtc.matrix (clip, mat="601", fulls=True, fulld=True)
clip = core.fmtc.resample (clip, css="420")
clip = core.fmtc.bitdepth (clip, bits=10)


I also ran script 9 using the previous primaries (from fmtconv r18) for BT2020 using the command (gd=[0.170, 0.797], bd=[0.131, 0.046], rd=[0.708, 0.292], wd=[0.3127, 0.3290]) and the results did not change.


Please let me know what you think. I ran all the tests that I could think of. I can run more tests if you have any other test ideas.

J1Man
30th March 2016, 14:27
Cretindesalpes:

I stumbled on a more serious bug. When "1886a" (alternative approximation of 1886) transfer function is used before and after primaries conversion, it creates heavy pink artifacts on bright areas of the video. I attached screenshots from Tears of Steel movie. You can replicate the bug on any movie with a bright outdoor scene. Artifacts appear mostly on bright parts of the image.

https://github.com/EleonoreMizo/fmtconv/files/195533/tears_of_steel_BugReport_1886a_transferfunction.zip


I used script 10 shown below to generate the screenshots. Script 11 that changes transfer function from 1886a to pure 2.3 gamma curve (without primaries conversion) also creates artifacts that almost posterize the output.

Script 10 (Primaries conversion with 1886a transfer function creates pink artifacts)
clip = core.fmtc.resample (clip, css="444")
clip = core.fmtc.matrix (clip, mat="709",fulls=False, fulld=True)
clip = core.fmtc.transfer (clip, transs="1886a", transd="linear")
clip = core.fmtc.primaries (clip, prims="709", primd="2020")
clip = core.fmtc.transfer (clip, transs="linear", transd="1886a")
clip = core.fmtc.matrix (clip, mat="2020", fulls=True, fulld=False)
clip = core.fmtc.resample (clip, css="420")
clip = core.fmtc.bitdepth (clip, bits=10)

Script 11 (changing transfer function from 1886a to pure 2.3 gamma curve creates artifacts)
clip = core.fmtc.resample (clip, css="444")
clip = core.fmtc.matrix (clip, mat="709",fulls=False, fulld=True)
clip = core.fmtc.transfer (clip, transs="1886a", transd="linear")
clip = core.fmtc.transfer (clip, transs="linear", transd="linear", gcor=1/2.3)
clip = core.fmtc.matrix (clip, mat="709", fulls=True, fulld=False)
clip = core.fmtc.resample (clip, css="420")
clip = core.fmtc.bitdepth (clip, bits=10)



Based on these two scripts, I think the bug is in 1886a transfer function code only.



Most probably you already have it, but I found the latest 1886 standard (with formulas) on the following page:
http://www.itu.int/rec/R-REC-BT.1886-0-201103-I


In theory, Should an accurate implementation of BT.1886 transfer function standard (1886a in fmtconv) provide more accurate linearization before primaries conversion for the latest movies?

Selur
7th August 2016, 11:30
'Small' feature request:
Would be nice/helpful if fmtconv would contain a 'helperfunction' which would convert the current color format&matrix to the target color format and matrix.
something like core.fmtc.convert(clip, srcmat, tarfor, tarmat)

so that when having to do a RGB to YUV420P10 conversion instead of having to call:
c = core.fmtc.matrix (clip=c, mat="601", col_fam=vs.YUV, bits=16)
c = core.fmtc.resample (clip=c, css="420")
c = core.fmtc.bitdepth (clip=c, bits=10)
one could simply call:
c = core.fmtc.bitdepth (clip=c, srcmat="601", tarfor="YUV420P10")

or when doing YUV420P10 601 to YUV420P8 709 instead of having to call:

c = core.fmtc.resample (clip=c, css="444")
c = core.fmtc.matrix (clip=c, mats="601", matd="709")
c = core.fmtc.resample (clip=c, css="420")
c = core.fmtc.bitdepth (clip=c, bits=8)

one could simply call:
c = core.fmtc.bitdepth (clip=c, srcmat="601", tarfor="YUV420P8", tarmar="709")
I understand that this would be some lengthy wrapper function to handle all the different possible conversions, but I think it would help the general pain of writing Vapoursynth scripts a bit and not everybody would have to write always those 3-X format conversion lines.

Cu Selur

jackoneill
7th August 2016, 12:11
'Small' feature request:
Would be nice/helpful if fmtconv would contain a 'helperfunction' which would convert the current color format&matrix to the target color format and matrix.
something like core.fmtc.convert(clip, srcmat, tarfor, tarmat)

so that when having to do a RGB to YUV420P10 conversion instead of having to call:
c = core.fmtc.matrix (clip=c, mat="601", col_fam=vs.YUV, bits=16)
c = core.fmtc.resample (clip=c, css="420")
c = core.fmtc.bitdepth (clip=c, bits=10)
one could simply call:
c = core.fmtc.bitdepth (clip=c, srcmat="601", tarfor="YUV420P10")

or when doing YUV420P10 601 to YUV420P8 709 instead of having to call:

c = core.fmtc.resample (clip=c, css="444")
c = core.fmtc.matrix (clip=c, mats="601", matd="709")
c = core.fmtc.resample (clip=c, css="420")
c = core.fmtc.bitdepth (clip=c, bits=8)

one could simply call:
c = core.fmtc.bitdepth (clip=c, srcmat="601", tarfor="YUV420P8", tarmar="709")
I understand that this would be some lengthy wrapper function to handle all the different possible conversions, but I think it would help the general pain of writing Vapoursynth scripts a bit and not everybody would have to write always those 3-X format conversion lines.

Cu Selur

The built-in resizers work the way you describe.
http://www.vapoursynth.com/doc/functions/resize.html
Swscale is not involved anymore, so you can use them without worries.

Selur
7th August 2016, 13:09
Nice! That helps! Thanks!

groucho86
1st September 2016, 17:23
Hi there,
I'm trying to (ultimately) create an MP4 with HDR metadata. My source is generated in Resolve in ACES with an ODT of P3D60 PQ (1000 nits) so it's HDR-Ready. I've outputted as both an OpenEXR image sequence and as a ProRes422HQ.

Having read threads on both doom9 and Blackmagic forums, I think x265 is expecting a YUV 420 10bit y4m stream.

I was doing the following in FFMPEG but was not getting correct results:
ffmpeg -nostats -start_number 00086400 -framerate 24000/1001 -i "/Volumes/TEST/p3d60/p3d60-%08d.exr" -strict -1 -vf \\
scale=out_color_matrix=bt2020:out_h_chr_pos=0:out_v_chr_pos=0,format=yuv420p10 -f yuv4mpegpipe - | x265 - --y4m --crf 13 \\
--tune grain --colorprim bt2020 --transfer smpte-st-2084 --colormatrix bt2020nc --master-display \\
"G(13250,34500)B(7500,3000)R(34000,16000)WP(15635,16450)L(10000000,1)" --max-cll "1000,400" --output "/Volumes/TEST/hevc/test.hevc"

I'm now trying ffmtconv but I'm unable to create the YUV 420 10bit stream after creating an smpte-2084 version. This is what I have:
c = core.lsmas.LibavSMASHSource(source="/Volumes/Test/ test01.mov")

c = core.fmtc.resample(clip=c, css="444")
c = core.fmtc.bitdepth(clip=c, bits=10)
c = core.fmtc.matrix2020cl(clip=c, full=True )
c = core.fmtc.transfer(c, transs="2020", transd="2084", cont=1000.0/10000.0)

c.set_output()

I then try something like
c = core.fmtc.resample(clip=c, css='420')

But get the following error:
File "src/cython/vapoursynth.pyx", line 1383, in vapoursynth.Function.__call__ (build/temp.macosx-10.9-x86_64-3.5/pyrex/vapoursynth.c:25204)
vapoursynth.Error: : couldn't get a pixel format identifier for the output clip.

Thank you in advance for your help.

dipje
2nd October 2016, 20:19
Another thing I noticed in r20. Am I doing something wrong, making wrong assumptions or is there something wrong in fmtconv somewhere?

I read a simple movie file (YUV420P8).

I resample to YUV444P16, use matrix to go RGB48 (from BT709), I transfer to linear, I use primaries to go from 709 to 2020, I transfer from linear to 2048 with a contrast value of 1000.0 / 10000.0 (0.1), then matrix to YUV with BT2020 (non-constant) matrix.

As a test, I do the reverse directly in the script. Matrix to RGB from BT2020nc, transfer to linear from 2084 with a contrast value of 10000.0 / 1000.0 (10.0), I use primaries to go from 2020 to 709, I transfer from linear to regular 709, and I use matrix to go to YUV with BT709 matrix.

The result should be pretty much exact the same as the input (with some rounding errors here and there or something), but what I get is a clear 'levels' difference. It seems as if somewhere in the process there is a 'limited range / full range' mix up. The colors seem right, it's just a little bit of levels / contrast that seems different.

I ended up added 'fulls' and 'fulld' everywhere to make sure it does what I expect it to but I still get the same.

Am I doing wrong? Fmtconv wrong? Or is this just the result from going from 709 to 2084 and back since it's not a pure 1-to-1 mapping or something?

My code copy & pasted to be clear:

orig = c
c = core.fmtc.resample(c, w = 1920, h = 1080, css = '444', kernel = 'spline36')
c = core.fmtc.matrix(c, fulls = False, fulld = True, mats = '709', col_fam = vs.RGB)
c = core.fmtc.transfer(c, fulls = True, fulld = True, transs = '61966-2-1', transd = 'linear')
c = core.fmtc.primaries(c, prims = '709', primd = '2020')
c = core.fmtc.transfer(c, fulls = True, fulld = True, transs = 'linear', transd = '2084', cont = 1000.0 / 10000.0)
c = core.fmtc.matrix(c, fulls = True, fulld = False, matd = '2020', col_fam = vs.YUV)
c = core.fmtc.resample(c, css = '420')
c = core.fmtc.bitdepth(c, fulls = False, fulld = False, bits = 10, dmode = 5)

z = c
z = core.fmtc.resample(z, css = '444', kernel = 'spline36')
z = core.fmtc.matrix(z, fulls = False, fulld = True, mats = '2020', col_fam = vs.RGB)
z = core.fmtc.transfer(z, fulls = True, fulld = True, transs = '2084', transd = 'linear', cont = 10)
z = core.fmtc.primaries(z, prims = '2020', primd = '709')
z = core.fmtc.transfer(z, fulls = True, fulld = True, transs = 'linear', transd = '709')
z = core.fmtc.matrix(z, fulls = True, fulld = False, matd = '709', col_fam = vs.YUV)
z = core.fmtc.resample(z, css = '420', kernel = 'spline36')
z = core.fmtc.bitdepth(z, fulls = False, fulld = False, bits = 8, dmode = 5, ampo = 1, ampn = 1)

# At this moment 'orig' and 'z' look different although they should look pretty much the same I guess

age
4th October 2016, 18:30
you have used different transfer values,probably you have to go in linear space using 709 transfer
or come back from linear space using "61966-2-1"

orig = c
c = core.fmtc.resample(c, w = 1920, h = 1080, css = '444', kernel = 'spline36')
c = core.fmtc.matrix(c, fulls = False, fulld = True, mats = '709', col_fam = vs.RGB)
c = core.fmtc.transfer(c, fulls = True, fulld = True, transs = '709', transd = 'linear')
#c = core.fmtc.transfer(c, fulls = True, fulld = True, transs = '61966-2-1', transd = 'linear')
c = core.fmtc.primaries(c, prims = '709', primd = '2020')
c = core.fmtc.transfer(c, fulls = True, fulld = True, transs = 'linear', transd = '2084', cont = 1000.0 / 10000.0)
c = core.fmtc.matrix(c, fulls = True, fulld = False, matd = '2020', col_fam = vs.YUV)
c = core.fmtc.resample(c, css = '420')
c = core.fmtc.bitdepth(c, fulls = False, fulld = False, bits = 10, dmode = 5)

z = c
z = core.fmtc.resample(z, css = '444', kernel = 'spline36')
z = core.fmtc.matrix(z, fulls = False, fulld = True, mats = '2020', col_fam = vs.RGB)
z = core.fmtc.transfer(z, fulls = True, fulld = True, transs = '2084', transd = 'linear', cont = 10)
z = core.fmtc.primaries(z, prims = '2020', primd = '709')
z = core.fmtc.transfer(z, fulls = True, fulld = True, transs = 'linear', transd = '709')
#z = core.fmtc.transfer(z, fulls = True, fulld = True, transs = 'linear', transd = '61966-2-1')
z = core.fmtc.matrix(z, fulls = True, fulld = False, matd = '709', col_fam = vs.YUV)
z = core.fmtc.resample(z, css = '420', kernel = 'spline36')
z = core.fmtc.bitdepth(z, fulls = False, fulld = False, bits = 8, dmode = 5, ampo = 1, ampn = 1)

dipje
4th October 2016, 22:07
D'oh.. stupid mistake on my part it seems. Will try it out, but srgb and 709 isn't always the same of course :S.

age
13th October 2016, 15:47
Is it possible to add/port some new resizer like ewa_lanczossharp (mpv player) ?