Wilbert
5th September 2004, 14:55
Continued from this thread:
http://forum.doom9.org/showthread.php?s=&postid=540719#post540719
YV12 (progressive) -> YUY2:
* Uses alternating 75/25 25/75 averages of nearest chroma samples
YV12 (interlaced) -> YUY2:
* Is also using alternating 75/25 25/75 averages, but of the nearest chroma samples from the correct field
If I understand it correctly, the odd chroma lines are just copied, and the missing even chroma lines are interpolated (in YV12->YUY2).
Maybe it's useful to make a ConvertBackToYV12 (analogue to ConvertBackToYUY2), which selects the odd chroma lines of the YUY2 clip (throwing away the interpolated even chroma lines). That way ConvertToYUY2(YV12source).ConvertBackToYV12 is lossless?
for a RGB clip is should map to ConvertBackToYUY2.ConvertBackToYV12 making ConvertToRGB(YV12source).ConvertBackToYV12 lossless.
Mug Funky
6th September 2004, 09:28
wilbert: that would be great if there were lossless convert to and back from YV12 and YUY2.
although, there's not that much around that doesn't work in yv12. the only ones i use are smartdecimate (which works well enough except for certain situations which probably wouldn't be noticed on playback anyway) and convertfps.
sh0dan
6th September 2004, 12:06
Originally posted by Wilbert
If I understand it correctly, the odd chroma lines are just copied, and the missing even chroma lines are interpolated (in YV12->YUY2).
No chroma is copied in YV12<->YUY2, since YUY2 chroma is placed on the line, and YV12 chroma is between the lines. So in both cases chroma has to be reinterpolated.
A "lossless" conversion mode could be emulated - like this:
src = last # Insert your (YV12) source here!
c1_y = convertToYUY2(src) # We use luma from this = lossless.
c1_u = utoy(src).convertToYUY2().pointresize(src.width/2,src.height) #We duplicate UV in YUY2
c1_v = vtoy(src).convertToYUY2().pointresize(src.width/2,src.height)
src_YUY2 = YtoUV(c1_u, c1_v, c1_y)
c2_y = ConvertToYV12(src_YUY2) #Again, copy luma
c2_u = utoy(src).bilinearResize(src.width/2, src.height/2) #Here we use bilinear! (*)
c2_v = vtoy(src).bilinearResize(src.width/2, src.height/2)
src_YV12 = YToUV(c2_u, c2_v, c2_y)
ScriptClip("SubTitle(src, string(ChromaVDifference(src, src_yv12)))") # (**)
ScriptClip("SubTitle(last, string(ChromaUDifference(src, src_yv12)), y=40)")
(*) We can use bilinear in this conversion, since chroma is duplicated in the YV12 -> YUY2. This means that both chroma values are considered, but chroma is unchanged if it has not been modified.
(**) Yes - it displays "0.000010" onscreen. While this might seem like a float roundoff, is is actually just a bug. For some reason I put in a "if difference is 0, set it to 1"... fixed now, though.
However, using this method, chroma is displaced on conversion. The two conversions just "undo" the misalignment, so they must be paired.
For interlaced material, separatefields/weave must be used.
Of course the conversion cannot go the other way around. You CAN keep UV in the luma channel, and do your processing there, and recombine them to one image when you have converted back to YUY2 - but all your YV12 filter will have to be invoked three times:src = last.convertToYuy2() # Insert your source here
c1_y = convertToYUY2(src) # We use luma from this = lossless.
c1_u = utoy(src).convertToYV12()
c1_v = vtoy(src).convertToYV12()
# Process c1_y, c1_u and c1_v separately
src_YUY2 = YtoUV(convertToYUY2(c1_u), convertToYUY2(c1_v), convertToYUY2(c1_y))
vBulletin® v3.8.4, Copyright ©2000-2010, Jelsoft Enterprises Ltd.