View Full Version : Poor man's NTSC 30p/60p to PAL 25p conversion
zambelli
18th October 2005, 10:27
I'm trying to come up with an NTSC to PAL conversion method that emphasizes smooth motion at the expense of detail. I've used Scharfis_Brain's convert60ito24p.avs (http://home.arcor.de/scharfis_brain/) function before and I was always pleased with the results, so I thought I'd use it as a starting point for my conversion.
Convert60ito24p takes a 60p source (umm, Scharfis, shouldn't the function be called 60p then? :) ) and in mode=2 it blends every field in a 3:2 pattern. The blending is weighted 25-50-25 for the 3 frames and 50-50 for the 2 frames.
My modified version, aptly named Convert60pto25p, also takes a 60p input. I've only kept mode 2, because it produces the smoothest motion, and I've modified the function to blend fields in a 3:2:3:2:2 pattern, with the same 25-50-25 and 50-50 blending as before.
This reduces 60 frames down to 25 (12:5 ratio), so if you're working with a 59.94 fps source, you need to make sure you add ChangeFPS(25) at the very end to avoid 24.975 fps output.
The usage goes something like this:
import (convert60pto25p.avs)
xxxsource("clip")
loadplugin(your 60fps bob deinterlacer like dgbob or tdeint)
your60fpsdeinterlacer() # apply if source is 60i
Convert60pTo25p(0)
And finally, here's my function. Many thanks to ScharfisBrain for writing the original one and I hope he'll excuse my bastardization of his idea. :)
function Convert60pTo25p (clip video, int offset)
{
work = assumefieldbased(video)
out = interleave(
\selectevery(
\layer(trim(work, 1, 0),
\layer(work, trim(work, 2, 0), "fast"),
\"fast"), 12, 0 + offset),
\selectevery(
\layer(work, trim(work, 1, 0), "fast"), 12, 3 + offset),
\selectevery(
\layer(trim(work, 1, 0),
\layer(work, trim(work, 2, 0), "fast"),
\"fast"), 12, 5 + offset),
\selectevery(
\layer(work, trim(work, 1, 0), "fast"), 12, 8 + offset),
\selectevery(
\layer(work, trim(work, 1, 0), "fast"), 12, 10 + offset))
assumeframebased(out)
}
Comments? Suggestions?
zambelli
20th October 2005, 20:35
I must've either written the perfect script or a script so bad it's not worth commenting on . ;)
Mug Funky
21st October 2005, 05:38
i'm just wondering whether it might be quicker and easier to just take the 60p and convertfps it to 50p, then blend adjacent frames to get to 25p.
but then, i find it advantageous to convert 60i (that is 30fps interlaced) to 50i (25fps interlaced) rather than go from an interlaced to progressive-at-half-the-framerate output.
well, i'm sticking around until a true-motion compensation technique arrives in avisynth (mvtools isn't "true" motion but SAD-based compensation which doesn't lend itself too well to actual interpolation as opposed to compensation. of course is it still incredibly useful for denoising and deinterlacing, but just not for creating new frames).
however, that's a pretty good scripting effort :) definitely continue with that stuff (and see if you can come up with a fast and accurate way to "classify" 60i, 30p and telecine parts of an NTSC video so they can get different treatments).
zambelli
25th October 2005, 00:49
i'm just wondering whether it might be quicker and easier to just take the 60p and convertfps it to 50p, then blend adjacent frames to get to 25p.
I haven't tried it, but wouldn't ConvertFPS(50) throw out 10 frames? Even if it accomplished 50p through blending, is there any guarantee that the blending pattern would provide fluid motion?
but then, i find it advantageous to convert 60i (that is 30fps interlaced) to 50i (25fps interlaced) rather than go from an interlaced to progressive-at-half-the-framerate output.
Agreed, and I should've been clearer in my post: my function is primarily designed for progressive content. It assumes progressive input and gives progressive output. My reason for writing it was because I had to convert some 30p (shot in HD, scaled down to NTSC) content to PAL. Starting with 60 frames (even if they're just duplicated from a 30p source) and ending with 25 seemed slightly more scaleable than trying to do a straight 30p->25p conversion.
however, that's a pretty good scripting effort :) definitely continue with that stuff (and see if you can come up with a fast and accurate way to "classify" 60i, 30p and telecine parts of an NTSC video so they can get different treatments).
So far the results have been pretty good: motion is very fluid, albeit there is considerable ghosting in high motion sequences, but it's noticable only if you literally watch it frame-by-frame. The most obvious blending artifact is present during camera pans: that's where the entire image gets blended so it all turns very fuzzy during the pans. Otherwise it looks quite good and no frames are ever dropped.
scharfis_brain
25th October 2005, 04:58
the problem I do see with it:
it puts out 24.975 fps instead of true 25 fps.
(1000/1001)
zambelli
25th October 2005, 20:27
the problem I do see with it:
it puts out 24.975 fps instead of true 25 fps.
(1000/1001)
Yeah, I anticipated that:
This reduces 60 frames down to 25 (12:5 ratio), so if you're working with a 59.94 fps source, you need to make sure you add ConvertFPS(25) at the very end to avoid 24.975 fps output.
This will result in one duplicated frame every 1 minute or so. Not a big deal, IMHO.
scharfis_brain
26th October 2005, 20:21
This will result in one duplicated frame every 1 minute or so. Not a big deal, IMH
with convertfps it will yield into a horrible ghosting/blending
only with changefps it will return 1 duplicated frame per 20 seconds
better will be:
source()
bob()
changefps(60)
Convert60pTo25p()
zambelli
27th October 2005, 10:11
You're right, I didn't think of that. ChangeFPS() does look a lot better.
wsl
1st November 2005, 04:29
At first i use Scharfis_Brain's convert60ito24p.avs.
Now i switch to Scharfis_Brain's mv60ito24p() together
with yv12average() from Didée to replace Overlay( a, b, opacity=0.5)
[link: http://forum.doom9.org/showthread.php?t=92292]
The latter combination gives better results than using convert60ito24p.avs
i would apprciate much if someone can write a similar mv version of Convert60pTo25p
Thanks everyone.
wsl
10th November 2005, 19:13
To use Convert60pTo25p on YV12 video,
i use overlay in place of layer:
function Overlay60pTo25p (clip video)
{
work = assumefieldbased(video)
work1 = trim(work, 1, 0)
work2 = trim(work, 2, 0)
out = interleave(
\selectevery(overlay (work1, overlay (work, work2)), 12, 0),
\selectevery(overlay (work, work1), 12, 3),
\selectevery(overlay (work1, overlay (work, work2)), 12, 5 ),
\selectevery(overlay (work, work1), 12, 8),
\selectevery(overlay (work, work1), 12, 10))
assumeframebased(out)
}
while trying to do a mv version of Convert60pTo25p,
i get stuck at the following line:
yv12average( yv12average(selectevery(5,1),selectevery(5,2),amount=0.46), selectevery(5,3),amount=0.35 )
i read through the MVtool Documentation but still cannot figure out how it
can combine 3 frames then 2 frame.
Please help.
Actually i managed to encode 8 minutes of a video using multiple
mv60ito25p() and yv12average() to combine frames in 3:2:3:2:2 pattern,
and the results are very good, much better than using Convert60pTo25p().
But the codes are very messy.
Piper
31st December 2005, 18:25
Actually i managed to encode 8 minutes of a video using multiple
mv60ito25p() and yv12average() to combine frames in 3:2:3:2:2 pattern,
and the results are very good, much better than using Convert60pTo25p().
But the codes are very messy.
I've searched, but have only found mention of mv60ito25p() in this thread. Can you post it? How would you use it and yv12average() in place of Convert60pTo25p()?
Having only previewed frames in Virtualdub, I like how the Convert60pTo25p() looks. There's quite a bit of blending frames in motion scenes, but the overall picture appears more stable than Overlay60pTo25p() which leaves more artifacts on horizontal lines and has similar appearance to RePal.
wsl
1st January 2006, 08:14
The function mv60ito25p() breaks each 60 frames into groups of 5-5-2
and call mv60ito24p() and yv12average() accordingly to get 5 frames
out of 12 frames.
since mvtool uses forward and backward frames,
the 5-5-2 grouping might prevent it from getting the correct frames.
so this mv60ito25p() might not work properly.
Maybe someone would explain how it (doesn't) works.
AVISource("dv.avi").ReInterpolate411()
LeakKernelBob(order=0)
changefps(60)
Lanczos4Resize(720,576)
ConvertToYV12()
mv60ito25p()
Return last
function mv60ito25p(clip x)
{
last=x
audio=last
a=selectevery(12,0,1,2,3,4)
b=selectevery(12,5,6,7,8,9)
c=selectevery(12,10,11)
aa=mv60ito24p(a)
bb=mv60ito24p(b)
cc= yv12average(c.SelectEven(),c.SelectOdd())
cc=DoubleWeave(cc)
interleave(aa,bb,cc)
video=selectevery(6,0,3,1,4,2)
return AudioDub(video,audio)
}
function mv60ito24p(clip x)
{
mbl=0.1
fwd=mvtools0962_mvanalyse(x,isb=false,lambda=4000)
bwd=mvtools0962_mvanalyse(x,isb=true, lambda=4000)
y=x.mvtools0962_mvinterpolate(bwd, fwd, nb = 4,bl = 0.5-mbl, el = 0.5+mbl, wf = "uniform")
interleave(y,x)
yv12average( yv12average(selectevery(5,1),selectevery(5,2),amount=0.46), selectevery(5,3),amount=0.35 )
}
function yv12average(clip clp1, clip clp2, float "amount", int "l", int "c")
{
amount = default(amount, 0.5)
l = default(l, 3)
c = default(c, 3)
BL="x "+string(1.0-amount)+" * y "+string(amount)+" * +"
YV12lutxy( clp1,clp2, BL,BL,BL, Y=l,U=c,V=c )
}
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.