This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm whether you accept or reject these cookies being set.

A cookie will be stored in your browser regardless of choice to prevent you being asked this question again. You will be able to change your cookie settings at any time using the link in the footer.

VIVTC mode: VFM gets the QTGMC'd clip as both clip and clip2 - is it intended?
#1
Hi Selur,

I'm using Hybrid's VIVTC handling on telecined NTSC film sources (720x480/486, ProRes 422 HQ)
and noticed something in the generated VapourSynth script that I'd like to check with you.

Settings: Filtering > (De-)Interlace/Telecine > Auto deinterlace handling: VIVTC (Vapoursynth)
VFM tab: Mode "2-way match + 3rd match on combed (p/c + n)", Deinterlacer: QTGMC (preset slow),
Order 0, Field 2, Mi 80, Block 32/32, Exclude 16/16, Scene threshold 12, Chroma matching on, Mic match 1.
Seen with Hybrid 2026.09.06.1, 2026.09.26.1 (macOS) and the 2026.10.01.1 Linux AppImage.

The generated script contains:

  clip2clip = clip
  clip2clip = qtgmc.QTGMC(Input=clip2clip, Preset="slow", TFF=False, ...)
  yv12 = core.resize.Bicubic(clip=clip2clip, format=vs.YUV420P8, range_in_s="limited")
  clip = core.vivtc.VFM(yv12, clip2=clip2clip, order=0, chroma=False)
  ...
  clip = core.std.FrameEval(clip=clip, eval=functools.partial(postprocess, clip=clip, deinterlaced=clip2clip), prop_src=clip)
  clip = core.vivtc.VDecimate(clip)

So VFM both analyses and outputs the already-deinterlaced QTGMC clip, never the original fields.
I measured this on 300 frames: VFMMatch was 'c' on 300/300 and every VFM output frame was
bit-identical to the QTGMC frame. Run on the original fields, VFM chose p on about two-thirds of
those frames, i.e. it actually re-paired fields. Over a full film, the chain's output is about
41 dB PSNR to the original fields, vs about 55 dB when VFM matches the original fields.

The vivtc docs describe clip2 as the format workaround with clip2 = the original
(yv12 = Bicubic(original); VFM(yv12, clip2=original)), and the post-processing example
applies the deinterlacer to the matched clip, used only for frames flagged _Combed.

Questions:
1. Is applying the selected Deinterlacer to every frame before VFM intended? I expected it to be
  used only for frames VFM still flags as combed.
2. If it isn't intended, could VIVTC mode generate VFM on the original (clip = 8-bit copy of the
  source, clip2 = source) with the deinterlacer only in the FrameEval post-processing?
3. Only order and chroma reach VFM in the script; the Block 32/32 (and other VFM tab values) don't
  seem to be passed. Is that expected?

P.S. In case it's useful for other users: with 720x486 sources, the YUV420P8 match clip has 243-row
chroma planes, and vivtc's compareFieldsSlow (field=0) reads one row past the end of the plane
(curnf on row 243). On Linux this intermittently segfaults vspipe in vivtc.so (it never crashed on
macOS for us). Padding the match clip to 488 rows (std.AddBorders(bottom=2)) avoids it.

Thanks for Hybrid and for any insight!
Reply
#2
(side note: haven't used vivtc for ages)
regarding 1.:
No, that’s not intended. When the source isn’t YUV420P8, Hybrid builds the 8-bit match clip and VFM’s clip2 from the same variable that also holds the deinterlaced clip. So VFM matches and outputs QTGMC frames, which explains your 300/300 ‘c’. With 8-bit 4:2:0 sources, VFM already works on the original fields.

regarding 2.: Yes, that’s should fix it: match clip = 8-bit conversion of the source, clip2 = source, and the selected deinterlacer only in the FrameEval post-processing for frames flagged _Combed. I’ll add it to the next dev build.

regarding 3.: Also a bug. Hybrid only writes options that differ from Hybrid’s defaults, and for Block X/Y those differ from vivtc’s own defaults (VFM: Hybrid 32 vs. vivtc 16; VDecimate: Hybrid 64 vs. vivtc 32). So your 32/32 got dropped and VFM ran with 16/16. Your other values match vivtc’s defaults, so leaving them out doesn’t change anything. Checked it, in vivtc’s source: VFM’s block default is 16/16 and VDecimate’s is 32/32, and clip2 does not affect chroma. I’ll fix that too.

About as seqfault: will look into adding a workaround (padding, deinterlacing, removing the padding)

=> don't have enough time to fix these before work, but will look at it once I'm back home after work (~13hrs), also found another small bug which could potentially cause issues with the used scan order in vfm. I'll also adress that and then release new dev versions. (which will then be inside the R81 folder in the experimental folder)

Cu Selur
----
Dev versions are in the 'experimental'-folder of my GoogleDrive, which is linked on the download page.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)