Robert Martens
15th March 2014, 06:51
Is there any way in Avisynth 2.5 to get the same output from ConvertToYUY2 that you get from Avisynth 2.6?
I'm back to a seemingly endless quest to finish my current plugin development project, and part of that involves regression tests that track the MD5 hash of test scripts' output frames. I recently discovered that while the majority of my tests produce the same output whether run under 2.5 or 2.6, some involving the creation of YUY2 and YV12 clips are giving different output depending on the host.
According to this post (http://forum.doom9.org/showthread.php?p=1038027#post1038027), Avisynth <= 2.58 uses a 0-1-1 kernel for RGB->YUY2 conversions, which was implemented for performance reasons way back when. It works quickly, but causes a slight horizontal chroma shift in the process. In 2.6, however, it was decided that the performance penalty of an improved approach was acceptable, and the 1-2-1 kernel referred to in the aforementioned post was implemented for Avisynth 2.6 (http://forum.doom9.org/showthread.php?p=1644457#post1644457).
Having heard of this issue before, I began by assuming it could be the cause of the different results, and after eliminating my plugin and test executable from the equation, I thought I'd managed to piece together a solution:
base = BlankClip(width=1, height=1, pixel_type="RGB24")
a = BlankClip(base, color=$FF0000)
b = BlankClip(base, color=$00FF00)
c = BlankClip(base, color=$0000FF)
d = BlankClip(base, color=$FFFF00)
two = StackVertical(StackHorizontal(a, b), StackHorizontal(c, d))
four = StackVertical( \
StackHorizontal(two, two.FlipVertical()), \
StackHorizontal(two.Turn180(), two.FlipHorizontal()) \
)
avs26 = four.ConvertToYUY2(matrix="PC.601")
w = four.Width()
h = four.Height()
avs25_chroma = four.BilinearResize(w, h, -0.5, 0).ConvertToYUY2(matrix="PC.601")
avs25 = MergeChroma(avs26, avs25_chroma)
return VersionNumber() < 2.6 ? avs25: avs26
I expect this script to produce identical output whether run under 2.5 or 2.6, and it seems to. Saving the results as EBMP files using ImageWriter, then loading both results and using Subtract, shows they're the same. The MD5 hash is exact, as well. Opening the script in AvsPmod, zooming in with "Fit inside window", then hovering over each square shows the same YUV readouts, too.
Unfortunately it only seems to work for that one contrived, small example. When I replace 'four' with a more involved clip, for example this HSL plot (https://github.com/ItEndsWithTens/TurnsTile/raw/master/test/scripts/clips/hsl.png), I still see different results. Subtracting the 2.5 results from the 2.6 results shows that the Y components are identical at 126, but scanning across the frame in AvsPmod shows that U and V jitter between roughly 127 and 130, when they should both be 128.
Am I missing something in this process, or is there just no way to achieve the output of 2.6 in 2.5? For my purposes I have a few other options for getting around this (save a reference frame from 2.6 as an EBMP so I can bypass conversions, maintain separate test scripts and reference data for 2.5, force developers running the test suite to use 2.6, etc.), but for my own edification I'd like to know if I'm just stumbling over the implementation of the idea, and so far despite scouring old threads I haven't figured out what I'm doing wrong.
I'm back to a seemingly endless quest to finish my current plugin development project, and part of that involves regression tests that track the MD5 hash of test scripts' output frames. I recently discovered that while the majority of my tests produce the same output whether run under 2.5 or 2.6, some involving the creation of YUY2 and YV12 clips are giving different output depending on the host.
According to this post (http://forum.doom9.org/showthread.php?p=1038027#post1038027), Avisynth <= 2.58 uses a 0-1-1 kernel for RGB->YUY2 conversions, which was implemented for performance reasons way back when. It works quickly, but causes a slight horizontal chroma shift in the process. In 2.6, however, it was decided that the performance penalty of an improved approach was acceptable, and the 1-2-1 kernel referred to in the aforementioned post was implemented for Avisynth 2.6 (http://forum.doom9.org/showthread.php?p=1644457#post1644457).
Having heard of this issue before, I began by assuming it could be the cause of the different results, and after eliminating my plugin and test executable from the equation, I thought I'd managed to piece together a solution:
base = BlankClip(width=1, height=1, pixel_type="RGB24")
a = BlankClip(base, color=$FF0000)
b = BlankClip(base, color=$00FF00)
c = BlankClip(base, color=$0000FF)
d = BlankClip(base, color=$FFFF00)
two = StackVertical(StackHorizontal(a, b), StackHorizontal(c, d))
four = StackVertical( \
StackHorizontal(two, two.FlipVertical()), \
StackHorizontal(two.Turn180(), two.FlipHorizontal()) \
)
avs26 = four.ConvertToYUY2(matrix="PC.601")
w = four.Width()
h = four.Height()
avs25_chroma = four.BilinearResize(w, h, -0.5, 0).ConvertToYUY2(matrix="PC.601")
avs25 = MergeChroma(avs26, avs25_chroma)
return VersionNumber() < 2.6 ? avs25: avs26
I expect this script to produce identical output whether run under 2.5 or 2.6, and it seems to. Saving the results as EBMP files using ImageWriter, then loading both results and using Subtract, shows they're the same. The MD5 hash is exact, as well. Opening the script in AvsPmod, zooming in with "Fit inside window", then hovering over each square shows the same YUV readouts, too.
Unfortunately it only seems to work for that one contrived, small example. When I replace 'four' with a more involved clip, for example this HSL plot (https://github.com/ItEndsWithTens/TurnsTile/raw/master/test/scripts/clips/hsl.png), I still see different results. Subtracting the 2.5 results from the 2.6 results shows that the Y components are identical at 126, but scanning across the frame in AvsPmod shows that U and V jitter between roughly 127 and 130, when they should both be 128.
Am I missing something in this process, or is there just no way to achieve the output of 2.6 in 2.5? For my purposes I have a few other options for getting around this (save a reference frame from 2.6 as an EBMP so I can bypass conversions, maintain separate test scripts and reference data for 2.5, force developers running the test suite to use 2.6, etc.), but for my own edification I'd like to know if I'm just stumbling over the implementation of the idea, and so far despite scouring old threads I haven't figured out what I'm doing wrong.